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