- fixed compile error on g++ 3.3 systems (missing stdint.h in probe.h)
[barry.git] / src / usbwrap.cc
blob5277255e71a16a000a31c5a4b4bb3eb26a4e5b74
1 ///
2 /// \file usbwrap.cc
3 /// USB API wrapper
4 ///
6 /*
7 Copyright (C) 2005-2006, Chris Frey
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
23 #include "usbwrap.h"
24 #include "data.h"
25 #include "error.h"
26 #include "debug.h"
28 #include <iomanip>
29 #include <sstream>
31 #define __DEBUG_MODE__
32 #include "debug.h"
34 namespace Usb {
36 ///////////////////////////////////////////////////////////////////////////////
37 // Match
39 Match::Match(int vendor, int product)
40 : m_busses(0),
41 m_dev(0),
42 m_vendor(vendor),
43 m_product(product)
45 usb_find_busses();
46 usb_find_devices();
47 m_busses = usb_get_busses();
50 Match::~Match()
54 bool Match::next_device(Usb::DeviceIDType *devid)
56 for( ; m_busses; m_busses = m_busses->next ) {
58 if( !m_dev )
59 m_dev = m_busses->devices;
61 for( ; m_dev; m_dev = m_dev->next ) {
62 // is there a match?
63 if( m_dev->descriptor.idVendor == m_vendor &&
64 m_dev->descriptor.idProduct == m_product ) {
65 // found!
66 *devid = m_dev;
68 // advance for next time
69 m_dev = m_dev->next;
70 if( !m_dev )
71 m_busses = m_busses->next;
73 // done
74 return true;
78 return false;
82 ///////////////////////////////////////////////////////////////////////////////
83 // Device
85 Device::Device(Usb::DeviceIDType id)
86 : m_id(id),
87 m_timeout(USBWRAP_DEFAULT_TIMEOUT)
89 m_handle = usb_open(id);
90 if( !m_handle )
91 throw UsbError("open failed");
94 Device::~Device()
96 usb_close(m_handle);
99 bool Device::SetConfiguration(unsigned char cfg)
101 m_lasterror = usb_set_configuration(m_handle, cfg);
102 return m_lasterror >= 0;
105 bool Device::ClearHalt(int ep)
107 m_lasterror = usb_clear_halt(m_handle, ep);
108 return m_lasterror >= 0;
111 bool Device::Reset()
113 m_lasterror = usb_reset(m_handle);
114 return m_lasterror == 0;
117 bool Device::BulkRead(int ep, Data &data)
119 m_lasterror = usb_bulk_read(m_handle, ep,
120 (char*) data.GetBuffer(), data.GetBufSize(), m_timeout);
121 if( m_lasterror < 0 )
122 throw UsbError("Error in usb_bulk_read");
123 return m_lasterror >= 0;
126 bool Device::BulkWrite(int ep, const Data &data)
128 ddout("BulkWrite to endpoint " << ep << ":\n" << data);
129 m_lasterror = usb_bulk_write(m_handle, ep,
130 (char*) data.GetData(), data.GetSize(), m_timeout);
131 if( m_lasterror < 0 )
132 throw UsbError("Error in usb_bulk_write");
133 return m_lasterror >= 0;
136 bool Device::BulkWrite(int ep, const void *data, size_t size)
138 #ifdef __DEBUG_MODE__
139 Data dump(data, size);
140 ddout("BulkWrite to endpoint " << ep << ":\n" << dump);
141 #endif
143 m_lasterror = usb_bulk_write(m_handle, ep,
144 (char*) data, size, m_timeout);
145 if( m_lasterror < 0 )
146 throw UsbError("Error in usb_bulk_write");
147 return m_lasterror >= 0;
150 bool Device::InterruptRead(int ep, Data &data)
152 m_lasterror = usb_interrupt_read(m_handle, ep,
153 (char*) data.GetBuffer(), data.GetBufSize(), m_timeout);
154 if( m_lasterror < 0 )
155 throw UsbError("Error in usb_interrupt_read");
156 return m_lasterror >= 0;
159 bool Device::InterruptWrite(int ep, const Data &data)
161 ddout("InterruptWrite to endpoint " << ep << ":\n" << data);
162 m_lasterror = usb_interrupt_write(m_handle, ep,
163 (char*) data.GetData(), data.GetSize(), m_timeout);
164 if( m_lasterror < 0 )
165 throw UsbError("Error in usb_interrupt_write");
166 return m_lasterror >= 0;
171 ///////////////////////////////////////////////////////////////////////////////
172 // EndpointDiscovery
174 bool EndpointDiscovery::Discover(struct usb_interface_descriptor *interface, int epcount)
176 // start fresh
177 clear();
178 m_valid = false;
180 EndpointPair pair;
182 if( !interface || !interface->endpoint )
183 return false;
185 for( int i = 0; i < epcount; i++ ) {
186 // load descriptor
187 usb_endpoint_descriptor desc;
188 desc = interface->endpoint[i];
189 dout(" endpoint_desc #" << i << " loaded"
190 << "\nbLength: " << (unsigned ) desc.bLength
191 << "\nbDescriptorType: " << (unsigned ) desc.bDescriptorType
192 << "\nbEndpointAddress: " << (unsigned ) desc.bEndpointAddress
193 << "\nbmAttributes: " << (unsigned ) desc.bmAttributes
194 << "\nwMaxPacketSize: " << (unsigned ) desc.wMaxPacketSize
195 << "\nbInterval: " << (unsigned ) desc.bInterval
196 << "\nbRefresh: " << (unsigned ) desc.bRefresh
197 << "\nbSynchAddress: " << (unsigned ) desc.bSynchAddress
198 << "\n"
201 // add to the map
202 (*this)[desc.bEndpointAddress] = desc;
203 dout(" endpoint added to map with bEndpointAddress: " << (unsigned int)desc.bEndpointAddress);
205 // parse the endpoint into read/write sets, if possible,
206 // going in discovery order...
207 // Assumptions:
208 // - endpoints of related utility will be grouped
209 // - endpoints with same type will be grouped
210 // - endpoints that do not meet the above assumptions
211 // do not belong in a pair
212 unsigned char type = desc.bmAttributes & USB_ENDPOINT_TYPE_MASK;
213 if( desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK ) {
214 // read endpoint
215 pair.read = desc.bEndpointAddress;
216 dout(" pair.read = " << (unsigned int)pair.read);
217 if( pair.IsTypeSet() && pair.type != type ) {
218 // if type is already set, we must start over
219 pair.write = 0;
222 else {
223 // write endpoint
224 pair.write = desc.bEndpointAddress;
225 dout(" pair.write = " << (unsigned int)pair.write);
226 if( pair.IsTypeSet() && pair.type != type ) {
227 // if type is already set, we must start over
228 pair.read = 0;
231 // save the type last
232 pair.type = type;
233 dout(" pair.type = " << (unsigned int)pair.type);
235 // if pair is complete, add to array
236 if( pair.IsComplete() ) {
237 m_endpoints.push_back(pair);
238 dout(" pair added! ("
239 << "read: " << (unsigned int)pair.read << ","
240 << "write: " << (unsigned int)pair.write << ","
241 << "type: " << (unsigned int)pair.type << ")");
242 pair = EndpointPair(); // clear
246 return m_valid = true;
250 ///////////////////////////////////////////////////////////////////////////////
251 // InterfaceDiscovery
253 bool InterfaceDiscovery::DiscoverInterface(struct usb_interface *interface)
255 if( !interface->altsetting )
256 return false;
258 for( int i = 0; i < interface->num_altsetting; i++ ) {
259 // load descriptor
260 InterfaceDesc desc;
261 desc.desc = interface->altsetting[i];
262 dout(" interface_desc #" << i << " loaded"
263 << "\nbLength: " << (unsigned) desc.desc.bLength
264 << "\nbDescriptorType: " << (unsigned) desc.desc.bDescriptorType
265 << "\nbInterfaceNumber: " << (unsigned) desc.desc.bInterfaceNumber
266 << "\nbAlternateSetting: " << (unsigned) desc.desc.bAlternateSetting
267 << "\nbNumEndpoints: " << (unsigned) desc.desc.bNumEndpoints
268 << "\nbInterfaceClass: " << (unsigned) desc.desc.bInterfaceClass
269 << "\nbInterfaceSubClass: " << (unsigned) desc.desc.bInterfaceSubClass
270 << "\nbInterfaceProtocol: " << (unsigned) desc.desc.bInterfaceProtocol
271 << "\niInterface: " << (unsigned) desc.desc.iInterface
272 << "\n"
275 // load all endpoints on this interface
276 if( !desc.endpoints.Discover(&desc.desc, desc.desc.bNumEndpoints) )
277 return false;
279 // add to the map
280 (*this)[desc.desc.bInterfaceNumber] = desc;
281 dout(" interface added to map with bInterfaceNumber: " << (unsigned int)desc.desc.bInterfaceNumber);
283 return true;
286 bool InterfaceDiscovery::Discover(Usb::DeviceIDType devid, int cfgidx, int ifcount)
288 // start fresh
289 clear();
290 m_valid = false;
292 if( !devid || !devid->config || !devid->config[cfgidx].interface )
293 return false;
295 for( int i = 0; i < ifcount; i++ ) {
296 if( !DiscoverInterface(&devid->config[cfgidx].interface[i]) )
297 return false;
300 return m_valid = true;
304 ///////////////////////////////////////////////////////////////////////////////
305 // ConfigDiscovery
307 bool ConfigDiscovery::Discover(Usb::DeviceIDType devid, int cfgcount)
309 // start fresh
310 clear();
311 m_valid = false;
313 for( int i = 0; i < cfgcount; i++ ) {
314 // load descriptor
315 ConfigDesc desc;
316 if( !devid || !devid->config )
317 return false;
318 desc.desc = devid->config[i];
319 dout(" config_desc #" << i << " loaded"
320 << "\nbLength: " << (unsigned int) desc.desc.bLength
321 << "\nbDescriptorType: " << (unsigned int) desc.desc.bDescriptorType
322 << "\nwTotalLength: " << (unsigned int) desc.desc.wTotalLength
323 << "\nbNumInterfaces: " << (unsigned int) desc.desc.bNumInterfaces
324 << "\nbConfigurationValue: " << (unsigned int) desc.desc.bConfigurationValue
325 << "\niConfiguration: " << (unsigned int) desc.desc.iConfiguration
326 << "\nbmAttributes: " << (unsigned int) desc.desc.bmAttributes
327 << "\nMaxPower: " << (unsigned int) desc.desc.MaxPower
328 << "\n"
331 // load all interfaces on this configuration
332 if( !desc.interfaces.Discover(devid, i, desc.desc.bNumInterfaces) )
333 return false;
335 // add to the map
336 (*this)[desc.desc.bConfigurationValue] = desc;
337 dout(" config added to map with bConfigurationValue: " << (unsigned int)desc.desc.bConfigurationValue);
340 return m_valid = true;
344 ///////////////////////////////////////////////////////////////////////////////
345 // DeviceDiscovery
347 DeviceDiscovery::DeviceDiscovery(Usb::DeviceIDType devid)
348 : m_valid(false)
350 Discover(devid);
353 bool DeviceDiscovery::Discover(Usb::DeviceIDType devid)
355 // start fresh
356 configs.clear();
357 m_valid = false;
359 // copy the descriptor over to our memory
360 if( !devid )
361 return false;
362 desc = devid->descriptor;
363 dout("device_desc loaded"
364 << "\nbLength: " << (unsigned int) desc.bLength
365 << "\nbDescriptorType: " << (unsigned int) desc.bDescriptorType
366 << "\nbcdUSB: " << (unsigned int) desc.bcdUSB
367 << "\nbDeviceClass: " << (unsigned int) desc.bDeviceClass
368 << "\nbDeviceSubClass: " << (unsigned int) desc.bDeviceSubClass
369 << "\nbDeviceProtocol: " << (unsigned int) desc.bDeviceProtocol
370 << "\nbMaxPacketSize0: " << (unsigned int) desc.bMaxPacketSize0
371 << "\nidVendor: " << (unsigned int) desc.idVendor
372 << "\nidProduct: " << (unsigned int) desc.idProduct
373 << "\nbcdDevice: " << (unsigned int) desc.bcdDevice
374 << "\niManufacturer: " << (unsigned int) desc.iManufacturer
375 << "\niProduct: " << (unsigned int) desc.iProduct
376 << "\niSerialNumber: " << (unsigned int) desc.iSerialNumber
377 << "\nbNumConfigurations: " << (unsigned int) desc.bNumConfigurations
378 << "\n"
381 m_valid = configs.Discover(devid, desc.bNumConfigurations);
382 return m_valid;
385 } // namespace Usb