xref: /haiku/src/add-ons/kernel/bus_managers/usb/usb.cpp (revision 58481f0f6ef1a61ba07283f012cafbc2ed874ead)
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_p.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(%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);
334 }
335 
336 
337 status_t
338 queue_isochronous(usb_pipe pipe, void *data, size_t dataLength,
339 	usb_iso_packet_descriptor *packetDesc, uint32 packetCount,
340 	uint32 *startingFrameNumber, uint32 flags, usb_callback_func callback,
341 	void *callbackCookie)
342 {
343 	TRACE_MODULE("queue_isochronous(%ld, %p, %ld, %p, %ld, %p, 0x%08lx, %p, %p)\n",
344 		pipe, data, dataLength, packetDesc, packetCount, startingFrameNumber,
345 		flags, callback, callbackCookie);
346 	Object *object = gUSBStack->GetObject(pipe);
347 	if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
348 		return B_DEV_INVALID_PIPE;
349 
350 	return ((IsochronousPipe *)object)->QueueIsochronous(data, dataLength,
351 		packetDesc, packetCount, startingFrameNumber, flags, callback,
352 		callbackCookie);
353 }
354 
355 
356 status_t
357 set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets,
358 	uint16 maxBufferDurationMS, uint16 sampleSize)
359 {
360 	TRACE_MODULE("set_pipe_policy(%ld, %d, %d, %d)\n", pipe, maxQueuedPackets,
361 		maxBufferDurationMS, sampleSize);
362 	Object *object = gUSBStack->GetObject(pipe);
363 	if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
364 		return B_DEV_INVALID_PIPE;
365 
366 	return ((IsochronousPipe *)object)->SetPipePolicy(maxQueuedPackets,
367 		maxBufferDurationMS, sampleSize);
368 }
369 
370 
371 status_t
372 cancel_queued_transfers(usb_pipe pipe)
373 {
374 	TRACE_MODULE("cancel_queued_transfers(%ld)\n", pipe);
375 	Object *object = gUSBStack->GetObject(pipe);
376 	if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
377 		return B_DEV_INVALID_PIPE;
378 
379 	return ((Pipe *)object)->CancelQueuedTransfers(false);
380 }
381 
382 
383 status_t
384 usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize)
385 {
386 	TRACE_MODULE("usb_ioctl(%lu, %p, %ld)\n", opcode, buffer, bufferSize);
387 
388 	switch (opcode) {
389 		case 'DNAM': {
390 			Object *object = gUSBStack->GetObject(*(usb_id *)buffer);
391 			if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
392 				return B_BAD_VALUE;
393 
394 			uint32 index = 0;
395 			return ((Device *)object)->BuildDeviceName((char *)buffer, &index,
396 				bufferSize, NULL);
397 		}
398 	}
399 
400 	return B_DEV_INVALID_IOCTL;
401 }
402 
403 
404 status_t
405 get_nth_roothub(uint32 index, usb_device *rootHub)
406 {
407 	if (!rootHub)
408 		return B_BAD_VALUE;
409 
410 	BusManager *busManager = gUSBStack->BusManagerAt(index);
411 	if (!busManager)
412 		return B_ENTRY_NOT_FOUND;
413 
414 	Hub *hub = busManager->GetRootHub();
415 	if (!hub)
416 		return B_NO_INIT;
417 
418 	*rootHub = hub->USBID();
419 	return B_OK;
420 }
421 
422 
423 status_t
424 get_nth_child(usb_device _hub, uint8 index, usb_device *childDevice)
425 {
426 	if (!childDevice)
427 		return B_BAD_VALUE;
428 
429 	Object *object = gUSBStack->GetObject(_hub);
430 	if (!object || (object->Type() & USB_OBJECT_HUB) == 0)
431 		return B_DEV_INVALID_PIPE;
432 
433 	Hub *hub = (Hub *)object;
434 	for (uint8 i = 0; i < 8; i++) {
435 		if (hub->ChildAt(i) == NULL)
436 			continue;
437 
438 		if (index-- > 0)
439 			continue;
440 
441 		*childDevice = hub->ChildAt(i)->USBID();
442 		return B_OK;
443 	}
444 
445 	return B_ENTRY_NOT_FOUND;
446 }
447 
448 
449 status_t
450 get_device_parent(usb_device _device, usb_device *parentHub, uint8 *portIndex)
451 {
452 	if (!parentHub || !portIndex)
453 		return B_BAD_VALUE;
454 
455 	Object *object = gUSBStack->GetObject(_device);
456 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
457 		return B_DEV_INVALID_PIPE;
458 
459 	Object *parent = object->Parent();
460 	if (!parent || (parent->Type() & USB_OBJECT_HUB) == 0)
461 		return B_ENTRY_NOT_FOUND;
462 
463 	Hub *hub = (Hub *)parent;
464 	for (uint8 i = 0; i < 8; i++) {
465 		if (hub->ChildAt(i) == object) {
466 			*portIndex = i;
467 			*parentHub = hub->USBID();
468 			return B_OK;
469 		}
470 	}
471 
472 	return B_ERROR;
473 }
474 
475 
476 status_t
477 reset_port(usb_device _hub, uint8 portIndex)
478 {
479 	Object *object = gUSBStack->GetObject(_hub);
480 	if (!object || (object->Type() & USB_OBJECT_HUB) == 0)
481 		return B_DEV_INVALID_PIPE;
482 
483 	Hub *hub = (Hub *)object;
484 	return hub->ResetPort(portIndex);
485 }
486 
487 
488 status_t
489 disable_port(usb_device _hub, uint8 portIndex)
490 {
491 	Object *object = gUSBStack->GetObject(_hub);
492 	if (!object || (object->Type() & USB_OBJECT_HUB) == 0)
493 		return B_DEV_INVALID_PIPE;
494 
495 	Hub *hub = (Hub *)object;
496 	return hub->DisablePort(portIndex);
497 }
498 
499 
500 /*
501 	This module exports the USB API v3
502 */
503 struct usb_module_info gModuleInfoV3 = {
504 	// First the bus_manager_info:
505 	{
506 		{
507 			"bus_managers/usb/v3",
508 			B_KEEP_LOADED,				// Keep loaded, even if no driver requires it
509 			bus_std_ops
510 		},
511 		NULL							// the rescan function
512 	},
513 
514 	register_driver,					// register_driver
515 	install_notify,						// install_notify
516 	uninstall_notify,					// uninstall_notify
517 	get_device_descriptor,				// get_device_descriptor
518 	get_nth_configuration,				// get_nth_configuration
519 	get_configuration,					// get_configuration
520 	set_configuration,					// set_configuration
521 	set_alt_interface,					// set_alt_interface
522 	set_feature,						// set_feature
523 	clear_feature, 						// clear_feature
524 	get_status, 						// get_status
525 	get_descriptor,						// get_descriptor
526 	send_request,						// send_request
527 	queue_interrupt,					// queue_interrupt
528 	queue_bulk,							// queue_bulk
529 	queue_bulk_v,						// queue_bulk_v
530 	queue_isochronous,					// queue_isochronous
531 	queue_request,						// queue_request
532 	set_pipe_policy,					// set_pipe_policy
533 	cancel_queued_transfers,			// cancel_queued_transfers
534 	usb_ioctl,							// usb_ioctl
535 	get_nth_roothub,					// get_nth_roothub
536 	get_nth_child,						// get_nth_child
537 	get_device_parent,					// get_device_parent
538 	reset_port,							// reset_port
539 	disable_port						// disable_port
540 };
541 
542 
543 //
544 // #pragma mark -
545 //
546 
547 
548 const usb_device_descriptor *
549 get_device_descriptor_v2(const void *device)
550 {
551 	return get_device_descriptor((usb_id)device);
552 }
553 
554 
555 const usb_configuration_info *
556 get_nth_configuration_v2(const void *device, uint index)
557 {
558 	return get_nth_configuration((usb_id)device, index);
559 }
560 
561 
562 const usb_configuration_info *
563 get_configuration_v2(const void *device)
564 {
565 	return get_configuration((usb_id)device);
566 }
567 
568 
569 status_t
570 set_configuration_v2(const void *device,
571 	const usb_configuration_info *configuration)
572 {
573 	return set_configuration((usb_id)device, configuration);
574 }
575 
576 
577 status_t
578 set_alt_interface_v2(const void *device, const usb_interface_info *interface)
579 {
580 	return set_alt_interface((usb_id)device, interface);
581 }
582 
583 
584 status_t
585 set_feature_v2(const void *object, uint16 selector)
586 {
587 	return set_feature((usb_id)object, selector);
588 }
589 
590 
591 status_t
592 clear_feature_v2(const void *object, uint16 selector)
593 {
594 	return clear_feature((usb_id)object, selector);
595 }
596 
597 
598 status_t
599 get_status_v2(const void *object, uint16 *status)
600 {
601 	return get_status((usb_id)object, status);
602 }
603 
604 
605 status_t
606 get_descriptor_v2(const void *device, uint8 type, uint8 index,
607 	uint16 languageID, void *data, size_t dataLength, size_t *actualLength)
608 {
609 	return get_descriptor((usb_id)device, type, index, languageID, data,
610 		dataLength, actualLength);
611 }
612 
613 
614 status_t
615 send_request_v2(const void *device, uint8 requestType, uint8 request,
616 	uint16 value, uint16 index, uint16 length, void *data,
617 	size_t /*dataLength*/, size_t *actualLength)
618 {
619 	return send_request((usb_id)device, requestType, request, value, index,
620 		length, data, actualLength);
621 }
622 
623 
624 status_t
625 queue_request_v2(const void *device, uint8 requestType, uint8 request,
626 	uint16 value, uint16 index, uint16 length, void *data,
627 	size_t /*dataLength*/, usb_callback_func callback, void *callbackCookie)
628 {
629 	return queue_request((usb_id)device, requestType, request, value, index,
630 		length, data, callback, callbackCookie);
631 }
632 
633 
634 status_t
635 queue_interrupt_v2(const void *pipe, void *data, size_t dataLength,
636 	usb_callback_func callback, void *callbackCookie)
637 {
638 	return queue_interrupt((usb_id)pipe, data, dataLength, callback,
639 		callbackCookie);
640 }
641 
642 
643 status_t
644 queue_bulk_v2(const void *pipe, void *data, size_t dataLength,
645 	usb_callback_func callback, void *callbackCookie)
646 {
647 	return queue_bulk((usb_id)pipe, data, dataLength, callback,
648 		callbackCookie);
649 }
650 
651 
652 status_t
653 queue_isochronous_v2(const void *pipe, void *data, size_t dataLength,
654 	rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback,
655 	void *callbackCookie)
656 {
657 	// ToDo: convert rlea to usb_iso_packet_descriptor
658 	// ToDo: use a flag to indicate that the callback shall produce a rlea
659 	usb_iso_packet_descriptor *packetDesc = NULL;
660 	return queue_isochronous((usb_id)pipe, data, dataLength, packetDesc, 0,
661 		NULL, 0, callback, callbackCookie);
662 }
663 
664 
665 status_t
666 set_pipe_policy_v2(const void *pipe, uint8 maxQueuedPackets,
667 	uint16 maxBufferDurationMS, uint16 sampleSize)
668 {
669 	return set_pipe_policy((usb_id)pipe, maxQueuedPackets, maxBufferDurationMS,
670 		sampleSize);
671 }
672 
673 
674 status_t
675 cancel_queued_transfers_v2(const void *pipe)
676 {
677 	return cancel_queued_transfers((usb_id)pipe);
678 }
679 
680 
681 struct usb_module_info_v2 {
682 	bus_manager_info				binfo;
683 	status_t						(*register_driver)(const char *, const usb_support_descriptor *, size_t, const char *);
684 	status_t						(*install_notify)(const char *, const usb_notify_hooks *);
685 	status_t						(*uninstall_notify)(const char *);
686 	const usb_device_descriptor		*(*get_device_descriptor)(const void *);
687 	const usb_configuration_info	*(*get_nth_configuration)(const void *, uint);
688 	const usb_configuration_info	*(*get_configuration)(const void *);
689 	status_t						(*set_configuration)(const void *, const usb_configuration_info *);
690 	status_t						(*set_alt_interface)(const void *, const usb_interface_info *);
691 	status_t						(*set_feature)(const void *, uint16);
692 	status_t						(*clear_feature)(const void *, uint16);
693 	status_t						(*get_status)(const void *, uint16 *);
694 	status_t						(*get_descriptor)(const void *, uint8, uint8, uint16, void *, size_t, size_t *);
695 	status_t						(*send_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, size_t *);
696 	status_t						(*queue_interrupt)(const void *, void *, size_t, usb_callback_func, void *);
697 	status_t						(*queue_bulk)(const void *, void *, size_t, usb_callback_func, void *);
698 	status_t						(*queue_isochronous)(const void *, void *, size_t, rlea *, uint16, usb_callback_func, void *);
699 	status_t						(*queue_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, usb_callback_func, void *);
700 	status_t						(*set_pipe_policy)(const void *, uint8, uint16, uint16);
701 	status_t						(*cancel_queued_transfers)(const void *);
702 	status_t						(*usb_ioctl)(uint32 opcode, void *,size_t);
703 };
704 
705 
706 /*
707 	This module exports the USB API v2
708 */
709 struct usb_module_info_v2 gModuleInfoV2 = {
710 	// First the bus_manager_info:
711 	{
712 		{
713 			"bus_managers/usb/v2",
714 			B_KEEP_LOADED,				// Keep loaded, even if no driver requires it
715 			bus_std_ops
716 		},
717 		NULL							// the rescan function
718 	},
719 
720 	register_driver,					// register_driver
721 	install_notify,						// install_notify
722 	uninstall_notify,					// uninstall_notify
723 	get_device_descriptor_v2,			// get_device_descriptor
724 	get_nth_configuration_v2,			// get_nth_configuration
725 	get_configuration_v2,				// get_configuration
726 	set_configuration_v2,				// set_configuration
727 	set_alt_interface_v2,				// set_alt_interface
728 	set_feature_v2,						// set_feature
729 	clear_feature_v2,					// clear_feature
730 	get_status_v2, 						// get_status
731 	get_descriptor_v2,					// get_descriptor
732 	send_request_v2,					// send_request
733 	queue_interrupt_v2,					// queue_interrupt
734 	queue_bulk_v2,						// queue_bulk
735 	queue_isochronous_v2,				// queue_isochronous
736 	queue_request_v2,					// queue_request
737 	set_pipe_policy_v2,					// set_pipe_policy
738 	cancel_queued_transfers_v2,			// cancel_queued_transfers
739 	usb_ioctl							// usb_ioctl
740 };
741 
742 
743 //
744 // #pragma mark -
745 //
746 
747 
748 module_info *modules[] = {
749 	(module_info *)&gModuleInfoV2,
750 	(module_info *)&gModuleInfoV3,
751 	NULL
752 };
753