1494 hardware serial support broken by v565 (#1496)

* bugfix: changing serial status did not check if the port was available

* bugfix: setbaud did not check if the port was available

* refactor: implementation improvements
This commit is contained in:
Dimitris Panokostas 2024-10-30 17:36:22 +01:00 committed by GitHub
parent 06ead89b9d
commit 318bc68406
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -343,28 +343,32 @@ static int opentcp (const TCHAR *sername)
int openser (const TCHAR *sername)
{
if (_tcsnicmp(sername, _T("tcp:"), 4) == 0) {
return opentcp(sername);
if (!_tcsnicmp(sername, _T("TCP://"), 6)) {
return opentcp(sername + 6);
}
if (!_tcsnicmp(sername, _T("TCP:"), 4)) {
return opentcp(sername + 4);
}
/* Call sp_get_port_by_name() to find the port. The port
* pointer will be updated to refer to the port found. */
check(sp_get_port_by_name(sername, &port));
int result = check(sp_open(port, SP_MODE_READ_WRITE));
if (sp_get_port_by_name(sername, &port) != SP_OK) {
write_log("Error finding serial port %s\n", sername);
return 0;
}
check(sp_set_baudrate(port, 9600));
check(sp_set_bits(port, 8));
check(sp_set_parity(port, SP_PARITY_NONE));
check(sp_set_stopbits(port, currprefs.serial_stopbits));
if (currprefs.serial_hwctsrts)
{
check(sp_set_flowcontrol(port, SP_FLOWCONTROL_RTSCTS));
if (sp_open(port, SP_MODE_READ_WRITE) != SP_OK) {
write_log("Error opening serial port %s\n", sername);
sp_free_port(port);
port = NULL;
return 0;
}
else
{
check(sp_set_flowcontrol(port, SP_FLOWCONTROL_NONE));
}
return result;
sp_set_baudrate(port, 9600);
sp_set_bits(port, 8);
sp_set_parity(port, SP_PARITY_NONE);
sp_set_stopbits(port, 1);
sp_set_flowcontrol(port, SP_FLOWCONTROL_NONE);
return 1;
}
void closeser ()
@ -388,10 +392,10 @@ void closeser ()
midi_emu_close();
}
#endif
if (serdev)
{
check(sp_close(port));
if (port != NULL) {
sp_close(port);
sp_free_port(port);
port = NULL;
}
}
@ -519,17 +523,28 @@ int readser(int* buffer)
}
dataininput = 0;
dataininputcnt = 0;
if (serdev) {
const int bytes = check(sp_input_waiting(port));
if (bytes) {
int len = bytes;
if (port != nullptr) {
int bytes_available = sp_input_waiting(port);
if (bytes_available < 0) {
write_log("Error checking input buffer: %s\n", sp_last_error_message());
return 0;
}
if (bytes_available > 0) {
int len = bytes_available;
if (len > sizeof(inputbuffer))
len = sizeof(inputbuffer);
dataininput = check(sp_blocking_read(port, inputbuffer, len, timeout));
dataininputcnt = 0;
if (!dataininput) {
int bytes_read = sp_nonblocking_read(port, inputbuffer, len);
if (bytes_read < 0) {
write_log("Error reading from serial port: %s\n", sp_last_error_message());
return 0;
}
dataininput = bytes_read;
dataininputcnt = 0;
if (bytes_read == 0)
return 0;
return readser(buffer);
}
}
@ -539,8 +554,15 @@ int readser(int* buffer)
void flushser(void)
{
if (serdev) {
check(sp_flush(port, SP_BUF_BOTH));
if (port) {
sp_flush(port, SP_BUF_INPUT);
}
else {
while (readseravail(NULL)) {
int data;
if (readser(&data) <= 0)
break;
}
}
}
@ -569,14 +591,17 @@ int readseravail(bool* breakcond)
return 0;
if (dataininput > dataininputcnt)
return 1;
if (serdev) {
if (port) {
if (breakcond && breakpending) {
*breakcond = true;
breakpending = false;
}
const int bytes = check(sp_input_waiting(port));
if (bytes > 0)
return bytes;
int bytes_available = sp_input_waiting(port);
if (bytes_available < 0) {
write_log("Error checking input buffer: %s\n", sp_last_error_message());
return 0;
}
return bytes_available;
}
}
return 0;
@ -781,7 +806,14 @@ static void outser(void)
return;
memcpy(outputbufferout, outputbuffer, datainoutput);
check(sp_nonblocking_write(port, outputbufferout, datainoutput));
int bytes_written = sp_blocking_write(port, outputbufferout, datainoutput, 1000);
if (bytes_written < 0) {
write_log("Failed to write to serial port: %d\n", bytes_written);
}
else if (bytes_written != datainoutput) {
write_log("Only wrote %d of %d bytes!\n", bytes_written, datainoutput);
}
datainoutput = 0;
}
@ -810,7 +842,7 @@ void writeser(int c)
midi_send_byte((uint8_t) c);
#endif
} else {
if (!serdev || !currprefs.use_serial)
if (!port || !currprefs.use_serial)
return;
if (datainoutput + 1 < sizeof(outputbuffer)) {
outputbuffer[datainoutput++] = c;
@ -824,7 +856,7 @@ void writeser(int c)
int checkserwrite(int spaceneeded)
{
if (!serdev || !currprefs.use_serial)
if (!port || !currprefs.use_serial)
return 1;
#ifdef WITH_MIDI
if (midi_ready) {
@ -1151,6 +1183,29 @@ void serial_hsynchandler (void)
}
}
void setserstat(int mask, int onoff)
{
if (mask & SP_FLOWCONTROL_DTRDSR)
{
if (currprefs.use_serial && port != nullptr)
{
check(sp_set_flowcontrol(port, onoff ? SP_FLOWCONTROL_DTRDSR : SP_FLOWCONTROL_NONE));
check(sp_set_dtr(port, onoff ? SP_DTR_ON : SP_DTR_OFF));
}
}
if (!currprefs.serial_hwctsrts)
{
if (mask & SP_FLOWCONTROL_RTSCTS)
{
if (currprefs.use_serial && port != nullptr)
{
check(sp_set_flowcontrol(port, onoff ? SP_FLOWCONTROL_RTSCTS : SP_FLOWCONTROL_NONE));
check(sp_set_rts(port, onoff ? SP_RTS_ON : SP_RTS_OFF));
}
}
}
}
int setbaud(int baud, int org_baud)
{
#ifdef WITH_MIDI
@ -1184,7 +1239,11 @@ int setbaud(int baud, int org_baud)
#endif
if (!currprefs.use_serial)
return 1;
return check(sp_set_baudrate(port, baud));
if (port != nullptr)
{
check(sp_set_baudrate(port, baud));
}
return 1;
}
void SERPER(uae_u16 w)
@ -1401,7 +1460,7 @@ void serial_dtr_on(void)
#ifdef SERIAL_PORT
if (currprefs.serial_demand)
serial_open();
check(sp_set_flowcontrol(port, SP_FLOWCONTROL_DTRDSR));
setserstat(SP_FLOWCONTROL_DTRDSR, dtr);
#endif
}
@ -1419,7 +1478,7 @@ void serial_dtr_off(void)
#ifdef SERIAL_PORT
if (currprefs.serial_demand)
serial_close();
check(sp_set_flowcontrol(port, SP_FLOWCONTROL_NONE));
setserstat(SP_FLOWCONTROL_DTRDSR, dtr);
#endif
}
@ -1482,7 +1541,8 @@ uae_u8 serial_readstatus(uae_u8 v, uae_u8 dir)
} else if (currprefs.use_serial) {
#ifdef SERIAL_PORT
/* Read the current config from the port into that configuration. */
check(sp_get_signals(port, &signal));
if (port != nullptr)
check(sp_get_signals(port, &signal));
#endif
}
else {
@ -1586,12 +1646,12 @@ uae_u8 serial_writestatus(uae_u8 newstate, uae_u8 dir)
if (!currprefs.serial_hwctsrts && currprefs.serial_rtsctsdtrdtecd && (dir & 0x40)) {
if ((oldserbits ^ newstate) & 0x40) {
if (newstate & 0x40) {
check(sp_set_flowcontrol(port, SP_FLOWCONTROL_NONE));
setserstat(SP_FLOWCONTROL_RTSCTS, 0);
#if SERIALHSDEBUG > 0
write_log(_T("SERIAL: RTS cleared\n"));
#endif
} else {
check(sp_set_flowcontrol(port, SP_FLOWCONTROL_RTSCTS));
setserstat(SP_FLOWCONTROL_RTSCTS, 1);
#if SERIALHSDEBUG > 0
write_log(_T("SERIAL: RTS set\n"));
#endif
@ -1774,7 +1834,7 @@ void serial_uartbreak (int v)
shmem_serial_send(0x40000000 | (v ? 0x20000 : 0x10000));
}
#endif
if (!serdev || !currprefs.use_serial)
if (!port || !currprefs.use_serial)
return;
#ifdef SERIAL_PORT
if (v)