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
1021c87a5dSJérôme Duval
111501c2bfSNiels Sascha Reedijk #include <util/kernel_cpp.h>
12853e6be8SMichael Lotz #include "usb_private.h"
131bad4a4eSMichael Lotz #include <USB_rle.h>
141501c2bfSNiels Sascha Reedijk
15f14fe767SMichael Lotz #define USB_MODULE_NAME "module"
1696da8285SMichael Lotz
17b8c6a851SMichael Lotz Stack *gUSBStack = NULL;
18e6ce95c5SJérôme Duval device_manager_info *gDeviceManager;
19b8c6a851SMichael Lotz
20b8c6a851SMichael Lotz
21159aa93bSMichael Lotz /*! The function is an evil hack to allow <tt> <kdebug>usb_keyboard </tt> to
22159aa93bSMichael Lotz execute transfers.
23159aa93bSMichael Lotz When invoked the first time, a new transfer is started, each time the
24159aa93bSMichael Lotz function is called afterwards, it is checked whether the transfer is already
25159aa93bSMichael Lotz completed. If called with argv[1] == "cancel" the function cancels a
26159aa93bSMichael Lotz possibly pending transfer.
27159aa93bSMichael Lotz */
28159aa93bSMichael Lotz static status_t
debug_run_transfer(Pipe * pipe,uint8 * data,size_t dataLength,usb_request_data * requestData,bool cancel)29159aa93bSMichael Lotz debug_run_transfer(Pipe *pipe, uint8 *data, size_t dataLength,
30159aa93bSMichael Lotz usb_request_data *requestData, bool cancel)
31159aa93bSMichael Lotz {
32159aa93bSMichael Lotz static uint8 transferBuffer[sizeof(Transfer)]
33159aa93bSMichael Lotz __attribute__((aligned(16)));
34159aa93bSMichael Lotz static Transfer *transfer = NULL;
35159aa93bSMichael Lotz
36159aa93bSMichael Lotz BusManager *bus = pipe->GetBusManager();
37159aa93bSMichael Lotz
38159aa93bSMichael Lotz if (cancel) {
39159aa93bSMichael Lotz if (transfer != NULL) {
40159aa93bSMichael Lotz bus->CancelDebugTransfer(transfer);
41159aa93bSMichael Lotz transfer = NULL;
42159aa93bSMichael Lotz }
43159aa93bSMichael Lotz
44159aa93bSMichael Lotz return B_OK;
45159aa93bSMichael Lotz }
46159aa93bSMichael Lotz
47159aa93bSMichael Lotz if (transfer != NULL) {
48159aa93bSMichael Lotz status_t error = bus->CheckDebugTransfer(transfer);
49159aa93bSMichael Lotz if (error != B_DEV_PENDING)
50159aa93bSMichael Lotz transfer = NULL;
51159aa93bSMichael Lotz
52159aa93bSMichael Lotz return error;
53159aa93bSMichael Lotz }
54159aa93bSMichael Lotz
55159aa93bSMichael Lotz transfer = new(transferBuffer) Transfer(pipe);
56159aa93bSMichael Lotz transfer->SetData(data, dataLength);
57159aa93bSMichael Lotz transfer->SetRequestData(requestData);
58159aa93bSMichael Lotz
59159aa93bSMichael Lotz status_t error = bus->StartDebugTransfer(transfer);
60159aa93bSMichael Lotz if (error != B_OK) {
61159aa93bSMichael Lotz transfer = NULL;
62159aa93bSMichael Lotz return error;
63159aa93bSMichael Lotz }
64159aa93bSMichael Lotz
65159aa93bSMichael Lotz return B_DEV_PENDING;
66159aa93bSMichael Lotz }
67159aa93bSMichael Lotz
68159aa93bSMichael Lotz
696eba0636SMichael Lotz static int
debug_get_pipe_for_id(int argc,char ** argv)706eba0636SMichael Lotz debug_get_pipe_for_id(int argc, char **argv)
716eba0636SMichael Lotz {
726eba0636SMichael Lotz if (gUSBStack == NULL)
736eba0636SMichael Lotz return 1;
746eba0636SMichael Lotz
756eba0636SMichael Lotz if (!is_debug_variable_defined("_usbPipeID"))
766eba0636SMichael Lotz return 2;
776eba0636SMichael Lotz
786eba0636SMichael Lotz uint64 id = get_debug_variable("_usbPipeID", 0);
796eba0636SMichael Lotz Object *object = gUSBStack->GetObjectNoLock((usb_id)id);
806eba0636SMichael Lotz if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
816eba0636SMichael Lotz return 3;
826eba0636SMichael Lotz
836eba0636SMichael Lotz set_debug_variable("_usbPipe", (uint64)object);
846eba0636SMichael Lotz return 0;
856eba0636SMichael Lotz }
86159aa93bSMichael Lotz
87159aa93bSMichael Lotz
88159aa93bSMichael Lotz static int
debug_process_transfer(int argc,char ** argv)89159aa93bSMichael Lotz debug_process_transfer(int argc, char **argv)
90159aa93bSMichael Lotz {
91159aa93bSMichael Lotz Pipe *pipe = (Pipe *)get_debug_variable("_usbPipe", 0);
92159aa93bSMichael Lotz if (pipe == NULL)
93159aa93bSMichael Lotz return B_BAD_VALUE;
94159aa93bSMichael Lotz
95159aa93bSMichael Lotz uint8 *data = (uint8 *)get_debug_variable("_usbTransferData", 0);
96159aa93bSMichael Lotz size_t length = (size_t)get_debug_variable("_usbTransferLength", 0);
97159aa93bSMichael Lotz usb_request_data *requestData
98159aa93bSMichael Lotz = (usb_request_data *)get_debug_variable("_usbRequestData", 0);
99159aa93bSMichael Lotz
100159aa93bSMichael Lotz return debug_run_transfer(pipe, data, length, requestData,
101159aa93bSMichael Lotz argc > 1 && strcmp(argv[1], "cancel") == 0);
102159aa93bSMichael Lotz }
103e31cac6eSMichael Lotz
104e31cac6eSMichael Lotz
105e31cac6eSMichael Lotz static int
debug_clear_stall(int argc,char * argv[])106e31cac6eSMichael Lotz debug_clear_stall(int argc, char *argv[])
107e31cac6eSMichael Lotz {
108e31cac6eSMichael Lotz Pipe *pipe = (Pipe *)get_debug_variable("_usbPipe", 0);
109e31cac6eSMichael Lotz if (pipe == NULL)
110e31cac6eSMichael Lotz return B_BAD_VALUE;
111e31cac6eSMichael Lotz
112e31cac6eSMichael Lotz static usb_request_data requestData;
113e31cac6eSMichael Lotz
114e31cac6eSMichael Lotz requestData.RequestType = USB_REQTYPE_STANDARD | USB_REQTYPE_ENDPOINT_OUT;
115e31cac6eSMichael Lotz requestData.Request = USB_REQUEST_CLEAR_FEATURE;
116e31cac6eSMichael Lotz requestData.Value = USB_FEATURE_ENDPOINT_HALT;
117e31cac6eSMichael Lotz requestData.Index = pipe->EndpointAddress()
118e31cac6eSMichael Lotz | (pipe->Direction() == Pipe::In ? USB_ENDPOINT_ADDR_DIR_IN
119e31cac6eSMichael Lotz : USB_ENDPOINT_ADDR_DIR_OUT);
120e31cac6eSMichael Lotz requestData.Length = 0;
121e31cac6eSMichael Lotz
122e31cac6eSMichael Lotz Pipe *parentPipe = ((Device *)pipe->Parent())->DefaultPipe();
123e31cac6eSMichael Lotz for (int tries = 0; tries < 100; tries++) {
124e31cac6eSMichael Lotz status_t result
125e31cac6eSMichael Lotz = debug_run_transfer(parentPipe, NULL, 0, &requestData, false);
126e31cac6eSMichael Lotz
127e31cac6eSMichael Lotz if (result == B_DEV_PENDING)
128e31cac6eSMichael Lotz continue;
129e31cac6eSMichael Lotz
130e31cac6eSMichael Lotz if (result == B_OK) {
131e31cac6eSMichael Lotz // clearing a stalled condition resets the data toggle
132e31cac6eSMichael Lotz pipe->SetDataToggle(false);
133e31cac6eSMichael Lotz return B_OK;
134e31cac6eSMichael Lotz }
135e31cac6eSMichael Lotz
136e31cac6eSMichael Lotz return result;
137e31cac6eSMichael Lotz }
138e31cac6eSMichael Lotz
139e31cac6eSMichael Lotz return B_TIMED_OUT;
140e31cac6eSMichael Lotz }
1416eba0636SMichael Lotz
1426eba0636SMichael Lotz
1431501c2bfSNiels Sascha Reedijk static int32
bus_std_ops(int32 op,...)1441501c2bfSNiels Sascha Reedijk bus_std_ops(int32 op, ...)
1451501c2bfSNiels Sascha Reedijk {
1461501c2bfSNiels Sascha Reedijk switch (op) {
14796da8285SMichael Lotz case B_MODULE_INIT: {
148f14fe767SMichael Lotz TRACE_MODULE("init\n");
1495b0ec61fSMichael Lotz if (gUSBStack)
1505b0ec61fSMichael Lotz return B_OK;
1515b0ec61fSMichael Lotz
15296da8285SMichael Lotz #ifdef TRACE_USB
1531a2e81b5SNiels Sascha Reedijk set_dprintf_enabled(true);
15402ce23a1SMichael Lotz #endif
155b8c6a851SMichael Lotz Stack *stack = new(std::nothrow) Stack();
156f14fe767SMichael Lotz TRACE_MODULE("usb_module: stack created %p\n", stack);
157b8c6a851SMichael Lotz if (!stack)
158b8c6a851SMichael Lotz return B_NO_MEMORY;
159b8c6a851SMichael Lotz
16096da8285SMichael Lotz if (stack->InitCheck() != B_OK) {
1611a2e81b5SNiels Sascha Reedijk delete stack;
1621501c2bfSNiels Sascha Reedijk return ENODEV;
1631501c2bfSNiels Sascha Reedijk }
16496da8285SMichael Lotz
165eb6a1cbcSMichael Lotz gUSBStack = stack;
166eb01fb72SMichael Lotz
1676eba0636SMichael Lotz add_debugger_command("get_usb_pipe_for_id",
1686eba0636SMichael Lotz &debug_get_pipe_for_id,
169159aa93bSMichael Lotz "Sets _usbPipe by resolving _usbPipeID");
170159aa93bSMichael Lotz add_debugger_command("usb_process_transfer",
171159aa93bSMichael Lotz &debug_process_transfer,
172159aa93bSMichael Lotz "Transfers _usbTransferData with _usbTransferLength"
173159aa93bSMichael Lotz " (and/or _usbRequestData) to pipe _usbPipe");
174e31cac6eSMichael Lotz add_debugger_command("usb_clear_stall",
175e31cac6eSMichael Lotz &debug_clear_stall,
176e31cac6eSMichael Lotz "Tries to issue a clear feature request for the endpoint halt"
177e31cac6eSMichael Lotz " feature on pipe _usbPipe");
1781501c2bfSNiels Sascha Reedijk break;
17996da8285SMichael Lotz }
18096da8285SMichael Lotz
1811501c2bfSNiels Sascha Reedijk case B_MODULE_UNINIT:
182f14fe767SMichael Lotz TRACE_MODULE("uninit\n");
183b8c6a851SMichael Lotz delete gUSBStack;
184b8c6a851SMichael Lotz gUSBStack = NULL;
185eb01fb72SMichael Lotz
1866eba0636SMichael Lotz remove_debugger_command("get_usb_pipe_for_id",
1876eba0636SMichael Lotz &debug_get_pipe_for_id);
1881501c2bfSNiels Sascha Reedijk break;
18996da8285SMichael Lotz
1901501c2bfSNiels Sascha Reedijk default:
1911501c2bfSNiels Sascha Reedijk return EINVAL;
1921501c2bfSNiels Sascha Reedijk }
19396da8285SMichael Lotz
1941501c2bfSNiels Sascha Reedijk return B_OK;
1951501c2bfSNiels Sascha Reedijk }
1961501c2bfSNiels Sascha Reedijk
1971501c2bfSNiels Sascha Reedijk
1985ee91867SAugustin Cavalier // #pragma mark - public methods
1995ee91867SAugustin Cavalier
2005ee91867SAugustin Cavalier
201b8c6a851SMichael Lotz status_t
register_driver(const char * driverName,const usb_support_descriptor * descriptors,size_t count,const char * optionalRepublishDriverName)202b8c6a851SMichael Lotz register_driver(const char *driverName,
203b8c6a851SMichael Lotz const usb_support_descriptor *descriptors,
204b8c6a851SMichael Lotz size_t count, const char *optionalRepublishDriverName)
205b8c6a851SMichael Lotz {
206b8c6a851SMichael Lotz return gUSBStack->RegisterDriver(driverName, descriptors, count,
207b8c6a851SMichael Lotz optionalRepublishDriverName);
208b8c6a851SMichael Lotz }
209b8c6a851SMichael Lotz
210b8c6a851SMichael Lotz
211b8c6a851SMichael Lotz status_t
install_notify(const char * driverName,const usb_notify_hooks * hooks)212b8c6a851SMichael Lotz install_notify(const char *driverName, const usb_notify_hooks *hooks)
213b8c6a851SMichael Lotz {
214b8c6a851SMichael Lotz return gUSBStack->InstallNotify(driverName, hooks);
215b8c6a851SMichael Lotz }
216b8c6a851SMichael Lotz
217b8c6a851SMichael Lotz
218b8c6a851SMichael Lotz status_t
uninstall_notify(const char * driverName)219b8c6a851SMichael Lotz uninstall_notify(const char *driverName)
220b8c6a851SMichael Lotz {
221b8c6a851SMichael Lotz return gUSBStack->UninstallNotify(driverName);
222b8c6a851SMichael Lotz }
223b8c6a851SMichael Lotz
224b8c6a851SMichael Lotz
225b8c6a851SMichael Lotz const usb_device_descriptor *
get_device_descriptor(usb_device dev)226dd249016SAugustin Cavalier get_device_descriptor(usb_device dev)
227b8c6a851SMichael Lotz {
228dd249016SAugustin Cavalier TRACE_MODULE("get_device_descriptor(%" B_PRId32 ")\n", dev);
229*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(dev), true);
2305ee91867SAugustin Cavalier if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
231b8c6a851SMichael Lotz return NULL;
2325ee91867SAugustin Cavalier Device *device = (Device *)object.Get();
233b8c6a851SMichael Lotz
234dd249016SAugustin Cavalier return device->DeviceDescriptor();
235b8c6a851SMichael Lotz }
236b8c6a851SMichael Lotz
237b8c6a851SMichael Lotz
238b8c6a851SMichael Lotz const usb_configuration_info *
get_nth_configuration(usb_device dev,uint32 index)239dd249016SAugustin Cavalier get_nth_configuration(usb_device dev, uint32 index)
240b8c6a851SMichael Lotz {
241d8b4cfc9SRene Gollent TRACE_MODULE("get_nth_configuration(%" B_PRId32 ", %" B_PRIu32 ")\n",
242dd249016SAugustin Cavalier dev, index);
243*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(dev), true);
2445ee91867SAugustin Cavalier if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
245b8c6a851SMichael Lotz return NULL;
2465ee91867SAugustin Cavalier Device *device = (Device *)object.Get();
247b8c6a851SMichael Lotz
248dd249016SAugustin Cavalier return device->ConfigurationAt((int32)index);
249b8c6a851SMichael Lotz }
250b8c6a851SMichael Lotz
251b8c6a851SMichael Lotz
252b8c6a851SMichael Lotz const usb_configuration_info *
get_configuration(usb_device dev)253dd249016SAugustin Cavalier get_configuration(usb_device dev)
254b8c6a851SMichael Lotz {
255dd249016SAugustin Cavalier TRACE_MODULE("get_configuration(%" B_PRId32 ")\n", dev);
256*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(dev), true);
2575ee91867SAugustin Cavalier if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
258b8c6a851SMichael Lotz return NULL;
2595ee91867SAugustin Cavalier Device *device = (Device *)object.Get();
260b8c6a851SMichael Lotz
261dd249016SAugustin Cavalier return device->Configuration();
262b8c6a851SMichael Lotz }
263b8c6a851SMichael Lotz
264b8c6a851SMichael Lotz
265b8c6a851SMichael Lotz status_t
set_configuration(usb_device dev,const usb_configuration_info * configuration)266dd249016SAugustin Cavalier set_configuration(usb_device dev,
267b8c6a851SMichael Lotz const usb_configuration_info *configuration)
268b8c6a851SMichael Lotz {
269dd249016SAugustin Cavalier TRACE_MODULE("set_configuration(%" B_PRId32 ", %p)\n", dev,
270d8b4cfc9SRene Gollent configuration);
271*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(dev), true);
2725ee91867SAugustin Cavalier if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
27317f83b21SMichael Lotz return B_DEV_INVALID_PIPE;
2745ee91867SAugustin Cavalier Device *device = (Device *)object.Get();
275b8c6a851SMichael Lotz
276dd249016SAugustin Cavalier return device->SetConfiguration(configuration);
277b8c6a851SMichael Lotz }
278b8c6a851SMichael Lotz
279b8c6a851SMichael Lotz
280b8c6a851SMichael Lotz status_t
set_alt_interface(usb_device dev,const usb_interface_info * interface)281dd249016SAugustin Cavalier set_alt_interface(usb_device dev, const usb_interface_info *interface)
282b8c6a851SMichael Lotz {
283dd249016SAugustin Cavalier TRACE_MODULE("set_alt_interface(%" B_PRId32 ", %p)\n", dev, interface);
284*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(dev), true);
2855ee91867SAugustin Cavalier if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
28617f83b21SMichael Lotz return B_DEV_INVALID_PIPE;
2875ee91867SAugustin Cavalier Device *device = (Device *)object.Get();
2885b0ec61fSMichael Lotz
289dd249016SAugustin Cavalier return device->SetAltInterface(interface);
290b8c6a851SMichael Lotz }
291b8c6a851SMichael Lotz
292b8c6a851SMichael Lotz
293b8c6a851SMichael Lotz status_t
set_feature(usb_id handle,uint16 selector)2945b0ec61fSMichael Lotz set_feature(usb_id handle, uint16 selector)
295b8c6a851SMichael Lotz {
296d8b4cfc9SRene Gollent TRACE_MODULE("set_feature(%" B_PRId32 ", %d)\n", handle, selector);
297*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(handle), true);
2985ee91867SAugustin Cavalier if (!object.IsSet())
29917f83b21SMichael Lotz return B_DEV_INVALID_PIPE;
300b8c6a851SMichael Lotz
3018fedfdfcSMichael Lotz return object->SetFeature(selector);
302b8c6a851SMichael Lotz }
303b8c6a851SMichael Lotz
304b8c6a851SMichael Lotz
305b8c6a851SMichael Lotz status_t
clear_feature(usb_id handle,uint16 selector)3065b0ec61fSMichael Lotz clear_feature(usb_id handle, uint16 selector)
307b8c6a851SMichael Lotz {
308d8b4cfc9SRene Gollent TRACE_MODULE("clear_feature(%" B_PRId32 ", %d)\n", handle, selector);
309*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(handle), true);
3105ee91867SAugustin Cavalier if (!object.IsSet())
31117f83b21SMichael Lotz return B_DEV_INVALID_PIPE;
312b8c6a851SMichael Lotz
3138fedfdfcSMichael Lotz return object->ClearFeature(selector);
314b8c6a851SMichael Lotz }
315b8c6a851SMichael Lotz
316b8c6a851SMichael Lotz
317b8c6a851SMichael Lotz status_t
get_status(usb_id handle,uint16 * status)3185b0ec61fSMichael Lotz get_status(usb_id handle, uint16 *status)
319b8c6a851SMichael Lotz {
320d8b4cfc9SRene Gollent TRACE_MODULE("get_status(%" B_PRId32 ", %p)\n", handle, status);
3215b0ec61fSMichael Lotz if (!status)
3225b0ec61fSMichael Lotz return B_BAD_VALUE;
3235b0ec61fSMichael Lotz
324*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(handle), true);
3255ee91867SAugustin Cavalier if (!object.IsSet())
32617f83b21SMichael Lotz return B_DEV_INVALID_PIPE;
327b8c6a851SMichael Lotz
3288fedfdfcSMichael Lotz return object->GetStatus(status);
329b8c6a851SMichael Lotz }
330b8c6a851SMichael Lotz
331b8c6a851SMichael Lotz
332b8c6a851SMichael Lotz status_t
get_descriptor(usb_device dev,uint8 type,uint8 index,uint16 languageID,void * data,size_t dataLength,size_t * actualLength)333dd249016SAugustin Cavalier get_descriptor(usb_device dev, uint8 type, uint8 index, uint16 languageID,
3345b0ec61fSMichael Lotz void *data, size_t dataLength, size_t *actualLength)
335b8c6a851SMichael Lotz {
336d8b4cfc9SRene Gollent TRACE_MODULE("get_descriptor(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, %p, "
337d8b4cfc9SRene Gollent "%" B_PRIuSIZE ", %p)\n",
338dd249016SAugustin Cavalier dev, type, index, languageID, data, dataLength, actualLength);
339*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(dev), true);
3405ee91867SAugustin Cavalier if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
34117f83b21SMichael Lotz return B_DEV_INVALID_PIPE;
3425ee91867SAugustin Cavalier Device *device = (Device *)object.Get();
343b8c6a851SMichael Lotz
344dd249016SAugustin Cavalier return device->GetDescriptor(type, index, languageID,
345b8c6a851SMichael Lotz data, dataLength, actualLength);
346b8c6a851SMichael Lotz }
347b8c6a851SMichael Lotz
348b8c6a851SMichael Lotz
349b8c6a851SMichael Lotz status_t
send_request(usb_device dev,uint8 requestType,uint8 request,uint16 value,uint16 index,uint16 length,void * data,size_t * actualLength)350dd249016SAugustin Cavalier send_request(usb_device dev, uint8 requestType, uint8 request,
3515b0ec61fSMichael Lotz uint16 value, uint16 index, uint16 length, void *data, size_t *actualLength)
352b8c6a851SMichael Lotz {
353d8b4cfc9SRene Gollent TRACE_MODULE("send_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x, "
354dd249016SAugustin Cavalier "%d, %p, %p)\n", dev, requestType, request, value, index, length,
355d8b4cfc9SRene Gollent data, actualLength);
356*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(dev), true);
3575ee91867SAugustin Cavalier if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
35817f83b21SMichael Lotz return B_DEV_INVALID_PIPE;
3595ee91867SAugustin Cavalier Device *device = (Device *)object.Get();
360b8c6a851SMichael Lotz
361dd249016SAugustin Cavalier return device->DefaultPipe()->SendRequest(requestType, request,
3628fedfdfcSMichael Lotz value, index, length, data, length, actualLength);
363b8c6a851SMichael Lotz }
364b8c6a851SMichael Lotz
365b8c6a851SMichael Lotz
366b8c6a851SMichael Lotz status_t
queue_request(usb_device dev,uint8 requestType,uint8 request,uint16 value,uint16 index,uint16 length,void * data,usb_callback_func callback,void * callbackCookie)367dd249016SAugustin Cavalier queue_request(usb_device dev, uint8 requestType, uint8 request,
3685b0ec61fSMichael Lotz uint16 value, uint16 index, uint16 length, void *data,
369b8c6a851SMichael Lotz usb_callback_func callback, void *callbackCookie)
370b8c6a851SMichael Lotz {
371d8b4cfc9SRene Gollent TRACE_MODULE("queue_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x,"
372dd249016SAugustin Cavalier " %u, %p, %p, %p)\n", dev, requestType, request, value, index,
373d8b4cfc9SRene Gollent length, data, callback, callbackCookie);
374*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(dev), true);
3755ee91867SAugustin Cavalier if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
37617f83b21SMichael Lotz return B_DEV_INVALID_PIPE;
3775ee91867SAugustin Cavalier Device *device = (Device *)object.Get();
378b8c6a851SMichael Lotz
379dd249016SAugustin Cavalier return device->DefaultPipe()->QueueRequest(requestType,
3808fedfdfcSMichael Lotz request, value, index, length, data, length, callback, callbackCookie);
381b8c6a851SMichael Lotz }
382b8c6a851SMichael Lotz
383b8c6a851SMichael Lotz
384b8c6a851SMichael Lotz status_t
queue_interrupt(usb_pipe pipe,void * data,size_t dataLength,usb_callback_func callback,void * callbackCookie)3855b0ec61fSMichael Lotz queue_interrupt(usb_pipe pipe, void *data, size_t dataLength,
386b8c6a851SMichael Lotz usb_callback_func callback, void *callbackCookie)
387b8c6a851SMichael Lotz {
388d8b4cfc9SRene Gollent TRACE_MODULE("queue_interrupt(%" B_PRId32 ", %p, %ld, %p, %p)\n",
389f14fe767SMichael Lotz pipe, data, dataLength, callback, callbackCookie);
390*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(pipe), true);
3915ee91867SAugustin Cavalier if (!object.IsSet() || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0)
39217f83b21SMichael Lotz return B_DEV_INVALID_PIPE;
393b8c6a851SMichael Lotz
3945ee91867SAugustin Cavalier return ((InterruptPipe *)object.Get())->QueueInterrupt(data, dataLength,
3955ee91867SAugustin Cavalier callback, callbackCookie);
396b8c6a851SMichael Lotz }
397b8c6a851SMichael Lotz
398b8c6a851SMichael Lotz
399b8c6a851SMichael Lotz status_t
queue_bulk(usb_pipe pipe,void * data,size_t dataLength,usb_callback_func callback,void * callbackCookie)4005b0ec61fSMichael Lotz queue_bulk(usb_pipe pipe, void *data, size_t dataLength,
401b8c6a851SMichael Lotz usb_callback_func callback, void *callbackCookie)
402b8c6a851SMichael Lotz {
403d8b4cfc9SRene Gollent TRACE_MODULE("queue_bulk(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, %p)\n",
404f14fe767SMichael Lotz pipe, data, dataLength, callback, callbackCookie);
405*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(pipe), true);
4065ee91867SAugustin Cavalier if (!object.IsSet() || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
40717f83b21SMichael Lotz return B_DEV_INVALID_PIPE;
408b8c6a851SMichael Lotz
4095ee91867SAugustin Cavalier return ((BulkPipe *)object.Get())->QueueBulk(data, dataLength, callback,
410b8c6a851SMichael Lotz callbackCookie);
411b8c6a851SMichael Lotz }
412b8c6a851SMichael Lotz
413b8c6a851SMichael Lotz
414b8c6a851SMichael Lotz status_t
queue_bulk_v(usb_pipe pipe,iovec * vector,size_t vectorCount,usb_callback_func callback,void * callbackCookie)4155b0ec61fSMichael Lotz queue_bulk_v(usb_pipe pipe, iovec *vector, size_t vectorCount,
4165b0ec61fSMichael Lotz usb_callback_func callback, void *callbackCookie)
417b8c6a851SMichael Lotz {
418d8b4cfc9SRene Gollent TRACE_MODULE("queue_bulk_v(%" B_PRId32 ", %p, %" B_PRIuSIZE " %p, %p)\n",
419f14fe767SMichael Lotz pipe, vector, vectorCount, callback, callbackCookie);
420*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(pipe), true);
4215ee91867SAugustin Cavalier if (!object.IsSet() || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
42217f83b21SMichael Lotz return B_DEV_INVALID_PIPE;
423b8c6a851SMichael Lotz
4245ee91867SAugustin Cavalier return ((BulkPipe *)object.Get())->QueueBulkV(vector, vectorCount,
42555a46882SAugustin Cavalier callback, callbackCookie);
42672457eddSMichael Lotz }
42772457eddSMichael Lotz
42872457eddSMichael Lotz
42972457eddSMichael Lotz status_t
queue_bulk_v_physical(usb_pipe pipe,physical_entry * vector,size_t vectorCount,usb_callback_func callback,void * callbackCookie)43055a46882SAugustin Cavalier queue_bulk_v_physical(usb_pipe pipe, physical_entry *vector, size_t vectorCount,
43172457eddSMichael Lotz usb_callback_func callback, void *callbackCookie)
43272457eddSMichael Lotz {
433d8b4cfc9SRene Gollent TRACE_MODULE("queue_bulk_v_physical(%" B_PRId32 ", %p, %" B_PRIuSIZE
434d8b4cfc9SRene Gollent ", %p, %p)\n", pipe, vector, vectorCount, callback, callbackCookie);
435*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(pipe), true);
4365ee91867SAugustin Cavalier if (!object.IsSet() || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
43772457eddSMichael Lotz return B_DEV_INVALID_PIPE;
43872457eddSMichael Lotz
4395ee91867SAugustin Cavalier return ((BulkPipe *)object.Get())->QueueBulkV(vector, vectorCount,
44055a46882SAugustin Cavalier callback, callbackCookie);
441b8c6a851SMichael Lotz }
442b8c6a851SMichael Lotz
443b8c6a851SMichael Lotz
444b8c6a851SMichael Lotz status_t
queue_isochronous(usb_pipe pipe,void * data,size_t dataLength,usb_iso_packet_descriptor * packetDesc,uint32 packetCount,uint32 * startingFrameNumber,uint32 flags,usb_callback_func callback,void * callbackCookie)4455b0ec61fSMichael Lotz queue_isochronous(usb_pipe pipe, void *data, size_t dataLength,
4461bad4a4eSMichael Lotz usb_iso_packet_descriptor *packetDesc, uint32 packetCount,
4471bad4a4eSMichael Lotz uint32 *startingFrameNumber, uint32 flags, usb_callback_func callback,
4485b0ec61fSMichael Lotz void *callbackCookie)
4495b0ec61fSMichael Lotz {
450d8b4cfc9SRene Gollent TRACE_MODULE("queue_isochronous(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, "
451d8b4cfc9SRene Gollent "%" B_PRId32 ", %p, 0x%08" B_PRIx32 ", %p, %p)\n",
452f14fe767SMichael Lotz pipe, data, dataLength, packetDesc, packetCount, startingFrameNumber,
453f14fe767SMichael Lotz flags, callback, callbackCookie);
454*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(pipe), true);
4555ee91867SAugustin Cavalier if (!object.IsSet() || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
45617f83b21SMichael Lotz return B_DEV_INVALID_PIPE;
4575b0ec61fSMichael Lotz
4585ee91867SAugustin Cavalier return ((IsochronousPipe *)object.Get())->QueueIsochronous(data, dataLength,
4591bad4a4eSMichael Lotz packetDesc, packetCount, startingFrameNumber, flags, callback,
4601bad4a4eSMichael Lotz callbackCookie);
4615b0ec61fSMichael Lotz }
4625b0ec61fSMichael Lotz
4635b0ec61fSMichael Lotz
4645b0ec61fSMichael Lotz status_t
set_pipe_policy(usb_pipe pipe,uint8 maxQueuedPackets,uint16 maxBufferDurationMS,uint16 sampleSize)4655b0ec61fSMichael Lotz set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets,
4665b0ec61fSMichael Lotz uint16 maxBufferDurationMS, uint16 sampleSize)
4675b0ec61fSMichael Lotz {
468d8b4cfc9SRene Gollent TRACE_MODULE("set_pipe_policy(%" B_PRId32 ", %d, %d, %d)\n", pipe,
469d8b4cfc9SRene Gollent maxQueuedPackets, maxBufferDurationMS, sampleSize);
470*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(pipe), true);
4715ee91867SAugustin Cavalier if (!object.IsSet() || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
47217f83b21SMichael Lotz return B_DEV_INVALID_PIPE;
4735b0ec61fSMichael Lotz
4745ee91867SAugustin Cavalier return ((IsochronousPipe *)object.IsSet())->SetPipePolicy(maxQueuedPackets,
47500f6fab9SMichael Lotz maxBufferDurationMS, sampleSize);
4765b0ec61fSMichael Lotz }
4775b0ec61fSMichael Lotz
4785b0ec61fSMichael Lotz
4795b0ec61fSMichael Lotz status_t
cancel_queued_transfers(usb_pipe pipe)4805b0ec61fSMichael Lotz cancel_queued_transfers(usb_pipe pipe)
481b8c6a851SMichael Lotz {
482d8b4cfc9SRene Gollent TRACE_MODULE("cancel_queued_transfers(%" B_PRId32 ")\n", pipe);
483*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(pipe), true);
4845ee91867SAugustin Cavalier if (!object.IsSet() || (object->Type() & USB_OBJECT_PIPE) == 0)
48517f83b21SMichael Lotz return B_DEV_INVALID_PIPE;
4865b0ec61fSMichael Lotz
4875ee91867SAugustin Cavalier return ((Pipe *)object.Get())->CancelQueuedTransfers(false);
488b8c6a851SMichael Lotz }
489b8c6a851SMichael Lotz
490b8c6a851SMichael Lotz
491b8c6a851SMichael Lotz status_t
cancel_queued_requests(usb_device dev)49276ddb69aSJérôme Duval cancel_queued_requests(usb_device dev)
49376ddb69aSJérôme Duval {
49476ddb69aSJérôme Duval TRACE_MODULE("cancel_queued_requests(%" B_PRId32 ")\n", dev);
495*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(dev), true);
49676ddb69aSJérôme Duval if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
49776ddb69aSJérôme Duval return B_DEV_INVALID_PIPE;
49876ddb69aSJérôme Duval Device *device = (Device *)object.Get();
49976ddb69aSJérôme Duval
50076ddb69aSJérôme Duval return device->DefaultPipe()->CancelQueuedTransfers(false);
50176ddb69aSJérôme Duval }
50276ddb69aSJérôme Duval
50376ddb69aSJérôme Duval
50476ddb69aSJérôme Duval status_t
usb_ioctl(uint32 opcode,void * buffer,size_t bufferSize)505b8c6a851SMichael Lotz usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize)
506b8c6a851SMichael Lotz {
507d8b4cfc9SRene Gollent TRACE_MODULE("usb_ioctl(%" B_PRIu32 ", %p, %" B_PRIuSIZE ")\n", opcode,
508d8b4cfc9SRene Gollent buffer, bufferSize);
50964f3c065SMichael Lotz
51064f3c065SMichael Lotz switch (opcode) {
51164f3c065SMichael Lotz case 'DNAM': {
512*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(*(usb_id *)buffer), true);
5135ee91867SAugustin Cavalier if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
5145b0ec61fSMichael Lotz return B_BAD_VALUE;
5155ee91867SAugustin Cavalier Device *device = (Device *)object.Get();
5165b0ec61fSMichael Lotz
51764f3c065SMichael Lotz uint32 index = 0;
518dd249016SAugustin Cavalier return device->BuildDeviceName((char *)buffer, &index,
5195b0ec61fSMichael Lotz bufferSize, NULL);
52064f3c065SMichael Lotz }
52164f3c065SMichael Lotz }
52264f3c065SMichael Lotz
52364f3c065SMichael Lotz return B_DEV_INVALID_IOCTL;
524b8c6a851SMichael Lotz }
525b8c6a851SMichael Lotz
526b8c6a851SMichael Lotz
5277e1490e0SMichael Lotz status_t
get_nth_roothub(uint32 index,usb_device * rootHub)5287e1490e0SMichael Lotz get_nth_roothub(uint32 index, usb_device *rootHub)
5297e1490e0SMichael Lotz {
5307e1490e0SMichael Lotz if (!rootHub)
5317e1490e0SMichael Lotz return B_BAD_VALUE;
5327e1490e0SMichael Lotz
5337e1490e0SMichael Lotz BusManager *busManager = gUSBStack->BusManagerAt(index);
5347e1490e0SMichael Lotz if (!busManager)
5357e1490e0SMichael Lotz return B_ENTRY_NOT_FOUND;
5367e1490e0SMichael Lotz
5377e1490e0SMichael Lotz Hub *hub = busManager->GetRootHub();
5387e1490e0SMichael Lotz if (!hub)
5397e1490e0SMichael Lotz return B_NO_INIT;
5407e1490e0SMichael Lotz
5417e1490e0SMichael Lotz *rootHub = hub->USBID();
5427e1490e0SMichael Lotz return B_OK;
5437e1490e0SMichael Lotz }
5447e1490e0SMichael Lotz
5457e1490e0SMichael Lotz
5467e1490e0SMichael Lotz status_t
get_nth_child(usb_device _hub,uint8 index,usb_device * childDevice)5477e1490e0SMichael Lotz get_nth_child(usb_device _hub, uint8 index, usb_device *childDevice)
5487e1490e0SMichael Lotz {
5497e1490e0SMichael Lotz if (!childDevice)
5507e1490e0SMichael Lotz return B_BAD_VALUE;
5517e1490e0SMichael Lotz
552*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(_hub), true);
5535ee91867SAugustin Cavalier if (!object.IsSet() || (object->Type() & USB_OBJECT_HUB) == 0)
5547e1490e0SMichael Lotz return B_DEV_INVALID_PIPE;
5557e1490e0SMichael Lotz
5565ee91867SAugustin Cavalier Hub *hub = (Hub *)object.Get();
5577e1490e0SMichael Lotz for (uint8 i = 0; i < 8; i++) {
5587e1490e0SMichael Lotz if (hub->ChildAt(i) == NULL)
5597e1490e0SMichael Lotz continue;
5607e1490e0SMichael Lotz
5617e1490e0SMichael Lotz if (index-- > 0)
5627e1490e0SMichael Lotz continue;
5637e1490e0SMichael Lotz
5647e1490e0SMichael Lotz *childDevice = hub->ChildAt(i)->USBID();
5657e1490e0SMichael Lotz return B_OK;
5667e1490e0SMichael Lotz }
5677e1490e0SMichael Lotz
5687e1490e0SMichael Lotz return B_ENTRY_NOT_FOUND;
5697e1490e0SMichael Lotz }
5707e1490e0SMichael Lotz
5717e1490e0SMichael Lotz
5727e1490e0SMichael Lotz status_t
get_device_parent(usb_device _device,usb_device * parentHub,uint8 * portIndex)5737e1490e0SMichael Lotz get_device_parent(usb_device _device, usb_device *parentHub, uint8 *portIndex)
5747e1490e0SMichael Lotz {
5757e1490e0SMichael Lotz if (!parentHub || !portIndex)
5767e1490e0SMichael Lotz return B_BAD_VALUE;
5777e1490e0SMichael Lotz
578*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(_device), true);
5795ee91867SAugustin Cavalier if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0)
5807e1490e0SMichael Lotz return B_DEV_INVALID_PIPE;
5817e1490e0SMichael Lotz
5827e1490e0SMichael Lotz Object *parent = object->Parent();
5837e1490e0SMichael Lotz if (!parent || (parent->Type() & USB_OBJECT_HUB) == 0)
5847e1490e0SMichael Lotz return B_ENTRY_NOT_FOUND;
5857e1490e0SMichael Lotz
5867e1490e0SMichael Lotz Hub *hub = (Hub *)parent;
5877e1490e0SMichael Lotz for (uint8 i = 0; i < 8; i++) {
5885ee91867SAugustin Cavalier if (hub->ChildAt(i) == object.Get()) {
5897e1490e0SMichael Lotz *portIndex = i;
5907e1490e0SMichael Lotz *parentHub = hub->USBID();
5917e1490e0SMichael Lotz return B_OK;
5927e1490e0SMichael Lotz }
5937e1490e0SMichael Lotz }
5947e1490e0SMichael Lotz
5957e1490e0SMichael Lotz return B_ERROR;
5967e1490e0SMichael Lotz }
5977e1490e0SMichael Lotz
5987e1490e0SMichael Lotz
5997e1490e0SMichael Lotz status_t
reset_port(usb_device _hub,uint8 portIndex)6007e1490e0SMichael Lotz reset_port(usb_device _hub, uint8 portIndex)
6017e1490e0SMichael Lotz {
602*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(_hub), true);
6035ee91867SAugustin Cavalier if (!object.IsSet() || (object->Type() & USB_OBJECT_HUB) == 0)
6047e1490e0SMichael Lotz return B_DEV_INVALID_PIPE;
6057e1490e0SMichael Lotz
6065ee91867SAugustin Cavalier Hub *hub = (Hub *)object.Get();
6077e1490e0SMichael Lotz return hub->ResetPort(portIndex);
6087e1490e0SMichael Lotz }
6097e1490e0SMichael Lotz
6107e1490e0SMichael Lotz
6117e1490e0SMichael Lotz status_t
disable_port(usb_device _hub,uint8 portIndex)6127e1490e0SMichael Lotz disable_port(usb_device _hub, uint8 portIndex)
6137e1490e0SMichael Lotz {
614*f7325a93SAugustin Cavalier BReference<Object> object(gUSBStack->GetObject(_hub), true);
6155ee91867SAugustin Cavalier if (!object.IsSet() || (object->Type() & USB_OBJECT_HUB) == 0)
6167e1490e0SMichael Lotz return B_DEV_INVALID_PIPE;
6177e1490e0SMichael Lotz
6185ee91867SAugustin Cavalier Hub *hub = (Hub *)object.Get();
6197e1490e0SMichael Lotz return hub->DisablePort(portIndex);
6207e1490e0SMichael Lotz }
6217e1490e0SMichael Lotz
6227e1490e0SMichael Lotz
62396da8285SMichael Lotz /*
6245b0ec61fSMichael Lotz This module exports the USB API v3
62596da8285SMichael Lotz */
6265b0ec61fSMichael Lotz struct usb_module_info gModuleInfoV3 = {
6271501c2bfSNiels Sascha Reedijk // First the bus_manager_info:
6281501c2bfSNiels Sascha Reedijk {
6291501c2bfSNiels Sascha Reedijk {
63055a46882SAugustin Cavalier "bus_managers/usb/v3.1",
6311501c2bfSNiels Sascha Reedijk B_KEEP_LOADED, // Keep loaded, even if no driver requires it
6321501c2bfSNiels Sascha Reedijk bus_std_ops
6331501c2bfSNiels Sascha Reedijk },
6341501c2bfSNiels Sascha Reedijk NULL // the rescan function
6351501c2bfSNiels Sascha Reedijk },
63696da8285SMichael Lotz
637b8c6a851SMichael Lotz register_driver, // register_driver
638b8c6a851SMichael Lotz install_notify, // install_notify
639b8c6a851SMichael Lotz uninstall_notify, // uninstall_notify
640b8c6a851SMichael Lotz get_device_descriptor, // get_device_descriptor
641b8c6a851SMichael Lotz get_nth_configuration, // get_nth_configuration
642b8c6a851SMichael Lotz get_configuration, // get_configuration
643b8c6a851SMichael Lotz set_configuration, // set_configuration
644b8c6a851SMichael Lotz set_alt_interface, // set_alt_interface
645b8c6a851SMichael Lotz set_feature, // set_feature
646b8c6a851SMichael Lotz clear_feature, // clear_feature
647b8c6a851SMichael Lotz get_status, // get_status
648b8c6a851SMichael Lotz get_descriptor, // get_descriptor
649b8c6a851SMichael Lotz send_request, // send_request
650b8c6a851SMichael Lotz queue_interrupt, // queue_interrupt
651b8c6a851SMichael Lotz queue_bulk, // queue_bulk
6525b0ec61fSMichael Lotz queue_bulk_v, // queue_bulk_v
65355a46882SAugustin Cavalier queue_bulk_v_physical, // queue_bulk_v_physical
654b8c6a851SMichael Lotz queue_isochronous, // queue_isochronous
655b8c6a851SMichael Lotz queue_request, // queue_request
656b8c6a851SMichael Lotz set_pipe_policy, // set_pipe_policy
657b8c6a851SMichael Lotz cancel_queued_transfers, // cancel_queued_transfers
65855a46882SAugustin Cavalier cancel_queued_requests, // cancel_queued_requests
6597e1490e0SMichael Lotz usb_ioctl, // usb_ioctl
6607e1490e0SMichael Lotz get_nth_roothub, // get_nth_roothub
6617e1490e0SMichael Lotz get_nth_child, // get_nth_child
6627e1490e0SMichael Lotz get_device_parent, // get_device_parent
6637e1490e0SMichael Lotz reset_port, // reset_port
66476ddb69aSJérôme Duval disable_port, // disable_port
6651501c2bfSNiels Sascha Reedijk };
6661501c2bfSNiels Sascha Reedijk
66796da8285SMichael Lotz
6685b0ec61fSMichael Lotz //
6695b0ec61fSMichael Lotz // #pragma mark -
6705b0ec61fSMichael Lotz //
6715b0ec61fSMichael Lotz
6725b0ec61fSMichael Lotz
6735b0ec61fSMichael Lotz const usb_device_descriptor *
get_device_descriptor_v2(const void * device)6745b0ec61fSMichael Lotz get_device_descriptor_v2(const void *device)
6755b0ec61fSMichael Lotz {
676d8b4cfc9SRene Gollent return get_device_descriptor((usb_id)(ssize_t)device);
6775b0ec61fSMichael Lotz }
6785b0ec61fSMichael Lotz
6795b0ec61fSMichael Lotz
6805b0ec61fSMichael Lotz const usb_configuration_info *
get_nth_configuration_v2(const void * device,uint index)6815b0ec61fSMichael Lotz get_nth_configuration_v2(const void *device, uint index)
6825b0ec61fSMichael Lotz {
683d8b4cfc9SRene Gollent return get_nth_configuration((usb_id)(ssize_t)device, index);
6845b0ec61fSMichael Lotz }
6855b0ec61fSMichael Lotz
6865b0ec61fSMichael Lotz
6875b0ec61fSMichael Lotz const usb_configuration_info *
get_configuration_v2(const void * device)6885b0ec61fSMichael Lotz get_configuration_v2(const void *device)
6895b0ec61fSMichael Lotz {
690d8b4cfc9SRene Gollent return get_configuration((usb_id)(ssize_t)device);
6915b0ec61fSMichael Lotz }
6925b0ec61fSMichael Lotz
6935b0ec61fSMichael Lotz
6945b0ec61fSMichael Lotz status_t
set_configuration_v2(const void * device,const usb_configuration_info * configuration)6955b0ec61fSMichael Lotz set_configuration_v2(const void *device,
6965b0ec61fSMichael Lotz const usb_configuration_info *configuration)
6975b0ec61fSMichael Lotz {
698d8b4cfc9SRene Gollent return set_configuration((usb_id)(ssize_t)device, configuration);
6995b0ec61fSMichael Lotz }
7005b0ec61fSMichael Lotz
7015b0ec61fSMichael Lotz
7025b0ec61fSMichael Lotz status_t
set_alt_interface_v2(const void * device,const usb_interface_info * interface)7035b0ec61fSMichael Lotz set_alt_interface_v2(const void *device, const usb_interface_info *interface)
7045b0ec61fSMichael Lotz {
705d8b4cfc9SRene Gollent return set_alt_interface((usb_id)(ssize_t)device, interface);
7065b0ec61fSMichael Lotz }
7075b0ec61fSMichael Lotz
7085b0ec61fSMichael Lotz
7095b0ec61fSMichael Lotz status_t
set_feature_v2(const void * object,uint16 selector)7105b0ec61fSMichael Lotz set_feature_v2(const void *object, uint16 selector)
7115b0ec61fSMichael Lotz {
712d8b4cfc9SRene Gollent return set_feature((usb_id)(ssize_t)object, selector);
7135b0ec61fSMichael Lotz }
7145b0ec61fSMichael Lotz
7155b0ec61fSMichael Lotz
7165b0ec61fSMichael Lotz status_t
clear_feature_v2(const void * object,uint16 selector)7175b0ec61fSMichael Lotz clear_feature_v2(const void *object, uint16 selector)
7185b0ec61fSMichael Lotz {
719d8b4cfc9SRene Gollent return clear_feature((usb_id)(ssize_t)object, selector);
7205b0ec61fSMichael Lotz }
7215b0ec61fSMichael Lotz
7225b0ec61fSMichael Lotz
7235b0ec61fSMichael Lotz status_t
get_status_v2(const void * object,uint16 * status)7245b0ec61fSMichael Lotz get_status_v2(const void *object, uint16 *status)
7255b0ec61fSMichael Lotz {
726d8b4cfc9SRene Gollent return get_status((usb_id)(ssize_t)object, status);
7275b0ec61fSMichael Lotz }
7285b0ec61fSMichael Lotz
7295b0ec61fSMichael Lotz
7305b0ec61fSMichael Lotz status_t
get_descriptor_v2(const void * device,uint8 type,uint8 index,uint16 languageID,void * data,size_t dataLength,size_t * actualLength)7315b0ec61fSMichael Lotz get_descriptor_v2(const void *device, uint8 type, uint8 index,
7325b0ec61fSMichael Lotz uint16 languageID, void *data, size_t dataLength, size_t *actualLength)
7335b0ec61fSMichael Lotz {
734d8b4cfc9SRene Gollent return get_descriptor((usb_id)(ssize_t)device, type, index, languageID, data,
7355b0ec61fSMichael Lotz dataLength, actualLength);
7365b0ec61fSMichael Lotz }
7375b0ec61fSMichael Lotz
7385b0ec61fSMichael Lotz
7395b0ec61fSMichael Lotz status_t
send_request_v2(const void * device,uint8 requestType,uint8 request,uint16 value,uint16 index,uint16 length,void * data,size_t,size_t * actualLength)7405b0ec61fSMichael Lotz send_request_v2(const void *device, uint8 requestType, uint8 request,
7415b0ec61fSMichael Lotz uint16 value, uint16 index, uint16 length, void *data,
7425b0ec61fSMichael Lotz size_t /*dataLength*/, size_t *actualLength)
7435b0ec61fSMichael Lotz {
744d8b4cfc9SRene Gollent return send_request((usb_id)(ssize_t)device, requestType, request, value, index,
7455b0ec61fSMichael Lotz length, data, actualLength);
7465b0ec61fSMichael Lotz }
7475b0ec61fSMichael Lotz
7485b0ec61fSMichael Lotz
7495b0ec61fSMichael Lotz status_t
queue_request_v2(const void * device,uint8 requestType,uint8 request,uint16 value,uint16 index,uint16 length,void * data,size_t,usb_callback_func callback,void * callbackCookie)7505b0ec61fSMichael Lotz queue_request_v2(const void *device, uint8 requestType, uint8 request,
7515b0ec61fSMichael Lotz uint16 value, uint16 index, uint16 length, void *data,
7525b0ec61fSMichael Lotz size_t /*dataLength*/, usb_callback_func callback, void *callbackCookie)
7535b0ec61fSMichael Lotz {
754d8b4cfc9SRene Gollent return queue_request((usb_id)(ssize_t)device, requestType, request, value, index,
7555b0ec61fSMichael Lotz length, data, callback, callbackCookie);
7565b0ec61fSMichael Lotz }
7575b0ec61fSMichael Lotz
7585b0ec61fSMichael Lotz
7595b0ec61fSMichael Lotz status_t
queue_interrupt_v2(const void * pipe,void * data,size_t dataLength,usb_callback_func callback,void * callbackCookie)7605b0ec61fSMichael Lotz queue_interrupt_v2(const void *pipe, void *data, size_t dataLength,
7615b0ec61fSMichael Lotz usb_callback_func callback, void *callbackCookie)
7625b0ec61fSMichael Lotz {
763d8b4cfc9SRene Gollent return queue_interrupt((usb_id)(ssize_t)pipe, data, dataLength, callback,
7645b0ec61fSMichael Lotz callbackCookie);
7655b0ec61fSMichael Lotz }
7665b0ec61fSMichael Lotz
7675b0ec61fSMichael Lotz
7685b0ec61fSMichael Lotz status_t
queue_bulk_v2(const void * pipe,void * data,size_t dataLength,usb_callback_func callback,void * callbackCookie)7695b0ec61fSMichael Lotz queue_bulk_v2(const void *pipe, void *data, size_t dataLength,
7705b0ec61fSMichael Lotz usb_callback_func callback, void *callbackCookie)
7715b0ec61fSMichael Lotz {
772d8b4cfc9SRene Gollent return queue_bulk((usb_id)(ssize_t)pipe, data, dataLength, callback,
7735b0ec61fSMichael Lotz callbackCookie);
7745b0ec61fSMichael Lotz }
7755b0ec61fSMichael Lotz
7765b0ec61fSMichael Lotz
7775b0ec61fSMichael Lotz status_t
queue_isochronous_v2(const void * pipe,void * data,size_t dataLength,rlea * rleArray,uint16 bufferDurationMS,usb_callback_func callback,void * callbackCookie)7785b0ec61fSMichael Lotz queue_isochronous_v2(const void *pipe, void *data, size_t dataLength,
7795b0ec61fSMichael Lotz rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback,
7805b0ec61fSMichael Lotz void *callbackCookie)
7815b0ec61fSMichael Lotz {
7821bad4a4eSMichael Lotz // ToDo: convert rlea to usb_iso_packet_descriptor
7831bad4a4eSMichael Lotz // ToDo: use a flag to indicate that the callback shall produce a rlea
7841bad4a4eSMichael Lotz usb_iso_packet_descriptor *packetDesc = NULL;
785d8b4cfc9SRene Gollent return queue_isochronous((usb_id)(ssize_t)pipe, data, dataLength, packetDesc, 0,
7861bad4a4eSMichael Lotz NULL, 0, callback, callbackCookie);
7875b0ec61fSMichael Lotz }
7885b0ec61fSMichael Lotz
7895b0ec61fSMichael Lotz
7905b0ec61fSMichael Lotz status_t
set_pipe_policy_v2(const void * pipe,uint8 maxQueuedPackets,uint16 maxBufferDurationMS,uint16 sampleSize)7915b0ec61fSMichael Lotz set_pipe_policy_v2(const void *pipe, uint8 maxQueuedPackets,
7925b0ec61fSMichael Lotz uint16 maxBufferDurationMS, uint16 sampleSize)
7935b0ec61fSMichael Lotz {
794d8b4cfc9SRene Gollent return set_pipe_policy((usb_id)(ssize_t)pipe, maxQueuedPackets, maxBufferDurationMS,
7955b0ec61fSMichael Lotz sampleSize);
7965b0ec61fSMichael Lotz }
7975b0ec61fSMichael Lotz
7985b0ec61fSMichael Lotz
7995b0ec61fSMichael Lotz status_t
cancel_queued_transfers_v2(const void * pipe)8005b0ec61fSMichael Lotz cancel_queued_transfers_v2(const void *pipe)
8015b0ec61fSMichael Lotz {
802d8b4cfc9SRene Gollent return cancel_queued_transfers((usb_id)(ssize_t)pipe);
8035b0ec61fSMichael Lotz }
8045b0ec61fSMichael Lotz
8055b0ec61fSMichael Lotz
8065b0ec61fSMichael Lotz struct usb_module_info_v2 {
8075b0ec61fSMichael Lotz bus_manager_info binfo;
8085b0ec61fSMichael Lotz status_t (*register_driver)(const char *, const usb_support_descriptor *, size_t, const char *);
8095b0ec61fSMichael Lotz status_t (*install_notify)(const char *, const usb_notify_hooks *);
8105b0ec61fSMichael Lotz status_t (*uninstall_notify)(const char *);
8115b0ec61fSMichael Lotz const usb_device_descriptor *(*get_device_descriptor)(const void *);
8125b0ec61fSMichael Lotz const usb_configuration_info *(*get_nth_configuration)(const void *, uint);
8135b0ec61fSMichael Lotz const usb_configuration_info *(*get_configuration)(const void *);
8145b0ec61fSMichael Lotz status_t (*set_configuration)(const void *, const usb_configuration_info *);
8155b0ec61fSMichael Lotz status_t (*set_alt_interface)(const void *, const usb_interface_info *);
8165b0ec61fSMichael Lotz status_t (*set_feature)(const void *, uint16);
8175b0ec61fSMichael Lotz status_t (*clear_feature)(const void *, uint16);
8185b0ec61fSMichael Lotz status_t (*get_status)(const void *, uint16 *);
8195b0ec61fSMichael Lotz status_t (*get_descriptor)(const void *, uint8, uint8, uint16, void *, size_t, size_t *);
8205b0ec61fSMichael Lotz status_t (*send_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, size_t *);
8215b0ec61fSMichael Lotz status_t (*queue_interrupt)(const void *, void *, size_t, usb_callback_func, void *);
8225b0ec61fSMichael Lotz status_t (*queue_bulk)(const void *, void *, size_t, usb_callback_func, void *);
8235b0ec61fSMichael Lotz status_t (*queue_isochronous)(const void *, void *, size_t, rlea *, uint16, usb_callback_func, void *);
8245b0ec61fSMichael Lotz status_t (*queue_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, usb_callback_func, void *);
8255b0ec61fSMichael Lotz status_t (*set_pipe_policy)(const void *, uint8, uint16, uint16);
8265b0ec61fSMichael Lotz status_t (*cancel_queued_transfers)(const void *);
8275b0ec61fSMichael Lotz status_t (*usb_ioctl)(uint32 opcode, void *,size_t);
8285b0ec61fSMichael Lotz };
8295b0ec61fSMichael Lotz
8305b0ec61fSMichael Lotz
8315b0ec61fSMichael Lotz /*
8325b0ec61fSMichael Lotz This module exports the USB API v2
8335b0ec61fSMichael Lotz */
8345b0ec61fSMichael Lotz struct usb_module_info_v2 gModuleInfoV2 = {
8355b0ec61fSMichael Lotz // First the bus_manager_info:
8365b0ec61fSMichael Lotz {
8375b0ec61fSMichael Lotz {
8385b0ec61fSMichael Lotz "bus_managers/usb/v2",
8395b0ec61fSMichael Lotz B_KEEP_LOADED, // Keep loaded, even if no driver requires it
8405b0ec61fSMichael Lotz bus_std_ops
8415b0ec61fSMichael Lotz },
8425b0ec61fSMichael Lotz NULL // the rescan function
8435b0ec61fSMichael Lotz },
8445b0ec61fSMichael Lotz
8455b0ec61fSMichael Lotz register_driver, // register_driver
8465b0ec61fSMichael Lotz install_notify, // install_notify
8475b0ec61fSMichael Lotz uninstall_notify, // uninstall_notify
8485b0ec61fSMichael Lotz get_device_descriptor_v2, // get_device_descriptor
8495b0ec61fSMichael Lotz get_nth_configuration_v2, // get_nth_configuration
8505b0ec61fSMichael Lotz get_configuration_v2, // get_configuration
8515b0ec61fSMichael Lotz set_configuration_v2, // set_configuration
8525b0ec61fSMichael Lotz set_alt_interface_v2, // set_alt_interface
8535b0ec61fSMichael Lotz set_feature_v2, // set_feature
8545b0ec61fSMichael Lotz clear_feature_v2, // clear_feature
8555b0ec61fSMichael Lotz get_status_v2, // get_status
8565b0ec61fSMichael Lotz get_descriptor_v2, // get_descriptor
8575b0ec61fSMichael Lotz send_request_v2, // send_request
8585b0ec61fSMichael Lotz queue_interrupt_v2, // queue_interrupt
8595b0ec61fSMichael Lotz queue_bulk_v2, // queue_bulk
8605b0ec61fSMichael Lotz queue_isochronous_v2, // queue_isochronous
8615b0ec61fSMichael Lotz queue_request_v2, // queue_request
8625b0ec61fSMichael Lotz set_pipe_policy_v2, // set_pipe_policy
8635b0ec61fSMichael Lotz cancel_queued_transfers_v2, // cancel_queued_transfers
8645b0ec61fSMichael Lotz usb_ioctl // usb_ioctl
8655b0ec61fSMichael Lotz };
8665b0ec61fSMichael Lotz
8675b0ec61fSMichael Lotz
8685b0ec61fSMichael Lotz //
8695b0ec61fSMichael Lotz // #pragma mark -
8705b0ec61fSMichael Lotz //
8715b0ec61fSMichael Lotz
8725b0ec61fSMichael Lotz
8731eebcfa0SJérôme Duval status_t
usb_added_device(device_node * parent)8741eebcfa0SJérôme Duval usb_added_device(device_node *parent)
8751eebcfa0SJérôme Duval {
8761eebcfa0SJérôme Duval return B_OK;
8771eebcfa0SJérôme Duval }
8781eebcfa0SJérôme Duval
8791eebcfa0SJérôme Duval
8801eebcfa0SJérôme Duval status_t
usb_get_stack(void ** stack)8811eebcfa0SJérôme Duval usb_get_stack(void** stack)
8821eebcfa0SJérôme Duval {
8831eebcfa0SJérôme Duval *stack = gUSBStack;
8841eebcfa0SJérôme Duval return B_OK;
8851eebcfa0SJérôme Duval }
8861eebcfa0SJérôme Duval
8871eebcfa0SJérôme Duval
8881eebcfa0SJérôme Duval usb_for_controller_interface gForControllerModule = {
8891eebcfa0SJérôme Duval {
8901eebcfa0SJérôme Duval {
8911eebcfa0SJérôme Duval USB_FOR_CONTROLLER_MODULE_NAME,
8921eebcfa0SJérôme Duval B_KEEP_LOADED,
8931eebcfa0SJérôme Duval &bus_std_ops
8941eebcfa0SJérôme Duval },
8951eebcfa0SJérôme Duval
8961eebcfa0SJérôme Duval NULL, // supported devices
8971eebcfa0SJérôme Duval usb_added_device,
8981eebcfa0SJérôme Duval NULL,
8991eebcfa0SJérôme Duval NULL,
9001eebcfa0SJérôme Duval NULL
9011eebcfa0SJérôme Duval },
9021eebcfa0SJérôme Duval
9031eebcfa0SJérôme Duval usb_get_stack,
9041eebcfa0SJérôme Duval };
9051eebcfa0SJérôme Duval
9061eebcfa0SJérôme Duval
907e6ce95c5SJérôme Duval static status_t
device_std_ops(int32 op,...)908e6ce95c5SJérôme Duval device_std_ops(int32 op, ...)
909e6ce95c5SJérôme Duval {
910e6ce95c5SJérôme Duval switch (op) {
911e6ce95c5SJérôme Duval case B_MODULE_INIT:
912e6ce95c5SJérôme Duval {
913e6ce95c5SJérôme Duval // Link to USB bus.
914e6ce95c5SJérôme Duval // USB device driver must have USB bus loaded, but it calls its
915e6ce95c5SJérôme Duval // functions directly instead via official interface, so this
916e6ce95c5SJérôme Duval // pointer is never read.
917e6ce95c5SJérôme Duval module_info *dummy;
91855a46882SAugustin Cavalier return get_module(B_USB_MODULE_NAME, &dummy);
919e6ce95c5SJérôme Duval }
920e6ce95c5SJérôme Duval case B_MODULE_UNINIT:
92155a46882SAugustin Cavalier return put_module(B_USB_MODULE_NAME);
922e6ce95c5SJérôme Duval
923e6ce95c5SJérôme Duval default:
924e6ce95c5SJérôme Duval return B_ERROR;
925e6ce95c5SJérôme Duval }
926e6ce95c5SJérôme Duval }
927e6ce95c5SJérôme Duval
928e6ce95c5SJérôme Duval
929e6ce95c5SJérôme Duval usb_device_interface gUSBDeviceModule = {
930e6ce95c5SJérôme Duval {
931e6ce95c5SJérôme Duval {
932e6ce95c5SJérôme Duval USB_DEVICE_MODULE_NAME,
933e6ce95c5SJérôme Duval 0,
934e6ce95c5SJérôme Duval device_std_ops
935e6ce95c5SJérôme Duval },
936e6ce95c5SJérôme Duval
937e6ce95c5SJérôme Duval NULL, // supported devices
938e6ce95c5SJérôme Duval NULL, // register node
939e6ce95c5SJérôme Duval NULL, //usb_init_device,
940e6ce95c5SJérôme Duval NULL, // (void (*)(void *)) usb_uninit_device,
941e6ce95c5SJérôme Duval NULL, // register child devices
942e6ce95c5SJérôme Duval NULL, // rescan
943e6ce95c5SJérôme Duval NULL// (void (*)(void *)) usb_device_removed
944e6ce95c5SJérôme Duval },
945e6ce95c5SJérôme Duval };
946e6ce95c5SJérôme Duval
947e6ce95c5SJérôme Duval
948e6ce95c5SJérôme Duval module_dependency module_dependencies[] = {
949e6ce95c5SJérôme Duval { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager },
950e6ce95c5SJérôme Duval {}
951e6ce95c5SJérôme Duval };
952e6ce95c5SJérôme Duval
953e6ce95c5SJérôme Duval
9541501c2bfSNiels Sascha Reedijk module_info *modules[] = {
9555b0ec61fSMichael Lotz (module_info *)&gModuleInfoV2,
9565b0ec61fSMichael Lotz (module_info *)&gModuleInfoV3,
9571eebcfa0SJérôme Duval (module_info *)&gForControllerModule,
958e6ce95c5SJérôme Duval (module_info *)&gUSBDeviceModule,
9591501c2bfSNiels Sascha Reedijk NULL
9601501c2bfSNiels Sascha Reedijk };
961