Changeset 9fa0f54 in rtems


Ignore:
Timestamp:
02/23/17 10:35:44 (7 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
5, master
Children:
c80f6aa9
Parents:
49d8f653
git-author:
Sebastian Huber <sebastian.huber@…> (02/23/17 10:35:44)
git-committer:
Sebastian Huber <sebastian.huber@…> (02/28/17 08:05:42)
Message:

termios: Change receive callback invocation

Call the receive callback in case a read will succeed without to block.
This enables the use of the receive callback for a poll() and select()
support. Increase raw input buffer size to allow buffering of one line.

Close #2916.

Files:
2 edited

Legend:

Unmodified
Added
Removed
  • cpukit/libcsupport/src/termios.c

    r49d8f653 r9fa0f54  
    8585
    8686static size_t rtems_termios_cbufsize = 256;
    87 static size_t rtems_termios_raw_input_size = 128;
     87static size_t rtems_termios_raw_input_size = 256;
    8888static size_t rtems_termios_raw_output_size = 64;
    8989
     
    12831283}
    12841284
    1285 /*
    1286  * Process a single input character
    1287  */
    1288 static int
    1289 iproc (unsigned char c, struct rtems_termios_tty *tty)
     1285static unsigned char
     1286iprocEarly (unsigned char c, rtems_termios_tty *tty)
    12901287{
    12911288  if (tty->termios.c_iflag & ISTRIP)
     
    13031300  }
    13041301
     1302  return c;
     1303}
     1304
     1305/*
     1306 * Process a single input character
     1307 */
     1308static int
     1309iproc (unsigned char c, struct rtems_termios_tty *tty)
     1310{
    13051311  if ((c != '\0') && (tty->termios.c_lflag & ICANON)) {
    13061312    if (c == tty->termios.c_cc[VERASE]) {
     
    13731379  }
    13741380
     1381  c = iprocEarly (c, tty);
    13751382  return siproc (c, tty);
    13761383}
     
    15691576}
    15701577
     1578static bool
     1579mustCallReceiveCallback (const rtems_termios_tty *tty, unsigned char c,
     1580                         unsigned int newTail, unsigned int head)
     1581{
     1582  if ((tty->termios.c_lflag & ICANON) != 0) {
     1583    return c == '\n' || c == tty->termios.c_cc[VEOF] ||
     1584      c == tty->termios.c_cc[VEOL] || c == tty->termios.c_cc[VEOL2];
     1585  } else {
     1586    unsigned int rawContentSize = (newTail - head) % tty->rawInBuf.Size;
     1587
     1588    return rawContentSize >= tty->termios.c_cc[VMIN];
     1589  }
     1590}
     1591
    15711592/*
    15721593 * Place characters on raw queue.
     
    16461667      unsigned int oldTail;
    16471668      unsigned int newTail;
     1669      bool callReciveCallback;
    16481670
    16491671      if (c == '\r' && (tty->termios.c_iflag & IGNCR) != 0) {
    16501672        continue;
    16511673      }
     1674
     1675      c = iprocEarly (c, tty);
    16521676
    16531677      rtems_termios_device_lock_acquire (ctx, &lock_context);
     
    16811705      }
    16821706
     1707      callReciveCallback = false;
     1708
    16831709      if (newTail != head) {
    16841710        tty->rawInBuf.theBuf[newTail] = c;
    16851711        tty->rawInBuf.Tail = newTail;
    1686 
    1687         rtems_termios_device_lock_release (ctx, &lock_context);
    16881712
    16891713        /*
     
    16911715         */
    16921716        if (tty->tty_rcv.sw_pfn != NULL && !tty->tty_rcvwakeup) {
    1693           tty->tty_rcvwakeup = true;
    1694           (*tty->tty_rcv.sw_pfn)(&tty->termios, tty->tty_rcv.sw_arg);
     1717          if (mustCallReceiveCallback (tty, c, newTail, head)) {
     1718            tty->tty_rcvwakeup = true;
     1719            callReciveCallback = true;
     1720          }
    16951721        }
    16961722      } else {
    16971723        ++dropped;
    1698         rtems_termios_device_lock_release (ctx, &lock_context);
     1724
     1725        if (tty->tty_rcv.sw_pfn != NULL && !tty->tty_rcvwakeup) {
     1726          tty->tty_rcvwakeup = true;
     1727          callReciveCallback = true;
     1728        }
     1729      }
     1730
     1731      rtems_termios_device_lock_release (ctx, &lock_context);
     1732
     1733      if (callReciveCallback) {
     1734        (*tty->tty_rcv.sw_pfn)(&tty->termios, tty->tty_rcv.sw_arg);
    16991735      }
    17001736    }
  • testsuites/libtests/termios09/init.c

    r49d8f653 r9fa0f54  
    4949  char output_buf[OUTPUT_BUFFER_SIZE];
    5050  int input_char;
     51  int callback_counter;
    5152} device_context;
    5253
     
    147148  ctx->term[i].c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
    148149    | INLCR | IGNCR | ICRNL | IXON);
    149   ctx->term[i].c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
     150  ctx->term[i].c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT
     151    | ECHOCTL | ECHOKE | ICANON | ISIG | IEXTEN);
    150152  ctx->term[i].c_cflag &= ~(CSIZE | PARENB);
    151153  ctx->term[i].c_cflag |= CS8;
     
    208210}
    209211
     212static void clear_set_lflag(
     213  test_context *ctx,
     214  size_t i,
     215  tcflag_t clear,
     216  tcflag_t set
     217)
     218{
     219  ctx->term[i].c_lflag &= ~clear;
     220  ctx->term[i].c_lflag |= set;
     221  set_term(ctx, i);
     222}
     223
     224static void set_vmin_vtime(
     225  test_context *ctx,
     226  size_t i,
     227  cc_t vmin,
     228  cc_t vtime
     229)
     230{
     231  ctx->term[i].c_cc[VMIN] = vmin;
     232  ctx->term[i].c_cc[VTIME] = vtime;
     233  set_term(ctx, i);
     234}
     235
     236static void set_veol_veol2(
     237  test_context *ctx,
     238  size_t i,
     239  cc_t veol,
     240  cc_t veol2
     241)
     242{
     243  ctx->term[i].c_cc[VEOL] = veol;
     244  ctx->term[i].c_cc[VEOL2] = veol2;
     245  set_term(ctx, i);
     246}
     247
    210248static void test_igncr(test_context *ctx)
    211249{
     
    239277}
    240278
     279static void test_istrip(test_context *ctx)
     280{
     281  size_t i;
     282
     283  for (i = 0; i < DEVICE_COUNT; ++i) {
     284    ssize_t n;
     285    char c;
     286
     287    c = 'x';
     288
     289    clear_set_iflag(ctx, i, 0, ISTRIP);
     290
     291    n = read(ctx->fds[i], &c, sizeof(c));
     292    rtems_test_assert(n == 0);
     293    rtems_test_assert(c == 'x');
     294
     295    input(ctx, i, '\376');
     296
     297    n = read(ctx->fds[i], &c, sizeof(c));
     298    rtems_test_assert(n == 1);
     299    rtems_test_assert(c == '~');
     300
     301    clear_set_iflag(ctx, i, ISTRIP, 0);
     302    input(ctx, i, '\376');
     303
     304    n = read(ctx->fds[i], &c, sizeof(c));
     305    rtems_test_assert(n == 1);
     306    rtems_test_assert(c == '\376');
     307  }
     308}
     309
     310static void test_iuclc(test_context *ctx)
     311{
     312  size_t i;
     313
     314  for (i = 0; i < DEVICE_COUNT; ++i) {
     315    ssize_t n;
     316    char c;
     317
     318    c = 'x';
     319
     320    clear_set_iflag(ctx, i, 0, IUCLC);
     321
     322    n = read(ctx->fds[i], &c, sizeof(c));
     323    rtems_test_assert(n == 0);
     324    rtems_test_assert(c == 'x');
     325
     326    input(ctx, i, 'A');
     327
     328    n = read(ctx->fds[i], &c, sizeof(c));
     329    rtems_test_assert(n == 1);
     330    rtems_test_assert(c == 'a');
     331
     332    clear_set_iflag(ctx, i, IUCLC, 0);
     333    input(ctx, i, 'A');
     334
     335    n = read(ctx->fds[i], &c, sizeof(c));
     336    rtems_test_assert(n == 1);
     337    rtems_test_assert(c == 'A');
     338  }
     339}
     340
     341static void test_icrnl(test_context *ctx)
     342{
     343  size_t i;
     344
     345  for (i = 0; i < DEVICE_COUNT; ++i) {
     346    ssize_t n;
     347    char c;
     348
     349    c = 'x';
     350
     351    clear_set_iflag(ctx, i, 0, ICRNL);
     352
     353    n = read(ctx->fds[i], &c, sizeof(c));
     354    rtems_test_assert(n == 0);
     355    rtems_test_assert(c == 'x');
     356
     357    input(ctx, i, '\r');
     358
     359    n = read(ctx->fds[i], &c, sizeof(c));
     360    rtems_test_assert(n == 1);
     361    rtems_test_assert(c == '\n');
     362
     363    clear_set_iflag(ctx, i, ICRNL, 0);
     364    input(ctx, i, '\r');
     365
     366    n = read(ctx->fds[i], &c, sizeof(c));
     367    rtems_test_assert(n == 1);
     368    rtems_test_assert(c == '\r');
     369  }
     370}
     371
     372static void test_inlcr(test_context *ctx)
     373{
     374  size_t i;
     375
     376  for (i = 0; i < DEVICE_COUNT; ++i) {
     377    ssize_t n;
     378    char c;
     379
     380    c = 'x';
     381
     382    clear_set_iflag(ctx, i, 0, INLCR);
     383
     384    n = read(ctx->fds[i], &c, sizeof(c));
     385    rtems_test_assert(n == 0);
     386    rtems_test_assert(c == 'x');
     387
     388    input(ctx, i, '\n');
     389
     390    n = read(ctx->fds[i], &c, sizeof(c));
     391    rtems_test_assert(n == 1);
     392    rtems_test_assert(c == '\r');
     393
     394    clear_set_iflag(ctx, i, INLCR, 0);
     395    input(ctx, i, '\n');
     396
     397    n = read(ctx->fds[i], &c, sizeof(c));
     398    rtems_test_assert(n == 1);
     399    rtems_test_assert(c == '\n');
     400  }
     401}
     402
     403static void callback(struct termios *tty, void *arg)
     404{
     405  device_context *ctx = arg;
     406
     407  ++ctx->callback_counter;
     408}
     409
     410static void test_rx_callback(test_context *ctx)
     411{
     412  size_t i = INTERRUPT;
     413  device_context *dev = &ctx->devices[i];
     414  ssize_t n;
     415  char buf[3];
     416
     417  buf[0] = 'x';
     418
     419  dev->callback_counter = 0;
     420  dev->tty->tty_rcv.sw_pfn = callback;
     421  dev->tty->tty_rcv.sw_arg = dev;
     422  clear_set_lflag(ctx, i, ICANON, 0);
     423
     424  set_vmin_vtime(ctx, i, 0, 0);
     425
     426  n = read(ctx->fds[i], buf, 1);
     427  rtems_test_assert(n == 0);
     428  rtems_test_assert(buf[0] == 'x');
     429
     430  input(ctx, i, 'a');
     431  rtems_test_assert(dev->callback_counter == 1);
     432
     433  input(ctx, i, 'b');
     434  rtems_test_assert(dev->callback_counter == 1);
     435
     436  n = read(ctx->fds[i], buf, 2);
     437  rtems_test_assert(n == 2);
     438  rtems_test_assert(buf[0] == 'a');
     439  rtems_test_assert(buf[1] == 'b');
     440
     441  set_vmin_vtime(ctx, i, 2, 0);
     442
     443  input(ctx, i, 'd');
     444  rtems_test_assert(dev->callback_counter == 1);
     445
     446  input(ctx, i, 'e');
     447  rtems_test_assert(dev->callback_counter == 2);
     448
     449  input(ctx, i, 'f');
     450  rtems_test_assert(dev->callback_counter == 2);
     451
     452  n = read(ctx->fds[i], buf, 3);
     453  rtems_test_assert(n == 3);
     454  rtems_test_assert(buf[0] == 'd');
     455  rtems_test_assert(buf[1] == 'e');
     456  rtems_test_assert(buf[2] == 'f');
     457
     458  dev->tty->tty_rcv.sw_pfn = NULL;
     459  dev->tty->tty_rcv.sw_arg = NULL;
     460}
     461
     462static void test_rx_callback_icanon(test_context *ctx)
     463{
     464  size_t i = INTERRUPT;
     465  device_context *dev = &ctx->devices[i];
     466  ssize_t n;
     467  char buf[255];
     468  size_t j;
     469
     470  buf[0] = 'x';
     471
     472  dev->callback_counter = 0;
     473  dev->tty->tty_rcv.sw_pfn = callback;
     474  dev->tty->tty_rcv.sw_arg = dev;
     475
     476  set_vmin_vtime(ctx, i, 0, 0);
     477
     478  n = read(ctx->fds[i], buf, 1);
     479  rtems_test_assert(n == 0);
     480  rtems_test_assert(buf[0] == 'x');
     481
     482  clear_set_lflag(ctx, i, 0, ICANON);
     483  set_veol_veol2(ctx, i, '1', '2');
     484
     485  input(ctx, i, '\n');
     486  rtems_test_assert(dev->callback_counter == 1);
     487
     488  input(ctx, i, 'a');
     489  rtems_test_assert(dev->callback_counter == 1);
     490
     491  input(ctx, i, '\n');
     492  rtems_test_assert(dev->callback_counter == 1);
     493
     494  n = read(ctx->fds[i], buf, 3);
     495  rtems_test_assert(n == 3);
     496  rtems_test_assert(buf[0] == '\n');
     497  rtems_test_assert(buf[1] == 'a');
     498  rtems_test_assert(buf[2] == '\n');
     499
     500  input(ctx, i, '\4');
     501  rtems_test_assert(dev->callback_counter == 2);
     502
     503  input(ctx, i, 'b');
     504  rtems_test_assert(dev->callback_counter == 2);
     505
     506  input(ctx, i, '\n');
     507  rtems_test_assert(dev->callback_counter == 2);
     508
     509  n = read(ctx->fds[i], buf, 2);
     510  rtems_test_assert(n == 2);
     511  rtems_test_assert(buf[0] == 'b');
     512  rtems_test_assert(buf[1] == '\n');
     513
     514  input(ctx, i, '1');
     515  rtems_test_assert(dev->callback_counter == 3);
     516
     517  input(ctx, i, 'c');
     518  rtems_test_assert(dev->callback_counter == 3);
     519
     520  input(ctx, i, '\n');
     521  rtems_test_assert(dev->callback_counter == 3);
     522
     523  n = read(ctx->fds[i], buf, 3);
     524  rtems_test_assert(n == 3);
     525  rtems_test_assert(buf[0] == '1');
     526  rtems_test_assert(buf[1] == 'c');
     527  rtems_test_assert(buf[2] == '\n');
     528
     529  input(ctx, i, '2');
     530  rtems_test_assert(dev->callback_counter == 4);
     531
     532  input(ctx, i, 'd');
     533  rtems_test_assert(dev->callback_counter == 4);
     534
     535  input(ctx, i, '\n');
     536  rtems_test_assert(dev->callback_counter == 4);
     537
     538  n = read(ctx->fds[i], buf, 3);
     539  rtems_test_assert(n == 3);
     540  rtems_test_assert(buf[0] == '2');
     541  rtems_test_assert(buf[1] == 'd');
     542  rtems_test_assert(buf[2] == '\n');
     543
     544  for (j = 0; j < 255; ++j) {
     545    input(ctx, i, 'e');
     546    rtems_test_assert(dev->callback_counter == 4);
     547  }
     548
     549  /* Raw input buffer overflow */
     550  input(ctx, i, 'e');
     551  rtems_test_assert(dev->callback_counter == 5);
     552
     553  dev->tty->tty_rcv.sw_pfn = NULL;
     554  dev->tty->tty_rcv.sw_arg = NULL;
     555  set_veol_veol2(ctx, i, '\0', '\0');
     556  clear_set_lflag(ctx, i, ICANON, 0);
     557}
     558
    241559static void Init(rtems_task_argument arg)
    242560{
     
    247565  setup(ctx);
    248566  test_igncr(ctx);
     567  test_istrip(ctx);
     568  test_iuclc(ctx);
     569  test_icrnl(ctx);
     570  test_inlcr(ctx);
     571  test_rx_callback(ctx);
     572  test_rx_callback_icanon(ctx);
    249573
    250574  TEST_END();
Note: See TracChangeset for help on using the changeset viewer.