]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Serial port update, telnet cr/lf translation.
authorToni Wilen <twilen@winuae.net>
Sat, 2 May 2015 16:18:32 +0000 (19:18 +0300)
committerToni Wilen <twilen@winuae.net>
Sat, 2 May 2015 16:18:32 +0000 (19:18 +0300)
od-win32/parser.cpp
od-win32/serial_win32.cpp

index 8e87bcfef7be3cea517c40948babb30f75fc076f..3fcf3f4ab5d3270db1a94ba8557516543ff51f5f 100644 (file)
@@ -860,7 +860,7 @@ static bool tcp_is_connected (void)
                if (select (1, &fd, NULL, NULL, &tv)) {
                        serialconn = accept (serialsocket, (struct sockaddr*)socketaddr, &sa_len);
                        if (serialconn != INVALID_SOCKET)
-                               write_log (_T("SERIRAL_TCP: connection accepted\n"));
+                               write_log (_T("SERIAL_TCP: connection accepted\n"));
                }
        }
        return serialconn != INVALID_SOCKET;
@@ -1092,7 +1092,7 @@ void closeser (void)
 static void outser (void)
 {
        DWORD actual;
-       if (WaitForSingleObject (writeevent, 0) == WAIT_OBJECT_0 && datainoutput > 0) {
+       if (datainoutput > 0 && WaitForSingleObject (writeevent, 0) == WAIT_OBJECT_0 ) {
                memcpy (outputbufferout, outputbuffer, datainoutput);
                WriteFile (hCom, outputbufferout, datainoutput, &actual, &writeol);
                datainoutput = 0;
@@ -1125,7 +1125,7 @@ void writeser (int c)
        }
 }
 
-int checkserwrite (void)
+int checkserwrite (int spaceneeded)
 {
        if (hCom == INVALID_HANDLE_VALUE || !currprefs.use_serial)
                return 1;
@@ -1133,7 +1133,7 @@ int checkserwrite (void)
                return 1;
        } else {
                outser ();
-               if (datainoutput >= sizeof (outputbuffer) - 1)
+               if (datainoutput + spaceneeded >= sizeof (outputbuffer))
                        return 0;
        }
        return 1;
@@ -1191,6 +1191,7 @@ int readser (int *buffer)
                        int err = recv (serialconn, buf, 1, 0);
                        if (err == 1) {
                                *buffer = buf[0];
+                               //write_log(_T(" %02X "), buf[0]);
                                return 1;
                        } else {
                                tcp_disconnect ();
@@ -1386,77 +1387,90 @@ void hsyncstuff (void)
 const static GUID GUID_DEVINTERFACE_PARALLEL = {0x97F76EF0,0xF883,0x11D0,
 {0xAF,0x1F,0x00,0x00,0xF8,0x00,0x84,0x5C}};
 
+static const GUID serportsguids[] =
+{
+       GUID_DEVINTERFACE_COMPORT,
+       // GUID_DEVINTERFACE_MODEM
+       { 0x2C7089AA, 0x2E0E, 0x11D1, { 0xB1, 0x14, 0x00, 0xC0, 0x4F, 0xC2, 0xAA, 0xE4} }
+};
+static const GUID parportsguids[] =
+{
+       GUID_DEVINTERFACE_PARALLEL
+};
+
 static int enumports_2 (struct serparportinfo **pi, int cnt, bool parport)
 {
        // Create a device information set that will be the container for
        // the device interfaces.
        HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
        SP_DEVICE_INTERFACE_DETAIL_DATA *pDetData = NULL;
-       BOOL bOk = TRUE;
        SP_DEVICE_INTERFACE_DATA ifcData;
        DWORD dwDetDataSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA) + 256 * sizeof (TCHAR);
-       DWORD ii;
+       const GUID *guids = parport ? parportsguids : serportsguids;
+       int guidcnt = parport ? sizeof(parportsguids)/sizeof(parportsguids[0]) : sizeof(serportsguids)/sizeof(serportsguids[0]);
 
-       hDevInfo = SetupDiGetClassDevs (parport ? &GUID_DEVINTERFACE_PARALLEL : &GUID_DEVINTERFACE_COMPORT, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
-       if(hDevInfo == INVALID_HANDLE_VALUE)
-               return 0;
-       // Enumerate the serial ports
-       pDetData = (SP_DEVICE_INTERFACE_DETAIL_DATA*)xmalloc (uae_u8, dwDetDataSize);
-       // This is required, according to the documentation. Yes,
-       // it's weird.
-       ifcData.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA);
-       pDetData->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
-       for (ii = 0; bOk; ii++) {
-               bOk = SetupDiEnumDeviceInterfaces (hDevInfo, NULL, parport ? &GUID_DEVINTERFACE_PARALLEL : &GUID_DEVINTERFACE_COMPORT, ii, &ifcData);
-               if (bOk) {
-                       // Got a device. Get the details.
-                       SP_DEVINFO_DATA devdata = { sizeof (SP_DEVINFO_DATA)};
-                       bOk = SetupDiGetDeviceInterfaceDetail (hDevInfo,
-                               &ifcData, pDetData, dwDetDataSize, NULL, &devdata);
+       for (int guididx = 0; guididx < guidcnt; guididx++) {
+               hDevInfo = SetupDiGetClassDevs (&guids[guididx], NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+               if(hDevInfo == INVALID_HANDLE_VALUE)
+                       continue;
+               // Enumerate the serial ports
+               pDetData = (SP_DEVICE_INTERFACE_DETAIL_DATA*)xmalloc (uae_u8, dwDetDataSize);
+               // This is required, according to the documentation. Yes,
+               // it's weird.
+               ifcData.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA);
+               pDetData->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
+               BOOL bOk = TRUE;
+               for (int ii = 0; bOk; ii++) {
+                       bOk = SetupDiEnumDeviceInterfaces (hDevInfo, NULL, &guids[guididx], ii, &ifcData);
                        if (bOk) {
-                               // Got a path to the device. Try to get some more info.
-                               TCHAR fname[256];
-                               TCHAR desc[256];
-                               BOOL bSuccess = SetupDiGetDeviceRegistryProperty (
-                                       hDevInfo, &devdata, SPDRP_FRIENDLYNAME, NULL,
-                                       (PBYTE)fname, sizeof (fname), NULL);
-                               bSuccess = bSuccess && SetupDiGetDeviceRegistryProperty (
-                                       hDevInfo, &devdata, SPDRP_DEVICEDESC, NULL,
-                                       (PBYTE)desc, sizeof (desc), NULL);
-                               if (bSuccess && cnt < MAX_SERPAR_PORTS) {
-                                       TCHAR *p;
-                                       pi[cnt] = xcalloc (struct serparportinfo, 1);
-                                       pi[cnt]->dev = my_strdup (pDetData->DevicePath);
-                                       pi[cnt]->name = my_strdup (fname);
-                                       p = _tcsstr (fname, parport ? _T("(LPT") : _T("(COM"));
-                                       if (p && (p[5] == ')' || p[6] == ')')) {
-                                               pi[cnt]->cfgname = xmalloc (TCHAR, 100);
-                                               if (isdigit(p[5]))
-                                                       _stprintf (pi[cnt]->cfgname, parport ? _T("LPT%c%c") : _T("COM%c%c"), p[4], p[5]);
-                                               else
-                                                       _stprintf (pi[cnt]->cfgname, parport ? _T("LPT%c") : _T("COM%c"), p[4]);
-                                       } else {
-                                               pi[cnt]->cfgname = my_strdup (pDetData->DevicePath);
+                               // Got a device. Get the details.
+                               SP_DEVINFO_DATA devdata = { sizeof (SP_DEVINFO_DATA)};
+                               bOk = SetupDiGetDeviceInterfaceDetail (hDevInfo,
+                                       &ifcData, pDetData, dwDetDataSize, NULL, &devdata);
+                               if (bOk) {
+                                       // Got a path to the device. Try to get some more info.
+                                       TCHAR fname[256];
+                                       TCHAR desc[256];
+                                       BOOL bSuccess = SetupDiGetDeviceRegistryProperty (
+                                               hDevInfo, &devdata, SPDRP_FRIENDLYNAME, NULL,
+                                               (PBYTE)fname, sizeof (fname), NULL);
+                                       bSuccess = bSuccess && SetupDiGetDeviceRegistryProperty (
+                                               hDevInfo, &devdata, SPDRP_DEVICEDESC, NULL,
+                                               (PBYTE)desc, sizeof (desc), NULL);
+                                       if (bSuccess && cnt < MAX_SERPAR_PORTS) {
+                                               TCHAR *p;
+                                               pi[cnt] = xcalloc (struct serparportinfo, 1);
+                                               pi[cnt]->dev = my_strdup (pDetData->DevicePath);
+                                               pi[cnt]->name = my_strdup (fname);
+                                               p = _tcsstr (fname, parport ? _T("(LPT") : _T("(COM"));
+                                               if (p && (p[5] == ')' || p[6] == ')')) {
+                                                       pi[cnt]->cfgname = xmalloc (TCHAR, 100);
+                                                       if (isdigit(p[5]))
+                                                               _stprintf (pi[cnt]->cfgname, parport ? _T("LPT%c%c") : _T("COM%c%c"), p[4], p[5]);
+                                                       else
+                                                               _stprintf (pi[cnt]->cfgname, parport ? _T("LPT%c") : _T("COM%c"), p[4]);
+                                               } else {
+                                                       pi[cnt]->cfgname = my_strdup (pDetData->DevicePath);
+                                               }
+                                               write_log (_T("%s: '%s' = '%s' = '%s'\n"), parport ? _T("PARPORT") : _T("SERPORT"), pi[cnt]->name, pi[cnt]->cfgname, pi[cnt]->dev);
+                                               cnt++;
                                        }
-                                       write_log (_T("%s: '%s' = '%s' = '%s'\n"), parport ? _T("PARPORT") : _T("SERPORT"), pi[cnt]->name, pi[cnt]->cfgname, pi[cnt]->dev);
-                                       cnt++;
+                               } else {
+                                       write_log (_T("SetupDiGetDeviceInterfaceDetail failed, err=%d"), GetLastError ());
+                                       break;
                                }
                        } else {
-                               write_log (_T("SetupDiGetDeviceInterfaceDetail failed, err=%d"), GetLastError ());
-                               goto end;
-                       }
-               } else {
-                       DWORD err = GetLastError ();
-                       if (err != ERROR_NO_MORE_ITEMS) {
-                               write_log (_T("SetupDiEnumDeviceInterfaces failed, err=%d"), err);
-                               goto end;
+                               DWORD err = GetLastError ();
+                               if (err != ERROR_NO_MORE_ITEMS) {
+                                       write_log (_T("SetupDiEnumDeviceInterfaces failed, err=%d"), err);
+                                       break;
+                               }
                        }
                }
+               xfree(pDetData);
+               if (hDevInfo != INVALID_HANDLE_VALUE)
+                       SetupDiDestroyDeviceInfoList (hDevInfo);
        }
-end:
-       xfree(pDetData);
-       if (hDevInfo != INVALID_HANDLE_VALUE)
-               SetupDiDestroyDeviceInfoList (hDevInfo);
        return cnt;
 }
 
index c5fce8aae7fa101ee4d65a75f600e38fc9985761..b7e90a79a62db977e7f08e6421f1fa5805440a70 100644 (file)
@@ -155,6 +155,7 @@ bool shmem_serial_create(void)
 #define SERIALDEBUG 0 /* 0, 1, 2 3 */
 #define SERIALHSDEBUG 0
 #define MODEMTEST   0 /* 0 or 1 */
+#define SERIAL_HSYNC_BEFORE_OVERFLOW 200
 
 static int data_in_serdat; /* new data written to SERDAT */
 static int data_in_serdatr; /* new data received */
@@ -168,6 +169,8 @@ static int ninebit;
 static int lastbitcycle_active_hsyncs;
 static bool gotlogwrite;
 static unsigned int lastbitcycle;
+static int serial_recv_previous, serial_send_previous;
+static int serdatr_last_got;
 int serdev;
 int seriallog = 0, log_sercon = 0;
 int serial_enet;
@@ -233,6 +236,8 @@ void SERPER (uae_u16 w)
                        baud = 115200;
                serial_period_hsyncs = 1;
        }
+       serial_recv_previous = -1;
+       serial_send_previous = -1;
 #ifdef SERIAL_PORT
        setbaud (baud);
 #endif
@@ -248,11 +253,22 @@ static TCHAR dochar (int v)
        return '.';
 }
 
+static bool canreceive(void)
+{
+       if (!data_in_serdatr)
+               return true;
+       if (currprefs.serial_direct)
+               return false;
+       return serdatr_last_got >= SERIAL_HSYNC_BEFORE_OVERFLOW || currprefs.cpu_cycle_exact;
+}
+
 static void checkreceive_enet (void)
 {
 #ifdef SERIAL_ENET
        uae_u16 recdata;
 
+       if (!canreceive())
+               return;
        if (!enet_readseravail ())
                return;
        if (!enet_readser (&recdata))
@@ -263,6 +279,7 @@ static void checkreceive_enet (void)
        else
                serdatr |= 0x100;
        data_in_serdatr = 1;
+       serdatr_last_got = 0;
        serial_check_irq ();
 #if SERIALDEBUG > 2
        write_log (_T("SERIAL: received %02X (%c)\n"), serdatr & 0xff, dochar (serdatr));
@@ -276,10 +293,12 @@ static void checkreceive_serial (void)
        static int ninebitdata;
        int recdata;
 
-       if (!readseravail())
+       if (!canreceive())
                return;
 
        if (ninebit) {
+               if (!readseravail())
+                       return;
                for (;;) {
                        if (!readser (&recdata))
                                return;
@@ -300,12 +319,25 @@ static void checkreceive_serial (void)
                        }
                }
        } else {
-               if (!readser (&recdata))
+               if (!readseravail())
                        return;
+               if (!readser(&recdata))
+                       return;
+               if (currprefs.serial_crlf) {
+                       if (recdata == 0 || (serial_recv_previous == 13 && recdata == 10)) {
+                               //write_log(_T(" [%02X] "), (uae_u8)recdata);
+                               serial_recv_previous = -1;
+                               return;
+                       }
+               }
+               //write_log(_T(" %02X "), (uae_u8)recdata);
+               serial_recv_previous = recdata;
                serdatr = recdata;
                serdatr |= 0x100;
        }
+
        data_in_serdatr = 1;
+       serdatr_last_got = 0;
        serial_check_irq ();
 #if SERIALDEBUG > 2
        write_log (_T("SERIAL: received %02X (%c)\n"), serdatr & 0xff, dochar (serdatr));
@@ -318,8 +350,6 @@ static void serdatcopy(void);
 
 static void checksend(void)
 {
-       bool sent = true;
-
        if (data_in_sershift != 1)
                return;
 
@@ -331,20 +361,28 @@ static void checksend(void)
        }
 #endif
 #ifdef SERIAL_PORT
-       if (checkserwrite()) {
-               if (ninebit)
-                       writeser(((serdatshift >> 8) & 1) | 0xa8);
+       if (ninebit) {
+               if (!checkserwrite(2))
+                       return;
+               writeser(((serdatshift >> 8) & 1) | 0xa8);
                writeser(serdatshift_masked);
        } else {
-               // buffer full, try again later
-               sent = false;
+               if (currprefs.serial_crlf) {
+                       if (serdatshift_masked == 10 && serial_send_previous != 13) {
+                               if (!checkserwrite(2))
+                                       return;
+                               writeser(13);
+                       }
+               }
+               if (!checkserwrite(1))
+                       return;
+               writeser(serdatshift_masked);
+               serial_send_previous = serdatshift_masked;
        }
 #endif
-       if (sent) {
-               data_in_sershift = 2;
-       }
+       data_in_sershift = 2;
 #if SERIALDEBUG > 2
-               write_log(_T("SERIAL: send %04X (%c)\n"), serdatshift, dochar(serdatshift));
+       write_log(_T("SERIAL: send %04X (%c)\n"), serdatshift, dochar(serdatshift));
 #endif
 }
 
@@ -379,7 +417,6 @@ static void serdatcopy(void)
        serial_check_irq();
        checksend();
 
-
        if (seriallog) {
                gotlogwrite = true;
                write_log(_T("%c"), dochar(serdatshift_masked));
@@ -445,6 +482,7 @@ void serial_hsynchandler (void)
                        serial_check_irq();
                }
        }
+       serdatr_last_got++;
        if (serial_period_hsyncs == 0)
                return;
        serial_period_hsync_counter++;