Intermediate fix to simplify usrp_one_time_init api
[debian/gnuradio] / usrp / host / lib / usrp_prims_libusb1.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2003,2004,2006,2009 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "usrp/usrp_prims.h"
28 #include "usrp_commands.h"
29 #include "usrp_ids.h"
30 #include "usrp_i2c_addr.h"
31 #include "fpga_regs_common.h"
32 #include "fpga_regs_standard.h"
33 #include <libusb-1.0/libusb.h>
34 #include <errno.h>
35 #include <stdio.h>
36 #include <unistd.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <ctype.h>
40 #include <time.h>               // FIXME should check with autoconf (nanosleep)
41 #include <algorithm>
42 #include <ad9862.h>
43 #include <assert.h>
44
45 extern "C" {
46 #include "md5.h"
47 };
48
49 #define VERBOSE 0
50
51 using namespace ad9862;
52
53 static const int FIRMWARE_HASH_SLOT     = 0;
54 static const int FPGA_HASH_SLOT         = 1;
55
56 static const int hash_slot_addr[2] = {
57   USRP_HASH_SLOT_0_ADDR,
58   USRP_HASH_SLOT_1_ADDR
59 };
60
61 static const char *default_firmware_filename = "std.ihx";
62 static const char *default_fpga_filename     = "std_2rxhb_2tx.rbf";
63
64 #include "std_paths.h"
65 #include <stdio.h>
66
67 /*
68 void
69 usrp_one_time_init ()
70 {
71   usrp_one_time_init (false);
72 }
73 */
74
75 void
76 usrp_one_time_init (libusb_context **ctx)
77 {
78   int ret;
79
80   if ((ret = libusb_init (ctx)) < 0)
81     fprintf (stderr, "usrp: libusb_init failed %i\n", ret);
82 }
83
84 /*
85 libusb_context *
86 usrp_one_time_init (bool new_context)
87 {
88
89   static bool first = true;
90   libusb_context *ctx = NULL;
91   int ret;
92
93   // On first call create default context in addition to any new requested
94   // context. The default context is probably useless in this form, but keep
95   // it for now due to possible compatibility reasons.
96
97   if (first) {
98     first = false;
99     if ((ret = libusb_init (NULL)) < 0)
100       fprintf (stderr, "usrp: libusb_init failed %i\n", ret);
101   }
102
103   if (new_context) {
104     if ((ret = libusb_init (&ctx)) < 0)
105       fprintf (stderr, "usrp: libusb_init failed %i\n", ret);
106   }
107
108   return ctx;
109 }
110 */
111
112 void
113 usrp_rescan ()
114 {
115   // nop
116 }
117
118 // ----------------------------------------------------------------
119
120 /*
121  * q must be a real USRP, not an FX2.  Return its hardware rev number.
122  */
123 int
124 usrp_hw_rev (struct libusb_device *q)
125 {
126   struct libusb_device_descriptor desc;
127   if (libusb_get_device_descriptor(q, &desc) < 0)
128     fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n");
129
130   return desc.bcdDevice & 0x00FF;
131 }
132
133 /*
134  * q must be a real USRP, not an FX2.  Return true if it's configured.
135  */
136 bool
137 _usrp_configured_p (struct libusb_device *q)
138 {
139   struct libusb_device_descriptor desc;
140   if (libusb_get_device_descriptor(q, &desc) < 0)
141     fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n");
142
143   return (desc.bcdDevice & 0xFF00) != 0;
144 }
145
146 bool
147 usrp_usrp_p (struct libusb_device *q)
148 {
149   struct libusb_device_descriptor desc;
150   if (libusb_get_device_descriptor(q, &desc) < 0)
151     fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n");
152
153   return (desc.idVendor == USB_VID_FSF
154           && desc.idProduct == USB_PID_FSF_USRP);
155 }
156
157 bool
158 usrp_fx2_p (struct libusb_device *q)
159 {
160   struct libusb_device_descriptor desc;
161   if (libusb_get_device_descriptor(q, &desc) < 0)
162     fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n");
163
164   return (desc.idVendor == USB_VID_CYPRESS
165           && desc.idProduct == USB_PID_CYPRESS_FX2);
166 }
167
168
169 // ----------------------------------------------------------------
170
171 struct libusb_device *
172 usrp_find_device (int nth, bool fx2_ok_p, libusb_context *ctx)
173 {
174   libusb_device **list;
175
176   struct libusb_device *q;
177   int    n_found = 0;
178
179 //usrp_one_time_init (false);
180   assert (ctx != NULL);
181
182   size_t cnt = libusb_get_device_list(ctx, &list);
183   size_t i = 0;
184
185   if (cnt < 0)
186     fprintf(stderr, "usrp: libusb_get_device_list failed %d\n", cnt);
187
188   for (i = 0; i < cnt; i++) {
189     q = list[i];
190     if (usrp_usrp_p (q) || (fx2_ok_p && usrp_fx2_p (q))) {
191         if (n_found == nth)     // return this one
192           return q;
193         n_found++;              // keep looking
194     }
195   }
196
197 /*
198  * The list needs to be freed. Right now just release it if nothing is found.
199  */
200
201   libusb_free_device_list(list, 1);
202
203   return 0;     // not found
204 }
205
206 struct libusb_device_handle *
207 usrp_open_interface (libusb_device *dev, int interface, int altinterface)
208 {
209   struct libusb_device_handle *udh;
210   int ret;
211
212   if (libusb_open (dev, &udh) < 0)
213     return 0;
214
215   if (dev != libusb_get_device (udh)){
216     fprintf (stderr, "%s:%d: internal error!\n", __FILE__, __LINE__);
217     abort ();
218   }
219
220   if ((ret = libusb_claim_interface (udh, interface)) < 0) {
221     fprintf (stderr, "%s:usb_claim_interface: failed interface %d\n", __FUNCTION__,interface);
222     fprintf (stderr, "%d\n", ret);
223     libusb_close (udh);
224     return 0;
225   }
226
227   if ((ret = libusb_set_interface_alt_setting (udh, interface,
228                                                    altinterface)) < 0) {
229     fprintf (stderr, "%s:usb_set_alt_interface: failed\n", __FUNCTION__);
230     fprintf (stderr, "%d\n", ret);
231     libusb_release_interface (udh, interface);
232     libusb_close (udh);
233     return 0;
234   }
235
236   return udh;
237 }
238
239 bool
240 usrp_close_interface (libusb_device_handle *udh)
241 {
242   // returns void
243   libusb_close(udh);
244   return 0;
245 }
246
247 // ----------------------------------------------------------------
248 // write internal ram using Cypress vendor extension
249
250 bool
251 write_internal_ram (struct libusb_device_handle *udh, unsigned char *buf,
252                     int start_addr, size_t len)
253 {
254   int addr;
255   int n;
256   int a;
257   int quanta = MAX_EP0_PKTSIZE;
258
259   for (addr = start_addr; addr < start_addr + (int) len; addr += quanta){
260     n = len + start_addr - addr;
261     if (n > quanta)
262       n = quanta;
263
264     a = libusb_control_transfer (udh, 0x40, 0xA0,
265                          addr, 0, (unsigned char *)(buf + (addr - start_addr)), n, 1000);
266
267     if (a < 0){
268       fprintf(stderr,"write_internal_ram failed: %u\n", a);
269       return false;
270     }
271   }
272   return true;
273 }
274
275 // ----------------------------------------------------------------
276 // write vendor extension command to USRP
277
278 int
279 write_cmd (struct libusb_device_handle *udh,
280            int request, int value, int index,
281            unsigned char *bytes, int len)
282 {
283   int   requesttype = (request & 0x80) ? VRT_VENDOR_IN : VRT_VENDOR_OUT;
284
285   int r = libusb_control_transfer(udh, requesttype, request, value, index,
286                                   (unsigned char *) bytes, len, 1000);
287
288   if (r < 0){
289     // we get EPIPE if the firmware stalls the endpoint.
290     if (r != LIBUSB_ERROR_PIPE) {
291       fprintf (stderr, "libusb_control_transfer failed: %i\n", r);
292     }
293   }
294
295   return r;
296 }
297
298 bool
299 usrp_set_hash (struct libusb_device_handle *udh, int which,
300                const unsigned char hash[USRP_HASH_SIZE])
301 {
302   which &= 1;
303
304   // we use the Cypress firmware down load command to jam it in.
305   int r = libusb_control_transfer (udh, 0x40, 0xa0, hash_slot_addr[which], 0,
306                            (unsigned char *) hash, USRP_HASH_SIZE, 1000);
307   return r == USRP_HASH_SIZE;
308 }
309   
310 bool
311 usrp_get_hash (struct libusb_device_handle *udh, int which,
312                unsigned char hash[USRP_HASH_SIZE])
313 {
314   which &= 1;
315
316   // we use the Cypress firmware upload command to fetch it.
317   int r = libusb_control_transfer (udh, 0xc0, 0xa0, hash_slot_addr[which], 0,
318                            (unsigned char *) hash, USRP_HASH_SIZE, 1000);
319   return r == USRP_HASH_SIZE;
320 }
321
322 bool
323 usrp_write_fpga_reg (struct libusb_device_handle *udh, int reg, int value)
324 {
325   switch (usrp_hw_rev (libusb_get_device (udh))){
326   case 0:                       // not supported ;)
327     abort();
328
329   default:
330     return usrp1_fpga_write (udh, reg, value);
331   }
332 }
333
334 bool
335 usrp_read_fpga_reg (struct libusb_device_handle *udh, int reg, int *value)
336 {
337   switch (usrp_hw_rev (libusb_get_device (udh))){
338   case 0:               // not supported ;)
339     abort();
340
341   default:
342     return usrp1_fpga_read (udh, reg, value);
343   }
344 }
345
346
347 static libusb_device_handle *
348 open_nth_cmd_interface (int nth, libusb_context *ctx)
349 {
350
351   struct libusb_device *udev = usrp_find_device (nth, false, ctx);
352   if (udev == 0){
353     fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth);
354     return 0;
355   }
356
357   struct libusb_device_handle *udh;
358
359   udh = usrp_open_cmd_interface (udev);
360   if (udh == 0){
361     // FIXME this could be because somebody else has it open.
362     // We should delay and retry...
363     fprintf (stderr, "open_nth_cmd_interface: open_cmd_interface failed\n");
364     return 0;
365   }
366
367   return udh;
368 }
369
370 usrp_load_status_t
371 usrp_load_firmware_nth (int nth, const char *filename, bool force, libusb_context *ctx)
372 {
373   struct libusb_device_handle *udh = open_nth_cmd_interface (nth, ctx);
374   if (udh == 0)
375     return ULS_ERROR;
376
377   usrp_load_status_t s = usrp_load_firmware (udh, filename, force);
378   usrp_close_interface (udh);
379
380   switch (s){
381
382   case ULS_ALREADY_LOADED:              // nothing changed...
383     return ULS_ALREADY_LOADED;
384     break;
385
386   case ULS_OK:
387     // we loaded firmware successfully.
388  
389     // It's highly likely that the board will renumerate (simulate a
390     // disconnect/reconnect sequence), invalidating our current
391     // handle.
392
393     // FIXME.  Turn this into a loop that rescans until we refind ourselves
394    
395     struct timespec     t;      // delay for 1 second
396     t.tv_sec = 2;
397     t.tv_nsec = 0;
398     our_nanosleep (&t);
399
400     return ULS_OK;
401
402   default:
403   case ULS_ERROR:               // some kind of problem
404     return ULS_ERROR;
405   }
406 }
407
408 bool
409 usrp_load_standard_bits (int nth, bool force,
410                          const std::string fpga_filename,
411                          const std::string firmware_filename,
412                          libusb_context *ctx)
413 {
414   usrp_load_status_t    s;
415   const char            *filename;
416   const char            *proto_filename;
417   int hw_rev;
418
419   assert (ctx != NULL);
420
421   // first, figure out what hardware rev we're dealing with
422   {
423     struct libusb_device *udev = usrp_find_device (nth, false, ctx);
424     if (udev == 0){
425       fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth);
426       return false;
427     }
428     hw_rev = usrp_hw_rev (udev);
429   }
430
431   // start by loading the firmware
432
433   proto_filename = get_proto_filename(firmware_filename, "USRP_FIRMWARE",
434                                       default_firmware_filename);
435   filename = find_file(proto_filename, hw_rev);
436   if (filename == 0){
437     fprintf (stderr, "Can't find firmware: %s\n", proto_filename);
438     return false;
439   }
440   s = usrp_load_firmware_nth (nth, filename, force, ctx);
441   load_status_msg (s, "firmware", filename);
442
443   if (s == ULS_ERROR)
444     return false;
445
446   // if we actually loaded firmware, we must reload fpga ...
447   if (s == ULS_OK)
448     force = true;
449
450   // now move on to the fpga configuration bitstream
451
452   proto_filename = get_proto_filename(fpga_filename, "USRP_FPGA",
453                                       default_fpga_filename);
454   filename = find_file (proto_filename, hw_rev);
455   if (filename == 0){
456     fprintf (stderr, "Can't find fpga bitstream: %s\n", proto_filename);
457     return false;
458   }
459   struct libusb_device_handle *udh = open_nth_cmd_interface (nth, ctx);
460   if (udh == 0)
461     return false;
462   
463   s = usrp_load_fpga (udh, filename, force);
464   usrp_close_interface (udh);
465   load_status_msg (s, "fpga bitstream", filename);
466
467   if (s == ULS_ERROR)
468     return false;
469
470   return true;
471 }
472
473 void
474 power_down_9862s (struct libusb_device_handle *udh)
475 {
476   static const unsigned char regs[] = {
477     REG_RX_PWR_DN,      0x01,                   // everything
478     REG_TX_PWR_DN,      0x0f,                   // pwr dn digital and analog_both
479     REG_TX_MODULATOR,   0x00                    // coarse & fine modulators disabled
480   };
481
482   switch (usrp_hw_rev (libusb_get_device (udh))){
483   case 0:
484     break;
485
486   default:
487     usrp_9862_write_many_all (udh, regs, sizeof (regs));
488     break;
489   }
490 }
491
492
493 // ----------------------------------------------------------------
494
495 std::string
496 usrp_serial_number(struct libusb_device_handle *udh)
497 {
498   struct libusb_device_descriptor desc;
499   if (libusb_get_device_descriptor(libusb_get_device(udh), &desc) < 0)
500     fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n");
501
502   unsigned char iserial = desc.iSerialNumber;
503   if (iserial == 0)
504     return "";
505
506   unsigned char buf[1024];
507   if (libusb_get_string_descriptor_ascii(udh, iserial, buf, sizeof(buf)) < 0)
508     return "";
509
510   return (char*) buf;
511 }