]> sigrok.org Git - libsigrok.git/blame - hardware/lascar-el-usb/protocol.c
usb: strip overly verbose debugging
[libsigrok.git] / hardware / lascar-el-usb / protocol.c
CommitLineData
46697e38
BV
1/*
2 * This file is part of the libsigrok project.
3 *
4 * Copyright (C) 2012 Bert Vermeulen <bert@biot.com>
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 <stdlib.h>
851d5b22
BV
21#include <sys/time.h>
22#include <string.h>
46697e38
BV
23#include <glib.h>
24#include "libsigrok.h"
25#include "libsigrok-internal.h"
26#include "protocol.h"
27
851d5b22
BV
28#define LASCAR_VENDOR "Lascar"
29#define LASCAR_INTERFACE 0
30#define LASCAR_EP_IN 0x82
31#define LASCAR_EP_OUT 2
32/* Max 100ms for a device to positively identify. */
33#define SCAN_TIMEOUT 100000
34
35extern struct sr_dev_driver lascar_el_usb_driver_info;
36static struct sr_dev_driver *di = &lascar_el_usb_driver_info;
37
38static const struct elusb_profile profiles[] = {
39 { 1, "EL-USB-1", LOG_UNSUPPORTED },
40 { 2, "EL-USB-1", LOG_UNSUPPORTED },
41 { 3, "EL-USB-2", LOG_TEMP_RH },
42 { 4, "EL-USB-3", LOG_UNSUPPORTED },
43 { 5, "EL-USB-4", LOG_UNSUPPORTED },
44 { 6, "EL-USB-3", LOG_UNSUPPORTED },
45 { 7, "EL-USB-4", LOG_UNSUPPORTED },
46 { 8, "EL-USB-LITE", LOG_UNSUPPORTED },
47 { 9, "EL-USB-CO", LOG_CO },
48 { 10, "EL-USB-TC", LOG_UNSUPPORTED },
49 { 11, "EL-USB-CO300", LOG_UNSUPPORTED },
50 { 12, "EL-USB-2-LCD", LOG_UNSUPPORTED },
51 { 13, "EL-USB-2+", LOG_UNSUPPORTED },
52 { 14, "EL-USB-1-PRO", LOG_UNSUPPORTED },
53 { 15, "EL-USB-TC-LCD", LOG_UNSUPPORTED },
54 { 16, "EL-USB-2-LCD+", LOG_UNSUPPORTED },
55 { 17, "EL-USB-5", LOG_UNSUPPORTED },
56 { 18, "EL-USB-1-RCG", LOG_UNSUPPORTED },
57 { 19, "EL-USB-1-LCD", LOG_UNSUPPORTED },
58 { 20, "EL-OEM-3", LOG_UNSUPPORTED },
59 { 21, "EL-USB-1-LCD", LOG_UNSUPPORTED },
60 { 0, NULL, 0 }
61};
62
63
64static void scan_xfer(struct libusb_transfer *xfer)
65{
66
67 xfer->user_data = GINT_TO_POINTER(1);
68
69}
70
71static struct sr_dev_inst *lascar_identify(libusb_device_handle *dev_hdl)
72{
73 struct drv_context *drvc;
74 const struct elusb_profile *profile;
75 struct sr_dev_inst *sdi;
76 struct libusb_transfer *xfer_in, *xfer_out;
77 struct timeval tv;
78 int64_t start;
79 int modelid, buflen, i;
80 unsigned char cmd[3], buf[256];
81 char firmware[5];
82
83 drvc = di->priv;
84 modelid = 0;
85
86 /* Some of these fail, but it needs doing -- some sort of mode
87 * setup for the SILabs F32x. */
88 libusb_control_transfer(dev_hdl, LIBUSB_REQUEST_TYPE_VENDOR,
89 0x00, 0xffff, 0x00, buf, 0, 50);
90 libusb_control_transfer(dev_hdl, LIBUSB_REQUEST_TYPE_VENDOR,
91 0x02, 0x0002, 0x00, buf, 0, 50);
92 libusb_control_transfer(dev_hdl, LIBUSB_REQUEST_TYPE_VENDOR,
93 0x02, 0x0001, 0x00, buf, 0, 50);
94
95 if (!(xfer_in = libusb_alloc_transfer(0)) ||
96 !(xfer_out = libusb_alloc_transfer(0)))
97 return 0;
98
99 /* Flush anything the F321 still has queued. */
100 while (libusb_bulk_transfer(dev_hdl, LASCAR_EP_IN, buf, 256, &buflen,
101 5) == 0 && buflen > 0)
102 ;
103
104 /* Keep a read request waiting in the wings, ready to pounce
105 * the moment the device sends something. */
106 libusb_fill_bulk_transfer(xfer_in, dev_hdl, LASCAR_EP_IN,
107 buf, 256, scan_xfer, 0, 10000);
108 if (libusb_submit_transfer(xfer_in) != 0)
109 goto cleanup;
110
111 /* Request device configuration structure. */
112 cmd[0] = 0x00;
113 cmd[1] = 0xff;
114 cmd[2] = 0xff;
115 libusb_fill_bulk_transfer(xfer_out, dev_hdl, LASCAR_EP_OUT,
116 cmd, 3, scan_xfer, 0, 100);
117 if (libusb_submit_transfer(xfer_out) != 0)
118 goto cleanup;
119
120 tv.tv_sec = 0;
121 tv.tv_usec = 0;
122 start = g_get_monotonic_time();
123 while (!xfer_in->user_data || !xfer_out->user_data) {
124 if (g_get_monotonic_time() - start > SCAN_TIMEOUT) {
125 start = 0;
126 break;
127 }
128 g_usleep(5000);
129 libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &tv);
130 }
131 if (!start) {
132 sr_dbg("no response");
133 goto cleanup;
134 }
135 if (xfer_in->actual_length != 3) {
136 sr_dbg("expected 3-byte header, got %d bytes", xfer_in->actual_length);
137 goto cleanup;
138 }
139
140 /* Got configuration structure header. */
141 sr_spew("response to config request: 0x%.2x 0x%.2x 0x%.2x ",
142 buf[0], buf[1], buf[2]);
143 buflen = buf[1] | (buf[2] << 8);
144 if (buf[0] != 0x02 || buflen > 256) {
145 sr_dbg("Invalid response to config request: "
146 "0x%.2x 0x%.2x 0x%.2x ", buf[0], buf[1], buf[2]);
147 libusb_close(dev_hdl);
148 goto cleanup;
149 }
150
151 /* Get configuration structure. */
152 xfer_in->length = buflen;
153 xfer_in->user_data = 0;
154 if (libusb_submit_transfer(xfer_in) != 0)
155 goto cleanup;
156 while (!xfer_in->user_data) {
157 if (g_get_monotonic_time() - start > SCAN_TIMEOUT) {
158 start = 0;
159 break;
160 }
161 g_usleep(5000);
162 libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &tv);
163 }
164 if (!start) {
165 sr_dbg("Timeout waiting for configuration structure.");
166 goto cleanup;
167 }
168 if (xfer_in->actual_length != buflen) {
169 sr_dbg("expected %d-byte structure, got %d bytes", buflen,
170 xfer_in->actual_length);
171 goto cleanup;
172 }
173 modelid = buf[0];
174
175cleanup:
176 if (!xfer_in->user_data || !xfer_in->user_data) {
177 if (!xfer_in->user_data)
178 libusb_cancel_transfer(xfer_in);
179 if (!xfer_out->user_data)
180 libusb_cancel_transfer(xfer_out);
181 start = g_get_monotonic_time();
182 while (!xfer_in->user_data || !xfer_out->user_data) {
183 if (g_get_monotonic_time() - start > 10000)
184 break;
185 g_usleep(1000);
186 libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &tv);
187 }
188 }
189 libusb_free_transfer(xfer_in);
190 libusb_free_transfer(xfer_out);
191
192 sdi = NULL;
193 if (modelid) {
194 profile = NULL;
195 for (i = 0; profiles[i].modelid; i++) {
196 if (profiles[i].modelid == modelid) {
197 profile = &profiles[i];
198 break;
199 }
200 }
201 if (!profile) {
202 sr_dbg("unknown EL-USB modelid %d", modelid);
203 return NULL;
204 }
205
206 i = buf[52] | (buf[53] << 8);
207 memcpy(firmware, buf + 0x30, 4);
208 firmware[4] = '\0';
209 sr_dbg("found %s with firmware version %s serial %d",
210 profile->modelname, firmware, i);
211
212 if (profile->logformat == LOG_UNSUPPORTED) {
213 sr_dbg("unsupported EL-USB logformat for %s", profile->modelname);
214 return NULL;
215 }
216
217 if (!(sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, LASCAR_VENDOR,
218 profile->modelname, firmware)))
219 return NULL;
220 sdi->driver = di;
221 }
222
223 return sdi;
224}
225
226SR_PRIV struct sr_dev_inst *lascar_scan(int bus, int address)
227{
228 struct drv_context *drvc;
229 struct sr_dev_inst *sdi;
230 struct libusb_device **devlist;
231 struct libusb_device_descriptor des;
232 libusb_device_handle *dev_hdl;
233 int ret, i;
234
235 drvc = di->priv;
236 sdi = NULL;
237
238 libusb_get_device_list(drvc->sr_ctx->libusb_ctx, &devlist);
239 for (i = 0; devlist[i]; i++) {
240 if ((ret = libusb_get_device_descriptor(devlist[i], &des))) {
241 sr_err("Failed to get device descriptor: %d.", ret);
242 continue;
243 }
244
245 if (libusb_get_bus_number(devlist[i]) != bus ||
246 libusb_get_device_address(devlist[i]) != address)
247 continue;
248
249 if ((ret = libusb_open(devlist[i], &dev_hdl)) != 0) {
250 sr_dbg("failed to open device for scan: %s",
251 libusb_error_name(ret));
252 continue;
253 }
254
255 sdi = lascar_identify(dev_hdl);
256 libusb_close(dev_hdl);
257 }
258
259 return sdi;
260}
261
262
46697e38
BV
263SR_PRIV int lascar_el_usb_receive_data(int fd, int revents, void *cb_data)
264{
265 const struct sr_dev_inst *sdi;
266 struct dev_context *devc;
267
268 if (!(sdi = cb_data))
269 return TRUE;
270
271 if (!(devc = sdi->priv))
272 return TRUE;
273
274 if (revents == G_IO_IN) {
275 /* TODO */
276 }
277
278 return TRUE;
279}