]> git.zerfleddert.de Git - rigol/blob - usbtmc.c
improve read from broken rigol scopes
[rigol] / usbtmc.c
1 #include <string.h>
2 #include <stdio.h>
3 #include <stdint.h>
4 #include <usb.h>
5 #include <arpa/inet.h>
6
7 #include "scope.h"
8 #include "usbtmc.h"
9
10 #define USB_TIMEOUT 10000
11 #define USBTMC_IN_TRANSFERSIZE 0x800
12
13 #if BYTE_ORDER == LITTLE_ENDIAN
14 #define LE32(x) x
15 #elif BYTE_ORDER == BIG_ENDIAN
16 #define LE32(x) ((uint32_t)((((uint32_t)x)>>24) | ((((uint32_t)x)>>8) & 0xff00) | ((((uint32_t)x)<<8) & 0xff0000) | (((uint32_t)x)<<24)))
17 #else
18 #error BYTE_ORDER not defined/known!
19 #endif
20
21 /* TODO: fix memory leak here: */
22 #define USB_ERROR(s, x) do { if (x < 0) { fprintf(stderr, "usb %s: %s\n", s, usb_strerror()); usbtmc_clear(sc); return 0; } } while(0)
23
24 /* This routine locates a scope by VID/PID and returns a struct scope* for it */
25 static struct scope* usbtmc_find_scope() {
26 struct usb_bus *bus;
27 struct usb_device *dev=NULL;
28 struct usb_dev_handle *devh;
29
30 struct scope *sc;
31
32 usb_find_busses();
33 usb_find_devices();
34
35 for (bus=usb_busses; bus; bus=bus->next) {
36 for (dev=bus->devices; dev; dev=dev->next) {
37 if (dev->descriptor.idVendor == 0x400 && dev->descriptor.idProduct == 0x5dc) {
38 devh = usb_open(dev);
39 if (devh == NULL)
40 return NULL;
41
42 sc = calloc(1, sizeof(struct scope));
43 if (sc == NULL) {
44 perror("calloc");
45 exit(EXIT_FAILURE);
46 }
47
48 sc->usb.dev = devh;
49
50 /* TODO: FIXME */
51 sc->usb.brokenRigol = 1;
52 sc->usb.ep_bulk_out = 0x01;
53 sc->usb.ep_bulk_in = 0x82;
54 sc->usb.wMaxPacketSize_in = 0x40;
55
56 return sc;
57 }
58 }
59 }
60
61 return NULL;
62 }
63
64 static unsigned char usb488_status(struct scope *sc)
65 {
66 int r;
67 unsigned char status[3];
68
69 sc->usb.bTag++;
70
71 r = usb_control_msg(sc->usb.dev, 0xA1,
72 USB488_CTL_READ_STATUS_BYTE,
73 (sc->usb.bTag & 0x7f), 0, (char*)status, 3,
74 USB_TIMEOUT);
75
76 if ((r != 3) || (status[0] != USBTMC_STATUS_SUCCESS) || (status[1] != (sc->usb.bTag & 0x7f))) {
77 printf("READ_STATUS_BYTE failed: %d 0x%x 0x%x 0x%x\n", r, status[0], status[1], status[2]);
78 return 0xff;
79 }
80
81 return status[2];
82 }
83
84 static struct usbtmc_capabilities* usbtmc_get_capabilities(struct scope *sc)
85 {
86 int r;
87 static struct usbtmc_capabilities res;
88
89 r = usb_control_msg(sc->usb.dev, 0xA1,
90 USBTMC_CTL_GET_CAPABILITIES,
91 0, 0, (char*)&res, sizeof(struct usbtmc_capabilities),
92 USB_TIMEOUT);
93 if (r != sizeof(struct usbtmc_capabilities)) {
94 printf("GET_CAPABILITIES failed: %s\n", usb_strerror());
95 return NULL;
96 }
97
98 printf("USBTMC Version %02x.%02x Capabilities:\n", res.bcdUSBTMC[0], res.bcdUSBTMC[1]);
99 if (res.USBTMCIFcapabilities & USBTMC_CAP_IF_INDICATOR_PULSE)
100 printf("\tInterface supports indicator pulse\n");
101
102 if (res.USBTMCIFcapabilities & USBTMC_CAP_IF_TALKONLY)
103 printf("\tInterface is talk only\n");
104
105 if (res.USBTMCIFcapabilities & USBTMC_CAP_IF_LISTENONLY)
106 printf("\tInterface is listen only\n");
107
108 if (res.USBTMCDEVcapabilities & USBTMC_CAP_DEV_TERMCHAR_SUPP)
109 printf("\tDevice supports Termchar\n");
110
111 printf("USB488 Version %02x.%02x Capabilities:\n", res.bcdUSB488[0], res.bcdUSB488[1]);
112
113 if (res.USB488IFcapabilities & USB488_CAP_IF_4882)
114 printf("\tInterface is 488.2 compliant\n");
115
116 if (res.USB488IFcapabilities & USB488_CAP_IF_LOCKOUT)
117 printf("\tInterface supports local lockout\n");
118
119 if (res.USB488IFcapabilities & USB488_CAP_IF_TRIGGER)
120 printf("\tInterface supports TRIGGER\n");
121
122 if (res.USB488DEVcapabilities & USB488_CAP_DEV_SCPI)
123 printf("\tDevice is SCPI compliant\n");
124
125 if (res.USB488DEVcapabilities & USB488_CAP_DEV_SR1)
126 printf("\tDevice is SR1 capable\n");
127
128 if (res.USB488DEVcapabilities & USB488_CAP_DEV_RL1)
129 printf("\tDevice is RL1 capable\n");
130
131 if (res.USB488DEVcapabilities & USB488_CAP_DEV_DT1)
132 printf("\tDevice is DT1 capable\n");
133
134 return &res;
135 }
136
137 void usbtmc_reset(struct scope *sc)
138 {
139 usb_reset(sc->usb.dev);
140 usbtmc_claim(sc);
141 }
142
143 static void usbtmc_clear(struct scope *sc)
144 {
145 int r;
146 unsigned char status[2];
147
148 printf("Initiating clear...\n");
149 r = usb_control_msg(sc->usb.dev, 0xA1,
150 USBTMC_CTL_INITIATE_CLEAR,
151 0, 0, (char*)status, 1,
152 USB_TIMEOUT);
153
154 if ((r != 1) || status[0] != USBTMC_STATUS_SUCCESS) {
155 printf("INITIATE_CLEAR failed (0x%x): %s\n", status[0], usb_strerror());
156 usbtmc_reset(sc);
157 return;
158 }
159
160 while(1) {
161 usleep(100000);
162 printf("Waiting for clear to complete...\n");
163
164 r = usb_control_msg(sc->usb.dev, 0xA1,
165 USBTMC_CTL_CHECK_CLEAR_STAT,
166 0, 0, (char*)status, 2,
167 USB_TIMEOUT);
168
169 if (r != 2) {
170 printf("CHECK_CLEAR failed: %s\n", usb_strerror());
171 return;
172 }
173
174 if (USBTMC_STATUS_FAIL(status[0])) {
175 printf("CHECK_CLEAR failed: 0x%x\n", status[0]);
176 return;
177 }
178
179 if ((status[0] == USBTMC_STATUS_SUCCESS) && (status[1] == 0)) {
180 printf("Success!\n");
181 break;
182 }
183 }
184 }
185
186 /*
187 * Send a scpi-command to the scope. The response goes into the buffer
188 * called resp, with a size of resplen. If resp==NULL, no response
189 * is requested.
190 */
191 int usbtmc_sendscpi(struct scope *sc, char* cmd,
192 unsigned char *resp, int resplen) {
193 int len,r;
194 int cmdlen = strlen(cmd);
195 struct usbtmc_header *req;
196
197 sc->usb.bTag++;
198
199 len = sizeof(struct usbtmc_header) + cmdlen;
200 if (len%4)
201 len += 4 - (len%4);
202
203 req = calloc(1, len);
204 if (req == NULL) {
205 perror("calloc");
206 exit(EXIT_FAILURE);
207 }
208
209 req->MsgID = USBTMC_DEV_DEP_MSG_OUT;
210 req->bTag = sc->usb.bTag;
211 req->bTagInverse = ~sc->usb.bTag;
212 req->TransferSize = LE32(cmdlen);
213 req->bmTransferAttributes = USBTMC_TRANSFERATTRIB_EOM;
214 memcpy(req->msg, cmd, cmdlen);
215
216 if (sc->usb.brokenRigol) {
217 r=usb_bulk_write(sc->usb.dev, sc->usb.ep_bulk_out,
218 (char*)req, sizeof(struct usbtmc_header),
219 USB_TIMEOUT);
220 USB_ERROR("USBTMC_DEV_DEP_MSG_OUT1", r);
221
222 r=usb_bulk_write(sc->usb.dev, sc->usb.ep_bulk_out,
223 (char*)&(req->msg), len - sizeof(struct usbtmc_header),
224 USB_TIMEOUT);
225 USB_ERROR("USBTMC_DEV_DEP_MSG_OUT2", r);
226 } else {
227 r=usb_bulk_write(sc->usb.dev, sc->usb.ep_bulk_out,
228 (char*)req, len, USB_TIMEOUT);
229 USB_ERROR("USBTMC_DEV_DEP_MSG_OUT", r);
230 }
231
232 free(req);
233
234 if (resp != NULL && resplen != 0) {
235 unsigned char *buff = NULL;
236 unsigned char rxbuff[USBTMC_IN_TRANSFERSIZE];
237 struct usbtmc_header *res;
238 int bytes_read;
239 unsigned int read_size = USBTMC_IN_TRANSFERSIZE;
240 unsigned int headerlen;
241
242 req = calloc(1, sizeof(struct usbtmc_header));
243 if (req == NULL) {
244 perror("calloc");
245 exit(EXIT_FAILURE);
246 }
247
248 if (sc->usb.brokenRigol == 1) {
249 read_size = sc->usb.wMaxPacketSize_in;
250 }
251
252 bytes_read = 0;
253 do {
254 headerlen = 0;
255
256 if ((sc->usb.brokenRigol == 0) || (bytes_read == 0)) {
257 sc->usb.bTag++;
258
259 req->MsgID = USBTMC_REQUEST_DEV_DEP_MSG_IN;
260 req->bTag = sc->usb.bTag;
261 req->bTagInverse = ~sc->usb.bTag;
262 req->TransferSize = LE32(USBTMC_IN_TRANSFERSIZE);
263 req->bmTransferAttributes = 0;
264 req->TermChar = 0;
265
266 /* send read command */
267 r=usb_bulk_write(sc->usb.dev, sc->usb.ep_bulk_out,
268 (char*)req, sizeof(struct usbtmc_header), USB_TIMEOUT);
269 USB_ERROR("USBTMC_REQUEST_DEV_DEP_MSG_IN", r);
270
271 headerlen = sizeof(struct usbtmc_header);
272 }
273
274 r=usb_bulk_read(sc->usb.dev, sc->usb.ep_bulk_in,
275 (char*)rxbuff, read_size, USB_TIMEOUT);
276 USB_ERROR("USBTMC_DEV_DEP_MSG_IN", r);
277
278 if (r < headerlen) {
279 fprintf(stderr, "Short read!\n");
280 return 0;
281 }
282
283 if (headerlen > 0) {
284 res = (struct usbtmc_header*)rxbuff;
285
286 if ((res->bTag != sc->usb.bTag) ||
287 (res->bTagInverse != (unsigned char)(~sc->usb.bTag))) {
288 fprintf(stderr, "Wrong TAG received! We: 0x%02x, Scope: 0x%02x\n", sc->usb.bTag, res->bTag);
289 if (sc->usb.brokenRigol == 1) {
290 fprintf(stderr, "Tying to restart transfer...\n");
291 bytes_read = 0;
292 continue;
293 }
294 return 0;
295 }
296
297 if (buff == NULL) {
298 len = LE32(res->TransferSize);
299 buff=malloc(len);
300 if (buff == NULL) {
301 perror("malloc");
302 exit(EXIT_FAILURE);
303 }
304 }
305 }
306
307 if ((r - headerlen) > 0) {
308 memcpy(buff + bytes_read, rxbuff + headerlen, r - headerlen);
309 bytes_read += r - headerlen;
310 }
311
312 read_size = USBTMC_IN_TRANSFERSIZE;
313 } while(bytes_read < len);
314
315 free(req);
316
317 /* TODO: FIXME */
318 if (bytes_read > resplen) {
319 fprintf(stderr, "Response buffer to small: %d instead of %d bytes!\n",
320 resplen, bytes_read);
321 bytes_read = resplen;
322 }
323
324 memcpy(resp, buff, bytes_read);
325 free(buff);
326
327 return bytes_read;
328 }
329 return 0;
330 }
331
332 void usbtmc_claim(struct scope *sc)
333 {
334 usb_claim_interface(sc->usb.dev, 0);
335 }
336
337 void usbtmc_release(struct scope *sc)
338 {
339 usb_release_interface(sc->usb.dev, 0);
340 }
341
342 /* Initialize the scope. */
343 struct scope* usbtmc_initscope(void) {
344 int r;
345 uint32_t vidpid;
346 struct scope *sc;
347
348 /* Init libusb */
349 usb_init();
350 /* Locate and open the scope */
351 sc = usbtmc_find_scope();
352 if (!sc) {
353 return NULL;
354 }
355
356 usbtmc_claim(sc);
357 sc->usb.cap = usbtmc_get_capabilities(sc);
358 printf("Device status: 0x%x\n", usb488_status(sc));
359 /* The following code isn't really necessary, the program works
360 OK without it too. */
361 r=usb_control_msg(sc->usb.dev, 0xC8, 9, 0, 0, (char*)&vidpid, 4, USB_TIMEOUT);
362 usbtmc_release(sc);
363 if (r < 0) {
364 fprintf (stderr, "Error %d sending init message: %s\n",
365 r, strerror (-r));
366 fprintf (stderr, "Do you have permission on the USB device?\n");
367 exit (1);
368 }
369 if (LE32(vidpid)!=0x40005dc) {
370 fprintf(stderr,"Init: buff[%i]=%x\n",r,LE32(vidpid));
371 }
372 return sc;
373 }
374
375 void usbtmc_close(struct scope *sc)
376 {
377 /* Free up and exit */
378 usb_close(sc->usb.dev);
379 }
Impressum, Datenschutz