]> git.zerfleddert.de Git - rigol/blob - usbtmc.c
update to libusb-1.0
[rigol] / usbtmc.c
1 #include <string.h>
2 #include <stdio.h>
3 #include <stdint.h>
4 #include <unistd.h>
5 #include <stdlib.h>
6 #include <libusb-1.0/libusb.h>
7 #include <arpa/inet.h>
8
9 #include "scope.h"
10 #include "usbtmc.h"
11
12 #define USB_TIMEOUT 10000
13 #define USBTMC_IN_TRANSFERSIZE 0x800
14
15 #define ID_VENDOR 0x400
16 #define ID_PRODUCT 0x5dc
17
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
26 /* TODO: fix memory leak here: */
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 :-( */
30 static 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 }
67
68 /* This routine locates a scope by VID/PID and returns a struct scope* for it */
69 static struct scope* usbtmc_find_scope() {
70 libusb_device_handle *devh = NULL;
71 libusb_device **list;
72 ssize_t cnt;
73 ssize_t i;
74 int err;
75 struct scope *sc;
76
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;
85
86 err = libusb_get_device_descriptor(list[i], &desc);
87 if (err)
88 continue;
89
90 if ((desc.idVendor == ID_VENDOR) && (desc.idProduct == ID_PRODUCT)) {
91 libusb_device *dev = list[i];
92
93 err = libusb_open(dev, &devh);
94 if (err) {
95 fprintf(stderr, "Can't open device: %d\n", err);
96 return NULL;
97 }
98
99 sc = calloc(1, sizeof(struct scope));
100 if (sc == NULL) {
101 perror("calloc");
102 exit(EXIT_FAILURE);
103 }
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;
114 }
115
116 }
117
118 return NULL;
119 }
120
121 static unsigned char usb488_status(struct scope *sc)
122 {
123 int r;
124 unsigned char status[3];
125
126 sc->usb.bTag++;
127
128 r = libusb_control_transfer(sc->usb.dev, 0xA1,
129 USB488_CTL_READ_STATUS_BYTE,
130 (sc->usb.bTag & 0x7f), 0, status, 3,
131 USB_TIMEOUT);
132
133 if ((r != 3) || (status[0] != USBTMC_STATUS_SUCCESS) || (status[1] != (sc->usb.bTag & 0x7f))) {
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
141 static struct usbtmc_capabilities* usbtmc_get_capabilities(struct scope *sc)
142 {
143 int r;
144 static struct usbtmc_capabilities res;
145
146 r = libusb_control_transfer(sc->usb.dev, 0xA1,
147 USBTMC_CTL_GET_CAPABILITIES,
148 0, 0, (unsigned char*)&res, sizeof(struct usbtmc_capabilities),
149 USB_TIMEOUT);
150 if (r != sizeof(struct usbtmc_capabilities)) {
151 printf("GET_CAPABILITIES failed: %s\n", usb_strerror(r));
152 return NULL;
153 }
154
155 printf("USBTMC Version %02x.%02x Capabilities:\n", res.bcdUSBTMC[0], res.bcdUSBTMC[1]);
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
168 printf("USB488 Version %02x.%02x Capabilities:\n", res.bcdUSB488[0], res.bcdUSB488[1]);
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
194 void usbtmc_reset(struct scope *sc)
195 {
196 libusb_reset_device(sc->usb.dev);
197 usbtmc_claim(sc);
198 }
199
200 static void usbtmc_clear(struct scope *sc)
201 {
202 int r;
203 unsigned char status[2];
204
205 printf("Initiating clear...\n");
206 r = libusb_control_transfer(sc->usb.dev, 0xA1,
207 USBTMC_CTL_INITIATE_CLEAR,
208 0, 0, status, 1,
209 USB_TIMEOUT);
210
211 if ((r != 1) || status[0] != USBTMC_STATUS_SUCCESS) {
212 printf("INITIATE_CLEAR failed (0x%x): %s\n", status[0], usb_strerror(r));
213 usbtmc_reset(sc);
214 return;
215 }
216
217 while(1) {
218 usleep(100000);
219 printf("Waiting for clear to complete...\n");
220
221 r = libusb_control_transfer(sc->usb.dev, 0xA1,
222 USBTMC_CTL_CHECK_CLEAR_STAT,
223 0, 0, status, 2,
224 USB_TIMEOUT);
225
226 if (r != 2) {
227 printf("CHECK_CLEAR failed: %s\n", usb_strerror(r));
228 return;
229 }
230
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)) {
237 printf("Success!\n");
238 break;
239 }
240 }
241 }
242
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 */
248 int usbtmc_sendscpi(struct scope *sc, char* cmd,
249 unsigned char *resp, int resplen) {
250 int len,r;
251 int err;
252 int cmdlen = strlen(cmd);
253 int transferred;
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) {
276 r=libusb_bulk_transfer(sc->usb.dev, sc->usb.ep_bulk_out,
277 (unsigned char*)req, sizeof(struct usbtmc_header),
278 &transferred,
279 USB_TIMEOUT);
280 USB_ERROR("USBTMC_DEV_DEP_MSG_OUT1", r);
281
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,
285 USB_TIMEOUT);
286 USB_ERROR("USBTMC_DEV_DEP_MSG_OUT2", r);
287 } else {
288 r=libusb_bulk_transfer(sc->usb.dev, sc->usb.ep_bulk_out,
289 (unsigned char*)req, len, &transferred, USB_TIMEOUT);
290 USB_ERROR("USBTMC_DEV_DEP_MSG_OUT", r);
291 }
292
293 free(req);
294
295 if (resp != NULL && resplen != 0) {
296 unsigned char *buff = NULL;
297 unsigned char rxbuff[USBTMC_IN_TRANSFERSIZE];
298 struct usbtmc_header *res;
299 int bytes_read;
300 unsigned int read_size = USBTMC_IN_TRANSFERSIZE;
301 unsigned int headerlen;
302
303 req = calloc(1, sizeof(struct usbtmc_header));
304 if (req == NULL) {
305 perror("calloc");
306 exit(EXIT_FAILURE);
307 }
308
309 if (sc->usb.brokenRigol == 1) {
310 read_size = sc->usb.wMaxPacketSize_in;
311 }
312
313 bytes_read = 0;
314 do {
315 headerlen = 0;
316
317 if ((sc->usb.brokenRigol == 0) || (bytes_read == 0)) {
318 sc->usb.bTag++;
319
320 req->MsgID = USBTMC_REQUEST_DEV_DEP_MSG_IN;
321 req->bTag = sc->usb.bTag;
322 req->bTagInverse = ~sc->usb.bTag;
323 req->TransferSize = LE32(USBTMC_IN_TRANSFERSIZE);
324 req->bmTransferAttributes = 0;
325 req->TermChar = 0;
326
327 /* send read command */
328 r=libusb_bulk_transfer(sc->usb.dev, sc->usb.ep_bulk_out,
329 (unsigned char*)req, sizeof(struct usbtmc_header), &transferred, USB_TIMEOUT);
330 USB_ERROR("USBTMC_REQUEST_DEV_DEP_MSG_IN", r);
331
332 headerlen = sizeof(struct usbtmc_header);
333 }
334
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);
338
339 if (r < headerlen) {
340 fprintf(stderr, "Short read!\n");
341 return 0;
342 }
343
344 if (headerlen > 0) {
345 res = (struct usbtmc_header*)rxbuff;
346
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
368 if ((r - headerlen) > 0) {
369 memcpy(buff + bytes_read, rxbuff + headerlen, r - headerlen);
370 bytes_read += r - headerlen;
371 }
372
373 read_size = USBTMC_IN_TRANSFERSIZE;
374 } while(bytes_read < len);
375
376 free(req);
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;
389 }
390 return 0;
391 }
392
393 void usbtmc_claim(struct scope *sc)
394 {
395 libusb_claim_interface(sc->usb.dev, 0);
396 }
397
398 void usbtmc_release(struct scope *sc)
399 {
400 libusb_release_interface(sc->usb.dev, 0);
401 }
402
403 /* Initialize the scope. */
404 struct scope* usbtmc_initscope(void) {
405 int r;
406 uint32_t vidpid;
407 struct scope *sc;
408
409 /* Init libusb */
410 libusb_init(NULL);
411 /* Locate and open the scope */
412 sc = usbtmc_find_scope();
413 if (!sc) {
414 return NULL;
415 }
416
417 usbtmc_claim(sc);
418 sc->usb.cap = usbtmc_get_capabilities(sc);
419 printf("Device status: 0x%x\n", usb488_status(sc));
420 /* The following code isn't really necessary, the program works
421 OK without it too. */
422 r=libusb_control_transfer(sc->usb.dev, 0xC8, 9, 0, 0, (unsigned char*)&vidpid, 4, USB_TIMEOUT);
423 usbtmc_release(sc);
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 }
430 if (LE32(vidpid)!=0x40005dc) {
431 fprintf(stderr,"Init: buff[%i]=%x\n",r,LE32(vidpid));
432 }
433 return sc;
434 }
435
436 void usbtmc_close(struct scope *sc)
437 {
438 /* Free up and exit */
439 libusb_close(sc->usb.dev);
440 }
Impressum, Datenschutz