update to libusb-1.0
[rigol] / usbtmc.c
CommitLineData
58a9e276
MG
1#include <string.h>
2#include <stdio.h>
3#include <stdint.h>
f416d675
MG
4#include <unistd.h>
5#include <stdlib.h>
6#include <libusb-1.0/libusb.h>
58a9e276
MG
7#include <arpa/inet.h>
8
7906b395 9#include "scope.h"
58a9e276
MG
10#include "usbtmc.h"
11
f7de0831
MG
12#define USB_TIMEOUT 10000
13#define USBTMC_IN_TRANSFERSIZE 0x800
165abe62 14
f416d675
MG
15#define ID_VENDOR 0x400
16#define ID_PRODUCT 0x5dc
17
ddf9f28b
MG
18#if BYTE_ORDER == LITTLE_ENDIAN
19#define LE32(x) x
20#elif BYTE_ORDER == BIG_ENDIAN
21#define LE32(x) ((uint32_t)((((uint32_t)x)>>24) | ((((uint32_t)x)>>8) & 0xff00) | ((((uint32_t)x)<<8) & 0xff0000) | (((uint32_t)x)<<24)))
22#else
23#error BYTE_ORDER not defined/known!
24#endif
25
483a564b 26/* TODO: fix memory leak here: */
f416d675
MG
27#define USB_ERROR(s, x) do { if (x < 0) { fprintf(stderr, "usb %s: %s\n", s, usb_strerror(x)); usbtmc_clear(sc); return 0; } } while(0)
28
29/* Not in all libusb-1.0 versions, so we have to roll our own :-( */
30static char * usb_strerror(int e)
31{
32 static char unknerr[256];
33
34 switch (e) {
35 case LIBUSB_SUCCESS:
36 return "Success";
37 case LIBUSB_ERROR_IO:
38 return "Input/output error";
39 case LIBUSB_ERROR_INVALID_PARAM:
40 return "Invalid parameter";
41 case LIBUSB_ERROR_ACCESS:
42 return "Access denied (insufficient permissions)";
43 case LIBUSB_ERROR_NO_DEVICE:
44 return "No such device (it may have been disconnected)";
45 case LIBUSB_ERROR_NOT_FOUND:
46 return "Entity not found";
47 case LIBUSB_ERROR_BUSY:
48 return "Resource busy";
49 case LIBUSB_ERROR_TIMEOUT:
50 return "Operation timed out";
51 case LIBUSB_ERROR_OVERFLOW:
52 return "Overflow";
53 case LIBUSB_ERROR_PIPE:
54 return "Pipe error";
55 case LIBUSB_ERROR_INTERRUPTED:
56 return "System call interrupted (perhaps due to signal)";
57 case LIBUSB_ERROR_NO_MEM:
58 return "Insufficient memory";
59 case LIBUSB_ERROR_NOT_SUPPORTED:
60 return "Operation not supported or unimplemented on this platform";
61 case LIBUSB_ERROR_OTHER:
62 return "Other error";
63 };
64 snprintf(unknerr, sizeof(unknerr), "Unknown error code %d / 0x%02x", e, e);
65 return unknerr;
66}
58a9e276 67
7b575069
MG
68/* This routine locates a scope by VID/PID and returns a struct scope* for it */
69static struct scope* usbtmc_find_scope() {
f416d675
MG
70 libusb_device_handle *devh = NULL;
71 libusb_device **list;
72 ssize_t cnt;
73 ssize_t i;
74 int err;
7b575069
MG
75 struct scope *sc;
76
f416d675
MG
77 cnt = libusb_get_device_list(NULL, &list);
78 if (cnt < 0) {
79 fprintf(stderr, "Can't get USB device list: %d\n", (int)cnt);
80 return NULL;
81 }
82
83 for (i = 0; i < cnt; i++){
84 struct libusb_device_descriptor desc;
7b575069 85
f416d675
MG
86 err = libusb_get_device_descriptor(list[i], &desc);
87 if (err)
88 continue;
7b575069 89
f416d675
MG
90 if ((desc.idVendor == ID_VENDOR) && (desc.idProduct == ID_PRODUCT)) {
91 libusb_device *dev = list[i];
7b575069 92
f416d675
MG
93 err = libusb_open(dev, &devh);
94 if (err) {
95 fprintf(stderr, "Can't open device: %d\n", err);
96 return NULL;
97 }
7b575069 98
f416d675
MG
99 sc = calloc(1, sizeof(struct scope));
100 if (sc == NULL) {
101 perror("calloc");
102 exit(EXIT_FAILURE);
58a9e276 103 }
f416d675
MG
104
105 sc->usb.dev = devh;
106
107 /* TODO: FIXME */
108 sc->usb.brokenRigol = 1;
109 sc->usb.ep_bulk_out = 0x01;
110 sc->usb.ep_bulk_in = 0x82;
111 sc->usb.wMaxPacketSize_in = 0x40;
112
113 return sc;
58a9e276 114 }
f416d675 115
58a9e276 116 }
7b575069 117
58a9e276
MG
118 return NULL;
119}
120
07a45f03 121static unsigned char usb488_status(struct scope *sc)
121b4233
MG
122{
123 int r;
124 unsigned char status[3];
125
126 sc->usb.bTag++;
127
f416d675 128 r = libusb_control_transfer(sc->usb.dev, 0xA1,
483a564b 129 USB488_CTL_READ_STATUS_BYTE,
f416d675 130 (sc->usb.bTag & 0x7f), 0, status, 3,
483a564b
MG
131 USB_TIMEOUT);
132
07a45f03 133 if ((r != 3) || (status[0] != USBTMC_STATUS_SUCCESS) || (status[1] != (sc->usb.bTag & 0x7f))) {
121b4233
MG
134 printf("READ_STATUS_BYTE failed: %d 0x%x 0x%x 0x%x\n", r, status[0], status[1], status[2]);
135 return 0xff;
136 }
137
138 return status[2];
139}
140
483a564b
MG
141static struct usbtmc_capabilities* usbtmc_get_capabilities(struct scope *sc)
142{
143 int r;
144 static struct usbtmc_capabilities res;
145
f416d675 146 r = libusb_control_transfer(sc->usb.dev, 0xA1,
483a564b 147 USBTMC_CTL_GET_CAPABILITIES,
f416d675 148 0, 0, (unsigned char*)&res, sizeof(struct usbtmc_capabilities),
483a564b
MG
149 USB_TIMEOUT);
150 if (r != sizeof(struct usbtmc_capabilities)) {
f416d675 151 printf("GET_CAPABILITIES failed: %s\n", usb_strerror(r));
483a564b
MG
152 return NULL;
153 }
154
f7de0831 155 printf("USBTMC Version %02x.%02x Capabilities:\n", res.bcdUSBTMC[0], res.bcdUSBTMC[1]);
483a564b
MG
156 if (res.USBTMCIFcapabilities & USBTMC_CAP_IF_INDICATOR_PULSE)
157 printf("\tInterface supports indicator pulse\n");
158
159 if (res.USBTMCIFcapabilities & USBTMC_CAP_IF_TALKONLY)
160 printf("\tInterface is talk only\n");
161
162 if (res.USBTMCIFcapabilities & USBTMC_CAP_IF_LISTENONLY)
163 printf("\tInterface is listen only\n");
164
165 if (res.USBTMCDEVcapabilities & USBTMC_CAP_DEV_TERMCHAR_SUPP)
166 printf("\tDevice supports Termchar\n");
167
f7de0831 168 printf("USB488 Version %02x.%02x Capabilities:\n", res.bcdUSB488[0], res.bcdUSB488[1]);
483a564b
MG
169
170 if (res.USB488IFcapabilities & USB488_CAP_IF_4882)
171 printf("\tInterface is 488.2 compliant\n");
172
173 if (res.USB488IFcapabilities & USB488_CAP_IF_LOCKOUT)
174 printf("\tInterface supports local lockout\n");
175
176 if (res.USB488IFcapabilities & USB488_CAP_IF_TRIGGER)
177 printf("\tInterface supports TRIGGER\n");
178
179 if (res.USB488DEVcapabilities & USB488_CAP_DEV_SCPI)
180 printf("\tDevice is SCPI compliant\n");
181
182 if (res.USB488DEVcapabilities & USB488_CAP_DEV_SR1)
183 printf("\tDevice is SR1 capable\n");
184
185 if (res.USB488DEVcapabilities & USB488_CAP_DEV_RL1)
186 printf("\tDevice is RL1 capable\n");
187
188 if (res.USB488DEVcapabilities & USB488_CAP_DEV_DT1)
189 printf("\tDevice is DT1 capable\n");
190
191 return &res;
192}
193
10ca7ea8
MG
194void usbtmc_reset(struct scope *sc)
195{
f416d675 196 libusb_reset_device(sc->usb.dev);
10ca7ea8
MG
197 usbtmc_claim(sc);
198}
199
f3ecdd6a
MG
200static void usbtmc_clear(struct scope *sc)
201{
202 int r;
203 unsigned char status[2];
204
205 printf("Initiating clear...\n");
f416d675 206 r = libusb_control_transfer(sc->usb.dev, 0xA1,
f3ecdd6a 207 USBTMC_CTL_INITIATE_CLEAR,
f416d675 208 0, 0, status, 1,
f3ecdd6a
MG
209 USB_TIMEOUT);
210
07a45f03 211 if ((r != 1) || status[0] != USBTMC_STATUS_SUCCESS) {
f416d675 212 printf("INITIATE_CLEAR failed (0x%x): %s\n", status[0], usb_strerror(r));
10ca7ea8 213 usbtmc_reset(sc);
f3ecdd6a
MG
214 return;
215 }
216
217 while(1) {
218 usleep(100000);
219 printf("Waiting for clear to complete...\n");
220
f416d675 221 r = libusb_control_transfer(sc->usb.dev, 0xA1,
f3ecdd6a 222 USBTMC_CTL_CHECK_CLEAR_STAT,
f416d675 223 0, 0, status, 2,
f3ecdd6a
MG
224 USB_TIMEOUT);
225
07a45f03 226 if (r != 2) {
f416d675 227 printf("CHECK_CLEAR failed: %s\n", usb_strerror(r));
f3ecdd6a
MG
228 return;
229 }
230
07a45f03
MG
231 if (USBTMC_STATUS_FAIL(status[0])) {
232 printf("CHECK_CLEAR failed: 0x%x\n", status[0]);
233 return;
234 }
235
236 if ((status[0] == USBTMC_STATUS_SUCCESS) && (status[1] == 0)) {
f3ecdd6a
MG
237 printf("Success!\n");
238 break;
239 }
240 }
241}
242
7b575069
MG
243/*
244 * Send a scpi-command to the scope. The response goes into the buffer
245 * called resp, with a size of resplen. If resp==NULL, no response
246 * is requested.
247 */
7906b395 248int usbtmc_sendscpi(struct scope *sc, char* cmd,
58a9e276 249 unsigned char *resp, int resplen) {
7b575069 250 int len,r;
f416d675 251 int err;
58a9e276 252 int cmdlen = strlen(cmd);
f416d675 253 int transferred;
7b575069
MG
254 struct usbtmc_header *req;
255
256 sc->usb.bTag++;
257
258 len = sizeof(struct usbtmc_header) + cmdlen;
259 if (len%4)
260 len += 4 - (len%4);
261
262 req = calloc(1, len);
263 if (req == NULL) {
264 perror("calloc");
265 exit(EXIT_FAILURE);
266 }
267
268 req->MsgID = USBTMC_DEV_DEP_MSG_OUT;
269 req->bTag = sc->usb.bTag;
270 req->bTagInverse = ~sc->usb.bTag;
271 req->TransferSize = LE32(cmdlen);
272 req->bmTransferAttributes = USBTMC_TRANSFERATTRIB_EOM;
273 memcpy(req->msg, cmd, cmdlen);
274
275 if (sc->usb.brokenRigol) {
f416d675
MG
276 r=libusb_bulk_transfer(sc->usb.dev, sc->usb.ep_bulk_out,
277 (unsigned char*)req, sizeof(struct usbtmc_header),
278 &transferred,
7b575069 279 USB_TIMEOUT);
0aa0b761 280 USB_ERROR("USBTMC_DEV_DEP_MSG_OUT1", r);
7b575069 281
f416d675
MG
282 r=libusb_bulk_transfer(sc->usb.dev, sc->usb.ep_bulk_out,
283 (unsigned char*)&(req->msg), len - sizeof(struct usbtmc_header),
284 &transferred,
7b575069 285 USB_TIMEOUT);
0aa0b761 286 USB_ERROR("USBTMC_DEV_DEP_MSG_OUT2", r);
7b575069 287 } else {
f416d675
MG
288 r=libusb_bulk_transfer(sc->usb.dev, sc->usb.ep_bulk_out,
289 (unsigned char*)req, len, &transferred, USB_TIMEOUT);
0aa0b761 290 USB_ERROR("USBTMC_DEV_DEP_MSG_OUT", r);
7b575069
MG
291 }
292
293 free(req);
294
58a9e276 295 if (resp != NULL && resplen != 0) {
f7de0831
MG
296 unsigned char *buff = NULL;
297 unsigned char rxbuff[USBTMC_IN_TRANSFERSIZE];
7b575069
MG
298 struct usbtmc_header *res;
299 int bytes_read;
7d42ad7e 300 unsigned int read_size = USBTMC_IN_TRANSFERSIZE;
f7de0831 301 unsigned int headerlen;
7b575069
MG
302
303 req = calloc(1, sizeof(struct usbtmc_header));
304 if (req == NULL) {
305 perror("calloc");
306 exit(EXIT_FAILURE);
307 }
308
f7de0831 309 if (sc->usb.brokenRigol == 1) {
7d42ad7e 310 read_size = sc->usb.wMaxPacketSize_in;
f7de0831 311 }
7b575069 312
f7de0831
MG
313 bytes_read = 0;
314 do {
315 headerlen = 0;
7b575069 316
f7de0831
MG
317 if ((sc->usb.brokenRigol == 0) || (bytes_read == 0)) {
318 sc->usb.bTag++;
7b575069 319
f7de0831
MG
320 req->MsgID = USBTMC_REQUEST_DEV_DEP_MSG_IN;
321 req->bTag = sc->usb.bTag;
322 req->bTagInverse = ~sc->usb.bTag;
7d42ad7e 323 req->TransferSize = LE32(USBTMC_IN_TRANSFERSIZE);
f7de0831
MG
324 req->bmTransferAttributes = 0;
325 req->TermChar = 0;
7b575069 326
f7de0831 327 /* send read command */
f416d675
MG
328 r=libusb_bulk_transfer(sc->usb.dev, sc->usb.ep_bulk_out,
329 (unsigned char*)req, sizeof(struct usbtmc_header), &transferred, USB_TIMEOUT);
f7de0831 330 USB_ERROR("USBTMC_REQUEST_DEV_DEP_MSG_IN", r);
7b575069 331
f7de0831
MG
332 headerlen = sizeof(struct usbtmc_header);
333 }
7b575069 334
f416d675
MG
335 err=libusb_bulk_transfer(sc->usb.dev, sc->usb.ep_bulk_in,
336 (unsigned char*)rxbuff, read_size, &r, USB_TIMEOUT);
337 USB_ERROR("USBTMC_DEV_DEP_MSG_IN", err);
7b575069 338
f7de0831
MG
339 if (r < headerlen) {
340 fprintf(stderr, "Short read!\n");
341 return 0;
342 }
7b575069 343
f7de0831
MG
344 if (headerlen > 0) {
345 res = (struct usbtmc_header*)rxbuff;
7b575069 346
f7de0831
MG
347 if ((res->bTag != sc->usb.bTag) ||
348 (res->bTagInverse != (unsigned char)(~sc->usb.bTag))) {
349 fprintf(stderr, "Wrong TAG received! We: 0x%02x, Scope: 0x%02x\n", sc->usb.bTag, res->bTag);
350 if (sc->usb.brokenRigol == 1) {
351 fprintf(stderr, "Tying to restart transfer...\n");
352 bytes_read = 0;
353 continue;
354 }
355 return 0;
356 }
357
358 if (buff == NULL) {
359 len = LE32(res->TransferSize);
360 buff=malloc(len);
361 if (buff == NULL) {
362 perror("malloc");
363 exit(EXIT_FAILURE);
364 }
365 }
366 }
367
7d42ad7e 368 if ((r - headerlen) > 0) {
f7de0831
MG
369 memcpy(buff + bytes_read, rxbuff + headerlen, r - headerlen);
370 bytes_read += r - headerlen;
371 }
372
7d42ad7e 373 read_size = USBTMC_IN_TRANSFERSIZE;
f7de0831
MG
374 } while(bytes_read < len);
375
376 free(req);
7b575069
MG
377
378 /* TODO: FIXME */
379 if (bytes_read > resplen) {
380 fprintf(stderr, "Response buffer to small: %d instead of %d bytes!\n",
381 resplen, bytes_read);
382 bytes_read = resplen;
383 }
384
385 memcpy(resp, buff, bytes_read);
386 free(buff);
387
388 return bytes_read;
58a9e276
MG
389 }
390 return 0;
391}
392
7906b395 393void usbtmc_claim(struct scope *sc)
ad9fbc05 394{
f416d675 395 libusb_claim_interface(sc->usb.dev, 0);
ad9fbc05
MG
396}
397
7906b395 398void usbtmc_release(struct scope *sc)
ad9fbc05 399{
f416d675 400 libusb_release_interface(sc->usb.dev, 0);
ad9fbc05
MG
401}
402
483a564b 403/* Initialize the scope. */
7906b395 404struct scope* usbtmc_initscope(void) {
58a9e276 405 int r;
80564ddb 406 uint32_t vidpid;
7906b395 407 struct scope *sc;
58a9e276 408
7b575069 409 /* Init libusb */
f416d675 410 libusb_init(NULL);
7b575069
MG
411 /* Locate and open the scope */
412 sc = usbtmc_find_scope();
413 if (!sc) {
2999345d 414 return NULL;
58a9e276 415 }
7906b395 416
7906b395 417 usbtmc_claim(sc);
90e416c4 418 sc->usb.cap = usbtmc_get_capabilities(sc);
07a45f03 419 printf("Device status: 0x%x\n", usb488_status(sc));
7b575069
MG
420 /* The following code isn't really necessary, the program works
421 OK without it too. */
f416d675 422 r=libusb_control_transfer(sc->usb.dev, 0xC8, 9, 0, 0, (unsigned char*)&vidpid, 4, USB_TIMEOUT);
7906b395 423 usbtmc_release(sc);
58a9e276
MG
424 if (r < 0) {
425 fprintf (stderr, "Error %d sending init message: %s\n",
426 r, strerror (-r));
427 fprintf (stderr, "Do you have permission on the USB device?\n");
428 exit (1);
429 }
80564ddb
MG
430 if (LE32(vidpid)!=0x40005dc) {
431 fprintf(stderr,"Init: buff[%i]=%x\n",r,LE32(vidpid));
58a9e276 432 }
7906b395 433 return sc;
58a9e276 434}
b74fea90 435
7906b395 436void usbtmc_close(struct scope *sc)
b74fea90 437{
7b575069 438 /* Free up and exit */
f416d675 439 libusb_close(sc->usb.dev);
b74fea90 440}
Impressum, Datenschutz