]> git.zerfleddert.de Git - rigol/blob - usbtmc.c
84df109b6778a82dcd15396878bbf40c16466abc
[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 static void usbtmc_clear(struct scope *sc)
138 {
139 int r;
140 unsigned char status[2];
141
142 printf("Initiating clear...\n");
143 r = usb_control_msg(sc->usb.dev, 0xA1,
144 USBTMC_CTL_INITIATE_CLEAR,
145 0, 0, (char*)status, 1,
146 USB_TIMEOUT);
147
148 if ((r != 1) || status[0] != USBTMC_STATUS_SUCCESS) {
149 printf("INITIATE_CLEAR failed (0x%x): %s\n", status[0], usb_strerror());
150 usb_reset(sc->usb.dev);
151 usbtmc_claim(sc);
152 return;
153 }
154
155 while(1) {
156 usleep(100000);
157 printf("Waiting for clear to complete...\n");
158
159 r = usb_control_msg(sc->usb.dev, 0xA1,
160 USBTMC_CTL_CHECK_CLEAR_STAT,
161 0, 0, (char*)status, 2,
162 USB_TIMEOUT);
163
164 if (r != 2) {
165 printf("CHECK_CLEAR failed: %s\n", usb_strerror());
166 return;
167 }
168
169 if (USBTMC_STATUS_FAIL(status[0])) {
170 printf("CHECK_CLEAR failed: 0x%x\n", status[0]);
171 return;
172 }
173
174 if ((status[0] == USBTMC_STATUS_SUCCESS) && (status[1] == 0)) {
175 printf("Success!\n");
176 break;
177 }
178 }
179 }
180
181 /*
182 * Send a scpi-command to the scope. The response goes into the buffer
183 * called resp, with a size of resplen. If resp==NULL, no response
184 * is requested.
185 */
186 int usbtmc_sendscpi(struct scope *sc, char* cmd,
187 unsigned char *resp, int resplen) {
188 int len,r;
189 int cmdlen = strlen(cmd);
190 struct usbtmc_header *req;
191
192 sc->usb.bTag++;
193
194 len = sizeof(struct usbtmc_header) + cmdlen;
195 if (len%4)
196 len += 4 - (len%4);
197
198 req = calloc(1, len);
199 if (req == NULL) {
200 perror("calloc");
201 exit(EXIT_FAILURE);
202 }
203
204 req->MsgID = USBTMC_DEV_DEP_MSG_OUT;
205 req->bTag = sc->usb.bTag;
206 req->bTagInverse = ~sc->usb.bTag;
207 req->TransferSize = LE32(cmdlen);
208 req->bmTransferAttributes = USBTMC_TRANSFERATTRIB_EOM;
209 memcpy(req->msg, cmd, cmdlen);
210
211 if (sc->usb.brokenRigol) {
212 r=usb_bulk_write(sc->usb.dev, sc->usb.ep_bulk_out,
213 (char*)req, sizeof(struct usbtmc_header),
214 USB_TIMEOUT);
215 USB_ERROR("USBTMC_DEV_DEP_MSG_OUT1", r);
216
217 r=usb_bulk_write(sc->usb.dev, sc->usb.ep_bulk_out,
218 (char*)&(req->msg), len - sizeof(struct usbtmc_header),
219 USB_TIMEOUT);
220 USB_ERROR("USBTMC_DEV_DEP_MSG_OUT2", r);
221 } else {
222 r=usb_bulk_write(sc->usb.dev, sc->usb.ep_bulk_out,
223 (char*)req, len, USB_TIMEOUT);
224 USB_ERROR("USBTMC_DEV_DEP_MSG_OUT", r);
225 }
226
227 free(req);
228
229 if (resp != NULL && resplen != 0) {
230 unsigned char *buff = NULL;
231 unsigned char rxbuff[USBTMC_IN_TRANSFERSIZE];
232 struct usbtmc_header *res;
233 int bytes_read;
234 unsigned int transfer_size = USBTMC_IN_TRANSFERSIZE;
235 unsigned int headerlen;
236
237 req = calloc(1, sizeof(struct usbtmc_header));
238 if (req == NULL) {
239 perror("calloc");
240 exit(EXIT_FAILURE);
241 }
242
243 if (sc->usb.brokenRigol == 1) {
244 transfer_size = sc->usb.wMaxPacketSize_in;
245 }
246
247 bytes_read = 0;
248 do {
249 headerlen = 0;
250
251 if ((sc->usb.brokenRigol == 0) || (bytes_read == 0)) {
252 sc->usb.bTag++;
253
254 req->MsgID = USBTMC_REQUEST_DEV_DEP_MSG_IN;
255 req->bTag = sc->usb.bTag;
256 req->bTagInverse = ~sc->usb.bTag;
257 req->TransferSize = LE32(transfer_size);
258 req->bmTransferAttributes = 0;
259 req->TermChar = 0;
260
261 /* send read command */
262 r=usb_bulk_write(sc->usb.dev, sc->usb.ep_bulk_out,
263 (char*)req, sizeof(struct usbtmc_header), USB_TIMEOUT);
264 USB_ERROR("USBTMC_REQUEST_DEV_DEP_MSG_IN", r);
265
266 headerlen = sizeof(struct usbtmc_header);
267 }
268
269 r=usb_bulk_read(sc->usb.dev, sc->usb.ep_bulk_in,
270 (char*)rxbuff, transfer_size, USB_TIMEOUT);
271 USB_ERROR("USBTMC_DEV_DEP_MSG_IN", r);
272
273 if (r < headerlen) {
274 fprintf(stderr, "Short read!\n");
275 return 0;
276 }
277
278
279 if (headerlen > 0) {
280 res = (struct usbtmc_header*)rxbuff;
281
282 if ((res->bTag != sc->usb.bTag) ||
283 (res->bTagInverse != (unsigned char)(~sc->usb.bTag))) {
284 fprintf(stderr, "Wrong TAG received! We: 0x%02x, Scope: 0x%02x\n", sc->usb.bTag, res->bTag);
285 if (sc->usb.brokenRigol == 1) {
286 fprintf(stderr, "Tying to restart transfer...\n");
287 bytes_read = 0;
288 continue;
289 }
290 return 0;
291 }
292
293 if (buff == NULL) {
294 len = LE32(res->TransferSize);
295 buff=malloc(len);
296 if (buff == NULL) {
297 perror("malloc");
298 exit(EXIT_FAILURE);
299 }
300 }
301 }
302
303 if ((sc->usb.brokenRigol == 0) || (transfer_size == USBTMC_IN_TRANSFERSIZE) ||
304 ((r - sizeof(struct usbtmc_header) >= len))) {
305 memcpy(buff + bytes_read, rxbuff + headerlen, r - headerlen);
306 bytes_read += r - headerlen;
307 }
308
309 transfer_size = USBTMC_IN_TRANSFERSIZE;
310 } while(bytes_read < len);
311
312 free(req);
313
314 /* TODO: FIXME */
315 if (bytes_read > resplen) {
316 fprintf(stderr, "Response buffer to small: %d instead of %d bytes!\n",
317 resplen, bytes_read);
318 bytes_read = resplen;
319 }
320
321 memcpy(resp, buff, bytes_read);
322 free(buff);
323
324 return bytes_read;
325 }
326 return 0;
327 }
328
329 void usbtmc_claim(struct scope *sc)
330 {
331 usb_claim_interface(sc->usb.dev, 0);
332 }
333
334 void usbtmc_release(struct scope *sc)
335 {
336 usb_release_interface(sc->usb.dev, 0);
337 }
338
339 /* Initialize the scope. */
340 struct scope* usbtmc_initscope(void) {
341 int r;
342 uint32_t vidpid;
343 struct scope *sc;
344
345 /* Init libusb */
346 usb_init();
347 /* Locate and open the scope */
348 sc = usbtmc_find_scope();
349 if (!sc) {
350 return NULL;
351 }
352
353 usbtmc_claim(sc);
354 sc->usb.cap = usbtmc_get_capabilities(sc);
355 printf("Device status: 0x%x\n", usb488_status(sc));
356 /* The following code isn't really necessary, the program works
357 OK without it too. */
358 r=usb_control_msg(sc->usb.dev, 0xC8, 9, 0, 0, (char*)&vidpid, 4, USB_TIMEOUT);
359 usbtmc_release(sc);
360 if (r < 0) {
361 fprintf (stderr, "Error %d sending init message: %s\n",
362 r, strerror (-r));
363 fprintf (stderr, "Do you have permission on the USB device?\n");
364 exit (1);
365 }
366 if (LE32(vidpid)!=0x40005dc) {
367 fprintf(stderr,"Init: buff[%i]=%x\n",r,LE32(vidpid));
368 }
369 return sc;
370 }
371
372 void usbtmc_close(struct scope *sc)
373 {
374 /* Free up and exit */
375 usb_close(sc->usb.dev);
376 }
Impressum, Datenschutz