]> sigrok.org Git - libsigrok.git/blob - src/hardware/hantek-4032l/protocol.c
hantek-4032l: Add option to abort acquisition.
[libsigrok.git] / src / hardware / hantek-4032l / protocol.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2016 Andreas Zschunke <andreas.zschunke@gmx.net>
5  * Copyright (C) 2017 Andrej Valek <andy@skyrain.eu>
6  * Copyright (C) 2017 Uwe Hermann <uwe@hermann-uwe.de>
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <config.h>
23 #include "protocol.h"
24
25 #define H4032L_USB_TIMEOUT 500
26
27 enum h4032l_cmd {
28         CMD_RESET = 0x00b3, /* Also arms the logic analyzer. */
29         CMD_CONFIGURE = 0x2b1a,
30         CMD_STATUS = 0x4b3a,
31         CMD_GET = 0x6b5a
32 };
33
34 struct h4032l_status_packet {
35         uint32_t magic;
36         uint32_t values;
37         uint32_t status;
38 };
39
40 static void finish_acquisition(struct sr_dev_inst *sdi)
41 {
42         struct drv_context *drvc = sdi->driver->context;
43
44         std_session_send_df_end(sdi);
45         usb_source_remove(sdi->session, drvc->sr_ctx);
46 }
47
48 static void free_transfer(struct libusb_transfer *transfer)
49 {
50         struct sr_dev_inst *sdi = transfer->user_data;
51         struct dev_context *devc = sdi->priv;
52
53         transfer->buffer = NULL;
54         libusb_free_transfer(transfer);
55         devc->usb_transfer = NULL;
56
57         finish_acquisition(sdi);
58 }
59
60 SR_PRIV int h4032l_receive_data(int fd, int revents, void *cb_data)
61 {
62         struct timeval tv;
63         struct drv_context *drvc;
64
65         (void)fd;
66         (void)revents;
67
68         drvc = (struct drv_context *)cb_data;
69
70         tv.tv_sec = tv.tv_usec = 0;
71         libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &tv);
72
73         return TRUE;
74 }
75
76 void LIBUSB_CALL h4032l_usb_callback(struct libusb_transfer *transfer)
77 {
78         const struct sr_dev_inst *sdi = transfer->user_data;
79         struct dev_context *devc = sdi->priv;
80         struct drv_context *drvc = sdi->driver->context;
81         struct sr_usb_dev_inst *usb = sdi->conn;
82         gboolean cmd = FALSE;
83         uint32_t max_samples = 512 / sizeof(uint32_t);
84         uint32_t *buffer;
85         struct h4032l_status_packet *status;
86         struct sr_datafeed_packet packet;
87         struct sr_datafeed_logic logic;
88         uint32_t number_samples;
89         int ret;
90
91         /*
92          * If acquisition has already ended, just free any queued up
93          * transfers that come in.
94          */
95         if (devc->acq_aborted) {
96                 free_transfer(transfer);
97                 return;
98         }
99
100         if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
101                 sr_dbg("%s error: %d.", __func__, transfer->status);
102
103         buffer = (uint32_t *)transfer->buffer;
104
105         switch (devc->status) {
106         case H4032L_STATUS_IDLE:
107                 sr_err("USB callback called in idle.");
108                 break;
109         case H4032L_STATUS_CMD_CONFIGURE:
110                 /* Select status request as next. */
111                 cmd = TRUE;
112                 devc->cmd_pkt.cmd = CMD_STATUS;
113                 devc->status = H4032L_STATUS_CMD_STATUS;
114                 break;
115         case H4032L_STATUS_CMD_STATUS:
116                 /* Select status request as next. */
117                 devc->status = H4032L_STATUS_RESPONSE_STATUS;
118                 break;
119         case H4032L_STATUS_RESPONSE_STATUS:
120                 /*
121                  * Check magic and if status is complete, then select
122                  * First Transfer as next.
123                  */
124                 status = (struct h4032l_status_packet *)transfer->buffer;
125                 if (status->magic != H4032L_STATUS_PACKET_MAGIC) {
126                         devc->status = H4032L_STATUS_RESPONSE_STATUS;
127                 } else if (status->status == 2) {
128                         devc->status = H4032L_STATUS_RESPONSE_STATUS_CONTINUE;
129                 } else {
130                         devc->status = H4032L_STATUS_RESPONSE_STATUS_RETRY;
131                 }
132                 break;
133         case H4032L_STATUS_RESPONSE_STATUS_RETRY:
134                 devc->status = H4032L_STATUS_CMD_STATUS;
135                 devc->cmd_pkt.cmd = CMD_STATUS;
136                 cmd = TRUE;
137                 break;
138         case H4032L_STATUS_RESPONSE_STATUS_CONTINUE:
139                 devc->status = H4032L_STATUS_CMD_GET;
140                 devc->cmd_pkt.cmd = CMD_GET;
141                 cmd = TRUE;
142                 break;
143         case H4032L_STATUS_CMD_GET:
144                 devc->status = H4032L_STATUS_FIRST_TRANSFER;
145                 break;
146         case H4032L_STATUS_FIRST_TRANSFER:
147                 /* Drop packets until H4032L_START_PACKET_MAGIC. */
148                 if (buffer[0] != H4032L_START_PACKET_MAGIC) {
149                         sr_dbg("Mismatch magic number of start poll.");
150                         break;
151                 }
152                 devc->status = H4032L_STATUS_TRANSFER;
153                 max_samples--;
154                 buffer++;
155                 /* Fallthrough. */
156         case H4032L_STATUS_TRANSFER:
157                 number_samples = (devc->remaining_samples < max_samples) ? devc->remaining_samples : max_samples;
158                 devc->remaining_samples -= number_samples;
159                 packet.type = SR_DF_LOGIC;
160                 packet.payload = &logic;
161                 logic.length = number_samples * sizeof(uint32_t);
162                 logic.unitsize = sizeof(uint32_t);
163                 logic.data = buffer;
164                 sr_session_send(sdi, &packet);
165                 sr_dbg("Remaining: %d %08X %08X.", devc->remaining_samples,
166                         buffer[0], buffer[1]);
167                 if (devc->remaining_samples == 0) {
168                         std_session_send_df_end(sdi);
169                         usb_source_remove(sdi->session, drvc->sr_ctx);
170                         devc->status = H4032L_STATUS_IDLE;
171                         if (buffer[number_samples] != H4032L_END_PACKET_MAGIC)
172                                 sr_err("Mismatch magic number of end poll.");
173                 }
174                 break;
175         }
176
177         if (devc->status != H4032L_STATUS_IDLE) {
178                 if (cmd) {
179                         /* Setup new USB cmd packet, reuse transfer object. */
180                         sr_dbg("New command: %d.", devc->status);
181                         libusb_fill_bulk_transfer(transfer, usb->devhdl,
182                                 2 | LIBUSB_ENDPOINT_OUT,
183                                 (unsigned char *)&devc->cmd_pkt,
184                                 sizeof(struct h4032l_cmd_pkt),
185                                 h4032l_usb_callback, (void *)sdi,
186                                 H4032L_USB_TIMEOUT);
187                 } else {
188                         /* Setup new USB poll packet, reuse transfer object. */
189                         sr_dbg("Poll: %d.", devc->status);
190                         libusb_fill_bulk_transfer(transfer, usb->devhdl,
191                                 6 | LIBUSB_ENDPOINT_IN,
192                                 devc->buffer, ARRAY_SIZE(devc->buffer),
193                                 h4032l_usb_callback,
194                                 (void *)sdi, H4032L_USB_TIMEOUT);
195                 }
196                 /* Send prepared USB packet. */
197                 if ((ret = libusb_submit_transfer(transfer)) != 0) {
198                         sr_err("Failed to submit transfer: %s.",
199                                libusb_error_name(ret));
200                         devc->status = H4032L_STATUS_IDLE;
201                 }
202         } else {
203                 sr_dbg("Now idle.");
204         }
205
206         if (devc->status == H4032L_STATUS_IDLE)
207                 free_transfer(transfer);
208 }
209
210 uint16_t h4032l_voltage2pwm(double voltage)
211 {
212         /*
213          * word PwmA - channel A Vref PWM value, pseudocode:
214          * -6V < ThresholdVoltage < +6V
215          * Vref = 1.8 - ThresholdVoltage
216          * if Vref > 10.0
217          *      Vref = 10.0
218          * if Vref < -5.0
219          *      Vref = -5.0
220          * pwm = ToInt((Vref + 5.0) / 15.0 * 4096.0)
221          * if pwm > 4095
222          *      pwm = 4095
223          */
224         voltage = 1.8 - voltage;
225         if (voltage > 10.0)
226                 voltage = 10.0;
227         else if (voltage < -5.0)
228                 voltage = -5.0;
229
230         return (uint16_t) ((voltage + 5.0) * (4096.0 / 15.0));
231 }
232
233 SR_PRIV int h4032l_start(const struct sr_dev_inst *sdi)
234 {
235         struct dev_context *devc = sdi->priv;
236         struct sr_usb_dev_inst *usb = sdi->conn;
237         struct libusb_transfer *transfer;
238         unsigned char buffer[] = {0x0f, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
239         int ret;
240
241         /* Send reset command to arm the logic analyzer. */
242         if ((ret = libusb_control_transfer(usb->devhdl,
243                 LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT, CMD_RESET,
244                 0x00, 0x00, buffer, ARRAY_SIZE(buffer), H4032L_USB_TIMEOUT)) < 0) {
245                 sr_err("Failed to send vendor request %s.", libusb_error_name(ret));
246                 return SR_ERR;
247         }
248
249         /* Wait for reset vendor request. */
250         g_usleep(20 * 1000);
251
252         /* Send configure command. */
253         devc->cmd_pkt.cmd = CMD_CONFIGURE;
254         devc->status = H4032L_STATUS_CMD_CONFIGURE;
255         devc->remaining_samples = devc->cmd_pkt.sample_size;
256
257         transfer = libusb_alloc_transfer(0);
258
259         libusb_fill_bulk_transfer(transfer, usb->devhdl,
260                 2 | LIBUSB_ENDPOINT_OUT, (unsigned char *)&devc->cmd_pkt,
261                 sizeof(struct h4032l_cmd_pkt), h4032l_usb_callback,
262                 (void *)sdi, H4032L_USB_TIMEOUT);
263
264         if ((ret = libusb_submit_transfer(transfer)) != 0) {
265                 sr_err("Failed to submit transfer: %s.", libusb_error_name(ret));
266                 libusb_free_transfer(transfer);
267                 return SR_ERR;
268         }
269
270         std_session_send_df_header(sdi);
271
272         return SR_OK;
273 }
274
275 SR_PRIV int h4032l_dev_open(struct sr_dev_inst *sdi)
276 {
277         struct drv_context *drvc = sdi->driver->context;
278         struct sr_usb_dev_inst *usb = sdi->conn;
279         struct libusb_device_descriptor des;
280         libusb_device **devlist;
281         int ret = SR_ERR, i, device_count;
282         char connection_id[64];
283
284         device_count = libusb_get_device_list(drvc->sr_ctx->libusb_ctx, &devlist);
285         if (device_count < 0) {
286                 sr_err("Failed to get device list: %s.",
287                        libusb_error_name(device_count));
288                 return SR_ERR;
289         }
290
291         for (i = 0; i < device_count; i++) {
292                 libusb_get_device_descriptor(devlist[i], &des);
293
294                 if (des.idVendor != H4032L_USB_VENDOR ||
295                     des.idProduct != H4032L_USB_PRODUCT)
296                         continue;
297
298                 if ((sdi->status == SR_ST_INITIALIZING) ||
299                     (sdi->status == SR_ST_INACTIVE)) {
300                         /* Check device by its physical USB bus/port address. */
301                         usb_get_port_path(devlist[i], connection_id,
302                                           sizeof(connection_id));
303                         if (strcmp(sdi->connection_id, connection_id))
304                                 /* This is not the one. */
305                                 continue;
306                 }
307
308                 if (!(ret = libusb_open(devlist[i], &usb->devhdl))) {
309                         if (usb->address == 0xff)
310                                 /*
311                                  * First time we touch this device after FW
312                                  * upload, so we don't know the address yet.
313                                  */
314                                 usb->address =
315                                     libusb_get_device_address(devlist[i]);
316                 } else {
317                         sr_err("Failed to open device: %s.",
318                                libusb_error_name(ret));
319                         ret = SR_ERR;
320                         break;
321                 }
322
323                 ret = SR_OK;
324                 break;
325         }
326
327         libusb_free_device_list(devlist, 1);
328         return ret;
329 }