Changeset 118a812 in rtems
- Timestamp:
- 10/23/97 13:13:46 (25 years ago)
- Branches:
- 4.10, 4.11, 4.8, 4.9, 5, master
- Children:
- 3ee825e8
- Parents:
- 3dbcece
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
c/src/exec/libcsupport/include/rtems/libio.h
r3dbcece r118a812 148 148 rtems_status_code rtems_termios_ioctl (void *arg); 149 149 void rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len); 150 void rtems_termios_reserve_resources( 151 rtems_configuration_table *configuration, 152 rtems_unsigned32 number_of_devices 153 ); 150 154 151 155 #endif /* _RTEMS_LIBIO_H */ -
c/src/exec/libcsupport/src/termios.c
r3dbcece r118a812 24 24 #include <termios.h> 25 25 #include <unistd.h> 26 #include <ringbuf.h>27 26 28 27 /* 29 28 * The size of the cooked buffer 30 29 */ 31 #define CBUFSIZE 256 30 #define CBUFSIZE 256 31 32 /* 33 * The size of the raw input message queue 34 */ 35 #define RAW_BUFFER_SIZE 128 32 36 33 37 /* … … 36 40 */ 37 41 struct rtems_termios_tty { 38 /* 39 * Linked-list of active TERMIOS devices 40 */ 41 struct rtems_termios_tty *forw; 42 struct rtems_termios_tty *back; 43 44 /* 45 * How many times has this device been opened 46 */ 47 int refcount; 48 49 /* 50 * This device 51 */ 52 rtems_device_major_number major; 53 rtems_device_major_number minor; 54 55 /* 56 * Mutual-exclusion semaphores 57 */ 58 rtems_id isem; 59 rtems_id osem; 60 61 /* 62 * The canonical (cooked) character buffer 63 */ 64 char cbuf[CBUFSIZE]; 65 int ccount; 66 int cindex; 67 68 /* 69 * Keep track of cursor (printhead) position 70 */ 71 int column; 72 int read_start_column; 73 74 /* 75 * The ioctl settings 76 */ 77 struct termios termios; 78 rtems_interval vtimeTicks; 79 80 /* 81 * Raw character buffer 82 */ 83 rtems_id rawInputSem; 84 Ring_buffer_t rawInputBuffer; 85 86 rtems_unsigned32 rawMessageOptions; 87 rtems_interval rawMessageTimeout; 88 rtems_interval rawMessageFirstTimeout; 89 90 /* 91 * Callbacks to device-specific routines 92 */ 93 int (*lastClose)(int major, int minor, void *arg); 94 int (*read)(int minor, char *buf ); 95 int (*write)(int minor, char *buf, int len); 42 /* 43 * Linked-list of active TERMIOS devices 44 */ 45 struct rtems_termios_tty *forw; 46 struct rtems_termios_tty *back; 47 48 /* 49 * How many times has this device been opened 50 */ 51 int refcount; 52 53 /* 54 * This device 55 */ 56 rtems_device_major_number major; 57 rtems_device_major_number minor; 58 59 /* 60 * Mutual-exclusion semaphores 61 */ 62 rtems_id isem; 63 rtems_id osem; 64 65 /* 66 * The canonical (cooked) character buffer 67 */ 68 char cbuf[CBUFSIZE]; 69 int ccount; 70 int cindex; 71 72 /* 73 * Keep track of cursor (printhead) position 74 */ 75 int column; 76 int read_start_column; 77 78 /* 79 * The ioctl settings 80 */ 81 struct termios termios; 82 rtems_interval vtimeTicks; 83 84 /* 85 * Raw character buffer 86 */ 87 volatile char rawBuf[RAW_BUFFER_SIZE]; 88 volatile unsigned int rawBufHead; 89 volatile unsigned int rawBufTail; 90 rtems_id rawBufSemaphore; 91 rtems_unsigned32 rawBufSemaphoreOptions; 92 rtems_interval rawBufSemaphoreTimeout; 93 rtems_interval rawBufSemaphoreFirstTimeout; 94 unsigned int rawBufDropped; /* Statistics */ 95 96 /* 97 * Callbacks to device-specific routines 98 */ 99 int (*lastClose)(int major, int minor, void *arg); 100 int (*read)(int minor, char *buf); 101 int (*write)(int minor, char *buf, int len); 96 102 }; 97 103 static struct rtems_termios_tty *ttyHead, *ttyTail; … … 101 107 rtems_termios_initialize (void) 102 108 { 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 } 119 109 rtems_status_code sc; 110 111 /* 112 * Create the mutex semaphore for the tty list 113 */ 114 if (!ttyMutex) { 115 sc = rtems_semaphore_create ( 116 rtems_build_name ('T', 'R', 'm', 'i'), 117 1, 118 RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, 119 RTEMS_NO_PRIORITY, 120 &ttyMutex); 121 if (sc != RTEMS_SUCCESSFUL) 122 rtems_fatal_error_occurred (sc); 123 } 124 } 125 120 126 /* 121 127 * Open a termios device … … 128 134 int (*deviceFirstOpen)(int major, int minor, void *arg), 129 135 int (*deviceLastClose)(int major, int minor, void *arg), 130 int (*deviceRead)(int minor, char *buf /*, int len*/),136 int (*deviceRead)(int minor, char *buf), 131 137 int (*deviceWrite)(int minor, char *buf, int len) 132 138 ) 133 139 { 134 rtems_status_code sc; 135 rtems_libio_open_close_args_t *args = arg; 136 struct rtems_termios_tty *tty; 137 138 /* 139 * See if the device has already been opened 140 */ 141 sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 142 if (sc != RTEMS_SUCCESSFUL) 143 return sc; 144 for (tty = ttyHead ; tty != NULL ; tty = tty->forw) { 145 if ((tty->major == major) && (tty->minor == minor)) 146 break; 147 } 148 if (tty == NULL) { 149 static char c = 'a'; 150 151 /* 152 * Create a new device 153 */ 154 tty = malloc (sizeof (struct rtems_termios_tty)); 155 if (tty == NULL) { 156 rtems_semaphore_release (ttyMutex); 157 return RTEMS_NO_MEMORY; 158 } 159 tty->forw = ttyHead; 160 ttyHead = tty; 161 tty->back = NULL; 162 if (ttyTail == NULL) 163 ttyTail = tty; 164 165 /* 166 * Set up mutex semaphores 167 */ 168 sc = rtems_semaphore_create ( 169 rtems_build_name ('T', 'R', 'i', c), 170 1, 171 RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, 172 RTEMS_NO_PRIORITY, 173 &tty->isem); 174 if (sc != RTEMS_SUCCESSFUL) 175 rtems_fatal_error_occurred (sc); 176 sc = rtems_semaphore_create ( 177 rtems_build_name ('T', 'R', 'o', c), 178 1, 179 RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, 180 RTEMS_NO_PRIORITY, 181 &tty->osem); 182 if (sc != RTEMS_SUCCESSFUL) 183 rtems_fatal_error_occurred (sc); 184 185 /* 186 * Set callbacks 187 */ 188 tty->write = deviceWrite; 189 tty->lastClose = deviceLastClose; 190 if ((tty->read = deviceRead) == NULL) { 191 sc = rtems_semaphore_create ( 192 rtems_build_name ('T', 'R', 'r', c), 193 0, 194 RTEMS_COUNTING_SEMAPHORE | RTEMS_FIFO | RTEMS_LOCAL, 195 RTEMS_NO_PRIORITY, 196 &tty->rawInputSem); 197 if (sc != RTEMS_SUCCESSFUL) 198 rtems_fatal_error_occurred (sc); 199 } 200 201 /* 202 * Initialize variables 203 */ 204 tty->column = 0; 205 tty->cindex = tty->ccount = 0; 206 207 /* 208 * Set default parameters 209 */ 210 tty->termios.c_iflag = BRKINT | ICRNL | IXON | IMAXBEL; 211 tty->termios.c_oflag = OPOST | ONLCR | XTABS; 212 tty->termios.c_cflag = B9600 | CS8 | CREAD; 213 tty->termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOK | ECHOE | ECHOCTL; 214 tty->termios.c_cc[VINTR] = '\003'; 215 tty->termios.c_cc[VQUIT] = '\034'; 216 tty->termios.c_cc[VERASE] = '\177'; 217 tty->termios.c_cc[VKILL] = '\025'; 218 tty->termios.c_cc[VEOF] = '\004'; 219 tty->termios.c_cc[VEOL] = '\000'; 220 tty->termios.c_cc[VEOL2] = '\000'; 221 tty->termios.c_cc[VSTART] = '\021'; 222 tty->termios.c_cc[VSTOP] = '\023'; 223 tty->termios.c_cc[VSUSP] = '\032'; 224 tty->termios.c_cc[VREPRINT] = '\022'; 225 tty->termios.c_cc[VDISCARD] = '\017'; 226 tty->termios.c_cc[VWERASE] = '\027'; 227 tty->termios.c_cc[VLNEXT] = '\026'; 228 229 /* 230 * Device-specific open 231 */ 232 if (deviceFirstOpen) 233 (*deviceFirstOpen) (major, minor, arg); 234 235 /* 236 * Bump name characer 237 */ 238 if (c++ == 'z') 239 c = 'a'; 240 } 241 tty->refcount++; 242 args->iop->data1 = tty; 243 rtems_semaphore_release (ttyMutex); 244 return RTEMS_SUCCESSFUL; 140 rtems_status_code sc; 141 rtems_libio_open_close_args_t *args = arg; 142 struct rtems_termios_tty *tty; 143 144 /* 145 * See if the device has already been opened 146 */ 147 sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 148 if (sc != RTEMS_SUCCESSFUL) 149 return sc; 150 for (tty = ttyHead ; tty != NULL ; tty = tty->forw) { 151 if ((tty->major == major) && (tty->minor == minor)) 152 break; 153 } 154 if (tty == NULL) { 155 static char c = 'a'; 156 157 /* 158 * Create a new device 159 */ 160 tty = malloc (sizeof (struct rtems_termios_tty)); 161 if (tty == NULL) { 162 rtems_semaphore_release (ttyMutex); 163 return RTEMS_NO_MEMORY; 164 } 165 tty->forw = ttyHead; 166 ttyHead = tty; 167 tty->back = NULL; 168 if (ttyTail == NULL) 169 ttyTail = tty; 170 171 /* 172 * Set up mutex semaphores 173 */ 174 sc = rtems_semaphore_create ( 175 rtems_build_name ('T', 'R', 'i', c), 176 1, 177 RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, 178 RTEMS_NO_PRIORITY, 179 &tty->isem); 180 if (sc != RTEMS_SUCCESSFUL) 181 rtems_fatal_error_occurred (sc); 182 sc = rtems_semaphore_create ( 183 rtems_build_name ('T', 'R', 'o', c), 184 1, 185 RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, 186 RTEMS_NO_PRIORITY, 187 &tty->osem); 188 if (sc != RTEMS_SUCCESSFUL) 189 rtems_fatal_error_occurred (sc); 190 191 /* 192 * Set callbacks 193 */ 194 tty->write = deviceWrite; 195 tty->lastClose = deviceLastClose; 196 if ((tty->read = deviceRead) == NULL) { 197 sc = rtems_semaphore_create ( 198 rtems_build_name ('T', 'R', 'r', c), 199 0, 200 RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY, 201 RTEMS_NO_PRIORITY, 202 &tty->rawBufSemaphore); 203 if (sc != RTEMS_SUCCESSFUL) 204 rtems_fatal_error_occurred (sc); 205 tty->rawBufHead = 0; 206 tty->rawBufTail = 0; 207 } 208 209 /* 210 * Initialize variables 211 */ 212 tty->column = 0; 213 tty->cindex = tty->ccount = 0; 214 215 /* 216 * Set default parameters 217 */ 218 tty->termios.c_iflag = BRKINT | ICRNL | IXON | IMAXBEL; 219 tty->termios.c_oflag = OPOST | ONLCR | XTABS; 220 tty->termios.c_cflag = B9600 | CS8 | CREAD; 221 tty->termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOK | ECHOE | ECHOCTL; 222 tty->termios.c_cc[VINTR] = '\003'; 223 tty->termios.c_cc[VQUIT] = '\034'; 224 tty->termios.c_cc[VERASE] = '\177'; 225 tty->termios.c_cc[VKILL] = '\025'; 226 tty->termios.c_cc[VEOF] = '\004'; 227 tty->termios.c_cc[VEOL] = '\000'; 228 tty->termios.c_cc[VEOL2] = '\000'; 229 tty->termios.c_cc[VSTART] = '\021'; 230 tty->termios.c_cc[VSTOP] = '\023'; 231 tty->termios.c_cc[VSUSP] = '\032'; 232 tty->termios.c_cc[VREPRINT] = '\022'; 233 tty->termios.c_cc[VDISCARD] = '\017'; 234 tty->termios.c_cc[VWERASE] = '\027'; 235 tty->termios.c_cc[VLNEXT] = '\026'; 236 237 /* 238 * Device-specific open 239 */ 240 if (deviceFirstOpen) 241 (*deviceFirstOpen) (major, minor, arg); 242 243 /* 244 * Bump name characer 245 */ 246 if (c++ == 'z') 247 c = 'a'; 248 } 249 tty->refcount++; 250 args->iop->data1 = tty; 251 rtems_semaphore_release (ttyMutex); 252 return RTEMS_SUCCESSFUL; 245 253 } 246 254 … … 248 256 rtems_termios_close (void *arg) 249 257 { 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 rtems_semaphore_delete (tty->rawInputSem);272 273 274 275 258 rtems_libio_open_close_args_t *args = arg; 259 struct rtems_termios_tty *tty = args->iop->data1; 260 rtems_status_code sc; 261 262 sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 263 if (sc != RTEMS_SUCCESSFUL) 264 rtems_fatal_error_occurred (sc); 265 if (--tty->refcount == 0) { 266 if (tty->lastClose) 267 (*tty->lastClose) (tty->major, tty->minor, arg); 268 if (tty->forw == NULL) 269 ttyTail = tty->back; 270 else 271 tty->forw->back = tty->back; 272 if (tty->back == NULL) 273 ttyHead = tty->forw; 274 else 275 tty->back->forw = tty->forw; 276 rtems_semaphore_delete (tty->isem); 277 rtems_semaphore_delete (tty->osem); 278 if (tty->read == NULL) 279 rtems_semaphore_delete (tty->rawBufSemaphore); 280 free (tty); 281 } 282 rtems_semaphore_release (ttyMutex); 283 return RTEMS_SUCCESSFUL; 276 284 } 277 285 … … 279 287 rtems_termios_ioctl (void *arg) 280 288 { 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 tty->rawMessageOptions = RTEMS_WAIT;301 tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;302 tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;303 304 305 306 307 308 309 tty->rawMessageOptions = RTEMS_WAIT;310 tty->rawMessageTimeout = tty->vtimeTicks;311 312 tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;313 314 tty->rawMessageFirstTimeout = tty->vtimeTicks;315 316 317 318 tty->rawMessageOptions = RTEMS_WAIT;319 tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;320 tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;321 322 323 tty->rawMessageOptions = RTEMS_NO_WAIT;324 325 326 327 328 329 330 289 rtems_libio_ioctl_args_t *args = arg; 290 struct rtems_termios_tty *tty = args->iop->data1; 291 rtems_status_code sc; 292 293 sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 294 if (sc != RTEMS_SUCCESSFUL) 295 return sc; 296 switch (args->command) { 297 default: 298 sc = RTEMS_INVALID_NUMBER; 299 break; 300 301 case RTEMS_IO_GET_ATTRIBUTES: 302 *(struct termios *)args->buffer = tty->termios; 303 break; 304 305 case RTEMS_IO_SET_ATTRIBUTES: 306 tty->termios = *(struct termios *)args->buffer; 307 if (tty->termios.c_lflag & ICANON) { 308 tty->rawBufSemaphoreOptions = RTEMS_WAIT; 309 tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT; 310 tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT; 311 } 312 else { 313 rtems_interval ticksPerSecond; 314 rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond); 315 tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10; 316 if (tty->termios.c_cc[VTIME]) { 317 tty->rawBufSemaphoreOptions = RTEMS_WAIT; 318 tty->rawBufSemap`oreTimeout = tty->vtimeTicks; 319 if (tty->termios.c_cc[VMIN]) 320 tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT; 321 else 322 tty->rawBufSemaphoreFirstTimeout = tty->vtimeTicks; 323 } 324 else { 325 if (tty->termios.c_cc[VMIN]) { 326 tty->rawBufSemaphoreOptions = RTEMS_WAIT; 327 tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT; 328 tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT; 329 } 330 else { 331 tty->rawBufSemaphoreOptions = RTEMS_NO_WAIT; 332 } 333 } 334 } 335 break; 336 } 337 rtems_semaphore_release (tty->osem); 338 return sc; 331 339 } 332 340 … … 337 345 oproc (unsigned char c, struct rtems_termios_tty *tty) 338 346 { 339 inti;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 347 int i; 348 349 if (tty->termios.c_oflag & OPOST) { 350 switch (c) { 351 case '\n': 352 if (tty->termios.c_oflag & ONLRET) 353 tty->column = 0; 354 if (tty->termios.c_oflag & ONLCR) { 355 (*tty->write)(tty->minor, "\r", 1); 356 tty->column = 0; 357 } 358 break; 359 360 case '\r': 361 if ((tty->termios.c_oflag & ONOCR) && (tty->column == 0)) 362 return; 363 if (tty->termios.c_oflag & OCRNL) { 364 c = '\n'; 365 if (tty->termios.c_oflag & ONLRET) 366 tty->column = 0; 367 break; 368 } 369 tty->column = 0; 370 break; 371 372 case '\t': 373 i = 8 - (tty->column & 7); 374 if ((tty->termios.c_oflag & TABDLY) == XTABS) { 375 tty->column += i; 376 (*tty->write)(tty->minor, " ", i); 377 return; 378 } 379 tty->column += i; 380 break; 381 382 case '\b': 383 if (tty->column > 0) 384 tty->column--; 385 break; 386 387 default: 388 if (tty->termios.c_oflag & OLCUC) 389 c = toupper(c); 390 if (!iscntrl(c)) 391 tty->column++; 392 break; 393 } 394 } 395 (*tty->write)(tty->minor, &c, 1); 388 396 } 389 397 … … 391 399 rtems_termios_write (void *arg) 392 400 { 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 401 rtems_libio_rw_args_t *args = arg; 402 struct rtems_termios_tty *tty = args->iop->data1; 403 rtems_status_code sc; 404 405 sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 406 if (sc != RTEMS_SUCCESSFUL) 407 return sc; 408 if (tty->termios.c_oflag & OPOST) { 409 unsigned32 count = args->count; 410 unsigned8 *buffer = args->buffer; 411 while (count--) 412 oproc (*buffer++, tty); 413 args->bytes_moved = args->count; 414 } 415 else { 416 if ((*tty->write)(tty->minor, args->buffer, args->count) < 0) 417 sc = RTEMS_UNSATISFIED; 418 else 419 args->bytes_moved = args->count; 420 } 421 rtems_semaphore_release (tty->osem); 422 return sc; 415 423 } 416 424 … … 421 429 echo (unsigned char c, struct rtems_termios_tty *tty) 422 430 { 423 424 425 426 427 428 429 430 431 432 433 431 if ((tty->termios.c_lflag & ECHOCTL) && iscntrl(c) && (c != '\t') && (c != '\n')) { 432 char echobuf[2]; 433 434 echobuf[0] = '^'; 435 echobuf[1] = c ^ 0x40; 436 (*tty->write)(tty->minor, echobuf, 2); 437 tty->column += 2; 438 } 439 else { 440 oproc (c, tty); 441 } 434 442 } 435 443 … … 442 450 erase (struct rtems_termios_tty *tty, int lineFlag) 443 451 { 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 452 if (tty->ccount == 0) 453 return; 454 if (lineFlag) { 455 if (!(tty->termios.c_lflag & ECHO)) { 456 tty->ccount = 0; 457 return; 458 } 459 if (!(tty->termios.c_lflag & ECHOE)) { 460 tty->ccount = 0; 461 echo (tty->termios.c_cc[VKILL], tty); 462 if (tty->termios.c_lflag & ECHOK) 463 echo ('\n', tty); 464 return; 465 } 466 } 467 while (tty->ccount) { 468 unsigned char c = tty->cbuf[--tty->ccount]; 469 470 if (tty->termios.c_lflag & ECHO) { 471 if (!lineFlag && !(tty->termios.c_lflag & ECHOE)) { 472 echo (tty->termios.c_cc[VERASE], tty); 473 } 474 else if (c == '\t') { 475 int col = tty->read_start_column; 476 int i = 0; 477 478 /* 479 * Find the character before the tab 480 */ 481 while (i != tty->ccount) { 482 c = tty->cbuf[i++]; 483 if (c == '\t') { 484 col = (col | 7) + 1; 485 } 486 else if (iscntrl (c)) { 487 if (tty->termios.c_lflag & ECHOCTL) 488 col += 2; 489 } 490 else { 491 col++; 492 } 493 } 494 495 /* 496 * Back up over the tab 497 */ 498 while (tty->column > col) { 499 (*tty->write)(tty->minor, "\b", 1); 500 tty->column--; 501 } 502 } 503 else { 504 if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) { 505 (*tty->write)(tty->minor, "\b \b", 3); 506 if (tty->column) 507 tty->column--; 508 } 509 if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) { 510 (*tty->write)(tty->minor, "\b \b", 3); 511 if (tty->column) 512 tty->column--; 513 } 514 } 515 } 516 if (!lineFlag) 517 break; 518 } 511 519 } 512 520 … … 517 525 iproc (unsigned char c, struct rtems_termios_tty *tty) 518 526 { 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 527 if (tty->termios.c_iflag & ISTRIP) 528 c &= 0x7f; 529 if (tty->termios.c_iflag & IUCLC) 530 c = tolower (c); 531 if (c == '\r') { 532 if (tty->termios.c_iflag & IGNCR) 533 return 0; 534 if (tty->termios.c_iflag & ICRNL) 535 c = '\n'; 536 } 537 else if ((c == '\n') && (tty->termios.c_iflag & INLCR)) { 538 c = '\r'; 539 } 540 if ((c != '\0') && (tty->termios.c_lflag & ICANON)) { 541 if (c == tty->termios.c_cc[VERASE]) { 542 erase (tty, 0); 543 return 0; 544 } 545 else if (c == tty->termios.c_cc[VKILL]) { 546 erase (tty, 1); 547 return 0; 548 } 549 else if (c == tty->termios.c_cc[VEOF]) { 550 return 1; 551 } 552 else if (c == '\n') { 553 if (tty->termios.c_lflag & (ECHO | ECHONL)) 554 echo (c, tty); 555 tty->cbuf[tty->ccount++] = c; 556 return 1; 557 } 558 else if ((c == tty->termios.c_cc[VEOL]) 559 || (c == tty->termios.c_cc[VEOL2])) { 560 if (tty->termios.c_lflag & ECHO) 561 echo (c, tty); 562 tty->cbuf[tty->ccount++] = c; 563 return 1; 564 } 565 } 566 567 /* 568 * FIXME: Should do IMAXBEL handling somehow 569 */ 570 if (tty->ccount < (CBUFSIZE-1)) { 571 if (tty->termios.c_lflag & ECHO) 572 echo (c, tty); 573 tty->cbuf[tty->ccount++] = c; 574 } 575 return 0; 568 576 } 569 577 … … 574 582 siproc (unsigned char c, struct rtems_termios_tty *tty) 575 583 { 576 577 578 579 580 581 582 583 584 585 586 587 588 589 584 int i; 585 586 /* 587 * Obtain output semaphore if character will be echoed 588 */ 589 if (tty->termios.c_lflag & (ECHO|ECHOE|ECHOK|ECHONL|ECHOPRT|ECHOCTL|ECHOKE)) { 590 rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 591 i = iproc (c, tty); 592 rtems_semaphore_release (tty->osem); 593 } 594 else { 595 i = iproc (c, tty); 596 } 597 return i; 590 598 } 591 599 … … 596 604 fillBufferPoll (struct rtems_termios_tty *tty) 597 605 { 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 606 unsigned char c; 607 int n; 608 609 if (tty->termios.c_lflag & ICANON) { 610 for (;;) { 611 n = (*tty->read)(tty->minor, &c); 612 if (n < 0) { 613 return RTEMS_UNSATISFIED; 614 } 615 else if (n == 0) { 616 rtems_task_wake_after (1); 617 } 618 else { 619 if (siproc (c, tty)) 620 break; 621 } 622 } 623 } 624 else { 625 rtems_interval then, now; 626 if (!tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME]) 627 rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then); 628 for (;;) { 629 n = (*tty->read)(tty->minor, &c); 630 if (n < 0) { 631 return RTEMS_UNSATISFIED; 632 } 633 else if (n == 0) { 634 if (tty->termios.c_cc[VMIN]) { 635 if (tty->termios.c_cc[VTIME] && tty->ccount) { 636 rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now); 637 if ((now - then) > tty->vtimeTicks) { 638 break; 639 } 640 } 641 } 642 else { 643 if (!tty->termios.c_cc[VTIME]) 644 break; 645 rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now); 646 if ((now - then) > tty->vtimeTicks) { 647 break; 648 } 649 } 650 rtems_task_wake_after (1); 651 } 652 else { 653 siproc (c, tty); 654 if (tty->ccount >= tty->termios.c_cc[VMIN]) 655 break; 656 if (tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME]) 657 rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then); 658 } 659 } 660 } 661 return RTEMS_SUCCESSFUL; 654 662 } 655 663 … … 660 668 fillBufferQueue (struct rtems_termios_tty *tty) 661 669 { 662 rtems_interval timeout = tty->rawMessageFirstTimeout; 663 rtems_status_code sc; 664 rtems_unsigned8 c; 665 666 for (;;) { 667 668 /* 669 * Read characters from raw queue 670 */ 671 sc = rtems_semaphore_obtain (tty->rawInputSem, 672 tty->rawMessageOptions, 673 timeout); 674 if (sc != RTEMS_SUCCESSFUL) 675 break; 676 Ring_buffer_Remove_character( &tty->rawInputBuffer, c ); 677 678 /* 679 * Process characters read from raw queue 680 */ 681 if (tty->termios.c_lflag & ICANON) { 682 if (siproc (c, tty)) 683 return RTEMS_SUCCESSFUL; 684 } 685 else { 686 siproc (c, tty); 687 if (tty->ccount >= tty->termios.c_cc[VMIN]) 688 return RTEMS_SUCCESSFUL; 689 } 690 691 timeout = tty->rawMessageTimeout; 692 } 693 return RTEMS_SUCCESSFUL; 670 rtems_interval timeout = tty->rawBufSemaphoreFirstTimeout; 671 rtems_status_code sc; 672 673 for (;;) { 674 /* 675 * Process characters read from raw queue 676 */ 677 while (tty->rawBufHead != tty->rawBufTail) { 678 unsigned char c; 679 unsigned int newHead; 680 681 newHead = (tty->rawBufHead + 1) % RAW_BUFFER_SIZE; 682 c = tty->rawBuf[newHead]; 683 tty->rawBufHead = newHead; 684 if (tty->termios.c_lflag & ICANON) { 685 if (siproc (c, tty)) 686 return RTEMS_SUCCESSFUL; 687 } 688 else { 689 siproc (c, tty); 690 if (tty->ccount >= tty->termios.c_cc[VMIN]) 691 return RTEMS_SUCCESSFUL; 692 } 693 timeout = tty->rawBufSemaphoreTimeout; 694 } 695 696 /* 697 * Wait for characters 698 */ 699 sc = rtems_semaphore_obtain (tty->rawBufSemaphore, 700 tty->rawBufSemaphoreOptions, 701 timeout); 702 if (sc != RTEMS_SUCCESSFUL) 703 break; 704 } 705 return RTEMS_SUCCESSFUL; 694 706 } 695 707 … … 697 709 rtems_termios_read (void *arg) 698 710 { 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 711 rtems_libio_rw_args_t *args = arg; 712 struct rtems_termios_tty *tty = args->iop->data1; 713 unsigned32 count = args->count; 714 unsigned8 *buffer = args->buffer; 715 rtems_status_code sc; 716 717 sc = rtems_semaphore_obtain (tty->isem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 718 if (sc != RTEMS_SUCCESSFUL) 719 return sc; 720 if (tty->cindex == tty->ccount) { 721 tty->cindex = tty->ccount = 0; 722 tty->read_start_column = tty->column; 723 if (tty->read) 724 sc = fillBufferPoll (tty); 725 else 726 sc = fillBufferQueue (tty); 727 if (sc != RTEMS_SUCCESSFUL) 728 tty->cindex = tty->ccount = 0; 729 } 730 while (count && (tty->cindex < tty->ccount)) { 731 *buffer++ = tty->cbuf[tty->cindex++]; 732 count--; 733 } 734 args->bytes_moved = args->count - count; 735 rtems_semaphore_release (tty->isem); 736 return sc; 725 737 } 726 738 … … 732 744 rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len) 733 745 { 734 struct rtems_termios_tty *tty = ttyp; 735 736 while (len) { 737 if (Ring_buffer_Is_full(&tty->rawInputBuffer)) 738 break; 739 Ring_buffer_Add_character(&tty->rawInputBuffer, *buf); 740 if (rtems_semaphore_release(tty->rawInputSem) != RTEMS_SUCCESSFUL) 741 break; 742 len -= 1; 743 buf += 1; 744 } 745 } 746 746 struct rtems_termios_tty *tty = ttyp; 747 unsigned int newTail; 748 749 while (len) { 750 newTail = (tty->rawBufTail + 1) % RAW_BUFFER_SIZE; 751 if (newTail == tty->rawBufHead) { 752 tty->rawBufDropped += len; 753 break; 754 } 755 tty->rawBuf[newTail] = *buf++; 756 len--; 757 tty->rawBufTail = newTail; 758 } 759 rtems_semaphore_release (tty->rawBufSemaphore); 760 } 761 762 /* 763 * Reserve enough resources to at least open every physical device 764 * once. 765 */ 766 767 void rtems_termios_reserve_resources( 768 rtems_configuration_table *configuration, 769 rtems_unsigned32 number_of_devices 770 ) 771 { 772 static int first_time = 1; 773 rtems_api_configuration_table *rtems_config; 774 775 if (!configuration) 776 rtems_fatal_error_occurred (0xFFF0F001); 777 778 rtems_config = configuration->RTEMS_api_configuration; 779 if (!rtems_config) 780 rtems_fatal_error_occurred (0xFFF0F002); 781 782 if (first_time) 783 rtems_config->maximum_semaphores += 1; 784 785 first_time = 0; 786 rtems_config->maximum_semaphores += (3 * number_of_devices); 787 } -
c/src/lib/include/rtems/libio.h
r3dbcece r118a812 148 148 rtems_status_code rtems_termios_ioctl (void *arg); 149 149 void rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len); 150 void rtems_termios_reserve_resources( 151 rtems_configuration_table *configuration, 152 rtems_unsigned32 number_of_devices 153 ); 150 154 151 155 #endif /* _RTEMS_LIBIO_H */ -
c/src/lib/libc/libio.h
r3dbcece r118a812 148 148 rtems_status_code rtems_termios_ioctl (void *arg); 149 149 void rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len); 150 void rtems_termios_reserve_resources( 151 rtems_configuration_table *configuration, 152 rtems_unsigned32 number_of_devices 153 ); 150 154 151 155 #endif /* _RTEMS_LIBIO_H */ -
c/src/lib/libc/termios.c
r3dbcece r118a812 24 24 #include <termios.h> 25 25 #include <unistd.h> 26 #include <ringbuf.h>27 26 28 27 /* 29 28 * The size of the cooked buffer 30 29 */ 31 #define CBUFSIZE 256 30 #define CBUFSIZE 256 31 32 /* 33 * The size of the raw input message queue 34 */ 35 #define RAW_BUFFER_SIZE 128 32 36 33 37 /* … … 36 40 */ 37 41 struct rtems_termios_tty { 38 /* 39 * Linked-list of active TERMIOS devices 40 */ 41 struct rtems_termios_tty *forw; 42 struct rtems_termios_tty *back; 43 44 /* 45 * How many times has this device been opened 46 */ 47 int refcount; 48 49 /* 50 * This device 51 */ 52 rtems_device_major_number major; 53 rtems_device_major_number minor; 54 55 /* 56 * Mutual-exclusion semaphores 57 */ 58 rtems_id isem; 59 rtems_id osem; 60 61 /* 62 * The canonical (cooked) character buffer 63 */ 64 char cbuf[CBUFSIZE]; 65 int ccount; 66 int cindex; 67 68 /* 69 * Keep track of cursor (printhead) position 70 */ 71 int column; 72 int read_start_column; 73 74 /* 75 * The ioctl settings 76 */ 77 struct termios termios; 78 rtems_interval vtimeTicks; 79 80 /* 81 * Raw character buffer 82 */ 83 rtems_id rawInputSem; 84 Ring_buffer_t rawInputBuffer; 85 86 rtems_unsigned32 rawMessageOptions; 87 rtems_interval rawMessageTimeout; 88 rtems_interval rawMessageFirstTimeout; 89 90 /* 91 * Callbacks to device-specific routines 92 */ 93 int (*lastClose)(int major, int minor, void *arg); 94 int (*read)(int minor, char *buf ); 95 int (*write)(int minor, char *buf, int len); 42 /* 43 * Linked-list of active TERMIOS devices 44 */ 45 struct rtems_termios_tty *forw; 46 struct rtems_termios_tty *back; 47 48 /* 49 * How many times has this device been opened 50 */ 51 int refcount; 52 53 /* 54 * This device 55 */ 56 rtems_device_major_number major; 57 rtems_device_major_number minor; 58 59 /* 60 * Mutual-exclusion semaphores 61 */ 62 rtems_id isem; 63 rtems_id osem; 64 65 /* 66 * The canonical (cooked) character buffer 67 */ 68 char cbuf[CBUFSIZE]; 69 int ccount; 70 int cindex; 71 72 /* 73 * Keep track of cursor (printhead) position 74 */ 75 int column; 76 int read_start_column; 77 78 /* 79 * The ioctl settings 80 */ 81 struct termios termios; 82 rtems_interval vtimeTicks; 83 84 /* 85 * Raw character buffer 86 */ 87 volatile char rawBuf[RAW_BUFFER_SIZE]; 88 volatile unsigned int rawBufHead; 89 volatile unsigned int rawBufTail; 90 rtems_id rawBufSemaphore; 91 rtems_unsigned32 rawBufSemaphoreOptions; 92 rtems_interval rawBufSemaphoreTimeout; 93 rtems_interval rawBufSemaphoreFirstTimeout; 94 unsigned int rawBufDropped; /* Statistics */ 95 96 /* 97 * Callbacks to device-specific routines 98 */ 99 int (*lastClose)(int major, int minor, void *arg); 100 int (*read)(int minor, char *buf); 101 int (*write)(int minor, char *buf, int len); 96 102 }; 97 103 static struct rtems_termios_tty *ttyHead, *ttyTail; … … 101 107 rtems_termios_initialize (void) 102 108 { 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 } 119 109 rtems_status_code sc; 110 111 /* 112 * Create the mutex semaphore for the tty list 113 */ 114 if (!ttyMutex) { 115 sc = rtems_semaphore_create ( 116 rtems_build_name ('T', 'R', 'm', 'i'), 117 1, 118 RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, 119 RTEMS_NO_PRIORITY, 120 &ttyMutex); 121 if (sc != RTEMS_SUCCESSFUL) 122 rtems_fatal_error_occurred (sc); 123 } 124 } 125 120 126 /* 121 127 * Open a termios device … … 128 134 int (*deviceFirstOpen)(int major, int minor, void *arg), 129 135 int (*deviceLastClose)(int major, int minor, void *arg), 130 int (*deviceRead)(int minor, char *buf /*, int len*/),136 int (*deviceRead)(int minor, char *buf), 131 137 int (*deviceWrite)(int minor, char *buf, int len) 132 138 ) 133 139 { 134 rtems_status_code sc; 135 rtems_libio_open_close_args_t *args = arg; 136 struct rtems_termios_tty *tty; 137 138 /* 139 * See if the device has already been opened 140 */ 141 sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 142 if (sc != RTEMS_SUCCESSFUL) 143 return sc; 144 for (tty = ttyHead ; tty != NULL ; tty = tty->forw) { 145 if ((tty->major == major) && (tty->minor == minor)) 146 break; 147 } 148 if (tty == NULL) { 149 static char c = 'a'; 150 151 /* 152 * Create a new device 153 */ 154 tty = malloc (sizeof (struct rtems_termios_tty)); 155 if (tty == NULL) { 156 rtems_semaphore_release (ttyMutex); 157 return RTEMS_NO_MEMORY; 158 } 159 tty->forw = ttyHead; 160 ttyHead = tty; 161 tty->back = NULL; 162 if (ttyTail == NULL) 163 ttyTail = tty; 164 165 /* 166 * Set up mutex semaphores 167 */ 168 sc = rtems_semaphore_create ( 169 rtems_build_name ('T', 'R', 'i', c), 170 1, 171 RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, 172 RTEMS_NO_PRIORITY, 173 &tty->isem); 174 if (sc != RTEMS_SUCCESSFUL) 175 rtems_fatal_error_occurred (sc); 176 sc = rtems_semaphore_create ( 177 rtems_build_name ('T', 'R', 'o', c), 178 1, 179 RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, 180 RTEMS_NO_PRIORITY, 181 &tty->osem); 182 if (sc != RTEMS_SUCCESSFUL) 183 rtems_fatal_error_occurred (sc); 184 185 /* 186 * Set callbacks 187 */ 188 tty->write = deviceWrite; 189 tty->lastClose = deviceLastClose; 190 if ((tty->read = deviceRead) == NULL) { 191 sc = rtems_semaphore_create ( 192 rtems_build_name ('T', 'R', 'r', c), 193 0, 194 RTEMS_COUNTING_SEMAPHORE | RTEMS_FIFO | RTEMS_LOCAL, 195 RTEMS_NO_PRIORITY, 196 &tty->rawInputSem); 197 if (sc != RTEMS_SUCCESSFUL) 198 rtems_fatal_error_occurred (sc); 199 } 200 201 /* 202 * Initialize variables 203 */ 204 tty->column = 0; 205 tty->cindex = tty->ccount = 0; 206 207 /* 208 * Set default parameters 209 */ 210 tty->termios.c_iflag = BRKINT | ICRNL | IXON | IMAXBEL; 211 tty->termios.c_oflag = OPOST | ONLCR | XTABS; 212 tty->termios.c_cflag = B9600 | CS8 | CREAD; 213 tty->termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOK | ECHOE | ECHOCTL; 214 tty->termios.c_cc[VINTR] = '\003'; 215 tty->termios.c_cc[VQUIT] = '\034'; 216 tty->termios.c_cc[VERASE] = '\177'; 217 tty->termios.c_cc[VKILL] = '\025'; 218 tty->termios.c_cc[VEOF] = '\004'; 219 tty->termios.c_cc[VEOL] = '\000'; 220 tty->termios.c_cc[VEOL2] = '\000'; 221 tty->termios.c_cc[VSTART] = '\021'; 222 tty->termios.c_cc[VSTOP] = '\023'; 223 tty->termios.c_cc[VSUSP] = '\032'; 224 tty->termios.c_cc[VREPRINT] = '\022'; 225 tty->termios.c_cc[VDISCARD] = '\017'; 226 tty->termios.c_cc[VWERASE] = '\027'; 227 tty->termios.c_cc[VLNEXT] = '\026'; 228 229 /* 230 * Device-specific open 231 */ 232 if (deviceFirstOpen) 233 (*deviceFirstOpen) (major, minor, arg); 234 235 /* 236 * Bump name characer 237 */ 238 if (c++ == 'z') 239 c = 'a'; 240 } 241 tty->refcount++; 242 args->iop->data1 = tty; 243 rtems_semaphore_release (ttyMutex); 244 return RTEMS_SUCCESSFUL; 140 rtems_status_code sc; 141 rtems_libio_open_close_args_t *args = arg; 142 struct rtems_termios_tty *tty; 143 144 /* 145 * See if the device has already been opened 146 */ 147 sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 148 if (sc != RTEMS_SUCCESSFUL) 149 return sc; 150 for (tty = ttyHead ; tty != NULL ; tty = tty->forw) { 151 if ((tty->major == major) && (tty->minor == minor)) 152 break; 153 } 154 if (tty == NULL) { 155 static char c = 'a'; 156 157 /* 158 * Create a new device 159 */ 160 tty = malloc (sizeof (struct rtems_termios_tty)); 161 if (tty == NULL) { 162 rtems_semaphore_release (ttyMutex); 163 return RTEMS_NO_MEMORY; 164 } 165 tty->forw = ttyHead; 166 ttyHead = tty; 167 tty->back = NULL; 168 if (ttyTail == NULL) 169 ttyTail = tty; 170 171 /* 172 * Set up mutex semaphores 173 */ 174 sc = rtems_semaphore_create ( 175 rtems_build_name ('T', 'R', 'i', c), 176 1, 177 RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, 178 RTEMS_NO_PRIORITY, 179 &tty->isem); 180 if (sc != RTEMS_SUCCESSFUL) 181 rtems_fatal_error_occurred (sc); 182 sc = rtems_semaphore_create ( 183 rtems_build_name ('T', 'R', 'o', c), 184 1, 185 RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, 186 RTEMS_NO_PRIORITY, 187 &tty->osem); 188 if (sc != RTEMS_SUCCESSFUL) 189 rtems_fatal_error_occurred (sc); 190 191 /* 192 * Set callbacks 193 */ 194 tty->write = deviceWrite; 195 tty->lastClose = deviceLastClose; 196 if ((tty->read = deviceRead) == NULL) { 197 sc = rtems_semaphore_create ( 198 rtems_build_name ('T', 'R', 'r', c), 199 0, 200 RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY, 201 RTEMS_NO_PRIORITY, 202 &tty->rawBufSemaphore); 203 if (sc != RTEMS_SUCCESSFUL) 204 rtems_fatal_error_occurred (sc); 205 tty->rawBufHead = 0; 206 tty->rawBufTail = 0; 207 } 208 209 /* 210 * Initialize variables 211 */ 212 tty->column = 0; 213 tty->cindex = tty->ccount = 0; 214 215 /* 216 * Set default parameters 217 */ 218 tty->termios.c_iflag = BRKINT | ICRNL | IXON | IMAXBEL; 219 tty->termios.c_oflag = OPOST | ONLCR | XTABS; 220 tty->termios.c_cflag = B9600 | CS8 | CREAD; 221 tty->termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOK | ECHOE | ECHOCTL; 222 tty->termios.c_cc[VINTR] = '\003'; 223 tty->termios.c_cc[VQUIT] = '\034'; 224 tty->termios.c_cc[VERASE] = '\177'; 225 tty->termios.c_cc[VKILL] = '\025'; 226 tty->termios.c_cc[VEOF] = '\004'; 227 tty->termios.c_cc[VEOL] = '\000'; 228 tty->termios.c_cc[VEOL2] = '\000'; 229 tty->termios.c_cc[VSTART] = '\021'; 230 tty->termios.c_cc[VSTOP] = '\023'; 231 tty->termios.c_cc[VSUSP] = '\032'; 232 tty->termios.c_cc[VREPRINT] = '\022'; 233 tty->termios.c_cc[VDISCARD] = '\017'; 234 tty->termios.c_cc[VWERASE] = '\027'; 235 tty->termios.c_cc[VLNEXT] = '\026'; 236 237 /* 238 * Device-specific open 239 */ 240 if (deviceFirstOpen) 241 (*deviceFirstOpen) (major, minor, arg); 242 243 /* 244 * Bump name characer 245 */ 246 if (c++ == 'z') 247 c = 'a'; 248 } 249 tty->refcount++; 250 args->iop->data1 = tty; 251 rtems_semaphore_release (ttyMutex); 252 return RTEMS_SUCCESSFUL; 245 253 } 246 254 … … 248 256 rtems_termios_close (void *arg) 249 257 { 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 rtems_semaphore_delete (tty->rawInputSem);272 273 274 275 258 rtems_libio_open_close_args_t *args = arg; 259 struct rtems_termios_tty *tty = args->iop->data1; 260 rtems_status_code sc; 261 262 sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 263 if (sc != RTEMS_SUCCESSFUL) 264 rtems_fatal_error_occurred (sc); 265 if (--tty->refcount == 0) { 266 if (tty->lastClose) 267 (*tty->lastClose) (tty->major, tty->minor, arg); 268 if (tty->forw == NULL) 269 ttyTail = tty->back; 270 else 271 tty->forw->back = tty->back; 272 if (tty->back == NULL) 273 ttyHead = tty->forw; 274 else 275 tty->back->forw = tty->forw; 276 rtems_semaphore_delete (tty->isem); 277 rtems_semaphore_delete (tty->osem); 278 if (tty->read == NULL) 279 rtems_semaphore_delete (tty->rawBufSemaphore); 280 free (tty); 281 } 282 rtems_semaphore_release (ttyMutex); 283 return RTEMS_SUCCESSFUL; 276 284 } 277 285 … … 279 287 rtems_termios_ioctl (void *arg) 280 288 { 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 tty->rawMessageOptions = RTEMS_WAIT;301 tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;302 tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;303 304 305 306 307 308 309 tty->rawMessageOptions = RTEMS_WAIT;310 tty->rawMessageTimeout = tty->vtimeTicks;311 312 tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;313 314 tty->rawMessageFirstTimeout = tty->vtimeTicks;315 316 317 318 tty->rawMessageOptions = RTEMS_WAIT;319 tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;320 tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;321 322 323 tty->rawMessageOptions = RTEMS_NO_WAIT;324 325 326 327 328 329 330 289 rtems_libio_ioctl_args_t *args = arg; 290 struct rtems_termios_tty *tty = args->iop->data1; 291 rtems_status_code sc; 292 293 sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 294 if (sc != RTEMS_SUCCESSFUL) 295 return sc; 296 switch (args->command) { 297 default: 298 sc = RTEMS_INVALID_NUMBER; 299 break; 300 301 case RTEMS_IO_GET_ATTRIBUTES: 302 *(struct termios *)args->buffer = tty->termios; 303 break; 304 305 case RTEMS_IO_SET_ATTRIBUTES: 306 tty->termios = *(struct termios *)args->buffer; 307 if (tty->termios.c_lflag & ICANON) { 308 tty->rawBufSemaphoreOptions = RTEMS_WAIT; 309 tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT; 310 tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT; 311 } 312 else { 313 rtems_interval ticksPerSecond; 314 rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond); 315 tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10; 316 if (tty->termios.c_cc[VTIME]) { 317 tty->rawBufSemaphoreOptions = RTEMS_WAIT; 318 tty->rawBufSemap`oreTimeout = tty->vtimeTicks; 319 if (tty->termios.c_cc[VMIN]) 320 tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT; 321 else 322 tty->rawBufSemaphoreFirstTimeout = tty->vtimeTicks; 323 } 324 else { 325 if (tty->termios.c_cc[VMIN]) { 326 tty->rawBufSemaphoreOptions = RTEMS_WAIT; 327 tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT; 328 tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT; 329 } 330 else { 331 tty->rawBufSemaphoreOptions = RTEMS_NO_WAIT; 332 } 333 } 334 } 335 break; 336 } 337 rtems_semaphore_release (tty->osem); 338 return sc; 331 339 } 332 340 … … 337 345 oproc (unsigned char c, struct rtems_termios_tty *tty) 338 346 { 339 inti;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 347 int i; 348 349 if (tty->termios.c_oflag & OPOST) { 350 switch (c) { 351 case '\n': 352 if (tty->termios.c_oflag & ONLRET) 353 tty->column = 0; 354 if (tty->termios.c_oflag & ONLCR) { 355 (*tty->write)(tty->minor, "\r", 1); 356 tty->column = 0; 357 } 358 break; 359 360 case '\r': 361 if ((tty->termios.c_oflag & ONOCR) && (tty->column == 0)) 362 return; 363 if (tty->termios.c_oflag & OCRNL) { 364 c = '\n'; 365 if (tty->termios.c_oflag & ONLRET) 366 tty->column = 0; 367 break; 368 } 369 tty->column = 0; 370 break; 371 372 case '\t': 373 i = 8 - (tty->column & 7); 374 if ((tty->termios.c_oflag & TABDLY) == XTABS) { 375 tty->column += i; 376 (*tty->write)(tty->minor, " ", i); 377 return; 378 } 379 tty->column += i; 380 break; 381 382 case '\b': 383 if (tty->column > 0) 384 tty->column--; 385 break; 386 387 default: 388 if (tty->termios.c_oflag & OLCUC) 389 c = toupper(c); 390 if (!iscntrl(c)) 391 tty->column++; 392 break; 393 } 394 } 395 (*tty->write)(tty->minor, &c, 1); 388 396 } 389 397 … … 391 399 rtems_termios_write (void *arg) 392 400 { 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 401 rtems_libio_rw_args_t *args = arg; 402 struct rtems_termios_tty *tty = args->iop->data1; 403 rtems_status_code sc; 404 405 sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 406 if (sc != RTEMS_SUCCESSFUL) 407 return sc; 408 if (tty->termios.c_oflag & OPOST) { 409 unsigned32 count = args->count; 410 unsigned8 *buffer = args->buffer; 411 while (count--) 412 oproc (*buffer++, tty); 413 args->bytes_moved = args->count; 414 } 415 else { 416 if ((*tty->write)(tty->minor, args->buffer, args->count) < 0) 417 sc = RTEMS_UNSATISFIED; 418 else 419 args->bytes_moved = args->count; 420 } 421 rtems_semaphore_release (tty->osem); 422 return sc; 415 423 } 416 424 … … 421 429 echo (unsigned char c, struct rtems_termios_tty *tty) 422 430 { 423 424 425 426 427 428 429 430 431 432 433 431 if ((tty->termios.c_lflag & ECHOCTL) && iscntrl(c) && (c != '\t') && (c != '\n')) { 432 char echobuf[2]; 433 434 echobuf[0] = '^'; 435 echobuf[1] = c ^ 0x40; 436 (*tty->write)(tty->minor, echobuf, 2); 437 tty->column += 2; 438 } 439 else { 440 oproc (c, tty); 441 } 434 442 } 435 443 … … 442 450 erase (struct rtems_termios_tty *tty, int lineFlag) 443 451 { 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 452 if (tty->ccount == 0) 453 return; 454 if (lineFlag) { 455 if (!(tty->termios.c_lflag & ECHO)) { 456 tty->ccount = 0; 457 return; 458 } 459 if (!(tty->termios.c_lflag & ECHOE)) { 460 tty->ccount = 0; 461 echo (tty->termios.c_cc[VKILL], tty); 462 if (tty->termios.c_lflag & ECHOK) 463 echo ('\n', tty); 464 return; 465 } 466 } 467 while (tty->ccount) { 468 unsigned char c = tty->cbuf[--tty->ccount]; 469 470 if (tty->termios.c_lflag & ECHO) { 471 if (!lineFlag && !(tty->termios.c_lflag & ECHOE)) { 472 echo (tty->termios.c_cc[VERASE], tty); 473 } 474 else if (c == '\t') { 475 int col = tty->read_start_column; 476 int i = 0; 477 478 /* 479 * Find the character before the tab 480 */ 481 while (i != tty->ccount) { 482 c = tty->cbuf[i++]; 483 if (c == '\t') { 484 col = (col | 7) + 1; 485 } 486 else if (iscntrl (c)) { 487 if (tty->termios.c_lflag & ECHOCTL) 488 col += 2; 489 } 490 else { 491 col++; 492 } 493 } 494 495 /* 496 * Back up over the tab 497 */ 498 while (tty->column > col) { 499 (*tty->write)(tty->minor, "\b", 1); 500 tty->column--; 501 } 502 } 503 else { 504 if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) { 505 (*tty->write)(tty->minor, "\b \b", 3); 506 if (tty->column) 507 tty->column--; 508 } 509 if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) { 510 (*tty->write)(tty->minor, "\b \b", 3); 511 if (tty->column) 512 tty->column--; 513 } 514 } 515 } 516 if (!lineFlag) 517 break; 518 } 511 519 } 512 520 … … 517 525 iproc (unsigned char c, struct rtems_termios_tty *tty) 518 526 { 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 527 if (tty->termios.c_iflag & ISTRIP) 528 c &= 0x7f; 529 if (tty->termios.c_iflag & IUCLC) 530 c = tolower (c); 531 if (c == '\r') { 532 if (tty->termios.c_iflag & IGNCR) 533 return 0; 534 if (tty->termios.c_iflag & ICRNL) 535 c = '\n'; 536 } 537 else if ((c == '\n') && (tty->termios.c_iflag & INLCR)) { 538 c = '\r'; 539 } 540 if ((c != '\0') && (tty->termios.c_lflag & ICANON)) { 541 if (c == tty->termios.c_cc[VERASE]) { 542 erase (tty, 0); 543 return 0; 544 } 545 else if (c == tty->termios.c_cc[VKILL]) { 546 erase (tty, 1); 547 return 0; 548 } 549 else if (c == tty->termios.c_cc[VEOF]) { 550 return 1; 551 } 552 else if (c == '\n') { 553 if (tty->termios.c_lflag & (ECHO | ECHONL)) 554 echo (c, tty); 555 tty->cbuf[tty->ccount++] = c; 556 return 1; 557 } 558 else if ((c == tty->termios.c_cc[VEOL]) 559 || (c == tty->termios.c_cc[VEOL2])) { 560 if (tty->termios.c_lflag & ECHO) 561 echo (c, tty); 562 tty->cbuf[tty->ccount++] = c; 563 return 1; 564 } 565 } 566 567 /* 568 * FIXME: Should do IMAXBEL handling somehow 569 */ 570 if (tty->ccount < (CBUFSIZE-1)) { 571 if (tty->termios.c_lflag & ECHO) 572 echo (c, tty); 573 tty->cbuf[tty->ccount++] = c; 574 } 575 return 0; 568 576 } 569 577 … … 574 582 siproc (unsigned char c, struct rtems_termios_tty *tty) 575 583 { 576 577 578 579 580 581 582 583 584 585 586 587 588 589 584 int i; 585 586 /* 587 * Obtain output semaphore if character will be echoed 588 */ 589 if (tty->termios.c_lflag & (ECHO|ECHOE|ECHOK|ECHONL|ECHOPRT|ECHOCTL|ECHOKE)) { 590 rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 591 i = iproc (c, tty); 592 rtems_semaphore_release (tty->osem); 593 } 594 else { 595 i = iproc (c, tty); 596 } 597 return i; 590 598 } 591 599 … … 596 604 fillBufferPoll (struct rtems_termios_tty *tty) 597 605 { 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 606 unsigned char c; 607 int n; 608 609 if (tty->termios.c_lflag & ICANON) { 610 for (;;) { 611 n = (*tty->read)(tty->minor, &c); 612 if (n < 0) { 613 return RTEMS_UNSATISFIED; 614 } 615 else if (n == 0) { 616 rtems_task_wake_after (1); 617 } 618 else { 619 if (siproc (c, tty)) 620 break; 621 } 622 } 623 } 624 else { 625 rtems_interval then, now; 626 if (!tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME]) 627 rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then); 628 for (;;) { 629 n = (*tty->read)(tty->minor, &c); 630 if (n < 0) { 631 return RTEMS_UNSATISFIED; 632 } 633 else if (n == 0) { 634 if (tty->termios.c_cc[VMIN]) { 635 if (tty->termios.c_cc[VTIME] && tty->ccount) { 636 rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now); 637 if ((now - then) > tty->vtimeTicks) { 638 break; 639 } 640 } 641 } 642 else { 643 if (!tty->termios.c_cc[VTIME]) 644 break; 645 rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now); 646 if ((now - then) > tty->vtimeTicks) { 647 break; 648 } 649 } 650 rtems_task_wake_after (1); 651 } 652 else { 653 siproc (c, tty); 654 if (tty->ccount >= tty->termios.c_cc[VMIN]) 655 break; 656 if (tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME]) 657 rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then); 658 } 659 } 660 } 661 return RTEMS_SUCCESSFUL; 654 662 } 655 663 … … 660 668 fillBufferQueue (struct rtems_termios_tty *tty) 661 669 { 662 rtems_interval timeout = tty->rawMessageFirstTimeout; 663 rtems_status_code sc; 664 rtems_unsigned8 c; 665 666 for (;;) { 667 668 /* 669 * Read characters from raw queue 670 */ 671 sc = rtems_semaphore_obtain (tty->rawInputSem, 672 tty->rawMessageOptions, 673 timeout); 674 if (sc != RTEMS_SUCCESSFUL) 675 break; 676 Ring_buffer_Remove_character( &tty->rawInputBuffer, c ); 677 678 /* 679 * Process characters read from raw queue 680 */ 681 if (tty->termios.c_lflag & ICANON) { 682 if (siproc (c, tty)) 683 return RTEMS_SUCCESSFUL; 684 } 685 else { 686 siproc (c, tty); 687 if (tty->ccount >= tty->termios.c_cc[VMIN]) 688 return RTEMS_SUCCESSFUL; 689 } 690 691 timeout = tty->rawMessageTimeout; 692 } 693 return RTEMS_SUCCESSFUL; 670 rtems_interval timeout = tty->rawBufSemaphoreFirstTimeout; 671 rtems_status_code sc; 672 673 for (;;) { 674 /* 675 * Process characters read from raw queue 676 */ 677 while (tty->rawBufHead != tty->rawBufTail) { 678 unsigned char c; 679 unsigned int newHead; 680 681 newHead = (tty->rawBufHead + 1) % RAW_BUFFER_SIZE; 682 c = tty->rawBuf[newHead]; 683 tty->rawBufHead = newHead; 684 if (tty->termios.c_lflag & ICANON) { 685 if (siproc (c, tty)) 686 return RTEMS_SUCCESSFUL; 687 } 688 else { 689 siproc (c, tty); 690 if (tty->ccount >= tty->termios.c_cc[VMIN]) 691 return RTEMS_SUCCESSFUL; 692 } 693 timeout = tty->rawBufSemaphoreTimeout; 694 } 695 696 /* 697 * Wait for characters 698 */ 699 sc = rtems_semaphore_obtain (tty->rawBufSemaphore, 700 tty->rawBufSemaphoreOptions, 701 timeout); 702 if (sc != RTEMS_SUCCESSFUL) 703 break; 704 } 705 return RTEMS_SUCCESSFUL; 694 706 } 695 707 … … 697 709 rtems_termios_read (void *arg) 698 710 { 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 711 rtems_libio_rw_args_t *args = arg; 712 struct rtems_termios_tty *tty = args->iop->data1; 713 unsigned32 count = args->count; 714 unsigned8 *buffer = args->buffer; 715 rtems_status_code sc; 716 717 sc = rtems_semaphore_obtain (tty->isem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 718 if (sc != RTEMS_SUCCESSFUL) 719 return sc; 720 if (tty->cindex == tty->ccount) { 721 tty->cindex = tty->ccount = 0; 722 tty->read_start_column = tty->column; 723 if (tty->read) 724 sc = fillBufferPoll (tty); 725 else 726 sc = fillBufferQueue (tty); 727 if (sc != RTEMS_SUCCESSFUL) 728 tty->cindex = tty->ccount = 0; 729 } 730 while (count && (tty->cindex < tty->ccount)) { 731 *buffer++ = tty->cbuf[tty->cindex++]; 732 count--; 733 } 734 args->bytes_moved = args->count - count; 735 rtems_semaphore_release (tty->isem); 736 return sc; 725 737 } 726 738 … … 732 744 rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len) 733 745 { 734 struct rtems_termios_tty *tty = ttyp; 735 736 while (len) { 737 if (Ring_buffer_Is_full(&tty->rawInputBuffer)) 738 break; 739 Ring_buffer_Add_character(&tty->rawInputBuffer, *buf); 740 if (rtems_semaphore_release(tty->rawInputSem) != RTEMS_SUCCESSFUL) 741 break; 742 len -= 1; 743 buf += 1; 744 } 745 } 746 746 struct rtems_termios_tty *tty = ttyp; 747 unsigned int newTail; 748 749 while (len) { 750 newTail = (tty->rawBufTail + 1) % RAW_BUFFER_SIZE; 751 if (newTail == tty->rawBufHead) { 752 tty->rawBufDropped += len; 753 break; 754 } 755 tty->rawBuf[newTail] = *buf++; 756 len--; 757 tty->rawBufTail = newTail; 758 } 759 rtems_semaphore_release (tty->rawBufSemaphore); 760 } 761 762 /* 763 * Reserve enough resources to at least open every physical device 764 * once. 765 */ 766 767 void rtems_termios_reserve_resources( 768 rtems_configuration_table *configuration, 769 rtems_unsigned32 number_of_devices 770 ) 771 { 772 static int first_time = 1; 773 rtems_api_configuration_table *rtems_config; 774 775 if (!configuration) 776 rtems_fatal_error_occurred (0xFFF0F001); 777 778 rtems_config = configuration->RTEMS_api_configuration; 779 if (!rtems_config) 780 rtems_fatal_error_occurred (0xFFF0F002); 781 782 if (first_time) 783 rtems_config->maximum_semaphores += 1; 784 785 first_time = 0; 786 rtems_config->maximum_semaphores += (3 * number_of_devices); 787 } -
cpukit/libcsupport/include/rtems/libio.h
r3dbcece r118a812 148 148 rtems_status_code rtems_termios_ioctl (void *arg); 149 149 void rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len); 150 void rtems_termios_reserve_resources( 151 rtems_configuration_table *configuration, 152 rtems_unsigned32 number_of_devices 153 ); 150 154 151 155 #endif /* _RTEMS_LIBIO_H */ -
cpukit/libcsupport/src/termios.c
r3dbcece r118a812 24 24 #include <termios.h> 25 25 #include <unistd.h> 26 #include <ringbuf.h>27 26 28 27 /* 29 28 * The size of the cooked buffer 30 29 */ 31 #define CBUFSIZE 256 30 #define CBUFSIZE 256 31 32 /* 33 * The size of the raw input message queue 34 */ 35 #define RAW_BUFFER_SIZE 128 32 36 33 37 /* … … 36 40 */ 37 41 struct rtems_termios_tty { 38 /* 39 * Linked-list of active TERMIOS devices 40 */ 41 struct rtems_termios_tty *forw; 42 struct rtems_termios_tty *back; 43 44 /* 45 * How many times has this device been opened 46 */ 47 int refcount; 48 49 /* 50 * This device 51 */ 52 rtems_device_major_number major; 53 rtems_device_major_number minor; 54 55 /* 56 * Mutual-exclusion semaphores 57 */ 58 rtems_id isem; 59 rtems_id osem; 60 61 /* 62 * The canonical (cooked) character buffer 63 */ 64 char cbuf[CBUFSIZE]; 65 int ccount; 66 int cindex; 67 68 /* 69 * Keep track of cursor (printhead) position 70 */ 71 int column; 72 int read_start_column; 73 74 /* 75 * The ioctl settings 76 */ 77 struct termios termios; 78 rtems_interval vtimeTicks; 79 80 /* 81 * Raw character buffer 82 */ 83 rtems_id rawInputSem; 84 Ring_buffer_t rawInputBuffer; 85 86 rtems_unsigned32 rawMessageOptions; 87 rtems_interval rawMessageTimeout; 88 rtems_interval rawMessageFirstTimeout; 89 90 /* 91 * Callbacks to device-specific routines 92 */ 93 int (*lastClose)(int major, int minor, void *arg); 94 int (*read)(int minor, char *buf ); 95 int (*write)(int minor, char *buf, int len); 42 /* 43 * Linked-list of active TERMIOS devices 44 */ 45 struct rtems_termios_tty *forw; 46 struct rtems_termios_tty *back; 47 48 /* 49 * How many times has this device been opened 50 */ 51 int refcount; 52 53 /* 54 * This device 55 */ 56 rtems_device_major_number major; 57 rtems_device_major_number minor; 58 59 /* 60 * Mutual-exclusion semaphores 61 */ 62 rtems_id isem; 63 rtems_id osem; 64 65 /* 66 * The canonical (cooked) character buffer 67 */ 68 char cbuf[CBUFSIZE]; 69 int ccount; 70 int cindex; 71 72 /* 73 * Keep track of cursor (printhead) position 74 */ 75 int column; 76 int read_start_column; 77 78 /* 79 * The ioctl settings 80 */ 81 struct termios termios; 82 rtems_interval vtimeTicks; 83 84 /* 85 * Raw character buffer 86 */ 87 volatile char rawBuf[RAW_BUFFER_SIZE]; 88 volatile unsigned int rawBufHead; 89 volatile unsigned int rawBufTail; 90 rtems_id rawBufSemaphore; 91 rtems_unsigned32 rawBufSemaphoreOptions; 92 rtems_interval rawBufSemaphoreTimeout; 93 rtems_interval rawBufSemaphoreFirstTimeout; 94 unsigned int rawBufDropped; /* Statistics */ 95 96 /* 97 * Callbacks to device-specific routines 98 */ 99 int (*lastClose)(int major, int minor, void *arg); 100 int (*read)(int minor, char *buf); 101 int (*write)(int minor, char *buf, int len); 96 102 }; 97 103 static struct rtems_termios_tty *ttyHead, *ttyTail; … … 101 107 rtems_termios_initialize (void) 102 108 { 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 } 119 109 rtems_status_code sc; 110 111 /* 112 * Create the mutex semaphore for the tty list 113 */ 114 if (!ttyMutex) { 115 sc = rtems_semaphore_create ( 116 rtems_build_name ('T', 'R', 'm', 'i'), 117 1, 118 RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, 119 RTEMS_NO_PRIORITY, 120 &ttyMutex); 121 if (sc != RTEMS_SUCCESSFUL) 122 rtems_fatal_error_occurred (sc); 123 } 124 } 125 120 126 /* 121 127 * Open a termios device … … 128 134 int (*deviceFirstOpen)(int major, int minor, void *arg), 129 135 int (*deviceLastClose)(int major, int minor, void *arg), 130 int (*deviceRead)(int minor, char *buf /*, int len*/),136 int (*deviceRead)(int minor, char *buf), 131 137 int (*deviceWrite)(int minor, char *buf, int len) 132 138 ) 133 139 { 134 rtems_status_code sc; 135 rtems_libio_open_close_args_t *args = arg; 136 struct rtems_termios_tty *tty; 137 138 /* 139 * See if the device has already been opened 140 */ 141 sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 142 if (sc != RTEMS_SUCCESSFUL) 143 return sc; 144 for (tty = ttyHead ; tty != NULL ; tty = tty->forw) { 145 if ((tty->major == major) && (tty->minor == minor)) 146 break; 147 } 148 if (tty == NULL) { 149 static char c = 'a'; 150 151 /* 152 * Create a new device 153 */ 154 tty = malloc (sizeof (struct rtems_termios_tty)); 155 if (tty == NULL) { 156 rtems_semaphore_release (ttyMutex); 157 return RTEMS_NO_MEMORY; 158 } 159 tty->forw = ttyHead; 160 ttyHead = tty; 161 tty->back = NULL; 162 if (ttyTail == NULL) 163 ttyTail = tty; 164 165 /* 166 * Set up mutex semaphores 167 */ 168 sc = rtems_semaphore_create ( 169 rtems_build_name ('T', 'R', 'i', c), 170 1, 171 RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, 172 RTEMS_NO_PRIORITY, 173 &tty->isem); 174 if (sc != RTEMS_SUCCESSFUL) 175 rtems_fatal_error_occurred (sc); 176 sc = rtems_semaphore_create ( 177 rtems_build_name ('T', 'R', 'o', c), 178 1, 179 RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, 180 RTEMS_NO_PRIORITY, 181 &tty->osem); 182 if (sc != RTEMS_SUCCESSFUL) 183 rtems_fatal_error_occurred (sc); 184 185 /* 186 * Set callbacks 187 */ 188 tty->write = deviceWrite; 189 tty->lastClose = deviceLastClose; 190 if ((tty->read = deviceRead) == NULL) { 191 sc = rtems_semaphore_create ( 192 rtems_build_name ('T', 'R', 'r', c), 193 0, 194 RTEMS_COUNTING_SEMAPHORE | RTEMS_FIFO | RTEMS_LOCAL, 195 RTEMS_NO_PRIORITY, 196 &tty->rawInputSem); 197 if (sc != RTEMS_SUCCESSFUL) 198 rtems_fatal_error_occurred (sc); 199 } 200 201 /* 202 * Initialize variables 203 */ 204 tty->column = 0; 205 tty->cindex = tty->ccount = 0; 206 207 /* 208 * Set default parameters 209 */ 210 tty->termios.c_iflag = BRKINT | ICRNL | IXON | IMAXBEL; 211 tty->termios.c_oflag = OPOST | ONLCR | XTABS; 212 tty->termios.c_cflag = B9600 | CS8 | CREAD; 213 tty->termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOK | ECHOE | ECHOCTL; 214 tty->termios.c_cc[VINTR] = '\003'; 215 tty->termios.c_cc[VQUIT] = '\034'; 216 tty->termios.c_cc[VERASE] = '\177'; 217 tty->termios.c_cc[VKILL] = '\025'; 218 tty->termios.c_cc[VEOF] = '\004'; 219 tty->termios.c_cc[VEOL] = '\000'; 220 tty->termios.c_cc[VEOL2] = '\000'; 221 tty->termios.c_cc[VSTART] = '\021'; 222 tty->termios.c_cc[VSTOP] = '\023'; 223 tty->termios.c_cc[VSUSP] = '\032'; 224 tty->termios.c_cc[VREPRINT] = '\022'; 225 tty->termios.c_cc[VDISCARD] = '\017'; 226 tty->termios.c_cc[VWERASE] = '\027'; 227 tty->termios.c_cc[VLNEXT] = '\026'; 228 229 /* 230 * Device-specific open 231 */ 232 if (deviceFirstOpen) 233 (*deviceFirstOpen) (major, minor, arg); 234 235 /* 236 * Bump name characer 237 */ 238 if (c++ == 'z') 239 c = 'a'; 240 } 241 tty->refcount++; 242 args->iop->data1 = tty; 243 rtems_semaphore_release (ttyMutex); 244 return RTEMS_SUCCESSFUL; 140 rtems_status_code sc; 141 rtems_libio_open_close_args_t *args = arg; 142 struct rtems_termios_tty *tty; 143 144 /* 145 * See if the device has already been opened 146 */ 147 sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 148 if (sc != RTEMS_SUCCESSFUL) 149 return sc; 150 for (tty = ttyHead ; tty != NULL ; tty = tty->forw) { 151 if ((tty->major == major) && (tty->minor == minor)) 152 break; 153 } 154 if (tty == NULL) { 155 static char c = 'a'; 156 157 /* 158 * Create a new device 159 */ 160 tty = malloc (sizeof (struct rtems_termios_tty)); 161 if (tty == NULL) { 162 rtems_semaphore_release (ttyMutex); 163 return RTEMS_NO_MEMORY; 164 } 165 tty->forw = ttyHead; 166 ttyHead = tty; 167 tty->back = NULL; 168 if (ttyTail == NULL) 169 ttyTail = tty; 170 171 /* 172 * Set up mutex semaphores 173 */ 174 sc = rtems_semaphore_create ( 175 rtems_build_name ('T', 'R', 'i', c), 176 1, 177 RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, 178 RTEMS_NO_PRIORITY, 179 &tty->isem); 180 if (sc != RTEMS_SUCCESSFUL) 181 rtems_fatal_error_occurred (sc); 182 sc = rtems_semaphore_create ( 183 rtems_build_name ('T', 'R', 'o', c), 184 1, 185 RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, 186 RTEMS_NO_PRIORITY, 187 &tty->osem); 188 if (sc != RTEMS_SUCCESSFUL) 189 rtems_fatal_error_occurred (sc); 190 191 /* 192 * Set callbacks 193 */ 194 tty->write = deviceWrite; 195 tty->lastClose = deviceLastClose; 196 if ((tty->read = deviceRead) == NULL) { 197 sc = rtems_semaphore_create ( 198 rtems_build_name ('T', 'R', 'r', c), 199 0, 200 RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY, 201 RTEMS_NO_PRIORITY, 202 &tty->rawBufSemaphore); 203 if (sc != RTEMS_SUCCESSFUL) 204 rtems_fatal_error_occurred (sc); 205 tty->rawBufHead = 0; 206 tty->rawBufTail = 0; 207 } 208 209 /* 210 * Initialize variables 211 */ 212 tty->column = 0; 213 tty->cindex = tty->ccount = 0; 214 215 /* 216 * Set default parameters 217 */ 218 tty->termios.c_iflag = BRKINT | ICRNL | IXON | IMAXBEL; 219 tty->termios.c_oflag = OPOST | ONLCR | XTABS; 220 tty->termios.c_cflag = B9600 | CS8 | CREAD; 221 tty->termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOK | ECHOE | ECHOCTL; 222 tty->termios.c_cc[VINTR] = '\003'; 223 tty->termios.c_cc[VQUIT] = '\034'; 224 tty->termios.c_cc[VERASE] = '\177'; 225 tty->termios.c_cc[VKILL] = '\025'; 226 tty->termios.c_cc[VEOF] = '\004'; 227 tty->termios.c_cc[VEOL] = '\000'; 228 tty->termios.c_cc[VEOL2] = '\000'; 229 tty->termios.c_cc[VSTART] = '\021'; 230 tty->termios.c_cc[VSTOP] = '\023'; 231 tty->termios.c_cc[VSUSP] = '\032'; 232 tty->termios.c_cc[VREPRINT] = '\022'; 233 tty->termios.c_cc[VDISCARD] = '\017'; 234 tty->termios.c_cc[VWERASE] = '\027'; 235 tty->termios.c_cc[VLNEXT] = '\026'; 236 237 /* 238 * Device-specific open 239 */ 240 if (deviceFirstOpen) 241 (*deviceFirstOpen) (major, minor, arg); 242 243 /* 244 * Bump name characer 245 */ 246 if (c++ == 'z') 247 c = 'a'; 248 } 249 tty->refcount++; 250 args->iop->data1 = tty; 251 rtems_semaphore_release (ttyMutex); 252 return RTEMS_SUCCESSFUL; 245 253 } 246 254 … … 248 256 rtems_termios_close (void *arg) 249 257 { 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 rtems_semaphore_delete (tty->rawInputSem);272 273 274 275 258 rtems_libio_open_close_args_t *args = arg; 259 struct rtems_termios_tty *tty = args->iop->data1; 260 rtems_status_code sc; 261 262 sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 263 if (sc != RTEMS_SUCCESSFUL) 264 rtems_fatal_error_occurred (sc); 265 if (--tty->refcount == 0) { 266 if (tty->lastClose) 267 (*tty->lastClose) (tty->major, tty->minor, arg); 268 if (tty->forw == NULL) 269 ttyTail = tty->back; 270 else 271 tty->forw->back = tty->back; 272 if (tty->back == NULL) 273 ttyHead = tty->forw; 274 else 275 tty->back->forw = tty->forw; 276 rtems_semaphore_delete (tty->isem); 277 rtems_semaphore_delete (tty->osem); 278 if (tty->read == NULL) 279 rtems_semaphore_delete (tty->rawBufSemaphore); 280 free (tty); 281 } 282 rtems_semaphore_release (ttyMutex); 283 return RTEMS_SUCCESSFUL; 276 284 } 277 285 … … 279 287 rtems_termios_ioctl (void *arg) 280 288 { 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 tty->rawMessageOptions = RTEMS_WAIT;301 tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;302 tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;303 304 305 306 307 308 309 tty->rawMessageOptions = RTEMS_WAIT;310 tty->rawMessageTimeout = tty->vtimeTicks;311 312 tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;313 314 tty->rawMessageFirstTimeout = tty->vtimeTicks;315 316 317 318 tty->rawMessageOptions = RTEMS_WAIT;319 tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;320 tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;321 322 323 tty->rawMessageOptions = RTEMS_NO_WAIT;324 325 326 327 328 329 330 289 rtems_libio_ioctl_args_t *args = arg; 290 struct rtems_termios_tty *tty = args->iop->data1; 291 rtems_status_code sc; 292 293 sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 294 if (sc != RTEMS_SUCCESSFUL) 295 return sc; 296 switch (args->command) { 297 default: 298 sc = RTEMS_INVALID_NUMBER; 299 break; 300 301 case RTEMS_IO_GET_ATTRIBUTES: 302 *(struct termios *)args->buffer = tty->termios; 303 break; 304 305 case RTEMS_IO_SET_ATTRIBUTES: 306 tty->termios = *(struct termios *)args->buffer; 307 if (tty->termios.c_lflag & ICANON) { 308 tty->rawBufSemaphoreOptions = RTEMS_WAIT; 309 tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT; 310 tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT; 311 } 312 else { 313 rtems_interval ticksPerSecond; 314 rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond); 315 tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10; 316 if (tty->termios.c_cc[VTIME]) { 317 tty->rawBufSemaphoreOptions = RTEMS_WAIT; 318 tty->rawBufSemap`oreTimeout = tty->vtimeTicks; 319 if (tty->termios.c_cc[VMIN]) 320 tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT; 321 else 322 tty->rawBufSemaphoreFirstTimeout = tty->vtimeTicks; 323 } 324 else { 325 if (tty->termios.c_cc[VMIN]) { 326 tty->rawBufSemaphoreOptions = RTEMS_WAIT; 327 tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT; 328 tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT; 329 } 330 else { 331 tty->rawBufSemaphoreOptions = RTEMS_NO_WAIT; 332 } 333 } 334 } 335 break; 336 } 337 rtems_semaphore_release (tty->osem); 338 return sc; 331 339 } 332 340 … … 337 345 oproc (unsigned char c, struct rtems_termios_tty *tty) 338 346 { 339 inti;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 347 int i; 348 349 if (tty->termios.c_oflag & OPOST) { 350 switch (c) { 351 case '\n': 352 if (tty->termios.c_oflag & ONLRET) 353 tty->column = 0; 354 if (tty->termios.c_oflag & ONLCR) { 355 (*tty->write)(tty->minor, "\r", 1); 356 tty->column = 0; 357 } 358 break; 359 360 case '\r': 361 if ((tty->termios.c_oflag & ONOCR) && (tty->column == 0)) 362 return; 363 if (tty->termios.c_oflag & OCRNL) { 364 c = '\n'; 365 if (tty->termios.c_oflag & ONLRET) 366 tty->column = 0; 367 break; 368 } 369 tty->column = 0; 370 break; 371 372 case '\t': 373 i = 8 - (tty->column & 7); 374 if ((tty->termios.c_oflag & TABDLY) == XTABS) { 375 tty->column += i; 376 (*tty->write)(tty->minor, " ", i); 377 return; 378 } 379 tty->column += i; 380 break; 381 382 case '\b': 383 if (tty->column > 0) 384 tty->column--; 385 break; 386 387 default: 388 if (tty->termios.c_oflag & OLCUC) 389 c = toupper(c); 390 if (!iscntrl(c)) 391 tty->column++; 392 break; 393 } 394 } 395 (*tty->write)(tty->minor, &c, 1); 388 396 } 389 397 … … 391 399 rtems_termios_write (void *arg) 392 400 { 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 401 rtems_libio_rw_args_t *args = arg; 402 struct rtems_termios_tty *tty = args->iop->data1; 403 rtems_status_code sc; 404 405 sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 406 if (sc != RTEMS_SUCCESSFUL) 407 return sc; 408 if (tty->termios.c_oflag & OPOST) { 409 unsigned32 count = args->count; 410 unsigned8 *buffer = args->buffer; 411 while (count--) 412 oproc (*buffer++, tty); 413 args->bytes_moved = args->count; 414 } 415 else { 416 if ((*tty->write)(tty->minor, args->buffer, args->count) < 0) 417 sc = RTEMS_UNSATISFIED; 418 else 419 args->bytes_moved = args->count; 420 } 421 rtems_semaphore_release (tty->osem); 422 return sc; 415 423 } 416 424 … … 421 429 echo (unsigned char c, struct rtems_termios_tty *tty) 422 430 { 423 424 425 426 427 428 429 430 431 432 433 431 if ((tty->termios.c_lflag & ECHOCTL) && iscntrl(c) && (c != '\t') && (c != '\n')) { 432 char echobuf[2]; 433 434 echobuf[0] = '^'; 435 echobuf[1] = c ^ 0x40; 436 (*tty->write)(tty->minor, echobuf, 2); 437 tty->column += 2; 438 } 439 else { 440 oproc (c, tty); 441 } 434 442 } 435 443 … … 442 450 erase (struct rtems_termios_tty *tty, int lineFlag) 443 451 { 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 452 if (tty->ccount == 0) 453 return; 454 if (lineFlag) { 455 if (!(tty->termios.c_lflag & ECHO)) { 456 tty->ccount = 0; 457 return; 458 } 459 if (!(tty->termios.c_lflag & ECHOE)) { 460 tty->ccount = 0; 461 echo (tty->termios.c_cc[VKILL], tty); 462 if (tty->termios.c_lflag & ECHOK) 463 echo ('\n', tty); 464 return; 465 } 466 } 467 while (tty->ccount) { 468 unsigned char c = tty->cbuf[--tty->ccount]; 469 470 if (tty->termios.c_lflag & ECHO) { 471 if (!lineFlag && !(tty->termios.c_lflag & ECHOE)) { 472 echo (tty->termios.c_cc[VERASE], tty); 473 } 474 else if (c == '\t') { 475 int col = tty->read_start_column; 476 int i = 0; 477 478 /* 479 * Find the character before the tab 480 */ 481 while (i != tty->ccount) { 482 c = tty->cbuf[i++]; 483 if (c == '\t') { 484 col = (col | 7) + 1; 485 } 486 else if (iscntrl (c)) { 487 if (tty->termios.c_lflag & ECHOCTL) 488 col += 2; 489 } 490 else { 491 col++; 492 } 493 } 494 495 /* 496 * Back up over the tab 497 */ 498 while (tty->column > col) { 499 (*tty->write)(tty->minor, "\b", 1); 500 tty->column--; 501 } 502 } 503 else { 504 if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) { 505 (*tty->write)(tty->minor, "\b \b", 3); 506 if (tty->column) 507 tty->column--; 508 } 509 if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) { 510 (*tty->write)(tty->minor, "\b \b", 3); 511 if (tty->column) 512 tty->column--; 513 } 514 } 515 } 516 if (!lineFlag) 517 break; 518 } 511 519 } 512 520 … … 517 525 iproc (unsigned char c, struct rtems_termios_tty *tty) 518 526 { 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 527 if (tty->termios.c_iflag & ISTRIP) 528 c &= 0x7f; 529 if (tty->termios.c_iflag & IUCLC) 530 c = tolower (c); 531 if (c == '\r') { 532 if (tty->termios.c_iflag & IGNCR) 533 return 0; 534 if (tty->termios.c_iflag & ICRNL) 535 c = '\n'; 536 } 537 else if ((c == '\n') && (tty->termios.c_iflag & INLCR)) { 538 c = '\r'; 539 } 540 if ((c != '\0') && (tty->termios.c_lflag & ICANON)) { 541 if (c == tty->termios.c_cc[VERASE]) { 542 erase (tty, 0); 543 return 0; 544 } 545 else if (c == tty->termios.c_cc[VKILL]) { 546 erase (tty, 1); 547 return 0; 548 } 549 else if (c == tty->termios.c_cc[VEOF]) { 550 return 1; 551 } 552 else if (c == '\n') { 553 if (tty->termios.c_lflag & (ECHO | ECHONL)) 554 echo (c, tty); 555 tty->cbuf[tty->ccount++] = c; 556 return 1; 557 } 558 else if ((c == tty->termios.c_cc[VEOL]) 559 || (c == tty->termios.c_cc[VEOL2])) { 560 if (tty->termios.c_lflag & ECHO) 561 echo (c, tty); 562 tty->cbuf[tty->ccount++] = c; 563 return 1; 564 } 565 } 566 567 /* 568 * FIXME: Should do IMAXBEL handling somehow 569 */ 570 if (tty->ccount < (CBUFSIZE-1)) { 571 if (tty->termios.c_lflag & ECHO) 572 echo (c, tty); 573 tty->cbuf[tty->ccount++] = c; 574 } 575 return 0; 568 576 } 569 577 … … 574 582 siproc (unsigned char c, struct rtems_termios_tty *tty) 575 583 { 576 577 578 579 580 581 582 583 584 585 586 587 588 589 584 int i; 585 586 /* 587 * Obtain output semaphore if character will be echoed 588 */ 589 if (tty->termios.c_lflag & (ECHO|ECHOE|ECHOK|ECHONL|ECHOPRT|ECHOCTL|ECHOKE)) { 590 rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 591 i = iproc (c, tty); 592 rtems_semaphore_release (tty->osem); 593 } 594 else { 595 i = iproc (c, tty); 596 } 597 return i; 590 598 } 591 599 … … 596 604 fillBufferPoll (struct rtems_termios_tty *tty) 597 605 { 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 606 unsigned char c; 607 int n; 608 609 if (tty->termios.c_lflag & ICANON) { 610 for (;;) { 611 n = (*tty->read)(tty->minor, &c); 612 if (n < 0) { 613 return RTEMS_UNSATISFIED; 614 } 615 else if (n == 0) { 616 rtems_task_wake_after (1); 617 } 618 else { 619 if (siproc (c, tty)) 620 break; 621 } 622 } 623 } 624 else { 625 rtems_interval then, now; 626 if (!tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME]) 627 rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then); 628 for (;;) { 629 n = (*tty->read)(tty->minor, &c); 630 if (n < 0) { 631 return RTEMS_UNSATISFIED; 632 } 633 else if (n == 0) { 634 if (tty->termios.c_cc[VMIN]) { 635 if (tty->termios.c_cc[VTIME] && tty->ccount) { 636 rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now); 637 if ((now - then) > tty->vtimeTicks) { 638 break; 639 } 640 } 641 } 642 else { 643 if (!tty->termios.c_cc[VTIME]) 644 break; 645 rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now); 646 if ((now - then) > tty->vtimeTicks) { 647 break; 648 } 649 } 650 rtems_task_wake_after (1); 651 } 652 else { 653 siproc (c, tty); 654 if (tty->ccount >= tty->termios.c_cc[VMIN]) 655 break; 656 if (tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME]) 657 rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then); 658 } 659 } 660 } 661 return RTEMS_SUCCESSFUL; 654 662 } 655 663 … … 660 668 fillBufferQueue (struct rtems_termios_tty *tty) 661 669 { 662 rtems_interval timeout = tty->rawMessageFirstTimeout; 663 rtems_status_code sc; 664 rtems_unsigned8 c; 665 666 for (;;) { 667 668 /* 669 * Read characters from raw queue 670 */ 671 sc = rtems_semaphore_obtain (tty->rawInputSem, 672 tty->rawMessageOptions, 673 timeout); 674 if (sc != RTEMS_SUCCESSFUL) 675 break; 676 Ring_buffer_Remove_character( &tty->rawInputBuffer, c ); 677 678 /* 679 * Process characters read from raw queue 680 */ 681 if (tty->termios.c_lflag & ICANON) { 682 if (siproc (c, tty)) 683 return RTEMS_SUCCESSFUL; 684 } 685 else { 686 siproc (c, tty); 687 if (tty->ccount >= tty->termios.c_cc[VMIN]) 688 return RTEMS_SUCCESSFUL; 689 } 690 691 timeout = tty->rawMessageTimeout; 692 } 693 return RTEMS_SUCCESSFUL; 670 rtems_interval timeout = tty->rawBufSemaphoreFirstTimeout; 671 rtems_status_code sc; 672 673 for (;;) { 674 /* 675 * Process characters read from raw queue 676 */ 677 while (tty->rawBufHead != tty->rawBufTail) { 678 unsigned char c; 679 unsigned int newHead; 680 681 newHead = (tty->rawBufHead + 1) % RAW_BUFFER_SIZE; 682 c = tty->rawBuf[newHead]; 683 tty->rawBufHead = newHead; 684 if (tty->termios.c_lflag & ICANON) { 685 if (siproc (c, tty)) 686 return RTEMS_SUCCESSFUL; 687 } 688 else { 689 siproc (c, tty); 690 if (tty->ccount >= tty->termios.c_cc[VMIN]) 691 return RTEMS_SUCCESSFUL; 692 } 693 timeout = tty->rawBufSemaphoreTimeout; 694 } 695 696 /* 697 * Wait for characters 698 */ 699 sc = rtems_semaphore_obtain (tty->rawBufSemaphore, 700 tty->rawBufSemaphoreOptions, 701 timeout); 702 if (sc != RTEMS_SUCCESSFUL) 703 break; 704 } 705 return RTEMS_SUCCESSFUL; 694 706 } 695 707 … … 697 709 rtems_termios_read (void *arg) 698 710 { 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 711 rtems_libio_rw_args_t *args = arg; 712 struct rtems_termios_tty *tty = args->iop->data1; 713 unsigned32 count = args->count; 714 unsigned8 *buffer = args->buffer; 715 rtems_status_code sc; 716 717 sc = rtems_semaphore_obtain (tty->isem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 718 if (sc != RTEMS_SUCCESSFUL) 719 return sc; 720 if (tty->cindex == tty->ccount) { 721 tty->cindex = tty->ccount = 0; 722 tty->read_start_column = tty->column; 723 if (tty->read) 724 sc = fillBufferPoll (tty); 725 else 726 sc = fillBufferQueue (tty); 727 if (sc != RTEMS_SUCCESSFUL) 728 tty->cindex = tty->ccount = 0; 729 } 730 while (count && (tty->cindex < tty->ccount)) { 731 *buffer++ = tty->cbuf[tty->cindex++]; 732 count--; 733 } 734 args->bytes_moved = args->count - count; 735 rtems_semaphore_release (tty->isem); 736 return sc; 725 737 } 726 738 … … 732 744 rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len) 733 745 { 734 struct rtems_termios_tty *tty = ttyp; 735 736 while (len) { 737 if (Ring_buffer_Is_full(&tty->rawInputBuffer)) 738 break; 739 Ring_buffer_Add_character(&tty->rawInputBuffer, *buf); 740 if (rtems_semaphore_release(tty->rawInputSem) != RTEMS_SUCCESSFUL) 741 break; 742 len -= 1; 743 buf += 1; 744 } 745 } 746 746 struct rtems_termios_tty *tty = ttyp; 747 unsigned int newTail; 748 749 while (len) { 750 newTail = (tty->rawBufTail + 1) % RAW_BUFFER_SIZE; 751 if (newTail == tty->rawBufHead) { 752 tty->rawBufDropped += len; 753 break; 754 } 755 tty->rawBuf[newTail] = *buf++; 756 len--; 757 tty->rawBufTail = newTail; 758 } 759 rtems_semaphore_release (tty->rawBufSemaphore); 760 } 761 762 /* 763 * Reserve enough resources to at least open every physical device 764 * once. 765 */ 766 767 void rtems_termios_reserve_resources( 768 rtems_configuration_table *configuration, 769 rtems_unsigned32 number_of_devices 770 ) 771 { 772 static int first_time = 1; 773 rtems_api_configuration_table *rtems_config; 774 775 if (!configuration) 776 rtems_fatal_error_occurred (0xFFF0F001); 777 778 rtems_config = configuration->RTEMS_api_configuration; 779 if (!rtems_config) 780 rtems_fatal_error_occurred (0xFFF0F002); 781 782 if (first_time) 783 rtems_config->maximum_semaphores += 1; 784 785 first_time = 0; 786 rtems_config->maximum_semaphores += (3 * number_of_devices); 787 }
Note: See TracChangeset
for help on using the changeset viewer.