Reorganize forward_to_tty, tty_write, tty_raw_write functions

Add tty_raw_write function and reorganize roles of them.

tty_raw_write:
Performs any processing that must be done character-by-character on the
fly. That is, output delays and ONULBRK processing.

tty_write :
Converts input data using output mapping and passes it to tty_raw_write.

forward_to_tty :
Converts input data according to the input/output mode and passes it to
tty_write. (output-mapping function move to tty_write. tx_total
statistics counting move to tty_raw_write and tty_sync.)
This commit is contained in:
yabu76 2026-01-02 00:35:52 +09:00
parent 6425ffe66a
commit 3b7fe3d258
2 changed files with 112 additions and 74 deletions

160
src/tty.c
View file

@ -256,7 +256,10 @@ void tty_sync(int fd)
cp += count; cp += count;
remain -= count; remain -= count;
/* Reduce the number of additional sends */ // Update transmit statistics
tx_total += count;
// Reduce the number of additional writes
if (remain > 0) if (remain > 0)
{ {
int estimated_sendtime_us = (int)((int64_t)count * 10 * 1000 * 1000 / option.baudrate); int estimated_sendtime_us = (int)((int64_t)count * 10 * 1000 * 1000 / option.baudrate);
@ -274,39 +277,45 @@ void tty_sync(int fd)
tty_buffer_count = 0; tty_buffer_count = 0;
} }
ssize_t tty_write(int fd, void *buffer, size_t count) static ssize_t tty_raw_write(int fd)
{ {
ssize_t retval = 0, bytes_written = 0; if ( ! (option.output_delay || option.output_line_delay || option.map_o_nulbrk) )
{
return 0; // No-op in this function, write in tty_sync()
}
// Write byte by byte with output delay and null break
ssize_t retval = 0;
size_t i; size_t i;
unsigned char *cbuf = (unsigned char *)buffer;
if (option.map_o_ltu) for (i = 0; i < tty_buffer_count; i++)
{ {
// Convert lower case to upper case if ((tty_buffer[i] == 0) && (option.map_o_nulbrk))
for (i = 0; i < count; i++)
{ {
cbuf[i] = toupper(cbuf[i]); retval = tcsendbreak(fd, 0);
if (retval < 0)
{
tio_warning_printf("Could not send break");
goto error;
} }
continue;
} }
if (option.output_delay || option.output_line_delay) retval = write_poll(fd, &tty_buffer[i], 1, WRITE_POLL_FOREVER);
{
// Write byte by byte with output delay
for (i = 0; i < count; i++)
{
retval = write_poll(fd, &cbuf[i], 1, WRITE_POLL_FOREVER);
if (retval < 0) if (retval < 0)
{ {
// Error // Error
tio_debug_printf("Write error (%s)", strerror(errno)); tio_debug_printf("Write error (%s)", strerror(errno));
return retval; goto error;
} }
bytes_written += retval;
fsync(fd); fsync(fd);
tcdrain(fd); tcdrain(fd);
if (option.output_line_delay && cbuf[i] == option.output_line_delay_char) // Update transmit statistics
tx_total++;
if (option.output_line_delay && tty_buffer[i] == option.output_line_delay_char)
{ {
delay(option.output_line_delay); delay(option.output_line_delay);
} }
@ -315,23 +324,80 @@ ssize_t tty_write(int fd, void *buffer, size_t count)
delay(option.output_delay); delay(option.output_delay);
} }
} }
retval = tty_buffer_count;
// Path-through
error:
// Reset
tty_buffer_write_ptr = tty_buffer;
tty_buffer_count = 0;
return retval;
}
ssize_t tty_write(int fd, const void *buffer, size_t count)
{
int status;
const char *cp = (char *)buffer;
size_t i;
for (i = 0; i < count; i++, cp++)
{
char *tp;
int bytes_add;
if (tty_buffer_count >= BUFSIZ)
{
status = tty_raw_write(fd);
if (status < 0)
{
return status;
} }
else
{
// Force write of tty buffer if too full
if ((tty_buffer_count + count) > BUFSIZ)
{
tty_sync(fd); tty_sync(fd);
} }
// Copy bytes to tty write buffer /* Map output character */
memcpy(tty_buffer_write_ptr, buffer, count); bytes_add = -1; /* negative value means "not mapped yet" */
tty_buffer_write_ptr += count; tp = tty_buffer_write_ptr;
tty_buffer_count += count; if ((*cp == 127) && (option.map_o_del_bs))
bytes_written = count; {
*tp = '\b';
bytes_add = 1;
}
if ((*cp == '\r') && (option.map_o_cr_nl))
{
*tp = '\n';
bytes_add = 1;
}
if ((*cp == '\r') && (option.map_o_ign_cr))
{
bytes_add = 0;
}
if ((*cp == '\n' || *cp == '\r') && (option.map_o_nl_crnl))
{
*tp = '\r';
*(tp + 1) = '\n';
bytes_add = 2;
}
if (bytes_add < 0)
{
*tp = (option.map_o_ltu) ? toupper(*cp) : *cp;
bytes_add = 1;
} }
return bytes_written; if (bytes_add > 0)
{
tty_buffer_write_ptr += bytes_add;
tty_buffer_count += bytes_add;
}
}
status = tty_raw_write(fd);
if (status < 0)
{
return status;
}
return count;
} }
void *tty_stdin_input_thread(void *arg) void *tty_stdin_input_thread(void *arg)
@ -476,10 +542,6 @@ static void handle_hex_prompt(char c)
{ {
tio_warning_printf("Could not write to tty device"); tio_warning_printf("Could not write to tty device");
} }
else
{
tx_total++;
}
} }
} }
@ -2520,38 +2582,26 @@ void tty_restore(void)
} }
} }
/* output mode and local echo handling */
void forward_to_tty(int fd, char output_char) void forward_to_tty(int fd, char output_char)
{ {
int status; int status;
/* Map output character */
if ((output_char == 127) && (option.map_o_del_bs))
{
output_char = '\b';
}
if ((output_char == '\r') && (option.map_o_cr_nl))
{
output_char = '\n';
}
if ((output_char == '\r') && (option.map_o_ign_cr)) if ((output_char == '\r') && (option.map_o_ign_cr))
{ {
return; return;
} }
/* Map newline character */ /* local echo special case in newline character */
if ((output_char == '\n' || output_char == '\r') && (option.map_o_nl_crnl)) if ((output_char == '\n' || output_char == '\r') && (option.map_o_nl_crnl))
{ {
char crlf[] = "\r\n"; optional_local_echo('\r');
optional_local_echo('\n');
optional_local_echo(crlf[0]); status = tty_write(fd, &output_char, 1);
optional_local_echo(crlf[1]);
status = tty_write(fd, crlf, 2);
if (status < 0) if (status < 0)
{ {
tio_warning_printf("Could not write to tty device"); tio_warning_printf("Could not write to tty device");
} }
tx_total += 2;
} }
else else
{ {
@ -2570,22 +2620,11 @@ void forward_to_tty(int fd, char output_char)
optional_local_echo(output_char); optional_local_echo(output_char);
} }
if ((output_char == 0) && (option.map_o_nulbrk))
{
status = tcsendbreak(fd, 0);
}
else
{
status = tty_write(fd, &output_char, 1); status = tty_write(fd, &output_char, 1);
}
if (status < 0) if (status < 0)
{ {
tio_warning_printf("Could not write to tty device"); tio_warning_printf("Could not write to tty device");
} }
/* Update transmit statistics */
tx_total++;
} }
break; break;
@ -2604,7 +2643,6 @@ void forward_to_tty(int fd, char output_char)
else else
{ {
optional_local_echo(output_char); optional_local_echo(output_char);
tx_total++;
} }
} }
break; break;

View file

@ -86,5 +86,5 @@ void tty_line_set(int fd, tty_line_config_t line_config[]);
void tty_search(void); void tty_search(void);
GList *tty_search_for_serial_devices(void); GList *tty_search_for_serial_devices(void);
void forward_to_tty(int fd, char output_char); void forward_to_tty(int fd, char output_char);
ssize_t tty_write(int fd, void *buffer, size_t count); ssize_t tty_write(int fd, const void *buffer, size_t count);
void tty_sync(int fd); void tty_sync(int fd);