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