xref: /haiku/src/add-ons/kernel/bus_managers/usb/usb.cpp (revision 13508e8bd034aac27c2e3271aefa04e255520d99)
196da8285SMichael Lotz /*
296da8285SMichael Lotz  * Copyright 2003-2006, Haiku Inc. All rights reserved.
396da8285SMichael Lotz  * Distributed under the terms of the MIT License.
496da8285SMichael Lotz  *
596da8285SMichael Lotz  * Authors:
65b0ec61fSMichael Lotz  *		Michael Lotz <mmlr@mlotz.ch>
796da8285SMichael Lotz  *		Niels S. Reedijk
896da8285SMichael Lotz  */
91501c2bfSNiels Sascha Reedijk 
101501c2bfSNiels Sascha Reedijk #include <util/kernel_cpp.h>
111501c2bfSNiels Sascha Reedijk #include "usb_p.h"
121bad4a4eSMichael Lotz #include <USB_rle.h>
131501c2bfSNiels Sascha Reedijk 
1496da8285SMichael Lotz 
15b8c6a851SMichael Lotz Stack *gUSBStack = NULL;
16b8c6a851SMichael Lotz 
17b8c6a851SMichael Lotz 
181501c2bfSNiels Sascha Reedijk static int32
191501c2bfSNiels Sascha Reedijk bus_std_ops(int32 op, ...)
201501c2bfSNiels Sascha Reedijk {
211501c2bfSNiels Sascha Reedijk 	switch (op) {
2296da8285SMichael Lotz 		case B_MODULE_INIT: {
235b0ec61fSMichael Lotz 			if (gUSBStack)
245b0ec61fSMichael Lotz 				return B_OK;
255b0ec61fSMichael Lotz 
26a94a8358SMichael Lotz 			void *address = NULL;
27a94a8358SMichael Lotz 			area_id shared = find_area("shared usb stack");
28a94a8358SMichael Lotz 			if (shared >= B_OK && clone_area("usb stack clone", &address,
29a94a8358SMichael Lotz 				B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, shared) >= B_OK) {
30a94a8358SMichael Lotz 				gUSBStack = *((Stack **)address);
31a94a8358SMichael Lotz 				return B_OK;
32a94a8358SMichael Lotz 			}
33a94a8358SMichael Lotz 
3496da8285SMichael Lotz #ifdef TRACE_USB
351a2e81b5SNiels Sascha Reedijk 			set_dprintf_enabled(true);
361a2e81b5SNiels Sascha Reedijk 			load_driver_symbols("usb");
37b8c6a851SMichael Lotz 			TRACE(("usb_module: init\n"));
3802ce23a1SMichael Lotz #endif
39b8c6a851SMichael Lotz 			Stack *stack = new(std::nothrow) Stack();
40b8c6a851SMichael Lotz 			if (!stack)
41b8c6a851SMichael Lotz 				return B_NO_MEMORY;
42b8c6a851SMichael Lotz 
4396da8285SMichael Lotz 			if (stack->InitCheck() != B_OK) {
441a2e81b5SNiels Sascha Reedijk 				delete stack;
451501c2bfSNiels Sascha Reedijk 				return ENODEV;
461501c2bfSNiels Sascha Reedijk 			}
4796da8285SMichael Lotz 
48b8c6a851SMichael Lotz 			gUSBStack = stack;
49a94a8358SMichael Lotz 			shared = create_area("shared usb stack", &address,
50a94a8358SMichael Lotz 				B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, B_NO_LOCK,
51a94a8358SMichael Lotz 				B_KERNEL_WRITE_AREA);
52a94a8358SMichael Lotz 			if (shared >= B_OK) {
53a94a8358SMichael Lotz 				*((Stack **)address) = gUSBStack;
54a94a8358SMichael Lotz 				return B_OK;
55a94a8358SMichael Lotz 			}
561501c2bfSNiels Sascha Reedijk 			break;
5796da8285SMichael Lotz 		}
5896da8285SMichael Lotz 
591501c2bfSNiels Sascha Reedijk 		case B_MODULE_UNINIT:
60c4cce727SMichael Lotz 			TRACE(("usb_module: uninit\n"));
61b8c6a851SMichael Lotz 			delete gUSBStack;
62b8c6a851SMichael Lotz 			gUSBStack = NULL;
631501c2bfSNiels Sascha Reedijk 			break;
6496da8285SMichael Lotz 
651501c2bfSNiels Sascha Reedijk 		default:
661501c2bfSNiels Sascha Reedijk 			return EINVAL;
671501c2bfSNiels Sascha Reedijk 	}
6896da8285SMichael Lotz 
691501c2bfSNiels Sascha Reedijk 	return B_OK;
701501c2bfSNiels Sascha Reedijk }
711501c2bfSNiels Sascha Reedijk 
721501c2bfSNiels Sascha Reedijk 
73b8c6a851SMichael Lotz status_t
74b8c6a851SMichael Lotz register_driver(const char *driverName,
75b8c6a851SMichael Lotz 	const usb_support_descriptor *descriptors,
76b8c6a851SMichael Lotz 	size_t count, const char *optionalRepublishDriverName)
77b8c6a851SMichael Lotz {
78b8c6a851SMichael Lotz 	return gUSBStack->RegisterDriver(driverName, descriptors, count,
79b8c6a851SMichael Lotz 		optionalRepublishDriverName);
80b8c6a851SMichael Lotz }
81b8c6a851SMichael Lotz 
82b8c6a851SMichael Lotz 
83b8c6a851SMichael Lotz status_t
84b8c6a851SMichael Lotz install_notify(const char *driverName, const usb_notify_hooks *hooks)
85b8c6a851SMichael Lotz {
86b8c6a851SMichael Lotz 	return gUSBStack->InstallNotify(driverName, hooks);
87b8c6a851SMichael Lotz }
88b8c6a851SMichael Lotz 
89b8c6a851SMichael Lotz 
90b8c6a851SMichael Lotz status_t
91b8c6a851SMichael Lotz uninstall_notify(const char *driverName)
92b8c6a851SMichael Lotz {
93b8c6a851SMichael Lotz 	return gUSBStack->UninstallNotify(driverName);
94b8c6a851SMichael Lotz }
95b8c6a851SMichael Lotz 
96b8c6a851SMichael Lotz 
97b8c6a851SMichael Lotz const usb_device_descriptor *
985b0ec61fSMichael Lotz get_device_descriptor(usb_device device)
99b8c6a851SMichael Lotz {
100c4cce727SMichael Lotz 	TRACE(("usb_module: get_device_descriptor(%ld)\n", device));
1015b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(device);
1025b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
103b8c6a851SMichael Lotz 		return NULL;
104b8c6a851SMichael Lotz 
1055b0ec61fSMichael Lotz 	return ((Device *)object)->DeviceDescriptor();
106b8c6a851SMichael Lotz }
107b8c6a851SMichael Lotz 
108b8c6a851SMichael Lotz 
109b8c6a851SMichael Lotz const usb_configuration_info *
1105b0ec61fSMichael Lotz get_nth_configuration(usb_device device, uint index)
111b8c6a851SMichael Lotz {
112c4cce727SMichael Lotz 	TRACE(("usb_module: get_nth_configuration(%ld, %d)\n", device, index));
1135b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(device);
1145b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
115b8c6a851SMichael Lotz 		return NULL;
116b8c6a851SMichael Lotz 
1175b0ec61fSMichael Lotz 	return ((Device *)object)->ConfigurationAt((int32)index);
118b8c6a851SMichael Lotz }
119b8c6a851SMichael Lotz 
120b8c6a851SMichael Lotz 
121b8c6a851SMichael Lotz const usb_configuration_info *
1225b0ec61fSMichael Lotz get_configuration(usb_device device)
123b8c6a851SMichael Lotz {
124c4cce727SMichael Lotz 	TRACE(("usb_module: get_configuration(%ld)\n", device));
1255b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(device);
1265b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
127b8c6a851SMichael Lotz 		return NULL;
128b8c6a851SMichael Lotz 
1295b0ec61fSMichael Lotz 	return ((Device *)object)->Configuration();
130b8c6a851SMichael Lotz }
131b8c6a851SMichael Lotz 
132b8c6a851SMichael Lotz 
133b8c6a851SMichael Lotz status_t
1345b0ec61fSMichael Lotz set_configuration(usb_device device,
135b8c6a851SMichael Lotz 	const usb_configuration_info *configuration)
136b8c6a851SMichael Lotz {
137c4cce727SMichael Lotz 	TRACE(("usb_module: set_configuration(%ld, 0x%08lx)\n", device, configuration));
1385b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(device);
1395b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
14017f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
141b8c6a851SMichael Lotz 
1425b0ec61fSMichael Lotz 	return ((Device *)object)->SetConfiguration(configuration);
143b8c6a851SMichael Lotz }
144b8c6a851SMichael Lotz 
145b8c6a851SMichael Lotz 
146b8c6a851SMichael Lotz status_t
1475b0ec61fSMichael Lotz set_alt_interface(usb_device device, const usb_interface_info *interface)
148b8c6a851SMichael Lotz {
149c4cce727SMichael Lotz 	TRACE(("usb_module: set_alt_interface(%ld, 0x%08lx)\n", device, interface));
1505b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(device);
1515b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
15217f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
1535b0ec61fSMichael Lotz 
154b8c6a851SMichael Lotz 	return B_ERROR;
155b8c6a851SMichael Lotz }
156b8c6a851SMichael Lotz 
157b8c6a851SMichael Lotz 
158b8c6a851SMichael Lotz status_t
1595b0ec61fSMichael Lotz set_feature(usb_id handle, uint16 selector)
160b8c6a851SMichael Lotz {
161c4cce727SMichael Lotz 	TRACE(("usb_module: set_feature(%ld, %d)\n", handle, selector));
1625b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(handle);
1638fedfdfcSMichael Lotz 	if (!object)
16417f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
165b8c6a851SMichael Lotz 
1668fedfdfcSMichael Lotz 	return object->SetFeature(selector);
167b8c6a851SMichael Lotz }
168b8c6a851SMichael Lotz 
169b8c6a851SMichael Lotz 
170b8c6a851SMichael Lotz status_t
1715b0ec61fSMichael Lotz clear_feature(usb_id handle, uint16 selector)
172b8c6a851SMichael Lotz {
173c4cce727SMichael Lotz 	TRACE(("usb_module: clear_feature(%ld, %d)\n", handle, selector));
1745b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(handle);
1758fedfdfcSMichael Lotz 	if (!object)
17617f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
177b8c6a851SMichael Lotz 
1788fedfdfcSMichael Lotz 	return object->ClearFeature(selector);
179b8c6a851SMichael Lotz }
180b8c6a851SMichael Lotz 
181b8c6a851SMichael Lotz 
182b8c6a851SMichael Lotz status_t
1835b0ec61fSMichael Lotz get_status(usb_id handle, uint16 *status)
184b8c6a851SMichael Lotz {
185c4cce727SMichael Lotz 	TRACE(("usb_module: get_status(%ld, 0x%08lx)\n", handle, status));
1865b0ec61fSMichael Lotz 	if (!status)
1875b0ec61fSMichael Lotz 		return B_BAD_VALUE;
1885b0ec61fSMichael Lotz 
1895b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(handle);
1908fedfdfcSMichael Lotz 	if (!object)
19117f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
192b8c6a851SMichael Lotz 
1938fedfdfcSMichael Lotz 	return object->GetStatus(status);
194b8c6a851SMichael Lotz }
195b8c6a851SMichael Lotz 
196b8c6a851SMichael Lotz 
197b8c6a851SMichael Lotz status_t
1985b0ec61fSMichael Lotz get_descriptor(usb_device device, uint8 type, uint8 index, uint16 languageID,
1995b0ec61fSMichael Lotz 	void *data, size_t dataLength, size_t *actualLength)
200b8c6a851SMichael Lotz {
201c4cce727SMichael Lotz 	TRACE(("usb_module: get_descriptor(%ld, 0x%02x, 0x%02x, 0x%04x, 0x%08lx, %ld, 0x%08lx)\n", device, type, index, languageID, data, dataLength, actualLength));
2025b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(device);
2035b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
20417f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
205b8c6a851SMichael Lotz 
2065b0ec61fSMichael Lotz 	return ((Device *)object)->GetDescriptor(type, index, languageID,
207b8c6a851SMichael Lotz 		data, dataLength, actualLength);
208b8c6a851SMichael Lotz }
209b8c6a851SMichael Lotz 
210b8c6a851SMichael Lotz 
211b8c6a851SMichael Lotz status_t
2125b0ec61fSMichael Lotz send_request(usb_device device, uint8 requestType, uint8 request,
2135b0ec61fSMichael Lotz 	uint16 value, uint16 index, uint16 length, void *data, size_t *actualLength)
214b8c6a851SMichael Lotz {
215c4cce727SMichael Lotz 	TRACE(("usb_module: send_request(%ld, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %d, 0x%08lx, 0x%08lx)\n", device, requestType, request, value, index, length, data, actualLength));
2165b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(device);
2175b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
21817f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
219b8c6a851SMichael Lotz 
2208fedfdfcSMichael Lotz 	return ((Device *)object)->DefaultPipe()->SendRequest(requestType, request,
2218fedfdfcSMichael Lotz 		value, index, length, data, length, actualLength);
222b8c6a851SMichael Lotz }
223b8c6a851SMichael Lotz 
224b8c6a851SMichael Lotz 
225b8c6a851SMichael Lotz status_t
2265b0ec61fSMichael Lotz queue_request(usb_device device, uint8 requestType, uint8 request,
2275b0ec61fSMichael Lotz 	uint16 value, uint16 index, uint16 length, void *data,
228b8c6a851SMichael Lotz 	usb_callback_func callback, void *callbackCookie)
229b8c6a851SMichael Lotz {
230c4cce727SMichael Lotz 	TRACE(("usb_module: queue_request(%ld, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %ld, 0x%08lx, 0x%08lx, 0x%08lx)\n", device, requestType, request, value, index, length, data, callback, callbackCookie));
2315b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(device);
2325b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
23317f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
234b8c6a851SMichael Lotz 
2358fedfdfcSMichael Lotz 	return ((Device *)object)->DefaultPipe()->QueueRequest(requestType,
2368fedfdfcSMichael Lotz 		request, value, index, length, data, length, callback, callbackCookie);
237b8c6a851SMichael Lotz }
238b8c6a851SMichael Lotz 
239b8c6a851SMichael Lotz 
240b8c6a851SMichael Lotz status_t
2415b0ec61fSMichael Lotz queue_interrupt(usb_pipe pipe, void *data, size_t dataLength,
242b8c6a851SMichael Lotz 	usb_callback_func callback, void *callbackCookie)
243b8c6a851SMichael Lotz {
244c4cce727SMichael Lotz 	TRACE(("usb_module: queue_interrupt(%ld, 0x%08lx, %ld, 0x%08lx, 0x%08lx)\n", pipe, data, dataLength, callback, callbackCookie));
2455b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(pipe);
2465b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0)
24717f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
248b8c6a851SMichael Lotz 
2495b0ec61fSMichael Lotz 	return ((InterruptPipe *)object)->QueueInterrupt(data, dataLength, callback,
250b8c6a851SMichael Lotz 		callbackCookie);
251b8c6a851SMichael Lotz }
252b8c6a851SMichael Lotz 
253b8c6a851SMichael Lotz 
254b8c6a851SMichael Lotz status_t
2555b0ec61fSMichael Lotz queue_bulk(usb_pipe pipe, void *data, size_t dataLength,
256b8c6a851SMichael Lotz 	usb_callback_func callback, void *callbackCookie)
257b8c6a851SMichael Lotz {
258c4cce727SMichael Lotz 	TRACE(("usb_module: queue_bulk(%ld, 0x%08lx, %ld, 0x%08lx, 0x%08lx)\n", pipe, data, dataLength, callback, callbackCookie));
2595b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(pipe);
2605b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
26117f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
262b8c6a851SMichael Lotz 
2635b0ec61fSMichael Lotz 	return ((BulkPipe *)object)->QueueBulk(data, dataLength, callback,
264b8c6a851SMichael Lotz 		callbackCookie);
265b8c6a851SMichael Lotz }
266b8c6a851SMichael Lotz 
267b8c6a851SMichael Lotz 
268b8c6a851SMichael Lotz status_t
2695b0ec61fSMichael Lotz queue_bulk_v(usb_pipe pipe, iovec *vector, size_t vectorCount,
2705b0ec61fSMichael Lotz 	usb_callback_func callback, void *callbackCookie)
271b8c6a851SMichael Lotz {
272c4cce727SMichael Lotz 	TRACE(("usb_module: queue_bulk(%ld, 0x%08lx, %ld, 0x%08lx, 0x%08lx)\n", pipe, vector, vectorCount, callback, callbackCookie));
2735b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(pipe);
2745b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
27517f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
276b8c6a851SMichael Lotz 
2771e8c0b36SMichael Lotz 	return ((BulkPipe *)object)->QueueBulkV(vector, vectorCount, callback,
2781e8c0b36SMichael Lotz 		callbackCookie);
279b8c6a851SMichael Lotz }
280b8c6a851SMichael Lotz 
281b8c6a851SMichael Lotz 
282b8c6a851SMichael Lotz status_t
2835b0ec61fSMichael Lotz queue_isochronous(usb_pipe pipe, void *data, size_t dataLength,
2841bad4a4eSMichael Lotz 	usb_iso_packet_descriptor *packetDesc, uint32 packetCount,
2851bad4a4eSMichael Lotz 	uint32 *startingFrameNumber, uint32 flags, usb_callback_func callback,
2865b0ec61fSMichael Lotz 	void *callbackCookie)
2875b0ec61fSMichael Lotz {
288c4cce727SMichael Lotz 	TRACE(("usb_module: queue_isochronous(%ld, 0x%08lx, %ld, 0x%08lx, %ld, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx)\n", pipe, data, dataLength, packetDesc, packetCount, startingFrameNumber, flags, callback, callbackCookie));
2895b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(pipe);
2905b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
29117f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
2925b0ec61fSMichael Lotz 
2935b0ec61fSMichael Lotz 	return ((IsochronousPipe *)object)->QueueIsochronous(data, dataLength,
2941bad4a4eSMichael Lotz 		packetDesc, packetCount, startingFrameNumber, flags, callback,
2951bad4a4eSMichael Lotz 		callbackCookie);
2965b0ec61fSMichael Lotz }
2975b0ec61fSMichael Lotz 
2985b0ec61fSMichael Lotz 
2995b0ec61fSMichael Lotz status_t
3005b0ec61fSMichael Lotz set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets,
3015b0ec61fSMichael Lotz 	uint16 maxBufferDurationMS, uint16 sampleSize)
3025b0ec61fSMichael Lotz {
303c4cce727SMichael Lotz 	TRACE(("usb_module: set_pipe_policy(%ld, %d, %d, %d)\n", pipe, maxQueuedPackets, maxBufferDurationMS, sampleSize));
3045b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(pipe);
3055b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
30617f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
3075b0ec61fSMichael Lotz 
30800f6fab9SMichael Lotz 	return ((IsochronousPipe *)object)->SetPipePolicy(maxQueuedPackets,
30900f6fab9SMichael Lotz 		maxBufferDurationMS, sampleSize);
3105b0ec61fSMichael Lotz }
3115b0ec61fSMichael Lotz 
3125b0ec61fSMichael Lotz 
3135b0ec61fSMichael Lotz status_t
3145b0ec61fSMichael Lotz cancel_queued_transfers(usb_pipe pipe)
315b8c6a851SMichael Lotz {
316c4cce727SMichael Lotz 	TRACE(("usb_module: cancel_queued_transfers(%ld)\n", pipe));
3175b0ec61fSMichael Lotz 	Object *object = gUSBStack->GetObject(pipe);
3185b0ec61fSMichael Lotz 	if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
31917f83b21SMichael Lotz 		return B_DEV_INVALID_PIPE;
3205b0ec61fSMichael Lotz 
321*13508e8bSMichael Lotz 	return ((Pipe *)object)->CancelQueuedTransfers(false);
322b8c6a851SMichael Lotz }
323b8c6a851SMichael Lotz 
324b8c6a851SMichael Lotz 
325b8c6a851SMichael Lotz status_t
326b8c6a851SMichael Lotz usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize)
327b8c6a851SMichael Lotz {
328c4cce727SMichael Lotz 	TRACE(("usb_module: usb_ioctl(0x%08lx, 0x%08lx, %ld)\n", opcode, buffer, bufferSize));
32964f3c065SMichael Lotz 
33064f3c065SMichael Lotz 	switch (opcode) {
33164f3c065SMichael Lotz 		case 'DNAM': {
3325b0ec61fSMichael Lotz 			Object *object = gUSBStack->GetObject(*(usb_id *)buffer);
3335b0ec61fSMichael Lotz 			if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
3345b0ec61fSMichael Lotz 				return B_BAD_VALUE;
3355b0ec61fSMichael Lotz 
33664f3c065SMichael Lotz 			uint32 index = 0;
3375b0ec61fSMichael Lotz 			return ((Device *)object)->BuildDeviceName((char *)buffer, &index,
3385b0ec61fSMichael Lotz 				bufferSize, NULL);
33964f3c065SMichael Lotz 		}
34064f3c065SMichael Lotz 	}
34164f3c065SMichael Lotz 
34264f3c065SMichael Lotz 	return B_DEV_INVALID_IOCTL;
343b8c6a851SMichael Lotz }
344b8c6a851SMichael Lotz 
345b8c6a851SMichael Lotz 
34696da8285SMichael Lotz /*
3475b0ec61fSMichael Lotz 	This module exports the USB API v3
34896da8285SMichael Lotz */
3495b0ec61fSMichael Lotz struct usb_module_info gModuleInfoV3 = {
3501501c2bfSNiels Sascha Reedijk 	// First the bus_manager_info:
3511501c2bfSNiels Sascha Reedijk 	{
3521501c2bfSNiels Sascha Reedijk 		{
3535b0ec61fSMichael Lotz 			"bus_managers/usb/v3",
3541501c2bfSNiels Sascha Reedijk 			B_KEEP_LOADED,				// Keep loaded, even if no driver requires it
3551501c2bfSNiels Sascha Reedijk 			bus_std_ops
3561501c2bfSNiels Sascha Reedijk 		},
3571501c2bfSNiels Sascha Reedijk 		NULL							// the rescan function
3581501c2bfSNiels Sascha Reedijk 	},
35996da8285SMichael Lotz 
360b8c6a851SMichael Lotz 	register_driver,					// register_driver
361b8c6a851SMichael Lotz 	install_notify,						// install_notify
362b8c6a851SMichael Lotz 	uninstall_notify,					// uninstall_notify
363b8c6a851SMichael Lotz 	get_device_descriptor,				// get_device_descriptor
364b8c6a851SMichael Lotz 	get_nth_configuration,				// get_nth_configuration
365b8c6a851SMichael Lotz 	get_configuration,					// get_configuration
366b8c6a851SMichael Lotz 	set_configuration,					// set_configuration
367b8c6a851SMichael Lotz 	set_alt_interface,					// set_alt_interface
368b8c6a851SMichael Lotz 	set_feature,						// set_feature
369b8c6a851SMichael Lotz 	clear_feature, 						// clear_feature
370b8c6a851SMichael Lotz 	get_status, 						// get_status
371b8c6a851SMichael Lotz 	get_descriptor,						// get_descriptor
372b8c6a851SMichael Lotz 	send_request,						// send_request
373b8c6a851SMichael Lotz 	queue_interrupt,					// queue_interrupt
374b8c6a851SMichael Lotz 	queue_bulk,							// queue_bulk
3755b0ec61fSMichael Lotz 	queue_bulk_v,						// queue_bulk_v
376b8c6a851SMichael Lotz 	queue_isochronous,					// queue_isochronous
377b8c6a851SMichael Lotz 	queue_request,						// queue_request
378b8c6a851SMichael Lotz 	set_pipe_policy,					// set_pipe_policy
379b8c6a851SMichael Lotz 	cancel_queued_transfers,			// cancel_queued_transfers
380b8c6a851SMichael Lotz 	usb_ioctl							// usb_ioctl
3811501c2bfSNiels Sascha Reedijk };
3821501c2bfSNiels Sascha Reedijk 
38396da8285SMichael Lotz 
3845b0ec61fSMichael Lotz //
3855b0ec61fSMichael Lotz // #pragma mark -
3865b0ec61fSMichael Lotz //
3875b0ec61fSMichael Lotz 
3885b0ec61fSMichael Lotz 
3895b0ec61fSMichael Lotz const usb_device_descriptor *
3905b0ec61fSMichael Lotz get_device_descriptor_v2(const void *device)
3915b0ec61fSMichael Lotz {
3925b0ec61fSMichael Lotz 	return get_device_descriptor((usb_id)device);
3935b0ec61fSMichael Lotz }
3945b0ec61fSMichael Lotz 
3955b0ec61fSMichael Lotz 
3965b0ec61fSMichael Lotz const usb_configuration_info *
3975b0ec61fSMichael Lotz get_nth_configuration_v2(const void *device, uint index)
3985b0ec61fSMichael Lotz {
3995b0ec61fSMichael Lotz 	return get_nth_configuration((usb_id)device, index);
4005b0ec61fSMichael Lotz }
4015b0ec61fSMichael Lotz 
4025b0ec61fSMichael Lotz 
4035b0ec61fSMichael Lotz const usb_configuration_info *
4045b0ec61fSMichael Lotz get_configuration_v2(const void *device)
4055b0ec61fSMichael Lotz {
4065b0ec61fSMichael Lotz 	return get_configuration((usb_id)device);
4075b0ec61fSMichael Lotz }
4085b0ec61fSMichael Lotz 
4095b0ec61fSMichael Lotz 
4105b0ec61fSMichael Lotz status_t
4115b0ec61fSMichael Lotz set_configuration_v2(const void *device,
4125b0ec61fSMichael Lotz 	const usb_configuration_info *configuration)
4135b0ec61fSMichael Lotz {
4145b0ec61fSMichael Lotz 	return set_configuration((usb_id)device, configuration);
4155b0ec61fSMichael Lotz }
4165b0ec61fSMichael Lotz 
4175b0ec61fSMichael Lotz 
4185b0ec61fSMichael Lotz status_t
4195b0ec61fSMichael Lotz set_alt_interface_v2(const void *device, const usb_interface_info *interface)
4205b0ec61fSMichael Lotz {
4215b0ec61fSMichael Lotz 	return set_alt_interface((usb_id)device, interface);
4225b0ec61fSMichael Lotz }
4235b0ec61fSMichael Lotz 
4245b0ec61fSMichael Lotz 
4255b0ec61fSMichael Lotz status_t
4265b0ec61fSMichael Lotz set_feature_v2(const void *object, uint16 selector)
4275b0ec61fSMichael Lotz {
4285b0ec61fSMichael Lotz 	return set_feature((usb_id)object, selector);
4295b0ec61fSMichael Lotz }
4305b0ec61fSMichael Lotz 
4315b0ec61fSMichael Lotz 
4325b0ec61fSMichael Lotz status_t
4335b0ec61fSMichael Lotz clear_feature_v2(const void *object, uint16 selector)
4345b0ec61fSMichael Lotz {
4355b0ec61fSMichael Lotz 	return clear_feature((usb_id)object, selector);
4365b0ec61fSMichael Lotz }
4375b0ec61fSMichael Lotz 
4385b0ec61fSMichael Lotz 
4395b0ec61fSMichael Lotz status_t
4405b0ec61fSMichael Lotz get_status_v2(const void *object, uint16 *status)
4415b0ec61fSMichael Lotz {
4425b0ec61fSMichael Lotz 	return get_status((usb_id)object, status);
4435b0ec61fSMichael Lotz }
4445b0ec61fSMichael Lotz 
4455b0ec61fSMichael Lotz 
4465b0ec61fSMichael Lotz status_t
4475b0ec61fSMichael Lotz get_descriptor_v2(const void *device, uint8 type, uint8 index,
4485b0ec61fSMichael Lotz 	uint16 languageID, void *data, size_t dataLength, size_t *actualLength)
4495b0ec61fSMichael Lotz {
4505b0ec61fSMichael Lotz 	return get_descriptor((usb_id)device, type, index, languageID, data,
4515b0ec61fSMichael Lotz 		dataLength, actualLength);
4525b0ec61fSMichael Lotz }
4535b0ec61fSMichael Lotz 
4545b0ec61fSMichael Lotz 
4555b0ec61fSMichael Lotz status_t
4565b0ec61fSMichael Lotz send_request_v2(const void *device, uint8 requestType, uint8 request,
4575b0ec61fSMichael Lotz 	uint16 value, uint16 index, uint16 length, void *data,
4585b0ec61fSMichael Lotz 	size_t /*dataLength*/, size_t *actualLength)
4595b0ec61fSMichael Lotz {
4605b0ec61fSMichael Lotz 	return send_request((usb_id)device, requestType, request, value, index,
4615b0ec61fSMichael Lotz 		length, data, actualLength);
4625b0ec61fSMichael Lotz }
4635b0ec61fSMichael Lotz 
4645b0ec61fSMichael Lotz 
4655b0ec61fSMichael Lotz status_t
4665b0ec61fSMichael Lotz queue_request_v2(const void *device, uint8 requestType, uint8 request,
4675b0ec61fSMichael Lotz 	uint16 value, uint16 index, uint16 length, void *data,
4685b0ec61fSMichael Lotz 	size_t /*dataLength*/, usb_callback_func callback, void *callbackCookie)
4695b0ec61fSMichael Lotz {
4705b0ec61fSMichael Lotz 	return queue_request((usb_id)device, requestType, request, value, index,
4715b0ec61fSMichael Lotz 		length, data, callback, callbackCookie);
4725b0ec61fSMichael Lotz }
4735b0ec61fSMichael Lotz 
4745b0ec61fSMichael Lotz 
4755b0ec61fSMichael Lotz status_t
4765b0ec61fSMichael Lotz queue_interrupt_v2(const void *pipe, void *data, size_t dataLength,
4775b0ec61fSMichael Lotz 	usb_callback_func callback, void *callbackCookie)
4785b0ec61fSMichael Lotz {
4795b0ec61fSMichael Lotz 	return queue_interrupt((usb_id)pipe, data, dataLength, callback,
4805b0ec61fSMichael Lotz 		callbackCookie);
4815b0ec61fSMichael Lotz }
4825b0ec61fSMichael Lotz 
4835b0ec61fSMichael Lotz 
4845b0ec61fSMichael Lotz status_t
4855b0ec61fSMichael Lotz queue_bulk_v2(const void *pipe, void *data, size_t dataLength,
4865b0ec61fSMichael Lotz 	usb_callback_func callback, void *callbackCookie)
4875b0ec61fSMichael Lotz {
4885b0ec61fSMichael Lotz 	return queue_bulk((usb_id)pipe, data, dataLength, callback,
4895b0ec61fSMichael Lotz 		callbackCookie);
4905b0ec61fSMichael Lotz }
4915b0ec61fSMichael Lotz 
4925b0ec61fSMichael Lotz 
4935b0ec61fSMichael Lotz status_t
4945b0ec61fSMichael Lotz queue_isochronous_v2(const void *pipe, void *data, size_t dataLength,
4955b0ec61fSMichael Lotz 	rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback,
4965b0ec61fSMichael Lotz 	void *callbackCookie)
4975b0ec61fSMichael Lotz {
4981bad4a4eSMichael Lotz 	// ToDo: convert rlea to usb_iso_packet_descriptor
4991bad4a4eSMichael Lotz 	// ToDo: use a flag to indicate that the callback shall produce a rlea
5001bad4a4eSMichael Lotz 	usb_iso_packet_descriptor *packetDesc = NULL;
5011bad4a4eSMichael Lotz 	return queue_isochronous((usb_id)pipe, data, dataLength, packetDesc, 0,
5021bad4a4eSMichael Lotz 		NULL, 0, callback, callbackCookie);
5035b0ec61fSMichael Lotz }
5045b0ec61fSMichael Lotz 
5055b0ec61fSMichael Lotz 
5065b0ec61fSMichael Lotz status_t
5075b0ec61fSMichael Lotz set_pipe_policy_v2(const void *pipe, uint8 maxQueuedPackets,
5085b0ec61fSMichael Lotz 	uint16 maxBufferDurationMS, uint16 sampleSize)
5095b0ec61fSMichael Lotz {
5105b0ec61fSMichael Lotz 	return set_pipe_policy((usb_id)pipe, maxQueuedPackets, maxBufferDurationMS,
5115b0ec61fSMichael Lotz 		sampleSize);
5125b0ec61fSMichael Lotz }
5135b0ec61fSMichael Lotz 
5145b0ec61fSMichael Lotz 
5155b0ec61fSMichael Lotz status_t
5165b0ec61fSMichael Lotz cancel_queued_transfers_v2(const void *pipe)
5175b0ec61fSMichael Lotz {
5185b0ec61fSMichael Lotz 	return cancel_queued_transfers((usb_id)pipe);
5195b0ec61fSMichael Lotz }
5205b0ec61fSMichael Lotz 
5215b0ec61fSMichael Lotz 
5225b0ec61fSMichael Lotz struct usb_module_info_v2 {
5235b0ec61fSMichael Lotz 	bus_manager_info				binfo;
5245b0ec61fSMichael Lotz 	status_t						(*register_driver)(const char *, const usb_support_descriptor *, size_t, const char *);
5255b0ec61fSMichael Lotz 	status_t						(*install_notify)(const char *, const usb_notify_hooks *);
5265b0ec61fSMichael Lotz 	status_t						(*uninstall_notify)(const char *);
5275b0ec61fSMichael Lotz 	const usb_device_descriptor		*(*get_device_descriptor)(const void *);
5285b0ec61fSMichael Lotz 	const usb_configuration_info	*(*get_nth_configuration)(const void *, uint);
5295b0ec61fSMichael Lotz 	const usb_configuration_info	*(*get_configuration)(const void *);
5305b0ec61fSMichael Lotz 	status_t						(*set_configuration)(const void *, const usb_configuration_info *);
5315b0ec61fSMichael Lotz 	status_t						(*set_alt_interface)(const void *, const usb_interface_info *);
5325b0ec61fSMichael Lotz 	status_t						(*set_feature)(const void *, uint16);
5335b0ec61fSMichael Lotz 	status_t						(*clear_feature)(const void *, uint16);
5345b0ec61fSMichael Lotz 	status_t						(*get_status)(const void *, uint16 *);
5355b0ec61fSMichael Lotz 	status_t						(*get_descriptor)(const void *, uint8, uint8, uint16, void *, size_t, size_t *);
5365b0ec61fSMichael Lotz 	status_t						(*send_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, size_t *);
5375b0ec61fSMichael Lotz 	status_t						(*queue_interrupt)(const void *, void *, size_t, usb_callback_func, void *);
5385b0ec61fSMichael Lotz 	status_t						(*queue_bulk)(const void *, void *, size_t, usb_callback_func, void *);
5395b0ec61fSMichael Lotz 	status_t						(*queue_isochronous)(const void *, void *, size_t, rlea *, uint16, usb_callback_func, void *);
5405b0ec61fSMichael Lotz 	status_t						(*queue_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, usb_callback_func, void *);
5415b0ec61fSMichael Lotz 	status_t						(*set_pipe_policy)(const void *, uint8, uint16, uint16);
5425b0ec61fSMichael Lotz 	status_t						(*cancel_queued_transfers)(const void *);
5435b0ec61fSMichael Lotz 	status_t						(*usb_ioctl)(uint32 opcode, void *,size_t);
5445b0ec61fSMichael Lotz };
5455b0ec61fSMichael Lotz 
5465b0ec61fSMichael Lotz 
5475b0ec61fSMichael Lotz /*
5485b0ec61fSMichael Lotz 	This module exports the USB API v2
5495b0ec61fSMichael Lotz */
5505b0ec61fSMichael Lotz struct usb_module_info_v2 gModuleInfoV2 = {
5515b0ec61fSMichael Lotz 	// First the bus_manager_info:
5525b0ec61fSMichael Lotz 	{
5535b0ec61fSMichael Lotz 		{
5545b0ec61fSMichael Lotz 			"bus_managers/usb/v2",
5555b0ec61fSMichael Lotz 			B_KEEP_LOADED,				// Keep loaded, even if no driver requires it
5565b0ec61fSMichael Lotz 			bus_std_ops
5575b0ec61fSMichael Lotz 		},
5585b0ec61fSMichael Lotz 		NULL							// the rescan function
5595b0ec61fSMichael Lotz 	},
5605b0ec61fSMichael Lotz 
5615b0ec61fSMichael Lotz 	register_driver,					// register_driver
5625b0ec61fSMichael Lotz 	install_notify,						// install_notify
5635b0ec61fSMichael Lotz 	uninstall_notify,					// uninstall_notify
5645b0ec61fSMichael Lotz 	get_device_descriptor_v2,			// get_device_descriptor
5655b0ec61fSMichael Lotz 	get_nth_configuration_v2,			// get_nth_configuration
5665b0ec61fSMichael Lotz 	get_configuration_v2,				// get_configuration
5675b0ec61fSMichael Lotz 	set_configuration_v2,				// set_configuration
5685b0ec61fSMichael Lotz 	set_alt_interface_v2,				// set_alt_interface
5695b0ec61fSMichael Lotz 	set_feature_v2,						// set_feature
5705b0ec61fSMichael Lotz 	clear_feature_v2,					// clear_feature
5715b0ec61fSMichael Lotz 	get_status_v2, 						// get_status
5725b0ec61fSMichael Lotz 	get_descriptor_v2,					// get_descriptor
5735b0ec61fSMichael Lotz 	send_request_v2,					// send_request
5745b0ec61fSMichael Lotz 	queue_interrupt_v2,					// queue_interrupt
5755b0ec61fSMichael Lotz 	queue_bulk_v2,						// queue_bulk
5765b0ec61fSMichael Lotz 	queue_isochronous_v2,				// queue_isochronous
5775b0ec61fSMichael Lotz 	queue_request_v2,					// queue_request
5785b0ec61fSMichael Lotz 	set_pipe_policy_v2,					// set_pipe_policy
5795b0ec61fSMichael Lotz 	cancel_queued_transfers_v2,			// cancel_queued_transfers
5805b0ec61fSMichael Lotz 	usb_ioctl							// usb_ioctl
5815b0ec61fSMichael Lotz };
5825b0ec61fSMichael Lotz 
5835b0ec61fSMichael Lotz 
5845b0ec61fSMichael Lotz //
5855b0ec61fSMichael Lotz // #pragma mark -
5865b0ec61fSMichael Lotz //
5875b0ec61fSMichael Lotz 
5885b0ec61fSMichael Lotz 
5891501c2bfSNiels Sascha Reedijk module_info *modules[] = {
5905b0ec61fSMichael Lotz 	(module_info *)&gModuleInfoV2,
5915b0ec61fSMichael Lotz 	(module_info *)&gModuleInfoV3,
5921501c2bfSNiels Sascha Reedijk 	NULL
5931501c2bfSNiels Sascha Reedijk };
594