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;
18
19
20/*!	The function is an evil hack to allow <tt> <kdebug>usb_keyboard </tt> to
21	execute transfers.
22	When invoked the first time, a new transfer is started, each time the
23	function is called afterwards, it is checked whether the transfer is already
24	completed. If called with argv[1] == "cancel" the function cancels a
25	possibly pending transfer.
26*/
27static status_t
28debug_run_transfer(Pipe *pipe, uint8 *data, size_t dataLength,
29	usb_request_data *requestData, bool cancel)
30{
31	static uint8 transferBuffer[sizeof(Transfer)]
32		__attribute__((aligned(16)));
33	static Transfer *transfer = NULL;
34
35	BusManager *bus = pipe->GetBusManager();
36
37	if (cancel) {
38		if (transfer != NULL) {
39			bus->CancelDebugTransfer(transfer);
40			transfer = NULL;
41		}
42
43		return B_OK;
44	}
45
46	if (transfer != NULL) {
47		status_t error = bus->CheckDebugTransfer(transfer);
48		if (error != B_DEV_PENDING)
49			transfer = NULL;
50
51		return error;
52	}
53
54	transfer = new(transferBuffer) Transfer(pipe);
55	transfer->SetData(data, dataLength);
56	transfer->SetRequestData(requestData);
57
58	status_t error = bus->StartDebugTransfer(transfer);
59	if (error != B_OK) {
60		transfer = NULL;
61		return error;
62	}
63
64	return B_DEV_PENDING;
65}
66
67
68static int
69debug_get_pipe_for_id(int argc, char **argv)
70{
71	if (gUSBStack == NULL)
72		return 1;
73
74	if (!is_debug_variable_defined("_usbPipeID"))
75		return 2;
76
77	uint64 id = get_debug_variable("_usbPipeID", 0);
78	Object *object = gUSBStack->GetObjectNoLock((usb_id)id);
79	if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
80		return 3;
81
82	set_debug_variable("_usbPipe", (uint64)object);
83	return 0;
84}
85
86
87static int
88debug_process_transfer(int argc, char **argv)
89{
90	Pipe *pipe = (Pipe *)get_debug_variable("_usbPipe", 0);
91	if (pipe == NULL)
92		return B_BAD_VALUE;
93
94	uint8 *data = (uint8 *)get_debug_variable("_usbTransferData", 0);
95	size_t length = (size_t)get_debug_variable("_usbTransferLength", 0);
96	usb_request_data *requestData
97		= (usb_request_data *)get_debug_variable("_usbRequestData", 0);
98
99	return debug_run_transfer(pipe, data, length, requestData,
100		argc > 1 && strcmp(argv[1], "cancel") == 0);
101}
102
103
104static int
105debug_clear_stall(int argc, char *argv[])
106{
107	Pipe *pipe = (Pipe *)get_debug_variable("_usbPipe", 0);
108	if (pipe == NULL)
109		return B_BAD_VALUE;
110
111	static usb_request_data requestData;
112
113	requestData.RequestType = USB_REQTYPE_STANDARD | USB_REQTYPE_ENDPOINT_OUT;
114	requestData.Request = USB_REQUEST_CLEAR_FEATURE;
115	requestData.Value = USB_FEATURE_ENDPOINT_HALT;
116	requestData.Index = pipe->EndpointAddress()
117		| (pipe->Direction() == Pipe::In ? USB_ENDPOINT_ADDR_DIR_IN
118			: USB_ENDPOINT_ADDR_DIR_OUT);
119	requestData.Length = 0;
120
121	Pipe *parentPipe = ((Device *)pipe->Parent())->DefaultPipe();
122	for (int tries = 0; tries < 100; tries++) {
123		status_t result
124			= debug_run_transfer(parentPipe, NULL, 0, &requestData, false);
125
126		if (result == B_DEV_PENDING)
127			continue;
128
129		if (result == B_OK) {
130			// clearing a stalled condition resets the data toggle
131			pipe->SetDataToggle(false);
132			return B_OK;
133		}
134
135		return result;
136	}
137
138	return B_TIMED_OUT;
139}
140
141
142static int32
143bus_std_ops(int32 op, ...)
144{
145	switch (op) {
146		case B_MODULE_INIT: {
147			TRACE_MODULE("init\n");
148			if (gUSBStack)
149				return B_OK;
150
151#ifdef TRACE_USB
152			set_dprintf_enabled(true);
153#endif
154			Stack *stack = new(std::nothrow) Stack();
155			TRACE_MODULE("usb_module: stack created %p\n", stack);
156			if (!stack)
157				return B_NO_MEMORY;
158
159			if (stack->InitCheck() != B_OK) {
160				delete stack;
161				return ENODEV;
162			}
163
164			gUSBStack = stack;
165
166			add_debugger_command("get_usb_pipe_for_id",
167				&debug_get_pipe_for_id,
168				"Sets _usbPipe by resolving _usbPipeID");
169			add_debugger_command("usb_process_transfer",
170				&debug_process_transfer,
171				"Transfers _usbTransferData with _usbTransferLength"
172				" (and/or _usbRequestData) to pipe _usbPipe");
173			add_debugger_command("usb_clear_stall",
174				&debug_clear_stall,
175				"Tries to issue a clear feature request for the endpoint halt"
176				" feature on pipe _usbPipe");
177			break;
178		}
179
180		case B_MODULE_UNINIT:
181			TRACE_MODULE("uninit\n");
182			delete gUSBStack;
183			gUSBStack = NULL;
184
185			remove_debugger_command("get_usb_pipe_for_id",
186				&debug_get_pipe_for_id);
187			break;
188
189		default:
190			return EINVAL;
191	}
192
193	return B_OK;
194}
195
196
197status_t
198register_driver(const char *driverName,
199	const usb_support_descriptor *descriptors,
200	size_t count, const char *optionalRepublishDriverName)
201{
202	return gUSBStack->RegisterDriver(driverName, descriptors, count,
203		optionalRepublishDriverName);
204}
205
206
207status_t
208install_notify(const char *driverName, const usb_notify_hooks *hooks)
209{
210	return gUSBStack->InstallNotify(driverName, hooks);
211}
212
213
214status_t
215uninstall_notify(const char *driverName)
216{
217	return gUSBStack->UninstallNotify(driverName);
218}
219
220
221const usb_device_descriptor *
222get_device_descriptor(usb_device dev)
223{
224	TRACE_MODULE("get_device_descriptor(%" B_PRId32 ")\n", dev);
225	Object *object = gUSBStack->GetObject(dev);
226	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
227		return NULL;
228	Device *device = (Device *)object;
229	if (device->InitCheck() != B_OK)
230		return NULL;
231
232	return device->DeviceDescriptor();
233}
234
235
236const usb_configuration_info *
237get_nth_configuration(usb_device dev, uint32 index)
238{
239	TRACE_MODULE("get_nth_configuration(%" B_PRId32 ", %" B_PRIu32 ")\n",
240		dev, index);
241	Object *object = gUSBStack->GetObject(dev);
242	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
243		return NULL;
244	Device *device = (Device *)object;
245	if (device->InitCheck() != B_OK)
246		return NULL;
247
248	return device->ConfigurationAt((int32)index);
249}
250
251
252const usb_configuration_info *
253get_configuration(usb_device dev)
254{
255	TRACE_MODULE("get_configuration(%" B_PRId32 ")\n", dev);
256	Object *object = gUSBStack->GetObject(dev);
257	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
258		return NULL;
259	Device *device = (Device *)object;
260	if (device->InitCheck() != B_OK)
261		return NULL;
262
263	return device->Configuration();
264}
265
266
267status_t
268set_configuration(usb_device dev,
269	const usb_configuration_info *configuration)
270{
271	TRACE_MODULE("set_configuration(%" B_PRId32 ", %p)\n", dev,
272		configuration);
273	Object *object = gUSBStack->GetObject(dev);
274	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
275		return B_DEV_INVALID_PIPE;
276	Device *device = (Device *)object;
277	if (device->InitCheck() != B_OK)
278		return B_NO_INIT;
279
280	return device->SetConfiguration(configuration);
281}
282
283
284status_t
285set_alt_interface(usb_device dev, const usb_interface_info *interface)
286{
287	TRACE_MODULE("set_alt_interface(%" B_PRId32 ", %p)\n", dev, interface);
288	Object *object = gUSBStack->GetObject(dev);
289	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
290		return B_DEV_INVALID_PIPE;
291	Device *device = (Device *)object;
292	if (device->InitCheck() != B_OK)
293		return B_NO_INIT;
294
295	return device->SetAltInterface(interface);
296}
297
298
299status_t
300set_feature(usb_id handle, uint16 selector)
301{
302	TRACE_MODULE("set_feature(%" B_PRId32 ", %d)\n", handle, selector);
303	Object *object = gUSBStack->GetObject(handle);
304	if (!object)
305		return B_DEV_INVALID_PIPE;
306
307	return object->SetFeature(selector);
308}
309
310
311status_t
312clear_feature(usb_id handle, uint16 selector)
313{
314	TRACE_MODULE("clear_feature(%" B_PRId32 ", %d)\n", handle, selector);
315	Object *object = gUSBStack->GetObject(handle);
316	if (!object)
317		return B_DEV_INVALID_PIPE;
318
319	return object->ClearFeature(selector);
320}
321
322
323status_t
324get_status(usb_id handle, uint16 *status)
325{
326	TRACE_MODULE("get_status(%" B_PRId32 ", %p)\n", handle, status);
327	if (!status)
328		return B_BAD_VALUE;
329
330	Object *object = gUSBStack->GetObject(handle);
331	if (!object)
332		return B_DEV_INVALID_PIPE;
333
334	return object->GetStatus(status);
335}
336
337
338status_t
339get_descriptor(usb_device dev, uint8 type, uint8 index, uint16 languageID,
340	void *data, size_t dataLength, size_t *actualLength)
341{
342	TRACE_MODULE("get_descriptor(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, %p, "
343		"%" B_PRIuSIZE ", %p)\n",
344		dev, type, index, languageID, data, dataLength, actualLength);
345	Object *object = gUSBStack->GetObject(dev);
346	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
347		return B_DEV_INVALID_PIPE;
348	Device *device = (Device *)object;
349	if (device->InitCheck() != B_OK)
350		return B_NO_INIT;
351
352	return device->GetDescriptor(type, index, languageID,
353		data, dataLength, actualLength);
354}
355
356
357status_t
358send_request(usb_device dev, uint8 requestType, uint8 request,
359	uint16 value, uint16 index, uint16 length, void *data, size_t *actualLength)
360{
361	TRACE_MODULE("send_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x, "
362		"%d, %p, %p)\n", dev, requestType, request, value, index, length,
363		data, actualLength);
364	Object *object = gUSBStack->GetObject(dev);
365	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
366		return B_DEV_INVALID_PIPE;
367	Device *device = (Device *)object;
368	if (device->InitCheck() != B_OK)
369		return B_NO_INIT;
370
371	return device->DefaultPipe()->SendRequest(requestType, request,
372		value, index, length, data, length, actualLength);
373}
374
375
376status_t
377queue_request(usb_device dev, uint8 requestType, uint8 request,
378	uint16 value, uint16 index, uint16 length, void *data,
379	usb_callback_func callback, void *callbackCookie)
380{
381	TRACE_MODULE("queue_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x,"
382		" %u, %p, %p, %p)\n", dev, requestType, request, value, index,
383		length, data, callback,	callbackCookie);
384	Object *object = gUSBStack->GetObject(dev);
385	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
386		return B_DEV_INVALID_PIPE;
387	Device *device = (Device *)object;
388	if (device->InitCheck() != B_OK)
389		return B_NO_INIT;
390
391	return device->DefaultPipe()->QueueRequest(requestType,
392		request, value, index, length, data, length, callback, callbackCookie);
393}
394
395
396status_t
397queue_interrupt(usb_pipe pipe, void *data, size_t dataLength,
398	usb_callback_func callback, void *callbackCookie)
399{
400	TRACE_MODULE("queue_interrupt(%" B_PRId32 ", %p, %ld, %p, %p)\n",
401		pipe, data, dataLength, callback, callbackCookie);
402	Object *object = gUSBStack->GetObject(pipe);
403	if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0)
404		return B_DEV_INVALID_PIPE;
405
406	return ((InterruptPipe *)object)->QueueInterrupt(data, dataLength, callback,
407		callbackCookie);
408}
409
410
411status_t
412queue_bulk(usb_pipe pipe, void *data, size_t dataLength,
413	usb_callback_func callback, void *callbackCookie)
414{
415	TRACE_MODULE("queue_bulk(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, %p)\n",
416		pipe, data, dataLength, callback, callbackCookie);
417	Object *object = gUSBStack->GetObject(pipe);
418	if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
419		return B_DEV_INVALID_PIPE;
420
421	return ((BulkPipe *)object)->QueueBulk(data, dataLength, callback,
422		callbackCookie);
423}
424
425
426status_t
427queue_bulk_v(usb_pipe pipe, iovec *vector, size_t vectorCount,
428	usb_callback_func callback, void *callbackCookie)
429{
430	TRACE_MODULE("queue_bulk_v(%" B_PRId32 ", %p, %" B_PRIuSIZE " %p, %p)\n",
431		pipe, vector, vectorCount, callback, callbackCookie);
432	Object *object = gUSBStack->GetObject(pipe);
433	if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
434		return B_DEV_INVALID_PIPE;
435
436	return ((BulkPipe *)object)->QueueBulkV(vector, vectorCount, callback,
437		callbackCookie, false);
438}
439
440
441status_t
442queue_bulk_v_physical(usb_pipe pipe, iovec *vector, size_t vectorCount,
443	usb_callback_func callback, void *callbackCookie)
444{
445	TRACE_MODULE("queue_bulk_v_physical(%" B_PRId32 ", %p, %" B_PRIuSIZE
446		", %p, %p)\n", pipe, vector, vectorCount, callback, callbackCookie);
447	Object *object = gUSBStack->GetObject(pipe);
448	if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
449		return B_DEV_INVALID_PIPE;
450
451	return ((BulkPipe *)object)->QueueBulkV(vector, vectorCount, callback,
452		callbackCookie, true);
453}
454
455
456status_t
457queue_isochronous(usb_pipe pipe, void *data, size_t dataLength,
458	usb_iso_packet_descriptor *packetDesc, uint32 packetCount,
459	uint32 *startingFrameNumber, uint32 flags, usb_callback_func callback,
460	void *callbackCookie)
461{
462	TRACE_MODULE("queue_isochronous(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, "
463		"%" B_PRId32 ", %p, 0x%08" B_PRIx32 ", %p, %p)\n",
464		pipe, data, dataLength, packetDesc, packetCount, startingFrameNumber,
465		flags, callback, callbackCookie);
466	Object *object = gUSBStack->GetObject(pipe);
467	if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
468		return B_DEV_INVALID_PIPE;
469
470	return ((IsochronousPipe *)object)->QueueIsochronous(data, dataLength,
471		packetDesc, packetCount, startingFrameNumber, flags, callback,
472		callbackCookie);
473}
474
475
476status_t
477set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets,
478	uint16 maxBufferDurationMS, uint16 sampleSize)
479{
480	TRACE_MODULE("set_pipe_policy(%" B_PRId32 ", %d, %d, %d)\n", pipe,
481		maxQueuedPackets, maxBufferDurationMS, sampleSize);
482	Object *object = gUSBStack->GetObject(pipe);
483	if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
484		return B_DEV_INVALID_PIPE;
485
486	return ((IsochronousPipe *)object)->SetPipePolicy(maxQueuedPackets,
487		maxBufferDurationMS, sampleSize);
488}
489
490
491status_t
492cancel_queued_transfers(usb_pipe pipe)
493{
494	TRACE_MODULE("cancel_queued_transfers(%" B_PRId32 ")\n", pipe);
495	Object *object = gUSBStack->GetObject(pipe);
496	if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
497		return B_DEV_INVALID_PIPE;
498
499	return ((Pipe *)object)->CancelQueuedTransfers(false);
500}
501
502
503status_t
504usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize)
505{
506	TRACE_MODULE("usb_ioctl(%" B_PRIu32 ", %p, %" B_PRIuSIZE ")\n", opcode,
507		buffer, bufferSize);
508
509	switch (opcode) {
510		case 'DNAM': {
511			Object *object = gUSBStack->GetObject(*(usb_id *)buffer);
512			if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
513				return B_BAD_VALUE;
514			Device *device = (Device *)object;
515			if (device->InitCheck() != B_OK)
516				return B_NO_INIT;
517
518			uint32 index = 0;
519			return device->BuildDeviceName((char *)buffer, &index,
520				bufferSize, NULL);
521		}
522	}
523
524	return B_DEV_INVALID_IOCTL;
525}
526
527
528status_t
529get_nth_roothub(uint32 index, usb_device *rootHub)
530{
531	if (!rootHub)
532		return B_BAD_VALUE;
533
534	BusManager *busManager = gUSBStack->BusManagerAt(index);
535	if (!busManager)
536		return B_ENTRY_NOT_FOUND;
537
538	Hub *hub = busManager->GetRootHub();
539	if (!hub)
540		return B_NO_INIT;
541
542	*rootHub = hub->USBID();
543	return B_OK;
544}
545
546
547status_t
548get_nth_child(usb_device _hub, uint8 index, usb_device *childDevice)
549{
550	if (!childDevice)
551		return B_BAD_VALUE;
552
553	Object *object = gUSBStack->GetObject(_hub);
554	if (!object || (object->Type() & USB_OBJECT_HUB) == 0)
555		return B_DEV_INVALID_PIPE;
556
557	Hub *hub = (Hub *)object;
558	for (uint8 i = 0; i < 8; i++) {
559		if (hub->ChildAt(i) == NULL)
560			continue;
561
562		if (index-- > 0)
563			continue;
564
565		*childDevice = hub->ChildAt(i)->USBID();
566		return B_OK;
567	}
568
569	return B_ENTRY_NOT_FOUND;
570}
571
572
573status_t
574get_device_parent(usb_device _device, usb_device *parentHub, uint8 *portIndex)
575{
576	if (!parentHub || !portIndex)
577		return B_BAD_VALUE;
578
579	Object *object = gUSBStack->GetObject(_device);
580	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
581		return B_DEV_INVALID_PIPE;
582
583	Object *parent = object->Parent();
584	if (!parent || (parent->Type() & USB_OBJECT_HUB) == 0)
585		return B_ENTRY_NOT_FOUND;
586
587	Hub *hub = (Hub *)parent;
588	for (uint8 i = 0; i < 8; i++) {
589		if (hub->ChildAt(i) == object) {
590			*portIndex = i;
591			*parentHub = hub->USBID();
592			return B_OK;
593		}
594	}
595
596	return B_ERROR;
597}
598
599
600status_t
601reset_port(usb_device _hub, uint8 portIndex)
602{
603	Object *object = gUSBStack->GetObject(_hub);
604	if (!object || (object->Type() & USB_OBJECT_HUB) == 0)
605		return B_DEV_INVALID_PIPE;
606
607	Hub *hub = (Hub *)object;
608	return hub->ResetPort(portIndex);
609}
610
611
612status_t
613disable_port(usb_device _hub, uint8 portIndex)
614{
615	Object *object = gUSBStack->GetObject(_hub);
616	if (!object || (object->Type() & USB_OBJECT_HUB) == 0)
617		return B_DEV_INVALID_PIPE;
618
619	Hub *hub = (Hub *)object;
620	return hub->DisablePort(portIndex);
621}
622
623
624/*
625	This module exports the USB API v3
626*/
627struct usb_module_info gModuleInfoV3 = {
628	// First the bus_manager_info:
629	{
630		{
631			"bus_managers/usb/v3",
632			B_KEEP_LOADED,				// Keep loaded, even if no driver requires it
633			bus_std_ops
634		},
635		NULL							// the rescan function
636	},
637
638	register_driver,					// register_driver
639	install_notify,						// install_notify
640	uninstall_notify,					// uninstall_notify
641	get_device_descriptor,				// get_device_descriptor
642	get_nth_configuration,				// get_nth_configuration
643	get_configuration,					// get_configuration
644	set_configuration,					// set_configuration
645	set_alt_interface,					// set_alt_interface
646	set_feature,						// set_feature
647	clear_feature, 						// clear_feature
648	get_status, 						// get_status
649	get_descriptor,						// get_descriptor
650	send_request,						// send_request
651	queue_interrupt,					// queue_interrupt
652	queue_bulk,							// queue_bulk
653	queue_bulk_v,						// queue_bulk_v
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	usb_ioctl,							// usb_ioctl
659	get_nth_roothub,					// get_nth_roothub
660	get_nth_child,						// get_nth_child
661	get_device_parent,					// get_device_parent
662	reset_port,							// reset_port
663	disable_port						// disable_port
664	//queue_bulk_v_physical				// queue_bulk_v_physical
665};
666
667
668//
669// #pragma mark -
670//
671
672
673const usb_device_descriptor *
674get_device_descriptor_v2(const void *device)
675{
676	return get_device_descriptor((usb_id)(ssize_t)device);
677}
678
679
680const usb_configuration_info *
681get_nth_configuration_v2(const void *device, uint index)
682{
683	return get_nth_configuration((usb_id)(ssize_t)device, index);
684}
685
686
687const usb_configuration_info *
688get_configuration_v2(const void *device)
689{
690	return get_configuration((usb_id)(ssize_t)device);
691}
692
693
694status_t
695set_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
702status_t
703set_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
709status_t
710set_feature_v2(const void *object, uint16 selector)
711{
712	return set_feature((usb_id)(ssize_t)object, selector);
713}
714
715
716status_t
717clear_feature_v2(const void *object, uint16 selector)
718{
719	return clear_feature((usb_id)(ssize_t)object, selector);
720}
721
722
723status_t
724get_status_v2(const void *object, uint16 *status)
725{
726	return get_status((usb_id)(ssize_t)object, status);
727}
728
729
730status_t
731get_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
739status_t
740send_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
749status_t
750queue_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
759status_t
760queue_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
768status_t
769queue_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
777status_t
778queue_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
790status_t
791set_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
799status_t
800cancel_queued_transfers_v2(const void *pipe)
801{
802	return cancel_queued_transfers((usb_id)(ssize_t)pipe);
803}
804
805
806struct 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*/
834struct 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
873module_info *modules[] = {
874	(module_info *)&gModuleInfoV2,
875	(module_info *)&gModuleInfoV3,
876	NULL
877};
878