]> sigrok.org Git - libsigrok.git/blob - src/hardware/chromium-twinkie/protocol.c
e9d334d68457ac55ccd13ab838c05906fce9f455
[libsigrok.git] / src / hardware / chromium-twinkie / protocol.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright 2014 Google, Inc
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 2 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 <stdint.h>
22 #include <string.h>
23 #include <libusb.h>
24 #include <stdio.h>
25 #include <errno.h>
26 #include <math.h>
27 #include <libsigrok/libsigrok.h>
28 #include "libsigrok-internal.h"
29 #include "protocol.h"
30
31 SR_PRIV int twinkie_start_acquisition(const struct sr_dev_inst *sdi)
32 {
33         (void)sdi;
34
35         return SR_OK;
36 }
37
38 SR_PRIV int twinkie_init_device(const struct sr_dev_inst *sdi)
39 {
40         (void)sdi;
41
42         return SR_OK;
43 }
44
45 static void finish_acquisition(struct sr_dev_inst *sdi)
46 {
47         struct sr_datafeed_packet packet;
48         struct dev_context *devc = sdi->priv;
49
50         /* Terminate session. */
51         packet.type = SR_DF_END;
52         sr_session_send(sdi, &packet);
53
54         /* Remove fds from polling. */
55         usb_source_remove(sdi->session, devc->ctx);
56
57         devc->num_transfers = 0;
58         g_free(devc->transfers);
59         g_free(devc->convbuffer);
60 }
61
62 static void free_transfer(struct libusb_transfer *transfer)
63 {
64         struct sr_dev_inst *sdi;
65         struct dev_context *devc;
66         unsigned int i;
67
68         sdi = transfer->user_data;
69         devc = sdi->priv;
70
71         g_free(transfer->buffer);
72         transfer->buffer = NULL;
73         libusb_free_transfer(transfer);
74
75         for (i = 0; i < devc->num_transfers; i++) {
76                 if (devc->transfers[i] == transfer) {
77                         devc->transfers[i] = NULL;
78                         break;
79                 }
80         }
81
82         devc->submitted_transfers--;
83         if (devc->submitted_transfers == 0)
84                 finish_acquisition(sdi);
85 }
86
87 static void export_samples(const struct sr_dev_inst *sdi, size_t cnt)
88 {
89         struct sr_datafeed_packet packet;
90         struct sr_datafeed_logic logic;
91         struct dev_context *devc = sdi->priv;
92
93         /* export the received data */
94         packet.type = SR_DF_LOGIC;
95         packet.payload = &logic;
96         if (devc->limit_samples &&
97             cnt > devc->limit_samples - devc->sent_samples)
98                 cnt = devc->limit_samples - devc->sent_samples;
99         logic.length = cnt;
100         logic.unitsize = 1;
101         logic.data = devc->convbuffer;
102         sr_session_send(sdi, &packet);
103         devc->sent_samples += cnt;
104 }
105
106 static void expand_sample_data(const struct sr_dev_inst *sdi,
107                                const uint8_t *src, size_t srccnt)
108 {
109         struct dev_context *devc = sdi->priv;
110         int i, f;
111         size_t b;
112         size_t rdy_samples, left_samples;
113         int frames = srccnt / 64;
114
115         for (f = 0; f < frames; f++) {
116                 int ch = (src[1] >> 4) & 3; /* samples channel number */
117                 int bit = 1 << ch; /* channel bit mask */
118                 struct cc_context *cc = devc->cc + ch;
119                 uint8_t *dest = devc->convbuffer + cc->idx;
120
121                 if (ch >= 2) /* only acquires CCx channels */
122                         continue;
123
124                 /* TODO: check timestamp, overflow, sequence number */
125
126                 /* skip header, go to edges data */
127                 src+=4;
128                 for (i = 0; i < 60; i++,src++)
129                         if (*src == cc->prev_src) {
130                                 cc->rollbacks++;
131                         } else {
132                                 uint8_t diff = *src - cc->prev_src;
133                                 int fixup = cc->rollbacks && (((int)*src < (int)cc->prev_src) || (*src == 0xff));
134                                 size_t total = (fixup ? cc->rollbacks - 1 : cc->rollbacks) * 256 + diff;
135
136                                 if (total + cc->idx > devc->convbuffer_size) {
137                                         sr_warn("overflow %d+%zd/%zd\n",
138                                                 cc->idx, total,
139                                                 devc->convbuffer_size);
140                                         /* reset current decoding */
141                                         cc->rollbacks = 0;
142                                         break;
143                                 }
144
145                                 /* insert bits in the buffer */
146                                 if (cc->level)
147                                         for (b = 0 ; b < total ; b++, dest++)
148                                                 *dest |= bit;
149                                 else
150                                         dest += total;
151                                 cc->idx += total;
152
153                                 /* flip level on the next edge */
154                                 cc->level = ~cc->level;
155
156                                 cc->rollbacks = 0;
157                                 cc->prev_src = *src;
158                         }
159                 /* expand repeated rollbacks */
160                 if (cc->rollbacks > 1) {
161                         size_t total = 256 * (cc->rollbacks - 1);
162                         if (total + cc->idx > devc->convbuffer_size) {
163                                 sr_warn("overflow %d+%zd/%zd\n",
164                                         cc->idx, total, devc->convbuffer_size);
165                                 /* reset current decoding */
166                                 total = 0;
167                         }
168                         /* insert bits in the buffer */
169                         if (cc->level)
170                                 for (b = 0 ; b < total ; b++, dest++)
171                                         *dest |= bit ;
172                         cc->idx += total;
173                         cc->rollbacks = 1;
174                 }
175         }
176
177         /* samples ready to be pushed (with both channels) */
178         rdy_samples = MIN(devc->cc[0].idx, devc->cc[1].idx);
179         left_samples = MAX(devc->cc[0].idx, devc->cc[1].idx) - rdy_samples;
180         /* skip empty transfer */
181         if (rdy_samples == 0)
182                 return;
183
184         export_samples(sdi, rdy_samples);
185
186         /* clean up what we have sent */
187         memmove(devc->convbuffer, devc->convbuffer + rdy_samples, left_samples);
188         memset(devc->convbuffer + left_samples, 0, rdy_samples);
189         devc->cc[0].idx -= rdy_samples;
190         devc->cc[1].idx -= rdy_samples;
191 }
192
193 SR_PRIV void LIBUSB_CALL twinkie_receive_transfer(struct libusb_transfer *transfer)
194 {
195         gboolean packet_has_error = FALSE;
196         struct sr_dev_inst *sdi;
197         struct dev_context *devc;
198
199         sdi = transfer->user_data;
200         devc = sdi->priv;
201
202         /*
203          * If acquisition has already ended, just free any queued up
204          * transfer that come in.
205          */
206         if (devc->sent_samples < 0) {
207                 free_transfer(transfer);
208                 return;
209         }
210
211         if (transfer->status || transfer->actual_length)
212                 sr_info("receive_transfer(): status %d received %d bytes.",
213                         transfer->status, transfer->actual_length);
214
215         switch (transfer->status) {
216         case LIBUSB_TRANSFER_NO_DEVICE:
217                 devc->sent_samples = -2;
218                 free_transfer(transfer);
219                 return;
220         case LIBUSB_TRANSFER_COMPLETED:
221         case LIBUSB_TRANSFER_TIMED_OUT: /* We may have received some data though. */
222                 break;
223         default:
224                 packet_has_error = TRUE;
225                 break;
226         }
227
228         if (transfer->actual_length % 64) {
229                 sr_err("Bad USB packet size.");
230                 packet_has_error = TRUE;
231         }
232
233         if (transfer->actual_length == 0 || packet_has_error)
234                 goto resubmit;
235
236         /* decode received edges */
237         expand_sample_data(sdi, transfer->buffer, transfer->actual_length);
238
239         if (devc->limit_samples &&
240                         (uint64_t)devc->sent_samples >= devc->limit_samples) {
241                 devc->sent_samples = -2;
242                 free_transfer(transfer);
243                 return;
244         }
245 resubmit:
246         if (libusb_submit_transfer(transfer) != LIBUSB_SUCCESS)
247                 free_transfer(transfer);
248 }