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