]> git.zerfleddert.de Git - rigol/blame - usbtmc.c
typo
[rigol] / usbtmc.c
CommitLineData
58a9e276
MG
1#include <string.h>
2#include <stdio.h>
3#include <stdint.h>
4#include <usb.h>
5#include <arpa/inet.h>
6
7906b395 7#include "scope.h"
58a9e276
MG
8#include "usbtmc.h"
9
f7de0831
MG
10#define USB_TIMEOUT 10000
11#define USBTMC_IN_TRANSFERSIZE 0x800
165abe62 12
ddf9f28b
MG
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
483a564b 21/* TODO: fix memory leak here: */
f3ecdd6a 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)
58a9e276 23
7b575069
MG
24/* This routine locates a scope by VID/PID and returns a struct scope* for it */
25static struct scope* usbtmc_find_scope() {
58a9e276
MG
26 struct usb_bus *bus;
27 struct usb_device *dev=NULL;
7b575069
MG
28 struct usb_dev_handle *devh;
29
30 struct scope *sc;
31
58a9e276
MG
32 usb_find_busses();
33 usb_find_devices();
7b575069 34
58a9e276
MG
35 for (bus=usb_busses; bus; bus=bus->next) {
36 for (dev=bus->devices; dev; dev=dev->next) {
7b575069
MG
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;
c399a457
MG
52 sc->usb.ep_bulk_out = 0x01;
53 sc->usb.ep_bulk_in = 0x82;
7b575069
MG
54 sc->usb.wMaxPacketSize_in = 0x40;
55
56 return sc;
58a9e276
MG
57 }
58 }
59 }
7b575069 60
58a9e276
MG
61 return NULL;
62}
63
07a45f03 64static unsigned char usb488_status(struct scope *sc)
121b4233
MG
65{
66 int r;
67 unsigned char status[3];
68
69 sc->usb.bTag++;
70
483a564b
MG
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
07a45f03 76 if ((r != 3) || (status[0] != USBTMC_STATUS_SUCCESS) || (status[1] != (sc->usb.bTag & 0x7f))) {
121b4233
MG
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
483a564b
MG
84static 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
f7de0831 98 printf("USBTMC Version %02x.%02x Capabilities:\n", res.bcdUSBTMC[0], res.bcdUSBTMC[1]);
483a564b
MG
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
f7de0831 111 printf("USB488 Version %02x.%02x Capabilities:\n", res.bcdUSB488[0], res.bcdUSB488[1]);
483a564b
MG
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
10ca7ea8
MG
137void usbtmc_reset(struct scope *sc)
138{
139 usb_reset(sc->usb.dev);
140 usbtmc_claim(sc);
141}
142
f3ecdd6a
MG
143static 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
07a45f03
MG
154 if ((r != 1) || status[0] != USBTMC_STATUS_SUCCESS) {
155 printf("INITIATE_CLEAR failed (0x%x): %s\n", status[0], usb_strerror());
10ca7ea8 156 usbtmc_reset(sc);
f3ecdd6a
MG
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
07a45f03 169 if (r != 2) {
f3ecdd6a
MG
170 printf("CHECK_CLEAR failed: %s\n", usb_strerror());
171 return;
172 }
173
07a45f03
MG
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)) {
f3ecdd6a
MG
180 printf("Success!\n");
181 break;
182 }
183 }
184}
185
7b575069
MG
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 */
7906b395 191int usbtmc_sendscpi(struct scope *sc, char* cmd,
58a9e276 192 unsigned char *resp, int resplen) {
7b575069 193 int len,r;
58a9e276 194 int cmdlen = strlen(cmd);
7b575069
MG
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);
0aa0b761 220 USB_ERROR("USBTMC_DEV_DEP_MSG_OUT1", r);
7b575069
MG
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);
0aa0b761 225 USB_ERROR("USBTMC_DEV_DEP_MSG_OUT2", r);
7b575069
MG
226 } else {
227 r=usb_bulk_write(sc->usb.dev, sc->usb.ep_bulk_out,
228 (char*)req, len, USB_TIMEOUT);
0aa0b761 229 USB_ERROR("USBTMC_DEV_DEP_MSG_OUT", r);
7b575069
MG
230 }
231
232 free(req);
233
58a9e276 234 if (resp != NULL && resplen != 0) {
f7de0831
MG
235 unsigned char *buff = NULL;
236 unsigned char rxbuff[USBTMC_IN_TRANSFERSIZE];
7b575069
MG
237 struct usbtmc_header *res;
238 int bytes_read;
7d42ad7e 239 unsigned int read_size = USBTMC_IN_TRANSFERSIZE;
f7de0831 240 unsigned int headerlen;
7b575069
MG
241
242 req = calloc(1, sizeof(struct usbtmc_header));
243 if (req == NULL) {
244 perror("calloc");
245 exit(EXIT_FAILURE);
246 }
247
f7de0831 248 if (sc->usb.brokenRigol == 1) {
7d42ad7e 249 read_size = sc->usb.wMaxPacketSize_in;
f7de0831 250 }
7b575069 251
f7de0831
MG
252 bytes_read = 0;
253 do {
254 headerlen = 0;
7b575069 255
f7de0831
MG
256 if ((sc->usb.brokenRigol == 0) || (bytes_read == 0)) {
257 sc->usb.bTag++;
7b575069 258
f7de0831
MG
259 req->MsgID = USBTMC_REQUEST_DEV_DEP_MSG_IN;
260 req->bTag = sc->usb.bTag;
261 req->bTagInverse = ~sc->usb.bTag;
7d42ad7e 262 req->TransferSize = LE32(USBTMC_IN_TRANSFERSIZE);
f7de0831
MG
263 req->bmTransferAttributes = 0;
264 req->TermChar = 0;
7b575069 265
f7de0831
MG
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);
7b575069 270
f7de0831
MG
271 headerlen = sizeof(struct usbtmc_header);
272 }
7b575069 273
f7de0831 274 r=usb_bulk_read(sc->usb.dev, sc->usb.ep_bulk_in,
7d42ad7e 275 (char*)rxbuff, read_size, USB_TIMEOUT);
f7de0831 276 USB_ERROR("USBTMC_DEV_DEP_MSG_IN", r);
7b575069 277
f7de0831
MG
278 if (r < headerlen) {
279 fprintf(stderr, "Short read!\n");
280 return 0;
281 }
7b575069 282
f7de0831
MG
283 if (headerlen > 0) {
284 res = (struct usbtmc_header*)rxbuff;
7b575069 285
f7de0831
MG
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
7d42ad7e 307 if ((r - headerlen) > 0) {
f7de0831
MG
308 memcpy(buff + bytes_read, rxbuff + headerlen, r - headerlen);
309 bytes_read += r - headerlen;
310 }
311
7d42ad7e 312 read_size = USBTMC_IN_TRANSFERSIZE;
f7de0831
MG
313 } while(bytes_read < len);
314
315 free(req);
7b575069
MG
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;
58a9e276
MG
328 }
329 return 0;
330}
331
7906b395 332void usbtmc_claim(struct scope *sc)
ad9fbc05 333{
7906b395 334 usb_claim_interface(sc->usb.dev, 0);
ad9fbc05
MG
335}
336
7906b395 337void usbtmc_release(struct scope *sc)
ad9fbc05 338{
7906b395 339 usb_release_interface(sc->usb.dev, 0);
ad9fbc05
MG
340}
341
483a564b 342/* Initialize the scope. */
7906b395 343struct scope* usbtmc_initscope(void) {
58a9e276 344 int r;
80564ddb 345 uint32_t vidpid;
7906b395 346 struct scope *sc;
58a9e276 347
7b575069 348 /* Init libusb */
58a9e276 349 usb_init();
7b575069
MG
350 /* Locate and open the scope */
351 sc = usbtmc_find_scope();
352 if (!sc) {
2999345d 353 return NULL;
58a9e276 354 }
7906b395 355
7906b395 356 usbtmc_claim(sc);
90e416c4 357 sc->usb.cap = usbtmc_get_capabilities(sc);
07a45f03 358 printf("Device status: 0x%x\n", usb488_status(sc));
7b575069
MG
359 /* The following code isn't really necessary, the program works
360 OK without it too. */
80564ddb 361 r=usb_control_msg(sc->usb.dev, 0xC8, 9, 0, 0, (char*)&vidpid, 4, USB_TIMEOUT);
7906b395 362 usbtmc_release(sc);
58a9e276
MG
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 }
80564ddb
MG
369 if (LE32(vidpid)!=0x40005dc) {
370 fprintf(stderr,"Init: buff[%i]=%x\n",r,LE32(vidpid));
58a9e276 371 }
7906b395 372 return sc;
58a9e276 373}
b74fea90 374
7906b395 375void usbtmc_close(struct scope *sc)
b74fea90 376{
7b575069 377 /* Free up and exit */
7906b395 378 usb_close(sc->usb.dev);
b74fea90 379}
Impressum, Datenschutz