/** Remove the device and all its children from the bus. @param Device The device to remove. @retval EFI_SUCCESS The device is removed. **/ EFI_STATUS UsbRemoveDevice ( IN USB_DEVICE *Device ) { USB_BUS *Bus; USB_DEVICE *Child; EFI_STATUS Status; EFI_STATUS ReturnStatus; UINTN Index; Bus = Device->Bus; // // Remove all the devices on its downstream ports. Search from devices[1]. // Devices[0] is the root hub. // ReturnStatus = EFI_SUCCESS; for (Index = 1; Index < Bus->MaxDevices; Index++) { Child = Bus->Devices[Index]; if ((Child == NULL) || (Child->ParentAddr != Device->Address)) { continue; } DBG("Remove child %d\n", Index); Status = UsbRemoveDevice (Child); if (!EFI_ERROR (Status)) { Bus->Devices[Index] = NULL; } else { Bus->Devices[Index]->DisconnectFail = TRUE; ReturnStatus = Status; // DEBUG ((EFI_D_INFO, "UsbRemoveDevice: failed to remove child %p at parent %p\n", Child, Device)); DBG("UsbRemoveDevice: failed to remove child %p at parent %p\n", Child, Device); } } if (EFI_ERROR (ReturnStatus)) { return ReturnStatus; } Status = UsbRemoveConfig (Device); if (!EFI_ERROR (Status)) { // DEBUG (( EFI_D_INFO, "UsbRemoveDevice: device %d removed\n", Device->Address)); DBG("UsbRemoveDevice: device %d removed\n", Device->Address); // ASSERT (Device->Address < Bus->MaxDevices); if (Device->Address >= Bus->MaxDevices) { DBG("Device->Address=%d > %d\n", Device->Address, Bus->MaxDevices); return EFI_DEVICE_ERROR; } Bus->Devices[Device->Address] = NULL; UsbFreeDevice (Device); } else { Bus->Devices[Device->Address]->DisconnectFail = TRUE; } return Status; }
EFI_STATUS UsbRemoveDevice ( IN USB_DEVICE *Device ) /*++ Routine Description: Remove the device and all its children from the bus. Arguments: Device - The device to remove Returns: EFI_SUCCESS - The device is removed --*/ { USB_BUS *Bus; USB_DEVICE *Child; EFI_STATUS Status; UINT8 Index; Bus = Device->Bus; // // Remove all the devices on its downstream ports. Search from devices[1]. // Devices[0] is the root hub. // for (Index = 1; Index < USB_MAX_DEVICES; Index++) { Child = Bus->Devices[Index]; if ((Child == NULL) || (Child->ParentAddr != Device->Address)) { continue; } Status = UsbRemoveDevice (Child); if (EFI_ERROR (Status)) { USB_ERROR (("UsbRemoveDevice: failed to remove child, ignore error\n")); Bus->Devices[Index] = NULL; } } UsbRemoveConfig (Device); USB_DEBUG (("UsbRemoveDevice: device %d removed\n", Device->Address)); Bus->Devices[Device->Address] = NULL; UsbFreeDevice (Device); return EFI_SUCCESS; }
/** Remove the device and all its children from the bus. @param Device The device to remove. @retval EFI_SUCCESS The device is removed. **/ EFI_STATUS UsbRemoveDevice ( IN USB_DEVICE *Device ) { USB_BUS *Bus; USB_DEVICE *Child; EFI_STATUS Status; UINTN Index; Bus = Device->Bus; // // Remove all the devices on its downstream ports. Search from devices[1]. // Devices[0] is the root hub. // for (Index = 1; Index < Bus->MaxDevices; Index++) { Child = Bus->Devices[Index]; if ((Child == NULL) || (Child->ParentAddr != Device->Address)) { continue; } Status = UsbRemoveDevice (Child); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "UsbRemoveDevice: failed to remove child, ignore error\n")); Bus->Devices[Index] = NULL; } } UsbRemoveConfig (Device); DEBUG (( EFI_D_INFO, "UsbRemoveDevice: device %d removed\n", Device->Address)); ASSERT (Device->Address < Bus->MaxDevices); Bus->Devices[Device->Address] = NULL; UsbFreeDevice (Device); return EFI_SUCCESS; }
STATIC EFI_STATUS UsbEnumerateNewDev ( IN USB_INTERFACE *HubIf, IN UINT8 Port ) /*++ Routine Description: Enumerate and configure the new device on the port of this HUB interface. Arguments: HubIf - The HUB that has the device connected Port - The port index of the hub (started with zero) Returns: EFI_SUCCESS - The device is enumerated (added or removed) EFI_OUT_OF_RESOURCES - Failed to allocate resource for the device Others - Failed to enumerate the device --*/ { USB_BUS *Bus; USB_HUB_API *HubApi; USB_DEVICE *Child; USB_DEVICE *Parent; EFI_USB_PORT_STATUS PortState; UINT8 Address; UINT8 Config; EFI_STATUS Status; Address = USB_MAX_DEVICES; Parent = HubIf->Device; Bus = Parent->Bus; HubApi = HubIf->HubApi; gBS->Stall (USB_WAIT_PORT_STABLE_STALL); // // Hub resets the device for at least 10 milliseconds. // Host learns device speed. If device is of low/full speed // and the hub is a EHCI root hub, ResetPort will release // the device to its companion UHCI and return an error. // Status = HubApi->ResetPort (HubIf, Port); if (EFI_ERROR (Status)) { USB_ERROR (("UsbEnumerateNewDev: failed to reset port %d - %r\n", Port, Status)); return Status; } USB_DEBUG (("UsbEnumerateNewDev: hub port %d is reset\n", Port)); Child = UsbCreateDevice (HubIf, Port); if (Child == NULL) { return EFI_OUT_OF_RESOURCES; } // // OK, now identify the device speed. After reset, hub // fully knows the actual device speed. // Status = HubApi->GetPortStatus (HubIf, Port, &PortState); if (EFI_ERROR (Status)) { USB_ERROR (("UsbEnumerateNewDev: failed to get speed of port %d\n", Port)); goto ON_ERROR; } if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_LOW_SPEED)) { Child->Speed = EFI_USB_SPEED_LOW; } else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_HIGH_SPEED)) { Child->Speed = EFI_USB_SPEED_HIGH; } else { Child->Speed = EFI_USB_SPEED_FULL; } USB_DEBUG (("UsbEnumerateNewDev: device is of %d speed\n", Child->Speed)); if (Child->Speed != EFI_USB_SPEED_HIGH) { // // If the child isn't a high speed device, it is necessary to // set the transaction translator. Port TT is 1-based. // This is quite simple: // 1. if parent is of high speed, then parent is our translator // 2. otherwise use parent's translator. // if (Parent->Speed == EFI_USB_SPEED_HIGH) { Child->Translator.TranslatorHubAddress = Parent->Address; Child->Translator.TranslatorPortNumber = Port + 1; } else { Child->Translator = Parent->Translator; } USB_DEBUG (("UsbEnumerateNewDev: device uses translator (%d, %d)\n", Child->Translator.TranslatorHubAddress, Child->Translator.TranslatorPortNumber)); } // // After port is reset, hub establishes a signal path between // the device and host (DEFALUT state). Device¡¯s registers are // reset, use default address 0 (host enumerates one device at // a time) , and ready to respond to control transfer at EP 0. // // // Host sends a Get_Descriptor request to learn the max packet // size of default pipe (only part of the device¡¯s descriptor). // Status = UsbGetMaxPacketSize0 (Child); if (EFI_ERROR (Status)) { USB_ERROR (("UsbEnumerateNewDev: failed to get max packet for EP 0 - %r\n", Status)); goto ON_ERROR; } USB_DEBUG (("UsbEnumerateNewDev: max packet size for EP 0 is %d\n", Child->MaxPacket0)); // // Host assigns an address to the device. Device completes the // status stage with default address, then switches to new address. // ADDRESS state. Address zero is reserved for root hub. // for (Address = 1; Address < USB_MAX_DEVICES; Address++) { if (Bus->Devices[Address] == NULL) { break; } } if (Address == USB_MAX_DEVICES) { USB_ERROR (("UsbEnumerateNewDev: address pool is full for port %d\n", Port)); Status = EFI_ACCESS_DENIED; goto ON_ERROR; } Bus->Devices[Address] = Child; Status = UsbSetAddress (Child, Address); Child->Address = Address; if (EFI_ERROR (Status)) { USB_ERROR (("UsbEnumerateNewDev: failed to set device address - %r\n", Status)); goto ON_ERROR; } gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL); USB_DEBUG (("UsbEnumerateNewDev: device is now ADDRESSED at %d\n", Address)); // // Host learns about the device¡¯s abilities by requesting device's // entire descriptions. // Status = UsbBuildDescTable (Child); if (EFI_ERROR (Status)) { USB_ERROR (("UsbEnumerateNewDev: failed to build descriptor table - %r\n", Status)); goto ON_ERROR; } // // Select a default configuration: UEFI must set the configuration // before the driver can connect to the device. // Config = Child->DevDesc->Configs[0]->Desc.ConfigurationValue; Status = UsbSetConfig (Child, Config); if (EFI_ERROR (Status)) { USB_ERROR (("UsbEnumerateNewDev: failed to set configure %d - %r\n", Config, Status)); goto ON_ERROR; } USB_DEBUG (("UsbEnumerateNewDev: device %d is now in CONFIGED state\n", Address)); // // Host assigns and loads a device driver. // Status = UsbSelectConfig (Child, Config); if (EFI_ERROR (Status)) { USB_ERROR (("UsbEnumerateNewDev: failed to create interfaces - %r\n", Status)); goto ON_ERROR; } return EFI_SUCCESS; ON_ERROR: if (Address != USB_MAX_DEVICES) { Bus->Devices[Address] = NULL; } if (Child != NULL) { UsbFreeDevice (Child); } return Status; }