* Fixed notify cookie handling. There is not one cookie per device, but one per device/driver combination

* Fixed SetFeature/ClearFeature/GetStatus for interfaces by adding the respective interface number
* Added driver rescanning mechanism (taken from bin/rescan)

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18912 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2006-09-23 17:24:23 +00:00
parent c4cc0591f1
commit 90b9fb4fbc
5 changed files with 96 additions and 52 deletions
+35 -28
View File
@@ -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;
}
+15 -10
View File
@@ -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;
}
@@ -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,
+30 -3
View File
@@ -8,6 +8,7 @@
*/
#include <module.h>
#include <unistd.h>
#include <util/kernel_cpp.h>
#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;
}
+10 -6
View File
@@ -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);