summaryrefslogtreecommitdiffstats
path: root/libusb/usbpp.h
blob: abda64f74334fdac4de8569e8a0367a8b80ac90f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
// -*- C++;indent-tabs-mode: t; tab-width: 4; c-basic-offset: 4; -*-
#ifndef __USBPP_HEADER__
#define __USBPP_HEADER__

#include <string>
#include <list>

#include <usb.h>

/*
 * The following usb.h function is not wrapped yet:
 *  char *usb_strerror(void);
 */


/**
 * \brief Classes to access Universal Serial Bus devices
 *
 * The USB Namespace provides a number of classes to work
 * with Universal Serial Bus (USB) devices attached to the
 * system.
 *
 * \author Brad Hards
 */
namespace USB {

	class Device;

	/**
	 * \brief Class representing a device endpoint
	 *
	 * This class represents a device endpoint. You need this class to
	 * perform bulk reads and writes.
	 *
	 */
	class Endpoint {
		/**
		 * Busses is a friend because it fills in the descriptor type
		 * information on initialisation and rescan.
		 */
		friend class Busses;
	public:
		Endpoint() {};

#ifdef USE_UNTESTED_LIBUSBPP_METHODS
		/**
		 * \brief Bulk write
		 * 
		 * This method performs a bulk transfer to the endpoint.
		 *
		 * \param message is the message to be sent.
		 * \param timeout is the USB transaction timeout in milliseconds
		 *
		 * \returns the number of bytes sent, or a negative value on
		 * failure
		 */
		int bulkWrite(QByteArray message, int timeout = 100);
		
		/**
		 * \brief Bulk read
		 * 
		 * This method performs a bulk transfer from the endpoint.
		 *
		 * \param length is the maximum data transfer required. 
		 * \param message is the message that was received.
		 * \param timeout is the USB transaction timeout in milliseconds
		 *
		 * \returns the number of bytes received, or a negative value on
		 * failure
		 */
		int bulkRead(int length, unsigned char *message, int timeout = 100);

		/**
		 * \brief Reset endpoint
		 *
		 * This method resets the endpoint.
		 */
		int reset(void);

		/**
		 * \brief Clear halt
		 *
		 * This method clears a halt (stall) on the endpoint.
		 */
		int clearHalt(void);

#endif /* USE_UNTESTED_LIBUSBPP_METHODS */

		/**
		 * \brief Endpoint descriptor information output
		 *
		 * This method dumps out the various characteristics
		 * of the endpoint to standard output. 
		 *
		 * It is mostly useful for debugging.
		 */
		void dumpDescriptor(void);

	private:
		void setDescriptor(struct usb_endpoint_descriptor);
		void setParent(Device *parent);
		u_int8_t  m_Length;
		u_int8_t  m_DescriptorType;
		u_int8_t  m_EndpointAddress;
		u_int8_t  m_Attributes;
		u_int16_t m_MaxPacketSize;
		u_int8_t  m_Interval;
		u_int8_t  m_Refresh;
		u_int8_t  m_SynchAddress;
		Device    *m_parent;
	};

	class AltSetting : public std::list<Endpoint *> {
		/**
		 * Busses is a friend because it fills in the descriptor type
		 * information on initialisation and rescan.
		 */
		friend class Busses;
	public:
		AltSetting() {};
		u_int8_t numEndpoints(void);

		/**
		 * \brief AltSetting descriptor information output
		 *
		 * This method dumps out the various characteristics
		 * of the alternate setting to standard output. 
		 *
		 * It is mostly useful for debugging.
		 */
		void dumpDescriptor(void);

		Endpoint *firstEndpoint(void);
		Endpoint *nextEndpoint(void);
		Endpoint *lastEndpoint(void);

	private:
		std::list<Endpoint *>::const_iterator iter;

		void setDescriptor(struct usb_interface_descriptor);
		/* we don't use a normal usb_interface_descriptor */
		/* because that would bring in the endpoint list */
		u_int8_t m_Length;
		u_int8_t m_DescriptorType;
		u_int8_t m_InterfaceNumber;
		u_int8_t m_AlternateSetting;
		u_int8_t m_NumEndpoints;
		u_int8_t m_InterfaceClass;
		u_int8_t m_InterfaceSubClass;
		u_int8_t m_InterfaceProtocol;
		u_int8_t m_Interface;
	};

