]> sigrok.org Git - libsigrok.git/blobdiff - src/hardware/ipdbg-la/protocol.c
scpi-pps: don't break SCPI devices when scanning for HP-IB devices
[libsigrok.git] / src / hardware / ipdbg-la / protocol.c
index f67730ae69adefaf81da46b439e33e65c7fe492f..b125f1efc8502aec362ed20be82393398c6e3bb9 100644 (file)
 #define _WIN32_WINNT 0x0501
 #include <winsock2.h>
 #include <ws2tcpip.h>
-#endif
-
-#include <string.h>
-#include <unistd.h>
-
-#ifndef _WIN32
+#else
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <netdb.h>
+#include <sys/ioctl.h>
 #endif
-
+#include <string.h>
+#include <unistd.h>
 #include <errno.h>
 #include "protocol.h"
 
-#include <sys/ioctl.h>
-
 #define BUFFER_SIZE 4
 
 /* Top-level command opcodes */
 
 static gboolean data_available(struct ipdbg_la_tcp *tcp)
 {
-#ifdef __WIN32__
-       ioctlsocket(tcp->socket, FIONREAD, &bytes_available);
+#ifdef _WIN32
+       u_long bytes_available;
+       if (ioctlsocket(tcp->socket, FIONREAD, &bytes_available) != 0) {
 #else
-       int status;
-
-       if (ioctl(tcp->socket, FIONREAD, &status) < 0) {        // TIOCMGET
+       int bytes_available;
+       if (ioctl(tcp->socket, FIONREAD, &bytes_available) < 0) { /* TIOCMGET */
+#endif
                sr_err("FIONREAD failed: %s\n", g_strerror(errno));
                return FALSE;
        }
-
-       return (status < 1) ? FALSE : TRUE;
-#endif  // __WIN32__
+       return (bytes_available > 0);
 }
 
 SR_PRIV struct ipdbg_la_tcp *ipdbg_la_tcp_new(void)
@@ -148,6 +142,14 @@ SR_PRIV int ipdbg_la_tcp_close(struct ipdbg_la_tcp *tcp)
 {
        int ret = SR_OK;
 
+#ifdef _WIN32
+       if (shutdown(tcp->socket, SD_SEND) != SOCKET_ERROR) {
+               char recvbuf[16];
+               int recvbuflen = 16;
+               /* Receive until the peer closes the connection. */
+               while (recv(tcp->socket, recvbuf, recvbuflen, 0) > 0);
+       }
+#endif
        if (close(tcp->socket) < 0)
                ret = SR_ERR;
 
@@ -159,7 +161,7 @@ SR_PRIV int ipdbg_la_tcp_close(struct ipdbg_la_tcp *tcp)
 static int tcp_send(struct ipdbg_la_tcp *tcp, const uint8_t *buf, size_t len)
 {
        int out;
-       out = send(tcp->socket, buf, len, 0);
+       out = send(tcp->socket, (const char *)buf, len, 0);
 
        if (out < 0) {
                sr_err("Send error: %s", g_strerror(errno));
@@ -178,14 +180,16 @@ static int tcp_receive_blocking(struct ipdbg_la_tcp *tcp,
        int received = 0;
        int error_count = 0;
 
-       /* Timeout after 500ms of not receiving data */
-       while ((received < bufsize) && (error_count < 500)) {
-               if (ipdbg_la_tcp_receive(tcp, buf) > 0) {
-                       buf++;
-                       received++;
+       /* Timeout after 2s of not receiving data. */
+       /* Increase timeout in case lab is not just beside the office. */
+       while ((received < bufsize) && (error_count < 2000)) {
+               int recd = ipdbg_la_tcp_receive(tcp, buf, bufsize - received);
+               if (recd > 0) {
+                       buf += recd;
+                       received += recd;
                } else {
                        error_count++;
-                       g_usleep(1000);  /* Sleep for 1ms */
+                       g_usleep(1000);
                }
        }
 
@@ -193,24 +197,16 @@ static int tcp_receive_blocking(struct ipdbg_la_tcp *tcp,
 }
 
 SR_PRIV int ipdbg_la_tcp_receive(struct ipdbg_la_tcp *tcp,
-       uint8_t *buf)
+       uint8_t *buf, size_t bufsize)
 {
        int received = 0;
-
-       if (data_available(tcp)) {
-               while (received < 1) {
-                       int len = recv(tcp->socket, buf, 1, 0);
-
-                       if (len < 0) {
-                               sr_err("Receive error: %s", g_strerror(errno));
-                               return SR_ERR;
-                       } else
-                               received += len;
-               }
-
-               return received;
-       } else
+       if (data_available(tcp))
+               received = recv(tcp->socket, (char *)buf, bufsize, 0);
+       if (received < 0) {
+               sr_err("Receive error: %s", g_strerror(errno));
                return -1;
+       } else
+               return received;
 }
 
 SR_PRIV int ipdbg_la_convert_trigger(const struct sr_dev_inst *sdi)
@@ -313,14 +309,22 @@ SR_PRIV int ipdbg_la_receive_data(int fd, int revents, void *cb_data)
 
        if (devc->num_transfers <
                (devc->limit_samples_max * devc->data_width_bytes)) {
-               uint8_t byte;
-
-               if (ipdbg_la_tcp_receive(tcp, &byte) == 1) {
-                       if (devc->num_transfers <
-                               (devc->limit_samples * devc->data_width_bytes))
-                               devc->raw_sample_buf[devc->num_transfers] = byte;
-
-                       devc->num_transfers++;
+               const size_t bufsize = 1024;
+               uint8_t buffer[bufsize];
+
+               const int recd = ipdbg_la_tcp_receive(tcp, buffer, bufsize);
+               if ( recd > 0) {
+                       int num_move = (((devc->num_transfers + recd) <=
+                                                        (devc->limit_samples * devc->data_width_bytes))
+                       ?
+                               recd
+                       :
+                               (int)((devc->limit_samples * devc->data_width_bytes) -
+                                               devc->num_transfers));
+                       if ( num_move > 0 )
+                               memcpy(&(devc->raw_sample_buf[devc->num_transfers]),
+                                               buffer, num_move);
+                       devc->num_transfers += recd;
                }
        } else {
                if (devc->delay_value > 0) {
@@ -334,8 +338,7 @@ SR_PRIV int ipdbg_la_receive_data(int fd, int revents, void *cb_data)
                }
 
                /* Send the trigger. */
-               packet.type = SR_DF_TRIGGER;
-               sr_session_send(cb_data, &packet);
+               std_session_send_df_trigger(cb_data);
 
                /* Send post-trigger samples. */
                packet.type = SR_DF_LOGIC;
@@ -382,7 +385,7 @@ static int send_escaping(struct ipdbg_la_tcp *tcp, uint8_t *data_to_send,
 SR_PRIV int ipdbg_la_send_delay(struct dev_context *devc,
        struct ipdbg_la_tcp *tcp)
 {
-       devc->delay_value = (devc->limit_samples / 100.0) * devc->capture_ratio;
+       devc->delay_value = ((devc->limit_samples - 1) / 100.0) * devc->capture_ratio;
 
        uint8_t buf;
        buf = CMD_CFG_LA;