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