	/**
	 * \brief Class representing an interface of a Device
	 *
	 * The Interface class represents a USB interface
	 * for a device attached to a Universal Serial Bus.
	 *
	 * Interfaces are the main element of the USB class
	 * structure.
	 *
	 * \author Brad Hards
	 */
	class Interface : public std::list<AltSetting *> {
		/**
		 * Busses is a friend because it fills in the descriptor type
		 * information on initialisation and rescan.
		 */
		friend class Busses;
	public:
		Interface() {};

#ifdef LIBUSB_HAS_GET_DRIVER_NP
		/**
		 * \brief get the current driver for an interface
		 * 
		 * \param driver a string containing the name of the current
		 * driver for the interface. You can typically pass in an empty
		 * string for this. 
		 *
		 * \return length of string, or 0 on error.
		 */
		int driverName(std::string &driver);
#endif

#ifdef USE_UNTESTED_LIBUSBPP_METHODS
		/**
		 * \brief Claim this interface
		 *
		 * This method claims the interface. You have to claim the
		 * interface before performing any operations on the interface (or
		 * on endpoints that are part of the interface).
		 *
		 * \return 0 on success or negative number on error.
		 */
		int claim(void);

		/**
		 * \brief Release this interface
		 *
		 * This method releases the interface. You should release the
		 * interface after all operations on it (and any lower level
		 * endpoints) are completed.
		 *
		 * \return 0 on success or negative number on error.
		 */
		int release(void);

		/**
		 * \brief Set interface alternate setting
		 *
		 * This method sets the interface to a particular AltSetting.
		 *
		 * \param altSettingNumber the AltSetting that the interface
		 * should be changed to.
		 *
		 * \return 0 on success, or a negative number in case of error.
		 */
		int setAltSetting(int altSettingNumber);
#endif /* USE_UNTESTED_LIBUSBPP_METHODS */

		/**
		 * \brief Number of Alternative Settings that this interface has
		 *
		 * This is a simple accessor method that specifies the number
		 * alternative settings that this device interface has.
		 */
		u_int8_t numAltSettings(void);

		/**
		 * \brief First AltSetting for the Interface
		 *
		 * This method returns a pointer to the first AltSetting
		 * for the Interface. 
		 *
		 * See nextAltSetting() for an example of how it might be
		 * used.
		 *
		 * \see nextAltSetting(), lastAltSetting(), numAltSettings()
		 */
		AltSetting *firstAltSetting(void);

		/**
		 * \brief Next AltSetting for the Interface
		 *
		 * This method returns a pointer to the next AltSetting
		 * for the Interface. 
		 *
		 * If you want to iterate through each AltSetting on 
		 * a device, you can use something like the following:
		 * \code
		 * USB::Configuration *this_Configuration;
		 * this_Configuration = device->firstConfiguration();
		 * for (i=0; i < device->numConfigurations(); i++) {
		 *	 this_Configuration->dumpDescriptor();
		 *   USB::Interface *this_Interface;
		 *   this_Interface = this_Configuration->firstInterface();
		 *   for (j=0; j < this_Configuration->numInterfaces(); j++) {
		 *     USB::AltSetting *this_AltSetting;
		 *     this_AltSetting = this_Interface->firstAltSetting();
		 *     for (k=0; k < this_Interface->numAltSettings(); k++) {
		 *       // do something with this_AltSetting
		 *       this_AltSetting = this_Interface->nextAltSetting();
		 *     }
		 *   this_Interface = this_Configuration->nextInterface();
		 *   }
		 *   this_Configuration = device->nextConfiguration();
		 * }
		 * \endcode
		 *
		 * \see firstAltSetting(), lastAltSetting(), numAltSettings()
		 */
		AltSetting *nextAltSetting(void);

		/**
		 * \brief Last AltSetting for the Interface
		 *
		 * This method returns a pointer to the last AltSetting
		 * for the Interface. 
		 *
		 * \see firstAltSetting(), nextAltSetting(), numAltSettings()
		 */

