usrp: Reorg of libusb error reporting
[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_primsi.h"
28 #include "usrp_commands.h"
29 #include <libusb-1.0/libusb.h>
30 #include <errno.h>
31 #include <stdio.h>
32 #include <unistd.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include <ad9862.h>
37 #include <assert.h>
38
39 extern "C" {
40 #include "md5.h"
41 };
42
43 using namespace ad9862;
44
45 /*
46  * libusb 0.12 / 1.0 compatibility
47  */
48
49 static const char *
50 _get_usb_error_str (int usb_err)
51 {
52   switch (usb_err) {
53   case LIBUSB_SUCCESS:
54     return "Success (no error)";
55   case LIBUSB_ERROR_IO:
56     return "Input/output error";
57   case LIBUSB_ERROR_INVALID_PARAM:
58     return "Invalid parameter";
59   case LIBUSB_ERROR_ACCESS:
60     return "Access denied (insufficient permissions";
61   case LIBUSB_ERROR_NO_DEVICE:
62     return "No such device (it may have been disconnected)";
63   case LIBUSB_ERROR_NOT_FOUND:
64     return "Entity not found";
65   case LIBUSB_ERROR_BUSY:
66     return "Resource busy";
67   case LIBUSB_ERROR_TIMEOUT:
68     return "Operation timed out";
69   case LIBUSB_ERROR_OVERFLOW:
70     return "Overflow";
71   case LIBUSB_ERROR_PIPE:
72     return "Pipe error";
73    case LIBUSB_ERROR_INTERRUPTED:
74     return "System call interrupted (perhaps due to signal)";
75   case LIBUSB_ERROR_NO_MEM:
76     return "Insufficient memory";
77   case LIBUSB_ERROR_NOT_SUPPORTED:
78     return "Operation not supported or unimplemented on this platform";
79   case LIBUSB_ERROR_OTHER:
80     return "Unknown error";
81   }
82
83   return "Unknown error";
84 }
85
86 struct libusb_device *
87 _get_usb_device (struct libusb_device_handle *udh)
88 {
89   return libusb_get_device (udh);
90 }
91
92 struct libusb_device_descriptor
93 _get_usb_device_descriptor(struct libusb_device *q)
94 {
95   int ret;
96   struct libusb_device_descriptor desc;
97
98   ret = libusb_get_device_descriptor(q, &desc);
99
100   if (ret < 0) {
101     fprintf (stderr, "usrp: libusb_get_device_descriptor failed: %s\n",
102              _get_usb_error_str(ret));
103   }
104   return desc;
105 }
106
107 int
108 _get_usb_string_descriptor (struct libusb_device_handle *udh, int index,
109                             unsigned char* data, int length)
110 {
111   int ret;
112   ret = libusb_get_string_descriptor_ascii (udh, (uint8_t) index, data, length);
113
114   if (ret < 0) {
115     fprintf (stderr, "usrp: libusb_get_string_descriptor_ascii failed: %s\n",
116              _get_usb_error_str(ret));
117   }
118   return ret;
119 }
120
121 int
122 _usb_control_transfer (struct libusb_device_handle *udh, int request_type,
123                        int request, int value, int index,
124                        unsigned char *data, int length, unsigned int timeout)
125 {
126   int ret;
127   ret = libusb_control_transfer (udh, request_type, request, value, index,
128                                  data, length, timeout);
129   if (ret < 0) {
130     fprintf (stderr, "usrp: libusb_control_transfer failed: %s\n",
131              _get_usb_error_str(ret));
132   }
133   return ret;
134 }
135
136 // ----------------------------------------------------------------
137
138
139 void
140 usrp_one_time_init (libusb_context **ctx)
141 {
142   int ret;
143
144   if ((ret = libusb_init (ctx)) < 0)
145     fprintf (stderr, "usrp: libusb_init failed: %s\n", _get_usb_error_str(ret));
146 }
147
148 void
149 usrp_rescan ()
150 {
151   // nop
152 }
153
154
155 struct libusb_device *
156 usrp_find_device (int nth, bool fx2_ok_p, libusb_context *ctx)
157 {
158   libusb_device **list;
159
160   struct libusb_device *q;
161   int    n_found = 0;
162
163   // Make sure not operating on default context. There are cases where operating
164   // with a single global (NULL) context may be preferable, so this check can be
165   // skipped if you know what you're doing.
166   assert (ctx != NULL);
167
168   size_t cnt = libusb_get_device_list(ctx, &list);
169   size_t i = 0;
170
171   if (cnt < 0)
172     fprintf(stderr, "usrp: libusb_get_device_list failed: %s\n",
173             _get_usb_error_str(cnt));
174
175   for (i = 0; i < cnt; i++) {
176     q = list[i];
177     if (usrp_usrp_p (q) || (fx2_ok_p && usrp_fx2_p (q))) {
178         if (n_found == nth)     // return this one
179           return q;
180         n_found++;              // keep looking
181     }
182   }
183
184   // The list needs to be freed. Right now just release it if nothing is found.
185   libusb_free_device_list(list, 1);
186
187   return 0;     // not found
188 }
189
190 struct libusb_device_handle *
191 usrp_open_interface (libusb_device *dev, int interface, int altinterface)
192 {
193   libusb_device_handle *udh;
194   int ret;
195
196   if (libusb_open (dev, &udh) < 0)
197     return 0;
198
199   if (dev != libusb_get_device (udh)){
200     fprintf (stderr, "%s:%d: internal error!\n", __FILE__, __LINE__);
201     abort ();
202   }
203
204   if ((ret = libusb_claim_interface (udh, interface)) < 0) {
205     fprintf (stderr, "%s:usb_claim_interface: failed interface %d\n",
206              __FUNCTION__, interface);
207     fprintf (stderr, "%s\n", _get_usb_error_str(ret));
208     libusb_close (udh);
209     return 0;
210   }
211
212   if ((ret = libusb_set_interface_alt_setting (udh, interface,
213                                                altinterface)) < 0) {
214     fprintf (stderr, "%s:usb_set_alt_interface: failed\n", __FUNCTION__);
215     fprintf (stderr, "%s\n", _get_usb_error_str(ret));
216     libusb_release_interface (udh, interface);
217     libusb_close (udh);
218     return 0;
219   }
220
221   return udh;
222 }
223
224 bool
225 usrp_close_interface (libusb_device_handle *udh)
226 {
227   // returns void
228   libusb_close(udh);
229   return 0;
230 }
231
232
233 // ----------------------------------------------------------------
234 // write vendor extension command to USRP
235
236
237 int
238 write_cmd (struct libusb_device_handle *udh,
239            int request, int value, int index,
240            unsigned char *bytes, int len)
241 {
242   int requesttype = (request & 0x80) ? VRT_VENDOR_IN : VRT_VENDOR_OUT;
243
244   int ret = libusb_control_transfer(udh, requesttype, request, value, index,
245                                     bytes, len, 1000);
246
247   if (ret < 0) {
248     // we get EPIPE if the firmware stalls the endpoint.
249     if (ret != LIBUSB_ERROR_PIPE) {
250       fprintf (stderr, "usrp: libusb_control_transfer failed: %s\n",
251                _get_usb_error_str(ret));
252       fprintf (stderr, "usrp: write_cmd failed\n");
253     }
254   }
255
256   return ret;
257 }
258