diff --git a/MdeModulePkg/Application/UsbVideoDxe/ComponentName.c b/MdeModulePkg/Application/UsbVideoDxe/ComponentName.c
new file mode 100644
index 0000000000..48b26e7ab7
--- /dev/null
+++ b/MdeModulePkg/Application/UsbVideoDxe/ComponentName.c
@@ -0,0 +1,298 @@
+/** @file
+
+  UEFI Component Name(2) protocol implementation for Usb Video driver.
+
+Copyright (c) 2024, American Megatrends LLC.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/UefiLib.h>
+#include <PiDxe.h>
+#include <Protocol/ComponentName.h>
+#include <Protocol/ComponentName2.h>
+
+/**
+  Retrieves a Unicode string that is the user readable name of the driver.
+
+  This function retrieves the user readable name of a driver in the form of a
+  Unicode string. If the driver specified by This has a user readable name in
+  the language specified by Language, then a pointer to the driver name is
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+  by This does not support the language specified by Language,
+  then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language. This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified
+                                in RFC 4646 or ISO 639-2 language code format.
+
+  @param  DriverName[out]       A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                driver specified by This in the language
+                                specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
+                                This and the language specified by Language was
+                                returned in DriverName.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbVideoComponentNameGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  );
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by a driver.
+
+  This function retrieves the user readable name of the controller specified by
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the
+  driver specified by This has a user readable name in the language specified by
+  Language, then a pointer to the controller name is returned in ControllerName,
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
+  managing the controller specified by ControllerHandle and ChildHandle,
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  ControllerHandle[in]  The handle of a controller that the driver
+                                specified by This is managing.  This handle
+                                specifies the controller whose name is to be
+                                returned.
+
+  @param  ChildHandle[in]       The handle of the child controller to retrieve
+                                the name of.  This is an optional parameter that
+                                may be NULL.  It will be NULL for device
+                                drivers.  It will also be NULL for a bus drivers
+                                that wish to retrieve the name of the bus
+                                controller.  It will not be NULL for a bus
+                                driver that wishes to retrieve the name of a
+                                child controller.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language.  This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified in
+                                RFC 4646 or ISO 639-2 language code format.
+
+  @param  ControllerName[out]   A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                controller specified by ControllerHandle and
+                                ChildHandle in the language specified by
+                                Language from the point of view of the driver
+                                specified by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in
+                                the language specified by Language for the
+                                driver specified by This was returned in
+                                DriverName.
+
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+                                EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
+                                managing the controller specified by
+                                ControllerHandle and ChildHandle.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbVideoComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
+  IN  EFI_HANDLE                   ControllerHandle,
+  IN  EFI_HANDLE                   ChildHandle        OPTIONAL,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **ControllerName
+  );
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  gUsbVideoComponentName = {
+  UsbVideoComponentNameGetDriverName,
+  UsbVideoComponentNameGetControllerName,
+  "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL  gUsbVideoComponentName2 = {
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UsbVideoComponentNameGetDriverName,
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbVideoComponentNameGetControllerName,
+  "en"
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE  gUsbVideoDriverNameTable[] = {
+  { "eng;en", L"Usb Video Driver" },
+  { NULL,     NULL              }
+};
+
+/**
+  Retrieves a Unicode string that is the user readable name of the driver.
+
+  This function retrieves the user readable name of a driver in the form of a
+  Unicode string. If the driver specified by This has a user readable name in
+  the language specified by Language, then a pointer to the driver name is
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+  by This does not support the language specified by Language,
+  then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language. This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified
+                                in RFC 4646 or ISO 639-2 language code format.
+
+  @param  DriverName[out]       A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                driver specified by This in the language
+                                specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
+                                This and the language specified by Language was
+                                returned in DriverName.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbVideoComponentNameGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  )
+{
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           gUsbVideoDriverNameTable,
+           DriverName,
+           (BOOLEAN)(This == &gUsbVideoComponentName)
+           );
+}
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by a driver.
+
+  This function retrieves the user readable name of the controller specified by
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the
+  driver specified by This has a user readable name in the language specified by
+  Language, then a pointer to the controller name is returned in ControllerName,
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
+  managing the controller specified by ControllerHandle and ChildHandle,
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  ControllerHandle[in]  The handle of a controller that the driver
+                                specified by This is managing.  This handle
+                                specifies the controller whose name is to be
+                                returned.
+
+  @param  ChildHandle[in]       The handle of the child controller to retrieve
+                                the name of.  This is an optional parameter that
+                                may be NULL.  It will be NULL for device
+                                drivers.  It will also be NULL for a bus drivers
+                                that wish to retrieve the name of the bus
+                                controller.  It will not be NULL for a bus
+                                driver that wishes to retrieve the name of a
+                                child controller.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language.  This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified in
+                                RFC 4646 or ISO 639-2 language code format.
+
+  @param  ControllerName[out]   A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                controller specified by ControllerHandle and
+                                ChildHandle in the language specified by
+                                Language from the point of view of the driver
+                                specified by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in
+                                the language specified by Language for the
+                                driver specified by This was returned in
+                                DriverName.
+
+  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+                                EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
+                                managing the controller specified by
+                                ControllerHandle and ChildHandle.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbVideoComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
+  IN  EFI_HANDLE                   ControllerHandle,
+  IN  EFI_HANDLE                   ChildHandle        OPTIONAL,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **ControllerName
+  )
+{
+  return EFI_UNSUPPORTED;
+}
diff --git a/MdeModulePkg/Application/UsbVideoDxe/UsbVideoDxe.c b/MdeModulePkg/Application/UsbVideoDxe/UsbVideoDxe.c
new file mode 100644
index 0000000000..57d53153e6
--- /dev/null
+++ b/MdeModulePkg/Application/UsbVideoDxe/UsbVideoDxe.c
@@ -0,0 +1,222 @@
+/** @file
+
+  Usb Video driver provides services for Usb video device
+
+  (C) Copyright 2011-2024, American Megatrends International LLC<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Protocol/UsbAssociationIo.h>
+#include "UsbVideoDxe.h"
+
+//
+// USB Keyboard Driver Global Variables
+//
+EFI_DRIVER_BINDING_PROTOCOL  gUsbVideoDriverBinding = {
+  UsbVideoDriverBindingSupported,
+  UsbVideoDriverBindingStart,
+  UsbVideoDriverBindingStop,
+  0xa,
+  NULL,
+  NULL
+};
+
+/**
+  Check whether USB video driver supports this device.
+
+  @param  This                   The USB video driver binding protocol.
+  @param  Controller             The controller handle to check.
+  @param  RemainingDevicePath    The remaining device path.
+
+  @retval EFI_SUCCESS            The driver supports this controller.
+  @retval other                  This device isn't supported.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbVideoDriverBindingSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
+  )
+{
+  EFI_STATUS                               Status;
+  EFI_USB_INTERFACE_ASSOCIATION_PROTOCOL   *UsbIaIo;
+  EFI_USB_INTERFACE_ASSOCIATION_DESCRIPTOR  Desc;
+
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiUsbInterfaceAssociationProtocolGuid,
+                  (VOID **)&UsbIaIo,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = UsbIaIo->UsbIaGetAssociationDescriptor (UsbIaIo, &Desc);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  gBS->CloseProtocol (
+        Controller,
+        &gEfiUsbInterfaceAssociationProtocolGuid,
+        This->DriverBindingHandle,
+        Controller
+        );
+
+  if ((Desc.FunctionClass == USB_VIDEO_CLASS) && (Desc.FunctionSubclass == USB_VIDEO_INTERFACE_COLLECTION_SUBCLASS)) {
+    return EFI_SUCCESS;
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Starts the USB video device with this driver.
+
+  @param  This                   The USB video driver binding instance.
+  @param  Controller             Handle of device to bind driver to.
+  @param  RemainingDevicePath    Optional parameter use to pick a specific child
+                                 device to start.
+
+  @retval EFI_SUCCESS            The controller is controlled by the usb video driver.
+  @retval EFI_UNSUPPORTED        No interrupt endpoint can be found.
+  @retval Other                  This controller cannot be started.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbVideoDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
+  )
+{
+  EFI_STATUS                                Status;
+  EFI_USB_INTERFACE_ASSOCIATION_PROTOCOL    *UsbIaIo;
+  EFI_USB_INTERFACE_ASSOCIATION_DESCRIPTOR  AssocDesc;
+  EFI_USB_INTERFACE_DESCRIPTOR              IntrfDesc;
+  EFI_USB_IO_PROTOCOL                       *UsbIo;
+  UINT8                                     IfNum;
+  UINTN                                     SettingCount;
+
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiUsbInterfaceAssociationProtocolGuid,
+                  (VOID **)&UsbIaIo,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = UsbIaIo->UsbIaGetAssociationDescriptor (UsbIaIo, &AssocDesc);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  for (IfNum = AssocDesc.FirstInterface; IfNum < (AssocDesc.FirstInterface + AssocDesc.InterfaceCount); IfNum++) {
+    Status = UsbIaIo->UsbIaGetAssociateSettings (UsbIaIo, IfNum, &UsbIo, &SettingCount);
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+    Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &IntrfDesc);
+    ASSERT_EFI_ERROR (Status);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+    if (IntrfDesc.InterfaceClass == USB_VIDEO_CLASS) {
+      if (IntrfDesc.InterfaceSubClass == USB_VIDEOCONTROL_SUBCLASS) {
+        // found video control UsbIo, store it in the device for future use
+        // TBD
+        //
+      }
+      if (IntrfDesc.InterfaceSubClass == USB_VIDEOSTREAMING_SUBCLASS) {
+        // found video streaming UsbIo, store it in the device for future use
+        // TBD
+        //
+      }
+    }
+  }
+  if (IfNum == (AssocDesc.FirstInterface + AssocDesc.InterfaceCount)) {
+    gBS->CloseProtocol (
+          Controller,
+          &gEfiUsbInterfaceAssociationProtocolGuid,
+          This->DriverBindingHandle,
+          Controller
+          );
+    return EFI_NOT_FOUND;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Stops the USB video device handled by this driver.
+
+  @param  This                   The USB video driver binding protocol.
+  @param  Controller             The controller to release.
+  @param  NumberOfChildren       The number of handles in ChildHandleBuffer.
+  @param  ChildHandleBuffer      The array of child handle.
+
+  @retval EFI_SUCCESS            The device was stopped.
+  @retval EFI_UNSUPPORTED        Simple Text In Protocol or Simple Text In Ex Protocol
+                                 is not installed on Controller.
+  @retval EFI_DEVICE_ERROR       The device could not be stopped due to a device error.
+  @retval Others                 Fail to uninstall protocols attached on the device.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbVideoDriverBindingStop (
+  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN  EFI_HANDLE                   Controller,
+  IN  UINTN                        NumberOfChildren,
+  IN  EFI_HANDLE                   *ChildHandleBuffer
+  )
+{
+  gBS->CloseProtocol (
+        Controller,
+        &gEfiUsbInterfaceAssociationProtocolGuid,
+        This->DriverBindingHandle,
+        Controller
+        );
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  The USB video driver entry pointer.
+
+  @param ImageHandle       The driver image handle.
+  @param SystemTable       The system table.
+
+  @return EFI_SUCCESS      The component name protocol is installed.
+  @return Others           Failed to init the usb driver.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbVideoDxeEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  return EfiLibInstallDriverBindingComponentName2 (
+           ImageHandle,
+           SystemTable,
+           &gUsbVideoDriverBinding,
+           ImageHandle,
+           &gUsbVideoComponentName,
+           &gUsbVideoComponentName2
+           );
+}
diff --git a/MdeModulePkg/Application/UsbVideoDxe/UsbVideoDxe.h b/MdeModulePkg/Application/UsbVideoDxe/UsbVideoDxe.h
new file mode 100644
index 0000000000..e3779e691b
--- /dev/null
+++ b/MdeModulePkg/Application/UsbVideoDxe/UsbVideoDxe.h
@@ -0,0 +1,102 @@
+/** @file
+  Header file for USB Video Driver's Data Structures.
+
+Copyright (c) 2025, American Megatrends LLC.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_USB_VIDEO_H_
+#define _EFI_USB_VIDEO_H_
+
+#include <Uefi.h>
+#include <Protocol/DriverBinding.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <PiDxe.h>
+
+#define USB_VIDEO_CLASS                          0xE
+#define USB_VIDEO_INTERFACE_COLLECTION_SUBCLASS  0x3
+#define USB_VIDEOCONTROL_SUBCLASS                0x1
+#define USB_VIDEOSTREAMING_SUBCLASS              0x2
+
+
+typedef struct _USB_VIDEO_DEVICE {
+  EFI_USB_IO_PROTOCOL *VideoCtlIo;
+} USB_VIDEO_DEVICE;
+
+extern EFI_COMPONENT_NAME_PROTOCOL   gUsbVideoComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL  gUsbVideoComponentName2;
+
+//
+// Functions of Driver Binding Protocol
+//
+
+/**
+  Check whether USB video driver supports this device.
+
+  @param  This                   The USB video driver binding protocol.
+  @param  Controller             The controller handle to check.
+  @param  RemainingDevicePath    The remaining device path.
+
+  @retval EFI_SUCCESS            The driver supports this controller.
+  @retval other                  This device isn't supported.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbVideoDriverBindingSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
+  );
+
+/**
+  Starts the USB video device with this driver.
+
+  @param  This                   The USB video driver binding instance.
+  @param  Controller             Handle of device to bind driver to.
+  @param  RemainingDevicePath    Optional parameter use to pick a specific child
+                                 device to start.
+
+  @retval EFI_SUCCESS            The controller is controlled by the usb video driver.
+  @retval EFI_UNSUPPORTED        No interrupt endpoint can be found.
+  @retval Other                  This controller cannot be started.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbVideoDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
+  );
+
+/**
+  Stops the USB video device handled by this driver.
+
+  @param  This                   The USB video driver binding protocol.
+  @param  Controller             The controller to release.
+  @param  NumberOfChildren       The number of handles in ChildHandleBuffer.
+  @param  ChildHandleBuffer      The array of child handle.
+
+  @retval EFI_SUCCESS            The device was stopped.
+  @retval EFI_UNSUPPORTED        Simple Text In Protocol or Simple Text In Ex Protocol
+                                 is not installed on Controller.
+  @retval EFI_DEVICE_ERROR       The device could not be stopped due to a device error.
+  @retval Others                 Fail to uninstall protocols attached on the device.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbVideoDriverBindingStop (
+  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN  EFI_HANDLE                   Controller,
+  IN  UINTN                        NumberOfChildren,
+  IN  EFI_HANDLE                   *ChildHandleBuffer
+  );
+
+
+#endif
diff --git a/MdeModulePkg/Application/UsbVideoDxe/UsbVideoDxe.inf b/MdeModulePkg/Application/UsbVideoDxe/UsbVideoDxe.inf
new file mode 100644
index 0000000000..cfa7fac901
--- /dev/null
+++ b/MdeModulePkg/Application/UsbVideoDxe/UsbVideoDxe.inf
@@ -0,0 +1,44 @@
+## @file
+# Usb Video driver provides services for Usb video device
+#
+# Copyright (c) 2025, American Megatrends LLC. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION     = 0x00010005
+  BASE_NAME       = UsbVideoDxe
+  FILE_GUID       = 4134A1FD-D9DB-405E-9876-7E58DB3B7908
+  MODULE_TYPE     = UEFI_DRIVER
+  VERSION_STRING  = 1.0
+  ENTRY_POINT     = UsbVideoDxeEntryPoint
+    
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  UsbVideoDxe.c
+  UsbVideoDxe.h
+  ComponentName.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  MemoryAllocationLib
+  DevicePathLib
+  UefiLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  BaseMemoryLib
+  DebugLib
+  ReportStatusCodeLib
+
+[Protocols]
+  gEfiUsbIoProtocolGuid
+  gEfiUsbInterfaceAssociationProtocolGuid
+    
\ No newline at end of file
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h
index 21a24218fc..f734442737 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h
@@ -3,6 +3,7 @@
     Usb Bus Driver Binding and Bus IO Protocol.
 
 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2025, American Megatrends International, LLC. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -15,6 +16,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Protocol/Usb2HostController.h>
 #include <Protocol/UsbHostController.h>
 #include <Protocol/UsbIo.h>
+#include <Protocol/UsbAssociationIo.h>
 #include <Protocol/DevicePath.h>
 
 #include <Library/BaseLib.h>
@@ -29,10 +31,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 
 #include <IndustryStandard/Usb.h>
 
-typedef struct _USB_DEVICE     USB_DEVICE;
-typedef struct _USB_INTERFACE  USB_INTERFACE;
-typedef struct _USB_BUS        USB_BUS;
-typedef struct _USB_HUB_API    USB_HUB_API;
+typedef struct _USB_DEVICE       USB_DEVICE;
+typedef struct _USB_INTERFACE    USB_INTERFACE;
+typedef struct _USB_BUS          USB_BUS;
+typedef struct _USB_HUB_API      USB_HUB_API;
+typedef struct _USB_ASSOCIATION  USB_ASSOCIATION;
 
 #include "UsbUtility.h"
 #include "UsbDesc.h"
@@ -132,8 +135,9 @@ typedef struct _USB_HUB_API    USB_HUB_API;
 //
 #define  USB_BUS_TPL  TPL_NOTIFY
 
-#define  USB_INTERFACE_SIGNATURE  SIGNATURE_32 ('U', 'S', 'B', 'I')
-#define  USB_BUS_SIGNATURE        SIGNATURE_32 ('U', 'S', 'B', 'B')
+#define  USB_INTERFACE_SIGNATURE    SIGNATURE_32 ('U', 'S', 'B', 'I')
+#define  USB_BUS_SIGNATURE          SIGNATURE_32 ('U', 'S', 'B', 'B')
+#define  USB_ASSOCIATION_SIGNATURE  SIGNATURE_32 ('U', 'S', 'B', 'A')
 
 #define USB_BIT(a)                 ((UINTN)(1 << (a)))
 #define USB_BIT_IS_SET(Data, Bit)  ((BOOLEAN)(((Data) & (Bit)) == (Bit)))
@@ -141,6 +145,9 @@ typedef struct _USB_HUB_API    USB_HUB_API;
 #define USB_INTERFACE_FROM_USBIO(a) \
           CR(a, USB_INTERFACE, UsbIo, USB_INTERFACE_SIGNATURE)
 
+#define USB_ASSOCIATION_FROM_USBIA(a) \
+          CR(a, USB_ASSOCIATION, UsbIaProtocol, USB_ASSOCIATION_SIGNATURE)
+
 #define USB_BUS_FROM_THIS(a) \
           CR(a, USB_BUS, BusId, USB_BUS_SIGNATURE)
 
@@ -176,6 +183,9 @@ struct _USB_DEVICE {
   UINT16                                LangId[USB_MAX_LANG_ID];
   UINT16                                TotalLangId;
 
+  UINT8                                 NumOfAssociation;
+  USB_ASSOCIATION                       *Associations[USB_MAX_ASSOCIATION];
+
   UINT8                                 NumOfInterface;
   USB_INTERFACE                         *Interfaces[USB_MAX_INTERFACE];
 
@@ -230,6 +240,23 @@ struct _USB_INTERFACE {
   UINT8                       MaxSpeed;
 };
 
+//
+// Stands for a function implemented using interface association
+//
+struct _USB_ASSOCIATION {
+  UINTN                             Signature;
+  USB_DEVICE                        *Device;
+  USB_INTERFACE_ASSOCIATION_DESC    *IaDesc;
+
+  //
+  // Handles and protocols
+  //
+  EFI_HANDLE                              Handle;
+  EFI_USB_INTERFACE_ASSOCIATION_PROTOCOL  UsbIaProtocol;
+  EFI_DEVICE_PATH_PROTOCOL                *DevicePath;
+  BOOLEAN                                 IsManaged;
+};
+
 //
 // Stands for the current USB Bus
 //
@@ -751,9 +778,10 @@ UsbBusControllerDriverStop (
   IN EFI_HANDLE                   *ChildHandleBuffer
   );
 
-extern EFI_USB_IO_PROTOCOL           mUsbIoProtocol;
-extern EFI_DRIVER_BINDING_PROTOCOL   mUsbBusDriverBinding;
-extern EFI_COMPONENT_NAME_PROTOCOL   mUsbBusComponentName;
-extern EFI_COMPONENT_NAME2_PROTOCOL  mUsbBusComponentName2;
+extern EFI_USB_IO_PROTOCOL                     mUsbIoProtocol;
+extern EFI_USB_INTERFACE_ASSOCIATION_PROTOCOL  mUsbIaProtocol;
+extern EFI_DRIVER_BINDING_PROTOCOL             mUsbBusDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL             mUsbBusComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL            mUsbBusComponentName2;
 
 #endif
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
index dd85894346..fdb40f9110 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
@@ -2,6 +2,7 @@
 #  The Usb Bus Dxe driver is used to enumerate and manage all attached usb devices.
 #
 #  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2025, American Megatrends International, LLC. All rights reserved.<BR>
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -40,6 +41,7 @@
   UsbUtility.c
   UsbDesc.h
   UsbBus.h
+  UsbIntfAssoc.c
 
 [Packages]
   MdePkg/MdePkg.dec
@@ -58,6 +60,7 @@
 
 [Protocols]
   gEfiUsbIoProtocolGuid                         ## BY_START
+  gEfiUsbInterfaceAssociationProtocolGuid
   ## TO_START
   ## BY_START
   gEfiDevicePathProtocolGuid
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c
index 8b078e7e49..f96df11e99 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c
@@ -3,6 +3,7 @@
     Manage Usb Descriptor List
 
 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2025, American Megatrends International, LLC. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -46,6 +47,24 @@ UsbFreeInterfaceDesc (
   FreePool (Setting);
 }
 
+/**
+  Free the interface association descriptor
+
+  @param  Iad               The interface association descriptor to free.
+
+**/
+VOID
+UsbFreeInterfaceAssociationDesc (
+  IN USB_INTERFACE_ASSOCIATION_DESC  *Iad
+  )
+{
+  if (Iad->Interfaces != NULL) {
+    FreePool (Iad->Interfaces);
+  }
+
+  FreePool (Iad);
+}
+
 /**
   Free a configuration descriptor with its interface
   descriptors. It may be initialized partially.
@@ -167,6 +186,11 @@ UsbCreateDesc (
       CtrlLen = sizeof (USB_ENDPOINT_DESC);
       break;
 
+    case USB_DESC_TYPE_INTERFACE_ASSOCIATION:
+      DescLen = sizeof (EFI_USB_INTERFACE_ASSOCIATION_DESCRIPTOR);
+      CtrlLen = sizeof (USB_INTERFACE_ASSOCIATION_DESC);
+      break;
+
     default:
       ASSERT (FALSE);
       return NULL;
@@ -231,6 +255,7 @@ UsbCreateDesc (
     return NULL;
   }
 
+  ASSERT (CtrlLen >= DescLen);
   CopyMem (Desc, Head, (UINTN)DescLen);
 
   *Consumed = Offset;
@@ -319,6 +344,85 @@ ON_ERROR:
   return NULL;
 }
 
+/**
+  Parse an interface association and its interfaces.
+
+  @param  DescBuf               The buffer of raw interface association descriptor.
+  @param  Len                   The length of the raw descriptor buffer.
+  @param  Config                The device configuration buffer.
+  @param  Consumed              The number of raw descriptor consumed.
+
+  @return The created interface association descriptor or NULL if failed.
+
+**/
+USB_INTERFACE_ASSOCIATION_DESC *
+UsbParseInterfaceAssociationDesc (
+  IN UINT8            *DescBuf,
+  IN UINTN            Len,
+  IN USB_CONFIG_DESC  *Config,
+  OUT UINTN           *Consumed
+  )
+{
+  USB_INTERFACE_ASSOCIATION_DESC  *Iad;
+  UINT8                           Index;
+  UINT8                           IfIndex;
+  UINT8                           i;
+  UINTN                           NumIf;
+  UINTN                           Used;
+
+  *Consumed = 0;
+  Iad       = UsbCreateDesc (DescBuf, Len, USB_DESC_TYPE_INTERFACE_ASSOCIATION, &Used);
+
+  if (Iad == NULL) {
+    return NULL;
+  }
+
+  //
+  // Create an array to hold the association's interfaces
+  //
+  NumIf = Iad->Desc.InterfaceCount;
+
+  DEBUG ((
+    DEBUG_INFO,
+    "UsbParseInterfaceAssociationDesc: interface association has %d interfaces\n",
+    (UINT32)NumIf
+    ));
+
+  ASSERT (NumIf > 0);
+  if (NumIf == 0) {
+    DEBUG ((DEBUG_ERROR, "UsbParseInterfaceAssociationDesc: no interfaces are reported for this association.\n"));
+    goto ON_ERROR;
+  }
+
+  Iad->Interfaces = AllocateZeroPool (sizeof (USB_INTERFACE_DESC *) * NumIf);
+
+  //
+  // Populate interfaces for this association
+  //
+  IfIndex = 0;
+  for (Index = Iad->Desc.FirstInterface; Index < (Iad->Desc.FirstInterface + Iad->Desc.InterfaceCount); Index++) {
+    for (i = 0; i < Config->Desc.NumInterfaces; i++) {
+      if (Index == Config->Interfaces[i]->Settings[0]->Desc.InterfaceNumber) {
+        break;
+      }
+    }
+
+    if (i == Config->Desc.NumInterfaces) {
+      DEBUG ((DEBUG_ERROR, "UsbParseInterfaceAssociationDesc: interface %d not found.\n", Index));
+      goto ON_ERROR;
+    }
+
+    Iad->Interfaces[IfIndex++] = Config->Interfaces[i];
+  }
+
+  *Consumed = Used;
+  return Iad;
+
+ON_ERROR:
+  UsbFreeInterfaceAssociationDesc (Iad);
+  return NULL;
+}
+
 /**
   Parse the configuration descriptor and its interfaces.
 
@@ -334,16 +438,22 @@ UsbParseConfigDesc (
   IN UINTN  Len
   )
 {
-  USB_CONFIG_DESC        *Config;
-  USB_INTERFACE_SETTING  *Setting;
-  USB_INTERFACE_DESC     *Interface;
-  UINTN                  Index;
-  UINTN                  NumIf;
-  UINTN                  Consumed;
+  USB_CONFIG_DESC                 *Config;
+  USB_INTERFACE_SETTING           *Setting;
+  USB_INTERFACE_DESC              *Interface;
+  UINTN                           Index;
+  UINTN                           NumIf;
+  UINTN                           Consumed;
+  UINT8                           *Buffer;
+  UINTN                           Length;
+  USB_INTERFACE_ASSOCIATION_DESC  *Iad;
 
   ASSERT (DescBuf != NULL);
 
-  Config = UsbCreateDesc (DescBuf, Len, USB_DESC_TYPE_CONFIG, &Consumed);
+  Buffer = DescBuf;
+  Length = Len;
+
+  Config = UsbCreateDesc (Buffer, Length, USB_DESC_TYPE_CONFIG, &Consumed);
 
   if (Config == NULL) {
     return NULL;
@@ -384,15 +494,15 @@ UsbParseConfigDesc (
   // setting 1|interface 1, setting 0|interface 2, setting 0|. Check
   // USB2.0 spec, page 267.
   //
-  DescBuf += Consumed;
-  Len     -= Consumed;
+  Buffer += Consumed;
+  Length -= Consumed;
 
   //
   // Make allowances for devices that return extra data at the
   // end of their config descriptors
   //
-  while (Len >= sizeof (EFI_USB_INTERFACE_DESCRIPTOR)) {
-    Setting = UsbParseInterfaceDesc (DescBuf, Len, &Consumed);
+  while (Length >= sizeof (EFI_USB_INTERFACE_DESCRIPTOR)) {
+    Setting = UsbParseInterfaceDesc (Buffer, Length, &Consumed);
 
     if (Setting == NULL) {
       DEBUG ((DEBUG_ERROR, "UsbParseConfigDesc: warning: failed to get interface setting, stop parsing now.\n"));
@@ -416,8 +526,36 @@ UsbParseConfigDesc (
     Interface->Settings[Interface->NumOfSetting] = Setting;
     Interface->NumOfSetting++;
 
-    DescBuf += Consumed;
-    Len     -= Consumed;
+    Buffer += Consumed;
+    Length -= Consumed;
+  }
+
+  //
+  // Process interface association descriptors.
+  //
+  Buffer = DescBuf;
+  Length = Len;
+
+  while (Length >= sizeof (EFI_USB_INTERFACE_ASSOCIATION_DESCRIPTOR)) {
+    Iad = UsbParseInterfaceAssociationDesc (Buffer, Length, Config, &Consumed);
+
+    if (Iad == NULL) {
+      break;
+    }
+
+    //
+    // Insert the association descriptor to the corresponding set.
+    //
+    if (Config->NumOfIads >= USB_MAX_ASSOCIATION) {
+      DEBUG ((DEBUG_ERROR, "UsbParseConfigDesc: too many interface association descriptors in this configuration.\n"));
+      goto ON_ERROR;
+    }
+
+    Config->Iads[Config->NumOfIads] = Iad;
+    Config->NumOfIads++;
+
+    Buffer += Consumed;
+    Length -= Consumed;
   }
 
   return Config;
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.h b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.h
index ce205e706d..03f38c7afa 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.h
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.h
@@ -3,6 +3,7 @@
     Manage Usb Descriptor List
 
 Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2025, American Megatrends International, LLC. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -11,6 +12,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #define _USB_DESCRIPTOR_H_
 
 #define USB_MAX_INTERFACE_SETTING  256
+#define USB_MAX_ASSOCIATION        16
 
 //
 // The RequestType in EFI_USB_DEVICE_REQUEST is composed of
@@ -62,8 +64,15 @@ typedef struct {
 } USB_INTERFACE_DESC;
 
 typedef struct {
-  EFI_USB_CONFIG_DESCRIPTOR    Desc;
-  USB_INTERFACE_DESC           **Interfaces;
+  EFI_USB_INTERFACE_ASSOCIATION_DESCRIPTOR    Desc;
+  USB_INTERFACE_DESC                          **Interfaces;
+} USB_INTERFACE_ASSOCIATION_DESC;
+
+typedef struct {
+  EFI_USB_CONFIG_DESCRIPTOR         Desc;
+  USB_INTERFACE_ASSOCIATION_DESC    *Iads[USB_MAX_ASSOCIATION];
+  UINT8                             NumOfIads;
+  USB_INTERFACE_DESC                **Interfaces;
 } USB_CONFIG_DESC;
 
 typedef struct {
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
index b3a40639f2..64786603c3 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
@@ -3,6 +3,7 @@
     Usb bus enumeration support.
 
 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2025, American Megatrends International, LLC. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -41,6 +42,41 @@ UsbGetEndpointDesc (
   return NULL;
 }
 
+/**
+  Check if given Usb interface is a part of Usb association.
+
+  @param[in]  Device    The device may have the interface association descriptor.
+  @param[in]  IfDesc    The interface descriptor to check for.
+  @param[out] IfAssoc   The USB association device pointer.
+
+  @retval EFI_SUCCESS   IfDesc is found within associations, IfAssoc has valid pointer.
+  @retval EFI_NOT_FOUND IfDesc does no belong to any association.
+
+**/
+EFI_STATUS
+GetInterfaceAssociation (
+  IN USB_DEVICE          *Device,
+  IN USB_INTERFACE_DESC  *IfDesc,
+  OUT USB_ASSOCIATION    **IfAssoc
+  )
+{
+  UINTN            Index;
+  UINTN            i;
+  USB_ASSOCIATION  *Ia;
+
+  for (Index = 0; Index < Device->NumOfAssociation; Index++) {
+    Ia = Device->Associations[Index];
+    for (i = 0; i < Ia->IaDesc->Desc.InterfaceCount; i++) {
+      if (IfDesc->Settings[0]->Desc.InterfaceNumber == Ia->IaDesc->Interfaces[i]->Settings[0]->Desc.InterfaceNumber) {
+        *IfAssoc = Ia;
+        return EFI_SUCCESS;
+      }
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
+
 /**
   Free the resource used by USB interface.
 
@@ -54,9 +90,25 @@ UsbFreeInterface (
   IN USB_INTERFACE  *UsbIf
   )
 {
-  EFI_STATUS  Status;
+  EFI_STATUS       Status;
+  USB_ASSOCIATION  *UsbIa;
 
-  UsbCloseHostProtoByChild (UsbIf->Device->Bus, UsbIf->Handle);
+  Status = GetInterfaceAssociation (UsbIf->Device, UsbIf->IfDesc, &UsbIa);
+
+  if (!EFI_ERROR (Status)) {
+    //
+    // Close USB Interface Association Protocol by Child
+    //
+    Status = gBS->CloseProtocol (
+                    UsbIa->Handle,
+                    &gEfiUsbInterfaceAssociationProtocolGuid,
+                    mUsbBusDriverBinding.DriverBindingHandle,
+                    UsbIf->Handle
+                    );
+    DEBUG ((DEBUG_INFO, "UsbFreeInterface: close IAD protocol by child, %r\n", Status));
+  } else {
+    UsbCloseHostProtoByChild (UsbIf->Device->Bus, UsbIf->Handle);
+  }
 
   Status = gBS->UninstallMultipleProtocolInterfaces (
                   UsbIf->Handle,
@@ -73,7 +125,66 @@ UsbFreeInterface (
 
     FreePool (UsbIf);
   } else {
-    UsbOpenHostProtoByChild (UsbIf->Device->Bus, UsbIf->Handle);
+    Status = GetInterfaceAssociation (UsbIf->Device, UsbIf->IfDesc, &UsbIa);
+
+    if (!EFI_ERROR (Status)) {
+      //
+      // Reopen USB Interface Assiciation Protocol by Child
+      //
+      Status = gBS->OpenProtocol (
+                      UsbIa->Handle,
+                      &gEfiUsbInterfaceAssociationProtocolGuid,
+                      (VOID **)&UsbIa,
+                      mUsbBusDriverBinding.DriverBindingHandle,
+                      UsbIf->Handle,
+                      EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+                      );
+      DEBUG ((DEBUG_INFO, "UsbFreeInterface: reopen IAD for child, Status = %r\n", Status));
+    } else {
+      //
+      // Reopen USB Host Controller Protocol by Child
+      //
+      Status = UsbOpenHostProtoByChild (UsbIf->Device->Bus, UsbIf->Handle);
+      DEBUG ((DEBUG_INFO, "UsbFreeInterface: reopen host controller for child, Status = %r\n", Status));
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Free the resource used by USB association.
+
+  @param  UsbIa                 The USB association to free.
+
+  @retval EFI_ACCESS_DENIED     The Usb association resource is still occupied.
+  @retval EFI_SUCCESS           The Usb association resource is freed.
+
+**/
+EFI_STATUS
+UsbFreeAssociation (
+  IN USB_ASSOCIATION  *UsbIa
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = gBS->UninstallMultipleProtocolInterfaces (
+                  UsbIa->Handle,
+                  &gEfiDevicePathProtocolGuid,
+                  UsbIa->DevicePath,
+                  &gEfiUsbInterfaceAssociationProtocolGuid,
+                  &UsbIa->UsbIaProtocol,
+                  NULL
+                  );
+
+  if (!EFI_ERROR (Status)) {
+    if (UsbIa->DevicePath != NULL) {
+      FreePool (UsbIa->DevicePath);
+    }
+
+    FreePool (UsbIa);
+  } else {
+    UsbOpenHostProtoByChild (UsbIa->Device->Bus, UsbIa->Handle);
   }
 
   return Status;
@@ -82,6 +193,7 @@ UsbFreeInterface (
 /**
   Create an interface for the descriptor IfDesc. Each
   device's configuration can have several interfaces.
+  Interface may belong to interface association.
 
   @param  Device                The device has the interface descriptor.
   @param  IfDesc                The interface descriptor.
@@ -95,10 +207,12 @@ UsbCreateInterface (
   IN USB_INTERFACE_DESC  *IfDesc
   )
 {
-  USB_DEVICE_PATH  UsbNode;
-  USB_INTERFACE    *UsbIf;
-  USB_INTERFACE    *HubIf;
-  EFI_STATUS       Status;
+  USB_DEVICE_PATH           UsbNode;
+  USB_INTERFACE             *UsbIf;
+  USB_INTERFACE             *HubIf;
+  USB_ASSOCIATION           *UsbIa;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePathProtocol;
+  EFI_STATUS                Status;
 
   UsbIf = AllocateZeroPool (sizeof (USB_INTERFACE));
 
@@ -128,10 +242,17 @@ UsbCreateInterface (
 
   SetDevicePathNodeLength (&UsbNode.Header, sizeof (UsbNode));
 
-  HubIf = Device->ParentIf;
-  ASSERT (HubIf != NULL);
+  Status = GetInterfaceAssociation (Device, IfDesc, &UsbIa);
+
+  if (!EFI_ERROR (Status)) {
+    DevicePathProtocol = UsbIa->DevicePath;
+  } else {
+    HubIf = Device->ParentIf;
+    ASSERT (HubIf != NULL);
+    DevicePathProtocol = HubIf->DevicePath;
+  }
 
-  UsbIf->DevicePath = AppendDevicePathNode (HubIf->DevicePath, &UsbNode.Header);
+  UsbIf->DevicePath = AppendDevicePathNode (DevicePathProtocol, &UsbNode.Header);
 
   if (UsbIf->DevicePath == NULL) {
     DEBUG ((DEBUG_ERROR, "UsbCreateInterface: failed to create device path\n"));
@@ -154,10 +275,28 @@ UsbCreateInterface (
     goto ON_ERROR;
   }
 
-  //
-  // Open USB Host Controller Protocol by Child
-  //
-  Status = UsbOpenHostProtoByChild (Device->Bus, UsbIf->Handle);
+  Status = GetInterfaceAssociation (Device, IfDesc, &UsbIa);
+
+  if (!EFI_ERROR (Status)) {
+    //
+    // Open USB Interface Assiciation Protocol by Child
+    //
+    Status = gBS->OpenProtocol (
+                    UsbIa->Handle,
+                    &gEfiUsbInterfaceAssociationProtocolGuid,
+                    (VOID **)&UsbIa,
+                    mUsbBusDriverBinding.DriverBindingHandle,
+                    UsbIf->Handle,
+                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+                    );
+    DEBUG ((DEBUG_INFO, "UsbCreateInterface: open IAD for child, Status = %r\n", Status));
+  } else {
+    //
+    // Open USB Host Controller Protocol by Child
+    //
+    Status = UsbOpenHostProtoByChild (Device->Bus, UsbIf->Handle);
+    DEBUG ((DEBUG_INFO, "UsbCreateInterface: open host controller for child, Status = %r\n", Status));
+  }
 
   if (EFI_ERROR (Status)) {
     gBS->UninstallMultipleProtocolInterfaces (
@@ -184,6 +323,112 @@ ON_ERROR:
   return NULL;
 }
 
+/**
+  Create an interface association instance and install protocols to manage it.
+
+  @param  Device        The Usb device that has the interface association.
+  @param  Index         The interface association index within Device.
+  @param  IfAssocDesc   The interface association descriptor.
+
+  @return The created USB interface association, or NULL.
+
+**/
+USB_ASSOCIATION *
+UsbCreateAssociation (
+  IN USB_DEVICE                      *Device,
+  IN UINT8                           Index,
+  IN USB_INTERFACE_ASSOCIATION_DESC  *IfAssocDesc
+  )
+{
+  USB_DEVICE_PATH  UsbNode;
+  USB_ASSOCIATION  *UsbAssoc;
+  EFI_STATUS       Status;
+
+  UsbAssoc = AllocateZeroPool (sizeof (USB_ASSOCIATION));
+
+  if (UsbAssoc == NULL) {
+    return NULL;
+  }
+
+  UsbAssoc->Signature = USB_ASSOCIATION_SIGNATURE;
+  UsbAssoc->Device    = Device;
+  UsbAssoc->IaDesc    = IfAssocDesc;
+
+  CopyMem (
+    &(UsbAssoc->UsbIaProtocol),
+    &mUsbIaProtocol,
+    sizeof (EFI_USB_INTERFACE_ASSOCIATION_PROTOCOL)
+    );
+
+  //
+  // Install USB association protocols
+  //
+  // Device path protocol for the association has the USB node similar to the
+  // one installed for USB interface.
+  //
+
+  UsbNode.Header.Type      = MESSAGING_DEVICE_PATH;
+  UsbNode.Header.SubType   = MSG_USB_DP;
+  UsbNode.ParentPortNumber = Device->ParentPort;
+  UsbNode.InterfaceNumber  = Index;
+
+  SetDevicePathNodeLength (&UsbNode.Header, sizeof (UsbNode));
+
+  ASSERT (Device->ParentIf != NULL);
+
+  UsbAssoc->DevicePath = AppendDevicePathNode (Device->ParentIf->DevicePath, &UsbNode.Header);
+
+  if (UsbAssoc->DevicePath == NULL) {
+    DEBUG ((DEBUG_ERROR, "UsbCreateAssociation: failed to create device path\n"));
+
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_ERROR;
+  }
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &UsbAssoc->Handle,
+                  &gEfiDevicePathProtocolGuid,
+                  UsbAssoc->DevicePath,
+                  &gEfiUsbInterfaceAssociationProtocolGuid,
+                  &UsbAssoc->UsbIaProtocol,
+                  NULL
+                  );
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "UsbCreateAssociation: failed to install UsbIad - %r\n", Status));
+    goto ON_ERROR;
+  }
+
+  //
+  // Open USB Host Controller Protocol by Child
+  //
+  Status = UsbOpenHostProtoByChild (Device->Bus, UsbAssoc->Handle);
+
+  if (EFI_ERROR (Status)) {
+    gBS->UninstallMultipleProtocolInterfaces (
+           UsbAssoc->Handle,
+           &gEfiDevicePathProtocolGuid,
+           UsbAssoc->DevicePath,
+           &gEfiUsbInterfaceAssociationProtocolGuid,
+           &UsbAssoc->UsbIaProtocol,
+           NULL
+           );
+
+    DEBUG ((DEBUG_ERROR, "UsbCreateAssociation: failed to open host for child - %r\n", Status));
+    goto ON_ERROR;
+  }
+
+  return UsbAssoc;
+
+ON_ERROR:
+  if (UsbAssoc->DevicePath != NULL) {
+    FreePool (UsbAssoc->DevicePath);
+  }
+
+  FreePool (UsbAssoc);
+  return NULL;
+}
+
 /**
   Free the resource used by this USB device.
 
@@ -236,6 +481,41 @@ UsbCreateDevice (
   return Device;
 }
 
+/**
+  Connect USB controller at TPL_CALLBACK
+
+  This function is called in both UsbIoControlTransfer and
+  the timer callback in hub enumeration. So, at least it is
+  called at TPL_CALLBACK. Some driver sitting on USB has
+  twisted TPL used. It should be no problem for us to connect
+  or disconnect at CALLBACK.
+
+  @param  Handle        Controller handle to be connected
+
+**/
+EFI_STATUS
+UsbConnectController (
+  EFI_HANDLE  Handle
+  )
+{
+  EFI_STATUS  Status;
+  EFI_TPL     OldTpl;
+
+  OldTpl = UsbGetCurrentTpl ();
+  DEBUG ((DEBUG_INFO, "UsbConnectDriver: TPL before connect is %d, %p\n", (UINT32)OldTpl, Handle));
+
+  gBS->RestoreTPL (TPL_CALLBACK);
+
+  Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);
+
+  DEBUG ((DEBUG_INFO, "UsbConnectDriver: TPL after connect is %d\n", (UINT32)UsbGetCurrentTpl ()));
+  ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);
+
+  gBS->RaiseTPL (OldTpl);
+
+  return Status;
+}
+
 /**
   Connect the USB interface with its driver. EFI USB bus will
   create a USB interface for each separate interface descriptor.
@@ -252,7 +532,6 @@ UsbConnectDriver (
   )
 {
   EFI_STATUS  Status;
-  EFI_TPL     OldTpl;
 
   Status = EFI_SUCCESS;
 
@@ -264,30 +543,12 @@ UsbConnectDriver (
     DEBUG ((DEBUG_INFO, "UsbConnectDriver: found a hub device\n"));
     Status = mUsbHubApi.Init (UsbIf);
   } else {
-    //
-    // This function is called in both UsbIoControlTransfer and
-    // the timer callback in hub enumeration. So, at least it is
-    // called at TPL_CALLBACK. Some driver sitting on USB has
-    // twisted TPL used. It should be no problem for us to connect
-    // or disconnect at CALLBACK.
-    //
-
     //
     // Only recursively wanted usb child device
     //
     if (UsbBusIsWantedUsbIO (UsbIf->Device->Bus, UsbIf)) {
-      OldTpl = UsbGetCurrentTpl ();
-      DEBUG ((DEBUG_INFO, "UsbConnectDriver: TPL before connect is %d, %p\n", (UINT32)OldTpl, UsbIf->Handle));
-
-      gBS->RestoreTPL (TPL_CALLBACK);
-
-      Status           = gBS->ConnectController (UsbIf->Handle, NULL, NULL, TRUE);
+      Status           = UsbConnectController (UsbIf->Handle);
       UsbIf->IsManaged = (BOOLEAN) !EFI_ERROR (Status);
-
-      DEBUG ((DEBUG_INFO, "UsbConnectDriver: TPL after connect is %d\n", (UINT32)UsbGetCurrentTpl ()));
-      ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);
-
-      gBS->RaiseTPL (OldTpl);
     }
   }
 
@@ -378,6 +639,7 @@ UsbSelectConfig (
   USB_INTERFACE       *UsbIf;
   EFI_STATUS          Status;
   UINT8               Index;
+  USB_ASSOCIATION     *UsbIa;
 
   //
   // Locate the active config, then set the device's pointer
@@ -393,7 +655,7 @@ UsbSelectConfig (
     }
   }
 
-  if (Index == DevDesc->Desc.NumConfigurations) {
+  if ((ConfigDesc == NULL) || (Index == DevDesc->Desc.NumConfigurations)) {
     return EFI_NOT_FOUND;
   }
 
@@ -406,6 +668,19 @@ UsbSelectConfig (
     Device->Address
     ));
 
+  //
+  // Create interfaces for each USB interface association descriptor.
+  //
+  Device->NumOfAssociation = ConfigDesc->NumOfIads;
+
+  for (Index = 0; Index < ConfigDesc->NumOfIads; Index++) {
+    DEBUG ((DEBUG_INFO, "UsbSelectConfig: process IAD %d\n", Index));
+
+    UsbIa = UsbCreateAssociation (Device, Index, ConfigDesc->Iads[Index]);
+    ASSERT (Index < USB_MAX_ASSOCIATION);
+    Device->Associations[Index] = UsbIa;
+  }
+
   //
   // Create interfaces for each USB interface descriptor.
   //
@@ -448,9 +723,55 @@ UsbSelectConfig (
 
   Device->NumOfInterface = Index;
 
+  //
+  // Connect association device drivers. Connection may fail if if device driver has been already
+  // started for any UsbIo that belongs to the association.
+  //
+  for (Index = 0; Index < Device->NumOfAssociation; Index++) {
+    Status                                 = gBS->ConnectController (Device->Associations[Index]->Handle, NULL, NULL, TRUE);
+    Device->Associations[Index]->IsManaged = (BOOLEAN) !EFI_ERROR (Status);
+
+    DEBUG ((DEBUG_INFO, "UsbSelectConfig: association driver connect: %r\n", Status));
+  }
+
   return EFI_SUCCESS;
 }
 
+/**
+  Disconnect USB controller at TPL_CALLBACK
+
+  This function is called in both UsbIoControlTransfer and
+  the timer callback in hub enumeration. So, at least it is
+  called at TPL_CALLBACK. Some driver sitting on USB has
+  twisted TPL used. It should be no problem for us to connect
+  or disconnect at CALLBACK.
+
+  @param  Handle        Controller handle to be disconnected
+
+**/
+EFI_STATUS
+UsbDisconnectController (
+  EFI_HANDLE  Handle
+  )
+{
+  EFI_TPL     OldTpl;
+  EFI_STATUS  Status;
+
+  OldTpl = UsbGetCurrentTpl ();
+  DEBUG ((DEBUG_INFO, "UsbDisconnectDriver: old TPL is %d, %p\n", (UINT32)OldTpl, Handle));
+
+  gBS->RestoreTPL (TPL_CALLBACK);
+
+  Status = gBS->DisconnectController (Handle, NULL, NULL);
+
+  DEBUG ((DEBUG_INFO, "UsbDisconnectDriver: TPL after disconnect is %d, %d\n", (UINT32)UsbGetCurrentTpl (), Status));
+  ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);
+
+  gBS->RaiseTPL (OldTpl);
+
+  return Status;
+}
+
 /**
   Disconnect the USB interface with its driver.
 
@@ -462,7 +783,6 @@ UsbDisconnectDriver (
   IN USB_INTERFACE  *UsbIf
   )
 {
-  EFI_TPL     OldTpl;
   EFI_STATUS  Status;
 
   //
@@ -473,27 +793,11 @@ UsbDisconnectDriver (
   if (UsbIf->IsHub) {
     Status = UsbIf->HubApi->Release (UsbIf);
   } else if (UsbIf->IsManaged) {
-    //
-    // This function is called in both UsbIoControlTransfer and
-    // the timer callback in hub enumeration. So, at least it is
-    // called at TPL_CALLBACK. Some driver sitting on USB has
-    // twisted TPL used. It should be no problem for us to connect
-    // or disconnect at CALLBACK.
-    //
-    OldTpl = UsbGetCurrentTpl ();
-    DEBUG ((DEBUG_INFO, "UsbDisconnectDriver: old TPL is %d, %p\n", (UINT32)OldTpl, UsbIf->Handle));
+    Status = UsbDisconnectController (UsbIf->Handle);
 
-    gBS->RestoreTPL (TPL_CALLBACK);
-
-    Status = gBS->DisconnectController (UsbIf->Handle, NULL, NULL);
     if (!EFI_ERROR (Status)) {
       UsbIf->IsManaged = FALSE;
     }
-
-    DEBUG ((DEBUG_INFO, "UsbDisconnectDriver: TPL after disconnect is %d, %d\n", (UINT32)UsbGetCurrentTpl (), Status));
-    ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);
-
-    gBS->RaiseTPL (OldTpl);
   }
 
   return Status;
@@ -510,10 +814,11 @@ UsbRemoveConfig (
   IN USB_DEVICE  *Device
   )
 {
-  USB_INTERFACE  *UsbIf;
-  UINTN          Index;
-  EFI_STATUS     Status;
-  EFI_STATUS     ReturnStatus;
+  USB_INTERFACE    *UsbIf;
+  USB_ASSOCIATION  *UsbIa;
+  UINTN            Index;
+  EFI_STATUS       Status;
+  EFI_STATUS       ReturnStatus;
 
   //
   // Remove each interface of the device
@@ -543,6 +848,35 @@ UsbRemoveConfig (
   }
 
   Device->ActiveConfig = NULL;
+
+  if (EFI_ERROR (ReturnStatus)) {
+    return ReturnStatus;
+  }
+
+  // ReturnStatus is EFI_SUCCESS
+
+  //
+  // Remove each interface association
+  //
+  for (Index = 0; Index < Device->NumOfAssociation; Index++) {
+    UsbIa = Device->Associations[Index];
+
+    Status = UsbDisconnectController (UsbIa->Handle);
+    if (!EFI_ERROR (Status)) {
+      Status = UsbFreeAssociation (UsbIa);
+      DEBUG ((DEBUG_INFO, "UsbRemoveConfig: free association: %r\n", Status));
+      if (EFI_ERROR (Status)) {
+        UsbConnectController (UsbIa->Handle);
+      }
+    }
+
+    if (!EFI_ERROR (Status)) {
+      Device->Associations[Index] = NULL;
+    } else {
+      ReturnStatus = Status;
+    }
+  }
+
   return ReturnStatus;
 }
 
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbIntfAssoc.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbIntfAssoc.c
new file mode 100644
index 0000000000..87218705b8
--- /dev/null
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbIntfAssoc.c
@@ -0,0 +1,153 @@
+/** @file
+
+  Usb Interface Association Protocol implementation.
+
+Copyright (c) 2025, American Megatrends International, LLC. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UsbBus.h"
+
+/**
+  Get the interface from interface association.
+
+  @param[in]  UsbIa   A pointer to the interface association data.
+  @param[in]  InterfaceNumber Interface to look for inside the association.
+
+  @retval A pointer to the interface data
+  @retval NULL  Interface is not found in the association.
+
+**/
+USB_INTERFACE_DESC *
+UsbAssocFindInterface (
+  IN USB_ASSOCIATION  *UsbIa,
+  IN UINT8            InterfaceNumber
+  )
+{
+  UINT8  Index;
+  UINT8  Intrf;
+
+  Intrf = UsbIa->IaDesc->Desc.FirstInterface;
+  for (Index = 0; Index < UsbIa->IaDesc->Desc.InterfaceCount; Index++) {
+    if (InterfaceNumber == Intrf) {
+      return UsbIa->IaDesc->Interfaces[Index];
+    }
+
+    Intrf++;
+  }
+
+  DEBUG ((DEBUG_ERROR, "UsbAssocFindInterface: interface 0x%x does not belong to this association\n", InterfaceNumber));
+  return NULL;
+}
+
+/**
+  Get the USB Interface Association Descriptor from the current USB configuration.
+
+  @param[in] This              A pointer to the EFI_USB_INTERFACE_ASSOCIATION_PROTOCOL instance.
+  @param[out] Descriptor       A pointer to the caller allocated USB Interface Association Descriptor.
+
+  @retval EFI_SUCCESS           The descriptor was retrieved successfully.
+  @retval EFI_INVALID_PARAMETER Descriptor is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbIaGetAssociationDescriptor (
+  IN  EFI_USB_INTERFACE_ASSOCIATION_PROTOCOL    *This,
+  OUT EFI_USB_INTERFACE_ASSOCIATION_DESCRIPTOR  *Descriptor
+  )
+{
+  USB_ASSOCIATION  *UsbIa;
+  EFI_TPL          OldTpl;
+  EFI_STATUS       Status;
+
+  OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
+
+  Status = EFI_SUCCESS;
+
+  ASSERT (Descriptor != NULL);
+  if (Descriptor == NULL) {
+    Status = EFI_INVALID_PARAMETER;
+    goto ON_EXIT;
+  }
+
+  UsbIa = USB_ASSOCIATION_FROM_USBIA (This);
+  CopyMem (Descriptor, &(UsbIa->IaDesc->Desc), sizeof (EFI_USB_INTERFACE_ASSOCIATION_DESCRIPTOR));
+
+ON_EXIT:
+  gBS->RestoreTPL (OldTpl);
+
+  return Status;
+}
+
+/**
+  Retrieve the details of the requested interface that belongs to USB association.
+
+  @param[in] This              A pointer to the EFI_USB_INTERFACE_ASSOCIATION_PROTOCOL instance.
+  @param[in] InterfaceNumber   Interface number.
+  @param[out] UsbIo            A pointer to the caller allocated UsbIo protocol.
+  @param[out] SettingsCount    A pointer to the caller allocated number of settings for this interface.
+
+  @retval EFI_SUCCESS           Output parameters were updated successfully.
+  @retval EFI_INVALID_PARAMETER UsbIo or SettuntsCount is NULL.
+  @retval EFI_NOT_FOUND         Interface does not belong to this interface association.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbIaGetAssociateSettings (
+  IN  EFI_USB_INTERFACE_ASSOCIATION_PROTOCOL  *This,
+  IN  UINT8                                   InterfaceNumber,
+  OUT EFI_USB_IO_PROTOCOL                     **UsbIo,
+  OUT UINTN                                   *SettingsCount
+  )
+{
+  USB_ASSOCIATION     *UsbIa;
+  EFI_TPL             OldTpl;
+  UINT8               Index;
+  EFI_STATUS          Status;
+  USB_DEVICE          *Device;
+  USB_INTERFACE_DESC  *IfDesc;
+
+  OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
+
+  ASSERT ((UsbIo != NULL) && (SettingsCount != NULL));
+  if ((UsbIo == NULL) || (SettingsCount == NULL)) {
+    Status =  EFI_INVALID_PARAMETER;
+    goto  ON_EXIT;
+  }
+
+  UsbIa = USB_ASSOCIATION_FROM_USBIA (This);
+
+  IfDesc = UsbAssocFindInterface (UsbIa, InterfaceNumber);
+  if (IfDesc == NULL) {
+    Status = EFI_NOT_FOUND;
+    goto ON_EXIT;
+  }
+
+  *SettingsCount = IfDesc->NumOfSetting - 1;
+
+  //
+  // Find UsbIo protocol for this interface
+  //
+  Device = UsbIa->Device;
+  Status = EFI_NOT_FOUND;
+
+  for (Index = 0; Index < Device->NumOfInterface; Index++) {
+    if (Device->Interfaces[Index]->IfSetting->Desc.InterfaceNumber == InterfaceNumber) {
+      *UsbIo = &Device->Interfaces[Index]->UsbIo;
+      Status = EFI_SUCCESS;
+      break;
+    }
+  }
+
+ON_EXIT:
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+}
+
+EFI_USB_INTERFACE_ASSOCIATION_PROTOCOL  mUsbIaProtocol = {
+  UsbIaGetAssociationDescriptor,
+  UsbIaGetAssociateSettings
+};
diff --git a/MdePkg/Include/Protocol/UsbAssociationIo.h b/MdePkg/Include/Protocol/UsbAssociationIo.h
new file mode 100644
index 0000000000..8ce66207c9
--- /dev/null
+++ b/MdePkg/Include/Protocol/UsbAssociationIo.h
@@ -0,0 +1,81 @@
+/** @file
+  EFI Usb Interface Association protocol.
+
+  This protocol is used by USB drivers, running in the EFI boot services
+  environment to access USB devices that implement their configurations
+  using interface association: USB cameras, USB audio devices, USB modems, etc.
+
+  Copyright (c) 2025, American Megatrends International LLC. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __USB_ASSOCIATION_IO_H__
+#define __USB_ASSOCIATION_IO_H__
+
+#include <IndustryStandard/Usb.h>
+#include <Protocol/UsbIo.h>
+
+typedef USB_INTERFACE_ASSOCIATION_DESCRIPTOR  EFI_USB_INTERFACE_ASSOCIATION_DESCRIPTOR;
+
+//
+// Global ID for the USB IAD Protocol
+//
+#define EFI_USB_INTERFACE_ASSOCIATION_PROTOCOL_GUID \
+  { \
+    0xf4279fb1, 0xef1e, 0x4346, { 0xab, 0x32, 0x3f, 0xe3, 0x86, 0xee, 0xb4, 0x52 } \
+  }
+
+typedef struct _EFI_USB_INTERFACE_ASSOCIATION_PROTOCOL EFI_USB_INTERFACE_ASSOCIATION_PROTOCOL;
+
+/**
+  Get the USB Interface Association Descriptor from the current USB configuration.
+
+  @param[in]  This              A pointer to the EFI_USB_IA_PROTOCOL instance.
+  @param[out]  Descriptor       A pointer to the caller allocated USB Interface Association Descriptor.
+
+  @retval EFI_SUCCESS           The descriptor was retrieved successfully.
+  @retval EFI_INVALID_PARAMETER Descriptor is NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_USB_IA_GET_ASSOCIATION_DESCRIPTOR)(
+  IN  EFI_USB_INTERFACE_ASSOCIATION_PROTOCOL    *This,
+  OUT EFI_USB_INTERFACE_ASSOCIATION_DESCRIPTOR  *Descriptor
+  );
+
+/**
+  Retrieve the details of the requested interface that belongs to USB association.
+
+  @param[in] This              A pointer to the EFI_USB_IA_PROTOCOL instance.
+  @param[in] InterfaceNumber   Interface number.
+  @param[out] UsbIo            A pointer to the caller allocated UsbIo protocol.
+  @param[out] SettingsCount    A pointer to the caller allocated number of settings for this interface.
+
+  @retval EFI_SUCCESS           Output parameters were updated successfully.
+  @retval EFI_INVALID_PARAMETER UsbIo or SettuntsCount is NULL.
+  @retval EFI_NOT_FOUND         Interface does not belong to this interface association.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_USB_IA_GET_ASSOCIATE_SETTINGS)(
+  IN  EFI_USB_INTERFACE_ASSOCIATION_PROTOCOL  *This,
+  IN  UINT8                                   InterfaceNumber,
+  OUT EFI_USB_IO_PROTOCOL                     **UsbIo,
+  OUT UINTN                                   *SettingsCount
+  );
+
+/**
+  USB interface association protocol functions.
+
+**/
+struct _EFI_USB_INTERFACE_ASSOCIATION_PROTOCOL {
+  EFI_USB_IA_GET_ASSOCIATION_DESCRIPTOR  UsbIaGetAssociationDescriptor;
+  EFI_USB_IA_GET_ASSOCIATE_SETTINGS      UsbIaGetAssociateSettings;
+};
+
+extern EFI_GUID  gEfiUsbInterfaceAssociationProtocolGuid;
+
+#endif
diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
index f4a60e5cc7..3fc30c23b9 100644
--- a/MdePkg/MdePkg.dec
+++ b/MdePkg/MdePkg.dec
@@ -1991,6 +1991,9 @@
   ## Include/Protocol/ShellDynamicCommand.h
   gEfiShellDynamicCommandProtocolGuid  = { 0x3c7200e9, 0x005f, 0x4ea4, {0x87, 0xde, 0xa3, 0xdf, 0xac, 0x8a, 0x27, 0xc3 }}
 
+  ## Include/Protocol/UsbAssociationIo.h
+  gEfiUsbInterfaceAssociationProtocolGuid = { 0xf4279fb1, 0xef1e, 0x4346, { 0xab, 0x32, 0x3f, 0xe3, 0x86, 0xee, 0xb4, 0x52 }}
+
 #
 # [Error.gEfiMdePkgTokenSpaceGuid]
 #   0x80000001 | Invalid value provided.