		AltSetting *lastAltSetting(void);

	private:
		std::list<AltSetting *>::const_iterator iter;

		void setNumAltSettings(u_int8_t);
		void setParent(Device *parent);
		u_int8_t m_numAltSettings;
		Device    *m_parent;

		/* index representing the interface, in this configuration */
		int m_interfaceNumber;
		void setInterfaceNumber(int interfaceNumber);
	};

	/**
	 * \brief Class representing a configuration of a Device
	 *
	 * The Configuration class represents a single configuration
	 * of a device attached to a Universal Serial Bus.
	 *
	 * \author Brad Hards 
	 */
	class Configuration : public std::list<Interface *> {
		/**
		 * Busses is a friend because it fills in the descriptor type
		 * information on initialisation and rescan.
		 */
		friend class Busses;
	public:
		Configuration() {};

		/**
		 * \brief Configuration descriptor information output
		 *
		 * This method dumps out the various characteristics
		 * of the configuration to standard output. 
		 *
		 * It is mostly useful for debugging.
		 */
		void dumpDescriptor(void);

		/**
		 * \brief Number of Interfaces that this device has
		 *
		 * This is a simple accessor method that specifies the number
		 * Interfaces that this device configuration has.
		 */
		u_int8_t numInterfaces(void);

		/**
		 * \brief First Interface for the Configuration
		 *
		 * This method returns a pointer to the first Interface
		 * for the Configuration. 
		 *
		 * See nextInterface() for an example of how it might be
		 * used.
		 *
		 * \see nextInterface(), lastInterface(), numInterfaces()
		 */
		Interface *firstInterface(void);

		/**
		 * \brief Next Interface for the Configuration
		 *
		 * This method returns a pointer to the next Interface
		 * for the Configuration. 
		 *
		 * If you want to iterate through each Interface on 
		 * a device, you can use something like the following:
		 * \code
		 * USB::Configuration *this_Configuration;
		 * this_Configuration = device->firstConfiguration();
		 * for (i=0; i < device->numConfigurations(); i++) {
		 *	 this_Interface = this_Configuration->firstInterface();
		 *	 for (j=0; j < this_Configuration->numInterfaces(); j++) {
		 *     // do something with this_Interface
		 *     this_Interface = this_Configuration->nextInterface();
		 *   }
		 *   this_Configuration->nextConfiguration();
		 * }
		 * \endcode
		 *
		 * \see firstInterface(), lastInterface(), numInterfaces()
		 */
		Interface *nextInterface(void);

		/**
		 * \brief Last Interface for the Configuration
		 *
		 * This method returns a pointer to the last Interface
		 * for the Configuration. 
		 *
		 * \see firstInterface(), nextInterface(), numInterfaces()
		 */
		Interface *lastInterface(void);

	private:
		std::list<Interface *>::const_iterator iter;

		void setDescriptor(struct usb_config_descriptor);
		/* we don't use a normal usb_config_descriptor */
		/* because that would bring in the interface list */
		u_int8_t  m_Length;
		u_int8_t  m_DescriptorType;
		u_int16_t m_TotalLength;
		u_int8_t  m_NumInterfaces;
		u_int8_t  m_ConfigurationValue;
		u_int8_t  m_Configuration;
		u_int8_t  m_Attributes;
		u_int8_t  m_MaxPower; 
	};

	/**
	 * \brief Class representing a Device on the Bus
	 *
	 * The Device class represents a single device
	 * attached to a Universal Serial Bus.
	 *
	 * \author Brad Hards 
	 */
	class Device : public std::list<Configuration *> {
		/**
		 * Busses is a friend because it fills in the descriptor type
		 * information on initialisation and rescan.
		 */
		friend class Busses;
		/** 
		 * Interface is a friend because it needs the handle() function to
		 * perform claim(), release().
		 */
		friend class Interface;
		/** 
		 * Endpoint is a friend because it needs the handle() function to
		 * perform reads, writes, and other transactions.
		 */
		friend class Endpoint;

	public:
		Device() {};
		~Device();

