X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=hardware%2Fbeaglelogic%2Fprotocol.c;fp=hardware%2Fbeaglelogic%2Fprotocol.c;h=1c01b64f758405955e5715d3b9a4a67998b51c9d;hb=ad9dbc1cdb4818954ee2954787feefc896b4c5c4;hp=f765a957ecc3a20dbc982872cf4dfa15b8233384;hpb=bb993797611dc5dfcba339238bdfcdad0af0c0aa;p=libsigrok.git diff --git a/hardware/beaglelogic/protocol.c b/hardware/beaglelogic/protocol.c index f765a957..1c01b64f 100644 --- a/hardware/beaglelogic/protocol.c +++ b/hardware/beaglelogic/protocol.c @@ -18,22 +18,94 @@ */ #include "protocol.h" +#include +#include +#include +#include +/* Define data packet size independent of packet (bufunitsize bytes) size + * from the BeagleLogic kernel module */ +#define PACKET_SIZE (512 * 1024) + +/* This implementation is zero copy from the libsigrok side. + * It does not copy any data, just passes a pointer from the mmap'ed + * 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) { const struct sr_dev_inst *sdi; struct dev_context *devc; + struct sr_datafeed_packet packet; + struct sr_datafeed_logic logic; - (void)fd; + int trigger_offset; + uint32_t packetsize; + uint64_t bytes_remaining; - if (!(sdi = cb_data)) + if (!(sdi = cb_data) || !(devc = sdi->priv)) return TRUE; - if (!(devc = sdi->priv)) - return TRUE; + packetsize = PACKET_SIZE; + logic.unitsize = SAMPLEUNIT_TO_BYTES(devc->sampleunit); if (revents == G_IO_IN) { - /* TODO */ + sr_info("In callback G_IO_IN, offset=%d", devc->offset); + + bytes_remaining = (devc->limit_samples * logic.unitsize) - + devc->bytes_read; + + /* Configure data packet */ + packet.type = SR_DF_LOGIC; + packet.payload = &logic; + logic.data = devc->sample_buf + devc->offset; + logic.length = MIN(packetsize, bytes_remaining); + + if (devc->trigger_fired) { + /* Send the incoming transfer to the session bus. */ + sr_session_send(devc->cb_data, &packet); + } else { + /* Check for trigger */ + trigger_offset = soft_trigger_logic_check(devc->stl, + logic.data, + packetsize); + + if (trigger_offset > -1) { + trigger_offset *= logic.unitsize; + logic.length = MIN(packetsize - trigger_offset, + bytes_remaining); + logic.data += trigger_offset; + + sr_session_send(devc->cb_data, &packet); + + devc->trigger_fired = TRUE; + } + } + + /* Move the read pointer forward */ + lseek(fd, packetsize, SEEK_CUR); + + /* 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 */ + packet.type = SR_DF_END; + packet.payload = NULL; + sr_session_send(devc->cb_data, &packet); + + sr_session_source_remove_pollfd(sdi->session, &devc->pollfd); } return TRUE;