xref: /haiku/headers/os/device/USBKit.h (revision cfc3fa87da824bdf593eb8b817a83b6376e77935)
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	*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 with the configuration value.
124 		// Use the returned object as an argument to SetConfiguration() to
125 		// change the active configuration of a device.
126 		uint32						CountConfigurations() const;
127 		const BUSBConfiguration		*ConfigurationAt(uint32 index) const;
128 
129 		const BUSBConfiguration		*ActiveConfiguration() const;
130 		status_t					SetConfiguration(
131 										const BUSBConfiguration *configuration);
132 
133 		// ControlTransfer() sends requests using the default pipe
134 		ssize_t						ControlTransfer(uint8 requestType,
135 										uint8 request, uint16 value,
136 										uint16 index, uint16 length,
137 										void *data) const;
138 
139 private:
140 virtual	void						_ReservedUSBDevice1();
141 virtual	void						_ReservedUSBDevice2();
142 virtual	void						_ReservedUSBDevice3();
143 virtual	void						_ReservedUSBDevice4();
144 virtual	void						_ReservedUSBDevice5();
145 
146 		char						*fPath;
147 		int							fRawFD;
148 
149 		usb_device_descriptor		fDescriptor;
150 		BUSBConfiguration			**fConfigurations;
151 		uint32						fActiveConfiguration;
152 
153 mutable	char						*fManufacturerString;
154 mutable	char						*fProductString;
155 mutable	char						*fSerialNumberString;
156 
157 		uint32						fReserved[10];
158 };
159 
160 
161 /*	A BUSBConfiguration object represents one of possibly multiple
162 	configurations a device might have. A valid object can only be gotten
163 	through the ConfigurationAt() and ActiveConfiguration() methods of a
164 	BUSBDevice.
165 	The BUSBConfiguration provides further access into the configuration by
166 	providing CountInterfaces() and InterfaceAt() to retrieve BUSBInterface
167 	objects. */
168 class BUSBConfiguration {
169 public:
170 		// Device() returns the parent device of this configuration. This
171 		// configuration is located at the index returned by Index() within
172 		// that parent device.
173 		uint32						Index() const;
174 		const BUSBDevice			*Device() const;
175 
176 		// Gets a describing string of this configuration if available.
177 		// Otherwise an empty string is returned.
178 		const char					*ConfigurationString() const;
179 
180 		const usb_configuration_descriptor
181 									*Descriptor() const;
182 
183 		// With CountInterfaces() and InterfaceAt() you can iterate through
184 		// the child interfaces of this configuration. It is the only valid
185 		// way to get a BUSBInterface object.
186 		// Note that the interface objects retrieved using InterfaceAt() will
187 		// be invalid and deleted as soon as this configuration gets deleted.
188 		uint32						CountInterfaces() const;
189 		const BUSBInterface			*InterfaceAt(uint32 index) const;
190 
191 private:
192 friend	class BUSBDevice;
193 									BUSBConfiguration(BUSBDevice *device,
194 										uint32 index, int rawFD);
195 									~BUSBConfiguration();
196 
197 		BUSBDevice					*fDevice;
198 		uint32						fIndex;
199 		int							fRawFD;
200 
201 		usb_configuration_descriptor fDescriptor;
202 		BUSBInterface				**fInterfaces;
203 
204 mutable	char						*fConfigurationString;
205 
206 		uint32						fReserved[10];
207 };
208 
209 
210 /*	The BUSBInterface class can be used to access the descriptor fields of
211 	an underleying USB interface. Most importantly though it can be used to
212 	iterate over and retrieve BUSBEndpoint objects that can be used to
213 	transfer data over the bus. */
214 class BUSBInterface {
215 public:
216 		// Configuration() returns the parent configuration of this interface.
217 		// This interface is located at the index returned by Index() in that
218 		// parent configuration.
219 		// Device() is a convenience function to directly reach the parent
220 		// device of this interface instead of going through the configuration.
221 		uint32						Index() const;
222 		const BUSBConfiguration		*Configuration() const;
223 		const BUSBDevice			*Device() const;
224 
225 		// These are accessors to descriptor fields. InterfaceString() tries
226 		// to return a describing string of this interface. If no string is
227 		// available an empty string will be returned.
228 		uint8						Class() const;
229 		uint8						Subclass() const;
230 		uint8						Protocol() const;
231 		const char					*InterfaceString() const;
232 
233 		const usb_interface_descriptor
234 									*Descriptor() const;
235 
236 		// Use OtherDescriptorAt() to get generic descriptors of an interface.
237 		// These are usually vendor or device specific extensions.
238 		status_t					OtherDescriptorAt(uint32 index,
239 										usb_descriptor *descriptor,
240 										size_t length) const;
241 
242 		// CountEndpoints() and EndpointAt() can be used to iterate over the
243 		// available endpoints within an interface. EndpointAt() is the only
244 		// valid way to get BUSBEndpoint object. Note that these objects will
245 		// get invalid and deleted as soon as the parent interface is deleted.
246 		uint32						CountEndpoints() const;
247 		const BUSBEndpoint			*EndpointAt(uint32 index) const;
248 
249 		// Using CountAlternates() you can retrieve the number of alternate
250 		// interfaces for this interface. Note that this interface itself
251 		// counts as an alternate so an alternate count of one really means
252 		// that you are currently using the sole interface present.
253 		// AlternateAt() returns the interface descriptor of the alternate
254 		// interface with the specified index. Using that you can peek at the
255 		// information contained in the descriptor without having to switch
256 		// to this alternate interface. Note that the alternate index set in
257 		// the interface descriptor returned is not necessarily the same index
258 		// you used to get the descriptor. Always use the zero based index you
259 		// used to get the information with and not the values of the returned
260 		// descriptor as the stack will handle that translation internally.
261 		// The interface descriptor returned was allocated by new and is yours.
262 		// You need to delete it when you're done with it.
263 		// With SetAlternate() you can switch this BUSBInterface object to the
264 		// alternate interface at the specified index. Note that all endpoints
265 		// retrieved through EndpointAt() will become invalid and will be
266 		// deleted as soon as you set an alternate interface (even if the
267 		// resulting interface is the same you were using before).
268 		uint32						CountAlternates() const;
269 		usb_interface_descriptor	*AlternateAt(uint32 alternateIndex);
270 		status_t					SetAlternate(uint32 alternateIndex);
271 
272 private:
273 friend	class BUSBConfiguration;
274 									BUSBInterface(BUSBConfiguration *config,
275 										uint32 index, int rawFD);
276 									~BUSBInterface();
277 
278 		void						_UpdateDescriptorAndEndpoints();
279 
280 		BUSBConfiguration			*fConfiguration;
281 		uint32						fIndex;
282 		int							fRawFD;
283 
284 		usb_interface_descriptor	fDescriptor;
285 		BUSBEndpoint				**fEndpoints;
286 
287 mutable	char						*fInterfaceString;
288 
289 		uint32						fReserved[10];
290 };
291 
292 
293 /*	The BUSBEndpoint represent a device endpoint that can be used to send or
294 	receive data. It also allows to query endpoint characteristics like
295 	endpoint type or direction. */
296 class BUSBEndpoint {
297 public:
298 		// Interface() returns the parent interface of this endpoint.
299 		// This endpoint is located at the index returned by Index() in the
300 		// parent interface.
301 		// Configuration() and Device() are convenience functions to directly
302 		// reach the parent configuration or device of this endpoint instead
303 		// of going through the parent objects.
304 		uint32						Index() const;
305 		const BUSBInterface			*Interface() const;
306 		const BUSBConfiguration		*Configuration() const;
307 		const BUSBDevice			*Device() const;
308 
309 		// These methods can be used to check for endpoint characteristics.
310 		bool						IsBulk() const;
311 		bool						IsInterrupt() const;
312 		bool						IsIsochronous() const;
313 		bool						IsControl() const;
314 
315 		bool						IsInput() const;
316 		bool						IsOutput() const;
317 
318 		uint16						MaxPacketSize() const;
319 		uint8						Interval() const;
320 
321 		const usb_endpoint_descriptor
322 									*Descriptor() const;
323 
324 		// These methods initiate transfers to or from the endpoint. All
325 		// transfers are synchronous and the actually transfered amount of
326 		// data is returned as a result. A negative value indicates an error.
327 		// Which transfer type to use depends on the endpoint type.
328 		ssize_t						ControlTransfer(uint8 requestType,
329 										uint8 request, uint16 value,
330 										uint16 index, uint16 length,
331 										void *data) const;
332 		ssize_t						InterruptTransfer(void *data,
333 										size_t length) const;
334 		ssize_t						BulkTransfer(void *data,
335 										size_t length) const;
336 		ssize_t						IsochronousTransfer(void *data,
337 										size_t length,
338 										usb_iso_packet_descriptor *packetDescriptors,
339 										uint32 packetCount)	const;
340 
341 		// These are convenience methods for getting and clearing the halt
342 		// state of an endpoint. They use the control pipe of the device to
343 		// send the corresponding requests.
344 		bool						IsStalled() const;
345 		status_t					ClearStall() const;
346 private:
347 friend	class BUSBInterface;
348 									BUSBEndpoint(BUSBInterface *interface,
349 										uint32 index, int rawFD);
350 									~BUSBEndpoint();
351 
352 		BUSBInterface				*fInterface;
353 		uint32						fIndex;
354 		int							fRawFD;
355 
356 		usb_endpoint_descriptor		fDescriptor;
357 
358 		uint32						fReserved[10];
359 };
360 
361 #endif
362