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
17Stack *gUSBStack = NULL;
18device_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*/
28static status_t
29debug_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
69static int
70debug_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
88static int
89debug_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
105static int
106debug_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
143static int32
144bus_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
201class ObjectBusyReleaser {
202public:
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
233private:
234	Object *fObject;
235};
236
237
238// #pragma mark - public methods
239
240
241status_t
242register_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
251status_t
252install_notify(const char *driverName, const usb_notify_hooks *hooks)
253{
254	return gUSBStack->InstallNotify(driverName, hooks);
255}
256
257
258status_t
259uninstall_notify(const char *driverName)
260{
261	return gUSBStack->UninstallNotify(driverName);
262}
263
264
265const usb_device_descriptor *
266get_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
278const usb_configuration_info *
279get_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
292const usb_configuration_info *
293get_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
305status_t
306set_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
320status_t
321set_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
333status_t
334set_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
345status_t
346clear_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
357status_t
358get_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
372status_t
373get_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
389status_t
390send_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
406status_t
407queue_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
424status_t
425queue_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
439status_t
440queue_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
454status_t
455queue_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);
466}
467
468
469status_t
470queue_bulk_v_physical(usb_pipe pipe, physical_entry *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);
481}
482
483
484status_t
485queue_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
504status_t
505set_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
519status_t
520cancel_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
531status_t
532cancel_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
544status_t
545usb_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
567status_t
568get_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
586status_t
587get_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
612status_t
613get_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
639status_t
640reset_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
651status_t
652disable_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*/
666struct usb_module_info gModuleInfoV3 = {
667	// First the bus_manager_info:
668	{
669		{
670			"bus_managers/usb/v3.1",
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_bulk_v_physical,				// queue_bulk_v_physical
694	queue_isochronous,					// queue_isochronous
695	queue_request,						// queue_request
696	set_pipe_policy,					// set_pipe_policy
697	cancel_queued_transfers,			// cancel_queued_transfers
698	cancel_queued_requests,				// cancel_queued_requests
699	usb_ioctl,							// usb_ioctl
700	get_nth_roothub,					// get_nth_roothub
701	get_nth_child,						// get_nth_child
702	get_device_parent,					// get_device_parent
703	reset_port,							// reset_port
704	disable_port,						// disable_port
705};
706
707
708//
709// #pragma mark -
710//
711
712
713const usb_device_descriptor *
714get_device_descriptor_v2(const void *device)
715{
716	return get_device_descriptor((usb_id)(ssize_t)device);
717}
718
719
720const usb_configuration_info *
721get_nth_configuration_v2(const void *device, uint index)
722{
723	return get_nth_configuration((usb_id)(ssize_t)device, index);
724}
725
726
727const usb_configuration_info *
728get_configuration_v2(const void *device)
729{
730	return get_configuration((usb_id)(ssize_t)device);
731}
732
733
734status_t
735set_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
742status_t
743set_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
749status_t
750set_feature_v2(const void *object, uint16 selector)
751{
752	return set_feature((usb_id)(ssize_t)object, selector);
753}
754
755
756status_t
757clear_feature_v2(const void *object, uint16 selector)
758{
759	return clear_feature((usb_id)(ssize_t)object, selector);
760}
761
762
763status_t
764get_status_v2(const void *object, uint16 *status)
765{
766	return get_status((usb_id)(ssize_t)object, status);
767}
768
769
770status_t
771get_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
779status_t
780send_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
789status_t
790queue_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
799status_t
800queue_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
808status_t
809queue_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
817status_t
818queue_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
830status_t
831set_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
839status_t
840cancel_queued_transfers_v2(const void *pipe)
841{
842	return cancel_queued_transfers((usb_id)(ssize_t)pipe);
843}
844
845
846struct 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*/
874struct 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
913status_t
914usb_added_device(device_node *parent)
915{
916	return B_OK;
917}
918
919
920status_t
921usb_get_stack(void** stack)
922{
923	*stack = gUSBStack;
924	return B_OK;
925}
926
927
928usb_for_controller_interface gForControllerModule = {
929	{
930		{
931			USB_FOR_CONTROLLER_MODULE_NAME,
932			B_KEEP_LOADED,
933			&bus_std_ops
934		},
935
936		NULL, // supported devices
937		usb_added_device,
938		NULL,
939		NULL,
940		NULL
941	},
942
943	usb_get_stack,
944};
945
946
947static status_t
948device_std_ops(int32 op, ...)
949{
950	switch (op) {
951		case B_MODULE_INIT:
952		{
953			// Link to USB bus.
954			// USB device driver must have USB bus loaded, but it calls its
955			// functions directly instead via official interface, so this
956			// pointer is never read.
957			module_info *dummy;
958			return get_module(B_USB_MODULE_NAME, &dummy);
959		}
960		case B_MODULE_UNINIT:
961			return put_module(B_USB_MODULE_NAME);
962
963		default:
964			return B_ERROR;
965	}
966}
967
968
969usb_device_interface gUSBDeviceModule = {
970	{
971		{
972			USB_DEVICE_MODULE_NAME,
973			0,
974			device_std_ops
975		},
976
977		NULL,	// supported devices
978		NULL,	// register node
979	NULL, //usb_init_device,
980	NULL, //	(void (*)(void *)) usb_uninit_device,
981		NULL,	// register child devices
982		NULL,	// rescan
983	NULL//	(void (*)(void *)) usb_device_removed
984	},
985};
986
987
988module_dependency module_dependencies[] = {
989	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager },
990	{}
991};
992
993
994module_info *modules[] = {
995	(module_info *)&gModuleInfoV2,
996	(module_info *)&gModuleInfoV3,
997	(module_info *)&gForControllerModule,
998	(module_info *)&gUSBDeviceModule,
999	NULL
1000};
1001