Completely redesign the USB explore process. Replaces the scary race conditions of the previous locking mechanism and simplifies handling of device changes by a more centralized approach.
Changes are now collected during explore and notifications as well as rescans are done at once. Through this a driver is also not rescanned multiple times anymore. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22929 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
d3625d72ed
commit
13508e8bd0
@ -269,7 +269,7 @@ BusManager::SubmitTransfer(Transfer *transfer)
|
||||
|
||||
|
||||
status_t
|
||||
BusManager::CancelQueuedTransfers(Pipe *pipe)
|
||||
BusManager::CancelQueuedTransfers(Pipe *pipe, bool force)
|
||||
{
|
||||
// virtual function to be overridden
|
||||
return B_ERROR;
|
||||
|
@ -15,6 +15,7 @@ Device::Device(Object *parent, usb_device_descriptor &desc, int8 deviceAddress,
|
||||
: Object(parent),
|
||||
fDeviceDescriptor(desc),
|
||||
fInitOK(false),
|
||||
fAvailable(true),
|
||||
fConfigurations(NULL),
|
||||
fCurrentConfiguration(NULL),
|
||||
fSpeed(speed),
|
||||
@ -252,10 +253,29 @@ Device::InitCheck()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Device::Changed(change_item **changeList, bool added)
|
||||
{
|
||||
fAvailable = added;
|
||||
change_item *changeItem = new(std::nothrow) change_item;
|
||||
if (!changeItem)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
changeItem->added = added;
|
||||
changeItem->device = this;
|
||||
changeItem->link = *changeList;
|
||||
*changeList = changeItem;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Device::GetDescriptor(uint8 descriptorType, uint8 index, uint16 languageID,
|
||||
void *data, size_t dataLength, size_t *actualLength)
|
||||
{
|
||||
if (!fAvailable)
|
||||
return B_ERROR;
|
||||
|
||||
return fDefaultPipe->SendRequest(
|
||||
USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD, // type
|
||||
USB_REQUEST_GET_DESCRIPTOR, // request
|
||||
@ -304,6 +324,8 @@ Device::SetConfiguration(const usb_configuration_info *configuration)
|
||||
status_t
|
||||
Device::SetConfigurationAt(uint8 index)
|
||||
{
|
||||
if (!fAvailable)
|
||||
return B_ERROR;
|
||||
if (index >= fDeviceDescriptor.num_configurations)
|
||||
return B_BAD_VALUE;
|
||||
if (&fConfigurations[index] == fCurrentConfiguration)
|
||||
@ -382,7 +404,7 @@ Device::Unconfigure(bool atDeviceLevel)
|
||||
// another configuration unconfigure will be called with
|
||||
// atDevice = false. otherwise we explicitly want to unconfigure
|
||||
// the device and have to send it the corresponding request.
|
||||
if (atDeviceLevel) {
|
||||
if (atDeviceLevel && fAvailable) {
|
||||
status_t result = fDefaultPipe->SendRequest(
|
||||
USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD, // type
|
||||
USB_REQUEST_SET_CONFIGURATION, // request
|
||||
@ -426,7 +448,7 @@ Device::DeviceDescriptor() const
|
||||
status_t
|
||||
Device::ReportDevice(usb_support_descriptor *supportDescriptors,
|
||||
uint32 supportDescriptorCount, const usb_notify_hooks *hooks,
|
||||
usb_driver_cookie **cookies, bool added)
|
||||
usb_driver_cookie **cookies, bool added, bool recursive)
|
||||
{
|
||||
TRACE(("USB Device %d: reporting device\n", fDeviceAddress));
|
||||
bool supported = false;
|
||||
@ -526,6 +548,9 @@ Device::BuildDeviceName(char *string, uint32 *index, size_t bufferSize,
|
||||
status_t
|
||||
Device::SetFeature(uint16 selector)
|
||||
{
|
||||
if (!fAvailable)
|
||||
return B_ERROR;
|
||||
|
||||
return fDefaultPipe->SendRequest(
|
||||
USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT,
|
||||
USB_REQUEST_SET_FEATURE,
|
||||
@ -541,6 +566,9 @@ Device::SetFeature(uint16 selector)
|
||||
status_t
|
||||
Device::ClearFeature(uint16 selector)
|
||||
{
|
||||
if (!fAvailable)
|
||||
return B_ERROR;
|
||||
|
||||
return fDefaultPipe->SendRequest(
|
||||
USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT,
|
||||
USB_REQUEST_CLEAR_FEATURE,
|
||||
@ -556,6 +584,9 @@ Device::ClearFeature(uint16 selector)
|
||||
status_t
|
||||
Device::GetStatus(uint16 *status)
|
||||
{
|
||||
if (!fAvailable)
|
||||
return B_ERROR;
|
||||
|
||||
return fDefaultPipe->SendRequest(
|
||||
USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_IN,
|
||||
USB_REQUEST_GET_STATUS,
|
||||
|
@ -30,11 +30,6 @@ Hub::Hub(Object *parent, usb_device_descriptor &desc, int8 deviceAddress,
|
||||
// Set to false again for the hub init.
|
||||
fInitOK = false;
|
||||
|
||||
if (benaphore_init(&fLock, "usb hub lock") < B_OK) {
|
||||
TRACE_ERROR(("USB Hub %d: failed to create hub lock\n", DeviceAddress()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (fDeviceDescriptor.device_class != 9) {
|
||||
TRACE_ERROR(("USB Hub %d: wrong class! bailing out\n", DeviceAddress()));
|
||||
return;
|
||||
@ -97,36 +92,26 @@ Hub::Hub(Object *parent, usb_device_descriptor &desc, int8 deviceAddress,
|
||||
|
||||
Hub::~Hub()
|
||||
{
|
||||
Lock();
|
||||
benaphore_destroy(&fLock);
|
||||
|
||||
// Remove all child devices
|
||||
for (int32 i = 0; i < fHubDescriptor.num_ports; i++) {
|
||||
if (!fChildren[i])
|
||||
continue;
|
||||
|
||||
TRACE(("USB Hub %d: removing device 0x%08lx\n", DeviceAddress(), fChildren[i]));
|
||||
rescan_item *rescanList = NULL;
|
||||
GetStack()->NotifyDeviceChange(fChildren[i], &rescanList, false);
|
||||
GetBusManager()->FreeDevice(fChildren[i]);
|
||||
GetStack()->RescanDrivers(rescanList);
|
||||
}
|
||||
|
||||
delete fInterruptPipe;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Hub::Lock()
|
||||
status_t
|
||||
Hub::Changed(change_item **changeList, bool added)
|
||||
{
|
||||
return (benaphore_lock(&fLock) == B_OK);
|
||||
}
|
||||
status_t result = Device::Changed(changeList, added);
|
||||
if (added || result < B_OK)
|
||||
return result;
|
||||
|
||||
for (int32 i = 0; i < fHubDescriptor.num_ports; i++) {
|
||||
if (fChildren[i] == NULL)
|
||||
continue;
|
||||
|
||||
void
|
||||
Hub::Unlock()
|
||||
{
|
||||
benaphore_unlock(&fLock);
|
||||
fChildren[i]->Changed(changeList, false);
|
||||
fChildren[i] = NULL;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -189,7 +174,7 @@ Hub::ResetPort(uint8 index)
|
||||
|
||||
|
||||
void
|
||||
Hub::Explore()
|
||||
Hub::Explore(change_item **changeList)
|
||||
{
|
||||
for (int32 i = 0; i < fHubDescriptor.num_ports; i++) {
|
||||
status_t result = UpdatePortStatus(i);
|
||||
@ -209,7 +194,6 @@ Hub::Explore()
|
||||
USB_REQUEST_CLEAR_FEATURE, C_PORT_CONNECTION, i + 1,
|
||||
0, NULL, 0, NULL);
|
||||
|
||||
rescan_item *rescanList = NULL;
|
||||
if (fPortStatus[i].status & PORT_STATUS_CONNECTION) {
|
||||
// new device attached!
|
||||
TRACE(("USB Hub %d: new device connected\n", DeviceAddress()));
|
||||
@ -234,18 +218,8 @@ Hub::Explore()
|
||||
|
||||
if (fChildren[i]) {
|
||||
TRACE_ERROR(("USB Hub %d: new device on a port that is already in use\n", DeviceAddress()));
|
||||
|
||||
// Remove previous device first
|
||||
TRACE(("USB Hub %d: removing device 0x%08lx\n", DeviceAddress(), fChildren[i]));
|
||||
GetStack()->NotifyDeviceChange(fChildren[i], &rescanList, false);
|
||||
|
||||
if (Lock()) {
|
||||
GetBusManager()->FreeDevice(fChildren[i]);
|
||||
fChildren[i] = NULL;
|
||||
Unlock();
|
||||
}
|
||||
|
||||
GetStack()->RescanDrivers(rescanList);
|
||||
fChildren[i]->Changed(changeList, false);
|
||||
fChildren[i] = NULL;
|
||||
}
|
||||
|
||||
usb_speed speed = USB_SPEED_FULLSPEED;
|
||||
@ -256,15 +230,10 @@ Hub::Explore()
|
||||
|
||||
Device *newDevice = GetBusManager()->AllocateDevice(this, speed);
|
||||
|
||||
if (newDevice && Lock()) {
|
||||
if (newDevice) {
|
||||
newDevice->Changed(changeList, true);
|
||||
fChildren[i] = newDevice;
|
||||
Unlock();
|
||||
GetStack()->NotifyDeviceChange(fChildren[i], &rescanList, true);
|
||||
GetStack()->RescanDrivers(rescanList);
|
||||
} else {
|
||||
if (newDevice)
|
||||
GetBusManager()->FreeDevice(newDevice);
|
||||
|
||||
// the device failed to setup correctly, disable the port
|
||||
// so that the device doesn't get in the way of future
|
||||
// addressing.
|
||||
@ -277,15 +246,8 @@ Hub::Explore()
|
||||
TRACE(("USB Hub %d: device removed\n", DeviceAddress()));
|
||||
if (fChildren[i]) {
|
||||
TRACE(("USB Hub %d: removing device 0x%08lx\n", DeviceAddress(), fChildren[i]));
|
||||
GetStack()->NotifyDeviceChange(fChildren[i], &rescanList, false);
|
||||
|
||||
if (Lock()) {
|
||||
GetBusManager()->FreeDevice(fChildren[i]);
|
||||
fChildren[i] = NULL;
|
||||
Unlock();
|
||||
}
|
||||
|
||||
GetStack()->RescanDrivers(rescanList);
|
||||
fChildren[i]->Changed(changeList, false);
|
||||
fChildren[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -325,7 +287,7 @@ Hub::Explore()
|
||||
if (!fChildren[i] || (fChildren[i]->Type() & USB_OBJECT_HUB) == 0)
|
||||
continue;
|
||||
|
||||
((Hub *)fChildren[i])->Explore();
|
||||
((Hub *)fChildren[i])->Explore(changeList);
|
||||
}
|
||||
}
|
||||
|
||||
@ -357,28 +319,26 @@ Hub::GetDescriptor(uint8 descriptorType, uint8 index, uint16 languageID,
|
||||
status_t
|
||||
Hub::ReportDevice(usb_support_descriptor *supportDescriptors,
|
||||
uint32 supportDescriptorCount, const usb_notify_hooks *hooks,
|
||||
usb_driver_cookie **cookies, bool added)
|
||||
usb_driver_cookie **cookies, bool added, bool recursive)
|
||||
{
|
||||
TRACE(("USB Hub %d: reporting hub\n", DeviceAddress()));
|
||||
|
||||
// Report ourselfs first
|
||||
status_t result = Device::ReportDevice(supportDescriptors,
|
||||
supportDescriptorCount, hooks, cookies, added);
|
||||
supportDescriptorCount, hooks, cookies, added, recursive);
|
||||
|
||||
// Then report all of our children
|
||||
if (!Lock())
|
||||
return B_ERROR;
|
||||
if (!recursive)
|
||||
return result;
|
||||
|
||||
for (int32 i = 0; i < fHubDescriptor.num_ports; i++) {
|
||||
if (!fChildren[i])
|
||||
continue;
|
||||
|
||||
if (fChildren[i]->ReportDevice(supportDescriptors,
|
||||
supportDescriptorCount, hooks, cookies, added) == B_OK)
|
||||
supportDescriptorCount, hooks, cookies, added, true) == B_OK)
|
||||
result = B_OK;
|
||||
}
|
||||
|
||||
Unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ Pipe::Pipe(Object *parent, int8 deviceAddress, uint8 endpointAddress,
|
||||
|
||||
Pipe::~Pipe()
|
||||
{
|
||||
CancelQueuedTransfers();
|
||||
CancelQueuedTransfers(true);
|
||||
GetBusManager()->NotifyPipeChange(this, USB_CHANGE_DESTROYED);
|
||||
}
|
||||
|
||||
@ -40,9 +40,9 @@ Pipe::SubmitTransfer(Transfer *transfer)
|
||||
|
||||
|
||||
status_t
|
||||
Pipe::CancelQueuedTransfers()
|
||||
Pipe::CancelQueuedTransfers(bool force)
|
||||
{
|
||||
return GetBusManager()->CancelQueuedTransfers(this);
|
||||
return GetBusManager()->CancelQueuedTransfers(this, force);
|
||||
}
|
||||
|
||||
|
||||
@ -309,7 +309,7 @@ ControlPipe::SendRequest(uint8 requestType, uint8 request, uint16 value,
|
||||
if (actualLength)
|
||||
*actualLength = 0;
|
||||
|
||||
CancelQueuedTransfers();
|
||||
CancelQueuedTransfers(false);
|
||||
return B_TIMED_OUT;
|
||||
}
|
||||
|
||||
|
@ -28,8 +28,13 @@ Stack::Stack()
|
||||
{
|
||||
TRACE(("USB Stack: stack init\n"));
|
||||
|
||||
if (benaphore_init(&fLock, "usb stack lock") < B_OK) {
|
||||
TRACE_ERROR(("USB Stack: failed to create benaphore lock\n"));
|
||||
if (benaphore_init(&fStackLock, "usb stack lock") < B_OK) {
|
||||
TRACE_ERROR(("USB Stack: failed to create stack lock\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (benaphore_init(&fExploreLock, "usb explore lock") < B_OK) {
|
||||
TRACE_ERROR(("USB Stack: failed to create explore lock\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -85,8 +90,10 @@ Stack::~Stack()
|
||||
fStopThreads = true;
|
||||
wait_for_thread(fExploreThread, &result);
|
||||
|
||||
Lock();
|
||||
benaphore_destroy(&fLock);
|
||||
benaphore_lock(&fStackLock);
|
||||
benaphore_destroy(&fStackLock);
|
||||
benaphore_lock(&fExploreLock);
|
||||
benaphore_destroy(&fExploreLock);
|
||||
|
||||
//Release the bus modules
|
||||
for (Vector<BusManager *>::Iterator i = fBusManagers.Begin();
|
||||
@ -111,14 +118,14 @@ Stack::InitCheck()
|
||||
bool
|
||||
Stack::Lock()
|
||||
{
|
||||
return (benaphore_lock(&fLock) == B_OK);
|
||||
return (benaphore_lock(&fStackLock) == B_OK);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Stack::Unlock()
|
||||
{
|
||||
benaphore_unlock(&fLock);
|
||||
benaphore_unlock(&fStackLock);
|
||||
}
|
||||
|
||||
|
||||
@ -189,13 +196,33 @@ Stack::ExploreThread(void *data)
|
||||
Stack *stack = (Stack *)data;
|
||||
|
||||
while (!stack->fStopThreads) {
|
||||
if (benaphore_lock(&stack->fExploreLock) != B_OK)
|
||||
break;
|
||||
|
||||
rescan_item *rescanList = NULL;
|
||||
change_item *changeItem = NULL;
|
||||
for (int32 i = 0; i < stack->fBusManagers.Count(); i++) {
|
||||
Hub *rootHub = stack->fBusManagers.ElementAt(i)->GetRootHub();
|
||||
if (rootHub)
|
||||
rootHub->Explore();
|
||||
rootHub->Explore(&changeItem);
|
||||
}
|
||||
|
||||
while (changeItem) {
|
||||
stack->NotifyDeviceChange(changeItem->device, &rescanList, changeItem->added);
|
||||
if (!changeItem->added) {
|
||||
// everyone possibly holding a reference is now notified so we
|
||||
// can delete the device
|
||||
changeItem->device->GetBusManager()->FreeDevice(changeItem->device);
|
||||
}
|
||||
|
||||
change_item *next = changeItem->link;
|
||||
delete changeItem;
|
||||
changeItem = next;
|
||||
}
|
||||
|
||||
stack->fFirstExploreDone = true;
|
||||
benaphore_unlock(&stack->fExploreLock);
|
||||
stack->RescanDrivers(rescanList);
|
||||
snooze(USB_DELAY_HUB_EXPLORE);
|
||||
}
|
||||
|
||||
@ -277,19 +304,33 @@ Stack::NotifyDeviceChange(Device *device, rescan_item **rescanList, bool added)
|
||||
while (element) {
|
||||
status_t result = device->ReportDevice(element->support_descriptors,
|
||||
element->support_descriptor_count, &element->notify_hooks,
|
||||
&element->cookies, added);
|
||||
&element->cookies, added, false);
|
||||
|
||||
if (result >= B_OK) {
|
||||
rescan_item *item = new(std::nothrow) rescan_item;
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
item->name = element->driver_name;
|
||||
const char *driverName = element->driver_name;
|
||||
if (element->republish_driver_name)
|
||||
item->name = element->republish_driver_name;
|
||||
driverName = element->republish_driver_name;
|
||||
|
||||
item->link = *rescanList;
|
||||
*rescanList = item;
|
||||
bool already = false;
|
||||
rescan_item *rescanItem = *rescanList;
|
||||
while (rescanItem) {
|
||||
if (strcmp(rescanItem->name, driverName) == 0) {
|
||||
// this driver is going to be rescanned already
|
||||
already = true;
|
||||
break;
|
||||
}
|
||||
rescanItem = rescanItem->link;
|
||||
}
|
||||
|
||||
if (!already) {
|
||||
rescanItem = new(std::nothrow) rescan_item;
|
||||
if (!rescanItem)
|
||||
return;
|
||||
|
||||
rescanItem->name = driverName;
|
||||
rescanItem->link = *rescanList;
|
||||
*rescanList = rescanItem;
|
||||
}
|
||||
}
|
||||
|
||||
element = element->link;
|
||||
@ -403,6 +444,9 @@ Stack::InstallNotify(const char *driverName, const usb_notify_hooks *hooks)
|
||||
usb_driver_info *element = fDriverList;
|
||||
while (element) {
|
||||
if (strcmp(element->driver_name, driverName) == 0) {
|
||||
if (benaphore_lock(&fExploreLock) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
// inform driver about any already present devices
|
||||
for (int32 i = 0; i < fBusManagers.Count(); i++) {
|
||||
Hub *rootHub = fBusManagers.ElementAt(i)->GetRootHub();
|
||||
@ -410,12 +454,13 @@ 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,
|
||||
&element->cookies, true);
|
||||
&element->cookies, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
element->notify_hooks.device_added = hooks->device_added;
|
||||
element->notify_hooks.device_removed = hooks->device_removed;
|
||||
benaphore_unlock(&fExploreLock);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -434,17 +479,21 @@ Stack::UninstallNotify(const char *driverName)
|
||||
usb_driver_info *element = fDriverList;
|
||||
while (element) {
|
||||
if (strcmp(element->driver_name, driverName) == 0) {
|
||||
if (benaphore_lock(&fExploreLock) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
// 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, &element->cookies, false, true);
|
||||
}
|
||||
|
||||
element->notify_hooks.device_added = NULL;
|
||||
element->notify_hooks.device_removed = NULL;
|
||||
benaphore_unlock(&fExploreLock);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
@ -318,7 +318,7 @@ cancel_queued_transfers(usb_pipe pipe)
|
||||
if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
|
||||
return B_DEV_INVALID_PIPE;
|
||||
|
||||
return ((Pipe *)object)->CancelQueuedTransfers();
|
||||
return ((Pipe *)object)->CancelQueuedTransfers(false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -60,6 +60,13 @@ struct usb_driver_info {
|
||||
};
|
||||
|
||||
|
||||
struct change_item {
|
||||
bool added;
|
||||
Device *device;
|
||||
change_item *link;
|
||||
};
|
||||
|
||||
|
||||
struct rescan_item {
|
||||
const char *name;
|
||||
rescan_item *link;
|
||||
@ -141,7 +148,8 @@ static int32 ExploreThread(void *data);
|
||||
bool fFirstExploreDone;
|
||||
bool fStopThreads;
|
||||
|
||||
benaphore fLock;
|
||||
benaphore fStackLock;
|
||||
benaphore fExploreLock;
|
||||
PhysicalMemoryAllocator *fAllocator;
|
||||
|
||||
uint32 fObjectIndex;
|
||||
@ -178,7 +186,8 @@ virtual status_t Start();
|
||||
virtual status_t Stop();
|
||||
|
||||
virtual status_t SubmitTransfer(Transfer *transfer);
|
||||
virtual status_t CancelQueuedTransfers(Pipe *pipe);
|
||||
virtual status_t CancelQueuedTransfers(Pipe *pipe,
|
||||
bool force);
|
||||
|
||||
virtual status_t NotifyPipeChange(Pipe *pipe,
|
||||
usb_change change);
|
||||
@ -260,7 +269,7 @@ virtual bool DataToggle() { return fDataToggle; };
|
||||
virtual void SetDataToggle(bool toggle) { fDataToggle = toggle; };
|
||||
|
||||
status_t SubmitTransfer(Transfer *transfer);
|
||||
status_t CancelQueuedTransfers();
|
||||
status_t CancelQueuedTransfers(bool force);
|
||||
|
||||
// Convenience functions for standard requests
|
||||
virtual status_t SetFeature(uint16 selector);
|
||||
@ -414,6 +423,9 @@ virtual ~Device();
|
||||
|
||||
status_t InitCheck();
|
||||
|
||||
virtual status_t Changed(change_item **changeList,
|
||||
bool added);
|
||||
|
||||
virtual uint32 Type() { return USB_OBJECT_DEVICE; };
|
||||
|
||||
ControlPipe *DefaultPipe() { return fDefaultPipe; };
|
||||
@ -437,7 +449,7 @@ virtual status_t ReportDevice(
|
||||
uint32 supportDescriptorCount,
|
||||
const usb_notify_hooks *hooks,
|
||||
usb_driver_cookie **cookies,
|
||||
bool added);
|
||||
bool added, bool recursive);
|
||||
virtual status_t BuildDeviceName(char *string,
|
||||
uint32 *index, size_t bufferSize,
|
||||
Device *device);
|
||||
@ -452,6 +464,7 @@ protected:
|
||||
bool fInitOK;
|
||||
|
||||
private:
|
||||
bool fAvailable;
|
||||
usb_configuration_info *fConfigurations;
|
||||
usb_configuration_info *fCurrentConfiguration;
|
||||
usb_speed fSpeed;
|
||||
@ -468,8 +481,8 @@ public:
|
||||
usb_speed speed);
|
||||
virtual ~Hub();
|
||||
|
||||
bool Lock();
|
||||
void Unlock();
|
||||
virtual status_t Changed(change_item **changeList,
|
||||
bool added);
|
||||
|
||||
virtual uint32 Type() { return USB_OBJECT_DEVICE | USB_OBJECT_HUB; };
|
||||
|
||||
@ -480,7 +493,7 @@ virtual status_t GetDescriptor(uint8 descriptorType,
|
||||
|
||||
status_t UpdatePortStatus(uint8 index);
|
||||
status_t ResetPort(uint8 index);
|
||||
void Explore();
|
||||
void Explore(change_item **changeList);
|
||||
static void InterruptCallback(void *cookie,
|
||||
status_t status, void *data,
|
||||
size_t actualLength);
|
||||
@ -490,14 +503,12 @@ virtual status_t ReportDevice(
|
||||
uint32 supportDescriptorCount,
|
||||
const usb_notify_hooks *hooks,
|
||||
usb_driver_cookie **cookies,
|
||||
bool added);
|
||||
bool added, bool recursive);
|
||||
virtual status_t BuildDeviceName(char *string,
|
||||
uint32 *index, size_t bufferSize,
|
||||
Device *device);
|
||||
|
||||
private:
|
||||
benaphore fLock;
|
||||
|
||||
InterruptPipe *fInterruptPipe;
|
||||
usb_hub_descriptor fHubDescriptor;
|
||||
|
||||
|
@ -864,7 +864,7 @@ EHCI::AddPendingTransfer(Transfer *transfer, ehci_qh *queueHead,
|
||||
|
||||
|
||||
status_t
|
||||
EHCI::CancelQueuedTransfers(Pipe *pipe)
|
||||
EHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
|
||||
{
|
||||
if (!Lock())
|
||||
return B_ERROR;
|
||||
@ -879,7 +879,13 @@ EHCI::CancelQueuedTransfers(Pipe *pipe)
|
||||
descriptor = (ehci_qtd *)descriptor->next_log;
|
||||
}
|
||||
|
||||
current->transfer->Finished(B_CANCELED, 0);
|
||||
if (!force) {
|
||||
// if the transfer is canceled by force, the one causing the
|
||||
// cancel is probably not the one who initiated the transfer
|
||||
// and the callback is likely not safe anymore
|
||||
current->transfer->Finished(B_CANCELED, 0);
|
||||
}
|
||||
|
||||
current->canceled = true;
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ public:
|
||||
virtual status_t SubmitTransfer(Transfer *transfer);
|
||||
status_t SubmitPeriodicTransfer(Transfer *transfer);
|
||||
status_t SubmitAsyncTransfer(Transfer *transfer);
|
||||
virtual status_t CancelQueuedTransfers(Pipe *pipe);
|
||||
virtual status_t CancelQueuedTransfers(Pipe *pipe, bool force);
|
||||
|
||||
virtual status_t NotifyPipeChange(Pipe *pipe,
|
||||
usb_change change);
|
||||
|
@ -791,7 +791,7 @@ OHCI::_ReadReg(uint32 reg)
|
||||
|
||||
|
||||
status_t
|
||||
OHCI::CancelQueuedTransfers(Pipe *pipe)
|
||||
OHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
@ -57,7 +57,8 @@ public:
|
||||
|
||||
status_t Start();
|
||||
virtual status_t SubmitTransfer(Transfer *transfer);
|
||||
virtual status_t CancelQueuedTransfers(Pipe *pipe);
|
||||
virtual status_t CancelQueuedTransfers(Pipe *pipe,
|
||||
bool force);
|
||||
status_t SubmitRequest(Transfer *transfer);
|
||||
|
||||
virtual status_t NotifyPipeChange(Pipe *pipe,
|
||||
|
@ -603,7 +603,7 @@ UHCI::SubmitTransfer(Transfer *transfer)
|
||||
|
||||
|
||||
status_t
|
||||
UHCI::CancelQueuedTransfers(Pipe *pipe)
|
||||
UHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
|
||||
{
|
||||
if (pipe->Type() & USB_OBJECT_ISO_PIPE)
|
||||
return CancelQueuedIsochronousTransfers(pipe);
|
||||
@ -621,7 +621,13 @@ UHCI::CancelQueuedTransfers(Pipe *pipe)
|
||||
descriptor = (uhci_td *)descriptor->link_log;
|
||||
}
|
||||
|
||||
current->transfer->Finished(B_CANCELED, 0);
|
||||
if (!force) {
|
||||
// if the transfer is canceled by force, the one causing the
|
||||
// cancel is probably not the one who initiated the transfer
|
||||
// and the callback is likely not safe anymore
|
||||
current->transfer->Finished(B_CANCELED, 0);
|
||||
}
|
||||
|
||||
current->canceled = true;
|
||||
}
|
||||
current = current->link;
|
||||
|
@ -91,7 +91,7 @@ public:
|
||||
|
||||
status_t Start();
|
||||
virtual status_t SubmitTransfer(Transfer *transfer);
|
||||
virtual status_t CancelQueuedTransfers(Pipe *pipe);
|
||||
virtual status_t CancelQueuedTransfers(Pipe *pipe, bool force);
|
||||
status_t CancelQueuedIsochronousTransfers(Pipe *pipe);
|
||||
status_t SubmitRequest(Transfer *transfer);
|
||||
status_t SubmitIsochronous(Transfer *transfer);
|
||||
|
Loading…
Reference in New Issue
Block a user