* 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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user