* 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),
|
fCurrentConfiguration(NULL),
|
||||||
fSpeed(speed),
|
fSpeed(speed),
|
||||||
fDeviceAddress(deviceAddress),
|
fDeviceAddress(deviceAddress),
|
||||||
fLock(-1),
|
fLock(-1)
|
||||||
fNotifyCookie(NULL)
|
|
||||||
{
|
{
|
||||||
TRACE(("USB Device: new device\n"));
|
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_count = 0;
|
||||||
interfaceInfo->generic = NULL;
|
interfaceInfo->generic = NULL;
|
||||||
|
|
||||||
Interface *interface = new(std::nothrow) Interface(this);
|
Interface *interface = new(std::nothrow) Interface(this,
|
||||||
|
interfaceDescriptor->interface_number);
|
||||||
interfaceInfo->handle = interface->USBID();
|
interfaceInfo->handle = interface->USBID();
|
||||||
|
|
||||||
currentInterface = interfaceInfo;
|
currentInterface = interfaceInfo;
|
||||||
@@ -347,20 +347,22 @@ Device::DeviceDescriptor() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
status_t
|
||||||
Device::ReportDevice(usb_support_descriptor *supportDescriptors,
|
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"));
|
TRACE(("USB Device ReportDevice\n"));
|
||||||
if (supportDescriptorCount == 0 || supportDescriptors == NULL) {
|
if ((added && hooks->device_added == NULL)
|
||||||
if (added && hooks->device_added != NULL)
|
|| (!added && hooks->device_removed == NULL)
|
||||||
hooks->device_added(USBID(), &fNotifyCookie);
|
|| (!added && cookies[fDeviceAddress] == NULL))
|
||||||
else if (!added && hooks->device_removed != NULL)
|
return B_BAD_VALUE;
|
||||||
hooks->device_removed(fNotifyCookie);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
if ((supportDescriptors[i].vendor != 0
|
||||||
&& fDeviceDescriptor.vendor_id != supportDescriptors[i].vendor)
|
&& fDeviceDescriptor.vendor_id != supportDescriptors[i].vendor)
|
||||||
|| (supportDescriptors[i].product != 0
|
|| (supportDescriptors[i].product != 0
|
||||||
@@ -373,18 +375,13 @@ Device::ReportDevice(usb_support_descriptor *supportDescriptors,
|
|||||||
|| fDeviceDescriptor.device_subclass == supportDescriptors[i].dev_subclass)
|
|| fDeviceDescriptor.device_subclass == supportDescriptors[i].dev_subclass)
|
||||||
&& (supportDescriptors[i].dev_protocol == 0
|
&& (supportDescriptors[i].dev_protocol == 0
|
||||||
|| fDeviceDescriptor.device_protocol == supportDescriptors[i].dev_protocol)) {
|
|| fDeviceDescriptor.device_protocol == supportDescriptors[i].dev_protocol)) {
|
||||||
|
supported = true;
|
||||||
if (added && hooks->device_added != NULL)
|
|
||||||
hooks->device_added(USBID(), &fNotifyCookie);
|
|
||||||
else if (!added && hooks->device_removed != NULL)
|
|
||||||
hooks->device_removed(fNotifyCookie);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// we have to check all interfaces for matching class/subclass/protocol
|
// we have to check all interfaces for matching class/subclass/protocol
|
||||||
for (uint32 j = 0; j < fDeviceDescriptor.num_configurations; j++) {
|
for (uint32 j = 0; !supported && j < fDeviceDescriptor.num_configurations; j++) {
|
||||||
for (uint32 k = 0; k < fConfigurations[j].interface_count; k++) {
|
for (uint32 k = 0; !supported && k < fConfigurations[j].interface_count; k++) {
|
||||||
for (uint32 l = 0; l < fConfigurations[j].interface[k].alt_count; l++) {
|
for (uint32 l = 0; !supported && l < fConfigurations[j].interface[k].alt_count; l++) {
|
||||||
usb_interface_descriptor *descriptor = fConfigurations[j].interface[k].alt[l].descr;
|
usb_interface_descriptor *descriptor = fConfigurations[j].interface[k].alt[l].descr;
|
||||||
if ((supportDescriptors[i].dev_class == 0
|
if ((supportDescriptors[i].dev_class == 0
|
||||||
|| descriptor->interface_class == supportDescriptors[i].dev_class)
|
|| descriptor->interface_class == supportDescriptors[i].dev_class)
|
||||||
@@ -392,17 +389,27 @@ Device::ReportDevice(usb_support_descriptor *supportDescriptors,
|
|||||||
|| descriptor->interface_subclass == supportDescriptors[i].dev_subclass)
|
|| descriptor->interface_subclass == supportDescriptors[i].dev_subclass)
|
||||||
&& (supportDescriptors[i].dev_protocol == 0
|
&& (supportDescriptors[i].dev_protocol == 0
|
||||||
|| descriptor->interface_protocol == supportDescriptors[i].dev_protocol)) {
|
|| descriptor->interface_protocol == supportDescriptors[i].dev_protocol)) {
|
||||||
|
supported = true;
|
||||||
if (added && hooks->device_added != NULL)
|
|
||||||
hooks->device_added(USBID(), &fNotifyCookie);
|
|
||||||
else if (!added && hooks->device_removed != NULL)
|
|
||||||
hooks->device_removed(fNotifyCookie);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
#endif
|
||||||
|
|
||||||
if (fPortStatus[i].change & PORT_STATUS_CONNECTION) {
|
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) {
|
if (fPortStatus[i].status & PORT_STATUS_CONNECTION) {
|
||||||
// new device attached!
|
// new device attached!
|
||||||
TRACE(("USB Hub: Explore(): New device connected\n"));
|
TRACE(("USB Hub: Explore(): New device connected\n"));
|
||||||
@@ -211,11 +216,6 @@ Hub::Explore()
|
|||||||
fChildren[i] = NULL;
|
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,
|
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"));
|
TRACE(("USB Hub ReportDevice\n"));
|
||||||
|
|
||||||
// Report ourselfs first
|
// 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
|
// Then report all of our children
|
||||||
for (int32 i = 0; i < fHubDescriptor.num_ports; i++) {
|
for (int32 i = 0; i < fHubDescriptor.num_ports; i++) {
|
||||||
if (!fChildren[i])
|
if (!fChildren[i])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
fChildren[i]->ReportDevice(supportDescriptors,
|
if (fChildren[i]->ReportDevice(supportDescriptors,
|
||||||
supportDescriptorCount, hooks, added);
|
supportDescriptorCount, hooks, cookies, added) == B_OK)
|
||||||
|
result = B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,9 @@
|
|||||||
#include "usb_p.h"
|
#include "usb_p.h"
|
||||||
|
|
||||||
|
|
||||||
Interface::Interface(Object *parent)
|
Interface::Interface(Object *parent, uint8 interfaceIndex)
|
||||||
: Object(parent)
|
: Object(parent),
|
||||||
|
fInterfaceIndex(interfaceIndex)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@ Interface::SetFeature(uint16 selector)
|
|||||||
USB_REQTYPE_STANDARD | USB_REQTYPE_INTERFACE_OUT,
|
USB_REQTYPE_STANDARD | USB_REQTYPE_INTERFACE_OUT,
|
||||||
USB_REQUEST_SET_FEATURE,
|
USB_REQUEST_SET_FEATURE,
|
||||||
selector,
|
selector,
|
||||||
0,
|
fInterfaceIndex,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
0,
|
0,
|
||||||
@@ -37,7 +38,7 @@ Interface::ClearFeature(uint16 selector)
|
|||||||
USB_REQTYPE_STANDARD | USB_REQTYPE_INTERFACE_OUT,
|
USB_REQTYPE_STANDARD | USB_REQTYPE_INTERFACE_OUT,
|
||||||
USB_REQUEST_CLEAR_FEATURE,
|
USB_REQUEST_CLEAR_FEATURE,
|
||||||
selector,
|
selector,
|
||||||
0,
|
fInterfaceIndex,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
0,
|
0,
|
||||||
@@ -51,7 +52,7 @@ Interface::GetStatus(uint16 *status)
|
|||||||
return ((Device *)Parent())->DefaultPipe()->SendRequest(
|
return ((Device *)Parent())->DefaultPipe()->SendRequest(
|
||||||
USB_REQTYPE_STANDARD | USB_REQTYPE_INTERFACE_IN,
|
USB_REQTYPE_STANDARD | USB_REQTYPE_INTERFACE_IN,
|
||||||
USB_REQUEST_GET_STATUS,
|
USB_REQUEST_GET_STATUS,
|
||||||
0,
|
fInterfaceIndex,
|
||||||
0,
|
0,
|
||||||
2,
|
2,
|
||||||
(void *)status,
|
(void *)status,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <module.h>
|
#include <module.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <util/kernel_cpp.h>
|
#include <util/kernel_cpp.h>
|
||||||
#include "usb_p.h"
|
#include "usb_p.h"
|
||||||
#include "PhysicalMemoryAllocator.h"
|
#include "PhysicalMemoryAllocator.h"
|
||||||
@@ -230,9 +231,18 @@ Stack::NotifyDeviceChange(Device *device, bool added)
|
|||||||
while (element) {
|
while (element) {
|
||||||
if ((added && element->notify_hooks.device_added != NULL)
|
if ((added && element->notify_hooks.device_added != NULL)
|
||||||
|| (!added && element->notify_hooks.device_removed != 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->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;
|
element = element->link;
|
||||||
@@ -258,6 +268,7 @@ Stack::RegisterDriver(const char *driverName,
|
|||||||
memcpy(info->support_descriptors, descriptors, descriptorsSize);
|
memcpy(info->support_descriptors, descriptors, descriptorsSize);
|
||||||
info->support_descriptor_count = descriptorCount;
|
info->support_descriptor_count = descriptorCount;
|
||||||
|
|
||||||
|
memset(info->cookies, 0, sizeof(void *) * 128);
|
||||||
info->notify_hooks.device_added = NULL;
|
info->notify_hooks.device_added = NULL;
|
||||||
info->notify_hooks.device_removed = NULL;
|
info->notify_hooks.device_removed = NULL;
|
||||||
info->link = NULL;
|
info->link = NULL;
|
||||||
@@ -285,6 +296,7 @@ status_t
|
|||||||
Stack::InstallNotify(const char *driverName, const usb_notify_hooks *hooks)
|
Stack::InstallNotify(const char *driverName, const usb_notify_hooks *hooks)
|
||||||
{
|
{
|
||||||
TRACE(("usb stack: installing notify hooks for driver \"%s\"\n", driverName));
|
TRACE(("usb stack: installing notify hooks for driver \"%s\"\n", driverName));
|
||||||
|
|
||||||
usb_driver_info *element = fDriverList;
|
usb_driver_info *element = fDriverList;
|
||||||
while (element) {
|
while (element) {
|
||||||
if (strcmp(element->driver_name, driverName) == 0) {
|
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
|
// Report device will recurse down the whole tree
|
||||||
rootHub->ReportDevice(element->support_descriptors,
|
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)
|
Stack::UninstallNotify(const char *driverName)
|
||||||
{
|
{
|
||||||
TRACE(("usb stack: uninstalling notify hooks for driver \"%s\"\n", driverName));
|
TRACE(("usb stack: uninstalling notify hooks for driver \"%s\"\n", driverName));
|
||||||
|
if (!Lock())
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
usb_driver_info *element = fDriverList;
|
usb_driver_info *element = fDriverList;
|
||||||
while (element) {
|
while (element) {
|
||||||
if (strcmp(element->driver_name, driverName) == 0) {
|
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_added = NULL;
|
||||||
element->notify_hooks.device_removed = NULL;
|
element->notify_hooks.device_removed = NULL;
|
||||||
|
Unlock();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
element = element->link;
|
element = element->link;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Unlock();
|
||||||
return B_NAME_NOT_FOUND;
|
return B_NAME_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ struct usb_driver_info {
|
|||||||
uint32 support_descriptor_count;
|
uint32 support_descriptor_count;
|
||||||
const char *republish_driver_name;
|
const char *republish_driver_name;
|
||||||
usb_notify_hooks notify_hooks;
|
usb_notify_hooks notify_hooks;
|
||||||
|
void *cookies[128];
|
||||||
usb_driver_info *link;
|
usb_driver_info *link;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -340,7 +341,8 @@ virtual uint32 Type() { return USB_OBJECT_PIPE | USB_OBJECT_ISO_PIPE; };
|
|||||||
|
|
||||||
class Interface : public Object {
|
class Interface : public Object {
|
||||||
public:
|
public:
|
||||||
Interface(Object *parent);
|
Interface(Object *parent,
|
||||||
|
uint8 interfaceIndex);
|
||||||
|
|
||||||
virtual uint32 Type() { return USB_OBJECT_INTERFACE; };
|
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 SetFeature(uint16 selector);
|
||||||
virtual status_t ClearFeature(uint16 selector);
|
virtual status_t ClearFeature(uint16 selector);
|
||||||
virtual status_t GetStatus(uint16 *status);
|
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 SetConfiguration(const usb_configuration_info *configuration);
|
||||||
status_t SetConfigurationAt(uint8 index);
|
status_t SetConfigurationAt(uint8 index);
|
||||||
|
|
||||||
virtual void ReportDevice(
|
virtual status_t ReportDevice(
|
||||||
usb_support_descriptor *supportDescriptors,
|
usb_support_descriptor *supportDescriptors,
|
||||||
uint32 supportDescriptorCount,
|
uint32 supportDescriptorCount,
|
||||||
const usb_notify_hooks *hooks,
|
const usb_notify_hooks *hooks,
|
||||||
bool added);
|
void *cookies[], bool added);
|
||||||
virtual status_t BuildDeviceName(char *string,
|
virtual status_t BuildDeviceName(char *string,
|
||||||
uint32 *index, size_t bufferSize,
|
uint32 *index, size_t bufferSize,
|
||||||
Device *device);
|
Device *device);
|
||||||
@@ -402,7 +407,6 @@ private:
|
|||||||
size_t fMaxPacketIn[16];
|
size_t fMaxPacketIn[16];
|
||||||
size_t fMaxPacketOut[16];
|
size_t fMaxPacketOut[16];
|
||||||
sem_id fLock;
|
sem_id fLock;
|
||||||
void *fNotifyCookie;
|
|
||||||
ControlPipe *fDefaultPipe;
|
ControlPipe *fDefaultPipe;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -428,11 +432,11 @@ static void InterruptCallback(void *cookie,
|
|||||||
uint32 status, void *data,
|
uint32 status, void *data,
|
||||||
size_t actualLength);
|
size_t actualLength);
|
||||||
|
|
||||||
virtual void ReportDevice(
|
virtual status_t ReportDevice(
|
||||||
usb_support_descriptor *supportDescriptors,
|
usb_support_descriptor *supportDescriptors,
|
||||||
uint32 supportDescriptorCount,
|
uint32 supportDescriptorCount,
|
||||||
const usb_notify_hooks *hooks,
|
const usb_notify_hooks *hooks,
|
||||||
bool added);
|
void *cookies[], bool added);
|
||||||
virtual status_t BuildDeviceName(char *string,
|
virtual status_t BuildDeviceName(char *string,
|
||||||
uint32 *index, size_t bufferSize,
|
uint32 *index, size_t bufferSize,
|
||||||
Device *device);
|
Device *device);
|
||||||
|
|||||||
Reference in New Issue
Block a user