]> git.zerfleddert.de Git - rigol/blob - rigol.c
don't continue when malloc bails out
[rigol] / rigol.c
1 /*
2 Sprite_tms hack to communicate with a Rigol DS1000-series scope using Linux.
3 This code is licensed under the GPL V3.
4
5 Warning: This code can in theory fubar the communications with the scope to a
6 point where the Linux USB-stack seems to get confused. Do a
7 rmmod uhci_hcd; modprobe uhci_hcd
8 (or alternately: use ohci_hcd) if that happens and you should be fine.
9 */
10
11 #include <usb.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <sys/stat.h>
16 #include <sys/types.h>
17 #include <sys/wait.h>
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <signal.h>
21 #include <time.h>
22
23 #include <readline/readline.h>
24 #include <readline/history.h>
25
26 #include "png.h"
27
28
29 //This routine locates a scope by VID/PID and returns an opened handle to it.
30 usb_dev_handle *find_scope() {
31 struct usb_bus *bus;
32 struct usb_device *dev=NULL;
33 usb_find_busses();
34 usb_find_devices();
35 for (bus=usb_busses; bus; bus=bus->next) {
36 for (dev=bus->devices; dev; dev=dev->next) {
37 //fprintf(stderr,"Prod/dev: %04X:%04X\n",dev->descriptor.idVendor,dev->descriptor.idProduct);
38 if (dev->descriptor.idVendor==0x400 && dev->descriptor.idProduct==0x5dc) {
39 return usb_open(dev);
40 }
41 }
42 }
43 return NULL;
44 }
45
46 //Helper-routine: Convert a little-endian 4-byte word to an int
47 void int2chars(unsigned char *buff,unsigned int a) {
48 buff[3]=(a>>24)&0xff;
49 buff[2]=(a>>16)&0xff;
50 buff[1]=(a>>8)&0xff;
51 buff[0]=(a)&0xff;
52 }
53
54 //Helper-routine: Convert an int to little-endian 4-byte word
55 unsigned int chars2int(unsigned char *buff) {
56 unsigned int a;
57 a=buff[3]<<24;
58 a+=buff[2]<<16;
59 a+=buff[1]<<8;
60 a+=buff[0];
61 return a;
62 }
63
64 #define MIN(a,b) (((a)<(b))?(a):(b))
65
66 inline char printable (char ch)
67 {
68 if (ch < ' ') return '.';
69 if (ch > '~') return '.';
70 return ch;
71 }
72
73 //Debugging: Print a buffers contents in hex
74 void printb (unsigned char *pkt, int len)
75 {
76 int i, j;
77
78 for (i=0;i<len;i+= 16) {
79 printf ("%04x: ", i);
80 for (j=0;j < MIN(len-i, 16);j++) {
81 printf (" %02x", pkt[i+j]);
82 if (j == 7) printf (" ");
83 }
84 if (j < 7) printf (" ");
85 for (;j<17;j++)
86 printf (" ");
87
88 for (j=0;j < MIN(len-i, 16);j++) {
89 printf ("%c", printable (pkt[i+j]));
90 }
91 printf ("\n");
92 }
93 }
94
95 //Send a scpi-command to the scope. The response goes into the buffer
96 //called resp, with a size of resplen. If resp==NULL, no response
97 //is requested.
98 int sendscpi(usb_dev_handle *dev, char* cmd,
99 unsigned char *resp, int resplen) {
100 unsigned char *buff;
101 int len,r,i;
102 int cmdlen = strlen(cmd);
103 static unsigned char seq=0;
104
105
106 buff=malloc(0x40);
107 seq++;
108 buff[0]=1; //func
109 buff[1]=seq; buff[2]=~seq; //nseq
110 buff[3]=0;
111 int2chars(buff+4, cmdlen);
112 buff[8]=1;
113 buff[9]=0x37;
114 buff[10]=0x39;
115 buff[11]=0x39;
116 //fprintf(stderr,"Writing header len=%d\n", cmdlen);
117 //printb(buff,12);
118 r=usb_bulk_write(dev, 1, (char*)buff, 12, 1000);
119 //fprintf(stderr,"%i bytes written. Writing cmd\n",r);
120 //printb(cmd, cmdlen);
121 r=usb_bulk_write(dev, 1, cmd, cmdlen, 1000);
122 //fprintf(stderr,"%i bytes written.\n",r);
123 if (resp != NULL && resplen != 0) {
124 //send read command
125 buff[0]=2; //func
126 seq++;
127 buff[1]=seq; buff[2]=~seq; //nseq
128 int2chars(buff+4,0x40);
129 buff[8]=1;
130 buff[9]=0xA;
131 buff[10]=0;
132 buff[11]=0;
133 //fprintf(stderr,"Writing resp req header\n");
134 //printb(buff,12);
135 r=usb_bulk_write(dev, 1, (char*)buff, 12, 1000);
136 //fprintf(stderr,"%i bytes written. Reading response hdr\n",r);
137 r=usb_bulk_read(dev, 2, (char*)buff, 0x40, 1000);
138 //printb(buff,r);
139 len=chars2int(buff+4);
140 //fprintf(stderr,"%i bytes read. Resplen=%i\n",r,len);
141 for (i=0; i<(r-12); i++) {
142 if (i<resplen) resp[i] = buff[i+12];
143 }
144 //printb(resp,r-12);
145 if (len > 0x40-12) {
146 //fprintf(stderr," Reading response:\n");
147 if (resplen<len) len=resplen;
148 r=usb_bulk_read(dev, 2, (char*)resp+(0x40-12), len-(0x40-12),1000);
149 //fprintf(stderr,"%i bytes read, wanted %i.\n", r, len-(0x40-12));
150 return r+(0x40-12);
151 }
152 return len;
153 }
154 return 0;
155 }
156
157 //Initialize the scope.
158 void initscope(usb_dev_handle *dev) {
159 int r;
160 unsigned char buff[10];
161 usb_claim_interface(dev,0);
162 //The following code isn't really necessary, the program works
163 //OK without it too.
164 r=usb_control_msg(dev, 0xC8, 9, 0, 0, (char*)buff, 4, 1000);
165 if (r < 0) {
166 fprintf (stderr, "Error %d sending init message: %s\n",
167 r, strerror (-r));
168 fprintf (stderr, "Do you have permission on the USB device?\n");
169 exit (1);
170 }
171 if (chars2int(buff)!=0x40004dc) {
172 fprintf(stderr,"Init: buff[%i]=%x\n",r,chars2int(buff));
173 }
174 return;
175 }
176
177 #define HAVE_READLINE
178 #ifndef HAVE_READLINE
179
180 char *readline (prompt)
181 {
182 char *buf;
183
184 printf (prompt);
185 fflush (stdout);
186 buf = malloc (1024);
187
188 if (fgets (buf, 1023, stdin) == NULL) {
189 free (buf);
190 return NULL;
191 }
192 l = strlen (buf);
193 if (buf[l-1] == '\n') {
194 buf[l] = 0;
195 }
196 return buf;
197 }
198
199 void add_history (char *buf)
200 {
201 }
202 #endif
203
204
205 void do_plot (struct usb_dev_handle *sc)
206 {
207 unsigned char ch1[1024], ch2[1024];
208 int i, l;
209
210 static FILE *gnuplot=NULL;
211 FILE *fp;
212
213 l = sendscpi(sc, ":WAV:DATA? CHANEL1", ch1, 1024);
214
215 if (l != 1024) {
216 printf ("hmm. didnt' get 1024 bytes. \n");
217 }
218
219 l = sendscpi(sc, ":WAV:DATA? CHANNEL2", ch2, 1024);
220
221 if (l != 1024) {
222 printf ("hmm. didnt' get 1024 bytes. \n");
223 }
224
225 if (!gnuplot) {
226 gnuplot = popen ("gnuplot", "w");
227 }
228
229 fp = fopen ("temp.dat", "w");
230 for (i=0xd4;i<0x32c;i++)
231 //for (i=0;i<0x400;i++)
232 fprintf (fp, "%d %d\n", 255 - ch1[i], 255 - ch2[i]);
233 fclose (fp);
234
235 fprintf (gnuplot, "plot 'temp.dat' using 1 with lines, 'temp.dat' using 2 with lines\n");
236 fflush (gnuplot);
237 }
238
239
240 #define ERROR -1e100
241
242 double get_float_from_scope (struct usb_dev_handle *sc, char *var)
243 {
244 unsigned char buf[1024];
245 double temp;
246 int l;
247
248 l = sendscpi(sc, var, buf, 1024);
249 if (l > 0) {
250 sscanf ((char*)buf, "%lf", &temp);
251 return temp;
252 }
253 return ERROR;
254 }
255
256
257 void do_get_buf (struct usb_dev_handle *sc)
258 {
259 FILE *fp;
260 int i, j, l, bp;
261 char buf[1024];
262 unsigned char ch1[1024];
263 unsigned char data[512*1024];
264 double sampfreq;
265
266 sendscpi (sc, ":STOP", NULL, 0);
267
268 sampfreq = get_float_from_scope (sc, ":ACQ:SAMP?");
269
270 printf ("Got sampling freq: %g\n", sampfreq);
271
272 sprintf (buf, ":TIM:SCAL %.15f", 50 / sampfreq);
273 printf ("sending scale cmd: %s\n", buf);
274 sendscpi (sc, buf, NULL, 0);
275
276 sleep (1);
277
278 bp=0;
279 for (i=-254*1024;i< 254*1024;i += 600) {
280 sprintf (buf, ":TIM:OFFSET %.15f", i / sampfreq);
281 printf ("Sending offset cmd: %s\n", buf);
282 sendscpi (sc, buf, NULL, 0);
283
284 l = sendscpi(sc, ":WAV:DATA? CHANEL1", ch1, 1024);
285
286 if (l != 1024) {
287 printf ("hmm. didnt' get 1024 bytes. \n");
288 }
289
290 for (j=0;j<600;j++)
291 data[bp++] = ch1[j+0xd4];
292 }
293 printf ("Got %d bytes of data. \n", bp);
294
295 fp = fopen ("ch1.dump", "w");
296 fwrite (data, bp, 1, fp);
297 fclose (fp);
298
299 sendscpi (sc, ":TIM:OFFSET 0", NULL, 0);
300 }
301
302 void do_get_screen(struct usb_dev_handle *sc)
303 {
304 unsigned char screen[320*234];
305 time_t lt;
306 char filename[256];
307 unsigned char *png;
308 int imglen;
309 int ret;
310 int l;
311 int fd;
312 pid_t display;
313
314 /* Hide "RMT" from screen */
315 l = sendscpi(sc, ":KEY:LOCK DISABLE", NULL, 0);
316 usleep(20000);
317
318 l = sendscpi(sc, ":LCD:DATA?", screen, sizeof(screen));
319
320 if (l != sizeof(screen)) {
321 printf ("hmm. didnt' get %d bytes, but %d\n\n", sizeof(screen), l);
322 }
323
324 png = lcd2png(screen, &imglen);
325
326 lt = time(NULL);
327 strftime(filename, sizeof(filename), "screen_%Y%m%d-%H%M%S.png", localtime(&lt));
328 fd=open(filename, O_CREAT|O_WRONLY, 0644);
329 if (fd == -1) {
330 perror("open");
331 exit(EXIT_FAILURE);
332 }
333
334 while(imglen > 0) {
335 ret = write(fd, png, imglen);
336 if (ret == -1) {
337 perror("write");
338 exit(EXIT_FAILURE);
339 }
340 imglen -= ret;
341 }
342 close(fd);
343 free(png);
344
345 printf("Waveform saved as %s\n", filename);
346
347 display = fork();
348 switch(display) {
349 case 0:
350 execlp("display", "display", filename, NULL);
351 exit(0);
352 break;
353 case -1:
354 perror("fork");
355 break;
356 default:
357 break;
358 }
359 }
360
361 void child_reaper(int sig)
362 {
363 pid_t child;
364
365 do {
366 child = waitpid(-1, NULL, WNOHANG);
367 } while(child > 0);
368
369 }
370
371 int main(int argc, char **argv)
372 {
373 struct usb_dev_handle *sc;
374 char *scpi;
375 unsigned char *buff;
376 int l;
377 struct sigaction act;
378
379 //Init libusb
380 usb_init();
381 //Locate and open the scope
382 sc=find_scope();
383 if (!sc) {
384 printf("No scope found.\n");
385 exit(1);
386 } else {
387 printf("Scope found.\n");
388 }
389 //Initialize scope
390 initscope(sc);
391 buff = malloc (1024*1024);
392 if (buff == NULL) {
393 perror("malloc");
394 exit(EXIT_FAILURE);
395 }
396
397 bzero(&act, sizeof(act));
398 act.sa_handler = child_reaper;
399 act.sa_flags = SA_NOCLDSTOP|SA_RESTART;
400 if (sigaction(SIGCHLD, &act, NULL) == -1) {
401 perror("sigaction");
402 exit(EXIT_FAILURE);
403 }
404
405 while (1) {
406 scpi = readline ("> ");
407
408 if (!scpi) break;
409 if (strlen (scpi) == 0) {
410 free (scpi);
411 continue;
412 }
413
414 add_history (scpi);
415
416 if (strncmp (scpi, "quit", 4) == 0) break;
417 if (strncmp (scpi, "plot", 4) == 0) {
418 do_plot (sc);
419 continue;
420 }
421 if (strncmp (scpi, "databuf", 7) == 0) {
422 do_get_buf (sc);
423 continue;
424 }
425 if (strncmp (scpi, "screen", 6) == 0) {
426 do_get_screen (sc);
427 continue;
428 }
429
430 l = strlen (scpi);
431 //printf ("got buf(%d): ", l);
432 //printb (scpi, l+2);
433 if (strchr (scpi, '?')) {
434 //printf ("Expecting reply\n");
435 l = sendscpi(sc, scpi, buff, 1024*1024);
436 //printf ("Got replylen = %d.\n", l);
437 buff[l] = 0; //zero-terminate
438 printb (buff, l);
439 } else {
440 //printf ("No reply expected\n");
441 l=sendscpi(sc,scpi,NULL,0);
442 }
443 free (scpi);
444 }
445 //Disable keylock, so the user doesn't have to press the 'force'-button
446 l=sendscpi(sc, ":KEY:LOCK DISABLE",NULL,0);
447
448 //Free up and exit
449 usb_release_interface(sc,0);
450 usb_close(sc);
451 return 0;
452 }
Impressum, Datenschutz