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#include <util/kernel_cpp.h>
11#include "usb_private.h"
12#include <USB_rle.h>
13
14#define USB_MODULE_NAME "module"
15
16Stack *gUSBStack = NULL;
17
18
19#ifdef HAIKU_TARGET_PLATFORM_HAIKU
20static int
21debug_get_pipe_for_id(int argc, char **argv)
22{
23	if (gUSBStack == NULL)
24		return 1;
25
26	if (!is_debug_variable_defined("_usbPipeID"))
27		return 2;
28
29	uint64 id = get_debug_variable("_usbPipeID", 0);
30	Object *object = gUSBStack->GetObjectNoLock((usb_id)id);
31	if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
32		return 3;
33
34	// check if we support debug transfers for this pipe (only on UHCI for now)
35	if (object->GetBusManager()->TypeName()[0] != 'u')
36		return 4;
37
38	set_debug_variable("_usbPipe", (uint64)object);
39	return 0;
40}
41#endif
42
43
44static int32
45bus_std_ops(int32 op, ...)
46{
47	switch (op) {
48		case B_MODULE_INIT: {
49			TRACE_MODULE("init\n");
50			if (gUSBStack)
51				return B_OK;
52
53#ifdef HAIKU_TARGET_PLATFORM_BEOS
54			// This code is to handle plain R5 (non-BONE) where the same module
55			// gets loaded multiple times (once for each exported module
56			// interface, the USB v2 and v3 API in our case). We don't want to
57			// ever create multiple stacks however, so we "share" the same stack
58			// for both modules by storing it's address in a shared area.
59			void *address = NULL;
60			area_id shared = find_area("shared usb stack");
61			if (shared >= B_OK && clone_area("usb stack clone", &address,
62				B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, shared) >= B_OK) {
63				gUSBStack = *((Stack **)address);
64				TRACE_MODULE("found shared stack at %p\n", gUSBStack);
65				return B_OK;
66			}
67#endif
68
69#ifdef TRACE_USB
70			set_dprintf_enabled(true);
71#ifndef HAIKU_TARGET_PLATFORM_HAIKU
72			load_driver_symbols("usb");
73#endif
74#endif
75			Stack *stack = new(std::nothrow) Stack();
76			TRACE_MODULE("usb_module: stack created %p\n", stack);
77			if (!stack)
78				return B_NO_MEMORY;
79
80			if (stack->InitCheck() != B_OK) {
81				delete stack;
82				return ENODEV;
83			}
84
85			gUSBStack = stack;
86
87#ifdef HAIKU_TARGET_PLATFORM_HAIKU
88			add_debugger_command("get_usb_pipe_for_id",
89				&debug_get_pipe_for_id,
90				"Gets the config for a USB pipe");
91#elif HAIKU_TARGET_PLATFORM_BEOS
92			// Plain R5 workaround, see comment above.
93			shared = create_area("shared usb stack", &address,
94				B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, B_NO_LOCK,
95				B_KERNEL_WRITE_AREA);
96			if (shared >= B_OK)
97				*((Stack **)address) = gUSBStack;
98#endif
99			break;
100		}
101
102		case B_MODULE_UNINIT:
103			TRACE_MODULE("uninit\n");
104			delete gUSBStack;
105			gUSBStack = NULL;
106
107#ifdef HAIKU_TARGET_PLATFORM_HAIKU
108			remove_debugger_command("get_usb_pipe_for_id",
109				&debug_get_pipe_for_id);
110#endif
111			break;
112
113		default:
114			return EINVAL;
115	}
116
117	return B_OK;
118}
119
120
121status_t
122register_driver(const char *driverName,
123	const usb_support_descriptor *descriptors,
124	size_t count, const char *optionalRepublishDriverName)
125{
126	return gUSBStack->RegisterDriver(driverName, descriptors, count,
127		optionalRepublishDriverName);
128}
129
130
131status_t
132install_notify(const char *driverName, const usb_notify_hooks *hooks)
133{
134	return gUSBStack->InstallNotify(driverName, hooks);
135}
136
137
138status_t
139uninstall_notify(const char *driverName)
140{
141	return gUSBStack->UninstallNotify(driverName);
142}
143
144
145const usb_device_descriptor *
146get_device_descriptor(usb_device device)
147{
148	TRACE_MODULE("get_device_descriptor(%" B_PRId32 ")\n", device);
149	Object *object = gUSBStack->GetObject(device);
150	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
151		return NULL;
152
153	return ((Device *)object)->DeviceDescriptor();
154}
155
156
157const usb_configuration_info *
158get_nth_configuration(usb_device device, uint32 index)
159{
160	TRACE_MODULE("get_nth_configuration(%" B_PRId32 ", %" B_PRIu32 ")\n",
161		device, index);
162	Object *object = gUSBStack->GetObject(device);
163	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
164		return NULL;
165
166	return ((Device *)object)->ConfigurationAt((int32)index);
167}
168
169
170const usb_configuration_info *
171get_configuration(usb_device device)
172{
173	TRACE_MODULE("get_configuration(%" B_PRId32 ")\n", device);
174	Object *object = gUSBStack->GetObject(device);
175	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
176		return NULL;
177
178	return ((Device *)object)->Configuration();
179}
180
181
182status_t
183set_configuration(usb_device device,
184	const usb_configuration_info *configuration)
185{
186	TRACE_MODULE("set_configuration(%" B_PRId32 ", %p)\n", device,
187		configuration);
188	Object *object = gUSBStack->GetObject(device);
189	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
190		return B_DEV_INVALID_PIPE;
191
192	return ((Device *)object)->SetConfiguration(configuration);
193}
194
195
196status_t
197set_alt_interface(usb_device device, const usb_interface_info *interface)
198{
199	TRACE_MODULE("set_alt_interface(%" B_PRId32 ", %p)\n", device, interface);
200	Object *object = gUSBStack->GetObject(device);
201	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
202		return B_DEV_INVALID_PIPE;
203
204	return ((Device *)object)->SetAltInterface(interface);
205}
206
207
208status_t
209set_feature(usb_id handle, uint16 selector)
210{
211	TRACE_MODULE("set_feature(%" B_PRId32 ", %d)\n", handle, selector);
212	Object *object = gUSBStack->GetObject(handle);
213	if (!object)
214		return B_DEV_INVALID_PIPE;
215
216	return object->SetFeature(selector);
217}
218
219
220status_t
221clear_feature(usb_id handle, uint16 selector)
222{
223	TRACE_MODULE("clear_feature(%" B_PRId32 ", %d)\n", handle, selector);
224	Object *object = gUSBStack->GetObject(handle);
225	if (!object)
226		return B_DEV_INVALID_PIPE;
227
228	return object->ClearFeature(selector);
229}
230
231
232status_t
233get_status(usb_id handle, uint16 *status)
234{
235	TRACE_MODULE("get_status(%" B_PRId32 ", %p)\n", handle, status);
236	if (!status)
237		return B_BAD_VALUE;
238
239	Object *object = gUSBStack->GetObject(handle);
240	if (!object)
241		return B_DEV_INVALID_PIPE;
242
243	return object->GetStatus(status);
244}
245
246
247status_t
248get_descriptor(usb_device device, uint8 type, uint8 index, uint16 languageID,
249	void *data, size_t dataLength, size_t *actualLength)
250{
251	TRACE_MODULE("get_descriptor(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, %p, "
252		"%" B_PRIuSIZE ", %p)\n",
253		device, type, index, languageID, data, dataLength, actualLength);
254	Object *object = gUSBStack->GetObject(device);
255	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
256		return B_DEV_INVALID_PIPE;
257
258	return ((Device *)object)->GetDescriptor(type, index, languageID,
259		data, dataLength, actualLength);
260}
261
262
263status_t
264send_request(usb_device device, uint8 requestType, uint8 request,
265	uint16 value, uint16 index, uint16 length, void *data, size_t *actualLength)
266{
267	TRACE_MODULE("send_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x, "
268		"%d, %p, %p)\n", device, requestType, request, value, index, length,
269		data, actualLength);
270	Object *object = gUSBStack->GetObject(device);
271	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
272		return B_DEV_INVALID_PIPE;
273
274	return ((Device *)object)->DefaultPipe()->SendRequest(requestType, request,
275		value, index, length, data, length, actualLength);
276}
277
278
279status_t
280queue_request(usb_device device, uint8 requestType, uint8 request,
281	uint16 value, uint16 index, uint16 length, void *data,
282	usb_callback_func callback, void *callbackCookie)
283{
284	TRACE_MODULE("queue_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x,"
285		" %u, %p, %p, %p)\n", device, requestType, request, value, index,
286		length, data, callback,	callbackCookie);
287	Object *object = gUSBStack->GetObject(device);
288	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
289		return B_DEV_INVALID_PIPE;
290
291	return ((Device *)object)->DefaultPipe()->QueueRequest(requestType,
292		request, value, index, length, data, length, callback, callbackCookie);
293}
294
295
296status_t
297queue_interrupt(usb_pipe pipe, void *data, size_t dataLength,
298	usb_callback_func callback, void *callbackCookie)
299{
300	TRACE_MODULE("queue_interrupt(%" B_PRId32 ", %p, %ld, %p, %p)\n",
301		pipe, data, dataLength, callback, callbackCookie);
302	Object *object = gUSBStack->GetObject(pipe);
303	if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0)
304		return B_DEV_INVALID_PIPE;
305
306	return ((InterruptPipe *)object)->QueueInterrupt(data, dataLength, callback,
307		callbackCookie);
308}
309
310
311status_t
312queue_bulk(usb_pipe pipe, void *data, size_t dataLength,
313	usb_callback_func callback, void *callbackCookie)
314{
315	TRACE_MODULE("queue_bulk(%"B_PRId32 ", %p, %" B_PRIuSIZE ", %p, %p)\n",
316		pipe, data, dataLength, callback, callbackCookie);
317	Object *object = gUSBStack->GetObject(pipe);
318	if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
319		return B_DEV_INVALID_PIPE;
320
321	return ((BulkPipe *)object)->QueueBulk(data, dataLength, callback,
322		callbackCookie);
323}
324
325
326status_t
327queue_bulk_v(usb_pipe pipe, iovec *vector, size_t vectorCount,
328	usb_callback_func callback, void *callbackCookie)
329{
330	TRACE_MODULE("queue_bulk_v(%" B_PRId32 ", %p, %" B_PRIuSIZE " %p, %p)\n",
331		pipe, vector, vectorCount, callback, callbackCookie);
332	Object *object = gUSBStack->GetObject(pipe);
333	if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
334		return B_DEV_INVALID_PIPE;
335
336	return ((BulkPipe *)object)->QueueBulkV(vector, vectorCount, callback,
337		callbackCookie, false);
338}
339
340
341status_t
342queue_bulk_v_physical(usb_pipe pipe, iovec *vector, size_t vectorCount,
343	usb_callback_func callback, void *callbackCookie)
344{
345	TRACE_MODULE("queue_bulk_v_physical(%" B_PRId32 ", %p, %" B_PRIuSIZE
346		", %p, %p)\n", pipe, vector, vectorCount, callback, callbackCookie);
347	Object *object = gUSBStack->GetObject(pipe);
348	if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
349		return B_DEV_INVALID_PIPE;
350
351	return ((BulkPipe *)object)->QueueBulkV(vector, vectorCount, callback,
352		callbackCookie, true);
353}
354
355
356status_t
357queue_isochronous(usb_pipe pipe, void *data, size_t dataLength,
358	usb_iso_packet_descriptor *packetDesc, uint32 packetCount,
359	uint32 *startingFrameNumber, uint32 flags, usb_callback_func callback,
360	void *callbackCookie)
361{
362	TRACE_MODULE("queue_isochronous(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, "
363		"%" B_PRId32 ", %p, 0x%08" B_PRIx32 ", %p, %p)\n",
364		pipe, data, dataLength, packetDesc, packetCount, startingFrameNumber,
365		flags, callback, callbackCookie);
366	Object *object = gUSBStack->GetObject(pipe);
367	if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
368		return B_DEV_INVALID_PIPE;
369
370	return ((IsochronousPipe *)object)->QueueIsochronous(data, dataLength,
371		packetDesc, packetCount, startingFrameNumber, flags, callback,
372		callbackCookie);
373}
374
375
376status_t
377set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets,
378	uint16 maxBufferDurationMS, uint16 sampleSize)
379{
380	TRACE_MODULE("set_pipe_policy(%" B_PRId32 ", %d, %d, %d)\n", pipe,
381		maxQueuedPackets, maxBufferDurationMS, sampleSize);
382	Object *object = gUSBStack->GetObject(pipe);
383	if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
384		return B_DEV_INVALID_PIPE;
385
386	return ((IsochronousPipe *)object)->SetPipePolicy(maxQueuedPackets,
387		maxBufferDurationMS, sampleSize);
388}
389
390
391status_t
392cancel_queued_transfers(usb_pipe pipe)
393{
394	TRACE_MODULE("cancel_queued_transfers(%" B_PRId32 ")\n", pipe);
395	Object *object = gUSBStack->GetObject(pipe);
396	if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
397		return B_DEV_INVALID_PIPE;
398
399	return ((Pipe *)object)->CancelQueuedTransfers(false);
400}
401
402
403status_t
404usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize)
405{
406	TRACE_MODULE("usb_ioctl(%" B_PRIu32 ", %p, %" B_PRIuSIZE ")\n", opcode,
407		buffer, bufferSize);
408
409	switch (opcode) {
410		case 'DNAM': {
411			Object *object = gUSBStack->GetObject(*(usb_id *)buffer);
412			if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
413				return B_BAD_VALUE;
414
415			uint32 index = 0;
416			return ((Device *)object)->BuildDeviceName((char *)buffer, &index,
417				bufferSize, NULL);
418		}
419	}
420
421	return B_DEV_INVALID_IOCTL;
422}
423
424
425status_t
426get_nth_roothub(uint32 index, usb_device *rootHub)
427{
428	if (!rootHub)
429		return B_BAD_VALUE;
430
431	BusManager *busManager = gUSBStack->BusManagerAt(index);
432	if (!busManager)
433		return B_ENTRY_NOT_FOUND;
434
435	Hub *hub = busManager->GetRootHub();
436	if (!hub)
437		return B_NO_INIT;
438
439	*rootHub = hub->USBID();
440	return B_OK;
441}
442
443
444status_t
445get_nth_child(usb_device _hub, uint8 index, usb_device *childDevice)
446{
447	if (!childDevice)
448		return B_BAD_VALUE;
449
450	Object *object = gUSBStack->GetObject(_hub);
451	if (!object || (object->Type() & USB_OBJECT_HUB) == 0)
452		return B_DEV_INVALID_PIPE;
453
454	Hub *hub = (Hub *)object;
455	for (uint8 i = 0; i < 8; i++) {
456		if (hub->ChildAt(i) == NULL)
457			continue;
458
459		if (index-- > 0)
460			continue;
461
462		*childDevice = hub->ChildAt(i)->USBID();
463		return B_OK;
464	}
465
466	return B_ENTRY_NOT_FOUND;
467}
468
469
470status_t
471get_device_parent(usb_device _device, usb_device *parentHub, uint8 *portIndex)
472{
473	if (!parentHub || !portIndex)
474		return B_BAD_VALUE;
475
476	Object *object = gUSBStack->GetObject(_device);
477	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
478		return B_DEV_INVALID_PIPE;
479
480	Object *parent = object->Parent();
481	if (!parent || (parent->Type() & USB_OBJECT_HUB) == 0)
482		return B_ENTRY_NOT_FOUND;
483
484	Hub *hub = (Hub *)parent;
485	for (uint8 i = 0; i < 8; i++) {
486		if (hub->ChildAt(i) == object) {
487			*portIndex = i;
488			*parentHub = hub->USBID();
489			return B_OK;
490		}
491	}
492
493	return B_ERROR;
494}
495
496
497status_t
498reset_port(usb_device _hub, uint8 portIndex)
499{
500	Object *object = gUSBStack->GetObject(_hub);
501	if (!object || (object->Type() & USB_OBJECT_HUB) == 0)
502		return B_DEV_INVALID_PIPE;
503
504	Hub *hub = (Hub *)object;
505	return hub->ResetPort(portIndex);
506}
507
508
509status_t
510disable_port(usb_device _hub, uint8 portIndex)
511{
512	Object *object = gUSBStack->GetObject(_hub);
513	if (!object || (object->Type() & USB_OBJECT_HUB) == 0)
514		return B_DEV_INVALID_PIPE;
515
516	Hub *hub = (Hub *)object;
517	return hub->DisablePort(portIndex);
518}
519
520
521/*
522	This module exports the USB API v3
523*/
524struct usb_module_info gModuleInfoV3 = {
525	// First the bus_manager_info:
526	{
527		{
528			"bus_managers/usb/v3",
529			B_KEEP_LOADED,				// Keep loaded, even if no driver requires it
530			bus_std_ops
531		},
532		NULL							// the rescan function
533	},
534
535	register_driver,					// register_driver
536	install_notify,						// install_notify
537	uninstall_notify,					// uninstall_notify
538	get_device_descriptor,				// get_device_descriptor
539	get_nth_configuration,				// get_nth_configuration
540	get_configuration,					// get_configuration
541	set_configuration,					// set_configuration
542	set_alt_interface,					// set_alt_interface
543	set_feature,						// set_feature
544	clear_feature, 						// clear_feature
545	get_status, 						// get_status
546	get_descriptor,						// get_descriptor
547	send_request,						// send_request
548	queue_interrupt,					// queue_interrupt
549	queue_bulk,							// queue_bulk
550	queue_bulk_v,						// queue_bulk_v
551	queue_isochronous,					// queue_isochronous
552	queue_request,						// queue_request
553	set_pipe_policy,					// set_pipe_policy
554	cancel_queued_transfers,			// cancel_queued_transfers
555	usb_ioctl,							// usb_ioctl
556	get_nth_roothub,					// get_nth_roothub
557	get_nth_child,						// get_nth_child
558	get_device_parent,					// get_device_parent
559	reset_port,							// reset_port
560	disable_port						// disable_port
561	//queue_bulk_v_physical				// queue_bulk_v_physical
562};
563
564
565//
566// #pragma mark -
567//
568
569
570const usb_device_descriptor *
571get_device_descriptor_v2(const void *device)
572{
573	return get_device_descriptor((usb_id)(ssize_t)device);
574}
575
576
577const usb_configuration_info *
578get_nth_configuration_v2(const void *device, uint index)
579{
580	return get_nth_configuration((usb_id)(ssize_t)device, index);
581}
582
583
584const usb_configuration_info *
585get_configuration_v2(const void *device)
586{
587	return get_configuration((usb_id)(ssize_t)device);
588}
589
590
591status_t
592set_configuration_v2(const void *device,
593	const usb_configuration_info *configuration)
594{
595	return set_configuration((usb_id)(ssize_t)device, configuration);
596}
597
598
599status_t
600set_alt_interface_v2(const void *device, const usb_interface_info *interface)
601{
602	return set_alt_interface((usb_id)(ssize_t)device, interface);
603}
604
605
606status_t
607set_feature_v2(const void *object, uint16 selector)
608{
609	return set_feature((usb_id)(ssize_t)object, selector);
610}
611
612
613status_t
614clear_feature_v2(const void *object, uint16 selector)
615{
616	return clear_feature((usb_id)(ssize_t)object, selector);
617}
618
619
620status_t
621get_status_v2(const void *object, uint16 *status)
622{
623	return get_status((usb_id)(ssize_t)object, status);
624}
625
626
627status_t
628get_descriptor_v2(const void *device, uint8 type, uint8 index,
629	uint16 languageID, void *data, size_t dataLength, size_t *actualLength)
630{
631	return get_descriptor((usb_id)(ssize_t)device, type, index, languageID, data,
632		dataLength, actualLength);
633}
634
635
636status_t
637send_request_v2(const void *device, uint8 requestType, uint8 request,
638	uint16 value, uint16 index, uint16 length, void *data,
639	size_t /*dataLength*/, size_t *actualLength)
640{
641	return send_request((usb_id)(ssize_t)device, requestType, request, value, index,
642		length, data, actualLength);
643}
644
645
646status_t
647queue_request_v2(const void *device, uint8 requestType, uint8 request,
648	uint16 value, uint16 index, uint16 length, void *data,
649	size_t /*dataLength*/, usb_callback_func callback, void *callbackCookie)
650{
651	return queue_request((usb_id)(ssize_t)device, requestType, request, value, index,
652		length, data, callback, callbackCookie);
653}
654
655
656status_t
657queue_interrupt_v2(const void *pipe, void *data, size_t dataLength,
658	usb_callback_func callback, void *callbackCookie)
659{
660	return queue_interrupt((usb_id)(ssize_t)pipe, data, dataLength, callback,
661		callbackCookie);
662}
663
664
665status_t
666queue_bulk_v2(const void *pipe, void *data, size_t dataLength,
667	usb_callback_func callback, void *callbackCookie)
668{
669	return queue_bulk((usb_id)(ssize_t)pipe, data, dataLength, callback,
670		callbackCookie);
671}
672
673
674status_t
675queue_isochronous_v2(const void *pipe, void *data, size_t dataLength,
676	rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback,
677	void *callbackCookie)
678{
679	// ToDo: convert rlea to usb_iso_packet_descriptor
680	// ToDo: use a flag to indicate that the callback shall produce a rlea
681	usb_iso_packet_descriptor *packetDesc = NULL;
682	return queue_isochronous((usb_id)(ssize_t)pipe, data, dataLength, packetDesc, 0,
683		NULL, 0, callback, callbackCookie);
684}
685
686
687status_t
688set_pipe_policy_v2(const void *pipe, uint8 maxQueuedPackets,
689	uint16 maxBufferDurationMS, uint16 sampleSize)
690{
691	return set_pipe_policy((usb_id)(ssize_t)pipe, maxQueuedPackets, maxBufferDurationMS,
692		sampleSize);
693}
694
695
696status_t
697cancel_queued_transfers_v2(const void *pipe)
698{
699	return cancel_queued_transfers((usb_id)(ssize_t)pipe);
700}
701
702
703struct usb_module_info_v2 {
704	bus_manager_info				binfo;
705	status_t						(*register_driver)(const char *, const usb_support_descriptor *, size_t, const char *);
706	status_t						(*install_notify)(const char *, const usb_notify_hooks *);
707	status_t						(*uninstall_notify)(const char *);
708	const usb_device_descriptor		*(*get_device_descriptor)(const void *);
709	const usb_configuration_info	*(*get_nth_configuration)(const void *, uint);
710	const usb_configuration_info	*(*get_configuration)(const void *);
711	status_t						(*set_configuration)(const void *, const usb_configuration_info *);
712	status_t						(*set_alt_interface)(const void *, const usb_interface_info *);
713	status_t						(*set_feature)(const void *, uint16);
714	status_t						(*clear_feature)(const void *, uint16);
715	status_t						(*get_status)(const void *, uint16 *);
716	status_t						(*get_descriptor)(const void *, uint8, uint8, uint16, void *, size_t, size_t *);
717	status_t						(*send_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, size_t *);
718	status_t						(*queue_interrupt)(const void *, void *, size_t, usb_callback_func, void *);
719	status_t						(*queue_bulk)(const void *, void *, size_t, usb_callback_func, void *);
720	status_t						(*queue_isochronous)(const void *, void *, size_t, rlea *, uint16, usb_callback_func, void *);
721	status_t						(*queue_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, usb_callback_func, void *);
722	status_t						(*set_pipe_policy)(const void *, uint8, uint16, uint16);
723	status_t						(*cancel_queued_transfers)(const void *);
724	status_t						(*usb_ioctl)(uint32 opcode, void *,size_t);
725};
726
727
728/*
729	This module exports the USB API v2
730*/
731struct usb_module_info_v2 gModuleInfoV2 = {
732	// First the bus_manager_info:
733	{
734		{
735			"bus_managers/usb/v2",
736			B_KEEP_LOADED,				// Keep loaded, even if no driver requires it
737			bus_std_ops
738		},
739		NULL							// the rescan function
740	},
741
742	register_driver,					// register_driver
743	install_notify,						// install_notify
744	uninstall_notify,					// uninstall_notify
745	get_device_descriptor_v2,			// get_device_descriptor
746	get_nth_configuration_v2,			// get_nth_configuration
747	get_configuration_v2,				// get_configuration
748	set_configuration_v2,				// set_configuration
749	set_alt_interface_v2,				// set_alt_interface
750	set_feature_v2,						// set_feature
751	clear_feature_v2,					// clear_feature
752	get_status_v2, 						// get_status
753	get_descriptor_v2,					// get_descriptor
754	send_request_v2,					// send_request
755	queue_interrupt_v2,					// queue_interrupt
756	queue_bulk_v2,						// queue_bulk
757	queue_isochronous_v2,				// queue_isochronous
758	queue_request_v2,					// queue_request
759	set_pipe_policy_v2,					// set_pipe_policy
760	cancel_queued_transfers_v2,			// cancel_queued_transfers
761	usb_ioctl							// usb_ioctl
762};
763
764
765//
766// #pragma mark -
767//
768
769
770module_info *modules[] = {
771	(module_info *)&gModuleInfoV2,
772	(module_info *)&gModuleInfoV3,
773	NULL
774};
775