		/**
		 * \brief OS representation of filename for this device
		 *
		 * libusb++ provides a uniform way of accessing USB
		 * devices irrespective of the underlying Operation System
		 * representation. If you want to map the libusb++ representation
		 * to the Operating System representation, you can do this
		 * with filename().
		 *
		 * On Linux, the filename is usually something like 002, which
		 * represents the second device (usually the first real device,
		 * after the root hub pseudo-device) on the bus.
		 *
		 * \see Bus::directoryName()
		 */
		std::string fileName(void);

		/** 
		 * \brief The vendor ID number, as provided by the device.
		 *
		 * This method returns a number containing the vendor
		 * (manufacturer) identification number. These are allocated
		 * by the USB Implementers Forum, and you can construct a
		 * lookup based on the number to get the manufacturer's name,
		 * even if the device does not contain a vendor string.
		 *
		 * \see Vendor()
		 */ 
		u_int16_t idVendor(void);

		/** 
		 * \brief The product ID number, as provided by the device.
		 *
		 * This method returns a number containing the product
		 * identification number. These are allocated
		 * by the manufacturer, and should be different on each device.
		 *
		 * \see Product()
		 */ 
		u_int16_t idProduct(void);

		/**
		 * \brief The product's revision ID, as provided by the device.
		 *
		 * This method returns a number containing the product's revision.
		 * This revision level is nominally binary coded decimal, but
		 * hexadecimal revision levels are not uncommon. The binary coded
		 * decimal version nominally has a major version in the high byte,
		 * and a minor version in the low byte. 
		 */
		u_int16_t idRevision(void);

		/**
		 * \brief The device's USB class, as provided by the device.
		 *
		 * This method returns a number containing the device's class.
		 * These are defined by the USB Implementer's Forum.
		 *
		 * A code of Zero is special (and common) - it means that the
		 * class is found in the Interface descriptor, rather than in the
		 * Device descriptor.
		 * 
		 * A code of 0xFF is also special (and far too common) - it means
		 * that the manufacturer didn't conform to one of the defined 
		 * class specifications, and chose to implement a vendor specified
		 * protocol.
		 *
		 */
		u_int8_t devClass(void);

		/**
		 * \brief The device's USB subclass, as provided by the device.
		 *
		 * This method returns a number containing the device's subclass.
		 * These subclasses are defined by the USB Implementer's Forum,
		 * and only have meaning in the context of a specified class. 
		 */
		u_int8_t devSubClass(void);

		/**
		 * \brief The device's USB protocol, as provided by the device.
		 *
		 * This method returns a number containing the device's protocol.
		 * These protocols are defined by the USB Implementer's Forum, and
		 * only have meaning in the context of a specified class and
		 * subclass. 
		 */
		u_int8_t devProtocol(void);

    
		/**
		 * \brief The vendor name string, as provided by the device.
		 *
		 * This method returns a string containing the name of the 
		 * device's vendor (manufacturer), as encoded into the device.
		 *
		 * Note that not all devices contain a vendor name, and also
		 * that under some operating systems you may not be able to
		 * read the vendor name without elevated privledges (typically
		 * root privledges).
		 *
		 * \see idVendor()
		 **/
		std::string Vendor(void);

		/**
		 * \brief The product name string, as provided by the device.
		 *
		 * This method returns a string containing the name of the 
		 * device's product name, as encoded into the device.
		 *
		 * Note that not all devices contain a product name, and also
		 * that under some operating systems you may not be able to
		 * read the vendor name without elevated privledges (typically
		 * root privledges).
		 * 
		 * \see idProduct()
		 **/
		std::string Product(void);

		/**
		 * \brief The serial number string, as provided by the device.
		 *
		 * This method returns a string containing a serial number for
		 * the device, as encoded into the device.
		 *
		 * Note that few devices contain a serial number string, and also
		 * that under some operating systems you may not be able to
		 * read the serial number without elevated privledges (typically
		 * root privledges). The USB specification requires that serial
		 * numbers are unique if they are provided, but adherence to this
		 * requirement by manufacturers is not universal.
		 **/
		std::string SerialNumber(void);

		/**
		 * \brief Number of Configurations that this device has
		 *
		 * This is a simple accessor method that specifies the number
		 * configurations that this device has.
		 */
		u_int8_t numConfigurations(void);

