USB: Check and set the Device object state appropriately.
The Device object gets an ID before it begins initializing, and loses its ID after it fully finishes tearing down, so simply verifying the Device object is non-NULL is not enough to verify that we can use it. We need to call InitCheck() every time. In Device itself, we should also unset fInitOK when beginning teardown, so that anyone who still has a handle can no longer use this Device object while teardown occurs (which, depending on the number of pipes, pending transfers, etc. may take some time.) Fixes #14949 and almost certainly any other USB-related KDLs in these codepaths.
This commit is contained in:
@@ -321,6 +321,9 @@ Device::Device(Object* parent, int8 hubAddress, uint8 hubPort,
|
||||
|
||||
Device::~Device()
|
||||
{
|
||||
// Unset fInitOK to indicate we are tearing down.
|
||||
fInitOK = false;
|
||||
|
||||
delete fDefaultPipe;
|
||||
|
||||
if (fConfigurations == NULL) {
|
||||
|
||||
@@ -219,65 +219,80 @@ uninstall_notify(const char *driverName)
|
||||
|
||||
|
||||
const usb_device_descriptor *
|
||||
get_device_descriptor(usb_device device)
|
||||
get_device_descriptor(usb_device dev)
|
||||
{
|
||||
TRACE_MODULE("get_device_descriptor(%" B_PRId32 ")\n", device);
|
||||
Object *object = gUSBStack->GetObject(device);
|
||||
TRACE_MODULE("get_device_descriptor(%" B_PRId32 ")\n", dev);
|
||||
Object *object = gUSBStack->GetObject(dev);
|
||||
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
|
||||
return NULL;
|
||||
Device *device = (Device *)object;
|
||||
if (device->InitCheck() != B_OK)
|
||||
return NULL;
|
||||
|
||||
return ((Device *)object)->DeviceDescriptor();
|
||||
return device->DeviceDescriptor();
|
||||
}
|
||||
|
||||
|
||||
const usb_configuration_info *
|
||||
get_nth_configuration(usb_device device, uint32 index)
|
||||
get_nth_configuration(usb_device dev, uint32 index)
|
||||
{
|
||||
TRACE_MODULE("get_nth_configuration(%" B_PRId32 ", %" B_PRIu32 ")\n",
|
||||
device, index);
|
||||
Object *object = gUSBStack->GetObject(device);
|
||||
dev, index);
|
||||
Object *object = gUSBStack->GetObject(dev);
|
||||
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
|
||||
return NULL;
|
||||
Device *device = (Device *)object;
|
||||
if (device->InitCheck() != B_OK)
|
||||
return NULL;
|
||||
|
||||
return ((Device *)object)->ConfigurationAt((int32)index);
|
||||
return device->ConfigurationAt((int32)index);
|
||||
}
|
||||
|
||||
|
||||
const usb_configuration_info *
|
||||
get_configuration(usb_device device)
|
||||
get_configuration(usb_device dev)
|
||||
{
|
||||
TRACE_MODULE("get_configuration(%" B_PRId32 ")\n", device);
|
||||
Object *object = gUSBStack->GetObject(device);
|
||||
TRACE_MODULE("get_configuration(%" B_PRId32 ")\n", dev);
|
||||
Object *object = gUSBStack->GetObject(dev);
|
||||
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
|
||||
return NULL;
|
||||
Device *device = (Device *)object;
|
||||
if (device->InitCheck() != B_OK)
|
||||
return NULL;
|
||||
|
||||
return ((Device *)object)->Configuration();
|
||||
return device->Configuration();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
set_configuration(usb_device device,
|
||||
set_configuration(usb_device dev,
|
||||
const usb_configuration_info *configuration)
|
||||
{
|
||||
TRACE_MODULE("set_configuration(%" B_PRId32 ", %p)\n", device,
|
||||
TRACE_MODULE("set_configuration(%" B_PRId32 ", %p)\n", dev,
|
||||
configuration);
|
||||
Object *object = gUSBStack->GetObject(device);
|
||||
Object *object = gUSBStack->GetObject(dev);
|
||||
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
|
||||
return B_DEV_INVALID_PIPE;
|
||||
Device *device = (Device *)object;
|
||||
if (device->InitCheck() != B_OK)
|
||||
return B_NO_INIT;
|
||||
|
||||
return ((Device *)object)->SetConfiguration(configuration);
|
||||
return device->SetConfiguration(configuration);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
set_alt_interface(usb_device device, const usb_interface_info *interface)
|
||||
set_alt_interface(usb_device dev, const usb_interface_info *interface)
|
||||
{
|
||||
TRACE_MODULE("set_alt_interface(%" B_PRId32 ", %p)\n", device, interface);
|
||||
Object *object = gUSBStack->GetObject(device);
|
||||
TRACE_MODULE("set_alt_interface(%" B_PRId32 ", %p)\n", dev, interface);
|
||||
Object *object = gUSBStack->GetObject(dev);
|
||||
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
|
||||
return B_DEV_INVALID_PIPE;
|
||||
Device *device = (Device *)object;
|
||||
if (device->InitCheck() != B_OK)
|
||||
return B_NO_INIT;
|
||||
|
||||
return ((Device *)object)->SetAltInterface(interface);
|
||||
return device->SetAltInterface(interface);
|
||||
}
|
||||
|
||||
|
||||
@@ -321,50 +336,59 @@ get_status(usb_id handle, uint16 *status)
|
||||
|
||||
|
||||
status_t
|
||||
get_descriptor(usb_device device, uint8 type, uint8 index, uint16 languageID,
|
||||
get_descriptor(usb_device dev, uint8 type, uint8 index, uint16 languageID,
|
||||
void *data, size_t dataLength, size_t *actualLength)
|
||||
{
|
||||
TRACE_MODULE("get_descriptor(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, %p, "
|
||||
"%" B_PRIuSIZE ", %p)\n",
|
||||
device, type, index, languageID, data, dataLength, actualLength);
|
||||
Object *object = gUSBStack->GetObject(device);
|
||||
dev, type, index, languageID, data, dataLength, actualLength);
|
||||
Object *object = gUSBStack->GetObject(dev);
|
||||
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
|
||||
return B_DEV_INVALID_PIPE;
|
||||
Device *device = (Device *)object;
|
||||
if (device->InitCheck() != B_OK)
|
||||
return B_NO_INIT;
|
||||
|
||||
return ((Device *)object)->GetDescriptor(type, index, languageID,
|
||||
return device->GetDescriptor(type, index, languageID,
|
||||
data, dataLength, actualLength);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
send_request(usb_device device, uint8 requestType, uint8 request,
|
||||
send_request(usb_device dev, uint8 requestType, uint8 request,
|
||||
uint16 value, uint16 index, uint16 length, void *data, size_t *actualLength)
|
||||
{
|
||||
TRACE_MODULE("send_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x, "
|
||||
"%d, %p, %p)\n", device, requestType, request, value, index, length,
|
||||
"%d, %p, %p)\n", dev, requestType, request, value, index, length,
|
||||
data, actualLength);
|
||||
Object *object = gUSBStack->GetObject(device);
|
||||
Object *object = gUSBStack->GetObject(dev);
|
||||
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
|
||||
return B_DEV_INVALID_PIPE;
|
||||
Device *device = (Device *)object;
|
||||
if (device->InitCheck() != B_OK)
|
||||
return B_NO_INIT;
|
||||
|
||||
return ((Device *)object)->DefaultPipe()->SendRequest(requestType, request,
|
||||
return device->DefaultPipe()->SendRequest(requestType, request,
|
||||
value, index, length, data, length, actualLength);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
queue_request(usb_device device, uint8 requestType, uint8 request,
|
||||
queue_request(usb_device dev, uint8 requestType, uint8 request,
|
||||
uint16 value, uint16 index, uint16 length, void *data,
|
||||
usb_callback_func callback, void *callbackCookie)
|
||||
{
|
||||
TRACE_MODULE("queue_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x,"
|
||||
" %u, %p, %p, %p)\n", device, requestType, request, value, index,
|
||||
" %u, %p, %p, %p)\n", dev, requestType, request, value, index,
|
||||
length, data, callback, callbackCookie);
|
||||
Object *object = gUSBStack->GetObject(device);
|
||||
Object *object = gUSBStack->GetObject(dev);
|
||||
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
|
||||
return B_DEV_INVALID_PIPE;
|
||||
Device *device = (Device *)object;
|
||||
if (device->InitCheck() != B_OK)
|
||||
return B_NO_INIT;
|
||||
|
||||
return ((Device *)object)->DefaultPipe()->QueueRequest(requestType,
|
||||
return device->DefaultPipe()->QueueRequest(requestType,
|
||||
request, value, index, length, data, length, callback, callbackCookie);
|
||||
}
|
||||
|
||||
@@ -487,9 +511,12 @@ usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize)
|
||||
Object *object = gUSBStack->GetObject(*(usb_id *)buffer);
|
||||
if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
|
||||
return B_BAD_VALUE;
|
||||
Device *device = (Device *)object;
|
||||
if (device->InitCheck() != B_OK)
|
||||
return B_NO_INIT;
|
||||
|
||||
uint32 index = 0;
|
||||
return ((Device *)object)->BuildDeviceName((char *)buffer, &index,
|
||||
return device->BuildDeviceName((char *)buffer, &index,
|
||||
bufferSize, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user