diff --git a/src/add-ons/kernel/bus_managers/usb/Device.cpp b/src/add-ons/kernel/bus_managers/usb/Device.cpp index d4f4917ea2..655cd8b044 100644 --- a/src/add-ons/kernel/bus_managers/usb/Device.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Device.cpp @@ -19,8 +19,7 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress, fCurrentConfiguration(NULL), fSpeed(speed), fDeviceAddress(deviceAddress), - fLock(-1), - fNotifyCookie(NULL) + fLock(-1) { TRACE(("USB Device: new device\n")); @@ -150,7 +149,8 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress, interfaceInfo->generic_count = 0; interfaceInfo->generic = NULL; - Interface *interface = new(std::nothrow) Interface(this); + Interface *interface = new(std::nothrow) Interface(this, + interfaceDescriptor->interface_number); interfaceInfo->handle = interface->USBID(); currentInterface = interfaceInfo; @@ -347,20 +347,22 @@ Device::DeviceDescriptor() const } -void +status_t Device::ReportDevice(usb_support_descriptor *supportDescriptors, - uint32 supportDescriptorCount, const usb_notify_hooks *hooks, bool added) + uint32 supportDescriptorCount, const usb_notify_hooks *hooks, + void *cookies[], bool added) { TRACE(("USB Device ReportDevice\n")); - if (supportDescriptorCount == 0 || supportDescriptors == NULL) { - if (added && hooks->device_added != NULL) - hooks->device_added(USBID(), &fNotifyCookie); - else if (!added && hooks->device_removed != NULL) - hooks->device_removed(fNotifyCookie); - return; - } + if ((added && hooks->device_added == NULL) + || (!added && hooks->device_removed == NULL) + || (!added && cookies[fDeviceAddress] == NULL)) + return B_BAD_VALUE; - for (uint32 i = 0; i < supportDescriptorCount; i++) { + bool supported = false; + if (supportDescriptorCount == 0 || supportDescriptors == NULL) + supported = true; + + for (uint32 i = 0; !supported && i < supportDescriptorCount; i++) { if ((supportDescriptors[i].vendor != 0 && fDeviceDescriptor.vendor_id != supportDescriptors[i].vendor) || (supportDescriptors[i].product != 0 @@ -373,18 +375,13 @@ Device::ReportDevice(usb_support_descriptor *supportDescriptors, || fDeviceDescriptor.device_subclass == supportDescriptors[i].dev_subclass) && (supportDescriptors[i].dev_protocol == 0 || fDeviceDescriptor.device_protocol == supportDescriptors[i].dev_protocol)) { - - if (added && hooks->device_added != NULL) - hooks->device_added(USBID(), &fNotifyCookie); - else if (!added && hooks->device_removed != NULL) - hooks->device_removed(fNotifyCookie); - return; + supported = true; } // we have to check all interfaces for matching class/subclass/protocol - for (uint32 j = 0; j < fDeviceDescriptor.num_configurations; j++) { - for (uint32 k = 0; k < fConfigurations[j].interface_count; k++) { - for (uint32 l = 0; l < fConfigurations[j].interface[k].alt_count; l++) { + for (uint32 j = 0; !supported && j < fDeviceDescriptor.num_configurations; j++) { + for (uint32 k = 0; !supported && k < fConfigurations[j].interface_count; k++) { + for (uint32 l = 0; !supported && l < fConfigurations[j].interface[k].alt_count; l++) { usb_interface_descriptor *descriptor = fConfigurations[j].interface[k].alt[l].descr; if ((supportDescriptors[i].dev_class == 0 || descriptor->interface_class == supportDescriptors[i].dev_class) @@ -392,17 +389,27 @@ Device::ReportDevice(usb_support_descriptor *supportDescriptors, || descriptor->interface_subclass == supportDescriptors[i].dev_subclass) && (supportDescriptors[i].dev_protocol == 0 || descriptor->interface_protocol == supportDescriptors[i].dev_protocol)) { - - if (added && hooks->device_added != NULL) - hooks->device_added(USBID(), &fNotifyCookie); - else if (!added && hooks->device_removed != NULL) - hooks->device_removed(fNotifyCookie); - return; + supported = true; } } } } } + + if (supported) { + if (added) { + status_t result = hooks->device_added(USBID(), &cookies[fDeviceAddress]); + if (result != B_OK) + cookies[fDeviceAddress] = NULL; + return result; + } + + hooks->device_removed(cookies[fDeviceAddress]); + cookies[fDeviceAddress] = NULL; + return B_OK; + } + + return B_UNSUPPORTED; } diff --git a/src/add-ons/kernel/bus_managers/usb/Hub.cpp b/src/add-ons/kernel/bus_managers/usb/Hub.cpp index 40881b9504..6bb81f5f81 100644 --- a/src/add-ons/kernel/bus_managers/usb/Hub.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Hub.cpp @@ -161,6 +161,11 @@ Hub::Explore() #endif if (fPortStatus[i].change & PORT_STATUS_CONNECTION) { + // clear status change + DefaultPipe()->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT, + USB_REQUEST_CLEAR_FEATURE, C_PORT_CONNECTION, i + 1, + 0, NULL, 0, NULL); + if (fPortStatus[i].status & PORT_STATUS_CONNECTION) { // new device attached! TRACE(("USB Hub: Explore(): New device connected\n")); @@ -211,11 +216,6 @@ Hub::Explore() fChildren[i] = NULL; } } - - // clear status change - DefaultPipe()->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT, - USB_REQUEST_CLEAR_FEATURE, C_PORT_CONNECTION, i + 1, - 0, NULL, 0, NULL); } } @@ -253,23 +253,28 @@ Hub::GetDescriptor(uint8 descriptorType, uint8 index, uint16 languageID, } -void +status_t Hub::ReportDevice(usb_support_descriptor *supportDescriptors, - uint32 supportDescriptorCount, const usb_notify_hooks *hooks, bool added) + uint32 supportDescriptorCount, const usb_notify_hooks *hooks, + void *cookies[], bool added) { TRACE(("USB Hub ReportDevice\n")); // Report ourselfs first - Device::ReportDevice(supportDescriptors, supportDescriptorCount, hooks, added); + status_t result = Device::ReportDevice(supportDescriptors, + supportDescriptorCount, hooks, cookies, added); // Then report all of our children for (int32 i = 0; i < fHubDescriptor.num_ports; i++) { if (!fChildren[i]) continue; - fChildren[i]->ReportDevice(supportDescriptors, - supportDescriptorCount, hooks, added); + if (fChildren[i]->ReportDevice(supportDescriptors, + supportDescriptorCount, hooks, cookies, added) == B_OK) + result = B_OK; } + + return result; } diff --git a/src/add-ons/kernel/bus_managers/usb/Interface.cpp b/src/add-ons/kernel/bus_managers/usb/Interface.cpp index de97857ca1..c3ac532155 100644 --- a/src/add-ons/kernel/bus_managers/usb/Interface.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Interface.cpp @@ -9,8 +9,9 @@ #include "usb_p.h" -Interface::Interface(Object *parent) - : Object(parent) +Interface::Interface(Object *parent, uint8 interfaceIndex) + : Object(parent), + fInterfaceIndex(interfaceIndex) { } @@ -22,7 +23,7 @@ Interface::SetFeature(uint16 selector) USB_REQTYPE_STANDARD | USB_REQTYPE_INTERFACE_OUT, USB_REQUEST_SET_FEATURE, selector, - 0, + fInterfaceIndex, 0, NULL, 0, @@ -37,7 +38,7 @@ Interface::ClearFeature(uint16 selector) USB_REQTYPE_STANDARD | USB_REQTYPE_INTERFACE_OUT, USB_REQUEST_CLEAR_FEATURE, selector, - 0, + fInterfaceIndex, 0, NULL, 0, @@ -51,7 +52,7 @@ Interface::GetStatus(uint16 *status) return ((Device *)Parent())->DefaultPipe()->SendRequest( USB_REQTYPE_STANDARD | USB_REQTYPE_INTERFACE_IN, USB_REQUEST_GET_STATUS, - 0, + fInterfaceIndex, 0, 2, (void *)status, diff --git a/src/add-ons/kernel/bus_managers/usb/Stack.cpp b/src/add-ons/kernel/bus_managers/usb/Stack.cpp index 7e910ba834..2bd351acb0 100644 --- a/src/add-ons/kernel/bus_managers/usb/Stack.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Stack.cpp @@ -8,6 +8,7 @@ */ #include +#include #include #include "usb_p.h" #include "PhysicalMemoryAllocator.h" @@ -230,9 +231,18 @@ Stack::NotifyDeviceChange(Device *device, bool added) while (element) { if ((added && element->notify_hooks.device_added != NULL) || (!added && element->notify_hooks.device_removed != NULL)) { - device->ReportDevice(element->support_descriptors, + status_t result = device->ReportDevice(element->support_descriptors, element->support_descriptor_count, - &element->notify_hooks, added); + &element->notify_hooks, element->cookies, added); + + if (result == B_OK) { + const char *name = element->driver_name; + if (element->republish_driver_name) + name = element->republish_driver_name; + int devFS = open("/dev", O_WRONLY); + write(devFS, name, strlen(name)); + close(devFS); + } } element = element->link; @@ -258,6 +268,7 @@ Stack::RegisterDriver(const char *driverName, memcpy(info->support_descriptors, descriptors, descriptorsSize); info->support_descriptor_count = descriptorCount; + memset(info->cookies, 0, sizeof(void *) * 128); info->notify_hooks.device_added = NULL; info->notify_hooks.device_removed = NULL; info->link = NULL; @@ -285,6 +296,7 @@ status_t Stack::InstallNotify(const char *driverName, const usb_notify_hooks *hooks) { TRACE(("usb stack: installing notify hooks for driver \"%s\"\n", driverName)); + usb_driver_info *element = fDriverList; while (element) { if (strcmp(element->driver_name, driverName) == 0) { @@ -297,7 +309,8 @@ Stack::InstallNotify(const char *driverName, const usb_notify_hooks *hooks) // Report device will recurse down the whole tree rootHub->ReportDevice(element->support_descriptors, - element->support_descriptor_count, hooks, true); + element->support_descriptor_count, hooks, + element->cookies, true); } } @@ -317,16 +330,30 @@ status_t Stack::UninstallNotify(const char *driverName) { TRACE(("usb stack: uninstalling notify hooks for driver \"%s\"\n", driverName)); + if (!Lock()) + return B_ERROR; + usb_driver_info *element = fDriverList; while (element) { if (strcmp(element->driver_name, driverName) == 0) { + // trigger the device removed hook + for (int32 i = 0; i < fBusManagers.Count(); i++) { + Hub *rootHub = fBusManagers.ElementAt(i)->GetRootHub(); + if (rootHub) + rootHub->ReportDevice(element->support_descriptors, + element->support_descriptor_count, + &element->notify_hooks, element->cookies, false); + } + element->notify_hooks.device_added = NULL; element->notify_hooks.device_removed = NULL; + Unlock(); return B_OK; } element = element->link; } + Unlock(); return B_NAME_NOT_FOUND; } diff --git a/src/add-ons/kernel/bus_managers/usb/usb_p.h b/src/add-ons/kernel/bus_managers/usb/usb_p.h index 9a03de9624..fb568d34f4 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb_p.h +++ b/src/add-ons/kernel/bus_managers/usb/usb_p.h @@ -48,6 +48,7 @@ struct usb_driver_info { uint32 support_descriptor_count; const char *republish_driver_name; usb_notify_hooks notify_hooks; + void *cookies[128]; usb_driver_info *link; }; @@ -340,7 +341,8 @@ virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_ISO_PIPE; }; class Interface : public Object { public: - Interface(Object *parent); + Interface(Object *parent, + uint8 interfaceIndex); virtual uint32 Type() { return USB_OBJECT_INTERFACE; }; @@ -348,6 +350,9 @@ virtual uint32 Type() { return USB_OBJECT_INTERFACE; }; virtual status_t SetFeature(uint16 selector); virtual status_t ClearFeature(uint16 selector); virtual status_t GetStatus(uint16 *status); + +private: + uint8 fInterfaceIndex; }; @@ -376,11 +381,11 @@ virtual status_t GetDescriptor(uint8 descriptorType, status_t SetConfiguration(const usb_configuration_info *configuration); status_t SetConfigurationAt(uint8 index); -virtual void ReportDevice( +virtual status_t ReportDevice( usb_support_descriptor *supportDescriptors, uint32 supportDescriptorCount, const usb_notify_hooks *hooks, - bool added); + void *cookies[], bool added); virtual status_t BuildDeviceName(char *string, uint32 *index, size_t bufferSize, Device *device); @@ -402,7 +407,6 @@ private: size_t fMaxPacketIn[16]; size_t fMaxPacketOut[16]; sem_id fLock; - void *fNotifyCookie; ControlPipe *fDefaultPipe; }; @@ -428,11 +432,11 @@ static void InterruptCallback(void *cookie, uint32 status, void *data, size_t actualLength); -virtual void ReportDevice( +virtual status_t ReportDevice( usb_support_descriptor *supportDescriptors, uint32 supportDescriptorCount, const usb_notify_hooks *hooks, - bool added); + void *cookies[], bool added); virtual status_t BuildDeviceName(char *string, uint32 *index, size_t bufferSize, Device *device);