		/**
		 * \brief fetch an arbitrary string from the device
		 * 
		 * \param string the string from the device. You can typically
		 * pass in an empty string for this.
		 * \param index the index of the string required
		 * \param lang the language ID to use. Defaults to using the
		 * first language ID.
		 *
		 * \return length of string, or 0 on error.
		 */
		int string(std::string &buf, int index, u_int16_t lang=0);

		/**
		 * \brief First Configuration for the Device
		 *
		 * This method returns a pointer to the first Configuration
		 * for the Device. 
		 *
		 * See nextConfiguration() for an example of how it might be
		 * used.
		 */
		Configuration *firstConfiguration(void);

		/**
		 * \brief Next Configuration for the Device
		 *
		 * This method returns a pointer to the next Configuration
		 * for the Device. 
		 *
		 * If you want to iterate through each Configuration on
		 * a device, you can use something like the following:
		 * \code
		 * USB::Configuration *this_Configuration;
		 * this_Configuration = device->firstConfiguration();
		 * for (i=0; i < device->numConfigurations(); i++) {
		 *   // do something with this_Configuration
		 *   this_Configuration->nextConfiguration();
		 * }
		 * \endcode
		 */
		Configuration *nextConfiguration(void);

		/**
		 * \brief Last Configuration for the Device
		 *
		 * This method returns a pointer to the last Configuration
		 * for the Device. 
		 *
		 */
		Configuration *lastConfiguration(void);

		/**
		 * \brief USB control transfer
		 *
		 * This method performs a standard control transfer to the default
		 * endpoint. See the USB specification for more details on this.
		 * 
		 * \param requestType corresponds to the bmRequestType field
		 * in the transfer
		 * \param request corresponds to the bRequest field in the
		 * transfer
		 * \param value corresponds to the wValue field in the transfer
		 * \param index corresponds to the wIndex field in the transfer
		 * \param length corresponds to the wLength field in the transfer
		 * \param payload corresponds to the data phase of a control
		 * transfer
		 * \param timeout is the timeout period for the control transfer,
		 * in milliseconds
		 *
		 * \return number of bytes sent or received, or a negative number
		 * in case of error.
		 */
		int controlTransfer(u_int8_t requestType, u_int8_t request,
				    u_int16_t value, u_int16_t index, u_int16_t length,
				    unsigned char *payload,
				    int timeout = 100); 

#ifdef USE_UNTESTED_LIBUSBPP_METHODS
		/**
		 * \brief USB device reset
		 *
		 * This method performs a device reset - see USB Specification
		 * 9.1 for how this changes the device state to the Default state.
		 *
		 * \return 0 on success, or a negative number in case of error.
		 */
		int reset(void);

		/**
		 * \brief Set device configuration
		 *
		 * This method sets the device to a particular Configuration.
		 *
		 * \param configurationNumber the configuration that the device
		 * should be changed to.
		 *
		 * \return 0 on success, or a negative number in case of error.
		 */
		int setConfiguration(int configurationNumber);
#endif /* USE_UNTESTED_LIBUSBPP_METHODS */
    
	private:
		std::list<Configuration *>::const_iterator iter;

		struct usb_dev_handle *handle();
		void setFileName(std::string);
		void setDescriptor(struct usb_device_descriptor);
		void setVendor(std::string);
		void setProduct(std::string);
		void setSerialNumber(std::string);
		void setDevHandle(struct usb_dev_handle *);
		std::string m_fileName;
		std::string m_Vendor;
		std::string m_Product;
		std::string m_SerialNumber;
		struct usb_device *m_dev;
		struct usb_dev_handle *m_handle;
		struct usb_device_descriptor m_descriptor;
	};

	/**
	 * \brief Class representing a single bus on the machine
	 *
	 * This class is essentially a list of Device class instances
	 */
	class Bus : public std::list<Device *> {
		/**
		 * Busses is a friend because it fills in the directory name
		 * information on initialisation and rescan.
		 */
		friend class Busses;
	public:
		Bus() {};
		/**
		 * \brief OS representation of directory name for this Bus
		 *
		 * libusb++ provides a uniform way of accessing USB
		 * busses irrespective of the underlying Operation System
		 * representation. If you want to map the libusb++ representation
		 * to the Operating System representation, you can do this
		 * with directory name().
		 *
		 * On Linux, the directoryname is usually something like 003, which
		 * represents the third bus on the host.
		 *
		 * \see Directory::filename()
		 */
		std::string directoryName(void);
	private:
		std::list<Device *>::const_iterator iter;

