Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 48 additions & 70 deletions components/drivers/serial/dev_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <rtdbg.h>

#ifdef RT_USING_POSIX_STDIO
#include <stdlib.h>
#include <dfs_file.h>
#include <fcntl.h>
#include <unistd.h>
Expand Down Expand Up @@ -1339,12 +1340,16 @@ static rt_err_t rt_serial_control(struct rt_device *dev,
}
else config.parity = PARITY_NONE;

ret = serial->ops->configure(serial, &config);
if (ret != RT_EOK)
/* Software-only termios changes must not reset the UART FIFO. */
if (rt_memcmp(&config, &serial->config, sizeof(config)) != 0)
{
return ret;
ret = serial->ops->configure(serial, &config);
if (ret != RT_EOK)
{
return ret;
}
serial->config = config;
}
serial->config = config;
}
break;
#ifndef RT_USING_TTY
Expand All @@ -1370,85 +1375,58 @@ static rt_err_t rt_serial_control(struct rt_device *dev,
break;
case TIOCGWINSZ:
{
struct winsize* p_winsize;
p_winsize = (struct winsize*)args;

if(rt_thread_self() != rt_thread_find("tshell"))
struct winsize *winsize = (struct winsize *)args;
char response[32] = { 0 };
const char query[] = "\033[18t";
rt_tick_t start_tick;
rt_size_t i = 0;
unsigned long rows, columns;
char *end;

if (winsize == RT_NULL)
{
/* only can be used in tshell thread; otherwise, return default size */
p_winsize->ws_col = 80;
p_winsize->ws_row = 24;
ret = -RT_EINVAL;
break;
}
else
{
#include <shell.h>
#define _TIO_BUFLEN 20
char _tio_buf[_TIO_BUFLEN];
unsigned char cnt1, cnt2, cnt3, i;
char row_s[4], col_s[4];
char *p;

rt_memset(_tio_buf, 0, _TIO_BUFLEN);
rt_memset(winsize, 0, sizeof(*winsize));
winsize->ws_row = 24;
winsize->ws_col = 80;
rt_device_write(dev, -1, query, sizeof(query) - 1);

/* send the command to terminal for getting the window size of the terminal */
rt_kprintf("\033[18t");

/* waiting for the response from the terminal */
i = 0;
while(i < _TIO_BUFLEN)
start_tick = rt_tick_get();
while (i < sizeof(response) - 1 &&
rt_tick_get() - start_tick < rt_tick_from_millisecond(200))
{
if (rt_device_read(dev, -1, &response[i], 1) == 1)
{
_tio_buf[i] = finsh_getchar();
if(_tio_buf[i] != 't')
{
i ++;
}
else
if (response[i++] == 't')
{
break;
}
}
if(i == _TIO_BUFLEN)
{
/* buffer overloaded, and return default size */
p_winsize->ws_col = 80;
p_winsize->ws_row = 24;
break;
}

/* interpreting data eg: "\033[8;1;15t" which means row is 1 and col is 15 (unit: size of ONE character) */
rt_memset(row_s,0,4);
rt_memset(col_s,0,4);
cnt1 = 0;
while(cnt1 < _TIO_BUFLEN && _tio_buf[cnt1] != ';')
{
cnt1++;
}
cnt2 = ++cnt1;
while(cnt2 < _TIO_BUFLEN && _tio_buf[cnt2] != ';')
{
cnt2++;
}
p = row_s;
while(cnt1 < cnt2)
{
*p++ = _tio_buf[cnt1++];
}
p = col_s;
cnt2++;
cnt3 = rt_strlen(_tio_buf) - 1;
while(cnt2 < cnt3)
else
{
*p++ = _tio_buf[cnt2++];
rt_thread_mdelay(1);
}

/* load the window size date */
p_winsize->ws_col = atoi(col_s);
p_winsize->ws_row = atoi(row_s);
#undef _TIO_BUFLEN
}

p_winsize->ws_xpixel = 0;/* unused */
p_winsize->ws_ypixel = 0;/* unused */
if (rt_memcmp(response, "\033[8;", 4) != 0)
{
break;
}
rows = strtoul(response + 4, &end, 10);
if (*end != ';')
{
break;
}
columns = strtoul(end + 1, &end, 10);
if (*end == 't' && end[1] == '\0' &&
rows != 0 && rows <= 999 && columns != 0 && columns <= 999)
{
winsize->ws_row = rows;
winsize->ws_col = columns;
}
}
break;
case FIONREAD:
Expand Down
106 changes: 40 additions & 66 deletions components/drivers/serial/dev_serial_v2.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#endif /* RT_SERIAL_BUF_STRATEGY_DROP */

#ifdef RT_USING_POSIX_STDIO
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
Expand Down Expand Up @@ -1873,85 +1874,58 @@ static rt_err_t rt_serial_control(struct rt_device *dev,
break;
case TIOCGWINSZ:
{
struct winsize *p_winsize;
p_winsize = (struct winsize *)args;

if (rt_thread_self() != rt_thread_find(FINSH_THREAD_NAME))
struct winsize *winsize = (struct winsize *)args;
char response[32] = { 0 };
const char query[] = "\033[18t";
rt_tick_t start_tick;
rt_size_t i = 0;
unsigned long rows, columns;
char *end;

if (winsize == RT_NULL)
{
/* only can be used in tshell thread; otherwise, return default size */
p_winsize->ws_col = 80;
p_winsize->ws_row = 24;
ret = -RT_EINVAL;
break;
}
else
{
#include <shell.h>
#define _TIO_BUFLEN 20
char _tio_buf[_TIO_BUFLEN];
unsigned char cnt1, cnt2, cnt3, i;
char row_s[4], col_s[4];
char *p;

rt_memset(_tio_buf, 0, _TIO_BUFLEN);

/* send the command to terminal for getting the window size of the terminal */
rt_kprintf("\033[18t");
rt_memset(winsize, 0, sizeof(*winsize));
winsize->ws_row = 24;
winsize->ws_col = 80;
rt_device_write(dev, -1, query, sizeof(query) - 1);

/* waiting for the response from the terminal */
i = 0;
while (i < _TIO_BUFLEN)
start_tick = rt_tick_get();
while (i < sizeof(response) - 1 &&
rt_tick_get() - start_tick < rt_tick_from_millisecond(200))
{
if (rt_device_read(dev, -1, &response[i], 1) == 1)
{
_tio_buf[i] = finsh_getchar();
if (_tio_buf[i] != 't')
{
i++;
}
else
if (response[i++] == 't')
{
break;
}
}
if (i == _TIO_BUFLEN)
{
/* buffer overloaded, and return default size */
p_winsize->ws_col = 80;
p_winsize->ws_row = 24;
break;
}

/* interpreting data eg: "\033[8;1;15t" which means row is 1 and col is 15 (unit: size of ONE character) */
rt_memset(row_s, 0, 4);
rt_memset(col_s, 0, 4);
cnt1 = 0;
while (cnt1 < _TIO_BUFLEN && _tio_buf[cnt1] != ';')
{
cnt1++;
}
cnt2 = ++cnt1;
while (cnt2 < _TIO_BUFLEN && _tio_buf[cnt2] != ';')
{
cnt2++;
}
p = row_s;
while (cnt1 < cnt2)
{
*p++ = _tio_buf[cnt1++];
}
p = col_s;
cnt2++;
cnt3 = rt_strlen(_tio_buf) - 1;
while (cnt2 < cnt3)
else
{
*p++ = _tio_buf[cnt2++];
rt_thread_mdelay(1);
}

/* load the window size date */
p_winsize->ws_col = atoi(col_s);
p_winsize->ws_row = atoi(row_s);
#undef _TIO_BUFLEN
}

p_winsize->ws_xpixel = 0; /* unused */
p_winsize->ws_ypixel = 0; /* unused */
if (rt_memcmp(response, "\033[8;", 4) != 0)
{
break;
}
rows = strtoul(response + 4, &end, 10);
if (*end != ';')
{
break;
}
columns = strtoul(end + 1, &end, 10);
if (*end == 't' && end[1] == '\0' &&
rows != 0 && rows <= 999 && columns != 0 && columns <= 999)
{
winsize->ws_row = rows;
winsize->ws_col = columns;
}
}
break;
case FIONREAD:
Expand Down
38 changes: 24 additions & 14 deletions components/drivers/serial/serial_tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include <rtdevice.h>
#include <terminal/terminal.h>

#include <sys/ioctl.h>

#define TTY_NAME_PREFIX "S" /* (S)erial */
#define LWP_TTY_WORKQUEUE_PRIORITY 3

Expand Down Expand Up @@ -159,6 +161,19 @@ static void _serial_tty_set_speed(struct lwp_tty *tp)
tp->t_termios_init_in.__c_ispeed = tp->t_termios_init_in.__c_ospeed = cfgetospeed(&tp->t_termios_init_in);
}

static void _serial_tty_update_winsize(struct lwp_tty *tp,
struct rt_serial_device *serial)
{
struct winsize winsz;

rt_memset(&winsz, 0, sizeof(winsz));
if (rt_device_control(&serial->parent, TIOCGWINSZ, &winsz) == RT_EOK &&
winsz.ws_row != 0 && winsz.ws_col != 0)
{
tp->t_winsize = winsz;
}
}

static int _serial_isbusy(struct rt_serial_device *serial)
{
rt_thread_t user_thread = rt_console_current_user();
Expand Down Expand Up @@ -222,6 +237,13 @@ static int serial_tty_open(struct lwp_tty *tp)
* to avoid driver accesssing null data,
* these are setup only after tty is registered
*/
if (rt_console_get_device() == &serial->parent)
{
/* Query before the bypass is installed so the response stays in
* the raw serial receive queue instead of being delivered as
* input. */
_serial_tty_update_winsize(tp, serial);
}
_setup_serial(serial, tp, softc);
}
return error;
Expand All @@ -243,20 +265,8 @@ static void serial_tty_close(struct lwp_tty *tp)
static int serial_tty_ioctl(struct lwp_tty *tp, rt_ubase_t cmd, rt_caddr_t data,
struct rt_thread *td)
{
int error;
switch (cmd)
{
default:
/**
* Note: for the most case, we don't let serial layer handle ioctl,
* for that they can't act properly regarding to the process
* management system, since it is unawared of that. So a ENOSYS is
* returned and caused the TTY layer to handle ioctl itself.
*/
error = -ENOSYS;
break;
}
return error;
/* Let the TTY layer handle process state and cached terminal settings. */
return -ENOSYS;
}

static int serial_tty_param(struct lwp_tty *tp, struct termios *t)
Expand Down
Loading