xref: /haiku/src/add-ons/kernel/bus_managers/usb/usb.cpp (revision dd249016c21ffe708e053b8c746633ad42b4c412)
196da8285SMichael Lotz /*
296da8285SMichael Lotz  * Copyright 2003-2006, Haiku Inc. All rights reserved.
396da8285SMichael Lotz  * Distributed under the terms of the MIT License.
496da8285SMichael Lotz  *
596da8285SMichael Lotz  * Authors:
65b0ec61fSMichael Lotz  *		Michael Lotz <mmlr@mlotz.ch>
796da8285SMichael Lotz  *		Niels S. Reedijk
896da8285SMichael Lotz  */
91501c2bfSNiels Sascha Reedijk 
1021c87a5dSJérôme Duval 
111501c2bfSNiels Sascha Reedijk #include <util/kernel_cpp.h>
12853e6be8SMichael Lotz #include "usb_private.h"
131bad4a4eSMichael Lotz #include <USB_rle.h>
141501c2bfSNiels Sascha Reedijk 
15f14fe767SMichael Lotz #define USB_MODULE_NAME "module"
1696da8285SMichael Lotz 
17b8c6a851SMichael Lotz Stack *gUSBStack = NULL;
18b8c6a851SMichael Lotz 
19b8c6a851SMichael Lotz 
20159aa93bSMichael Lotz /*!	The function is an evil hack to allow <tt> <kdebug>usb_keyboard </tt> to
21159aa93bSMichael Lotz 	execute transfers.
22159aa93bSMichael Lotz 	When invoked the first time, a new transfer is started, each time the
23159aa93bSMichael Lotz 	function is called afterwards, it is checked whether the transfer is already
24159aa93bSMichael Lotz 	completed. If called with argv[1] == "cancel" the function cancels a
25159aa93bSMichael Lotz 	possibly pending transfer.
26159aa93bSMichael Lotz */
27159aa93bSMichael Lotz static status_t
28159aa93bSMichael Lotz debug_run_transfer(Pipe *pipe, uint8 *data, size_t dataLength,
29159aa93bSMichael Lotz 	usb_request_data *requestData, bool cancel)
30159aa93bSMichael Lotz {
31159aa93bSMichael Lotz 	static uint8 transferBuffer[sizeof(Transfer)]
32159aa93bSMichael Lotz 		__attribute__((aligned(16)));
33159aa93bSMichael Lotz 	static Transfer *transfer = NULL;
34159aa93bSMichael Lotz 
35159aa93bSMichael Lotz 	BusManager *bus = pipe->GetBusManager();
36159aa93bSMichael Lotz 
37159aa93bSMichael Lotz 	if (cancel) {
38159aa93bSMichael Lotz 		if (transfer != NULL) {
39159aa93bSMichael Lotz 			bus->CancelDebugTransfer(transfer);
40159aa93bSMichael Lotz 			transfer = NULL;
41159aa93bSMichael Lotz 		}
42159aa93bSMichael Lotz 
43159aa93bSMichael Lotz 		return B_OK;
44159aa93bSMichael Lotz 	}
45159aa93bSMichael Lotz 
46159aa93bSMichael Lotz 	if (transfer != NULL) {
47159aa93bSMichael Lotz 		status_t error = bus->CheckDebugTransfer(transfer);
48159aa93bSMichael Lotz 		if (error != B_DEV_PENDING)
49159aa93bSMichael Lotz 			transfer = NULL;
50159aa93bSMichael Lotz 
51159aa93bSMichael Lotz 		return error;
52159aa93bSMichael Lotz 	}
53159aa93bSMichael Lotz 
54159aa93bSMichael Lotz 	transfer = new(transferBuffer) Transfer(pipe);
55159aa93bSMichael Lotz 	transfer->SetData(data, dataLength);
56159aa93bSMichael Lotz 	transfer->SetRequestData(requestData);
57159aa93bSMichael Lotz 
58159aa93bSMichael Lotz 	status_t error = bus->StartDebugTransfer(transfer);
59159aa93bSMichael Lotz 	if (error != B_OK) {
60159aa93bSMichael Lotz 		transfer = NULL;
61159aa93bSMichael Lotz 		return error;
62159aa93bSMichael Lotz 	}
63159aa93bSMichael Lotz 
64159aa93bSMichael Lotz 	return B_DEV_PENDING;
65159aa93bSMichael Lotz }
66159aa93bSMichael Lotz 
67159aa93bSMichael Lotz 
686eba0636SMichael Lotz static int
696eba0636SMichael Lotz debug_get_pipe_for_id(int argc, char **argv)
706eba0636SMichael Lotz {
716eba0636SMichael Lotz 	if (gUSBStack == NULL)
726eba0636SMichael Lotz 		return 1;
736eba0636SMichael Lotz 
746eba0636SMichael Lotz 	if (!is_debug_variable_defined("_usbPipeID"))
756eba0636SMichael Lotz 		return 2;
766eba0636SMichael Lotz 
776eba0636SMichael Lotz 	uint64 id = get_debug_variable("_usbPipeID", 0);
786eba0636SMichael Lotz 	Object *object = gUSBStack->GetObjectNoLock((usb_id)id);
796eba0636SMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
806eba0636SMichael Lotz 		return 3;
816eba0636SMichael Lotz 
826eba0636SMichael Lotz 	set_debug_variable("_usbPipe", (uint64)object);
836eba0636SMichael Lotz 	return 0;
846eba0636SMichael Lotz }
85159aa93bSMichael Lotz 
86159aa93bSMichael Lotz 
87159aa93bSMichael Lotz static int
88159aa93bSMichael Lotz debug_process_transfer(int argc, char **argv)
89159aa93bSMichael Lotz {
90159aa93bSMichael Lotz 	Pipe *pipe = (Pipe *)get_debug_variable("_usbPipe", 0);
91159aa93bSMichael Lotz 	if (pipe == NULL)
92159aa93bSMichael Lotz 		return B_BAD_VALUE;
93159aa93bSMichael Lotz 
94159aa93bSMichael Lotz 	uint8 *data = (uint8 *)get_debug_variable("_usbTransferData", 0);
95159aa93bSMichael Lotz 	size_t length = (size_t)get_debug_variable("_usbTransferLength", 0);
96159aa93bSMichael Lotz 	usb_request_data *requestData
97159aa93bSMichael Lotz 		= (usb_request_data *)get_debug_variable("_usbRequestData", 0);
98159aa93bSMichael Lotz 
99159aa93bSMichael Lotz 	return debug_run_transfer(pipe, data, length, requestData,
100159aa93bSMichael Lotz 		argc > 1 && strcmp(argv[1], "cancel") == 0);
101159aa93bSMichael Lotz }
102e31cac6eSMichael Lotz 
103e31cac6eSMichael Lotz 
104e31cac6eSMichael Lotz static int
105e31cac6eSMichael Lotz debug_clear_stall(int argc, char *argv[])
106e31cac6eSMichael Lotz {
107e31cac6eSMichael Lotz 	Pipe *pipe = (Pipe *)get_debug_variable("_usbPipe", 0);
108e31cac6eSMichael Lotz 	if (pipe == NULL)
109e31cac6eSMichael Lotz 		return B_BAD_VALUE;
110e31cac6eSMichael Lotz 
111e31cac6eSMichael Lotz 	static usb_request_data requestData;
112e31cac6eSMichael Lotz 
113e31cac6eSMichael Lotz 	requestData.RequestType = USB_REQTYPE_STANDARD | USB_REQTYPE_ENDPOINT_OUT;
114e31cac6eSMichael Lotz 	requestData.Request = USB_REQUEST_CLEAR_FEATURE;
115e31cac6eSMichael Lotz 	requestData.Value = USB_FEATURE_ENDPOINT_HALT;
116e31cac6eSMichael Lotz 	requestData.Index = pipe->EndpointAddress()
117e31cac6eSMichael Lotz 		| (pipe->Direction() == Pipe::In ? USB_ENDPOINT_ADDR_DIR_IN
118e31cac6eSMichael Lotz 			: USB_ENDPOINT_ADDR_DIR_OUT);
119e31cac6eSMichael Lotz 	requestData.Length = 0;
120e31cac6eSMichael Lotz 
121e31cac6eSMichael Lotz 	Pipe *parentPipe = ((Device *)pipe->Parent())->DefaultPipe();
122e31cac6eSMichael Lotz 	for (int tries = 0; tries < 100; tries++) {
123e31cac6eSMichael Lotz 		status_t result
124e31cac6eSMichael Lotz 			= debug_run_transfer(parentPipe, NULL, 0, &requestData, false);
125e31cac6eSMichael Lotz 
126e31cac6eSMichael Lotz 		if (result == B_DEV_PENDING)
127e31cac6eSMichael Lotz 			continue;
128e31cac6eSMichael Lotz 
129e31cac6eSMichael Lotz 		if (result == B_OK) {
130e31cac6eSMichael Lotz 			// clearing a stalled condition resets the data toggle
131e31cac6eSMichael Lotz 			pipe->SetDataToggle(false);
132e31cac6eSMichael Lotz 			return B_OK;
133e31cac6eSMichael Lotz 		}
134e31cac6eSMichael Lotz 
135e31cac6eSMichael Lotz 		return result;
136e31cac6eSMichael Lotz 	}
137e31cac6eSMichael Lotz 
138e31cac6eSMichael Lotz 	return B_TIMED_OUT;
139e31cac6eSMichael Lotz }
1406eba0636SMichael Lotz 
1416eba0636SMichael Lotz 
1421501c2bfSNiels Sascha Reedijk static int32
1431501c2bfSNiels Sascha Reedijk bus_std_ops(int32 op, ...)
1441501c2bfSNiels Sascha Reedijk {
1451501c2bfSNiels Sascha Reedijk 	switch (op) {
14696da8285SMichael Lotz 		case B_MODULE_INIT: {
147f14fe767SMichael Lotz 			TRACE_MODULE("init\n");
1485b0ec61fSMichael Lotz 			if (gUSBStack)
1495b0ec61fSMichael Lotz 				return B_OK;
1505b0ec61fSMichael Lotz 
15196da8285SMichael Lotz #ifdef TRACE_USB
1521a2e81b5SNiels Sascha Reedijk 			set_dprintf_enabled(true);
15302ce23a1SMichael Lotz #endif
154b8c6a851SMichael Lotz 			Stack *stack = new(std::nothrow) Stack();
155f14fe767SMichael Lotz 			TRACE_MODULE("usb_module: stack created %p\n", stack);
156b8c6a851SMichael Lotz 			if (!stack)
157b8c6a851SMichael Lotz 				return B_NO_MEMORY;
158b8c6a851SMichael Lotz 
15996da8285SMichael Lotz 			if (stack->InitCheck() != B_OK) {
1601a2e81b5SNiels Sascha Reedijk 				delete stack;
1611501c2bfSNiels Sascha Reedijk 				return ENODEV;
1621501c2bfSNiels Sascha Reedijk 			}
16396da8285SMichael Lotz 
164eb6a1cbcSMichael Lotz 			gUSBStack = stack;
165eb01fb72SMichael Lotz 
1666eba0636SMichael Lotz 			add_debugger_command("get_usb_pipe_for_id",
1676eba0636SMichael Lotz 				&debug_get_pipe_for_id,
168159aa93bSMichael Lotz 				"Sets _usbPipe by resolving _usbPipeID");
169159aa93bSMichael Lotz 			add_debugger_command("usb_process_transfer",
170159aa93bSMichael Lotz 				&debug_process_transfer,
171159aa93bSMichael Lotz 				"Transfers _usbTransferData with _usbTransferLength"
172159aa93bSMichael Lotz 				" (and/or _usbRequestData) to pipe _usbPipe");
173e31cac6eSMichael Lotz 			add_debugger_command("usb_clear_stall",
174e31cac6eSMichael Lotz 				&debug_clear_stall,
175e31cac6eSMichael Lotz 				"Tries to issue a clear feature request for the endpoint halt"
176e31cac6eSMichael Lotz 				" feature on pipe _usbPipe");
1771501c2bfSNiels Sascha Reedijk 			break;
17896da8285SMichael Lotz 		}
17996da8285SMichael Lotz 
1801501c2bfSNiels Sascha Reedijk 		case B_MODULE_UNINIT:
181f14fe767SMichael Lotz 			TRACE_MODULE("uninit\n");
182b8c6a851SMichael Lotz 			delete gUSBStack;
183b8c6a851SMichael Lotz 			gUSBStack = NULL;
184eb01fb72SMichael Lotz 
1856eba0636SMichael Lotz 			remove_debugger_command("get_usb_pipe_for_id",
1866eba0636SMichael Lotz 				&debug_get_pipe_for_id);
1871501c2bfSNiels Sascha Reedijk 			break;
18896da8285SMichael Lotz 
1891501c2bfSNiels Sascha Reedijk 		default:
1901501c2bfSNiels Sascha Reedijk 			return EINVAL;
1911501c2bfSNiels Sascha Reedijk 	}
19296da8285SMichael Lotz 
1931501c2bfSNiels Sascha Reedijk 	return B_OK;
1941501c2bfSNiels Sascha Reedijk }
1951501c2bfSNiels Sascha Reedijk 
1961501c2bfSNiels Sascha Reedijk 
197b8c6a851SMichael Lotz status_t
198b8c6a851SMichael Lotz register_driver(const char *driverName,
199b8c6a851SMichael Lotz 	const usb_support_descriptor *descriptors,
200b8c6a851SMichael Lotz 	size_t count, const char *optionalRepublishDriverName)
201b8c6a851SMichael Lotz {
202b8c6a851SMichael Lotz 	return gUSBStack->RegisterDriver(driverName, descriptors, count,
203b8c6a851SMichael Lotz 		optionalRepublishDriverName);
204b8c6a851SMichael Lotz }
205b8c6a851SMichael Lotz 
206b8c6a851SMichael Lotz 
207b8c6a851SMichael Lotz status_t
208b8c6a851SMichael Lotz install_notify(const char *driverName, const usb_notify_hooks *hooks)
209b8c6a851SMichael Lotz {
210b8c6a851SMichael Lotz 	return gUSBStack->InstallNotify(driverName, hooks);
211b8c6a851SMichael Lotz }
212b8c6a851SMichael Lotz 
213b8c6a851SMichael Lotz 
214b8c6a851SMichael Lotz status_t
215b8c6a851SMichael Lotz uninstall_notify(const char *driverName)
216b8c6a851SMichael Lotz {
217b8c6a851SMichael Lotz 	return gUSBStack->UninstallNotify(driverName);
218b8c6a851SMichael Lotz }
219b8c6a851SMichael Lotz 
220b8c6a851SMichael Lotz 
221b8c6a851SMichael Lotz const usb_device_descriptor *
222*dd249016SAugustin Cavalier get_device_descriptor(usb_device dev)
223b8c6a851SMichael Lotz {
224*dd249016SAugustin Cavalier 	TRACE_MODULE("get_device_descriptor(%" B_PRId32 ")\n", dev);
225*dd249016SAugustin Cavalier 	Object *object = gUSBStack->GetObject(dev);
2265b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
227b8c6a851SMichael Lotz 		return NULL;
228*dd249016SAugustin Cavalier 	Device *device = (Device *)object;
229*dd249016SAugustin Cavalier 	if (device->InitCheck() != B_OK)
230*dd249016SAugustin Cavalier 		return NULL;
231b8c6a851SMichael Lotz 
232*dd249016SAugustin Cavalier 	return device->DeviceDescriptor();
233b8c6a851SMichael Lotz }
234b8c6a851SMichael Lotz 
235b8c6a851SMichael Lotz 
236b8c6a851SMichael Lotz const usb_configuration_info *
237*dd249016SAugustin Cavalier get_nth_configuration(usb_device dev, uint32 index)
238b8c6a851SMichael Lotz {
239d8b4cfc9SRene Gollent 	TRACE_MODULE("get_nth_configuration(%" B_PRId32 ", %" B_PRIu32 ")\n",
240*dd249016SAugustin Cavalier 		dev, index);
241*dd249016SAugustin Cavalier 	Object *object = gUSBStack->GetObject(dev);
2425b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
243b8c6a851SMichael Lotz 		return NULL;
244*dd249016SAugustin Cavalier 	Device *device = (Device *)object;
245*dd249016SAugustin Cavalier 	if (device->InitCheck() != B_OK)
246*dd249016SAugustin Cavalier 		return NULL;
247b8c6a851SMichael Lotz 
248*dd249016SAugustin Cavalier 	return device->ConfigurationAt((int32)index);
249b8c6a851SMichael Lotz }
250b8c6a851SMichael Lotz 
251b8c6a851SMichael Lotz 
252b8c6a851SMichael Lotz const usb_configuration_info *
253*dd249016SAugustin Cavalier get_configuration(usb_device dev)
254b8c6a851SMichael Lotz {
255*dd249016SAugustin Cavalier 	TRACE_MODULE("get_configuration(%" B_PRId32 ")\n", dev);
256*dd249016SAugustin Cavalier 	Object *object = gUSBStack->GetObject(dev);
2575b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
258b8c6a851SMichael Lotz 		return NULL;
259*dd249016SAugustin Cavalier 	Device *device = (Device *)object;
260*dd249016SAugustin Cavalier 	if (device->InitCheck() != B_OK)
261*dd249016SAugustin Cavalier 		return NULL;
262b8c6a851SMichael Lotz 
263*dd249016SAugustin Cavalier 	return device->Configuration();
264b8c6a851SMichael Lotz }
265b8c6a851SMichael Lotz 
266b8c6a851SMichael Lotz 
267b8c6a851SMichael Lotz status_t
268*dd249016SAugustin Cavalier set_configuration(usb_device dev,
269b8c6a851SMichael Lotz 	const usb_configuration_info *configuration)
270b8c6a851SMichael Lotz {
271*dd249016SAugustin Cavalier 	TRACE_MODULE("set_configuration(%" B_PRId32 ", %p)\n", dev,
272d8b4cfc9SRene Gollent 		configuration);
273*dd249016SAugustin Cavalier 	Object *object = gUSBStack->GetObject(dev);
2745b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
27517f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
276*dd249016SAugustin Cavalier 	Device *device = (Device *)object;
277*dd249016SAugustin Cavalier 	if (device->InitCheck() != B_OK)
278*dd249016SAugustin Cavalier 		return B_NO_INIT;
279b8c6a851SMichael Lotz 
280*dd249016SAugustin Cavalier 	return device->SetConfiguration(configuration);
281b8c6a851SMichael Lotz }
282b8c6a851SMichael Lotz 
283b8c6a851SMichael Lotz 
284b8c6a851SMichael Lotz status_t
285*dd249016SAugustin Cavalier set_alt_interface(usb_device dev, const usb_interface_info *interface)
286b8c6a851SMichael Lotz {
287*dd249016SAugustin Cavalier 	TRACE_MODULE("set_alt_interface(%" B_PRId32 ", %p)\n", dev, interface);
288*dd249016SAugustin Cavalier 	Object *object = gUSBStack->GetObject(dev);
2895b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
29017f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
291*dd249016SAugustin Cavalier 	Device *device = (Device *)object;
292*dd249016SAugustin Cavalier 	if (device->InitCheck() != B_OK)
293*dd249016SAugustin Cavalier 		return B_NO_INIT;
2945b0ec61fSMichael Lotz 
295*dd249016SAugustin Cavalier 	return device->SetAltInterface(interface);
296b8c6a851SMichael Lotz }
297b8c6a851SMichael Lotz 
298b8c6a851SMichael Lotz 
299b8c6a851SMichael Lotz status_t
3005b0ec61fSMichael Lotz set_feature(usb_id handle, uint16 selector)
301b8c6a851SMichael Lotz {
302d8b4cfc9SRene Gollent 	TRACE_MODULE("set_feature(%" B_PRId32 ", %d)\n", handle, selector);
3035b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(handle);
3048fedfdfcSMichael Lotz 	if (!object)
30517f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
306b8c6a851SMichael Lotz 
3078fedfdfcSMichael Lotz 	return object->SetFeature(selector);
308b8c6a851SMichael Lotz }
309b8c6a851SMichael Lotz 
310b8c6a851SMichael Lotz 
311b8c6a851SMichael Lotz status_t
3125b0ec61fSMichael Lotz clear_feature(usb_id handle, uint16 selector)
313b8c6a851SMichael Lotz {
314d8b4cfc9SRene Gollent 	TRACE_MODULE("clear_feature(%" B_PRId32 ", %d)\n", handle, selector);
3155b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(handle);
3168fedfdfcSMichael Lotz 	if (!object)
31717f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
318b8c6a851SMichael Lotz 
3198fedfdfcSMichael Lotz 	return object->ClearFeature(selector);
320b8c6a851SMichael Lotz }
321b8c6a851SMichael Lotz 
322b8c6a851SMichael Lotz 
323b8c6a851SMichael Lotz status_t
3245b0ec61fSMichael Lotz get_status(usb_id handle, uint16 *status)
325b8c6a851SMichael Lotz {
326d8b4cfc9SRene Gollent 	TRACE_MODULE("get_status(%" B_PRId32 ", %p)\n", handle, status);
3275b0ec61fSMichael Lotz 	if (!status)
3285b0ec61fSMichael Lotz 		return B_BAD_VALUE;
3295b0ec61fSMichael Lotz 
3305b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(handle);
3318fedfdfcSMichael Lotz 	if (!object)
33217f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
333b8c6a851SMichael Lotz 
3348fedfdfcSMichael Lotz 	return object->GetStatus(status);
335b8c6a851SMichael Lotz }
336b8c6a851SMichael Lotz 
337b8c6a851SMichael Lotz 
338b8c6a851SMichael Lotz status_t
339*dd249016SAugustin Cavalier get_descriptor(usb_device dev, uint8 type, uint8 index, uint16 languageID,
3405b0ec61fSMichael Lotz 	void *data, size_t dataLength, size_t *actualLength)
341b8c6a851SMichael Lotz {
342d8b4cfc9SRene Gollent 	TRACE_MODULE("get_descriptor(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, %p, "
343d8b4cfc9SRene Gollent 		"%" B_PRIuSIZE ", %p)\n",
344*dd249016SAugustin Cavalier 		dev, type, index, languageID, data, dataLength, actualLength);
345*dd249016SAugustin Cavalier 	Object *object = gUSBStack->GetObject(dev);
3465b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
34717f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
348*dd249016SAugustin Cavalier 	Device *device = (Device *)object;
349*dd249016SAugustin Cavalier 	if (device->InitCheck() != B_OK)
350*dd249016SAugustin Cavalier 		return B_NO_INIT;
351b8c6a851SMichael Lotz 
352*dd249016SAugustin Cavalier 	return device->GetDescriptor(type, index, languageID,
353b8c6a851SMichael Lotz 		data, dataLength, actualLength);
354b8c6a851SMichael Lotz }
355b8c6a851SMichael Lotz 
356b8c6a851SMichael Lotz 
357b8c6a851SMichael Lotz status_t
358*dd249016SAugustin Cavalier send_request(usb_device dev, uint8 requestType, uint8 request,
3595b0ec61fSMichael Lotz 	uint16 value, uint16 index, uint16 length, void *data, size_t *actualLength)
360b8c6a851SMichael Lotz {
361d8b4cfc9SRene Gollent 	TRACE_MODULE("send_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x, "
362*dd249016SAugustin Cavalier 		"%d, %p, %p)\n", dev, requestType, request, value, index, length,
363d8b4cfc9SRene Gollent 		data, actualLength);
364*dd249016SAugustin Cavalier 	Object *object = gUSBStack->GetObject(dev);
3655b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
36617f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
367*dd249016SAugustin Cavalier 	Device *device = (Device *)object;
368*dd249016SAugustin Cavalier 	if (device->InitCheck() != B_OK)
369*dd249016SAugustin Cavalier 		return B_NO_INIT;
370b8c6a851SMichael Lotz 
371*dd249016SAugustin Cavalier 	return device->DefaultPipe()->SendRequest(requestType, request,
3728fedfdfcSMichael Lotz 		value, index, length, data, length, actualLength);
373b8c6a851SMichael Lotz }
374b8c6a851SMichael Lotz 
375b8c6a851SMichael Lotz 
376b8c6a851SMichael Lotz status_t
377*dd249016SAugustin Cavalier queue_request(usb_device dev, uint8 requestType, uint8 request,
3785b0ec61fSMichael Lotz 	uint16 value, uint16 index, uint16 length, void *data,
379b8c6a851SMichael Lotz 	usb_callback_func callback, void *callbackCookie)
380b8c6a851SMichael Lotz {
381d8b4cfc9SRene Gollent 	TRACE_MODULE("queue_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x,"
382*dd249016SAugustin Cavalier 		" %u, %p, %p, %p)\n", dev, requestType, request, value, index,
383d8b4cfc9SRene Gollent 		length, data, callback,	callbackCookie);
384*dd249016SAugustin Cavalier 	Object *object = gUSBStack->GetObject(dev);
3855b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
38617f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
387*dd249016SAugustin Cavalier 	Device *device = (Device *)object;
388*dd249016SAugustin Cavalier 	if (device->InitCheck() != B_OK)
389*dd249016SAugustin Cavalier 		return B_NO_INIT;
390b8c6a851SMichael Lotz 
391*dd249016SAugustin Cavalier 	return device->DefaultPipe()->QueueRequest(requestType,
3928fedfdfcSMichael Lotz 		request, value, index, length, data, length, callback, callbackCookie);
393b8c6a851SMichael Lotz }
394b8c6a851SMichael Lotz 
395b8c6a851SMichael Lotz 
396b8c6a851SMichael Lotz status_t
3975b0ec61fSMichael Lotz queue_interrupt(usb_pipe pipe, void *data, size_t dataLength,
398b8c6a851SMichael Lotz 	usb_callback_func callback, void *callbackCookie)
399b8c6a851SMichael Lotz {
400d8b4cfc9SRene Gollent 	TRACE_MODULE("queue_interrupt(%" B_PRId32 ", %p, %ld, %p, %p)\n",
401f14fe767SMichael Lotz 		pipe, data, dataLength, callback, callbackCookie);
4025b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(pipe);
4035b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0)
40417f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
405b8c6a851SMichael Lotz 
4065b0ec61fSMichael Lotz 	return ((InterruptPipe *)object)->QueueInterrupt(data, dataLength, callback,
407b8c6a851SMichael Lotz 		callbackCookie);
408b8c6a851SMichael Lotz }
409b8c6a851SMichael Lotz 
410b8c6a851SMichael Lotz 
411b8c6a851SMichael Lotz status_t
4125b0ec61fSMichael Lotz queue_bulk(usb_pipe pipe, void *data, size_t dataLength,
413b8c6a851SMichael Lotz 	usb_callback_func callback, void *callbackCookie)
414b8c6a851SMichael Lotz {
415d8b4cfc9SRene Gollent 	TRACE_MODULE("queue_bulk(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, %p)\n",
416f14fe767SMichael Lotz 		pipe, data, dataLength, callback, callbackCookie);
4175b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(pipe);
4185b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
41917f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
420b8c6a851SMichael Lotz 
4215b0ec61fSMichael Lotz 	return ((BulkPipe *)object)->QueueBulk(data, dataLength, callback,
422b8c6a851SMichael Lotz 		callbackCookie);
423b8c6a851SMichael Lotz }
424b8c6a851SMichael Lotz 
425b8c6a851SMichael Lotz 
426b8c6a851SMichael Lotz status_t
4275b0ec61fSMichael Lotz queue_bulk_v(usb_pipe pipe, iovec *vector, size_t vectorCount,
4285b0ec61fSMichael Lotz 	usb_callback_func callback, void *callbackCookie)
429b8c6a851SMichael Lotz {
430d8b4cfc9SRene Gollent 	TRACE_MODULE("queue_bulk_v(%" B_PRId32 ", %p, %" B_PRIuSIZE " %p, %p)\n",
431f14fe767SMichael Lotz 		pipe, vector, vectorCount, callback, callbackCookie);
4325b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(pipe);
4335b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
43417f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
435b8c6a851SMichael Lotz 
4361e8c0b36SMichael Lotz 	return ((BulkPipe *)object)->QueueBulkV(vector, vectorCount, callback,
43772457eddSMichael Lotz 		callbackCookie, false);
43872457eddSMichael Lotz }
43972457eddSMichael Lotz 
44072457eddSMichael Lotz 
44172457eddSMichael Lotz status_t
44272457eddSMichael Lotz queue_bulk_v_physical(usb_pipe pipe, iovec *vector, size_t vectorCount,
44372457eddSMichael Lotz 	usb_callback_func callback, void *callbackCookie)
44472457eddSMichael Lotz {
445d8b4cfc9SRene Gollent 	TRACE_MODULE("queue_bulk_v_physical(%" B_PRId32 ", %p, %" B_PRIuSIZE
446d8b4cfc9SRene Gollent 		", %p, %p)\n", pipe, vector, vectorCount, callback, callbackCookie);
44772457eddSMichael Lotz 	Object *object = gUSBStack->GetObject(pipe);
44872457eddSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
44972457eddSMichael Lotz 		return B_DEV_INVALID_PIPE;
45072457eddSMichael Lotz 
45172457eddSMichael Lotz 	return ((BulkPipe *)object)->QueueBulkV(vector, vectorCount, callback,
45272457eddSMichael Lotz 		callbackCookie, true);
453b8c6a851SMichael Lotz }
454b8c6a851SMichael Lotz 
455b8c6a851SMichael Lotz 
456b8c6a851SMichael Lotz status_t
4575b0ec61fSMichael Lotz queue_isochronous(usb_pipe pipe, void *data, size_t dataLength,
4581bad4a4eSMichael Lotz 	usb_iso_packet_descriptor *packetDesc, uint32 packetCount,
4591bad4a4eSMichael Lotz 	uint32 *startingFrameNumber, uint32 flags, usb_callback_func callback,
4605b0ec61fSMichael Lotz 	void *callbackCookie)
4615b0ec61fSMichael Lotz {
462d8b4cfc9SRene Gollent 	TRACE_MODULE("queue_isochronous(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, "
463d8b4cfc9SRene Gollent 		"%" B_PRId32 ", %p, 0x%08" B_PRIx32 ", %p, %p)\n",
464f14fe767SMichael Lotz 		pipe, data, dataLength, packetDesc, packetCount, startingFrameNumber,
465f14fe767SMichael Lotz 		flags, callback, callbackCookie);
4665b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(pipe);
4675b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
46817f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
4695b0ec61fSMichael Lotz 
4705b0ec61fSMichael Lotz 	return ((IsochronousPipe *)object)->QueueIsochronous(data, dataLength,
4711bad4a4eSMichael Lotz 		packetDesc, packetCount, startingFrameNumber, flags, callback,
4721bad4a4eSMichael Lotz 		callbackCookie);
4735b0ec61fSMichael Lotz }
4745b0ec61fSMichael Lotz 
4755b0ec61fSMichael Lotz 
4765b0ec61fSMichael Lotz status_t
4775b0ec61fSMichael Lotz set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets,
4785b0ec61fSMichael Lotz 	uint16 maxBufferDurationMS, uint16 sampleSize)
4795b0ec61fSMichael Lotz {
480d8b4cfc9SRene Gollent 	TRACE_MODULE("set_pipe_policy(%" B_PRId32 ", %d, %d, %d)\n", pipe,
481d8b4cfc9SRene Gollent 		maxQueuedPackets, maxBufferDurationMS, sampleSize);
4825b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(pipe);
4835b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
48417f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
4855b0ec61fSMichael Lotz 
48600f6fab9SMichael Lotz 	return ((IsochronousPipe *)object)->SetPipePolicy(maxQueuedPackets,
48700f6fab9SMichael Lotz 		maxBufferDurationMS, sampleSize);
4885b0ec61fSMichael Lotz }
4895b0ec61fSMichael Lotz 
4905b0ec61fSMichael Lotz 
4915b0ec61fSMichael Lotz status_t
4925b0ec61fSMichael Lotz cancel_queued_transfers(usb_pipe pipe)
493b8c6a851SMichael Lotz {
494d8b4cfc9SRene Gollent 	TRACE_MODULE("cancel_queued_transfers(%" B_PRId32 ")\n", pipe);
4955b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(pipe);
4965b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
49717f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
4985b0ec61fSMichael Lotz 
49913508e8bSMichael Lotz 	return ((Pipe *)object)->CancelQueuedTransfers(false);
500b8c6a851SMichael Lotz }
501b8c6a851SMichael Lotz 
502b8c6a851SMichael Lotz 
503b8c6a851SMichael Lotz status_t
504b8c6a851SMichael Lotz usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize)
505b8c6a851SMichael Lotz {
506d8b4cfc9SRene Gollent 	TRACE_MODULE("usb_ioctl(%" B_PRIu32 ", %p, %" B_PRIuSIZE ")\n", opcode,
507d8b4cfc9SRene Gollent 		buffer, bufferSize);
50864f3c065SMichael Lotz 
50964f3c065SMichael Lotz 	switch (opcode) {
51064f3c065SMichael Lotz 		case 'DNAM': {
5115b0ec61fSMichael Lotz 			Object *object = gUSBStack->GetObject(*(usb_id *)buffer);
5125b0ec61fSMichael Lotz 			if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
5135b0ec61fSMichael Lotz 				return B_BAD_VALUE;
514*dd249016SAugustin Cavalier 			Device *device = (Device *)object;
515*dd249016SAugustin Cavalier 			if (device->InitCheck() != B_OK)
516*dd249016SAugustin Cavalier 				return B_NO_INIT;
5175b0ec61fSMichael Lotz 
51864f3c065SMichael Lotz 			uint32 index = 0;
519*dd249016SAugustin Cavalier 			return device->BuildDeviceName((char *)buffer, &index,
5205b0ec61fSMichael Lotz 				bufferSize, NULL);
52164f3c065SMichael Lotz 		}
52264f3c065SMichael Lotz 	}
52364f3c065SMichael Lotz 
52464f3c065SMichael Lotz 	return B_DEV_INVALID_IOCTL;
525b8c6a851SMichael Lotz }
526b8c6a851SMichael Lotz 
527b8c6a851SMichael Lotz 
5287e1490e0SMichael Lotz status_t
5297e1490e0SMichael Lotz get_nth_roothub(uint32 index, usb_device *rootHub)
5307e1490e0SMichael Lotz {
5317e1490e0SMichael Lotz 	if (!rootHub)
5327e1490e0SMichael Lotz 		return B_BAD_VALUE;
5337e1490e0SMichael Lotz 
5347e1490e0SMichael Lotz 	BusManager *busManager = gUSBStack->BusManagerAt(index);
5357e1490e0SMichael Lotz 	if (!busManager)
5367e1490e0SMichael Lotz 		return B_ENTRY_NOT_FOUND;
5377e1490e0SMichael Lotz 
5387e1490e0SMichael Lotz 	Hub *hub = busManager->GetRootHub();
5397e1490e0SMichael Lotz 	if (!hub)
5407e1490e0SMichael Lotz 		return B_NO_INIT;
5417e1490e0SMichael Lotz 
5427e1490e0SMichael Lotz 	*rootHub = hub->USBID();
5437e1490e0SMichael Lotz 	return B_OK;
5447e1490e0SMichael Lotz }
5457e1490e0SMichael Lotz 
5467e1490e0SMichael Lotz 
5477e1490e0SMichael Lotz status_t
5487e1490e0SMichael Lotz get_nth_child(usb_device _hub, uint8 index, usb_device *childDevice)
5497e1490e0SMichael Lotz {
5507e1490e0SMichael Lotz 	if (!childDevice)
5517e1490e0SMichael Lotz 		return B_BAD_VALUE;
5527e1490e0SMichael Lotz 
5537e1490e0SMichael Lotz 	Object *object = gUSBStack->GetObject(_hub);
5547e1490e0SMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_HUB) == 0)
5557e1490e0SMichael Lotz 		return B_DEV_INVALID_PIPE;
5567e1490e0SMichael Lotz 
5577e1490e0SMichael Lotz 	Hub *hub = (Hub *)object;
5587e1490e0SMichael Lotz 	for (uint8 i = 0; i < 8; i++) {
5597e1490e0SMichael Lotz 		if (hub->ChildAt(i) == NULL)
5607e1490e0SMichael Lotz 			continue;
5617e1490e0SMichael Lotz 
5627e1490e0SMichael Lotz 		if (index-- > 0)
5637e1490e0SMichael Lotz 			continue;
5647e1490e0SMichael Lotz 
5657e1490e0SMichael Lotz 		*childDevice = hub->ChildAt(i)->USBID();
5667e1490e0SMichael Lotz 		return B_OK;
5677e1490e0SMichael Lotz 	}
5687e1490e0SMichael Lotz 
5697e1490e0SMichael Lotz 	return B_ENTRY_NOT_FOUND;
5707e1490e0SMichael Lotz }
5717e1490e0SMichael Lotz 
5727e1490e0SMichael Lotz 
5737e1490e0SMichael Lotz status_t
5747e1490e0SMichael Lotz get_device_parent(usb_device _device, usb_device *parentHub, uint8 *portIndex)
5757e1490e0SMichael Lotz {
5767e1490e0SMichael Lotz 	if (!parentHub || !portIndex)
5777e1490e0SMichael Lotz 		return B_BAD_VALUE;
5787e1490e0SMichael Lotz 
5797e1490e0SMichael Lotz 	Object *object = gUSBStack->GetObject(_device);
5807e1490e0SMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
5817e1490e0SMichael Lotz 		return B_DEV_INVALID_PIPE;
5827e1490e0SMichael Lotz 
5837e1490e0SMichael Lotz 	Object *parent = object->Parent();
5847e1490e0SMichael Lotz 	if (!parent || (parent->Type() & USB_OBJECT_HUB) == 0)
5857e1490e0SMichael Lotz 		return B_ENTRY_NOT_FOUND;
5867e1490e0SMichael Lotz 
5877e1490e0SMichael Lotz 	Hub *hub = (Hub *)parent;
5887e1490e0SMichael Lotz 	for (uint8 i = 0; i < 8; i++) {
5897e1490e0SMichael Lotz 		if (hub->ChildAt(i) == object) {
5907e1490e0SMichael Lotz 			*portIndex = i;
5917e1490e0SMichael Lotz 			*parentHub = hub->USBID();
5927e1490e0SMichael Lotz 			return B_OK;
5937e1490e0SMichael Lotz 		}
5947e1490e0SMichael Lotz 	}
5957e1490e0SMichael Lotz 
5967e1490e0SMichael Lotz 	return B_ERROR;
5977e1490e0SMichael Lotz }
5987e1490e0SMichael Lotz 
5997e1490e0SMichael Lotz 
6007e1490e0SMichael Lotz status_t
6017e1490e0SMichael Lotz reset_port(usb_device _hub, uint8 portIndex)
6027e1490e0SMichael Lotz {
6037e1490e0SMichael Lotz 	Object *object = gUSBStack->GetObject(_hub);
6047e1490e0SMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_HUB) == 0)
6057e1490e0SMichael Lotz 		return B_DEV_INVALID_PIPE;
6067e1490e0SMichael Lotz 
6077e1490e0SMichael Lotz 	Hub *hub = (Hub *)object;
6087e1490e0SMichael Lotz 	return hub->ResetPort(portIndex);
6097e1490e0SMichael Lotz }
6107e1490e0SMichael Lotz 
6117e1490e0SMichael Lotz 
6127e1490e0SMichael Lotz status_t
6137e1490e0SMichael Lotz disable_port(usb_device _hub, uint8 portIndex)
6147e1490e0SMichael Lotz {
6157e1490e0SMichael Lotz 	Object *object = gUSBStack->GetObject(_hub);
6167e1490e0SMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_HUB) == 0)
6177e1490e0SMichael Lotz 		return B_DEV_INVALID_PIPE;
6187e1490e0SMichael Lotz 
6197e1490e0SMichael Lotz 	Hub *hub = (Hub *)object;
6207e1490e0SMichael Lotz 	return hub->DisablePort(portIndex);
6217e1490e0SMichael Lotz }
6227e1490e0SMichael Lotz 
6237e1490e0SMichael Lotz 
62496da8285SMichael Lotz /*
6255b0ec61fSMichael Lotz 	This module exports the USB API v3
62696da8285SMichael Lotz */
6275b0ec61fSMichael Lotz struct usb_module_info gModuleInfoV3 = {
6281501c2bfSNiels Sascha Reedijk 	// First the bus_manager_info:
6291501c2bfSNiels Sascha Reedijk 	{
6301501c2bfSNiels Sascha Reedijk 		{
6315b0ec61fSMichael Lotz 			"bus_managers/usb/v3",
6321501c2bfSNiels Sascha Reedijk 			B_KEEP_LOADED,				// Keep loaded, even if no driver requires it
6331501c2bfSNiels Sascha Reedijk 			bus_std_ops
6341501c2bfSNiels Sascha Reedijk 		},
6351501c2bfSNiels Sascha Reedijk 		NULL							// the rescan function
6361501c2bfSNiels Sascha Reedijk 	},
63796da8285SMichael Lotz 
638b8c6a851SMichael Lotz 	register_driver,					// register_driver
639b8c6a851SMichael Lotz 	install_notify,						// install_notify
640b8c6a851SMichael Lotz 	uninstall_notify,					// uninstall_notify
641b8c6a851SMichael Lotz 	get_device_descriptor,				// get_device_descriptor
642b8c6a851SMichael Lotz 	get_nth_configuration,				// get_nth_configuration
643b8c6a851SMichael Lotz 	get_configuration,					// get_configuration
644b8c6a851SMichael Lotz 	set_configuration,					// set_configuration
645b8c6a851SMichael Lotz 	set_alt_interface,					// set_alt_interface
646b8c6a851SMichael Lotz 	set_feature,						// set_feature
647b8c6a851SMichael Lotz 	clear_feature, 						// clear_feature
648b8c6a851SMichael Lotz 	get_status, 						// get_status
649b8c6a851SMichael Lotz 	get_descriptor,						// get_descriptor
650b8c6a851SMichael Lotz 	send_request,						// send_request
651b8c6a851SMichael Lotz 	queue_interrupt,					// queue_interrupt
652b8c6a851SMichael Lotz 	queue_bulk,							// queue_bulk
6535b0ec61fSMichael Lotz 	queue_bulk_v,						// queue_bulk_v
654b8c6a851SMichael Lotz 	queue_isochronous,					// queue_isochronous
655b8c6a851SMichael Lotz 	queue_request,						// queue_request
656b8c6a851SMichael Lotz 	set_pipe_policy,					// set_pipe_policy
657b8c6a851SMichael Lotz 	cancel_queued_transfers,			// cancel_queued_transfers
6587e1490e0SMichael Lotz 	usb_ioctl,							// usb_ioctl
6597e1490e0SMichael Lotz 	get_nth_roothub,					// get_nth_roothub
6607e1490e0SMichael Lotz 	get_nth_child,						// get_nth_child
6617e1490e0SMichael Lotz 	get_device_parent,					// get_device_parent
6627e1490e0SMichael Lotz 	reset_port,							// reset_port
6637e1490e0SMichael Lotz 	disable_port						// disable_port
66472457eddSMichael Lotz 	//queue_bulk_v_physical				// queue_bulk_v_physical
6651501c2bfSNiels Sascha Reedijk };
6661501c2bfSNiels Sascha Reedijk 
66796da8285SMichael Lotz 
6685b0ec61fSMichael Lotz //
6695b0ec61fSMichael Lotz // #pragma mark -
6705b0ec61fSMichael Lotz //
6715b0ec61fSMichael Lotz 
6725b0ec61fSMichael Lotz 
6735b0ec61fSMichael Lotz const usb_device_descriptor *
6745b0ec61fSMichael Lotz get_device_descriptor_v2(const void *device)
6755b0ec61fSMichael Lotz {
676d8b4cfc9SRene Gollent 	return get_device_descriptor((usb_id)(ssize_t)device);
6775b0ec61fSMichael Lotz }
6785b0ec61fSMichael Lotz 
6795b0ec61fSMichael Lotz 
6805b0ec61fSMichael Lotz const usb_configuration_info *
6815b0ec61fSMichael Lotz get_nth_configuration_v2(const void *device, uint index)
6825b0ec61fSMichael Lotz {
683d8b4cfc9SRene Gollent 	return get_nth_configuration((usb_id)(ssize_t)device, index);
6845b0ec61fSMichael Lotz }
6855b0ec61fSMichael Lotz 
6865b0ec61fSMichael Lotz 
6875b0ec61fSMichael Lotz const usb_configuration_info *
6885b0ec61fSMichael Lotz get_configuration_v2(const void *device)
6895b0ec61fSMichael Lotz {
690d8b4cfc9SRene Gollent 	return get_configuration((usb_id)(ssize_t)device);
6915b0ec61fSMichael Lotz }
6925b0ec61fSMichael Lotz 
6935b0ec61fSMichael Lotz 
6945b0ec61fSMichael Lotz status_t
6955b0ec61fSMichael Lotz set_configuration_v2(const void *device,
6965b0ec61fSMichael Lotz 	const usb_configuration_info *configuration)
6975b0ec61fSMichael Lotz {
698d8b4cfc9SRene Gollent 	return set_configuration((usb_id)(ssize_t)device, configuration);
6995b0ec61fSMichael Lotz }
7005b0ec61fSMichael Lotz 
7015b0ec61fSMichael Lotz 
7025b0ec61fSMichael Lotz status_t
7035b0ec61fSMichael Lotz set_alt_interface_v2(const void *device, const usb_interface_info *interface)
7045b0ec61fSMichael Lotz {
705d8b4cfc9SRene Gollent 	return set_alt_interface((usb_id)(ssize_t)device, interface);
7065b0ec61fSMichael Lotz }
7075b0ec61fSMichael Lotz 
7085b0ec61fSMichael Lotz 
7095b0ec61fSMichael Lotz status_t
7105b0ec61fSMichael Lotz set_feature_v2(const void *object, uint16 selector)
7115b0ec61fSMichael Lotz {
712d8b4cfc9SRene Gollent 	return set_feature((usb_id)(ssize_t)object, selector);
7135b0ec61fSMichael Lotz }
7145b0ec61fSMichael Lotz 
7155b0ec61fSMichael Lotz 
7165b0ec61fSMichael Lotz status_t
7175b0ec61fSMichael Lotz clear_feature_v2(const void *object, uint16 selector)
7185b0ec61fSMichael Lotz {
719d8b4cfc9SRene Gollent 	return clear_feature((usb_id)(ssize_t)object, selector);
7205b0ec61fSMichael Lotz }
7215b0ec61fSMichael Lotz 
7225b0ec61fSMichael Lotz 
7235b0ec61fSMichael Lotz status_t
7245b0ec61fSMichael Lotz get_status_v2(const void *object, uint16 *status)
7255b0ec61fSMichael Lotz {
726d8b4cfc9SRene Gollent 	return get_status((usb_id)(ssize_t)object, status);
7275b0ec61fSMichael Lotz }
7285b0ec61fSMichael Lotz 
7295b0ec61fSMichael Lotz 
7305b0ec61fSMichael Lotz status_t
7315b0ec61fSMichael Lotz get_descriptor_v2(const void *device, uint8 type, uint8 index,
7325b0ec61fSMichael Lotz 	uint16 languageID, void *data, size_t dataLength, size_t *actualLength)
7335b0ec61fSMichael Lotz {
734d8b4cfc9SRene Gollent 	return get_descriptor((usb_id)(ssize_t)device, type, index, languageID, data,
7355b0ec61fSMichael Lotz 		dataLength, actualLength);
7365b0ec61fSMichael Lotz }
7375b0ec61fSMichael Lotz 
7385b0ec61fSMichael Lotz 
7395b0ec61fSMichael Lotz status_t
7405b0ec61fSMichael Lotz send_request_v2(const void *device, uint8 requestType, uint8 request,
7415b0ec61fSMichael Lotz 	uint16 value, uint16 index, uint16 length, void *data,
7425b0ec61fSMichael Lotz 	size_t /*dataLength*/, size_t *actualLength)
7435b0ec61fSMichael Lotz {
744d8b4cfc9SRene Gollent 	return send_request((usb_id)(ssize_t)device, requestType, request, value, index,
7455b0ec61fSMichael Lotz 		length, data, actualLength);
7465b0ec61fSMichael Lotz }
7475b0ec61fSMichael Lotz 
7485b0ec61fSMichael Lotz 
7495b0ec61fSMichael Lotz status_t
7505b0ec61fSMichael Lotz queue_request_v2(const void *device, uint8 requestType, uint8 request,
7515b0ec61fSMichael Lotz 	uint16 value, uint16 index, uint16 length, void *data,
7525b0ec61fSMichael Lotz 	size_t /*dataLength*/, usb_callback_func callback, void *callbackCookie)
7535b0ec61fSMichael Lotz {
754d8b4cfc9SRene Gollent 	return queue_request((usb_id)(ssize_t)device, requestType, request, value, index,
7555b0ec61fSMichael Lotz 		length, data, callback, callbackCookie);
7565b0ec61fSMichael Lotz }
7575b0ec61fSMichael Lotz 
7585b0ec61fSMichael Lotz 
7595b0ec61fSMichael Lotz status_t
7605b0ec61fSMichael Lotz queue_interrupt_v2(const void *pipe, void *data, size_t dataLength,
7615b0ec61fSMichael Lotz 	usb_callback_func callback, void *callbackCookie)
7625b0ec61fSMichael Lotz {
763d8b4cfc9SRene Gollent 	return queue_interrupt((usb_id)(ssize_t)pipe, data, dataLength, callback,
7645b0ec61fSMichael Lotz 		callbackCookie);
7655b0ec61fSMichael Lotz }
7665b0ec61fSMichael Lotz 
7675b0ec61fSMichael Lotz 
7685b0ec61fSMichael Lotz status_t
7695b0ec61fSMichael Lotz queue_bulk_v2(const void *pipe, void *data, size_t dataLength,
7705b0ec61fSMichael Lotz 	usb_callback_func callback, void *callbackCookie)
7715b0ec61fSMichael Lotz {
772d8b4cfc9SRene Gollent 	return queue_bulk((usb_id)(ssize_t)pipe, data, dataLength, callback,
7735b0ec61fSMichael Lotz 		callbackCookie);
7745b0ec61fSMichael Lotz }
7755b0ec61fSMichael Lotz 
7765b0ec61fSMichael Lotz 
7775b0ec61fSMichael Lotz status_t
7785b0ec61fSMichael Lotz queue_isochronous_v2(const void *pipe, void *data, size_t dataLength,
7795b0ec61fSMichael Lotz 	rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback,
7805b0ec61fSMichael Lotz 	void *callbackCookie)
7815b0ec61fSMichael Lotz {
7821bad4a4eSMichael Lotz 	// ToDo: convert rlea to usb_iso_packet_descriptor
7831bad4a4eSMichael Lotz 	// ToDo: use a flag to indicate that the callback shall produce a rlea
7841bad4a4eSMichael Lotz 	usb_iso_packet_descriptor *packetDesc = NULL;
785d8b4cfc9SRene Gollent 	return queue_isochronous((usb_id)(ssize_t)pipe, data, dataLength, packetDesc, 0,
7861bad4a4eSMichael Lotz 		NULL, 0, callback, callbackCookie);
7875b0ec61fSMichael Lotz }
7885b0ec61fSMichael Lotz 
7895b0ec61fSMichael Lotz 
7905b0ec61fSMichael Lotz status_t
7915b0ec61fSMichael Lotz set_pipe_policy_v2(const void *pipe, uint8 maxQueuedPackets,
7925b0ec61fSMichael Lotz 	uint16 maxBufferDurationMS, uint16 sampleSize)
7935b0ec61fSMichael Lotz {
794d8b4cfc9SRene Gollent 	return set_pipe_policy((usb_id)(ssize_t)pipe, maxQueuedPackets, maxBufferDurationMS,
7955b0ec61fSMichael Lotz 		sampleSize);
7965b0ec61fSMichael Lotz }
7975b0ec61fSMichael Lotz 
7985b0ec61fSMichael Lotz 
7995b0ec61fSMichael Lotz status_t
8005b0ec61fSMichael Lotz cancel_queued_transfers_v2(const void *pipe)
8015b0ec61fSMichael Lotz {
802d8b4cfc9SRene Gollent 	return cancel_queued_transfers((usb_id)(ssize_t)pipe);
8035b0ec61fSMichael Lotz }
8045b0ec61fSMichael Lotz 
8055b0ec61fSMichael Lotz 
8065b0ec61fSMichael Lotz struct usb_module_info_v2 {
8075b0ec61fSMichael Lotz 	bus_manager_info				binfo;
8085b0ec61fSMichael Lotz 	status_t						(*register_driver)(const char *, const usb_support_descriptor *, size_t, const char *);
8095b0ec61fSMichael Lotz 	status_t						(*install_notify)(const char *, const usb_notify_hooks *);
8105b0ec61fSMichael Lotz 	status_t						(*uninstall_notify)(const char *);
8115b0ec61fSMichael Lotz 	const usb_device_descriptor		*(*get_device_descriptor)(const void *);
8125b0ec61fSMichael Lotz 	const usb_configuration_info	*(*get_nth_configuration)(const void *, uint);
8135b0ec61fSMichael Lotz 	const usb_configuration_info	*(*get_configuration)(const void *);
8145b0ec61fSMichael Lotz 	status_t						(*set_configuration)(const void *, const usb_configuration_info *);
8155b0ec61fSMichael Lotz 	status_t						(*set_alt_interface)(const void *, const usb_interface_info *);
8165b0ec61fSMichael Lotz 	status_t						(*set_feature)(const void *, uint16);
8175b0ec61fSMichael Lotz 	status_t						(*clear_feature)(const void *, uint16);
8185b0ec61fSMichael Lotz 	status_t						(*get_status)(const void *, uint16 *);
8195b0ec61fSMichael Lotz 	status_t						(*get_descriptor)(const void *, uint8, uint8, uint16, void *, size_t, size_t *);
8205b0ec61fSMichael Lotz 	status_t						(*send_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, size_t *);
8215b0ec61fSMichael Lotz 	status_t						(*queue_interrupt)(const void *, void *, size_t, usb_callback_func, void *);
8225b0ec61fSMichael Lotz 	status_t						(*queue_bulk)(const void *, void *, size_t, usb_callback_func, void *);
8235b0ec61fSMichael Lotz 	status_t						(*queue_isochronous)(const void *, void *, size_t, rlea *, uint16, usb_callback_func, void *);
8245b0ec61fSMichael Lotz 	status_t						(*queue_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, usb_callback_func, void *);
8255b0ec61fSMichael Lotz 	status_t						(*set_pipe_policy)(const void *, uint8, uint16, uint16);
8265b0ec61fSMichael Lotz 	status_t						(*cancel_queued_transfers)(const void *);
8275b0ec61fSMichael Lotz 	status_t						(*usb_ioctl)(uint32 opcode, void *,size_t);
8285b0ec61fSMichael Lotz };
8295b0ec61fSMichael Lotz 
8305b0ec61fSMichael Lotz 
8315b0ec61fSMichael Lotz /*
8325b0ec61fSMichael Lotz 	This module exports the USB API v2
8335b0ec61fSMichael Lotz */
8345b0ec61fSMichael Lotz struct usb_module_info_v2 gModuleInfoV2 = {
8355b0ec61fSMichael Lotz 	// First the bus_manager_info:
8365b0ec61fSMichael Lotz 	{
8375b0ec61fSMichael Lotz 		{
8385b0ec61fSMichael Lotz 			"bus_managers/usb/v2",
8395b0ec61fSMichael Lotz 			B_KEEP_LOADED,				// Keep loaded, even if no driver requires it
8405b0ec61fSMichael Lotz 			bus_std_ops
8415b0ec61fSMichael Lotz 		},
8425b0ec61fSMichael Lotz 		NULL							// the rescan function
8435b0ec61fSMichael Lotz 	},
8445b0ec61fSMichael Lotz 
8455b0ec61fSMichael Lotz 	register_driver,					// register_driver
8465b0ec61fSMichael Lotz 	install_notify,						// install_notify
8475b0ec61fSMichael Lotz 	uninstall_notify,					// uninstall_notify
8485b0ec61fSMichael Lotz 	get_device_descriptor_v2,			// get_device_descriptor
8495b0ec61fSMichael Lotz 	get_nth_configuration_v2,			// get_nth_configuration
8505b0ec61fSMichael Lotz 	get_configuration_v2,				// get_configuration
8515b0ec61fSMichael Lotz 	set_configuration_v2,				// set_configuration
8525b0ec61fSMichael Lotz 	set_alt_interface_v2,				// set_alt_interface
8535b0ec61fSMichael Lotz 	set_feature_v2,						// set_feature
8545b0ec61fSMichael Lotz 	clear_feature_v2,					// clear_feature
8555b0ec61fSMichael Lotz 	get_status_v2, 						// get_status
8565b0ec61fSMichael Lotz 	get_descriptor_v2,					// get_descriptor
8575b0ec61fSMichael Lotz 	send_request_v2,					// send_request
8585b0ec61fSMichael Lotz 	queue_interrupt_v2,					// queue_interrupt
8595b0ec61fSMichael Lotz 	queue_bulk_v2,						// queue_bulk
8605b0ec61fSMichael Lotz 	queue_isochronous_v2,				// queue_isochronous
8615b0ec61fSMichael Lotz 	queue_request_v2,					// queue_request
8625b0ec61fSMichael Lotz 	set_pipe_policy_v2,					// set_pipe_policy
8635b0ec61fSMichael Lotz 	cancel_queued_transfers_v2,			// cancel_queued_transfers
8645b0ec61fSMichael Lotz 	usb_ioctl							// usb_ioctl
8655b0ec61fSMichael Lotz };
8665b0ec61fSMichael Lotz 
8675b0ec61fSMichael Lotz 
8685b0ec61fSMichael Lotz //
8695b0ec61fSMichael Lotz // #pragma mark -
8705b0ec61fSMichael Lotz //
8715b0ec61fSMichael Lotz 
8725b0ec61fSMichael Lotz 
8731501c2bfSNiels Sascha Reedijk module_info *modules[] = {
8745b0ec61fSMichael Lotz 	(module_info *)&gModuleInfoV2,
8755b0ec61fSMichael Lotz 	(module_info *)&gModuleInfoV3,
8761501c2bfSNiels Sascha Reedijk 	NULL
8771501c2bfSNiels Sascha Reedijk };
878