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.
31 #define __DEBUG_MODE__
36 ///////////////////////////////////////////////////////////////////////////////
39 Match::Match(int vendor
, int product
)
47 m_busses
= usb_get_busses();
54 bool Match::next_device(Usb::DeviceIDType
*devid
)
56 for( ; m_busses
; m_busses
= m_busses
->next
) {
59 m_dev
= m_busses
->devices
;
61 for( ; m_dev
; m_dev
= m_dev
->next
) {
63 if( m_dev
->descriptor
.idVendor
== m_vendor
&&
64 m_dev
->descriptor
.idProduct
== m_product
) {
68 // advance for next time
71 m_busses
= m_busses
->next
;
82 ///////////////////////////////////////////////////////////////////////////////
85 Device::Device(Usb::DeviceIDType id
)
87 m_timeout(USBWRAP_DEFAULT_TIMEOUT
)
89 m_handle
= usb_open(id
);
91 throw UsbError("open failed");
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;
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
);
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 ///////////////////////////////////////////////////////////////////////////////
174 bool EndpointDiscovery::Discover(struct usb_interface_descriptor
*interface
, int epcount
)
182 if( !interface
|| !interface
->endpoint
)
185 for( int i
= 0; i
< epcount
; i
++ ) {
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
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...
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
) {
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
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
231 // save the type last
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
)
258 for( int i
= 0; i
< interface
->num_altsetting
; i
++ ) {
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
275 // load all endpoints on this interface
276 if( !desc
.endpoints
.Discover(&desc
.desc
, desc
.desc
.bNumEndpoints
) )
280 (*this)[desc
.desc
.bInterfaceNumber
] = desc
;
281 dout(" interface added to map with bInterfaceNumber: " << (unsigned int)desc
.desc
.bInterfaceNumber
);
286 bool InterfaceDiscovery::Discover(Usb::DeviceIDType devid
, int cfgidx
, int ifcount
)
292 if( !devid
|| !devid
->config
|| !devid
->config
[cfgidx
].interface
)
295 for( int i
= 0; i
< ifcount
; i
++ ) {
296 if( !DiscoverInterface(&devid
->config
[cfgidx
].interface
[i
]) )
300 return m_valid
= true;
304 ///////////////////////////////////////////////////////////////////////////////
307 bool ConfigDiscovery::Discover(Usb::DeviceIDType devid
, int cfgcount
)
313 for( int i
= 0; i
< cfgcount
; i
++ ) {
316 if( !devid
|| !devid
->config
)
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
331 // load all interfaces on this configuration
332 if( !desc
.interfaces
.Discover(devid
, i
, desc
.desc
.bNumInterfaces
) )
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 ///////////////////////////////////////////////////////////////////////////////
347 DeviceDiscovery::DeviceDiscovery(Usb::DeviceIDType devid
)
353 bool DeviceDiscovery::Discover(Usb::DeviceIDType devid
)
359 // copy the descriptor over to our memory
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
381 m_valid
= configs
.Discover(devid
, desc
.bNumConfigurations
);