		void setDirectoryName(std::string);
		std::string m_directoryName;
	};

	/**
	 * \brief A vendor/product ID pair
	 *
	 * DeviceID provides a list of (vendor, product) identification
	 * pairs. It is intended for use in a list of device numbers to
	 * search for, but there is no reason why it couldn't be used for a
	 * general purpose (vendor,product) tuple if you had some reason for
	 * this.
	 *
	 * The description for Busses::match() provides an example of how
	 * this class might be used.
	 *
	 * \see DeviceIDList, Busses::match()
	 */
	class DeviceID {
	public:
		DeviceID() {};
		/** 
		 * \brief Standard constructor
		 *
		 * This constructor takes (vendor, product) tuple, which are
		 * stored away.
		 *
		 * \param vendor the 16 bit vendor number for the device
		 * \param product the 16 bit product number for the device
		 */
		DeviceID(u_int16_t vendor, u_int16_t product);

		/**
		 * \brief vendor number for the device
		 *
		 * This method returns the 16 bit vendor number.
		 */
		u_int16_t vendor(void);

		/**
		 * \brief product number for the device
		 *
		 * This method returns the 16 bit product number.
		 */
		u_int16_t product(void);

	private:
		u_int16_t m_vendor;
		u_int16_t m_product;
	};

	/**
	 * \brief A list of vendor/product pairs
	 *
	 * DeviceIDList provides a list of DeviceID classes, which is
	 * essentially a list of (vendor, product) identification pairs.
	 *
	 * \see DeviceID
	 */
	typedef std::list<DeviceID> DeviceIDList;

	/**
	 * \brief Class representing all the busses on the machine
	 *
	 * This class is essentially a list of Bus class instances
	 */
	class Busses : public std::list<Bus *> {
	public:
		Busses();

		/** 
		 * \brief Update method
		 *
		 * This method can be called to rescan the various devices
		 * attached to the various busses. You should use it to
		 * update if things change. Unfortunately there is no 
		 * way to automatically detect this change in a portable way, 
		 * so worst case is that you need to call this using some
		 * kind of timer in the background.
		 */
		void rescan(void);

		/**
		 * \brief find all devices with matching device class designator
		 *
		 * This method searches every device on every bus, and returns a
		 * list of pointers to the devices that have a matching device
		 * class code
		 */
		std::list<Device *> match(u_int8_t Class);

		/**
		 * \brief find all devices with matching device IDs
		 *
		 * This method searches every device on every bus, and returns a
		 * list of pointers to the devices that have a matching device
		 * ID. That is, if the (vendor, product) tuple of a device matches
		 * one of the tuples on the list, then the device will be added to
		 * the list of matches.  
		 *
		 * An example of usage is shown below:
		 * \code
		 * USB::Busses buslist;
		 * USB::Device *device;
		 * std::list<USB::Device> miceFound;
		 * USB::DeviceIDList mouseList;
		 *
		 * mouseList.append(USB::DeviceID(VENDOR_LOGITECH, 0xC00E)); // Wheel Mouse Optical
		 * mouseList.append(USB::DeviceID(VENDOR_LOGITECH, 0xC012)); // MouseMan Dual Optical
		 * mouseList.append(USB::DeviceID(VENDOR_LOGITECH, 0xC506)); // MX700 Optical Mouse
		 *
		 * miceFound = buslist.match(mouseList);
		 *
		 * for ( device = miceFound.first(); device; device = miceFound.next() ) {
		 *     // do something with each mouse that matched
		 * }
		 * FIXME: This is incorrect now
		 * \endcode
		 */
		std::list<Device *> match(DeviceIDList);

	private:
		std::list<Bus *>::const_iterator iter;
	};
  
	class Error {
	public:
	private:
	};

}
#endif /* __USBPP_HEADER__ */