xref: /haiku/src/add-ons/kernel/bus_managers/usb/usb.cpp (revision 759ee24c4c1722813609c3b7c77fabef275b02bf)
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 
11 #include <util/kernel_cpp.h>
12 #include "usb_private.h"
13 #include <USB_rle.h>
14 
15 #define USB_MODULE_NAME "module"
16 
17 Stack *gUSBStack = NULL;
18 
19 
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 
141 
142 static int32
143 bus_std_ops(int32 op, ...)
144 {
145 	switch (op) {
146 		case B_MODULE_INIT: {
147 			TRACE_MODULE("init\n");
148 			if (gUSBStack)
149 				return B_OK;
150 
151 #ifdef TRACE_USB
152 			set_dprintf_enabled(true);
153 #endif
154 			Stack *stack = new(std::nothrow) Stack();
155 			TRACE_MODULE("usb_module: stack created %p\n", stack);
156 			if (!stack)
157 				return B_NO_MEMORY;
158 
159 			if (stack->InitCheck() != B_OK) {
160 				delete stack;
161 				return ENODEV;
162 			}
163 
164 			gUSBStack = stack;
165 
166 			add_debugger_command("get_usb_pipe_for_id",
167 				&debug_get_pipe_for_id,
168 				"Sets _usbPipe by resolving _usbPipeID");
169 			add_debugger_command("usb_process_transfer",
170 				&debug_process_transfer,
171 				"Transfers _usbTransferData with _usbTransferLength"
172 				" (and/or _usbRequestData) to pipe _usbPipe");
173 			add_debugger_command("usb_clear_stall",
174 				&debug_clear_stall,
175 				"Tries to issue a clear feature request for the endpoint halt"
176 				" feature on pipe _usbPipe");
177 			break;
178 		}
179 
180 		case B_MODULE_UNINIT:
181 			TRACE_MODULE("uninit\n");
182 			delete gUSBStack;
183 			gUSBStack = NULL;
184 
185 			remove_debugger_command("get_usb_pipe_for_id",
186 				&debug_get_pipe_for_id);
187 			break;
188 
189 		default:
190 			return EINVAL;
191 	}
192 
193 	return B_OK;
194 }
195 
196 
197 status_t
198 register_driver(const char *driverName,
199 	const usb_support_descriptor *descriptors,
200 	size_t count, const char *optionalRepublishDriverName)
201 {
202 	return gUSBStack->RegisterDriver(driverName, descriptors, count,
203 		optionalRepublishDriverName);
204 }
205 
206 
207 status_t
208 install_notify(const char *driverName, const usb_notify_hooks *hooks)
209 {
210 	return gUSBStack->InstallNotify(driverName, hooks);
211 }
212 
213 
214 status_t
215 uninstall_notify(const char *driverName)
216 {
217 	return gUSBStack->UninstallNotify(driverName);
218 }
219 
220 
221 const usb_device_descriptor *
222 get_device_descriptor(usb_device dev)
223 {
224 	TRACE_MODULE("get_device_descriptor(%" B_PRId32 ")\n", dev);
225 	Object *object = gUSBStack->GetObject(dev);
226 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
227 		return NULL;
228 	Device *device = (Device *)object;
229 	if (device->InitCheck() != B_OK)
230 		return NULL;
231 
232 	return device->DeviceDescriptor();
233 }
234 
235 
236 const usb_configuration_info *
237 get_nth_configuration(usb_device dev, uint32 index)
238 {
239 	TRACE_MODULE("get_nth_configuration(%" B_PRId32 ", %" B_PRIu32 ")\n",
240 		dev, index);
241 	Object *object = gUSBStack->GetObject(dev);
242 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
243 		return NULL;
244 	Device *device = (Device *)object;
245 	if (device->InitCheck() != B_OK)
246 		return NULL;
247 
248 	return device->ConfigurationAt((int32)index);
249 }
250 
251 
252 const usb_configuration_info *
253 get_configuration(usb_device dev)
254 {
255 	TRACE_MODULE("get_configuration(%" B_PRId32 ")\n", dev);
256 	Object *object = gUSBStack->GetObject(dev);
257 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
258 		return NULL;
259 	Device *device = (Device *)object;
260 	if (device->InitCheck() != B_OK)
261 		return NULL;
262 
263 	return device->Configuration();
264 }
265 
266 
267 status_t
268 set_configuration(usb_device dev,
269 	const usb_configuration_info *configuration)
270 {
271 	TRACE_MODULE("set_configuration(%" B_PRId32 ", %p)\n", dev,
272 		configuration);
273 	Object *object = gUSBStack->GetObject(dev);
274 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
275 		return B_DEV_INVALID_PIPE;
276 	Device *device = (Device *)object;
277 	if (device->InitCheck() != B_OK)
278 		return B_NO_INIT;
279 
280 	return device->SetConfiguration(configuration);
281 }
282 
283 
284 status_t
285 set_alt_interface(usb_device dev, const usb_interface_info *interface)
286 {
287 	TRACE_MODULE("set_alt_interface(%" B_PRId32 ", %p)\n", dev, interface);
288 	Object *object = gUSBStack->GetObject(dev);
289 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
290 		return B_DEV_INVALID_PIPE;
291 	Device *device = (Device *)object;
292 	if (device->InitCheck() != B_OK)
293 		return B_NO_INIT;
294 
295 	return device->SetAltInterface(interface);
296 }
297 
298 
299 status_t
300 set_feature(usb_id handle, uint16 selector)
301 {
302 	TRACE_MODULE("set_feature(%" B_PRId32 ", %d)\n", handle, selector);
303 	Object *object = gUSBStack->GetObject(handle);
304 	if (!object)
305 		return B_DEV_INVALID_PIPE;
306 
307 	return object->SetFeature(selector);
308 }
309 
310 
311 status_t
312 clear_feature(usb_id handle, uint16 selector)
313 {
314 	TRACE_MODULE("clear_feature(%" B_PRId32 ", %d)\n", handle, selector);
315 	Object *object = gUSBStack->GetObject(handle);
316 	if (!object)
317 		return B_DEV_INVALID_PIPE;
318 
319 	return object->ClearFeature(selector);
320 }
321 
322 
323 status_t
324 get_status(usb_id handle, uint16 *status)
325 {
326 	TRACE_MODULE("get_status(%" B_PRId32 ", %p)\n", handle, status);
327 	if (!status)
328 		return B_BAD_VALUE;
329 
330 	Object *object = gUSBStack->GetObject(handle);
331 	if (!object)
332 		return B_DEV_INVALID_PIPE;
333 
334 	return object->GetStatus(status);
335 }
336 
337 
338 status_t
339 get_descriptor(usb_device dev, uint8 type, uint8 index, uint16 languageID,
340 	void *data, size_t dataLength, size_t *actualLength)
341 {
342 	TRACE_MODULE("get_descriptor(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, %p, "
343 		"%" B_PRIuSIZE ", %p)\n",
344 		dev, type, index, languageID, data, dataLength, actualLength);
345 	Object *object = gUSBStack->GetObject(dev);
346 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
347 		return B_DEV_INVALID_PIPE;
348 	Device *device = (Device *)object;
349 	if (device->InitCheck() != B_OK)
350 		return B_NO_INIT;
351 
352 	return device->GetDescriptor(type, index, languageID,
353 		data, dataLength, actualLength);
354 }
355 
356 
357 status_t
358 send_request(usb_device dev, uint8 requestType, uint8 request,
359 	uint16 value, uint16 index, uint16 length, void *data, size_t *actualLength)
360 {
361 	TRACE_MODULE("send_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x, "
362 		"%d, %p, %p)\n", dev, requestType, request, value, index, length,
363 		data, actualLength);
364 	Object *object = gUSBStack->GetObject(dev);
365 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
366 		return B_DEV_INVALID_PIPE;
367 	Device *device = (Device *)object;
368 	if (device->InitCheck() != B_OK)
369 		return B_NO_INIT;
370 
371 	return device->DefaultPipe()->SendRequest(requestType, request,
372 		value, index, length, data, length, actualLength);
373 }
374 
375 
376 status_t
377 queue_request(usb_device dev, uint8 requestType, uint8 request,
378 	uint16 value, uint16 index, uint16 length, void *data,
379 	usb_callback_func callback, void *callbackCookie)
380 {
381 	TRACE_MODULE("queue_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x,"
382 		" %u, %p, %p, %p)\n", dev, requestType, request, value, index,
383 		length, data, callback,	callbackCookie);
384 	Object *object = gUSBStack->GetObject(dev);
385 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
386 		return B_DEV_INVALID_PIPE;
387 	Device *device = (Device *)object;
388 	if (device->InitCheck() != B_OK)
389 		return B_NO_INIT;
390 
391 	return device->DefaultPipe()->QueueRequest(requestType,
392 		request, value, index, length, data, length, callback, callbackCookie);
393 }
394 
395 
396 status_t
397 queue_interrupt(usb_pipe pipe, void *data, size_t dataLength,
398 	usb_callback_func callback, void *callbackCookie)
399 {
400 	TRACE_MODULE("queue_interrupt(%" B_PRId32 ", %p, %ld, %p, %p)\n",
401 		pipe, data, dataLength, callback, callbackCookie);
402 	Object *object = gUSBStack->GetObject(pipe);
403 	if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0)
404 		return B_DEV_INVALID_PIPE;
405 
406 	return ((InterruptPipe *)object)->QueueInterrupt(data, dataLength, callback,
407 		callbackCookie);
408 }
409 
410 
411 status_t
412 queue_bulk(usb_pipe pipe, void *data, size_t dataLength,
413 	usb_callback_func callback, void *callbackCookie)
414 {
415 	TRACE_MODULE("queue_bulk(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, %p)\n",
416 		pipe, data, dataLength, callback, callbackCookie);
417 	Object *object = gUSBStack->GetObject(pipe);
418 	if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
419 		return B_DEV_INVALID_PIPE;
420 
421 	return ((BulkPipe *)object)->QueueBulk(data, dataLength, callback,
422 		callbackCookie);
423 }
424 
425 
426 status_t
427 queue_bulk_v(usb_pipe pipe, iovec *vector, size_t vectorCount,
428 	usb_callback_func callback, void *callbackCookie)
429 {
430 	TRACE_MODULE("queue_bulk_v(%" B_PRId32 ", %p, %" B_PRIuSIZE " %p, %p)\n",
431 		pipe, vector, vectorCount, callback, callbackCookie);
432 	Object *object = gUSBStack->GetObject(pipe);
433 	if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
434 		return B_DEV_INVALID_PIPE;
435 
436 	return ((BulkPipe *)object)->QueueBulkV(vector, vectorCount, callback,
437 		callbackCookie, false);
438 }
439 
440 
441 status_t
442 queue_bulk_v_physical(usb_pipe pipe, iovec *vector, size_t vectorCount,
443 	usb_callback_func callback, void *callbackCookie)
444 {
445 	TRACE_MODULE("queue_bulk_v_physical(%" B_PRId32 ", %p, %" B_PRIuSIZE
446 		", %p, %p)\n", pipe, vector, vectorCount, callback, callbackCookie);
447 	Object *object = gUSBStack->GetObject(pipe);
448 	if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
449 		return B_DEV_INVALID_PIPE;
450 
451 	return ((BulkPipe *)object)->QueueBulkV(vector, vectorCount, callback,
452 		callbackCookie, true);
453 }
454 
455 
456 status_t
457 queue_isochronous(usb_pipe pipe, void *data, size_t dataLength,
458 	usb_iso_packet_descriptor *packetDesc, uint32 packetCount,
459 	uint32 *startingFrameNumber, uint32 flags, usb_callback_func callback,
460 	void *callbackCookie)
461 {
462 	TRACE_MODULE("queue_isochronous(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, "
463 		"%" B_PRId32 ", %p, 0x%08" B_PRIx32 ", %p, %p)\n",
464 		pipe, data, dataLength, packetDesc, packetCount, startingFrameNumber,
465 		flags, callback, callbackCookie);
466 	Object *object = gUSBStack->GetObject(pipe);
467 	if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
468 		return B_DEV_INVALID_PIPE;
469 
470 	return ((IsochronousPipe *)object)->QueueIsochronous(data, dataLength,
471 		packetDesc, packetCount, startingFrameNumber, flags, callback,
472 		callbackCookie);
473 }
474 
475 
476 status_t
477 set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets,
478 	uint16 maxBufferDurationMS, uint16 sampleSize)
479 {
480 	TRACE_MODULE("set_pipe_policy(%" B_PRId32 ", %d, %d, %d)\n", pipe,
481 		maxQueuedPackets, maxBufferDurationMS, sampleSize);
482 	Object *object = gUSBStack->GetObject(pipe);
483 	if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
484 		return B_DEV_INVALID_PIPE;
485 
486 	return ((IsochronousPipe *)object)->SetPipePolicy(maxQueuedPackets,
487 		maxBufferDurationMS, sampleSize);
488 }
489 
490 
491 status_t
492 cancel_queued_transfers(usb_pipe pipe)
493 {
494 	TRACE_MODULE("cancel_queued_transfers(%" B_PRId32 ")\n", pipe);
495 	Object *object = gUSBStack->GetObject(pipe);
496 	if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
497 		return B_DEV_INVALID_PIPE;
498 
499 	return ((Pipe *)object)->CancelQueuedTransfers(false);
500 }
501 
502 
503 status_t
504 usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize)
505 {
506 	TRACE_MODULE("usb_ioctl(%" B_PRIu32 ", %p, %" B_PRIuSIZE ")\n", opcode,
507 		buffer, bufferSize);
508 
509 	switch (opcode) {
510 		case 'DNAM': {
511 			Object *object = gUSBStack->GetObject(*(usb_id *)buffer);
512 			if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
513 				return B_BAD_VALUE;
514 			Device *device = (Device *)object;
515 			if (device->InitCheck() != B_OK)
516 				return B_NO_INIT;
517 
518 			uint32 index = 0;
519 			return device->BuildDeviceName((char *)buffer, &index,
520 				bufferSize, NULL);
521 		}
522 	}
523 
524 	return B_DEV_INVALID_IOCTL;
525 }
526 
527 
528 status_t
529 get_nth_roothub(uint32 index, usb_device *rootHub)
530 {
531 	if (!rootHub)
532 		return B_BAD_VALUE;
533 
534 	BusManager *busManager = gUSBStack->BusManagerAt(index);
535 	if (!busManager)
536 		return B_ENTRY_NOT_FOUND;
537 
538 	Hub *hub = busManager->GetRootHub();
539 	if (!hub)
540 		return B_NO_INIT;
541 
542 	*rootHub = hub->USBID();
543 	return B_OK;
544 }
545 
546 
547 status_t
548 get_nth_child(usb_device _hub, uint8 index, usb_device *childDevice)
549 {
550 	if (!childDevice)
551 		return B_BAD_VALUE;
552 
553 	Object *object = gUSBStack->GetObject(_hub);
554 	if (!object || (object->Type() & USB_OBJECT_HUB) == 0)
555 		return B_DEV_INVALID_PIPE;
556 
557 	Hub *hub = (Hub *)object;
558 	for (uint8 i = 0; i < 8; i++) {
559 		if (hub->ChildAt(i) == NULL)
560 			continue;
561 
562 		if (index-- > 0)
563 			continue;
564 
565 		*childDevice = hub->ChildAt(i)->USBID();
566 		return B_OK;
567 	}
568 
569 	return B_ENTRY_NOT_FOUND;
570 }
571 
572 
573 status_t
574 get_device_parent(usb_device _device, usb_device *parentHub, uint8 *portIndex)
575 {
576 	if (!parentHub || !portIndex)
577 		return B_BAD_VALUE;
578 
579 	Object *object = gUSBStack->GetObject(_device);
580 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
581 		return B_DEV_INVALID_PIPE;
582 
583 	Object *parent = object->Parent();
584 	if (!parent || (parent->Type() & USB_OBJECT_HUB) == 0)
585 		return B_ENTRY_NOT_FOUND;
586 
587 	Hub *hub = (Hub *)parent;
588 	for (uint8 i = 0; i < 8; i++) {
589 		if (hub->ChildAt(i) == object) {
590 			*portIndex = i;
591 			*parentHub = hub->USBID();
592 			return B_OK;
593 		}
594 	}
595 
596 	return B_ERROR;
597 }
598 
599 
600 status_t
601 reset_port(usb_device _hub, uint8 portIndex)
602 {
603 	Object *object = gUSBStack->GetObject(_hub);
604 	if (!object || (object->Type() & USB_OBJECT_HUB) == 0)
605 		return B_DEV_INVALID_PIPE;
606 
607 	Hub *hub = (Hub *)object;
608 	return hub->ResetPort(portIndex);
609 }
610 
611 
612 status_t
613 disable_port(usb_device _hub, uint8 portIndex)
614 {
615 	Object *object = gUSBStack->GetObject(_hub);
616 	if (!object || (object->Type() & USB_OBJECT_HUB) == 0)
617 		return B_DEV_INVALID_PIPE;
618 
619 	Hub *hub = (Hub *)object;
620 	return hub->DisablePort(portIndex);
621 }
622 
623 
624 /*
625 	This module exports the USB API v3
626 */
627 struct usb_module_info gModuleInfoV3 = {
628 	// First the bus_manager_info:
629 	{
630 		{
631 			"bus_managers/usb/v3",
632 			B_KEEP_LOADED,				// Keep loaded, even if no driver requires it
633 			bus_std_ops
634 		},
635 		NULL							// the rescan function
636 	},
637 
638 	register_driver,					// register_driver
639 	install_notify,						// install_notify
640 	uninstall_notify,					// uninstall_notify
641 	get_device_descriptor,				// get_device_descriptor
642 	get_nth_configuration,				// get_nth_configuration
643 	get_configuration,					// get_configuration
644 	set_configuration,					// set_configuration
645 	set_alt_interface,					// set_alt_interface
646 	set_feature,						// set_feature
647 	clear_feature, 						// clear_feature
648 	get_status, 						// get_status
649 	get_descriptor,						// get_descriptor
650 	send_request,						// send_request
651 	queue_interrupt,					// queue_interrupt
652 	queue_bulk,							// queue_bulk
653 	queue_bulk_v,						// queue_bulk_v
654 	queue_isochronous,					// queue_isochronous
655 	queue_request,						// queue_request
656 	set_pipe_policy,					// set_pipe_policy
657 	cancel_queued_transfers,			// cancel_queued_transfers
658 	usb_ioctl,							// usb_ioctl
659 	get_nth_roothub,					// get_nth_roothub
660 	get_nth_child,						// get_nth_child
661 	get_device_parent,					// get_device_parent
662 	reset_port,							// reset_port
663 	disable_port						// disable_port
664 	//queue_bulk_v_physical				// queue_bulk_v_physical
665 };
666 
667 
668 //
669 // #pragma mark -
670 //
671 
672 
673 const usb_device_descriptor *
674 get_device_descriptor_v2(const void *device)
675 {
676 	return get_device_descriptor((usb_id)(ssize_t)device);
677 }
678 
679 
680 const usb_configuration_info *
681 get_nth_configuration_v2(const void *device, uint index)
682 {
683 	return get_nth_configuration((usb_id)(ssize_t)device, index);
684 }
685 
686 
687 const usb_configuration_info *
688 get_configuration_v2(const void *device)
689 {
690 	return get_configuration((usb_id)(ssize_t)device);
691 }
692 
693 
694 status_t
695 set_configuration_v2(const void *device,
696 	const usb_configuration_info *configuration)
697 {
698 	return set_configuration((usb_id)(ssize_t)device, configuration);
699 }
700 
701 
702 status_t
703 set_alt_interface_v2(const void *device, const usb_interface_info *interface)
704 {
705 	return set_alt_interface((usb_id)(ssize_t)device, interface);
706 }
707 
708 
709 status_t
710 set_feature_v2(const void *object, uint16 selector)
711 {
712 	return set_feature((usb_id)(ssize_t)object, selector);
713 }
714 
715 
716 status_t
717 clear_feature_v2(const void *object, uint16 selector)
718 {
719 	return clear_feature((usb_id)(ssize_t)object, selector);
720 }
721 
722 
723 status_t
724 get_status_v2(const void *object, uint16 *status)
725 {
726 	return get_status((usb_id)(ssize_t)object, status);
727 }
728 
729 
730 status_t
731 get_descriptor_v2(const void *device, uint8 type, uint8 index,
732 	uint16 languageID, void *data, size_t dataLength, size_t *actualLength)
733 {
734 	return get_descriptor((usb_id)(ssize_t)device, type, index, languageID, data,
735 		dataLength, actualLength);
736 }
737 
738 
739 status_t
740 send_request_v2(const void *device, uint8 requestType, uint8 request,
741 	uint16 value, uint16 index, uint16 length, void *data,
742 	size_t /*dataLength*/, size_t *actualLength)
743 {
744 	return send_request((usb_id)(ssize_t)device, requestType, request, value, index,
745 		length, data, actualLength);
746 }
747 
748 
749 status_t
750 queue_request_v2(const void *device, uint8 requestType, uint8 request,
751 	uint16 value, uint16 index, uint16 length, void *data,
752 	size_t /*dataLength*/, usb_callback_func callback, void *callbackCookie)
753 {
754 	return queue_request((usb_id)(ssize_t)device, requestType, request, value, index,
755 		length, data, callback, callbackCookie);
756 }
757 
758 
759 status_t
760 queue_interrupt_v2(const void *pipe, void *data, size_t dataLength,
761 	usb_callback_func callback, void *callbackCookie)
762 {
763 	return queue_interrupt((usb_id)(ssize_t)pipe, data, dataLength, callback,
764 		callbackCookie);
765 }
766 
767 
768 status_t
769 queue_bulk_v2(const void *pipe, void *data, size_t dataLength,
770 	usb_callback_func callback, void *callbackCookie)
771 {
772 	return queue_bulk((usb_id)(ssize_t)pipe, data, dataLength, callback,
773 		callbackCookie);
774 }
775 
776 
777 status_t
778 queue_isochronous_v2(const void *pipe, void *data, size_t dataLength,
779 	rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback,
780 	void *callbackCookie)
781 {
782 	// ToDo: convert rlea to usb_iso_packet_descriptor
783 	// ToDo: use a flag to indicate that the callback shall produce a rlea
784 	usb_iso_packet_descriptor *packetDesc = NULL;
785 	return queue_isochronous((usb_id)(ssize_t)pipe, data, dataLength, packetDesc, 0,
786 		NULL, 0, callback, callbackCookie);
787 }
788 
789 
790 status_t
791 set_pipe_policy_v2(const void *pipe, uint8 maxQueuedPackets,
792 	uint16 maxBufferDurationMS, uint16 sampleSize)
793 {
794 	return set_pipe_policy((usb_id)(ssize_t)pipe, maxQueuedPackets, maxBufferDurationMS,
795 		sampleSize);
796 }
797 
798 
799 status_t
800 cancel_queued_transfers_v2(const void *pipe)
801 {
802 	return cancel_queued_transfers((usb_id)(ssize_t)pipe);
803 }
804 
805 
806 struct usb_module_info_v2 {
807 	bus_manager_info				binfo;
808 	status_t						(*register_driver)(const char *, const usb_support_descriptor *, size_t, const char *);
809 	status_t						(*install_notify)(const char *, const usb_notify_hooks *);
810 	status_t						(*uninstall_notify)(const char *);
811 	const usb_device_descriptor		*(*get_device_descriptor)(const void *);
812 	const usb_configuration_info	*(*get_nth_configuration)(const void *, uint);
813 	const usb_configuration_info	*(*get_configuration)(const void *);
814 	status_t						(*set_configuration)(const void *, const usb_configuration_info *);
815 	status_t						(*set_alt_interface)(const void *, const usb_interface_info *);
816 	status_t						(*set_feature)(const void *, uint16);
817 	status_t						(*clear_feature)(const void *, uint16);
818 	status_t						(*get_status)(const void *, uint16 *);
819 	status_t						(*get_descriptor)(const void *, uint8, uint8, uint16, void *, size_t, size_t *);
820 	status_t						(*send_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, size_t *);
821 	status_t						(*queue_interrupt)(const void *, void *, size_t, usb_callback_func, void *);
822 	status_t						(*queue_bulk)(const void *, void *, size_t, usb_callback_func, void *);
823 	status_t						(*queue_isochronous)(const void *, void *, size_t, rlea *, uint16, usb_callback_func, void *);
824 	status_t						(*queue_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, usb_callback_func, void *);
825 	status_t						(*set_pipe_policy)(const void *, uint8, uint16, uint16);
826 	status_t						(*cancel_queued_transfers)(const void *);
827 	status_t						(*usb_ioctl)(uint32 opcode, void *,size_t);
828 };
829 
830 
831 /*
832 	This module exports the USB API v2
833 */
834 struct usb_module_info_v2 gModuleInfoV2 = {
835 	// First the bus_manager_info:
836 	{
837 		{
838 			"bus_managers/usb/v2",
839 			B_KEEP_LOADED,				// Keep loaded, even if no driver requires it
840 			bus_std_ops
841 		},
842 		NULL							// the rescan function
843 	},
844 
845 	register_driver,					// register_driver
846 	install_notify,						// install_notify
847 	uninstall_notify,					// uninstall_notify
848 	get_device_descriptor_v2,			// get_device_descriptor
849 	get_nth_configuration_v2,			// get_nth_configuration
850 	get_configuration_v2,				// get_configuration
851 	set_configuration_v2,				// set_configuration
852 	set_alt_interface_v2,				// set_alt_interface
853 	set_feature_v2,						// set_feature
854 	clear_feature_v2,					// clear_feature
855 	get_status_v2, 						// get_status
856 	get_descriptor_v2,					// get_descriptor
857 	send_request_v2,					// send_request
858 	queue_interrupt_v2,					// queue_interrupt
859 	queue_bulk_v2,						// queue_bulk
860 	queue_isochronous_v2,				// queue_isochronous
861 	queue_request_v2,					// queue_request
862 	set_pipe_policy_v2,					// set_pipe_policy
863 	cancel_queued_transfers_v2,			// cancel_queued_transfers
864 	usb_ioctl							// usb_ioctl
865 };
866 
867 
868 //
869 // #pragma mark -
870 //
871 
872 
873 module_info *modules[] = {
874 	(module_info *)&gModuleInfoV2,
875 	(module_info *)&gModuleInfoV3,
876 	NULL
877 };
878