]> sigrok.org Git - libsigrok.git/blobdiff - src/hardware/beaglelogic/protocol.c
beaglelogic: Implement TCP protocol
[libsigrok.git] / src / hardware / beaglelogic / protocol.c
index 8f3ce26593175b50aff04570dc481a633684071b..2787b9bac9ef56f7c043ab2974a085d45fc63819 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#ifdef _WIN32
+#define _WIN32_WINNT 0x0501
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <sys/socket.h>
+#endif
+#include <errno.h>
 #include "protocol.h"
+#include "beaglelogic.h"
 
 /* Define data packet size independent of packet (bufunitsize bytes) size
  * from the BeagleLogic kernel module */
@@ -32,7 +41,7 @@
  * kernel buffers appropriately. It is up to the application which is
  * using libsigrok to decide how to deal with the data.
  */
-SR_PRIV int beaglelogic_receive_data(int fd, int revents, void *cb_data)
+SR_PRIV int beaglelogic_native_receive_data(int fd, int revents, void *cb_data)
 {
        const struct sr_dev_inst *sdi;
        struct dev_context *devc;
@@ -107,3 +116,86 @@ SR_PRIV int beaglelogic_receive_data(int fd, int revents, void *cb_data)
 
        return TRUE;
 }
+
+SR_PRIV int beaglelogic_tcp_receive_data(int fd, int revents, void *cb_data)
+{
+       const struct sr_dev_inst *sdi;
+       struct dev_context *devc;
+       struct sr_datafeed_packet packet;
+       struct sr_datafeed_logic logic;
+
+       int len;
+       int pre_trigger_samples;
+       int trigger_offset;
+       uint32_t packetsize;
+       uint64_t bytes_remaining;
+
+       if (!(sdi = cb_data) || !(devc = sdi->priv))
+               return TRUE;
+
+       packetsize = TCP_BUFFER_SIZE;
+       logic.unitsize = SAMPLEUNIT_TO_BYTES(devc->sampleunit);
+
+       if (revents == G_IO_IN) {
+               sr_info("In callback G_IO_IN");
+
+               len = recv(fd, devc->tcp_buffer, TCP_BUFFER_SIZE, 0);
+               if (len < 0) {
+                       sr_err("Receive error: %s", g_strerror(errno));
+                       return SR_ERR;
+               }
+
+               packetsize = len;
+
+               bytes_remaining = (devc->limit_samples * logic.unitsize) -
+                               devc->bytes_read;
+
+               /* Configure data packet */
+               packet.type = SR_DF_LOGIC;
+               packet.payload = &logic;
+               logic.data = devc->tcp_buffer;
+               logic.length = MIN(packetsize, bytes_remaining);
+
+               if (devc->trigger_fired) {
+                       /* Send the incoming transfer to the session bus. */
+                       sr_session_send(sdi, &packet);
+               } else {
+                       /* Check for trigger */
+                       trigger_offset = soft_trigger_logic_check(devc->stl,
+                                       logic.data, packetsize, &pre_trigger_samples);
+                       if (trigger_offset > -1) {
+                               devc->bytes_read += pre_trigger_samples * logic.unitsize;
+                               trigger_offset *= logic.unitsize;
+                               logic.length = MIN(packetsize - trigger_offset,
+                                               bytes_remaining);
+                               logic.data += trigger_offset;
+
+                               sr_session_send(sdi, &packet);
+
+                               devc->trigger_fired = TRUE;
+                       }
+               }
+
+               /* Update byte count and offset (roll over if needed) */
+               devc->bytes_read += logic.length;
+               if ((devc->offset += packetsize) >= devc->buffersize) {
+                       /* One shot capture, we abort and settle with less than
+                        * the required number of samples */
+                       if (devc->triggerflags)
+                               devc->offset = 0;
+                       else
+                               packetsize = 0;
+               }
+       }
+
+       /* EOF Received or we have reached the limit */
+       if (devc->bytes_read >= devc->limit_samples * logic.unitsize ||
+                       packetsize == 0) {
+               /* Send EOA Packet, stop polling */
+               std_session_send_df_end(sdi);
+               devc->beaglelogic->stop(devc);
+               sr_session_source_remove_pollfd(sdi->session, &devc->pollfd);
+       }
+
+       return TRUE;
+}