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