usbbus.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,516 行 · 第 1/5 页
C
2,516 行
Arguments:
ParentHubController - Parent Hub which this device is connected.
HostController - Host Controller handle
ParentPort - Parent Hub port which this device is connected.
UsbIoDevice - The device to be configured.
Returns:
EFI_SUCCESS
EFI_DEVICE_ERROR
EFI_OUT_OF_RESOURCES
--*/
{
UINT8 DevAddress;
UINT8 Index;
EFI_STATUS Result;
UINT32 Status;
CHAR16 *StrManufacturer;
CHAR16 *StrProduct;
CHAR16 *StrSerialNumber;
EFI_USB_IO_PROTOCOL *UsbIo;
UINT8 NumOfInterface;
USB_IO_CONTROLLER_DEVICE *FirstController;
USB_BUS_CONTROLLER_DEVICE *UsbBusDev;
USB_IO_CONTROLLER_DEVICE *UsbIoController;
UsbBusDev = UsbIoDevice->BusController;
UsbSetTransactionTranslator (
ParentHubController,
ParentPort,
UsbIoDevice
);
//
// Since a USB device must have at least on interface,
// so create this instance first
//
FirstController = CreateUsbIoControllerDevice ();
FirstController->UsbDevice = UsbIoDevice;
UsbIoDevice->UsbController[0] = FirstController;
FirstController->InterfaceNumber = 0;
FirstController->ParentPort = ParentPort;
FirstController->Parent = ParentHubController;
FirstController->HostController = HostController;
InitializeUsbIoInstance (FirstController);
DEBUG ((gUSBDebugLevel, "Configuration Usb Device at 0x%x...\n", ParentPort));
//
// Ensure we used the correctly USB I/O instance
//
UsbIo = &FirstController->UsbIo;
if (UsbIoDevice->DeviceSpeed != EFI_USB_SPEED_HIGH) {
ParentPortReset (FirstController, FALSE, 0);
}
//
// First retrieve the 1st 8 bytes of
// in order to get the MaxPacketSize for Endpoint 0
//
for (Index = 0; Index < 3; Index++) {
UsbIoDevice->DeviceDescriptor.MaxPacketSize0 = 8;
gBS->Stall (100 * 1000);
Result = UsbGetDescriptor (
UsbIo,
(USB_DT_DEVICE << 8),
0,
8,
&UsbIoDevice->DeviceDescriptor,
&Status
);
if (!EFI_ERROR (Result)) {
DEBUG (
(gUSBDebugLevel,
"Get Device Descriptor Success, MaxPacketSize0 = 0x%x\n",
UsbIoDevice->DeviceDescriptor.MaxPacketSize0)
);
break;
}
}
if (Index == 3) {
ReportUsbStatusCode (
UsbBusDev,
EFI_ERROR_CODE | EFI_ERROR_MINOR,
EFI_IO_BUS_USB | EFI_IOB_EC_READ_ERROR
);
DEBUG ((gUSBErrorLevel, "Get Device Descriptor Fail when configing\n"));
gBS->FreePool (FirstController);
return EFI_DEVICE_ERROR;
}
DevAddress = UsbAllocateAddress (UsbIoDevice->BusController->AddressPool);
if (DevAddress == 0) {
DEBUG ((gUSBErrorLevel, "Cannot allocate address\n"));
gBS->FreePool (FirstController);
return EFI_OUT_OF_RESOURCES;
}
Result = UsbSetDeviceAddress (UsbIo, DevAddress, &Status);
if (EFI_ERROR (Result)) {
DEBUG ((gUSBErrorLevel, "Set address error\n"));
ReportUsbStatusCode (
UsbBusDev,
EFI_ERROR_CODE | EFI_ERROR_MINOR,
EFI_IO_BUS_USB | EFI_IOB_EC_WRITE_ERROR
);
UsbFreeAddress (
DevAddress,
UsbIoDevice->BusController->AddressPool
);
gBS->FreePool (FirstController);
return EFI_DEVICE_ERROR;
}
UsbIoDevice->DeviceAddress = DevAddress;
//
// SetAddress Complete Time by Spec, Max 50ms
//
gBS->Stall (10 * 1000);
//
// Get the whole device descriptor
//
Result = UsbGetDescriptor (
UsbIo,
(USB_DT_DEVICE << 8),
0,
sizeof (EFI_USB_DEVICE_DESCRIPTOR),
&UsbIoDevice->DeviceDescriptor,
&Status
);
if (EFI_ERROR (Result)) {
DEBUG ((gUSBErrorLevel, "Get whole Device Descriptor error\n"));
ReportUsbStatusCode (
UsbBusDev,
EFI_ERROR_CODE | EFI_ERROR_MINOR,
EFI_IO_BUS_USB | EFI_IOB_EC_READ_ERROR
);
UsbFreeAddress (
DevAddress,
UsbIoDevice->BusController->AddressPool
);
gBS->FreePool (FirstController);
return EFI_DEVICE_ERROR;
}
//
// Get & parse all configurations for this device, including
// all configuration descriptors, all interface descriptors, all
// endpoint descriptors
//
Result = UsbGetAllConfigurations (UsbIoDevice);
if (EFI_ERROR (Result)) {
DEBUG ((gUSBErrorLevel, "Failed to get device configuration\n"));
ReportUsbStatusCode (
UsbBusDev,
EFI_ERROR_CODE | EFI_ERROR_MINOR,
EFI_IO_BUS_USB | EFI_IOB_EC_READ_ERROR
);
UsbFreeAddress (
DevAddress,
UsbIoDevice->BusController->AddressPool
);
gBS->FreePool (FirstController);
return EFI_DEVICE_ERROR;
}
//
// Set the 1st configuration value
//
Result = UsbSetDefaultConfiguration (UsbIoDevice);
if (EFI_ERROR (Result)) {
DEBUG ((gUSBErrorLevel, "Failed to set device configuration\n"));
ReportUsbStatusCode (
UsbBusDev,
EFI_ERROR_CODE | EFI_ERROR_MINOR,
EFI_IO_BUS_USB | EFI_IOB_EC_WRITE_ERROR
);
UsbFreeAddress (
DevAddress,
UsbIoDevice->BusController->AddressPool
);
gBS->FreePool (FirstController);
return EFI_DEVICE_ERROR;
}
UsbIoDevice->IsConfigured = TRUE;
//
// Get all string table if applicable
//
Result = UsbGetStringtable (UsbIoDevice);
if (EFI_ERROR (Result)) {
DEBUG ((gUSBDebugLevel, "Device doesn't support string table\n"));
} else {
StrManufacturer = NULL;
UsbIo->UsbGetStringDescriptor (
UsbIo,
UsbIoDevice->LangID[0],
(UsbIoDevice->DeviceDescriptor).StrManufacturer,
&StrManufacturer
);
StrProduct = NULL;
UsbIo->UsbGetStringDescriptor (
UsbIo,
UsbIoDevice->LangID[0],
(UsbIoDevice->DeviceDescriptor).StrProduct,
&StrProduct
);
StrSerialNumber = NULL;
UsbIo->UsbGetStringDescriptor (
UsbIo,
UsbIoDevice->LangID[0],
(UsbIoDevice->DeviceDescriptor).StrSerialNumber,
&StrSerialNumber
);
if (StrManufacturer) {
gBS->FreePool (StrManufacturer);
}
if (StrProduct) {
gBS->FreePool (StrProduct);
}
if (StrSerialNumber) {
gBS->FreePool (StrSerialNumber);
}
}
//
// Create USB_IO_CONTROLLER_DEVICE for
// each detected interface
//
FirstController->CurrentConfigValue = UsbIoDevice->ActiveConfig->CongfigDescriptor.ConfigurationValue;
NumOfInterface = UsbIoDevice->ActiveConfig->CongfigDescriptor.NumInterfaces;
UsbIoDevice->NumOfControllers = NumOfInterface;
Result = InitUsbIoController (FirstController);
if (EFI_ERROR (Result)) {
ReportUsbStatusCode (
UsbBusDev,
EFI_ERROR_CODE | EFI_ERROR_MINOR,
EFI_IO_BUS_USB | EFI_IOB_EC_INTERFACE_ERROR
);
gBS->FreePool (FirstController);
UsbIoDevice->UsbController[0] = NULL;
return EFI_DEVICE_ERROR;
}
for (Index = 1; Index < NumOfInterface; Index++) {
UsbIoController = CreateUsbIoControllerDevice ();
UsbIoController->UsbDevice = UsbIoDevice;
UsbIoController->CurrentConfigValue = UsbIoDevice->ActiveConfig->CongfigDescriptor.ConfigurationValue;
UsbIoController->InterfaceNumber = Index;
UsbIoDevice->UsbController[Index] = UsbIoController;
UsbIoController->ParentPort = ParentPort;
UsbIoController->Parent = ParentHubController;
UsbIoController->HostController = HostController;
//
// First copy the USB_IO Protocol instance
//
EfiCopyMem (
&UsbIoController->UsbIo,
UsbIo,
sizeof (EFI_USB_IO_PROTOCOL)
);
Result = InitUsbIoController (UsbIoController);
if (EFI_ERROR (Result)) {
ReportUsbStatusCode (
UsbBusDev,
EFI_ERROR_CODE | EFI_ERROR_MINOR,
EFI_IO_BUS_USB | EFI_IOB_EC_INTERFACE_ERROR
);
gBS->FreePool (UsbIoController);
UsbIoDevice->UsbController[Index] = NULL;
}
}
return EFI_SUCCESS;
}
//
// USB Device DeConfiguration
//
EFI_STATUS
UsbDeviceDeConfiguration (
IN USB_IO_DEVICE *UsbIoDevice
)
/*++
Routine Description:
Remove Device, Device Handles, Uninstall Protocols.
Arguments:
UsbIoDevice - The device to be deconfigured.
Returns:
EFI_SUCCESS
EFI_DEVICE_ERROR
--*/
{
USB_IO_CONTROLLER_DEVICE *UsbController;
UINT8 index;
USB_IO_DEVICE *ChildDevice;
UINT8 Index;
EFI_USB_IO_PROTOCOL *UsbIo;
//
// Double check UsbIoDevice exists
//
if (UsbIoDevice == NULL) {
return EFI_SUCCESS;
}
UsbUnsetTransactionTranslator (UsbIoDevice);
for (index = 0; index < UsbIoDevice->NumOfControllers; index++) {
//
// Check if it is a hub, if so, de configuration all its
// downstream ports
//
UsbController = UsbIoDevice->UsbController[index];
//
// Check the controller pointer
//
if (UsbController == NULL) {
continue;
}
if (UsbController->IsUsbHub) {
DEBUG ((gUSBDebugLevel, "Hub Deconfig, First Deconfig its downstream ports\n"));
//
// First Remove interrupt transfer request for the status
// change port
//
UsbIo = &UsbController->UsbIo;
UsbIo->UsbAsyncInterruptTransfer (
UsbIo,
UsbController->HubEndpointAddress,
FALSE,
0,
0,
NULL,
NULL
);
if (NULL != UsbController->HubNotify) {
gBS->CloseEvent (UsbController->HubNotify);
}
for (Index = 0; Index < UsbController->DownstreamPorts; Index++) {
if (UsbController->Children[Index]) {
ChildDevice = UsbController->Children[Index];
UsbDeviceDeConfiguration (ChildDevice);
UsbController->Children[Index] = NULL;
}
}
}
//
// If the controller is managed by a device driver, we need to
// disconnect them
//
if (UsbController->IsManagedByDriver) {
gBS->DisconnectController (
UsbController->Handle,
NULL,
NULL
);
}
//
// remove child handle reference to the USB_HC_PROTOCOL
//
if (UsbIoDevice->BusController->Hc2ProtocolSupported) {
gBS->CloseProtocol (
UsbController->HostController,
&gEfiUsb2HcProtocolGuid,
gUsbBusDriverBinding.DriverBindingHandle,
UsbController->Handle
);
} else {
gBS->CloseProtocol (
UsbController->HostController,
&gEfiUsbHcProtocolGuid,
gUsbBusDriverBinding.DriverBindingHandle,
UsbController->Handle
);
}
//
// Uninstall EFI_USB_IO_PROTOCOL & DEVICE_PATH_PROTOCOL
// installed on this handle
//
gBS->UninstallMultipleProtocolInterfaces (
UsbController->Handle,
&gEfiDevicePathProtocolGuid,
UsbController->DevicePath,
&gEfiUsbIoProtocolGuid,
&UsbController->UsbIo,
NULL
);
if (UsbController->DevicePath != NULL) {
gBS->FreePool (UsbController->DevicePath);
}
gBS->FreePool (UsbController);
UsbIoDevice->UsbController[index] = NULL;
}
//
// Free address for later use
//
UsbFreeAddress (
UsbIoDevice->DeviceAddress,
UsbIoDevice->BusController->AddressPool
);
//
// Free all resouces allocated for all its configurations
//
UsbDestroyAllConfiguration (UsbIoDevice);
if (UsbIoDevice) {
gBS->FreePool (UsbIoDevice);
UsbIoDevice = NULL;
}
return EFI_SUCCESS;
}
//
// After interrupt complete, this function will be called,
// This function need to be well-defined later
//
STATIC
EFI_STATUS
EFIAPI
OnHubInterruptComplete (
IN VOID *Data,
IN UINTN DataLength,
IN VOID *Context,
IN UINT32 Result
)
/*++
Routine Description:
Whenever hub interrupt occurs, this routine will be called to check
which event happens.
Arguments:
Data - Hub interrupt transfer data.
DataLength - The length of the Data.
Context - Hub Controller Device.
Result - Hub interrupt transfer status.
Returns:
EFI_SUCCESS
EFI_DEVICE_ERROR
--*/
{
USB_IO_CONTROLLER_DEVICE *HubController;
UINT8 Index;
UINT8 *ptr;
EFI_USB_IO_PROTOCOL *UsbIo;
UINT32 UsbResult;
BOOLEAN Disconnected;
EFI_STATUS Status;
HubController = (USB_IO_CONTROLLER_DEVICE *) Context;
UsbIo = &HubController->UsbIo;
//
// If something error in this interrupt transfer,
//
if (Result != EFI_USB_NOERROR) {
if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
UsbClearEndpointHalt (
UsbIo,
HubController->HubEndpointAddress,
&UsbResult
);
}
//
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?