add usbtmc_status
[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
7a226bb8 10#define USB_TIMEOUT 50000
165abe62 11
ddf9f28b
MG
12#if BYTE_ORDER == LITTLE_ENDIAN
13#define LE32(x) x
14#elif BYTE_ORDER == BIG_ENDIAN
15#define LE32(x) ((uint32_t)((((uint32_t)x)>>24) | ((((uint32_t)x)>>8) & 0xff00) | ((((uint32_t)x)<<8) & 0xff0000) | (((uint32_t)x)<<24)))
16#else
17#error BYTE_ORDER not defined/known!
18#endif
19
0aa0b761 20#define USB_ERROR(s, x) do { if (x < 0) { fprintf(stderr, "usb %s: %s\n", s, usb_strerror()); usb_reset(sc->usb.dev); return 0; } } while(0)
58a9e276 21
7b575069
MG
22/* This routine locates a scope by VID/PID and returns a struct scope* for it */
23static struct scope* usbtmc_find_scope() {
58a9e276
MG
24 struct usb_bus *bus;
25 struct usb_device *dev=NULL;
7b575069
MG
26 struct usb_dev_handle *devh;
27
28 struct scope *sc;
29
58a9e276
MG
30 usb_find_busses();
31 usb_find_devices();
7b575069 32
58a9e276
MG
33 for (bus=usb_busses; bus; bus=bus->next) {
34 for (dev=bus->devices; dev; dev=dev->next) {
7b575069
MG
35 if (dev->descriptor.idVendor == 0x400 && dev->descriptor.idProduct == 0x5dc) {
36 devh = usb_open(dev);
37 if (devh == NULL)
38 return NULL;
39
40 sc = calloc(1, sizeof(struct scope));
41 if (sc == NULL) {
42 perror("calloc");
43 exit(EXIT_FAILURE);
44 }
45
46 sc->usb.dev = devh;
47
48 /* TODO: FIXME */
49 sc->usb.brokenRigol = 1;
50 sc->usb.ep_bulk_out = 1;
51 sc->usb.ep_bulk_in = 2;
52 sc->usb.wMaxPacketSize_in = 0x40;
53
54 return sc;
58a9e276
MG
55 }
56 }
57 }
7b575069 58
58a9e276
MG
59 return NULL;
60}
61
121b4233
MG
62unsigned char usbtmc_status(struct scope *sc)
63{
64 int r;
65 unsigned char status[3];
66
67 sc->usb.bTag++;
68
69 r = usb_control_msg(sc->usb.dev, 0xA1, 128, (sc->usb.bTag & 0x7f), 0, (char*)status, 3, USB_TIMEOUT);
70 if ((r != 3) || (status[0] != 0x01) || (status[1] != (sc->usb.bTag & 0x7f))) {
71 printf("READ_STATUS_BYTE failed: %d 0x%x 0x%x 0x%x\n", r, status[0], status[1], status[2]);
72 return 0xff;
73 }
74
75 return status[2];
76}
77
7b575069
MG
78/*
79 * Send a scpi-command to the scope. The response goes into the buffer
80 * called resp, with a size of resplen. If resp==NULL, no response
81 * is requested.
82 */
7906b395 83int usbtmc_sendscpi(struct scope *sc, char* cmd,
58a9e276 84 unsigned char *resp, int resplen) {
7b575069 85 int len,r;
58a9e276 86 int cmdlen = strlen(cmd);
7b575069
MG
87 struct usbtmc_header *req;
88
89 sc->usb.bTag++;
90
91 len = sizeof(struct usbtmc_header) + cmdlen;
92 if (len%4)
93 len += 4 - (len%4);
94
95 req = calloc(1, len);
96 if (req == NULL) {
97 perror("calloc");
98 exit(EXIT_FAILURE);
99 }
100
101 req->MsgID = USBTMC_DEV_DEP_MSG_OUT;
102 req->bTag = sc->usb.bTag;
103 req->bTagInverse = ~sc->usb.bTag;
104 req->TransferSize = LE32(cmdlen);
105 req->bmTransferAttributes = USBTMC_TRANSFERATTRIB_EOM;
106 memcpy(req->msg, cmd, cmdlen);
107
108 if (sc->usb.brokenRigol) {
109 r=usb_bulk_write(sc->usb.dev, sc->usb.ep_bulk_out,
110 (char*)req, sizeof(struct usbtmc_header),
111 USB_TIMEOUT);
0aa0b761 112 USB_ERROR("USBTMC_DEV_DEP_MSG_OUT1", r);
7b575069
MG
113
114 r=usb_bulk_write(sc->usb.dev, sc->usb.ep_bulk_out,
115 (char*)&(req->msg), len - sizeof(struct usbtmc_header),
116 USB_TIMEOUT);
0aa0b761 117 USB_ERROR("USBTMC_DEV_DEP_MSG_OUT2", r);
7b575069
MG
118 } else {
119 r=usb_bulk_write(sc->usb.dev, sc->usb.ep_bulk_out,
120 (char*)req, len, USB_TIMEOUT);
0aa0b761 121 USB_ERROR("USBTMC_DEV_DEP_MSG_OUT", r);
7b575069
MG
122 }
123
124 free(req);
125
58a9e276 126 if (resp != NULL && resplen != 0) {
7b575069
MG
127 unsigned char *buff;
128 struct usbtmc_header *res;
129 int bytes_read;
130
131 sc->usb.bTag++;
132
133 req = calloc(1, sizeof(struct usbtmc_header));
134 if (req == NULL) {
135 perror("calloc");
136 exit(EXIT_FAILURE);
137 }
138
139 req->MsgID = USBTMC_REQUEST_DEV_DEP_MSG_IN;
140 req->bTag = sc->usb.bTag;
141 req->bTagInverse = ~sc->usb.bTag;
142 req->TransferSize = LE32(sc->usb.wMaxPacketSize_in);
0aa0b761 143 req->bmTransferAttributes = USBTMC_TRANSFERATTRIB_EOM;
7b575069
MG
144 req->TermChar = 0;
145
146 /* send read command */
147 r=usb_bulk_write(sc->usb.dev, sc->usb.ep_bulk_out,
148 (char*)req, sizeof(struct usbtmc_header), USB_TIMEOUT);
0aa0b761 149 USB_ERROR("USBTMC_REQUEST_DEV_DEP_MSG_IN", r);
7b575069
MG
150
151 free(req);
152
153 buff=malloc(sc->usb.wMaxPacketSize_in);
154 if (buff == NULL) {
155 perror("malloc");
156 exit(EXIT_FAILURE);
58a9e276 157 }
7b575069
MG
158
159 r=usb_bulk_read(sc->usb.dev, sc->usb.ep_bulk_in,
160 (char*)buff, sc->usb.wMaxPacketSize_in, USB_TIMEOUT);
0aa0b761 161 USB_ERROR("USBTMC_DEV_DEP_MSG_IN1", r);
7b575069
MG
162
163 if (r < sizeof(struct usbtmc_header)) {
164 fprintf(stderr, "Short read!\n");
165 return 0;
58a9e276 166 }
7b575069
MG
167
168 bytes_read = r - sizeof(struct usbtmc_header);
169
170 res = (struct usbtmc_header*)buff;
171 len = LE32(res->TransferSize);
172
173 memmove(buff, buff + sizeof(struct usbtmc_header), bytes_read);
174
175 buff = realloc(buff, len);
176 if (buff == NULL) {
177 perror("realloc");
178 exit(EXIT_FAILURE);
179 }
180
181 while ((len - bytes_read) > 0) {
182 r=usb_bulk_read(sc->usb.dev, sc->usb.ep_bulk_in,
183 (char*)buff + bytes_read, len - bytes_read,
184 USB_TIMEOUT);
0aa0b761 185 USB_ERROR("USBTMC_DEV_DEP_MSG_INx", r);
7b575069
MG
186
187 bytes_read += r;
188 }
189
190 /* TODO: FIXME */
191 if (bytes_read > resplen) {
192 fprintf(stderr, "Response buffer to small: %d instead of %d bytes!\n",
193 resplen, bytes_read);
194 bytes_read = resplen;
195 }
196
197 memcpy(resp, buff, bytes_read);
198 free(buff);
199
200 return bytes_read;
58a9e276
MG
201 }
202 return 0;
203}
204
7906b395 205void usbtmc_claim(struct scope *sc)
ad9fbc05 206{
7906b395 207 usb_claim_interface(sc->usb.dev, 0);
ad9fbc05
MG
208}
209
7906b395 210void usbtmc_release(struct scope *sc)
ad9fbc05 211{
7906b395 212 usb_release_interface(sc->usb.dev, 0);
ad9fbc05
MG
213}
214
58a9e276 215//Initialize the scope.
7906b395 216struct scope* usbtmc_initscope(void) {
58a9e276
MG
217 int r;
218 unsigned char buff[10];
7906b395 219 struct scope *sc;
58a9e276 220
7b575069 221 /* Init libusb */
58a9e276 222 usb_init();
7b575069
MG
223 /* Locate and open the scope */
224 sc = usbtmc_find_scope();
225 if (!sc) {
2999345d 226 return NULL;
58a9e276 227 }
7906b395 228
7906b395 229 usbtmc_claim(sc);
7b575069
MG
230 /* The following code isn't really necessary, the program works
231 OK without it too. */
7906b395
MG
232 r=usb_control_msg(sc->usb.dev, 0xC8, 9, 0, 0, (char*)buff, 4, USB_TIMEOUT);
233 usbtmc_release(sc);
58a9e276
MG
234 if (r < 0) {
235 fprintf (stderr, "Error %d sending init message: %s\n",
236 r, strerror (-r));
237 fprintf (stderr, "Do you have permission on the USB device?\n");
238 exit (1);
239 }
7b575069
MG
240 if (LE32((*(uint32_t*)buff))!=0x40005dc) {
241 fprintf(stderr,"Init: buff[%i]=%x\n",r,LE32((*(uint32_t*)buff)));
58a9e276 242 }
7906b395 243 return sc;
58a9e276 244}
b74fea90 245
7906b395 246void usbtmc_close(struct scope *sc)
b74fea90 247{
7b575069 248 /* Free up and exit */
7906b395 249 usb_close(sc->usb.dev);
b74fea90 250}
Impressum, Datenschutz