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