2 * Copyright 2003-2006, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Michael Lotz <mmlr@mlotz.ch>
10 #include <util/kernel_cpp.h>
11 #include "usb_private.h"
14 #define USB_MODULE_NAME "module"
16 Stack
*gUSBStack
= NULL
;
19 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
21 debug_get_pipe_for_id(int argc
, char **argv
)
23 if (gUSBStack
== NULL
)
26 if (!is_debug_variable_defined("_usbPipeID"))
29 uint64 id
= get_debug_variable("_usbPipeID", 0);
30 Object
*object
= gUSBStack
->GetObjectNoLock((usb_id
)id
);
31 if (!object
|| (object
->Type() & USB_OBJECT_PIPE
) == 0)
34 // check if we support debug transfers for this pipe (only on UHCI for now)
35 if (object
->GetBusManager()->TypeName()[0] != 'u')
38 set_debug_variable("_usbPipe", (uint64
)object
);
45 bus_std_ops(int32 op
, ...)
49 TRACE_MODULE("init\n");
53 #ifdef HAIKU_TARGET_PLATFORM_BEOS
54 // This code is to handle plain R5 (non-BONE) where the same module
55 // gets loaded multiple times (once for each exported module
56 // interface, the USB v2 and v3 API in our case). We don't want to
57 // ever create multiple stacks however, so we "share" the same stack
58 // for both modules by storing it's address in a shared area.
60 area_id shared
= find_area("shared usb stack");
61 if (shared
>= B_OK
&& clone_area("usb stack clone", &address
,
62 B_ANY_KERNEL_ADDRESS
, B_KERNEL_READ_AREA
, shared
) >= B_OK
) {
63 gUSBStack
= *((Stack
**)address
);
64 TRACE_MODULE("found shared stack at %p\n", gUSBStack
);
70 set_dprintf_enabled(true);
71 #ifndef HAIKU_TARGET_PLATFORM_HAIKU
72 load_driver_symbols("usb");
75 Stack
*stack
= new(std::nothrow
) Stack();
76 TRACE_MODULE("usb_module: stack created %p\n", stack
);
80 if (stack
->InitCheck() != B_OK
) {
87 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
88 add_debugger_command("get_usb_pipe_for_id",
89 &debug_get_pipe_for_id
,
90 "Gets the config for a USB pipe");
91 #elif HAIKU_TARGET_PLATFORM_BEOS
92 // Plain R5 workaround, see comment above.
93 shared
= create_area("shared usb stack", &address
,
94 B_ANY_KERNEL_ADDRESS
, B_PAGE_SIZE
, B_NO_LOCK
,
97 *((Stack
**)address
) = gUSBStack
;
102 case B_MODULE_UNINIT
:
103 TRACE_MODULE("uninit\n");
107 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
108 remove_debugger_command("get_usb_pipe_for_id",
109 &debug_get_pipe_for_id
);
122 register_driver(const char *driverName
,
123 const usb_support_descriptor
*descriptors
,
124 size_t count
, const char *optionalRepublishDriverName
)
126 return gUSBStack
->RegisterDriver(driverName
, descriptors
, count
,
127 optionalRepublishDriverName
);
132 install_notify(const char *driverName
, const usb_notify_hooks
*hooks
)
134 return gUSBStack
->InstallNotify(driverName
, hooks
);
139 uninstall_notify(const char *driverName
)
141 return gUSBStack
->UninstallNotify(driverName
);
145 const usb_device_descriptor
*
146 get_device_descriptor(usb_device device
)
148 TRACE_MODULE("get_device_descriptor(%ld)\n", device
);
149 Object
*object
= gUSBStack
->GetObject(device
);
150 if (!object
|| (object
->Type() & USB_OBJECT_DEVICE
) == 0)
153 return ((Device
*)object
)->DeviceDescriptor();
157 const usb_configuration_info
*
158 get_nth_configuration(usb_device device
, uint32 index
)
160 TRACE_MODULE("get_nth_configuration(%ld, %lu)\n", device
, index
);
161 Object
*object
= gUSBStack
->GetObject(device
);
162 if (!object
|| (object
->Type() & USB_OBJECT_DEVICE
) == 0)
165 return ((Device
*)object
)->ConfigurationAt((int32
)index
);
169 const usb_configuration_info
*
170 get_configuration(usb_device device
)
172 TRACE_MODULE("get_configuration(%ld)\n", device
);
173 Object
*object
= gUSBStack
->GetObject(device
);
174 if (!object
|| (object
->Type() & USB_OBJECT_DEVICE
) == 0)
177 return ((Device
*)object
)->Configuration();
182 set_configuration(usb_device device
,
183 const usb_configuration_info
*configuration
)
185 TRACE_MODULE("set_configuration(%ld, %p)\n", device
, configuration
);
186 Object
*object
= gUSBStack
->GetObject(device
);
187 if (!object
|| (object
->Type() & USB_OBJECT_DEVICE
) == 0)
188 return B_DEV_INVALID_PIPE
;
190 return ((Device
*)object
)->SetConfiguration(configuration
);
195 set_alt_interface(usb_device device
, const usb_interface_info
*interface
)
197 TRACE_MODULE("set_alt_interface(%ld, %p)\n", device
, interface
);
198 Object
*object
= gUSBStack
->GetObject(device
);
199 if (!object
|| (object
->Type() & USB_OBJECT_DEVICE
) == 0)
200 return B_DEV_INVALID_PIPE
;
202 return ((Device
*)object
)->SetAltInterface(interface
);
207 set_feature(usb_id handle
, uint16 selector
)
209 TRACE_MODULE("set_feature(%ld, %d)\n", handle
, selector
);
210 Object
*object
= gUSBStack
->GetObject(handle
);
212 return B_DEV_INVALID_PIPE
;
214 return object
->SetFeature(selector
);
219 clear_feature(usb_id handle
, uint16 selector
)
221 TRACE_MODULE("clear_feature(%ld, %d)\n", handle
, selector
);
222 Object
*object
= gUSBStack
->GetObject(handle
);
224 return B_DEV_INVALID_PIPE
;
226 return object
->ClearFeature(selector
);
231 get_status(usb_id handle
, uint16
*status
)
233 TRACE_MODULE("get_status(%ld, %p)\n", handle
, status
);
237 Object
*object
= gUSBStack
->GetObject(handle
);
239 return B_DEV_INVALID_PIPE
;
241 return object
->GetStatus(status
);
246 get_descriptor(usb_device device
, uint8 type
, uint8 index
, uint16 languageID
,
247 void *data
, size_t dataLength
, size_t *actualLength
)
249 TRACE_MODULE("get_descriptor(%ld, 0x%02x, 0x%02x, 0x%04x, %p, %ld, %p)\n",
250 device
, type
, index
, languageID
, data
, dataLength
, actualLength
);
251 Object
*object
= gUSBStack
->GetObject(device
);
252 if (!object
|| (object
->Type() & USB_OBJECT_DEVICE
) == 0)
253 return B_DEV_INVALID_PIPE
;
255 return ((Device
*)object
)->GetDescriptor(type
, index
, languageID
,
256 data
, dataLength
, actualLength
);
261 send_request(usb_device device
, uint8 requestType
, uint8 request
,
262 uint16 value
, uint16 index
, uint16 length
, void *data
, size_t *actualLength
)
264 TRACE_MODULE("send_request(%ld, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %d, %p, %p)\n",
265 device
, requestType
, request
, value
, index
, length
, data
, actualLength
);
266 Object
*object
= gUSBStack
->GetObject(device
);
267 if (!object
|| (object
->Type() & USB_OBJECT_DEVICE
) == 0)
268 return B_DEV_INVALID_PIPE
;
270 return ((Device
*)object
)->DefaultPipe()->SendRequest(requestType
, request
,
271 value
, index
, length
, data
, length
, actualLength
);
276 queue_request(usb_device device
, uint8 requestType
, uint8 request
,
277 uint16 value
, uint16 index
, uint16 length
, void *data
,
278 usb_callback_func callback
, void *callbackCookie
)
280 TRACE_MODULE("queue_request(%ld, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %u, %p, %p, %p)\n",
281 device
, requestType
, request
, value
, index
, length
, data
, callback
,
283 Object
*object
= gUSBStack
->GetObject(device
);
284 if (!object
|| (object
->Type() & USB_OBJECT_DEVICE
) == 0)
285 return B_DEV_INVALID_PIPE
;
287 return ((Device
*)object
)->DefaultPipe()->QueueRequest(requestType
,
288 request
, value
, index
, length
, data
, length
, callback
, callbackCookie
);
293 queue_interrupt(usb_pipe pipe
, void *data
, size_t dataLength
,
294 usb_callback_func callback
, void *callbackCookie
)
296 TRACE_MODULE("queue_interrupt(%ld, %p, %ld, %p, %p)\n",
297 pipe
, data
, dataLength
, callback
, callbackCookie
);
298 Object
*object
= gUSBStack
->GetObject(pipe
);
299 if (!object
|| (object
->Type() & USB_OBJECT_INTERRUPT_PIPE
) == 0)
300 return B_DEV_INVALID_PIPE
;
302 return ((InterruptPipe
*)object
)->QueueInterrupt(data
, dataLength
, callback
,
308 queue_bulk(usb_pipe pipe
, void *data
, size_t dataLength
,
309 usb_callback_func callback
, void *callbackCookie
)
311 TRACE_MODULE("queue_bulk(%ld, %p, %ld, %p, %p)\n",
312 pipe
, data
, dataLength
, callback
, callbackCookie
);
313 Object
*object
= gUSBStack
->GetObject(pipe
);
314 if (!object
|| (object
->Type() & USB_OBJECT_BULK_PIPE
) == 0)
315 return B_DEV_INVALID_PIPE
;
317 return ((BulkPipe
*)object
)->QueueBulk(data
, dataLength
, callback
,
323 queue_bulk_v(usb_pipe pipe
, iovec
*vector
, size_t vectorCount
,
324 usb_callback_func callback
, void *callbackCookie
)
326 TRACE_MODULE("queue_bulk_v(%ld, %p, %ld, %p, %p)\n",
327 pipe
, vector
, vectorCount
, callback
, callbackCookie
);
328 Object
*object
= gUSBStack
->GetObject(pipe
);
329 if (!object
|| (object
->Type() & USB_OBJECT_BULK_PIPE
) == 0)
330 return B_DEV_INVALID_PIPE
;
332 return ((BulkPipe
*)object
)->QueueBulkV(vector
, vectorCount
, callback
,
333 callbackCookie
, false);
338 queue_bulk_v_physical(usb_pipe pipe
, iovec
*vector
, size_t vectorCount
,
339 usb_callback_func callback
, void *callbackCookie
)
341 TRACE_MODULE("queue_bulk_v_physical(%ld, %p, %ld, %p, %p)\n",
342 pipe
, vector
, vectorCount
, callback
, callbackCookie
);
343 Object
*object
= gUSBStack
->GetObject(pipe
);
344 if (!object
|| (object
->Type() & USB_OBJECT_BULK_PIPE
) == 0)
345 return B_DEV_INVALID_PIPE
;
347 return ((BulkPipe
*)object
)->QueueBulkV(vector
, vectorCount
, callback
,
348 callbackCookie
, true);
353 queue_isochronous(usb_pipe pipe
, void *data
, size_t dataLength
,
354 usb_iso_packet_descriptor
*packetDesc
, uint32 packetCount
,
355 uint32
*startingFrameNumber
, uint32 flags
, usb_callback_func callback
,
356 void *callbackCookie
)
358 TRACE_MODULE("queue_isochronous(%ld, %p, %ld, %p, %ld, %p, 0x%08lx, %p, %p)\n",
359 pipe
, data
, dataLength
, packetDesc
, packetCount
, startingFrameNumber
,
360 flags
, callback
, callbackCookie
);
361 Object
*object
= gUSBStack
->GetObject(pipe
);
362 if (!object
|| (object
->Type() & USB_OBJECT_ISO_PIPE
) == 0)
363 return B_DEV_INVALID_PIPE
;
365 return ((IsochronousPipe
*)object
)->QueueIsochronous(data
, dataLength
,
366 packetDesc
, packetCount
, startingFrameNumber
, flags
, callback
,
372 set_pipe_policy(usb_pipe pipe
, uint8 maxQueuedPackets
,
373 uint16 maxBufferDurationMS
, uint16 sampleSize
)
375 TRACE_MODULE("set_pipe_policy(%ld, %d, %d, %d)\n", pipe
, maxQueuedPackets
,
376 maxBufferDurationMS
, sampleSize
);
377 Object
*object
= gUSBStack
->GetObject(pipe
);
378 if (!object
|| (object
->Type() & USB_OBJECT_ISO_PIPE
) == 0)
379 return B_DEV_INVALID_PIPE
;
381 return ((IsochronousPipe
*)object
)->SetPipePolicy(maxQueuedPackets
,
382 maxBufferDurationMS
, sampleSize
);
387 cancel_queued_transfers(usb_pipe pipe
)
389 TRACE_MODULE("cancel_queued_transfers(%ld)\n", pipe
);
390 Object
*object
= gUSBStack
->GetObject(pipe
);
391 if (!object
|| (object
->Type() & USB_OBJECT_PIPE
) == 0)
392 return B_DEV_INVALID_PIPE
;
394 return ((Pipe
*)object
)->CancelQueuedTransfers(false);
399 usb_ioctl(uint32 opcode
, void *buffer
, size_t bufferSize
)
401 TRACE_MODULE("usb_ioctl(%lu, %p, %ld)\n", opcode
, buffer
, bufferSize
);
405 Object
*object
= gUSBStack
->GetObject(*(usb_id
*)buffer
);
406 if (!object
|| (object
->Type() & USB_OBJECT_DEVICE
) == 0)
410 return ((Device
*)object
)->BuildDeviceName((char *)buffer
, &index
,
415 return B_DEV_INVALID_IOCTL
;
420 get_nth_roothub(uint32 index
, usb_device
*rootHub
)
425 BusManager
*busManager
= gUSBStack
->BusManagerAt(index
);
427 return B_ENTRY_NOT_FOUND
;
429 Hub
*hub
= busManager
->GetRootHub();
433 *rootHub
= hub
->USBID();
439 get_nth_child(usb_device _hub
, uint8 index
, usb_device
*childDevice
)
444 Object
*object
= gUSBStack
->GetObject(_hub
);
445 if (!object
|| (object
->Type() & USB_OBJECT_HUB
) == 0)
446 return B_DEV_INVALID_PIPE
;
448 Hub
*hub
= (Hub
*)object
;
449 for (uint8 i
= 0; i
< 8; i
++) {
450 if (hub
->ChildAt(i
) == NULL
)
456 *childDevice
= hub
->ChildAt(i
)->USBID();
460 return B_ENTRY_NOT_FOUND
;
465 get_device_parent(usb_device _device
, usb_device
*parentHub
, uint8
*portIndex
)
467 if (!parentHub
|| !portIndex
)
470 Object
*object
= gUSBStack
->GetObject(_device
);
471 if (!object
|| (object
->Type() & USB_OBJECT_DEVICE
) == 0)
472 return B_DEV_INVALID_PIPE
;
474 Object
*parent
= object
->Parent();
475 if (!parent
|| (parent
->Type() & USB_OBJECT_HUB
) == 0)
476 return B_ENTRY_NOT_FOUND
;
478 Hub
*hub
= (Hub
*)parent
;
479 for (uint8 i
= 0; i
< 8; i
++) {
480 if (hub
->ChildAt(i
) == object
) {
482 *parentHub
= hub
->USBID();
492 reset_port(usb_device _hub
, uint8 portIndex
)
494 Object
*object
= gUSBStack
->GetObject(_hub
);
495 if (!object
|| (object
->Type() & USB_OBJECT_HUB
) == 0)
496 return B_DEV_INVALID_PIPE
;
498 Hub
*hub
= (Hub
*)object
;
499 return hub
->ResetPort(portIndex
);
504 disable_port(usb_device _hub
, uint8 portIndex
)
506 Object
*object
= gUSBStack
->GetObject(_hub
);
507 if (!object
|| (object
->Type() & USB_OBJECT_HUB
) == 0)
508 return B_DEV_INVALID_PIPE
;
510 Hub
*hub
= (Hub
*)object
;
511 return hub
->DisablePort(portIndex
);
516 This module exports the USB API v3
518 struct usb_module_info gModuleInfoV3
= {
519 // First the bus_manager_info:
522 "bus_managers/usb/v3",
523 B_KEEP_LOADED
, // Keep loaded, even if no driver requires it
526 NULL
// the rescan function
529 register_driver
, // register_driver
530 install_notify
, // install_notify
531 uninstall_notify
, // uninstall_notify
532 get_device_descriptor
, // get_device_descriptor
533 get_nth_configuration
, // get_nth_configuration
534 get_configuration
, // get_configuration
535 set_configuration
, // set_configuration
536 set_alt_interface
, // set_alt_interface
537 set_feature
, // set_feature
538 clear_feature
, // clear_feature
539 get_status
, // get_status
540 get_descriptor
, // get_descriptor
541 send_request
, // send_request
542 queue_interrupt
, // queue_interrupt
543 queue_bulk
, // queue_bulk
544 queue_bulk_v
, // queue_bulk_v
545 queue_isochronous
, // queue_isochronous
546 queue_request
, // queue_request
547 set_pipe_policy
, // set_pipe_policy
548 cancel_queued_transfers
, // cancel_queued_transfers
549 usb_ioctl
, // usb_ioctl
550 get_nth_roothub
, // get_nth_roothub
551 get_nth_child
, // get_nth_child
552 get_device_parent
, // get_device_parent
553 reset_port
, // reset_port
554 disable_port
// disable_port
555 //queue_bulk_v_physical // queue_bulk_v_physical
564 const usb_device_descriptor
*
565 get_device_descriptor_v2(const void *device
)
567 return get_device_descriptor((usb_id
)device
);
571 const usb_configuration_info
*
572 get_nth_configuration_v2(const void *device
, uint index
)
574 return get_nth_configuration((usb_id
)device
, index
);
578 const usb_configuration_info
*
579 get_configuration_v2(const void *device
)
581 return get_configuration((usb_id
)device
);
586 set_configuration_v2(const void *device
,
587 const usb_configuration_info
*configuration
)
589 return set_configuration((usb_id
)device
, configuration
);
594 set_alt_interface_v2(const void *device
, const usb_interface_info
*interface
)
596 return set_alt_interface((usb_id
)device
, interface
);
601 set_feature_v2(const void *object
, uint16 selector
)
603 return set_feature((usb_id
)object
, selector
);
608 clear_feature_v2(const void *object
, uint16 selector
)
610 return clear_feature((usb_id
)object
, selector
);
615 get_status_v2(const void *object
, uint16
*status
)
617 return get_status((usb_id
)object
, status
);
622 get_descriptor_v2(const void *device
, uint8 type
, uint8 index
,
623 uint16 languageID
, void *data
, size_t dataLength
, size_t *actualLength
)
625 return get_descriptor((usb_id
)device
, type
, index
, languageID
, data
,
626 dataLength
, actualLength
);
631 send_request_v2(const void *device
, uint8 requestType
, uint8 request
,
632 uint16 value
, uint16 index
, uint16 length
, void *data
,
633 size_t /*dataLength*/, size_t *actualLength
)
635 return send_request((usb_id
)device
, requestType
, request
, value
, index
,
636 length
, data
, actualLength
);
641 queue_request_v2(const void *device
, uint8 requestType
, uint8 request
,
642 uint16 value
, uint16 index
, uint16 length
, void *data
,
643 size_t /*dataLength*/, usb_callback_func callback
, void *callbackCookie
)
645 return queue_request((usb_id
)device
, requestType
, request
, value
, index
,
646 length
, data
, callback
, callbackCookie
);
651 queue_interrupt_v2(const void *pipe
, void *data
, size_t dataLength
,
652 usb_callback_func callback
, void *callbackCookie
)
654 return queue_interrupt((usb_id
)pipe
, data
, dataLength
, callback
,
660 queue_bulk_v2(const void *pipe
, void *data
, size_t dataLength
,
661 usb_callback_func callback
, void *callbackCookie
)
663 return queue_bulk((usb_id
)pipe
, data
, dataLength
, callback
,
669 queue_isochronous_v2(const void *pipe
, void *data
, size_t dataLength
,
670 rlea
*rleArray
, uint16 bufferDurationMS
, usb_callback_func callback
,
671 void *callbackCookie
)
673 // ToDo: convert rlea to usb_iso_packet_descriptor
674 // ToDo: use a flag to indicate that the callback shall produce a rlea
675 usb_iso_packet_descriptor
*packetDesc
= NULL
;
676 return queue_isochronous((usb_id
)pipe
, data
, dataLength
, packetDesc
, 0,
677 NULL
, 0, callback
, callbackCookie
);
682 set_pipe_policy_v2(const void *pipe
, uint8 maxQueuedPackets
,
683 uint16 maxBufferDurationMS
, uint16 sampleSize
)
685 return set_pipe_policy((usb_id
)pipe
, maxQueuedPackets
, maxBufferDurationMS
,
691 cancel_queued_transfers_v2(const void *pipe
)
693 return cancel_queued_transfers((usb_id
)pipe
);
697 struct usb_module_info_v2
{
698 bus_manager_info binfo
;
699 status_t (*register_driver
)(const char *, const usb_support_descriptor
*, size_t, const char *);
700 status_t (*install_notify
)(const char *, const usb_notify_hooks
*);
701 status_t (*uninstall_notify
)(const char *);
702 const usb_device_descriptor
*(*get_device_descriptor
)(const void *);
703 const usb_configuration_info
*(*get_nth_configuration
)(const void *, uint
);
704 const usb_configuration_info
*(*get_configuration
)(const void *);
705 status_t (*set_configuration
)(const void *, const usb_configuration_info
*);
706 status_t (*set_alt_interface
)(const void *, const usb_interface_info
*);
707 status_t (*set_feature
)(const void *, uint16
);
708 status_t (*clear_feature
)(const void *, uint16
);
709 status_t (*get_status
)(const void *, uint16
*);
710 status_t (*get_descriptor
)(const void *, uint8
, uint8
, uint16
, void *, size_t, size_t *);
711 status_t (*send_request
)(const void *, uint8
, uint8
, uint16
, uint16
, uint16
, void *, size_t, size_t *);
712 status_t (*queue_interrupt
)(const void *, void *, size_t, usb_callback_func
, void *);
713 status_t (*queue_bulk
)(const void *, void *, size_t, usb_callback_func
, void *);
714 status_t (*queue_isochronous
)(const void *, void *, size_t, rlea
*, uint16
, usb_callback_func
, void *);
715 status_t (*queue_request
)(const void *, uint8
, uint8
, uint16
, uint16
, uint16
, void *, size_t, usb_callback_func
, void *);
716 status_t (*set_pipe_policy
)(const void *, uint8
, uint16
, uint16
);
717 status_t (*cancel_queued_transfers
)(const void *);
718 status_t (*usb_ioctl
)(uint32 opcode
, void *,size_t);
723 This module exports the USB API v2
725 struct usb_module_info_v2 gModuleInfoV2
= {
726 // First the bus_manager_info:
729 "bus_managers/usb/v2",
730 B_KEEP_LOADED
, // Keep loaded, even if no driver requires it
733 NULL
// the rescan function
736 register_driver
, // register_driver
737 install_notify
, // install_notify
738 uninstall_notify
, // uninstall_notify
739 get_device_descriptor_v2
, // get_device_descriptor
740 get_nth_configuration_v2
, // get_nth_configuration
741 get_configuration_v2
, // get_configuration
742 set_configuration_v2
, // set_configuration
743 set_alt_interface_v2
, // set_alt_interface
744 set_feature_v2
, // set_feature
745 clear_feature_v2
, // clear_feature
746 get_status_v2
, // get_status
747 get_descriptor_v2
, // get_descriptor
748 send_request_v2
, // send_request
749 queue_interrupt_v2
, // queue_interrupt
750 queue_bulk_v2
, // queue_bulk
751 queue_isochronous_v2
, // queue_isochronous
752 queue_request_v2
, // queue_request
753 set_pipe_policy_v2
, // set_pipe_policy
754 cancel_queued_transfers_v2
, // cancel_queued_transfers
755 usb_ioctl
// usb_ioctl
764 module_info
*modules
[] = {
765 (module_info
*)&gModuleInfoV2
,
766 (module_info
*)&gModuleInfoV3
,