xref: /haiku/src/add-ons/kernel/bus_managers/usb/usb.cpp (revision 6eafb4b041ad79cb936b2041fdb9c56b1209cc10)
1 /*
2  * Copyright 2003-2006, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Michael Lotz <mmlr@mlotz.ch>
7  *		Niels S. Reedijk
8  */
9 
10 #include <util/kernel_cpp.h>
11 #include "usb_private.h"
12 #include <USB_rle.h>
13 
14 #define USB_MODULE_NAME "module"
15 
16 Stack *gUSBStack = NULL;
17 
18 
19 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
20 /*!	The function is an evil hack to allow <tt> <kdebug>usb_keyboard </tt> to
21 	execute transfers.
22 	When invoked the first time, a new transfer is started, each time the
23 	function is called afterwards, it is checked whether the transfer is already
24 	completed. If called with argv[1] == "cancel" the function cancels a
25 	possibly pending transfer.
26 */
27 static status_t
28 debug_run_transfer(Pipe *pipe, uint8 *data, size_t dataLength,
29 	usb_request_data *requestData, bool cancel)
30 {
31 	static uint8 transferBuffer[sizeof(Transfer)]
32 		__attribute__((aligned(16)));
33 	static Transfer *transfer = NULL;
34 
35 	BusManager *bus = pipe->GetBusManager();
36 
37 	if (cancel) {
38 		if (transfer != NULL) {
39 			bus->CancelDebugTransfer(transfer);
40 			transfer = NULL;
41 		}
42 
43 		return B_OK;
44 	}
45 
46 	if (transfer != NULL) {
47 		status_t error = bus->CheckDebugTransfer(transfer);
48 		if (error != B_DEV_PENDING)
49 			transfer = NULL;
50 
51 		return error;
52 	}
53 
54 	transfer = new(transferBuffer) Transfer(pipe);
55 	transfer->SetData(data, dataLength);
56 	transfer->SetRequestData(requestData);
57 
58 	status_t error = bus->StartDebugTransfer(transfer);
59 	if (error != B_OK) {
60 		transfer = NULL;
61 		return error;
62 	}
63 
64 	return B_DEV_PENDING;
65 }
66 
67 
68 static int
69 debug_get_pipe_for_id(int argc, char **argv)
70 {
71 	if (gUSBStack == NULL)
72 		return 1;
73 
74 	if (!is_debug_variable_defined("_usbPipeID"))
75 		return 2;
76 
77 	uint64 id = get_debug_variable("_usbPipeID", 0);
78 	Object *object = gUSBStack->GetObjectNoLock((usb_id)id);
79 	if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
80 		return 3;
81 
82 	set_debug_variable("_usbPipe", (uint64)object);
83 	return 0;
84 }
85 
86 
87 static int
88 debug_process_transfer(int argc, char **argv)
89 {
90 	Pipe *pipe = (Pipe *)get_debug_variable("_usbPipe", 0);
91 	if (pipe == NULL)
92 		return B_BAD_VALUE;
93 
94 	uint8 *data = (uint8 *)get_debug_variable("_usbTransferData", 0);
95 	size_t length = (size_t)get_debug_variable("_usbTransferLength", 0);
96 	usb_request_data *requestData
97 		= (usb_request_data *)get_debug_variable("_usbRequestData", 0);
98 
99 	return debug_run_transfer(pipe, data, length, requestData,
100 		argc > 1 && strcmp(argv[1], "cancel") == 0);
101 }
102 
103 
104 static int
105 debug_clear_stall(int argc, char *argv[])
106 {
107 	Pipe *pipe = (Pipe *)get_debug_variable("_usbPipe", 0);
108 	if (pipe == NULL)
109 		return B_BAD_VALUE;
110 
111 	static usb_request_data requestData;
112 
113 	requestData.RequestType = USB_REQTYPE_STANDARD | USB_REQTYPE_ENDPOINT_OUT;
114 	requestData.Request = USB_REQUEST_CLEAR_FEATURE;
115 	requestData.Value = USB_FEATURE_ENDPOINT_HALT;
116 	requestData.Index = pipe->EndpointAddress()
117 		| (pipe->Direction() == Pipe::In ? USB_ENDPOINT_ADDR_DIR_IN
118 			: USB_ENDPOINT_ADDR_DIR_OUT);
119 	requestData.Length = 0;
120 
121 	Pipe *parentPipe = ((Device *)pipe->Parent())->DefaultPipe();
122 	for (int tries = 0; tries < 100; tries++) {
123 		status_t result
124 			= debug_run_transfer(parentPipe, NULL, 0, &requestData, false);
125 
126 		if (result == B_DEV_PENDING)
127 			continue;
128 
129 		if (result == B_OK) {
130 			// clearing a stalled condition resets the data toggle
131 			pipe->SetDataToggle(false);
132 			return B_OK;
133 		}
134 
135 		return result;
136 	}
137 
138 	return B_TIMED_OUT;
139 }
140 #endif
141 
142 
143 static int32
144 bus_std_ops(int32 op, ...)
145 {
146 	switch (op) {
147 		case B_MODULE_INIT: {
148 			TRACE_MODULE("init\n");
149 			if (gUSBStack)
150 				return B_OK;
151 
152 #ifdef HAIKU_TARGET_PLATFORM_BEOS
153 			// This code is to handle plain R5 (non-BONE) where the same module
154 			// gets loaded multiple times (once for each exported module
155 			// interface, the USB v2 and v3 API in our case). We don't want to
156 			// ever create multiple stacks however, so we "share" the same stack
157 			// for both modules by storing it's address in a shared area.
158 			void *address = NULL;
159 			area_id shared = find_area("shared usb stack");
160 			if (shared >= B_OK && clone_area("usb stack clone", &address,
161 				B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, shared) >= B_OK) {
162 				gUSBStack = *((Stack **)address);
163 				TRACE_MODULE("found shared stack at %p\n", gUSBStack);
164 				return B_OK;
165 			}
166 #endif
167 
168 #ifdef TRACE_USB
169 			set_dprintf_enabled(true);
170 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
171 			load_driver_symbols("usb");
172 #endif
173 #endif
174 			Stack *stack = new(std::nothrow) Stack();
175 			TRACE_MODULE("usb_module: stack created %p\n", stack);
176 			if (!stack)
177 				return B_NO_MEMORY;
178 
179 			if (stack->InitCheck() != B_OK) {
180 				delete stack;
181 				return ENODEV;
182 			}
183 
184 			gUSBStack = stack;
185 
186 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
187 			add_debugger_command("get_usb_pipe_for_id",
188 				&debug_get_pipe_for_id,
189 				"Sets _usbPipe by resolving _usbPipeID");
190 			add_debugger_command("usb_process_transfer",
191 				&debug_process_transfer,
192 				"Transfers _usbTransferData with _usbTransferLength"
193 				" (and/or _usbRequestData) to pipe _usbPipe");
194 			add_debugger_command("usb_clear_stall",
195 				&debug_clear_stall,
196 				"Tries to issue a clear feature request for the endpoint halt"
197 				" feature on pipe _usbPipe");
198 #elif HAIKU_TARGET_PLATFORM_BEOS
199 			// Plain R5 workaround, see comment above.
200 			shared = create_area("shared usb stack", &address,
201 				B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, B_NO_LOCK,
202 				B_KERNEL_WRITE_AREA);
203 			if (shared >= B_OK)
204 				*((Stack **)address) = gUSBStack;
205 #endif
206 			break;
207 		}
208 
209 		case B_MODULE_UNINIT:
210 			TRACE_MODULE("uninit\n");
211 			delete gUSBStack;
212 			gUSBStack = NULL;
213 
214 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
215 			remove_debugger_command("get_usb_pipe_for_id",
216 				&debug_get_pipe_for_id);
217 #endif
218 			break;
219 
220 		default:
221 			return EINVAL;
222 	}
223 
224 	return B_OK;
225 }
226 
227 
228 status_t
229 register_driver(const char *driverName,
230 	const usb_support_descriptor *descriptors,
231 	size_t count, const char *optionalRepublishDriverName)
232 {
233 	return gUSBStack->RegisterDriver(driverName, descriptors, count,
234 		optionalRepublishDriverName);
235 }
236 
237 
238 status_t
239 install_notify(const char *driverName, const usb_notify_hooks *hooks)
240 {
241 	return gUSBStack->InstallNotify(driverName, hooks);
242 }
243 
244 
245 status_t
246 uninstall_notify(const char *driverName)
247 {
248 	return gUSBStack->UninstallNotify(driverName);
249 }
250 
251 
252 const usb_device_descriptor *
253 get_device_descriptor(usb_device device)
254 {
255 	TRACE_MODULE("get_device_descriptor(%" B_PRId32 ")\n", device);
256 	Object *object = gUSBStack->GetObject(device);
257 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
258 		return NULL;
259 
260 	return ((Device *)object)->DeviceDescriptor();
261 }
262 
263 
264 const usb_configuration_info *
265 get_nth_configuration(usb_device device, uint32 index)
266 {
267 	TRACE_MODULE("get_nth_configuration(%" B_PRId32 ", %" B_PRIu32 ")\n",
268 		device, index);
269 	Object *object = gUSBStack->GetObject(device);
270 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
271 		return NULL;
272 
273 	return ((Device *)object)->ConfigurationAt((int32)index);
274 }
275 
276 
277 const usb_configuration_info *
278 get_configuration(usb_device device)
279 {
280 	TRACE_MODULE("get_configuration(%" B_PRId32 ")\n", device);
281 	Object *object = gUSBStack->GetObject(device);
282 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
283 		return NULL;
284 
285 	return ((Device *)object)->Configuration();
286 }
287 
288 
289 status_t
290 set_configuration(usb_device device,
291 	const usb_configuration_info *configuration)
292 {
293 	TRACE_MODULE("set_configuration(%" B_PRId32 ", %p)\n", device,
294 		configuration);
295 	Object *object = gUSBStack->GetObject(device);
296 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
297 		return B_DEV_INVALID_PIPE;
298 
299 	return ((Device *)object)->SetConfiguration(configuration);
300 }
301 
302 
303 status_t
304 set_alt_interface(usb_device device, const usb_interface_info *interface)
305 {
306 	TRACE_MODULE("set_alt_interface(%" B_PRId32 ", %p)\n", device, interface);
307 	Object *object = gUSBStack->GetObject(device);
308 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
309 		return B_DEV_INVALID_PIPE;
310 
311 	return ((Device *)object)->SetAltInterface(interface);
312 }
313 
314 
315 status_t
316 set_feature(usb_id handle, uint16 selector)
317 {
318 	TRACE_MODULE("set_feature(%" B_PRId32 ", %d)\n", handle, selector);
319 	Object *object = gUSBStack->GetObject(handle);
320 	if (!object)
321 		return B_DEV_INVALID_PIPE;
322 
323 	return object->SetFeature(selector);
324 }
325 
326 
327 status_t
328 clear_feature(usb_id handle, uint16 selector)
329 {
330 	TRACE_MODULE("clear_feature(%" B_PRId32 ", %d)\n", handle, selector);
331 	Object *object = gUSBStack->GetObject(handle);
332 	if (!object)
333 		return B_DEV_INVALID_PIPE;
334 
335 	return object->ClearFeature(selector);
336 }
337 
338 
339 status_t
340 get_status(usb_id handle, uint16 *status)
341 {
342 	TRACE_MODULE("get_status(%" B_PRId32 ", %p)\n", handle, status);
343 	if (!status)
344 		return B_BAD_VALUE;
345 
346 	Object *object = gUSBStack->GetObject(handle);
347 	if (!object)
348 		return B_DEV_INVALID_PIPE;
349 
350 	return object->GetStatus(status);
351 }
352 
353 
354 status_t
355 get_descriptor(usb_device device, uint8 type, uint8 index, uint16 languageID,
356 	void *data, size_t dataLength, size_t *actualLength)
357 {
358 	TRACE_MODULE("get_descriptor(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, %p, "
359 		"%" B_PRIuSIZE ", %p)\n",
360 		device, type, index, languageID, data, dataLength, actualLength);
361 	Object *object = gUSBStack->GetObject(device);
362 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
363 		return B_DEV_INVALID_PIPE;
364 
365 	return ((Device *)object)->GetDescriptor(type, index, languageID,
366 		data, dataLength, actualLength);
367 }
368 
369 
370 status_t
371 send_request(usb_device device, uint8 requestType, uint8 request,
372 	uint16 value, uint16 index, uint16 length, void *data, size_t *actualLength)
373 {
374 	TRACE_MODULE("send_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x, "
375 		"%d, %p, %p)\n", device, requestType, request, value, index, length,
376 		data, actualLength);
377 	Object *object = gUSBStack->GetObject(device);
378 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
379 		return B_DEV_INVALID_PIPE;
380 
381 	return ((Device *)object)->DefaultPipe()->SendRequest(requestType, request,
382 		value, index, length, data, length, actualLength);
383 }
384 
385 
386 status_t
387 queue_request(usb_device device, uint8 requestType, uint8 request,
388 	uint16 value, uint16 index, uint16 length, void *data,
389 	usb_callback_func callback, void *callbackCookie)
390 {
391 	TRACE_MODULE("queue_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x,"
392 		" %u, %p, %p, %p)\n", device, requestType, request, value, index,
393 		length, data, callback,	callbackCookie);
394 	Object *object = gUSBStack->GetObject(device);
395 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
396 		return B_DEV_INVALID_PIPE;
397 
398 	return ((Device *)object)->DefaultPipe()->QueueRequest(requestType,
399 		request, value, index, length, data, length, callback, callbackCookie);
400 }
401 
402 
403 status_t
404 queue_interrupt(usb_pipe pipe, void *data, size_t dataLength,
405 	usb_callback_func callback, void *callbackCookie)
406 {
407 	TRACE_MODULE("queue_interrupt(%" B_PRId32 ", %p, %ld, %p, %p)\n",
408 		pipe, data, dataLength, callback, callbackCookie);
409 	Object *object = gUSBStack->GetObject(pipe);
410 	if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0)
411 		return B_DEV_INVALID_PIPE;
412 
413 	return ((InterruptPipe *)object)->QueueInterrupt(data, dataLength, callback,
414 		callbackCookie);
415 }
416 
417 
418 status_t
419 queue_bulk(usb_pipe pipe, void *data, size_t dataLength,
420 	usb_callback_func callback, void *callbackCookie)
421 {
422 	TRACE_MODULE("queue_bulk(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, %p)\n",
423 		pipe, data, dataLength, callback, callbackCookie);
424 	Object *object = gUSBStack->GetObject(pipe);
425 	if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
426 		return B_DEV_INVALID_PIPE;
427 
428 	return ((BulkPipe *)object)->QueueBulk(data, dataLength, callback,
429 		callbackCookie);
430 }
431 
432 
433 status_t
434 queue_bulk_v(usb_pipe pipe, iovec *vector, size_t vectorCount,
435 	usb_callback_func callback, void *callbackCookie)
436 {
437 	TRACE_MODULE("queue_bulk_v(%" B_PRId32 ", %p, %" B_PRIuSIZE " %p, %p)\n",
438 		pipe, vector, vectorCount, callback, callbackCookie);
439 	Object *object = gUSBStack->GetObject(pipe);
440 	if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
441 		return B_DEV_INVALID_PIPE;
442 
443 	return ((BulkPipe *)object)->QueueBulkV(vector, vectorCount, callback,
444 		callbackCookie, false);
445 }
446 
447 
448 status_t
449 queue_bulk_v_physical(usb_pipe pipe, iovec *vector, size_t vectorCount,
450 	usb_callback_func callback, void *callbackCookie)
451 {
452 	TRACE_MODULE("queue_bulk_v_physical(%" B_PRId32 ", %p, %" B_PRIuSIZE
453 		", %p, %p)\n", pipe, vector, vectorCount, callback, callbackCookie);
454 	Object *object = gUSBStack->GetObject(pipe);
455 	if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
456 		return B_DEV_INVALID_PIPE;
457 
458 	return ((BulkPipe *)object)->QueueBulkV(vector, vectorCount, callback,
459 		callbackCookie, true);
460 }
461 
462 
463 status_t
464 queue_isochronous(usb_pipe pipe, void *data, size_t dataLength,
465 	usb_iso_packet_descriptor *packetDesc, uint32 packetCount,
466 	uint32 *startingFrameNumber, uint32 flags, usb_callback_func callback,
467 	void *callbackCookie)
468 {
469 	TRACE_MODULE("queue_isochronous(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, "
470 		"%" B_PRId32 ", %p, 0x%08" B_PRIx32 ", %p, %p)\n",
471 		pipe, data, dataLength, packetDesc, packetCount, startingFrameNumber,
472 		flags, callback, callbackCookie);
473 	Object *object = gUSBStack->GetObject(pipe);
474 	if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
475 		return B_DEV_INVALID_PIPE;
476 
477 	return ((IsochronousPipe *)object)->QueueIsochronous(data, dataLength,
478 		packetDesc, packetCount, startingFrameNumber, flags, callback,
479 		callbackCookie);
480 }
481 
482 
483 status_t
484 set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets,
485 	uint16 maxBufferDurationMS, uint16 sampleSize)
486 {
487 	TRACE_MODULE("set_pipe_policy(%" B_PRId32 ", %d, %d, %d)\n", pipe,
488 		maxQueuedPackets, maxBufferDurationMS, sampleSize);
489 	Object *object = gUSBStack->GetObject(pipe);
490 	if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
491 		return B_DEV_INVALID_PIPE;
492 
493 	return ((IsochronousPipe *)object)->SetPipePolicy(maxQueuedPackets,
494 		maxBufferDurationMS, sampleSize);
495 }
496 
497 
498 status_t
499 cancel_queued_transfers(usb_pipe pipe)
500 {
501 	TRACE_MODULE("cancel_queued_transfers(%" B_PRId32 ")\n", pipe);
502 	Object *object = gUSBStack->GetObject(pipe);
503 	if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
504 		return B_DEV_INVALID_PIPE;
505 
506 	return ((Pipe *)object)->CancelQueuedTransfers(false);
507 }
508 
509 
510 status_t
511 usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize)
512 {
513 	TRACE_MODULE("usb_ioctl(%" B_PRIu32 ", %p, %" B_PRIuSIZE ")\n", opcode,
514 		buffer, bufferSize);
515 
516 	switch (opcode) {
517 		case 'DNAM': {
518 			Object *object = gUSBStack->GetObject(*(usb_id *)buffer);
519 			if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
520 				return B_BAD_VALUE;
521 
522 			uint32 index = 0;
523 			return ((Device *)object)->BuildDeviceName((char *)buffer, &index,
524 				bufferSize, NULL);
525 		}
526 	}
527 
528 	return B_DEV_INVALID_IOCTL;
529 }
530 
531 
532 status_t
533 get_nth_roothub(uint32 index, usb_device *rootHub)
534 {
535 	if (!rootHub)
536 		return B_BAD_VALUE;
537 
538 	BusManager *busManager = gUSBStack->BusManagerAt(index);
539 	if (!busManager)
540 		return B_ENTRY_NOT_FOUND;
541 
542 	Hub *hub = busManager->GetRootHub();
543 	if (!hub)
544 		return B_NO_INIT;
545 
546 	*rootHub = hub->USBID();
547 	return B_OK;
548 }
549 
550 
551 status_t
552 get_nth_child(usb_device _hub, uint8 index, usb_device *childDevice)
553 {
554 	if (!childDevice)
555 		return B_BAD_VALUE;
556 
557 	Object *object = gUSBStack->GetObject(_hub);
558 	if (!object || (object->Type() & USB_OBJECT_HUB) == 0)
559 		return B_DEV_INVALID_PIPE;
560 
561 	Hub *hub = (Hub *)object;
562 	for (uint8 i = 0; i < 8; i++) {
563 		if (hub->ChildAt(i) == NULL)
564 			continue;
565 
566 		if (index-- > 0)
567 			continue;
568 
569 		*childDevice = hub->ChildAt(i)->USBID();
570 		return B_OK;
571 	}
572 
573 	return B_ENTRY_NOT_FOUND;
574 }
575 
576 
577 status_t
578 get_device_parent(usb_device _device, usb_device *parentHub, uint8 *portIndex)
579 {
580 	if (!parentHub || !portIndex)
581 		return B_BAD_VALUE;
582 
583 	Object *object = gUSBStack->GetObject(_device);
584 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
585 		return B_DEV_INVALID_PIPE;
586 
587 	Object *parent = object->Parent();
588 	if (!parent || (parent->Type() & USB_OBJECT_HUB) == 0)
589 		return B_ENTRY_NOT_FOUND;
590 
591 	Hub *hub = (Hub *)parent;
592 	for (uint8 i = 0; i < 8; i++) {
593 		if (hub->ChildAt(i) == object) {
594 			*portIndex = i;
595 			*parentHub = hub->USBID();
596 			return B_OK;
597 		}
598 	}
599 
600 	return B_ERROR;
601 }
602 
603 
604 status_t
605 reset_port(usb_device _hub, uint8 portIndex)
606 {
607 	Object *object = gUSBStack->GetObject(_hub);
608 	if (!object || (object->Type() & USB_OBJECT_HUB) == 0)
609 		return B_DEV_INVALID_PIPE;
610 
611 	Hub *hub = (Hub *)object;
612 	return hub->ResetPort(portIndex);
613 }
614 
615 
616 status_t
617 disable_port(usb_device _hub, uint8 portIndex)
618 {
619 	Object *object = gUSBStack->GetObject(_hub);
620 	if (!object || (object->Type() & USB_OBJECT_HUB) == 0)
621 		return B_DEV_INVALID_PIPE;
622 
623 	Hub *hub = (Hub *)object;
624 	return hub->DisablePort(portIndex);
625 }
626 
627 
628 /*
629 	This module exports the USB API v3
630 */
631 struct usb_module_info gModuleInfoV3 = {
632 	// First the bus_manager_info:
633 	{
634 		{
635 			"bus_managers/usb/v3",
636 			B_KEEP_LOADED,				// Keep loaded, even if no driver requires it
637 			bus_std_ops
638 		},
639 		NULL							// the rescan function
640 	},
641 
642 	register_driver,					// register_driver
643 	install_notify,						// install_notify
644 	uninstall_notify,					// uninstall_notify
645 	get_device_descriptor,				// get_device_descriptor
646 	get_nth_configuration,				// get_nth_configuration
647 	get_configuration,					// get_configuration
648 	set_configuration,					// set_configuration
649 	set_alt_interface,					// set_alt_interface
650 	set_feature,						// set_feature
651 	clear_feature, 						// clear_feature
652 	get_status, 						// get_status
653 	get_descriptor,						// get_descriptor
654 	send_request,						// send_request
655 	queue_interrupt,					// queue_interrupt
656 	queue_bulk,							// queue_bulk
657 	queue_bulk_v,						// queue_bulk_v
658 	queue_isochronous,					// queue_isochronous
659 	queue_request,						// queue_request
660 	set_pipe_policy,					// set_pipe_policy
661 	cancel_queued_transfers,			// cancel_queued_transfers
662 	usb_ioctl,							// usb_ioctl
663 	get_nth_roothub,					// get_nth_roothub
664 	get_nth_child,						// get_nth_child
665 	get_device_parent,					// get_device_parent
666 	reset_port,							// reset_port
667 	disable_port						// disable_port
668 	//queue_bulk_v_physical				// queue_bulk_v_physical
669 };
670 
671 
672 //
673 // #pragma mark -
674 //
675 
676 
677 const usb_device_descriptor *
678 get_device_descriptor_v2(const void *device)
679 {
680 	return get_device_descriptor((usb_id)(ssize_t)device);
681 }
682 
683 
684 const usb_configuration_info *
685 get_nth_configuration_v2(const void *device, uint index)
686 {
687 	return get_nth_configuration((usb_id)(ssize_t)device, index);
688 }
689 
690 
691 const usb_configuration_info *
692 get_configuration_v2(const void *device)
693 {
694 	return get_configuration((usb_id)(ssize_t)device);
695 }
696 
697 
698 status_t
699 set_configuration_v2(const void *device,
700 	const usb_configuration_info *configuration)
701 {
702 	return set_configuration((usb_id)(ssize_t)device, configuration);
703 }
704 
705 
706 status_t
707 set_alt_interface_v2(const void *device, const usb_interface_info *interface)
708 {
709 	return set_alt_interface((usb_id)(ssize_t)device, interface);
710 }
711 
712 
713 status_t
714 set_feature_v2(const void *object, uint16 selector)
715 {
716 	return set_feature((usb_id)(ssize_t)object, selector);
717 }
718 
719 
720 status_t
721 clear_feature_v2(const void *object, uint16 selector)
722 {
723 	return clear_feature((usb_id)(ssize_t)object, selector);
724 }
725 
726 
727 status_t
728 get_status_v2(const void *object, uint16 *status)
729 {
730 	return get_status((usb_id)(ssize_t)object, status);
731 }
732 
733 
734 status_t
735 get_descriptor_v2(const void *device, uint8 type, uint8 index,
736 	uint16 languageID, void *data, size_t dataLength, size_t *actualLength)
737 {
738 	return get_descriptor((usb_id)(ssize_t)device, type, index, languageID, data,
739 		dataLength, actualLength);
740 }
741 
742 
743 status_t
744 send_request_v2(const void *device, uint8 requestType, uint8 request,
745 	uint16 value, uint16 index, uint16 length, void *data,
746 	size_t /*dataLength*/, size_t *actualLength)
747 {
748 	return send_request((usb_id)(ssize_t)device, requestType, request, value, index,
749 		length, data, actualLength);
750 }
751 
752 
753 status_t
754 queue_request_v2(const void *device, uint8 requestType, uint8 request,
755 	uint16 value, uint16 index, uint16 length, void *data,
756 	size_t /*dataLength*/, usb_callback_func callback, void *callbackCookie)
757 {
758 	return queue_request((usb_id)(ssize_t)device, requestType, request, value, index,
759 		length, data, callback, callbackCookie);
760 }
761 
762 
763 status_t
764 queue_interrupt_v2(const void *pipe, void *data, size_t dataLength,
765 	usb_callback_func callback, void *callbackCookie)
766 {
767 	return queue_interrupt((usb_id)(ssize_t)pipe, data, dataLength, callback,
768 		callbackCookie);
769 }
770 
771 
772 status_t
773 queue_bulk_v2(const void *pipe, void *data, size_t dataLength,
774 	usb_callback_func callback, void *callbackCookie)
775 {
776 	return queue_bulk((usb_id)(ssize_t)pipe, data, dataLength, callback,
777 		callbackCookie);
778 }
779 
780 
781 status_t
782 queue_isochronous_v2(const void *pipe, void *data, size_t dataLength,
783 	rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback,
784 	void *callbackCookie)
785 {
786 	// ToDo: convert rlea to usb_iso_packet_descriptor
787 	// ToDo: use a flag to indicate that the callback shall produce a rlea
788 	usb_iso_packet_descriptor *packetDesc = NULL;
789 	return queue_isochronous((usb_id)(ssize_t)pipe, data, dataLength, packetDesc, 0,
790 		NULL, 0, callback, callbackCookie);
791 }
792 
793 
794 status_t
795 set_pipe_policy_v2(const void *pipe, uint8 maxQueuedPackets,
796 	uint16 maxBufferDurationMS, uint16 sampleSize)
797 {
798 	return set_pipe_policy((usb_id)(ssize_t)pipe, maxQueuedPackets, maxBufferDurationMS,
799 		sampleSize);
800 }
801 
802 
803 status_t
804 cancel_queued_transfers_v2(const void *pipe)
805 {
806 	return cancel_queued_transfers((usb_id)(ssize_t)pipe);
807 }
808 
809 
810 struct usb_module_info_v2 {
811 	bus_manager_info				binfo;
812 	status_t						(*register_driver)(const char *, const usb_support_descriptor *, size_t, const char *);
813 	status_t						(*install_notify)(const char *, const usb_notify_hooks *);
814 	status_t						(*uninstall_notify)(const char *);
815 	const usb_device_descriptor		*(*get_device_descriptor)(const void *);
816 	const usb_configuration_info	*(*get_nth_configuration)(const void *, uint);
817 	const usb_configuration_info	*(*get_configuration)(const void *);
818 	status_t						(*set_configuration)(const void *, const usb_configuration_info *);
819 	status_t						(*set_alt_interface)(const void *, const usb_interface_info *);
820 	status_t						(*set_feature)(const void *, uint16);
821 	status_t						(*clear_feature)(const void *, uint16);
822 	status_t						(*get_status)(const void *, uint16 *);
823 	status_t						(*get_descriptor)(const void *, uint8, uint8, uint16, void *, size_t, size_t *);
824 	status_t						(*send_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, size_t *);
825 	status_t						(*queue_interrupt)(const void *, void *, size_t, usb_callback_func, void *);
826 	status_t						(*queue_bulk)(const void *, void *, size_t, usb_callback_func, void *);
827 	status_t						(*queue_isochronous)(const void *, void *, size_t, rlea *, uint16, usb_callback_func, void *);
828 	status_t						(*queue_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, usb_callback_func, void *);
829 	status_t						(*set_pipe_policy)(const void *, uint8, uint16, uint16);
830 	status_t						(*cancel_queued_transfers)(const void *);
831 	status_t						(*usb_ioctl)(uint32 opcode, void *,size_t);
832 };
833 
834 
835 /*
836 	This module exports the USB API v2
837 */
838 struct usb_module_info_v2 gModuleInfoV2 = {
839 	// First the bus_manager_info:
840 	{
841 		{
842 			"bus_managers/usb/v2",
843 			B_KEEP_LOADED,				// Keep loaded, even if no driver requires it
844 			bus_std_ops
845 		},
846 		NULL							// the rescan function
847 	},
848 
849 	register_driver,					// register_driver
850 	install_notify,						// install_notify
851 	uninstall_notify,					// uninstall_notify
852 	get_device_descriptor_v2,			// get_device_descriptor
853 	get_nth_configuration_v2,			// get_nth_configuration
854 	get_configuration_v2,				// get_configuration
855 	set_configuration_v2,				// set_configuration
856 	set_alt_interface_v2,				// set_alt_interface
857 	set_feature_v2,						// set_feature
858 	clear_feature_v2,					// clear_feature
859 	get_status_v2, 						// get_status
860 	get_descriptor_v2,					// get_descriptor
861 	send_request_v2,					// send_request
862 	queue_interrupt_v2,					// queue_interrupt
863 	queue_bulk_v2,						// queue_bulk
864 	queue_isochronous_v2,				// queue_isochronous
865 	queue_request_v2,					// queue_request
866 	set_pipe_policy_v2,					// set_pipe_policy
867 	cancel_queued_transfers_v2,			// cancel_queued_transfers
868 	usb_ioctl							// usb_ioctl
869 };
870 
871 
872 //
873 // #pragma mark -
874 //
875 
876 
877 module_info *modules[] = {
878 	(module_info *)&gModuleInfoV2,
879 	(module_info *)&gModuleInfoV3,
880 	NULL
881 };
882