]> sigrok.org Git - libsigrok.git/blob - src/hardware/beaglelogic/protocol.c
beaglelogic: Implement TCP protocol
[libsigrok.git] / src / hardware / beaglelogic / protocol.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2014 Kumar Abhishek <abhishek@theembeddedkitchen.net>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #ifdef _WIN32
25 #define _WIN32_WINNT 0x0501
26 #include <winsock2.h>
27 #include <ws2tcpip.h>
28 #else
29 #include <sys/socket.h>
30 #endif
31 #include <errno.h>
32 #include "protocol.h"
33 #include "beaglelogic.h"
34
35 /* Define data packet size independent of packet (bufunitsize bytes) size
36  * from the BeagleLogic kernel module */
37 #define PACKET_SIZE     (512 * 1024)
38
39 /* This implementation is zero copy from the libsigrok side.
40  * It does not copy any data, just passes a pointer from the mmap'ed
41  * kernel buffers appropriately. It is up to the application which is
42  * using libsigrok to decide how to deal with the data.
43  */
44 SR_PRIV int beaglelogic_native_receive_data(int fd, int revents, void *cb_data)
45 {
46         const struct sr_dev_inst *sdi;
47         struct dev_context *devc;
48         struct sr_datafeed_packet packet;
49         struct sr_datafeed_logic logic;
50
51         int trigger_offset;
52         int pre_trigger_samples;
53         uint32_t packetsize;
54         uint64_t bytes_remaining;
55
56         if (!(sdi = cb_data) || !(devc = sdi->priv))
57                 return TRUE;
58
59         packetsize = PACKET_SIZE;
60         logic.unitsize = SAMPLEUNIT_TO_BYTES(devc->sampleunit);
61
62         if (revents == G_IO_IN) {
63                 sr_info("In callback G_IO_IN, offset=%d", devc->offset);
64
65                 bytes_remaining = (devc->limit_samples * logic.unitsize) -
66                                 devc->bytes_read;
67
68                 /* Configure data packet */
69                 packet.type = SR_DF_LOGIC;
70                 packet.payload = &logic;
71                 logic.data = devc->sample_buf + devc->offset;
72                 logic.length = MIN(packetsize, bytes_remaining);
73
74                 if (devc->trigger_fired) {
75                         /* Send the incoming transfer to the session bus. */
76                         sr_session_send(sdi, &packet);
77                 } else {
78                         /* Check for trigger */
79                         trigger_offset = soft_trigger_logic_check(devc->stl,
80                                         logic.data, packetsize, &pre_trigger_samples);
81                         if (trigger_offset > -1) {
82                                 devc->bytes_read += pre_trigger_samples * logic.unitsize;
83                                 trigger_offset *= logic.unitsize;
84                                 logic.length = MIN(packetsize - trigger_offset,
85                                                 bytes_remaining);
86                                 logic.data += trigger_offset;
87
88                                 sr_session_send(sdi, &packet);
89
90                                 devc->trigger_fired = TRUE;
91                         }
92                 }
93
94                 /* Move the read pointer forward */
95                 lseek(fd, packetsize, SEEK_CUR);
96
97                 /* Update byte count and offset (roll over if needed) */
98                 devc->bytes_read += logic.length;
99                 if ((devc->offset += packetsize) >= devc->buffersize) {
100                         /* One shot capture, we abort and settle with less than
101                          * the required number of samples */
102                         if (devc->triggerflags)
103                                 devc->offset = 0;
104                         else
105                                 packetsize = 0;
106                 }
107         }
108
109         /* EOF Received or we have reached the limit */
110         if (devc->bytes_read >= devc->limit_samples * logic.unitsize ||
111                         packetsize == 0) {
112                 /* Send EOA Packet, stop polling */
113                 std_session_send_df_end(sdi);
114                 sr_session_source_remove_pollfd(sdi->session, &devc->pollfd);
115         }
116
117         return TRUE;
118 }
119
120 SR_PRIV int beaglelogic_tcp_receive_data(int fd, int revents, void *cb_data)
121 {
122         const struct sr_dev_inst *sdi;
123         struct dev_context *devc;
124         struct sr_datafeed_packet packet;
125         struct sr_datafeed_logic logic;
126
127         int len;
128         int pre_trigger_samples;
129         int trigger_offset;
130         uint32_t packetsize;
131         uint64_t bytes_remaining;
132
133         if (!(sdi = cb_data) || !(devc = sdi->priv))
134                 return TRUE;
135
136         packetsize = TCP_BUFFER_SIZE;
137         logic.unitsize = SAMPLEUNIT_TO_BYTES(devc->sampleunit);
138
139         if (revents == G_IO_IN) {
140                 sr_info("In callback G_IO_IN");
141
142                 len = recv(fd, devc->tcp_buffer, TCP_BUFFER_SIZE, 0);
143                 if (len < 0) {
144                         sr_err("Receive error: %s", g_strerror(errno));
145                         return SR_ERR;
146                 }
147
148                 packetsize = len;
149
150                 bytes_remaining = (devc->limit_samples * logic.unitsize) -
151                                 devc->bytes_read;
152
153                 /* Configure data packet */
154                 packet.type = SR_DF_LOGIC;
155                 packet.payload = &logic;
156                 logic.data = devc->tcp_buffer;
157                 logic.length = MIN(packetsize, bytes_remaining);
158
159                 if (devc->trigger_fired) {
160                         /* Send the incoming transfer to the session bus. */
161                         sr_session_send(sdi, &packet);
162                 } else {
163                         /* Check for trigger */
164                         trigger_offset = soft_trigger_logic_check(devc->stl,
165                                         logic.data, packetsize, &pre_trigger_samples);
166                         if (trigger_offset > -1) {
167                                 devc->bytes_read += pre_trigger_samples * logic.unitsize;
168                                 trigger_offset *= logic.unitsize;
169                                 logic.length = MIN(packetsize - trigger_offset,
170                                                 bytes_remaining);
171                                 logic.data += trigger_offset;
172
173                                 sr_session_send(sdi, &packet);
174
175                                 devc->trigger_fired = TRUE;
176                         }
177                 }
178
179                 /* Update byte count and offset (roll over if needed) */
180                 devc->bytes_read += logic.length;
181                 if ((devc->offset += packetsize) >= devc->buffersize) {
182                         /* One shot capture, we abort and settle with less than
183                          * the required number of samples */
184                         if (devc->triggerflags)
185                                 devc->offset = 0;
186                         else
187                                 packetsize = 0;
188                 }
189         }
190
191         /* EOF Received or we have reached the limit */
192         if (devc->bytes_read >= devc->limit_samples * logic.unitsize ||
193                         packetsize == 0) {
194                 /* Send EOA Packet, stop polling */
195                 std_session_send_df_end(sdi);
196                 devc->beaglelogic->stop(devc);
197                 sr_session_source_remove_pollfd(sdi->session, &devc->pollfd);
198         }
199
200         return TRUE;
201 }