xref: /haiku/src/add-ons/kernel/bus_managers/usb/usb.cpp (revision fc7456e9b1ec38c941134ed6d01c438cf289381e)
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 device_manager_info *gDeviceManager;
19 
20 
21 /*!	The function is an evil hack to allow <tt> <kdebug>usb_keyboard </tt> to
22 	execute transfers.
23 	When invoked the first time, a new transfer is started, each time the
24 	function is called afterwards, it is checked whether the transfer is already
25 	completed. If called with argv[1] == "cancel" the function cancels a
26 	possibly pending transfer.
27 */
28 static status_t
29 debug_run_transfer(Pipe *pipe, uint8 *data, size_t dataLength,
30 	usb_request_data *requestData, bool cancel)
31 {
32 	static uint8 transferBuffer[sizeof(Transfer)]
33 		__attribute__((aligned(16)));
34 	static Transfer *transfer = NULL;
35 
36 	BusManager *bus = pipe->GetBusManager();
37 
38 	if (cancel) {
39 		if (transfer != NULL) {
40 			bus->CancelDebugTransfer(transfer);
41 			transfer = NULL;
42 		}
43 
44 		return B_OK;
45 	}
46 
47 	if (transfer != NULL) {
48 		status_t error = bus->CheckDebugTransfer(transfer);
49 		if (error != B_DEV_PENDING)
50 			transfer = NULL;
51 
52 		return error;
53 	}
54 
55 	transfer = new(transferBuffer) Transfer(pipe);
56 	transfer->SetData(data, dataLength);
57 	transfer->SetRequestData(requestData);
58 
59 	status_t error = bus->StartDebugTransfer(transfer);
60 	if (error != B_OK) {
61 		transfer = NULL;
62 		return error;
63 	}
64 
65 	return B_DEV_PENDING;
66 }
67 
68 
69 static int
70 debug_get_pipe_for_id(int argc, char **argv)
71 {
72 	if (gUSBStack == NULL)
73 		return 1;
74 
75 	if (!is_debug_variable_defined("_usbPipeID"))
76 		return 2;
77 
78 	uint64 id = get_debug_variable("_usbPipeID", 0);
79 	Object *object = gUSBStack->GetObjectNoLock((usb_id)id);
80 	if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
81 		return 3;
82 
83 	set_debug_variable("_usbPipe", (uint64)object);
84 	return 0;
85 }
86 
87 
88 static int
89 debug_process_transfer(int argc, char **argv)
90 {
91 	Pipe *pipe = (Pipe *)get_debug_variable("_usbPipe", 0);
92 	if (pipe == NULL)
93 		return B_BAD_VALUE;
94 
95 	uint8 *data = (uint8 *)get_debug_variable("_usbTransferData", 0);
96 	size_t length = (size_t)get_debug_variable("_usbTransferLength", 0);
97 	usb_request_data *requestData
98 		= (usb_request_data *)get_debug_variable("_usbRequestData", 0);
99 
100 	return debug_run_transfer(pipe, data, length, requestData,
101 		argc > 1 && strcmp(argv[1], "cancel") == 0);
102 }
103 
104 
105 static int
106 debug_clear_stall(int argc, char *argv[])
107 {
108 	Pipe *pipe = (Pipe *)get_debug_variable("_usbPipe", 0);
109 	if (pipe == NULL)
110 		return B_BAD_VALUE;
111 
112 	static usb_request_data requestData;
113 
114 	requestData.RequestType = USB_REQTYPE_STANDARD | USB_REQTYPE_ENDPOINT_OUT;
115 	requestData.Request = USB_REQUEST_CLEAR_FEATURE;
116 	requestData.Value = USB_FEATURE_ENDPOINT_HALT;
117 	requestData.Index = pipe->EndpointAddress()
118 		| (pipe->Direction() == Pipe::In ? USB_ENDPOINT_ADDR_DIR_IN
119 			: USB_ENDPOINT_ADDR_DIR_OUT);
120 	requestData.Length = 0;
121 
122 	Pipe *parentPipe = ((Device *)pipe->Parent())->DefaultPipe();
123 	for (int tries = 0; tries < 100; tries++) {
124 		status_t result
125 			= debug_run_transfer(parentPipe, NULL, 0, &requestData, false);
126 
127 		if (result == B_DEV_PENDING)
128 			continue;
129 
130 		if (result == B_OK) {
131 			// clearing a stalled condition resets the data toggle
132 			pipe->SetDataToggle(false);
133 			return B_OK;
134 		}
135 
136 		return result;
137 	}
138 
139 	return B_TIMED_OUT;
140 }
141 
142 
143 static int32
144 bus_std_ops(int32 op, ...)
145 {
146 	switch (op) {
147 		case B_MODULE_INIT: {
148 			TRACE_MODULE("init\n");
149 			if (gUSBStack)
150 				return B_OK;
151 
152 #ifdef TRACE_USB
153 			set_dprintf_enabled(true);
154 #endif
155 			Stack *stack = new(std::nothrow) Stack();
156 			TRACE_MODULE("usb_module: stack created %p\n", stack);
157 			if (!stack)
158 				return B_NO_MEMORY;
159 
160 			if (stack->InitCheck() != B_OK) {
161 				delete stack;
162 				return ENODEV;
163 			}
164 
165 			gUSBStack = stack;
166 
167 			add_debugger_command("get_usb_pipe_for_id",
168 				&debug_get_pipe_for_id,
169 				"Sets _usbPipe by resolving _usbPipeID");
170 			add_debugger_command("usb_process_transfer",
171 				&debug_process_transfer,
172 				"Transfers _usbTransferData with _usbTransferLength"
173 				" (and/or _usbRequestData) to pipe _usbPipe");
174 			add_debugger_command("usb_clear_stall",
175 				&debug_clear_stall,
176 				"Tries to issue a clear feature request for the endpoint halt"
177 				" feature on pipe _usbPipe");
178 			break;
179 		}
180 
181 		case B_MODULE_UNINIT:
182 			TRACE_MODULE("uninit\n");
183 			delete gUSBStack;
184 			gUSBStack = NULL;
185 
186 			remove_debugger_command("get_usb_pipe_for_id",
187 				&debug_get_pipe_for_id);
188 			break;
189 
190 		default:
191 			return EINVAL;
192 	}
193 
194 	return B_OK;
195 }
196 
197 
198 // #pragma mark - public methods
199 
200 
201 status_t
202 register_driver(const char *driverName,
203 	const usb_support_descriptor *descriptors,
204 	size_t count, const char *optionalRepublishDriverName)
205 {
206 	return gUSBStack->RegisterDriver(driverName, descriptors, count,
207 		optionalRepublishDriverName);
208 }
209 
210 
211 status_t
212 install_notify(const char *driverName, const usb_notify_hooks *hooks)
213 {
214 	return gUSBStack->InstallNotify(driverName, hooks);
215 }
216 
217 
218 status_t
219 uninstall_notify(const char *driverName)
220 {
221 	return gUSBStack->UninstallNotify(driverName);
222 }
223 
224 
225 const usb_device_descriptor *
226 get_device_descriptor(usb_device dev)
227 {
228 	TRACE_MODULE("get_device_descriptor(%" B_PRId32 ")\n", dev);
229 	BReference<Object> object(gUSBStack->GetObject(dev), true);
230 	if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
231 		return NULL;
232 	Device *device = (Device *)object.Get();
233 
234 	return device->DeviceDescriptor();
235 }
236 
237 
238 const usb_configuration_info *
239 get_nth_configuration(usb_device dev, uint32 index)
240 {
241 	TRACE_MODULE("get_nth_configuration(%" B_PRId32 ", %" B_PRIu32 ")\n",
242 		dev, index);
243 	BReference<Object> object(gUSBStack->GetObject(dev), true);
244 	if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
245 		return NULL;
246 	Device *device = (Device *)object.Get();
247 
248 	return device->ConfigurationAt((int32)index);
249 }
250 
251 
252 const usb_configuration_info *
253 get_configuration(usb_device dev)
254 {
255 	TRACE_MODULE("get_configuration(%" B_PRId32 ")\n", dev);
256 	BReference<Object> object(gUSBStack->GetObject(dev), true);
257 	if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
258 		return NULL;
259 	Device *device = (Device *)object.Get();
260 
261 	return device->Configuration();
262 }
263 
264 
265 status_t
266 set_configuration(usb_device dev,
267 	const usb_configuration_info *configuration)
268 {
269 	TRACE_MODULE("set_configuration(%" B_PRId32 ", %p)\n", dev,
270 		configuration);
271 	BReference<Object> object(gUSBStack->GetObject(dev), true);
272 	if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
273 		return B_DEV_INVALID_PIPE;
274 	Device *device = (Device *)object.Get();
275 
276 	return device->SetConfiguration(configuration);
277 }
278 
279 
280 status_t
281 set_alt_interface(usb_device dev, const usb_interface_info *interface)
282 {
283 	TRACE_MODULE("set_alt_interface(%" B_PRId32 ", %p)\n", dev, interface);
284 	BReference<Object> object(gUSBStack->GetObject(dev), true);
285 	if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
286 		return B_DEV_INVALID_PIPE;
287 	Device *device = (Device *)object.Get();
288 
289 	return device->SetAltInterface(interface);
290 }
291 
292 
293 status_t
294 set_feature(usb_id handle, uint16 selector)
295 {
296 	TRACE_MODULE("set_feature(%" B_PRId32 ", %d)\n", handle, selector);
297 	BReference<Object> object(gUSBStack->GetObject(handle), true);
298 	if (!object.IsSet())
299 		return B_DEV_INVALID_PIPE;
300 
301 	return object->SetFeature(selector);
302 }
303 
304 
305 status_t
306 clear_feature(usb_id handle, uint16 selector)
307 {
308 	TRACE_MODULE("clear_feature(%" B_PRId32 ", %d)\n", handle, selector);
309 	BReference<Object> object(gUSBStack->GetObject(handle), true);
310 	if (!object.IsSet())
311 		return B_DEV_INVALID_PIPE;
312 
313 	return object->ClearFeature(selector);
314 }
315 
316 
317 status_t
318 get_status(usb_id handle, uint16 *status)
319 {
320 	TRACE_MODULE("get_status(%" B_PRId32 ", %p)\n", handle, status);
321 	if (!status)
322 		return B_BAD_VALUE;
323 
324 	BReference<Object> object(gUSBStack->GetObject(handle), true);
325 	if (!object.IsSet())
326 		return B_DEV_INVALID_PIPE;
327 
328 	return object->GetStatus(status);
329 }
330 
331 
332 status_t
333 get_descriptor(usb_device dev, uint8 type, uint8 index, uint16 languageID,
334 	void *data, size_t dataLength, size_t *actualLength)
335 {
336 	TRACE_MODULE("get_descriptor(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, %p, "
337 		"%" B_PRIuSIZE ", %p)\n",
338 		dev, type, index, languageID, data, dataLength, actualLength);
339 	BReference<Object> object(gUSBStack->GetObject(dev), true);
340 	if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
341 		return B_DEV_INVALID_PIPE;
342 	Device *device = (Device *)object.Get();
343 
344 	return device->GetDescriptor(type, index, languageID,
345 		data, dataLength, actualLength);
346 }
347 
348 
349 status_t
350 send_request(usb_device dev, uint8 requestType, uint8 request,
351 	uint16 value, uint16 index, uint16 length, void *data, size_t *actualLength)
352 {
353 	TRACE_MODULE("send_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x, "
354 		"%d, %p, %p)\n", dev, requestType, request, value, index, length,
355 		data, actualLength);
356 	BReference<Object> object(gUSBStack->GetObject(dev), true);
357 	if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
358 		return B_DEV_INVALID_PIPE;
359 	Device *device = (Device *)object.Get();
360 
361 	return device->DefaultPipe()->SendRequest(requestType, request,
362 		value, index, length, data, length, actualLength);
363 }
364 
365 
366 status_t
367 queue_request(usb_device dev, uint8 requestType, uint8 request,
368 	uint16 value, uint16 index, uint16 length, void *data,
369 	usb_callback_func callback, void *callbackCookie)
370 {
371 	TRACE_MODULE("queue_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x,"
372 		" %u, %p, %p, %p)\n", dev, requestType, request, value, index,
373 		length, data, callback,	callbackCookie);
374 	BReference<Object> object(gUSBStack->GetObject(dev), true);
375 	if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
376 		return B_DEV_INVALID_PIPE;
377 	Device *device = (Device *)object.Get();
378 
379 	return device->DefaultPipe()->QueueRequest(requestType,
380 		request, value, index, length, data, length, callback, callbackCookie);
381 }
382 
383 
384 status_t
385 queue_interrupt(usb_pipe pipe, void *data, size_t dataLength,
386 	usb_callback_func callback, void *callbackCookie)
387 {
388 	TRACE_MODULE("queue_interrupt(%" B_PRId32 ", %p, %ld, %p, %p)\n",
389 		pipe, data, dataLength, callback, callbackCookie);
390 	BReference<Object> object(gUSBStack->GetObject(pipe), true);
391 	if (!object.IsSet() || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0)
392 		return B_DEV_INVALID_PIPE;
393 
394 	return ((InterruptPipe *)object.Get())->QueueInterrupt(data, dataLength,
395 		callback, callbackCookie);
396 }
397 
398 
399 status_t
400 queue_bulk(usb_pipe pipe, void *data, size_t dataLength,
401 	usb_callback_func callback, void *callbackCookie)
402 {
403 	TRACE_MODULE("queue_bulk(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, %p)\n",
404 		pipe, data, dataLength, callback, callbackCookie);
405 	BReference<Object> object(gUSBStack->GetObject(pipe), true);
406 	if (!object.IsSet() || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
407 		return B_DEV_INVALID_PIPE;
408 
409 	return ((BulkPipe *)object.Get())->QueueBulk(data, dataLength, callback,
410 		callbackCookie);
411 }
412 
413 
414 status_t
415 queue_bulk_v(usb_pipe pipe, iovec *vector, size_t vectorCount,
416 	usb_callback_func callback, void *callbackCookie)
417 {
418 	TRACE_MODULE("queue_bulk_v(%" B_PRId32 ", %p, %" B_PRIuSIZE " %p, %p)\n",
419 		pipe, vector, vectorCount, callback, callbackCookie);
420 	BReference<Object> object(gUSBStack->GetObject(pipe), true);
421 	if (!object.IsSet() || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
422 		return B_DEV_INVALID_PIPE;
423 
424 	return ((BulkPipe *)object.Get())->QueueBulkV(vector, vectorCount,
425 		callback, callbackCookie);
426 }
427 
428 
429 status_t
430 queue_bulk_v_physical(usb_pipe pipe, physical_entry *vector, size_t vectorCount,
431 	usb_callback_func callback, void *callbackCookie)
432 {
433 	TRACE_MODULE("queue_bulk_v_physical(%" B_PRId32 ", %p, %" B_PRIuSIZE
434 		", %p, %p)\n", pipe, vector, vectorCount, callback, callbackCookie);
435 	BReference<Object> object(gUSBStack->GetObject(pipe), true);
436 	if (!object.IsSet() || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
437 		return B_DEV_INVALID_PIPE;
438 
439 	return ((BulkPipe *)object.Get())->QueueBulkV(vector, vectorCount,
440 		callback, callbackCookie);
441 }
442 
443 
444 status_t
445 queue_isochronous(usb_pipe pipe, void *data, size_t dataLength,
446 	usb_iso_packet_descriptor *packetDesc, uint32 packetCount,
447 	uint32 *startingFrameNumber, uint32 flags, usb_callback_func callback,
448 	void *callbackCookie)
449 {
450 	TRACE_MODULE("queue_isochronous(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, "
451 		"%" B_PRId32 ", %p, 0x%08" B_PRIx32 ", %p, %p)\n",
452 		pipe, data, dataLength, packetDesc, packetCount, startingFrameNumber,
453 		flags, callback, callbackCookie);
454 	BReference<Object> object(gUSBStack->GetObject(pipe), true);
455 	if (!object.IsSet() || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
456 		return B_DEV_INVALID_PIPE;
457 
458 	return ((IsochronousPipe *)object.Get())->QueueIsochronous(data, dataLength,
459 		packetDesc, packetCount, startingFrameNumber, flags, callback,
460 		callbackCookie);
461 }
462 
463 
464 status_t
465 set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets,
466 	uint16 maxBufferDurationMS, uint16 sampleSize)
467 {
468 	TRACE_MODULE("set_pipe_policy(%" B_PRId32 ", %d, %d, %d)\n", pipe,
469 		maxQueuedPackets, maxBufferDurationMS, sampleSize);
470 	BReference<Object> object(gUSBStack->GetObject(pipe), true);
471 	if (!object.IsSet() || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
472 		return B_DEV_INVALID_PIPE;
473 
474 	return ((IsochronousPipe *)object.IsSet())->SetPipePolicy(maxQueuedPackets,
475 		maxBufferDurationMS, sampleSize);
476 }
477 
478 
479 status_t
480 cancel_queued_transfers(usb_pipe pipe)
481 {
482 	TRACE_MODULE("cancel_queued_transfers(%" B_PRId32 ")\n", pipe);
483 	BReference<Object> object(gUSBStack->GetObject(pipe), true);
484 	if (!object.IsSet() || (object->Type() & USB_OBJECT_PIPE) == 0)
485 		return B_DEV_INVALID_PIPE;
486 
487 	return ((Pipe *)object.Get())->CancelQueuedTransfers(false);
488 }
489 
490 
491 status_t
492 cancel_queued_requests(usb_device dev)
493 {
494 	TRACE_MODULE("cancel_queued_requests(%" B_PRId32 ")\n", dev);
495 	BReference<Object> object(gUSBStack->GetObject(dev), true);
496 	if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
497 		return B_DEV_INVALID_PIPE;
498 	 Device *device = (Device *)object.Get();
499 
500 	 return device->DefaultPipe()->CancelQueuedTransfers(false);
501 }
502 
503 
504 status_t
505 usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize)
506 {
507 	TRACE_MODULE("usb_ioctl(%" B_PRIu32 ", %p, %" B_PRIuSIZE ")\n", opcode,
508 		buffer, bufferSize);
509 
510 	switch (opcode) {
511 		case 'DNAM': {
512 			BReference<Object> object(gUSBStack->GetObject(*(usb_id *)buffer), true);
513 			if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
514 				return B_BAD_VALUE;
515 			Device *device = (Device *)object.Get();
516 
517 			uint32 index = 0;
518 			return device->BuildDeviceName((char *)buffer, &index,
519 				bufferSize, NULL);
520 		}
521 	}
522 
523 	return B_DEV_INVALID_IOCTL;
524 }
525 
526 
527 status_t
528 get_nth_roothub(uint32 index, usb_device *rootHub)
529 {
530 	if (!rootHub)
531 		return B_BAD_VALUE;
532 
533 	BusManager *busManager = gUSBStack->BusManagerAt(index);
534 	if (!busManager)
535 		return B_ENTRY_NOT_FOUND;
536 
537 	Hub *hub = busManager->GetRootHub();
538 	if (!hub)
539 		return B_NO_INIT;
540 
541 	*rootHub = hub->USBID();
542 	return B_OK;
543 }
544 
545 
546 status_t
547 get_nth_child(usb_device _hub, uint8 index, usb_device *childDevice)
548 {
549 	if (!childDevice)
550 		return B_BAD_VALUE;
551 
552 	BReference<Object> object(gUSBStack->GetObject(_hub), true);
553 	if (!object.IsSet() || (object->Type() & USB_OBJECT_HUB) == 0)
554 		return B_DEV_INVALID_PIPE;
555 
556 	Hub *hub = (Hub *)object.Get();
557 	for (uint8 i = 0; i < 8; i++) {
558 		if (hub->ChildAt(i) == NULL)
559 			continue;
560 
561 		if (index-- > 0)
562 			continue;
563 
564 		*childDevice = hub->ChildAt(i)->USBID();
565 		return B_OK;
566 	}
567 
568 	return B_ENTRY_NOT_FOUND;
569 }
570 
571 
572 status_t
573 get_device_parent(usb_device _device, usb_device *parentHub, uint8 *portIndex)
574 {
575 	if (!parentHub || !portIndex)
576 		return B_BAD_VALUE;
577 
578 	BReference<Object> object(gUSBStack->GetObject(_device), true);
579 	if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
580 		return B_DEV_INVALID_PIPE;
581 
582 	Object *parent = object->Parent();
583 	if (!parent || (parent->Type() & USB_OBJECT_HUB) == 0)
584 		return B_ENTRY_NOT_FOUND;
585 
586 	Hub *hub = (Hub *)parent;
587 	for (uint8 i = 0; i < 8; i++) {
588 		if (hub->ChildAt(i) == object.Get()) {
589 			*portIndex = i;
590 			*parentHub = hub->USBID();
591 			return B_OK;
592 		}
593 	}
594 
595 	return B_ERROR;
596 }
597 
598 
599 status_t
600 reset_port(usb_device _hub, uint8 portIndex)
601 {
602 	BReference<Object> object(gUSBStack->GetObject(_hub), true);
603 	if (!object.IsSet() || (object->Type() & USB_OBJECT_HUB) == 0)
604 		return B_DEV_INVALID_PIPE;
605 
606 	Hub *hub = (Hub *)object.Get();
607 	return hub->ResetPort(portIndex);
608 }
609 
610 
611 status_t
612 disable_port(usb_device _hub, uint8 portIndex)
613 {
614 	BReference<Object> object(gUSBStack->GetObject(_hub), true);
615 	if (!object.IsSet() || (object->Type() & USB_OBJECT_HUB) == 0)
616 		return B_DEV_INVALID_PIPE;
617 
618 	Hub *hub = (Hub *)object.Get();
619 	return hub->DisablePort(portIndex);
620 }
621 
622 
623 /*
624 	This module exports the USB API v3
625 */
626 struct usb_module_info gModuleInfoV3 = {
627 	// First the bus_manager_info:
628 	{
629 		{
630 			"bus_managers/usb/v3.1",
631 			B_KEEP_LOADED,				// Keep loaded, even if no driver requires it
632 			bus_std_ops
633 		},
634 		NULL							// the rescan function
635 	},
636 
637 	register_driver,					// register_driver
638 	install_notify,						// install_notify
639 	uninstall_notify,					// uninstall_notify
640 	get_device_descriptor,				// get_device_descriptor
641 	get_nth_configuration,				// get_nth_configuration
642 	get_configuration,					// get_configuration
643 	set_configuration,					// set_configuration
644 	set_alt_interface,					// set_alt_interface
645 	set_feature,						// set_feature
646 	clear_feature, 						// clear_feature
647 	get_status, 						// get_status
648 	get_descriptor,						// get_descriptor
649 	send_request,						// send_request
650 	queue_interrupt,					// queue_interrupt
651 	queue_bulk,							// queue_bulk
652 	queue_bulk_v,						// queue_bulk_v
653 	queue_bulk_v_physical,				// queue_bulk_v_physical
654 	queue_isochronous,					// queue_isochronous
655 	queue_request,						// queue_request
656 	set_pipe_policy,					// set_pipe_policy
657 	cancel_queued_transfers,			// cancel_queued_transfers
658 	cancel_queued_requests,				// cancel_queued_requests
659 	usb_ioctl,							// usb_ioctl
660 	get_nth_roothub,					// get_nth_roothub
661 	get_nth_child,						// get_nth_child
662 	get_device_parent,					// get_device_parent
663 	reset_port,							// reset_port
664 	disable_port,						// disable_port
665 };
666 
667 
668 //
669 // #pragma mark -
670 //
671 
672 
673 const usb_device_descriptor *
674 get_device_descriptor_v2(const void *device)
675 {
676 	return get_device_descriptor((usb_id)(ssize_t)device);
677 }
678 
679 
680 const usb_configuration_info *
681 get_nth_configuration_v2(const void *device, uint index)
682 {
683 	return get_nth_configuration((usb_id)(ssize_t)device, index);
684 }
685 
686 
687 const usb_configuration_info *
688 get_configuration_v2(const void *device)
689 {
690 	return get_configuration((usb_id)(ssize_t)device);
691 }
692 
693 
694 status_t
695 set_configuration_v2(const void *device,
696 	const usb_configuration_info *configuration)
697 {
698 	return set_configuration((usb_id)(ssize_t)device, configuration);
699 }
700 
701 
702 status_t
703 set_alt_interface_v2(const void *device, const usb_interface_info *interface)
704 {
705 	return set_alt_interface((usb_id)(ssize_t)device, interface);
706 }
707 
708 
709 status_t
710 set_feature_v2(const void *object, uint16 selector)
711 {
712 	return set_feature((usb_id)(ssize_t)object, selector);
713 }
714 
715 
716 status_t
717 clear_feature_v2(const void *object, uint16 selector)
718 {
719 	return clear_feature((usb_id)(ssize_t)object, selector);
720 }
721 
722 
723 status_t
724 get_status_v2(const void *object, uint16 *status)
725 {
726 	return get_status((usb_id)(ssize_t)object, status);
727 }
728 
729 
730 status_t
731 get_descriptor_v2(const void *device, uint8 type, uint8 index,
732 	uint16 languageID, void *data, size_t dataLength, size_t *actualLength)
733 {
734 	return get_descriptor((usb_id)(ssize_t)device, type, index, languageID, data,
735 		dataLength, actualLength);
736 }
737 
738 
739 status_t
740 send_request_v2(const void *device, uint8 requestType, uint8 request,
741 	uint16 value, uint16 index, uint16 length, void *data,
742 	size_t /*dataLength*/, size_t *actualLength)
743 {
744 	return send_request((usb_id)(ssize_t)device, requestType, request, value, index,
745 		length, data, actualLength);
746 }
747 
748 
749 status_t
750 queue_request_v2(const void *device, uint8 requestType, uint8 request,
751 	uint16 value, uint16 index, uint16 length, void *data,
752 	size_t /*dataLength*/, usb_callback_func callback, void *callbackCookie)
753 {
754 	return queue_request((usb_id)(ssize_t)device, requestType, request, value, index,
755 		length, data, callback, callbackCookie);
756 }
757 
758 
759 status_t
760 queue_interrupt_v2(const void *pipe, void *data, size_t dataLength,
761 	usb_callback_func callback, void *callbackCookie)
762 {
763 	return queue_interrupt((usb_id)(ssize_t)pipe, data, dataLength, callback,
764 		callbackCookie);
765 }
766 
767 
768 status_t
769 queue_bulk_v2(const void *pipe, void *data, size_t dataLength,
770 	usb_callback_func callback, void *callbackCookie)
771 {
772 	return queue_bulk((usb_id)(ssize_t)pipe, data, dataLength, callback,
773 		callbackCookie);
774 }
775 
776 
777 status_t
778 queue_isochronous_v2(const void *pipe, void *data, size_t dataLength,
779 	rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback,
780 	void *callbackCookie)
781 {
782 	// ToDo: convert rlea to usb_iso_packet_descriptor
783 	// ToDo: use a flag to indicate that the callback shall produce a rlea
784 	usb_iso_packet_descriptor *packetDesc = NULL;
785 	return queue_isochronous((usb_id)(ssize_t)pipe, data, dataLength, packetDesc, 0,
786 		NULL, 0, callback, callbackCookie);
787 }
788 
789 
790 status_t
791 set_pipe_policy_v2(const void *pipe, uint8 maxQueuedPackets,
792 	uint16 maxBufferDurationMS, uint16 sampleSize)
793 {
794 	return set_pipe_policy((usb_id)(ssize_t)pipe, maxQueuedPackets, maxBufferDurationMS,
795 		sampleSize);
796 }
797 
798 
799 status_t
800 cancel_queued_transfers_v2(const void *pipe)
801 {
802 	return cancel_queued_transfers((usb_id)(ssize_t)pipe);
803 }
804 
805 
806 struct usb_module_info_v2 {
807 	bus_manager_info				binfo;
808 	status_t						(*register_driver)(const char *, const usb_support_descriptor *, size_t, const char *);
809 	status_t						(*install_notify)(const char *, const usb_notify_hooks *);
810 	status_t						(*uninstall_notify)(const char *);
811 	const usb_device_descriptor		*(*get_device_descriptor)(const void *);
812 	const usb_configuration_info	*(*get_nth_configuration)(const void *, uint);
813 	const usb_configuration_info	*(*get_configuration)(const void *);
814 	status_t						(*set_configuration)(const void *, const usb_configuration_info *);
815 	status_t						(*set_alt_interface)(const void *, const usb_interface_info *);
816 	status_t						(*set_feature)(const void *, uint16);
817 	status_t						(*clear_feature)(const void *, uint16);
818 	status_t						(*get_status)(const void *, uint16 *);
819 	status_t						(*get_descriptor)(const void *, uint8, uint8, uint16, void *, size_t, size_t *);
820 	status_t						(*send_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, size_t *);
821 	status_t						(*queue_interrupt)(const void *, void *, size_t, usb_callback_func, void *);
822 	status_t						(*queue_bulk)(const void *, void *, size_t, usb_callback_func, void *);
823 	status_t						(*queue_isochronous)(const void *, void *, size_t, rlea *, uint16, usb_callback_func, void *);
824 	status_t						(*queue_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, usb_callback_func, void *);
825 	status_t						(*set_pipe_policy)(const void *, uint8, uint16, uint16);
826 	status_t						(*cancel_queued_transfers)(const void *);
827 	status_t						(*usb_ioctl)(uint32 opcode, void *,size_t);
828 };
829 
830 
831 /*
832 	This module exports the USB API v2
833 */
834 struct usb_module_info_v2 gModuleInfoV2 = {
835 	// First the bus_manager_info:
836 	{
837 		{
838 			"bus_managers/usb/v2",
839 			B_KEEP_LOADED,				// Keep loaded, even if no driver requires it
840 			bus_std_ops
841 		},
842 		NULL							// the rescan function
843 	},
844 
845 	register_driver,					// register_driver
846 	install_notify,						// install_notify
847 	uninstall_notify,					// uninstall_notify
848 	get_device_descriptor_v2,			// get_device_descriptor
849 	get_nth_configuration_v2,			// get_nth_configuration
850 	get_configuration_v2,				// get_configuration
851 	set_configuration_v2,				// set_configuration
852 	set_alt_interface_v2,				// set_alt_interface
853 	set_feature_v2,						// set_feature
854 	clear_feature_v2,					// clear_feature
855 	get_status_v2, 						// get_status
856 	get_descriptor_v2,					// get_descriptor
857 	send_request_v2,					// send_request
858 	queue_interrupt_v2,					// queue_interrupt
859 	queue_bulk_v2,						// queue_bulk
860 	queue_isochronous_v2,				// queue_isochronous
861 	queue_request_v2,					// queue_request
862 	set_pipe_policy_v2,					// set_pipe_policy
863 	cancel_queued_transfers_v2,			// cancel_queued_transfers
864 	usb_ioctl							// usb_ioctl
865 };
866 
867 
868 //
869 // #pragma mark -
870 //
871 
872 
873 status_t
874 usb_added_device(device_node *parent)
875 {
876 	return B_OK;
877 }
878 
879 
880 status_t
881 usb_get_stack(void** stack)
882 {
883 	*stack = gUSBStack;
884 	return B_OK;
885 }
886 
887 
888 usb_for_controller_interface gForControllerModule = {
889 	{
890 		{
891 			USB_FOR_CONTROLLER_MODULE_NAME,
892 			B_KEEP_LOADED,
893 			&bus_std_ops
894 		},
895 
896 		NULL, // supported devices
897 		usb_added_device,
898 		NULL,
899 		NULL,
900 		NULL
901 	},
902 
903 	usb_get_stack,
904 };
905 
906 
907 static status_t
908 device_std_ops(int32 op, ...)
909 {
910 	switch (op) {
911 		case B_MODULE_INIT:
912 		{
913 			// Link to USB bus.
914 			// USB device driver must have USB bus loaded, but it calls its
915 			// functions directly instead via official interface, so this
916 			// pointer is never read.
917 			module_info *dummy;
918 			return get_module(B_USB_MODULE_NAME, &dummy);
919 		}
920 		case B_MODULE_UNINIT:
921 			return put_module(B_USB_MODULE_NAME);
922 
923 		default:
924 			return B_ERROR;
925 	}
926 }
927 
928 
929 usb_device_interface gUSBDeviceModule = {
930 	{
931 		{
932 			USB_DEVICE_MODULE_NAME,
933 			0,
934 			device_std_ops
935 		},
936 
937 		NULL,	// supported devices
938 		NULL,	// register node
939 	NULL, //usb_init_device,
940 	NULL, //	(void (*)(void *)) usb_uninit_device,
941 		NULL,	// register child devices
942 		NULL,	// rescan
943 	NULL//	(void (*)(void *)) usb_device_removed
944 	},
945 };
946 
947 
948 module_dependency module_dependencies[] = {
949 	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager },
950 	{}
951 };
952 
953 
954 module_info *modules[] = {
955 	(module_info *)&gModuleInfoV2,
956 	(module_info *)&gModuleInfoV3,
957 	(module_info *)&gForControllerModule,
958 	(module_info *)&gUSBDeviceModule,
959 	NULL
960 };
961