* Clear the endpoints of an alternate interface that is going away before

updating the active pointer as otherwise the endpoints of the new alternate
  would have been cleared instead of the old one (leaking endpoints).
* Only clear and re-initialize the endpoints of the interface we are setting
  an alterntate. Otherwise we tear down all the device endpoints which would
  result in a bad situation for composite devices where multiple drivers may
  use different functions (through different interfaces) of a device side by
  side.
* Minor cleanup.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25432 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2008-05-10 21:09:44 +00:00
parent 899aa8e1f6
commit bb90c2a603
2 changed files with 22 additions and 12 deletions
+20 -10
View File
@@ -370,7 +370,7 @@ Device::SetConfigurationAt(uint8 index)
fCurrentConfiguration = &fConfigurations[index]; fCurrentConfiguration = &fConfigurations[index];
// Initialize all the endpoints that are now active // Initialize all the endpoints that are now active
InitEndpoints(); InitEndpoints(-1);
// Wait some for the configuration being finished // Wait some for the configuration being finished
if (!fIsRootHub) if (!fIsRootHub)
@@ -380,13 +380,16 @@ Device::SetConfigurationAt(uint8 index)
void void
Device::InitEndpoints() Device::InitEndpoints(int32 interfaceIndex)
{ {
int8 hubAddress = 0; int8 hubAddress = 0;
if (Parent() && (Parent()->Type() & USB_OBJECT_HUB)) if (Parent() && (Parent()->Type() & USB_OBJECT_HUB))
hubAddress = ((Hub *)Parent())->DeviceAddress(); hubAddress = ((Hub *)Parent())->DeviceAddress();
for (size_t j = 0; j < fCurrentConfiguration->interface_count; j++) { for (size_t j = 0; j < fCurrentConfiguration->interface_count; j++) {
if (interfaceIndex >= 0 && j != (size_t)interfaceIndex)
continue;
usb_interface_info *interfaceInfo = fCurrentConfiguration->interface[j].active; usb_interface_info *interfaceInfo = fCurrentConfiguration->interface[j].active;
for (size_t i = 0; i < interfaceInfo->endpoint_count; i++) { for (size_t i = 0; i < interfaceInfo->endpoint_count; i++) {
usb_endpoint_info *endpoint = &interfaceInfo->endpoint[i]; usb_endpoint_info *endpoint = &interfaceInfo->endpoint[i];
@@ -424,6 +427,7 @@ Device::InitEndpoints()
} }
} }
status_t status_t
Device::Unconfigure(bool atDeviceLevel) Device::Unconfigure(bool atDeviceLevel)
{ {
@@ -450,17 +454,20 @@ Device::Unconfigure(bool atDeviceLevel)
if (!fCurrentConfiguration) if (!fCurrentConfiguration)
return B_OK; return B_OK;
ClearEndpoints();
ClearEndpoints(-1);
fCurrentConfiguration = NULL; fCurrentConfiguration = NULL;
return B_OK; return B_OK;
} }
void void
Device::ClearEndpoints() Device::ClearEndpoints(int32 interfaceIndex)
{ {
for (size_t j = 0; j < fCurrentConfiguration->interface_count; j++) { for (size_t j = 0; j < fCurrentConfiguration->interface_count; j++) {
if (interfaceIndex >= 0 && j != (size_t)interfaceIndex)
continue;
usb_interface_info *interfaceInfo = fCurrentConfiguration->interface[j].active; usb_interface_info *interfaceInfo = fCurrentConfiguration->interface[j].active;
for (size_t i = 0; i < interfaceInfo->endpoint_count; i++) { for (size_t i = 0; i < interfaceInfo->endpoint_count; i++) {
usb_endpoint_info *endpoint = &interfaceInfo->endpoint[i]; usb_endpoint_info *endpoint = &interfaceInfo->endpoint[i];
@@ -474,12 +481,13 @@ Device::ClearEndpoints()
status_t status_t
Device::SetAltInterface(const usb_interface_info *interface) Device::SetAltInterface(const usb_interface_info *interface)
{ {
uint8 interfaceNumber = interface->descr->interface_number;
// Tell the device to set the alternate settings // Tell the device to set the alternate settings
status_t result = fDefaultPipe->SendRequest( status_t result = fDefaultPipe->SendRequest(
USB_REQTYPE_INTERFACE_OUT | USB_REQTYPE_STANDARD, // type USB_REQTYPE_INTERFACE_OUT | USB_REQTYPE_STANDARD, // type
USB_REQUEST_SET_INTERFACE, // request USB_REQUEST_SET_INTERFACE, // request
interface->descr->alternate_setting, // value interface->descr->alternate_setting, // value
interface->descr->interface_number, // index interfaceNumber, // index
0, // length 0, // length
NULL, // buffer NULL, // buffer
0, // buffer length 0, // buffer length
@@ -488,15 +496,17 @@ Device::SetAltInterface(const usb_interface_info *interface)
if (result < B_OK) if (result < B_OK)
return result; return result;
// Update descriptor // Clear the no longer active endpoints
ClearEndpoints(interfaceNumber);
// Update the active pointer of the interface list
usb_interface_list *interfaceList usb_interface_list *interfaceList
= &fCurrentConfiguration->interface[interface->descr->interface_number]; = &fCurrentConfiguration->interface[interfaceNumber];
interfaceList->active interfaceList->active
= &interfaceList->alt[interface->descr->alternate_setting]; = &interfaceList->alt[interface->descr->alternate_setting];
ClearEndpoints(); // Initialize the new endpoints
InitEndpoints(); InitEndpoints(interfaceNumber);
return result; return result;
} }
+2 -2
View File
@@ -443,8 +443,8 @@ virtual status_t GetDescriptor(uint8 descriptorType,
status_t SetAltInterface(const usb_interface_info *interface); status_t SetAltInterface(const usb_interface_info *interface);
void InitEndpoints(); void InitEndpoints(int32 interfaceIndex);
void ClearEndpoints(); void ClearEndpoints(int32 interfaceIndex);
virtual status_t ReportDevice( virtual status_t ReportDevice(
usb_support_descriptor *supportDescriptors, usb_support_descriptor *supportDescriptors,