1/*
2 * Copyright 2007-2008, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef _USBKIT_H
6#define _USBKIT_H
7
8#include <SupportDefs.h>
9#include <USB_spec.h>
10#include <USB_isochronous.h>
11
12
13class BUSBRoster;
14class BUSBDevice;
15class BUSBConfiguration;
16class BUSBInterface;
17class BUSBEndpoint;
18
19
20/*	The BUSBRoster class can be used to watch for devices that get attached or
21	removed from the USB bus.
22	You subclass the roster and implement the pure virtual DeviceAdded() and
23	DeviceRemoved() hooks. */
24class BUSBRoster {
25public:
26									BUSBRoster();
27virtual								~BUSBRoster();
28
29		// The DeviceAdded() hook will be called when a new device gets
30		// attached to the USB bus. The hook is called with an initialized
31		// BUSBDevice object. If you return B_OK from your hook the object
32		// will stay valid and the DeviceRemoved() hook will be called for
33		// it. Otherwise the object is deleted and DeviceRemoved() is not
34		// called.
35virtual	status_t					DeviceAdded(BUSBDevice *device) = 0;
36
37		// When a device gets detached from the bus that you hold a
38		// BUSBDevice object for (gotten through DeviceAdded()) the
39		// DeviceRemoved() hook will be called. The device object gets
40		// invalid and will be deleted as soon as you return from the hook
41		// so be sure to remove all references to it.
42virtual	void						DeviceRemoved(BUSBDevice *device) = 0;
43
44		void						Start();
45		void						Stop();
46
47private:
48virtual	void						_ReservedUSBRoster1();
49virtual	void						_ReservedUSBRoster2();
50virtual	void						_ReservedUSBRoster3();
51virtual	void						_ReservedUSBRoster4();
52virtual	void						_ReservedUSBRoster5();
53
54		void *						fLooper;
55		uint32						fReserved[10];
56};
57
58
59/*	The BUSBDevice presents an interface to a USB device. You can either get
60	it through the BUSBRoster or by creating one yourself and setting it to
61	a valid raw usb device (with a path of "/dev/bus/usb/x").
62	The device class provides direct accessors for descriptor fields as well
63	as convenience functions to directly get string representations of fields.
64	The BUSBDevice also provides access for the BUSBConfiguration objects of
65	a device. These objects and all of their child objects depend on the
66	parent device and will be deleted as soon as the device object is
67	destroyed. */
68class BUSBDevice {
69public:
70									BUSBDevice(const char *path = NULL);
71virtual								~BUSBDevice();
72
73virtual	status_t					InitCheck();
74
75		status_t					SetTo(const char *path);
76		void						Unset();
77
78		// Returns the location on the bus represented as hub/device sequence.
79		const char *				Location() const;
80		bool						IsHub() const;
81
82		// These are direct accessors to descriptor fields.
83		uint16						USBVersion() const;
84		uint8						Class() const;
85		uint8						Subclass() const;
86		uint8						Protocol() const;
87		uint8						MaxEndpoint0PacketSize() const;
88		uint16						VendorID() const;
89		uint16						ProductID() const;
90		uint16						Version() const;
91
92		// The string functions return the string representation of the
93		// descriptor data. The strings are decoded to normal 0 terminated
94		// C strings and are cached and owned by the object.
95		// If a string is not available an empty string is returned.
96		const char *				ManufacturerString() const;
97		const char *				ProductString() const;
98		const char *				SerialNumberString() const;
99
100		const usb_device_descriptor *
101									Descriptor() const;
102
103		// GetStringDescriptor() can be used to retrieve the raw
104		// usb_string_descriptor with a given index. The strings contained
105		// in these descriptors are usually two-byte unicode encoded.
106		size_t						GetStringDescriptor(uint32 index,
107										usb_string_descriptor *descriptor,
108										size_t length) const;
109
110		// Use the DecodeStringDescriptor() convenience function to get a
111		// 0-terminated c string for a given string index. Note that this
112		// will allocate the string as "new char[];" and needs to be deleted
113		// like "delete[] string;" by the caller.
114		char *						DecodeStringDescriptor(uint32 index) const;
115
116		size_t						GetDescriptor(uint8 type, uint8 index,
117										uint16 languageID, void *data,
118										size_t length) const;
119
120		// With ConfigurationAt() or ActiveConfiguration() you can get an
121		// object that represents the configuration at a certain index or at
122		// the index that is currently configured. Note that the index does not
123		// necessarily correspond to the configuration_value present in the
124		// configuration descriptor.
125		// Use the returned object as an argument to SetConfiguration() to
126		// change the active configuration of a device.
127		uint32						CountConfigurations() const;
128		const BUSBConfiguration *	ConfigurationAt(uint32 index) const;
129
130		const BUSBConfiguration *	ActiveConfiguration() const;
131		status_t					SetConfiguration(
132										const BUSBConfiguration *configuration);
133
134		// ControlTransfer() sends requests using the default pipe.
135		ssize_t						ControlTransfer(uint8 requestType,
136										uint8 request, uint16 value,
137										uint16 index, uint16 length,
138										void *data) const;
139
140private:
141virtual	void						_ReservedUSBDevice1();
142virtual	void						_ReservedUSBDevice2();
143virtual	void						_ReservedUSBDevice3();
144virtual	void						_ReservedUSBDevice4();
145virtual	void						_ReservedUSBDevice5();
146
147		char *						fPath;
148		int							fRawFD;
149
150		usb_device_descriptor		fDescriptor;
151		BUSBConfiguration **		fConfigurations;
152		uint32						fActiveConfiguration;
153
154mutable	char *						fManufacturerString;
155mutable	char *						fProductString;
156mutable	char *						fSerialNumberString;
157
158		uint32						fReserved[10];
159};
160
161
162/*	A BUSBConfiguration object represents one of possibly multiple
163	configurations a device might have. A valid object can only be gotten
164	through the ConfigurationAt() or ActiveConfiguration() methods of a
165	BUSBDevice.
166	The BUSBConfiguration provides further access into the configuration by
167	providing CountInterfaces() and InterfaceAt() to retrieve BUSBInterface
168	objects. */
169class BUSBConfiguration {
170public:
171		// Device() returns the parent device of this configuration. This
172		// configuration is located at the index returned by Index() within
173		// that parent device.
174		uint32						Index() const;
175		const BUSBDevice *			Device() const;
176
177		// Gets a descriptive string for this configuration, if available.
178		// Otherwise an empty string is returned.
179		const char *				ConfigurationString() const;
180
181		const usb_configuration_descriptor *
182									Descriptor() const;
183
184		// With CountInterfaces() and InterfaceAt() you can iterate through
185		// the child interfaces of this configuration. It is the only valid
186		// way to get a BUSBInterface object.
187		// Note that the interface objects retrieved using InterfaceAt() will
188		// be invalid and deleted as soon as this configuration gets deleted.
189		uint32						CountInterfaces() const;
190		const BUSBInterface *		InterfaceAt(uint32 index) const;
191
192private:
193friend	class BUSBDevice;
194									BUSBConfiguration(BUSBDevice *device,
195										uint32 index, int rawFD);
196									~BUSBConfiguration();
197
198		BUSBDevice *				fDevice;
199		uint32						fIndex;
200		int							fRawFD;
201
202		usb_configuration_descriptor fDescriptor;
203		BUSBInterface **			fInterfaces;
204
205mutable	char *						fConfigurationString;
206
207		uint32						fReserved[10];
208};
209
210
211/*	The BUSBInterface class can be used to access the descriptor fields of
212	an underleying USB interface. Most importantly though it can be used to
213	iterate over and retrieve BUSBEndpoint objects that can be used to
214	transfer data over the bus. */
215class BUSBInterface {
216public:
217		// Configuration() returns the parent configuration of this interface.
218		// This interface is located at the index returned by Index() in that
219		// parent configuration and represents the alternate interface returned
220		// by AlternateIndex().
221		// Device() is a convenience function to directly reach the parent
222		// device of this interface instead of going through the configuration.
223		uint32						Index() const;
224		uint32						AlternateIndex() const;
225		const BUSBConfiguration *	Configuration() const;
226		const BUSBDevice *			Device() const;
227
228		// These are accessors to descriptor fields. InterfaceString() tries
229		// to return a descriptive string for the interface. If no string is
230		// available an empty string is returned.
231		uint8						Class() const;
232		uint8						Subclass() const;
233		uint8						Protocol() const;
234		const char *				InterfaceString() const;
235
236		const usb_interface_descriptor *
237									Descriptor() const;
238
239		// Use OtherDescriptorAt() to get generic descriptors of an interface.
240		// These are usually device/interface class specific or they may
241		// represent vendor specific extensions.
242		status_t					OtherDescriptorAt(uint32 index,
243										usb_descriptor *descriptor,
244										size_t length) const;
245
246		// CountEndpoints() and EndpointAt() can be used to iterate over the
247		// available endpoints within an interface. EndpointAt() is the only
248		// valid way to get BUSBEndpoint object. Note that these objects will
249		// get invalid and deleted as soon as the parent interface is deleted.
250		uint32						CountEndpoints() const;
251		const BUSBEndpoint *		EndpointAt(uint32 index) const;
252
253		// Using CountAlternates() you can retrieve the number of alternate
254		// interfaces for this interface. Note that this interface itself
255		// counts as an alternate so an alternate count of one really means
256		// that you are currently using the sole interface present.
257		// AlternateAt() returns the interface descriptor of the alternate
258		// interface with the specified index. Using that you can peek at the
259		// attributes of that alternate (including endpoints) without having to
260		// switch to this alternate interface.
261		// Note that you cannot use any endpoint you retrieve through an
262		// interface you get through AlternateAt(). Even if you switch to that
263		// alternate later on, you cannot use an interface returned by
264		// AlternateAt(). Instead switch to that alternate using the interface
265		// you got from the configuration and then use this switched interface
266		// to enumerate the endpoints.
267		// ActiveAlternateIndex() returns the index of the currently active
268		// alternate interface.
269		// With SetAlternate() you can switch this BUSBInterface object to the
270		// alternate interface at the specified index. Note that all endpoints
271		// retrieved through EndpointAt() will become invalid and will be
272		// deleted as soon as you set an alternate interface (even if the
273		// resulting interface is the same you were using before).
274		uint32						CountAlternates() const;
275		uint32						ActiveAlternateIndex() const;
276		const BUSBInterface *		AlternateAt(uint32 alternateIndex) const;
277		status_t					SetAlternate(uint32 alternateIndex);
278
279private:
280friend	class BUSBConfiguration;
281									BUSBInterface(BUSBConfiguration *config,
282										uint32 index, uint32 alternate,
283										int rawFD);
284									~BUSBInterface();
285
286		void						_UpdateDescriptorAndEndpoints();
287
288		BUSBConfiguration *			fConfiguration;
289		uint32						fIndex;
290		uint32						fAlternate;
291		int							fRawFD;
292
293		usb_interface_descriptor	fDescriptor;
294		BUSBEndpoint **				fEndpoints;
295
296mutable	uint32						fAlternateCount;
297mutable	BUSBInterface **			fAlternates;
298
299mutable	char *						fInterfaceString;
300
301		uint32						fReserved[10];
302};
303
304
305/*	The BUSBEndpoint represent a device endpoint that can be used to send or
306	receive data. It also allows to query endpoint characteristics like
307	endpoint type or direction. */
308class BUSBEndpoint {
309public:
310		// Interface() returns the parent interface of this endpoint.
311		// This endpoint is located at the index returned by Index() in the
312		// parent interface.
313		// Configuration() and Device() are convenience functions to directly
314		// reach the parent configuration or device of this endpoint instead
315		// of going through the parent objects.
316		uint32						Index() const;
317		const BUSBInterface *		Interface() const;
318		const BUSBConfiguration *	Configuration() const;
319		const BUSBDevice *			Device() const;
320
321		// These methods can be used to check for endpoint characteristics.
322		bool						IsBulk() const;
323		bool						IsInterrupt() const;
324		bool						IsIsochronous() const;
325		bool						IsControl() const;
326
327		bool						IsInput() const;
328		bool						IsOutput() const;
329
330		uint16						MaxPacketSize() const;
331		uint8						Interval() const;
332
333		const usb_endpoint_descriptor *
334									Descriptor() const;
335
336		// These methods initiate transfers to or from the endpoint. All
337		// transfers are synchronous and the actually transfered amount of
338		// data is returned as a result. A negative value indicates an error.
339		// Which transfer type to use depends on the endpoint type.
340		ssize_t						ControlTransfer(uint8 requestType,
341										uint8 request, uint16 value,
342										uint16 index, uint16 length,
343										void *data) const;
344		ssize_t						InterruptTransfer(void *data,
345										size_t length) const;
346		ssize_t						BulkTransfer(void *data,
347										size_t length) const;
348		ssize_t						IsochronousTransfer(void *data,
349										size_t length,
350										usb_iso_packet_descriptor *packetDescriptors,
351										uint32 packetCount)	const;
352
353		// These are convenience methods for getting and clearing the halt
354		// state of an endpoint. They use the control pipe of the device to
355		// send the corresponding requests.
356		bool						IsStalled() const;
357		status_t					ClearStall() const;
358
359private:
360friend	class BUSBInterface;
361									BUSBEndpoint(BUSBInterface *interface,
362										uint32 index, int rawFD);
363									~BUSBEndpoint();
364
365		BUSBInterface *				fInterface;
366		uint32						fIndex;
367		int							fRawFD;
368
369		usb_endpoint_descriptor		fDescriptor;
370
371		uint32						fReserved[10];
372};
373
374#endif // _USB_KIT_H
375