Statistics
| Branch: | Tag: | Revision:

root / host / lib / transport / libusb1_control.cpp @ 86c86ede

History | View | Annotate | Download (6.6 kB)

1
//
2
// Copyright 2010 Ettus Research LLC
3
//
4
// This program is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
//
17

    
18
#include <uhd/types/usb_descriptor.hpp>
19
#include <uhd/utils/exception.hpp>
20
#include <uhd/transport/usb_control.hpp>
21
#include <libusb-1.0/libusb.h>
22
#include <boost/asio.hpp>
23
#include <iostream>
24

    
25
using namespace uhd::transport;
26

    
27
static int libusb_debug_level = 0;
28
static int libusb_timeout = 0;
29

    
30
/***********************************************************************
31
 * libusb-1.0 implementation of USB control transport
32
 **********************************************************************/
33
class libusb_control_impl : public usb_control {
34
public:
35
    libusb_control_impl(uhd::usb_descriptor_t descriptor);
36
    ~libusb_control_impl();
37

    
38
    size_t submit(boost::uint8_t request_type,
39
                  boost::uint8_t request,
40
                  boost::uint16_t value,
41
                  boost::uint16_t index,
42
                  unsigned char *buff,
43
                  boost::uint16_t length); 
44

    
45
    static uhd::usb_descriptor_t create_descriptor(libusb_device *dev);
46
    static std::string get_serial(libusb_device *dev);
47

    
48
private:
49
    uhd::usb_descriptor_t _descriptor;
50

    
51
    libusb_context       *_ctx;
52
    libusb_device_handle *_dev_handle;
53

    
54
    bool open_device();
55
    bool open_interface();
56
    bool compare_device(libusb_device *dev, uhd::usb_descriptor_t descriptor);
57
};
58

    
59

    
60
libusb_control_impl::libusb_control_impl(uhd::usb_descriptor_t descriptor)
61
 :  _descriptor(descriptor), _ctx(NULL), _dev_handle(NULL)
62
{
63
    if (libusb_init(&_ctx) < 0)
64
        UHD_THROW_SITE_INFO("USB: failed to initialize libusb");
65

    
66
    libusb_set_debug(_ctx, libusb_debug_level);
67

    
68
    if (!open_device())
69
        UHD_THROW_SITE_INFO("USB: failed to open device");
70

    
71
    if (!open_interface())
72
        UHD_THROW_SITE_INFO("USB: failed to open device interface");
73
}
74

    
75

    
76
libusb_control_impl::~libusb_control_impl()
77
{
78
    libusb_close(_dev_handle);
79
    libusb_exit(_ctx);
80
}
81

    
82

    
83
uhd::usb_descriptor_t libusb_control_impl::create_descriptor(libusb_device *dev)
84
{
85
    libusb_device_descriptor desc;
86

    
87
    if (libusb_get_device_descriptor(dev, &desc) < 0)
88
        UHD_THROW_SITE_INFO("USB: failed to get device descriptor");
89

    
90
    uhd::usb_descriptor_t descriptor;
91

    
92
    descriptor.serial      = get_serial(dev); 
93
    descriptor.product_id  = desc.idProduct;   
94
    descriptor.vendor_id   = desc.idVendor;
95
    descriptor.device_addr = libusb_get_device_address(dev);
96

    
97
    return descriptor;
98
}
99

    
100

    
101
std::string libusb_control_impl::get_serial(libusb_device *dev)
102
{
103
    unsigned char buff[32];
104

    
105
    libusb_device_descriptor desc;
106
    if (libusb_get_device_descriptor(dev, &desc) < 0)
107
        return "";
108

    
109
    if (desc.iSerialNumber == 0)
110
        return "";
111

    
112
    //open the device because we have to
113
    libusb_device_handle *dev_handle;
114
    if (libusb_open(dev, &dev_handle) < 0)
115
        return "";
116

    
117
    if (libusb_get_string_descriptor_ascii(dev_handle, desc.iSerialNumber,
118
                                           buff, sizeof(buff)) < 0) {
119
        return "";
120
    }
121

    
122
    libusb_close(dev_handle);
123

    
124
    return (char*) buff;
125
}
126

    
127

    
128
bool libusb_control_impl::open_device()
129
{
130
    libusb_device **list;
131
    libusb_device *dev;
132

    
133
    ssize_t cnt = libusb_get_device_list(_ctx, &list);
134

    
135
    if (cnt < 0)
136
        return cnt;
137

    
138
    ssize_t i = 0;
139
    for (i = 0; i < cnt; i++) {
140
        dev = list[i];
141
        if (compare_device(dev, _descriptor))
142
            goto found;
143
    } 
144
    return false;
145

    
146
found:
147
    int ret;
148
    if ((ret = libusb_open(dev, &_dev_handle)) < 0)
149
        return false;
150
    else 
151
        return true;
152
}
153

    
154

    
155
bool libusb_control_impl::compare_device(libusb_device *dev,
156
                                         uhd::usb_descriptor_t descriptor)
157
{
158
    std::string serial         = descriptor.serial;
159
    boost::uint16_t vendor_id  = descriptor.vendor_id;
160
    boost::uint16_t product_id = descriptor.product_id;
161
    boost::uint8_t device_addr = descriptor.device_addr;
162

    
163
    libusb_device_descriptor libusb_desc;
164
    if (libusb_get_device_descriptor(dev, &libusb_desc) < 0)
165
        return false;
166
    if (serial != get_serial(dev))
167
        return false;
168
    if (vendor_id != libusb_desc.idVendor)
169
        return false;
170
    if (product_id != libusb_desc.idProduct)
171
        return false; 
172
    if (device_addr != libusb_get_device_address(dev))
173
        return false;
174

    
175
    return true;
176
}
177

    
178

    
179
bool libusb_control_impl::open_interface()
180
{
181
    if (libusb_claim_interface(_dev_handle, 0) < 0)
182
        return false;
183
    else
184
        return true;
185
}
186

    
187

    
188
size_t libusb_control_impl::submit(boost::uint8_t request_type,
189
                                   boost::uint8_t request,
190
                                   boost::uint16_t value,
191
                                   boost::uint16_t index, 
192
                                   unsigned char *buff,
193
                                   boost::uint16_t length) 
194
{
195
    return libusb_control_transfer(_dev_handle,
196
                                   request_type,
197
                                   request,
198
                                   value,
199
                                   index,
200
                                   buff, 
201
                                   length, 
202
                                   libusb_timeout);
203
}
204

    
205

    
206
/***********************************************************************
207
 * USB control public make functions
208
 **********************************************************************/
209
usb_control::sptr usb_control::make(uhd::usb_descriptor_t descriptor)
210
{
211
    return sptr(new libusb_control_impl(descriptor));
212
}
213

    
214
uhd::usb_descriptors_t usb_control::get_device_list()
215
{
216
    libusb_device **list;
217
    uhd::usb_descriptors_t descriptors;
218

    
219
    if (libusb_init(NULL) < 0)
220
        UHD_THROW_SITE_INFO("USB: failed to initialize libusb");
221

    
222
    ssize_t cnt = libusb_get_device_list(NULL, &list);
223

    
224
    if (cnt < 0)
225
        UHD_THROW_SITE_INFO("USB: failed to get device list");
226

    
227
    ssize_t i = 0;
228
    for (i = 0; i < cnt; i++) {
229
        libusb_device *dev = list[i];
230
        descriptors.push_back(libusb_control_impl::create_descriptor(dev));
231
    } 
232

    
233
    libusb_free_device_list(list, 0);
234
    libusb_exit(NULL);
235
    return descriptors;
236
}
237

    
238