From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM02-BN1-obe.outbound.protection.outlook.com (NAM02-BN1-obe.outbound.protection.outlook.com [40.107.212.71]) by mx.groups.io with SMTP id smtpd.web10.99906.1683517964976460527 for ; Sun, 07 May 2023 20:52:46 -0700 Authentication-Results: mx.groups.io; dkim=fail, err=mail: missing word in phrase: charset not supported: "iso-2022-jp"; spf=pass (domain: ami.com, ip: 40.107.212.71, mailfrom: richardho@ami.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=B/L6DOamDE54/5PrqJnvmgffpnEIZMP1LWio11Y2PiQRUlm0FJ87jclupkyqBbuaJ0rxV2/LofCKf/UfpoutaE4O96dgJnw6NgCh30MTp7QkIVjlNKssBQ/BGG54fGmfeLpy1cPmGrE3AUYXHsFivyjkQoIGsb7wd8BtdI47O7W6raGd5AbQfVUeUkAyrPK5QIStlBXUEa8fDeiLmE+hNHe+0Qm1kBLKsXQghq9Sn37qdyDZluLhpgHI4g7BO+Ih344vqpfZL+MYlU7JdYneMCZITbI+aGkKFyco9B2HrP5D4qjyOBrhSosqI4jBR1s5RClOQURL0IYteM08suc1MQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=vRZXUqFx7SmQ+swv0RvhU66IBKYRSrLLYpMmy7jeT/U=; b=BZPgAicfEren3QyHPt35sF7HUYctRbgb1gx+ob3VOwdOOzmLlv3ehWzdP5EFokzwAbe3wAQBgv9Sql1Eko4YWExm4pzMZipDQ6PDQgr3Oo8tvJLPkXVDzNNQ8lZtDc+9q08nd2ppG2kh0W6Fut5qrKrNGGdbIU/7P+UXRhs7Bm4Qf8hiCeJ0UeRzIvVaLUdrl9ezr6FfSxQIDBBlS333E+sWhjwLD+3j5H8mwbju1jQNFLuwbCLE39U4Ud06giVczPSxgKwh+ZxR4yczNMHcJ0NnLcooNBK+Jd4KSXAr5+z5r5jDRzzWBxUGZqK9oDCGeFf938fzwjSVPP3MZ8b0Pg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=ami.com; dmarc=pass action=none header.from=ami.com; dkim=pass header.d=ami.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ami.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=vRZXUqFx7SmQ+swv0RvhU66IBKYRSrLLYpMmy7jeT/U=; b=fbDBs57mO40uvmRPwJFvyHmGWneh+qZ+HDT2q/KONu0+R/EU/d9p31Wjsw4lCTvUz/V2ly88Pyw8H2pngZ1ffRzz0LBsaP/gQ2Vh8Eu+i/3j+GH6BTfTCGH2uW1nfxmg66lC/3DvIVoroS3DdcUVYshcPwU4Ie/tgwd6awrPwVg= Received: from CY8PR10MB6441.namprd10.prod.outlook.com (2603:10b6:930:63::16) by DS0PR10MB6996.namprd10.prod.outlook.com (2603:10b6:8:152::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6363.31; Mon, 8 May 2023 03:52:41 +0000 Received: from CY8PR10MB6441.namprd10.prod.outlook.com ([fe80::1eb2:3625:6f26:9ed6]) by CY8PR10MB6441.namprd10.prod.outlook.com ([fe80::1eb2:3625:6f26:9ed6%6]) with mapi id 15.20.6363.032; Mon, 8 May 2023 03:52:41 +0000 From: =?UTF-8?B?UmljaGFyZEhvIFvkvZXmmI7lv6Bd?= To: "devel@edk2.groups.io" CC: Andrew Fish , Leif Lindholm , Michael D Kinney , Michael Kubacki , Zhiguang Liu , Liming Gao , Hao A Wu , Ray Ni , Tinh Nguyen , Rebecca Cran , =?iso-2022-jp?B?VG9ueSBMbyAoGyRCTWU2Yj4+GyhCKQ==?= Subject: [PATCH v3 3/3] MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm: Add USB Cdc NCM devices support Thread-Topic: [PATCH v3 3/3] MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm: Add USB Cdc NCM devices support Thread-Index: AQHZgWCJ20NhhYBxzkiEYLUp+OILmg== Date: Mon, 8 May 2023 03:52:41 +0000 Message-ID: <20230508035224.967-3-richardho@ami.com> References: <20230508035224.967-1-richardho@ami.com> In-Reply-To: <20230508035224.967-1-richardho@ami.com> Accept-Language: zh-TW, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-mailer: git-send-email 2.35.1.windows.2 authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=ami.com; x-ms-publictraffictype: Email x-ms-traffictypediagnostic: CY8PR10MB6441:EE_|DS0PR10MB6996:EE_ x-ms-office365-filtering-correlation-id: 4b43e1f3-33e0-4eef-d297-08db4f77ac60 x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: sLTw9DmlgQa3u/Kzu29XuR8oq3tX5BORJpTRP1qd8YEgsT61zKZgpHqIq0ATkGG9IO+kBX/1XunAoN487csZgmxx2+BOosqJL4ik7avShoS955Awf040++lqRb2TetYY+Ms9Xm9kbhuRwTWugH3ZEWHGACSGRZrYWttKjG0fzaB+z2NSI27Qe4GPtlFnsoS8Tm0psP36y5Zt62/Dh5BjwouIyr8OLRWzjhtMzDBf9bnbkMwumxkDisPD4c0xa8RYgqeLBdTR1zWZy0+dYKhyMZVN5ljzVLZ3a5zKwE4MB12H4xhGeypX4UfKoJRby37Rx7bcAla7CqSM/dy63Gc1oxLK1Tltu+ZPfx2dJm2H3o2bCYUHSUAgIUnT1iePqjHWxmYzJnVe+C1VWMdhN9KBegKutriDgNSAEuWMZM0i/HrMvMIHQP6FUxgntXGJ6UyQwOw6QuTeUpD+wIj5IVhTVZHLvMd8Xw6XZ0ptfLjTggo1B2uMqqJw/q9OPz4316fkYGiCEiZOwxuEdHHNz+WNAPSdL4mjhGgoYXaUtiA0Z95sZxm1ygbU85gPRVd6Vl5t8zhjWhXl5YLoLRb3Vvxzbu4KxxJJjjDqQ7T8BdtdiAh0lAE8tXYjFKmthh0qX2r5vuMbhNWWa13sKWb7G39dqg== x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:CY8PR10MB6441.namprd10.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230028)(4636009)(366004)(346002)(136003)(396003)(39840400004)(376002)(451199021)(8936002)(8676002)(6512007)(6506007)(1076003)(26005)(2616005)(7416002)(2906002)(30864003)(83380400001)(4326008)(41300700001)(91956017)(76116006)(478600001)(6486002)(6916009)(316002)(19627235002)(5660300002)(186003)(66446008)(64756008)(66946007)(66476007)(66556008)(54906003)(71200400001)(36756003)(40140700001)(85182001)(86362001)(38070700005)(38100700002)(122000001)(579004)(559001)(44824005);DIR:OUT;SFP:1101; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?iso-2022-jp?B?UUtBbUFZM2RKdjdaYkliUnBtZkpvUWYzdzZzeEFPT0NwQXBVSHBpRG54?= =?iso-2022-jp?B?aTV5UVRpWWU1ZzdHcVZrdWM4ZUZvNUtZT2JGMDJnbXdLVTJXczZOcTRN?= =?iso-2022-jp?B?dXVQMzkwSnlLKzRKSUpoR2RYVXNSSWEwVlJNUE9uK2NnOTN4c0dqZllx?= =?iso-2022-jp?B?QW9mc3JvS3RTblZWUFF4eVRiemZ3SEpuMWJvbHBHeUsyZnZ5SkJFUjZu?= =?iso-2022-jp?B?bHVvaUVEcVZwaUxoRitMK1MxRzVDeXdycnhYbVpWWEFUOFFIVExyVGJ3?= =?iso-2022-jp?B?Q2NxQkp2TTVQUTVxcFRVMEpoVFU3RFE5czdnUUc1Q1R6KzV0UlE2c2U2?= =?iso-2022-jp?B?SGRmNm9yRjFXTmJjd29lY0xQditEQkJ1UGF0Yk12VzdqbSthVEwxaFdN?= =?iso-2022-jp?B?MkNHUCs5VElqYUpNY3FtTHNWUWo1ZGFZeFJ1UlhKZUdiYnd4MkN1SG1K?= =?iso-2022-jp?B?Q3NLSHR5UkFuNlhmZzVaM1lUT09GR2hDL0l5WGhDZFRVOUl2dHFRSm01?= =?iso-2022-jp?B?dGhJMFBjVnliZVJsbFRQNktBTVprODcxT0h0ajB4NkdDTTZWcFN5VUNw?= =?iso-2022-jp?B?dGpvTzkwS0VyZmFzMi9zV3ZkdW5OclFDREhmSElLUFB5L0FNR2ZmUGt3?= =?iso-2022-jp?B?VG1LTllFdWhZcFpzd0N3L2o5Z0ZQb01JaHIvMzY2WlpvbEJXYVoxV3NK?= =?iso-2022-jp?B?SEtEb2Fua3pKTVRKMlZybkRaeS9HeGlkeWxEVU1nNkJhK1VMNU1EZlVH?= =?iso-2022-jp?B?ZmlDK1d5ZFF3ZnkvY1JpcW9DS0hMckp2S2t2VllkM0kyRXBXVS9wMUU0?= =?iso-2022-jp?B?c00zNXMxQzNpaEZEcUxQb245cENKTGZvQW1ZeWJPOFhUNS9CSzVqaW5E?= =?iso-2022-jp?B?enRjeUpISGJpWFB6Z0crLzVOZ2Q0bVg2aDZkb2oxYUVpS00xU3JaTVZm?= =?iso-2022-jp?B?U0czTkdubFlnSUZsNEMrcHpQcHZza3YrVlpEZnRNUjc2aFM2WFdJajBC?= =?iso-2022-jp?B?TTd5VW1iM3pZR2lDMzgrNG5PdjRKUGgzRDJSMHpBVFIwZnFXZjdML2dL?= =?iso-2022-jp?B?UHpwY1JEQlB5c1ZDUmVxMWJzYnpGcy9kRGphTG9QWi9VMDN2MEE5eDhp?= =?iso-2022-jp?B?bU9talpYT0tDMks5SVVNYTZmcStMN29KR0h5RzNmeWw0eUoxVXlSOGd5?= =?iso-2022-jp?B?ME8vcXBKK3lvbWtwK04vZTNPZzZyR0JSUzQvay9XS2dVY0lmem1yUFMx?= =?iso-2022-jp?B?Yk5xZGVIeWRxTWRCRVdQR2owS0R5SWJQYzFqblVSYThJb1pHR3gvSkEv?= =?iso-2022-jp?B?TnNFVVJCVUljck5vWFU2bi9uYktrb3V6Ung4WklTY3lzQjlWeUtSVnRh?= =?iso-2022-jp?B?Q1JSRk9oZmZVcDVvV1pGM00wNlloNGNYb1VldEhUVHpmYVFXeGlwTVQ4?= =?iso-2022-jp?B?M01Mcjc3MG5iUnVLejlPT3gwbkNibVgvb3lHNGVKWVdSaE9nY0NSQlh5?= =?iso-2022-jp?B?QW5BTGllREtaUEZRQ0U4NFg1blBUdEdNeC9tZXlQdU1BR2g0dzR6bDB0?= =?iso-2022-jp?B?V1FZY1BNb0FCL2ppSWNuQW5kOXZ3WWwzQ2hjVWpZNEFSWVZ2bWxpLzVt?= =?iso-2022-jp?B?Wk1JeGJ6a0pyQ1pzZ0lRMjJBOVVINDNDMHd1SHJDWURuQ29UeFNwbmFm?= =?iso-2022-jp?B?SHQyd1A4YjF4dG15bHA5c1lZa0hCclhIVG9rWVo0R0NHTzlMdFlJRjhq?= =?iso-2022-jp?B?ZmZaN0srcU1CK2hheVNuNld0eCtuQTUvRmRQdnJXNGVySXY3Y2xQVFhz?= =?iso-2022-jp?B?QStBUUJZaGxWcG03ZEg3U3ZkbnRzVlg1c3pHTUY4aDZwdlNJOUc1TkF5?= =?iso-2022-jp?B?U0hPa2oyWE1SQkVxblhxQWpsMHJQM2FnVnQ0cXRNUTY2RGtZTlhlWjFy?= =?iso-2022-jp?B?N1EwTFVlaVRqS01HRVJGSVpXajkvWkJKRmxEcEVYUWZ0QTRoT1J1UUZp?= =?iso-2022-jp?B?ZXRyWk9Va0RkZDJlT3orczFDMXVrWm5pUG5zNzM0cjVHdVYwOG5YRG02?= =?iso-2022-jp?B?QSt4VWF5TGNpWVBoaE1YK3o4RUNEdm9vS0JIaFZsNjdlMmJvUms0dGlQ?= =?iso-2022-jp?B?dmdzZFAxZU5INk8xN1NuTDhnTnJmcWNWWmJDOGFMVk9qWCsvVXhmM1RT?= =?iso-2022-jp?B?amM1N0lvNXcyMEhqV0tiTE9lL0Q5cTBmSXBLenZNUVNubGNQemRXRWl2?= =?iso-2022-jp?B?VlY2L3JxK0JkSU9MTDY4VU5tbG9TVjhDWmkrMVZjVHlldkF6eFJ5NnBX?= =?iso-2022-jp?B?NENKSQ==?= MIME-Version: 1.0 X-OriginatorOrg: ami.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: CY8PR10MB6441.namprd10.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 4b43e1f3-33e0-4eef-d297-08db4f77ac60 X-MS-Exchange-CrossTenant-originalarrivaltime: 08 May 2023 03:52:41.4372 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 27e97857-e15f-486c-b58e-86c2b3040f93 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: 4oi24+cNmdrKR5Meir6GN3t5KTVAjbfZWJ/nUDk0HXi3keysNrhJGJ1N9wbJWvLw7Wi7z6DuwobTPyMy9osxyA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DS0PR10MB6996 Content-Language: en-US Content-Type: text/plain; charset="iso-2022-jp" Content-Transfer-Encoding: quoted-printable This driver provides UEFI driver for USB CDC NCM device Signed-off-by: Richard Ho Cc: Andrew Fish Cc: Leif Lindholm Cc: Michael D Kinney Cc: Michael Kubacki Cc: Zhiguang Liu Cc: Liming Gao Cc: Hao A Wu Cc: Ray Ni Tested-by: Tinh Nguyen Reviewed-by: Rebecca Cran Reviewed-by: Tony Lo --- .../Usb/UsbNetwork/UsbCdcNcm/ComponentName.c | 170 +++ .../Bus/Usb/UsbNetwork/UsbCdcNcm/UsbCdcNcm.c | 506 +++++++++ .../Bus/Usb/UsbNetwork/UsbCdcNcm/UsbCdcNcm.h | 245 +++++ .../Usb/UsbNetwork/UsbCdcNcm/UsbCdcNcm.inf | 42 + .../Usb/UsbNetwork/UsbCdcNcm/UsbNcmFunction.c | 966 ++++++++++++++++++ 5 files changed, 1929 insertions(+) create mode 100644 MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/ComponentName= .c create mode 100644 MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbCdcNcm.c create mode 100644 MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbCdcNcm.h create mode 100644 MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbCdcNcm.inf create mode 100644 MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbNcmFunctio= n.c diff --git a/MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/ComponentName.c b/Md= eModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/ComponentName.c new file mode 100644 index 0000000000..3cf3dc222d --- /dev/null +++ b/MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/ComponentName.c @@ -0,0 +1,170 @@ +/** @file + This file contains code for USB Ncm Driver Component Name definitions + + Copyright (c) 2023, American Megatrends International LLC. All rights re= served.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#include "UsbCdcNcm.h" + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE gUsbNcmDriverNameT= able[] =3D { + { + "eng;en", + L"USB NCM Driver" + }, + { + NULL, + NULL + } +}; + +EFI_STATUS +EFIAPI +UsbNcmComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +UsbNcmComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gUsbNcmComponen= tName =3D { + UsbNcmComponentNameGetDriverName, + UsbNcmComponentNameGetControllerName, + "eng" +}; + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gUsbNcmCompone= ntName2 =3D { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UsbNcmComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbNcmComponentNameGetControlle= rName, + "en" +}; + +/** + 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 o= f 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 speci= fied + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param[in] Language A pointer to a Null-terminated ASCII strin= g + array indicating the language. This is the + language of the driver name that the calle= r 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 specifie= d + in RFC 4646 or ISO 639-2 language code for= mat. + @param[out] DriverName 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 specifie= d by + This and the language specified by Languag= e 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 supp= ort + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +UsbNcmComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + gUsbNcmDriverNameTable, + DriverName, + (BOOLEAN)(This =3D=3D &gUsbNcmComponentName) + ); +} + +/** + Retrieves a Unicode string that is the user readable name of the control= ler + that is being managed by a driver. + + This function retrieves the user readable name of the controller specifi= ed 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 specif= ied by + Language, then a pointer to the controller name is returned in Controlle= rName, + and EFI_SUCCESS is returned. If the driver specified by This is not cur= rently + 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 retu= rned. + + @param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param[in] Controller The handle of a controller that the driver + specified by This is managing. This handl= e + specifies the controller whose name is to = be + returned. + @param[in] ChildHandle The handle of the child controller to retr= ieve + the name of. This is an optional paramete= r that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus d= rivers + 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[in] Language A pointer to a Null-terminated ASCII strin= g + array indicating the language. This is th= e + language of the driver name that the calle= r 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 specifie= d in + RFC 4646 or ISO 639-2 language code format= . + @param[out] ControllerName A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle a= nd + ChildHandle in the language specified by + Language from the point of view of the dri= ver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable n= ame 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 va= lid + 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 curren= tly + managing the controller specified by + ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +UsbNcmComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbCdcNcm.c b/MdeMod= ulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbCdcNcm.c new file mode 100644 index 0000000000..f67e6aab69 --- /dev/null +++ b/MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbCdcNcm.c @@ -0,0 +1,506 @@ +/** @file + This file contains code for USB Network Control Model + binding driver + + Copyright (c) 2023, American Megatrends International LLC. All rights re= served.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "UsbCdcNcm.h" + +EFI_DRIVER_BINDING_PROTOCOL gUsbNcmDriverBinding =3D { + UsbNcmDriverSupported, + UsbNcmDriverStart, + UsbNcmDriverStop, + USB_NCM_DRIVER_VERSION, + NULL, + NULL +}; + +/** + Check if this interface is USB NCM SubType + + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance. + + @retval TRUE USB NCM SubType. + @retval FALSE Not USB NCM SubType. + +**/ +BOOLEAN +IsSupportedDevice ( + IN EFI_USB_IO_PROTOCOL *UsbIo + ) +{ + EFI_STATUS Status; + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &InterfaceDescriptor= ); + if (EFI_ERROR (Status)) { + return FALSE; + } + + if ((InterfaceDescriptor.InterfaceClass =3D=3D USB_CDC_CLASS) && + (InterfaceDescriptor.InterfaceSubClass =3D=3D USB_CDC_NCM_SUBCLASS) = && + (InterfaceDescriptor.InterfaceProtocol =3D=3D USB_NO_CLASS_PROTOCOL)= ) + { + return TRUE; + } + + return FALSE; +} + +/** + USB NCM Driver Binding Support. + + @param[in] This Protocol instance pointer. + @param[in] ControllerHandle Handle of device to test. + @param[in] RemainingDevicePath Optional parameter use to pick a speci= fic child + device to start. + + @retval EFI_SUCCESS This driver supports this device. + @retval EFI_ALREADY_STARTED This driver is already running on this= device. + @retval other This driver does not support this devi= ce. + +**/ +EFI_STATUS +EFIAPI +UsbNcmDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + + Status =3D gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + (VOID **)&UsbIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D IsSupportedDevice (UsbIo) ? EFI_SUCCESS : EFI_UNSUPPORTED; + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + return Status; +} + +/** + Check if the USB NCM and USB CDC Data interfaces are from the same devic= e. + + @param[in] UsbEthPath A pointer to the EFI_DEVICE_PATH= _PROTOCOL instance. + @param[in] UsbCdcDataPath A pointer to the EFI_DEVICE_PATH= _PROTOCOL instance. + + @retval EFI_SUCCESS Is the same device. + @retval EFI_NOT_FOUND Is not the same device. + +**/ +EFI_STATUS +IsSameDevice ( + IN EFI_DEVICE_PATH_PROTOCOL *UsbEthPath, + IN EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath + ) +{ + while (1) { + if ((UsbEthPath->Type =3D=3D ACPI_DEVICE_PATH) && (UsbEthPath->SubType= =3D=3D ACPI_DP)) { + if (CompareMem ((ACPI_HID_DEVICE_PATH *)UsbCdcDataPath, (ACPI_HID_DE= VICE_PATH *)UsbEthPath, sizeof (ACPI_HID_DEVICE_PATH))) { + return EFI_NOT_FOUND; + } + } + + if ((UsbEthPath->Type =3D=3D HARDWARE_DEVICE_PATH) && (UsbEthPath->Sub= Type =3D=3D HW_PCI_DP)) { + if (CompareMem ((PCI_DEVICE_PATH *)UsbCdcDataPath, (PCI_DEVICE_PATH = *)UsbEthPath, sizeof (PCI_DEVICE_PATH))) { + return EFI_NOT_FOUND; + } + } + + if ((UsbEthPath->Type =3D=3D MESSAGING_DEVICE_PATH) && (UsbEthPath->Su= bType =3D=3D MSG_USB_DP)) { + if (IsDevicePathEnd (NextDevicePathNode (UsbEthPath))) { + if (((USB_DEVICE_PATH *)UsbEthPath)->ParentPortNumber =3D=3D + ((USB_DEVICE_PATH *)UsbCdcDataPath)->ParentPortNumber) + { + return EFI_SUCCESS; + } else { + return EFI_NOT_FOUND; + } + } else { + if (CompareMem ((USB_DEVICE_PATH *)UsbCdcDataPath, (USB_DEVICE_PAT= H *)UsbEthPath, sizeof (USB_DEVICE_PATH))) { + return EFI_NOT_FOUND; + } + } + } + + UsbEthPath =3D NextDevicePathNode (UsbEthPath); + UsbCdcDataPath =3D NextDevicePathNode (UsbCdcDataPath); + } +} + +/** + Check if the USB CDC Data(UsbIo) installed and return USB CDC Data Handl= e. + + @param[in] UsbEthPath A pointer to the EFI_DEVICE_PATH_PRO= TOCOL instance. + @param[in, out] UsbCdcDataHandle A pointer to the EFI_HANDLE for USB = CDC Data. + + @retval TRUE USB CDC Data(UsbIo) installed. + @retval FALSE USB CDC Data(UsbIo) did not installed. + +**/ +BOOLEAN +IsUsbCdcData ( + IN EFI_DEVICE_PATH_PROTOCOL *UsbEthPath, + IN OUT EFI_HANDLE *UsbCdcDataHandle + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_INTERFACE_DESCRIPTOR Interface; + EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath; + + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiUsbIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return FALSE; + } + + for (Index =3D 0; Index < HandleCount; Index++) { + Status =3D gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiUsbIoProtocolGuid, + (VOID **)&UsbIo + ); + ASSERT_EFI_ERROR (Status); + + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); + ASSERT_EFI_ERROR (Status); + + if ((Interface.InterfaceClass =3D=3D USB_CDC_DATA_CLASS) && + (Interface.InterfaceSubClass =3D=3D USB_CDC_DATA_SUBCLASS) && + (Interface.InterfaceProtocol =3D=3D USB_NCM_NTB_PROTOCOL)) + { + Status =3D gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiDevicePathProtocolGuid, + (VOID **)&UsbCdcDataPath + ); + if (EFI_ERROR (Status)) { + continue; + } + + Status =3D IsSameDevice (UsbEthPath, UsbCdcDataPath); + if (!EFI_ERROR (Status)) { + CopyMem (UsbCdcDataHandle, &HandleBuffer[Index], sizeof (EFI_HANDL= E)); + FreePool (HandleBuffer); + return TRUE; + } + } + } + + FreePool (HandleBuffer); + return FALSE; +} + +/** + Call Back Function. + + @param[in] Event Event whose notification function is being invok= ed. + @param[in] Context The pointer to the notification function's conte= xt, + which is implementation-dependent. + +**/ +VOID +EFIAPI +CallbackFunction ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_INTERFACE_DESCRIPTOR Interface; + + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiUsbIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return; + } + + for (Index =3D 0; Index < HandleCount; Index++) { + Status =3D gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiUsbIoProtocolGuid, + (VOID **)&UsbIo + ); + ASSERT_EFI_ERROR (Status); + + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); + ASSERT_EFI_ERROR (Status); + + if ((Interface.InterfaceClass =3D=3D USB_CDC_CLASS) && + (Interface.InterfaceSubClass =3D=3D USB_CDC_NCM_SUBCLASS) && + (Interface.InterfaceProtocol =3D=3D USB_NO_CLASS_PROTOCOL)) + { + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); + } + } + + FreePool (HandleBuffer); + gBS->CloseEvent (Event); +} + +/** + USB NCM Driver Binding Start. + + @param[in] This Protocol instance pointer. + @param[in] ControllerHandle Handle of device to bind driver to. + @param[in] RemainingDevicePath Optional parameter use to pick a spe= cific child + device to start. + + @retval EFI_SUCCESS This driver is added to ControllerHa= ndle + @retval EFI_DEVICE_ERROR This driver could not be started due= to a device error + @retval EFI_OUT_OF_RESOURCES The driver could not install success= fully due to a lack of resources. + @retval other This driver does not support this de= vice + +**/ +EFI_STATUS +EFIAPI +UsbNcmDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + VOID *Reg; + EFI_EVENT Event; + USB_ETHERNET_DRIVER *UsbEthDriver; + EFI_DEVICE_PATH_PROTOCOL *UsbEthPath; + EFI_HANDLE UsbCdcDataHandle; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_INTERFACE_DESCRIPTOR Interface; + + Status =3D gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + (VOID **)&UsbIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D gBS->OpenProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + (VOID **)&UsbEthPath, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + return Status; + } + + Status =3D IsUsbCdcData (UsbEthPath, &UsbCdcDataHandle) ? EFI_SUCCESS : = EFI_UNSUPPORTED; + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + Status =3D gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, Callback= Function, NULL, &Event); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D gBS->RegisterProtocolNotify (&gEfiUsbIoProtocolGuid, Event,= &Reg); + return Status; + } + + UsbEthDriver =3D AllocateZeroPool (sizeof (USB_ETHERNET_DRIVER)); + if (!UsbEthDriver) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + return EFI_OUT_OF_RESOURCES; + } + + Status =3D LoadAllDescriptor (UsbIo, &UsbEthDriver->Config); + ASSERT_EFI_ERROR (Status); + + GetEndpoint (UsbIo, UsbEthDriver); + + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); + ASSERT_EFI_ERROR (Status); + + UsbEthDriver->Signature =3D USB_ETHERNET_SIGNAT= URE; + UsbEthDriver->NumOfInterface =3D Interface.Interface= Number; + UsbEthDriver->UsbCdcDataHandle =3D UsbCdcDataHandle; + UsbEthDriver->UsbIo =3D UsbIo; + UsbEthDriver->UsbEth.UsbEthReceive =3D UsbEthNcmReceive; + UsbEthDriver->UsbEth.UsbEthTransmit =3D UsbEthNcmTransmit; + UsbEthDriver->UsbEth.UsbEthInterrupt =3D UsbEthNcmInterrupt; + UsbEthDriver->UsbEth.UsbEthMacAddress =3D GetUsbEthMacAddress= ; + UsbEthDriver->UsbEth.UsbEthMaxBulkSize =3D UsbEthNcmBulkSize; + UsbEthDriver->UsbEth.UsbHeaderFunDescriptor =3D GetUsbHeaderFunDesc= riptor; + UsbEthDriver->UsbEth.UsbUnionFunDescriptor =3D GetUsbUnionFunDescr= iptor; + UsbEthDriver->UsbEth.UsbEthFunDescriptor =3D GetUsbEthFunDescrip= tor; + UsbEthDriver->UsbEth.SetUsbEthMcastFilter =3D SetUsbEthMcastFilte= r; + UsbEthDriver->UsbEth.SetUsbEthPowerPatternFilter =3D SetUsbEthPowerFilte= r; + UsbEthDriver->UsbEth.GetUsbEthPowerPatternFilter =3D GetUsbEthPowerFilte= r; + UsbEthDriver->UsbEth.SetUsbEthPacketFilter =3D SetUsbEthPacketFilt= er; + UsbEthDriver->UsbEth.GetUsbEthStatistic =3D GetUsbEthStatistic; + + UsbEthDriver->BulkBuffer =3D AllocateZeroPool (USB_NCM_MAX_NTB_SIZE); + + Status =3D gBS->InstallProtocolInterface ( + &ControllerHandle, + &gEdkIIUsbEthProtocolGuid, + EFI_NATIVE_INTERFACE, + &(UsbEthDriver->UsbEth) + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + FreePool (UsbEthDriver); + return Status; + } + + return Status; +} + +/** + USB NCM Driver Binding Stop. + + @param[in] This Protocol instance pointer. + @param[in] ControllerHandle Handle of device to stop driver on + @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer= . If number of + children is zero stop the entire bus d= river. + @param[in] ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed ControllerHandl= e + @retval other This driver was not removed from this = device + +**/ +EFI_STATUS +EFIAPI +UsbNcmDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EDKII_USB_ETHERNET_PROTOCOL *UsbEthProtocol; + USB_ETHERNET_DRIVER *UsbEthDriver; + + Status =3D gBS->OpenProtocol ( + ControllerHandle, + &gEdkIIUsbEthProtocolGuid, + (VOID **)&UsbEthProtocol, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (UsbEthProtocol); + + Status =3D gBS->UninstallProtocolInterface ( + ControllerHandle, + &gEdkIIUsbEthProtocolGuid, + UsbEthProtocol + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + FreePool (UsbEthDriver->Config); + FreePool (UsbEthDriver->BulkBuffer); + FreePool (UsbEthDriver); + return Status; +} + +/** + Entrypoint of NCM Driver. + + This function is the entrypoint of NCM Driver. It installs Driver Bindin= g + Protocols together with Component Name Protocols. + + @param[in] ImageHandle The firmware allocated handle for the EFI = image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + +**/ +EFI_STATUS +EFIAPI +UsbNcmEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + gUsbNcmDriverBinding.DriverBindingHandle =3D ImageHandle; + gUsbNcmDriverBinding.ImageHandle =3D ImageHandle; + + return gBS->InstallMultipleProtocolInterfaces ( + &gUsbNcmDriverBinding.DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, + &gUsbNcmDriverBinding, + &gEfiComponentName2ProtocolGuid, + &gUsbNcmComponentName2, + NULL + ); +} diff --git a/MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbCdcNcm.h b/MdeMod= ulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbCdcNcm.h new file mode 100644 index 0000000000..76f0452f57 --- /dev/null +++ b/MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbCdcNcm.h @@ -0,0 +1,245 @@ +/** @file + Header file for USB Network Control Model driver + + Copyright (c) 2023, American Megatrends International LLC. All rights re= served.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _USB_CDC_NCM_H_ +#define _USB_CDC_NCM_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + UINTN Signature; + EDKII_USB_ETHERNET_PROTOCOL UsbEth; + EFI_HANDLE UsbCdcDataHandle; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_CONFIG_DESCRIPTOR *Config; + UINT8 NumOfInterface; + UINT8 BulkInEndpoint; + UINT8 BulkOutEndpoint; + UINT8 InterruptEndpoint; + EFI_MAC_ADDRESS MacAddress; + UINT16 BulkOutSequence; + UINT8 *BulkBuffer; + UINT8 TotalDatagram; + UINT8 NowDatagram; +} USB_ETHERNET_DRIVER; + +#define USB_NCM_DRIVER_VERSION 1 +#define USB_ETHERNET_BULK_TIMEOUT 1 +#define USB_ETHERNET_TRANSFER_TIMEOUT 200 +#define USB_NCM_MAX_NTB_SIZE 0xFFFF +#define USB_ETHERNET_FRAME_SIZE 0x5F2 // MAX ethernet frame size + +// Defined in USB NCM 1.0 spec., section 3.2 and 3.3 +#define USB_NCM_NTH_SIGN_16 0x484D434E +#define USB_NCM_NDP_SIGN_16 0x304D434E +#define USB_NCM_NDP_SIGN_16_CRC 0x314D434E +#define USB_NCM_NTH_LENGTH 0x000C +#define USB_NCM_NDP_LENGTH 0x0010// at least 16 + +// USB NCM Transfer header structure - UINT16 +typedef struct { + UINT32 Signature; + UINT16 HeaderLength; + UINT16 Sequence; + UINT16 BlockLength; + UINT16 NdpIndex; +} USB_NCM_TRANSFER_HEADER_16; + +// USB NCM Datagram pointer structure - UINT16 +typedef struct { + UINT32 Signature; + UINT16 Length; + UINT16 NextNdpIndex; +} USB_NCM_DATAGRAM_POINTER_16; + +// USB NCM Datagram structure +typedef struct { + UINT16 DatagramIndex; + UINT16 DatagramLength; +} USB_NCM_DATA_GRAM; + +#define USB_ETHERNET_SIGNATURE SIGNATURE_32('u', 'e', 't', 'h') +#define USB_ETHERNET_DEV_FROM_THIS(a) CR (a, USB_ETHERNET_DRIVER, UsbEth,= USB_ETHERNET_SIGNATURE) + +typedef struct { + UINT16 Src; + UINT16 Dst; +} BIT_MAP; + +extern EFI_COMPONENT_NAME2_PROTOCOL gUsbNcmComponentName2; + +EFI_STATUS +EFIAPI +UsbNcmDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +UsbNcmDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +UsbNcmDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +EFI_STATUS +LoadAllDescriptor ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc + ); + +BOOLEAN +NextDescriptor ( + IN EFI_USB_CONFIG_DESCRIPTOR *Desc, + IN OUT UINTN *Offset + ); + +EFI_STATUS +GetFunctionalDescriptor ( + IN EFI_USB_CONFIG_DESCRIPTOR *Config, + IN UINT8 FunDescriptorType, + OUT VOID *DataBuffer + ); + +VOID +GetEndpoint ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN OUT USB_ETHERNET_DRIVER *UsbEthDriver + ); + +EFI_STATUS +EFIAPI +UsbEthNcmReceive ( + IN PXE_CDB *Cdb, + IN EDKII_USB_ETHERNET_PROTOCOL *This, + IN OUT VOID *Packet, + IN OUT UINTN *PacketLength + ); + +EFI_STATUS +EFIAPI +UsbEthNcmTransmit ( + IN PXE_CDB *Cdb, + IN EDKII_USB_ETHERNET_PROTOCOL *This, + IN VOID *Packet, + IN OUT UINTN *PacketLength + ); + +EFI_STATUS +EFIAPI +UsbEthNcmInterrupt ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + IN BOOLEAN IsNewTransfer, + IN UINTN PollingInterval, + IN EFI_USB_DEVICE_REQUEST *Request + ); + +EFI_STATUS +EFIAPI +InterruptCallback ( + IN VOID *Data, + IN UINTN DataLength, + IN VOID *Context, + IN UINT32 Status + ); + +EFI_STATUS +EFIAPI +GetUsbEthMacAddress ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + OUT EFI_MAC_ADDRESS *MacAddress + ); + +EFI_STATUS +EFIAPI +UsbEthNcmBulkSize ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + OUT UINTN *BulkSize + ); + +EFI_STATUS +EFIAPI +GetUsbHeaderFunDescriptor ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor + ); + +EFI_STATUS +EFIAPI +GetUsbUnionFunDescriptor ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor + ); + +EFI_STATUS +EFIAPI +GetUsbEthFunDescriptor ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor + ); + +EFI_STATUS +EFIAPI +SetUsbEthMcastFilter ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + IN UINT16 Value, + IN VOID *McastAddr + ); + +EFI_STATUS +EFIAPI +SetUsbEthPowerFilter ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + IN UINT16 Value, + IN UINT16 Length, + IN VOID *PatternFilter + ); + +EFI_STATUS +EFIAPI +GetUsbEthPowerFilter ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + IN UINT16 Value, + OUT BOOLEAN *PatternActive + ); + +EFI_STATUS +EFIAPI +SetUsbEthPacketFilter ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + IN UINT16 Value + ); + +EFI_STATUS +EFIAPI +GetUsbEthStatistic ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + IN UINT16 FeatureSelector, + OUT VOID *Statistic + ); + +#endif diff --git a/MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbCdcNcm.inf b/MdeM= odulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbCdcNcm.inf new file mode 100644 index 0000000000..d98dd1969f --- /dev/null +++ b/MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbCdcNcm.inf @@ -0,0 +1,42 @@ +## @file +# This is Usb Cdc Ncm driver for DXE phase. +# +# Copyright (c) 2023, American Megatrends International LLC. All rights re= served.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D UsbCdcNcm + FILE_GUID =3D 52230d31-6c11-4442-b262-bec6bfe84efa + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D UsbNcmEntry + +[Sources] + UsbCdcNcm.c + UsbCdcNcm.h + UsbNcmFunction.c + ComponentName.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiBootServicesTableLib + UefiLib + DebugLib + UefiUsbLib + MemoryAllocationLib + BaseMemoryLib + +[Protocols] + gEfiUsbIoProtocolGuid + gEfiDevicePathProtocolGuid + gEfiDriverBindingProtocolGuid + gEdkIIUsbEthProtocolGuid + +[Depex] + TRUE diff --git a/MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbNcmFunction.c b/M= deModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbNcmFunction.c new file mode 100644 index 0000000000..d5975b7942 --- /dev/null +++ b/MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbNcmFunction.c @@ -0,0 +1,966 @@ +/** @file + This file contains code for USB Ethernet descriptor + and specific requests implement. + + Copyright (c) 2023, American Megatrends International LLC. All rights re= served.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "UsbCdcNcm.h" + +/** + Load All of device descriptor. + + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL i= nstance. + @param[out] ConfigDesc A pointer to the configuration descrip= tor. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_OUT_OF_RESOURCES The request could not be completed because= the + buffer specified by DescriptorLength and D= escriptor + is not large enough to hold the result of = the request. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. = The transfer + status is returned in Status. + +**/ +EFI_STATUS +LoadAllDescriptor ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc + ) +{ + EFI_STATUS Status; + UINT32 TransStatus; + EFI_USB_CONFIG_DESCRIPTOR Tmp; + + Status =3D UsbIo->UsbGetConfigDescriptor (UsbIo, &Tmp); + ASSERT_EFI_ERROR (Status); + + Status =3D gBS->AllocatePool (EfiBootServicesData, Tmp.TotalLength, (VOI= D **)ConfigDesc); + ASSERT_EFI_ERROR (Status); + + Status =3D UsbGetDescriptor ( + UsbIo, + USB_DESC_TYPE_CONFIG << 8 | (Tmp.ConfigurationValue - 1), = // zero based + 0, + Tmp.TotalLength, + *ConfigDesc, + &TransStatus + ); + return Status; +} + +/** + Returns pointer to the next descriptor for the pack of USB descriptors + located in continues memory segment + + @param[in] Desc A pointer to the CONFIG_DESCRIPTOR instance. + @param[in, out] Offset A pointer to the sum of descriptor length. + + @retval TRUE The request executed successfully. + @retval FALSE No next descriptor. + +**/ +BOOLEAN +NextDescriptor ( + IN EFI_USB_CONFIG_DESCRIPTOR *Desc, + IN OUT UINTN *Offset + ) +{ + if ((Desc =3D=3D NULL) || (*Offset >=3D Desc->TotalLength)) { + return FALSE; + } + + if (((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))->Length =3D=3D= 0) { + return FALSE; + } + + *Offset +=3D ((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))->Leng= th; + if ( *Offset >=3D Desc->TotalLength ) { + return FALSE; + } + + return TRUE; +} + +/** + Read Function descriptor + + @param[in] Config A pointer to all of configuration. + @param[in] FunDescriptorType USB CDC class descriptor SubType. + @param[out] DataBuffer A pointer to the Data of corresponding to= device capability. + + @retval EFI_SUCCESS The device capability descriptor was retrieve= d + successfully. + @retval EFI_UNSUPPORTED No supported. + @retval EFI_NOT_FOUND The device capability descriptor was not foun= d. + +**/ +EFI_STATUS +GetFunctionalDescriptor ( + IN EFI_USB_CONFIG_DESCRIPTOR *Config, + IN UINT8 FunDescriptorType, + OUT VOID *DataBuffer + ) +{ + EFI_STATUS Status; + UINTN Offset; + EFI_USB_INTERFACE_DESCRIPTOR *Interface; + + Status =3D EFI_NOT_FOUND; + + for (Offset =3D 0; NextDescriptor (Config, &Offset);) { + Interface =3D (EFI_USB_INTERFACE_DESCRIPTOR *)((UINT8 *)Config + Offse= t); + if (Interface->DescriptorType =3D=3D CS_INTERFACE) { + if (((USB_HEADER_FUN_DESCRIPTOR *)Interface)->DescriptorSubtype =3D= =3D FunDescriptorType) { + switch (FunDescriptorType) { + case HEADER_FUN_DESCRIPTOR: + CopyMem ( + DataBuffer, + (USB_HEADER_FUN_DESCRIPTOR *)Interface, + sizeof (USB_HEADER_FUN_DESCRIPTOR) + ); + return EFI_SUCCESS; + case UNION_FUN_DESCRIPTOR: + CopyMem ( + DataBuffer, + (USB_UNION_FUN_DESCRIPTOR *)Interface, + ((USB_UNION_FUN_DESCRIPTOR *)Interface)->FunctionLength + ); + return EFI_SUCCESS; + case ETHERNET_FUN_DESCRIPTOR: + CopyMem ( + DataBuffer, + (USB_ETHERNET_FUN_DESCRIPTOR *)Interface, + sizeof (USB_ETHERNET_FUN_DESCRIPTOR) + ); + return EFI_SUCCESS; + default: + Status =3D EFI_UNSUPPORTED; + break; + } + } + } + } + + return Status; +} + +/** + Get USB Ethernet IO endpoint and USB CDC data IO endpoint. + + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL insta= nce. + @param[in, out] UsbEthDriver A pointer to the USB_ETHERNET_DRIVER insta= nce. + +**/ +VOID +GetEndpoint ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN OUT USB_ETHERNET_DRIVER *UsbEthDriver + ) +{ + EFI_STATUS Status; + UINT8 Index; + UINT32 Result; + EFI_USB_INTERFACE_DESCRIPTOR Interface; + EFI_USB_ENDPOINT_DESCRIPTOR Endpoint; + + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); + ASSERT_EFI_ERROR (Status); + + if (Interface.NumEndpoints =3D=3D 0) { + Status =3D UsbSetInterface (UsbIo, Interface.InterfaceNumber, 1, &Resu= lt); + ASSERT_EFI_ERROR (Status); + + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); + ASSERT_EFI_ERROR (Status); + } + + for (Index =3D 0; Index < Interface.NumEndpoints; Index++) { + Status =3D UsbIo->UsbGetEndpointDescriptor (UsbIo, Index, &Endpoint); + ASSERT_EFI_ERROR (Status); + + switch ((Endpoint.Attributes & (BIT0 | BIT1))) { + case USB_ENDPOINT_BULK: + if (Endpoint.EndpointAddress & BIT7) { + UsbEthDriver->BulkInEndpoint =3D Endpoint.EndpointAddress; + } else { + UsbEthDriver->BulkOutEndpoint =3D Endpoint.EndpointAddress; + } + + break; + case USB_ENDPOINT_INTERRUPT: + UsbEthDriver->InterruptEndpoint =3D Endpoint.EndpointAddress; + break; + } + } +} + +/** + This function is used to manage a USB device with the bulk transfer pipe= . The endpoint is Bulk in. + + @param[in] Cdb A pointer to the command descriptor block. + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROTOC= OL instance. + @param[in, out] Packet A pointer to the buffer of data that will = be transmitted to USB + device or received from USB device. + @param[in, out] PacketLength A pointer to the PacketLength. + + @retval EFI_SUCCESS The bulk transfer has been successfully ex= ecuted. + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status i= s returned in status. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due to = a lack of resources. + @retval EFI_TIMEOUT The control transfer fails due to timeout. + +**/ +EFI_STATUS +EFIAPI +UsbEthNcmReceive ( + IN PXE_CDB *Cdb, + IN EDKII_USB_ETHERNET_PROTOCOL *This, + IN OUT VOID *Packet, + IN OUT UINTN *PacketLength + ) +{ + EFI_STATUS Status; + USB_ETHERNET_DRIVER *UsbEthDriver; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT32 TransStatus; + UINT8 Index; + UINTN BulkDataLength; + UINTN TotalLength; + USB_NCM_TRANSFER_HEADER_16 *Nth; + USB_NCM_DATAGRAM_POINTER_16 *Ndp; + USB_NCM_DATA_GRAM *Datagram; + + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); + TotalLength =3D 0; + + if (UsbEthDriver->TotalDatagram =3D=3D UsbEthDriver->NowDatagram) { + Status =3D gBS->HandleProtocol ( + UsbEthDriver->UsbCdcDataHandle, + &gEfiUsbIoProtocolGuid, + (VOID **)&UsbIo + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (UsbEthDriver->BulkInEndpoint =3D=3D 0) { + GetEndpoint (UsbIo, UsbEthDriver); + } + + BulkDataLength =3D USB_NCM_MAX_NTB_SIZE; + SetMem (UsbEthDriver->BulkBuffer, BulkDataLength, 0); + UsbEthDriver->NowDatagram =3D 0; + UsbEthDriver->TotalDatagram =3D 0; + + Status =3D UsbIo->UsbBulkTransfer ( + UsbIo, + UsbEthDriver->BulkInEndpoint, + UsbEthDriver->BulkBuffer, + &BulkDataLength, + USB_ETHERNET_BULK_TIMEOUT, + &TransStatus + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Nth =3D (USB_NCM_TRANSFER_HEADER_16 *)UsbEthDr= iver->BulkBuffer; + Ndp =3D (USB_NCM_DATAGRAM_POINTER_16 *)((UINT8= *)UsbEthDriver->BulkBuffer + Nth->NdpIndex); + Datagram =3D (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + s= izeof (USB_NCM_DATAGRAM_POINTER_16)); + UsbEthDriver->TotalDatagram =3D (UINT8)((Ndp->Length - 8) / 4 - 1); + + for (Index =3D 0; Index < UsbEthDriver->TotalDatagram; Index++) { + TotalLength +=3D Datagram->DatagramLength; + Datagram =3D (USB_NCM_DATA_GRAM *)((UINT8 *)Datagram + sizeof (U= SB_NCM_DATA_GRAM)); + } + + if (TotalLength < USB_ETHERNET_FRAME_SIZE) { + Datagram =3D (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + sizeof (USB_NCM_DA= TAGRAM_POINTER_16)); + + TotalLength =3D 0; + for (Index =3D 0; Index < UsbEthDriver->TotalDatagram; Index++) { + CopyMem ((UINT8 *)Packet + TotalLength, (UINT8 *)UsbEthDriver->Bul= kBuffer + Datagram->DatagramIndex, Datagram->DatagramLength); + TotalLength +=3D Datagram->DatagramLength; + Datagram =3D (USB_NCM_DATA_GRAM *)((UINT8 *)Datagram + sizeof = (USB_NCM_DATA_GRAM)); + } + + *PacketLength =3D TotalLength; + UsbEthDriver->NowDatagram =3D UsbEthDriver->TotalDatagram; + } else { + UsbEthDriver->NowDatagram++; + + Datagram =3D (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + sizeof (USB_NCM_DA= TAGRAM_POINTER_16)); + CopyMem (Packet, (UINT8 *)UsbEthDriver->BulkBuffer + Datagram->Datag= ramIndex, Datagram->DatagramLength); + *PacketLength =3D Datagram->DatagramLength; + } + + return Status; + } else { + UsbEthDriver->NowDatagram++; + + Nth =3D (USB_NCM_TRANSFER_HEADER_16 *)UsbEthDriver->BulkBuffer; + Ndp =3D (USB_NCM_DATAGRAM_POINTER_16 *)((UINT8 *)UsbEthDriver->Bu= lkBuffer + Nth->NdpIndex); + Datagram =3D (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + sizeof (USB_NCM_DATA= GRAM_POINTER_16)); + Datagram =3D (USB_NCM_DATA_GRAM *)((UINT8 *)Datagram + sizeof (USB_NCM= _DATA_GRAM) * (UsbEthDriver->NowDatagram - 1)); + + CopyMem (Packet, (UINT8 *)UsbEthDriver->BulkBuffer + Datagram->Datagra= mIndex, Datagram->DatagramLength); + *PacketLength =3D Datagram->DatagramLength; + + return EFI_SUCCESS; + } +} + +/** + This function is used to manage a USB device with the bulk transfer pipe= . The endpoint is Bulk out. + + @param[in] Cdb A pointer to the command descriptor block. + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROTOC= OL instance. + @param[in] Packet A pointer to the buffer of data that will = be transmitted to USB + device or received from USB device. + @param[in, out] PacketLength A pointer to the PacketLength. + + @retval EFI_SUCCESS The bulk transfer has been successfully ex= ecuted. + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status i= s returned in status. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due to = a lack of resources. + @retval EFI_TIMEOUT The control transfer fails due to timeout. + +**/ +EFI_STATUS +EFIAPI +UsbEthNcmTransmit ( + IN PXE_CDB *Cdb, + IN EDKII_USB_ETHERNET_PROTOCOL *This, + IN VOID *Packet, + IN OUT UINTN *PacketLength + ) +{ + EFI_STATUS Status; + USB_ETHERNET_DRIVER *UsbEthDriver; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT32 TransStatus; + USB_NCM_TRANSFER_HEADER_16 *Nth; + USB_NCM_DATAGRAM_POINTER_16 *Ndp; + USB_NCM_DATA_GRAM *Datagram; + UINT8 *TotalPacket; + UINTN TotalLength; + + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); + + Status =3D gBS->HandleProtocol ( + UsbEthDriver->UsbCdcDataHandle, + &gEfiUsbIoProtocolGuid, + (VOID **)&UsbIo + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (UsbEthDriver->BulkOutEndpoint =3D=3D 0) { + GetEndpoint (UsbIo, UsbEthDriver); + } + + TotalLength =3D (UINTN)(USB_NCM_NTH_LENGTH + USB_NCM_NDP_LENGTH + (*Pack= etLength)); + + Status =3D gBS->AllocatePool (EfiBootServicesData, TotalLength, (VOID **= )&TotalPacket); + if (EFI_ERROR (Status)) { + return Status; + } + + SetMem (TotalPacket, TotalLength, 0); + + Nth =3D (USB_NCM_TRANSFER_HEADER_16 *)TotalPacket; + Nth->Signature =3D USB_NCM_NTH_SIGN_16; + Nth->HeaderLength =3D USB_NCM_NTH_LENGTH; + Nth->Sequence =3D UsbEthDriver->BulkOutSequence++; + Nth->BlockLength =3D (UINT16)TotalLength; + Nth->NdpIndex =3D Nth->HeaderLength; + + Ndp =3D (USB_NCM_DATAGRAM_POINTER_16 *)((UINT8 *)TotalPack= et + Nth->NdpIndex); + Ndp->Signature =3D USB_NCM_NDP_SIGN_16; + Ndp->Length =3D USB_NCM_NDP_LENGTH; + Ndp->NextNdpIndex =3D 0x00; + + Datagram =3D (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + sizeof= (USB_NCM_DATAGRAM_POINTER_16)); + Datagram->DatagramIndex =3D Nth->HeaderLength + Ndp->Length; + Datagram->DatagramLength =3D (UINT16)*PacketLength; + + CopyMem (TotalPacket + Datagram->DatagramIndex, Packet, *PacketLength); + + *PacketLength =3D TotalLength; + + Status =3D UsbIo->UsbBulkTransfer ( + UsbIo, + UsbEthDriver->BulkOutEndpoint, + TotalPacket, + PacketLength, + USB_ETHERNET_BULK_TIMEOUT, + &TransStatus + ); + FreePool (TotalPacket); + return Status; +} + +/** + Async USB transfer callback routine. + + @param[in] Data Data received or sent via the USB Asynchrono= us Transfer, if the + transfer completed successfully. + @param[in] DataLength The length of Data received or sent via the = Asynchronous + Transfer, if transfer successfully completes= . + @param[in] Context Data passed from UsbAsyncInterruptTransfer()= request. + @param[in] Status Indicates the result of the asynchronous tra= nsfer. + + @retval EFI_SUCCESS The asynchronous USB transfer request has = been successfully executed. + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request fail= ed. + +**/ +EFI_STATUS +EFIAPI +InterruptCallback ( + IN VOID *Data, + IN UINTN DataLength, + IN VOID *Context, + IN UINT32 Status + ) +{ + if ((Data =3D=3D NULL) || (Context =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (((EFI_USB_DEVICE_REQUEST *)Data)->Request =3D=3D USB_CDC_NETWORK_CON= NECTION) { + CopyMem ( + (EFI_USB_DEVICE_REQUEST *)Context, + (EFI_USB_DEVICE_REQUEST *)Data, + sizeof (EFI_USB_DEVICE_REQUEST) + ); + } + + return EFI_SUCCESS; +} + +/** + This function is used to manage a USB device with an interrupt transfer = pipe. + + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROTOC= OL instance. + @param[in] IsNewTransfer If TRUE, a new transfer will be submitted = to USB controller. If + FALSE, the interrupt transfer is deleted f= rom the device's interrupt + transfer queue. + @param[in] PollingInterval Indicates the periodic rate, in millisecon= ds, that the transfer is to be + executed.This parameter is required when I= sNewTransfer is TRUE. The + value must be between 1 to 255, otherwise = EFI_INVALID_PARAMETER is returned. + The units are in milliseconds. + @param[in] Request A pointer to the EFI_USB_DEVICE_REQUEST da= ta. + + @retval EFI_SUCCESS The asynchronous USB transfer request tran= sfer has been successfully executed. + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request fail= ed. + +**/ +EFI_STATUS +EFIAPI +UsbEthNcmInterrupt ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + IN BOOLEAN IsNewTransfer, + IN UINTN PollingInterval, + IN EFI_USB_DEVICE_REQUEST *Request + ) +{ + EFI_STATUS Status; + USB_ETHERNET_DRIVER *UsbEthDriver; + UINTN DataLength; + + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); + DataLength =3D 0; + + if (IsNewTransfer =3D=3D TRUE) { + DataLength =3D sizeof (EFI_USB_DEVICE_REQUEST) + sizeof (USB_CONNECT_S= PEED_CHANGE); + Status =3D UsbEthDriver->UsbIo->UsbAsyncInterruptTransfer ( + UsbEthDriver->UsbIo, + UsbEthDriver->InterruptEndpoint, + IsNewTransfer, + PollingInterval, + DataLength, + (EFI_ASYNC_USB_TRANSFER_CALLBACK)I= nterruptCallback, + Request + ); + } else { + Status =3D UsbEthDriver->UsbIo->UsbAsyncInterruptTransfer ( + UsbEthDriver->UsbIo, + UsbEthDriver->InterruptEndpoint, + IsNewTransfer, + 0, + 0, + NULL, + NULL + ); + } + + return Status; +} + +/** + Retrieves the USB Ethernet Mac Address. + + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROTOCOL i= nstance. + @param[out] MacAddress A pointer to the caller allocated USB Ethernet= Mac Address. + + @retval EFI_SUCCESS The USB Header Functional descriptor was r= etrieved successfully. + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. + @retval EFI_NOT_FOUND The USB Header Functional descriptor was n= ot found. + +**/ +EFI_STATUS +EFIAPI +GetUsbEthMacAddress ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + OUT EFI_MAC_ADDRESS *MacAddress + ) +{ + EFI_STATUS Status; + USB_ETHERNET_DRIVER *UsbEthDriver; + USB_ETHERNET_FUN_DESCRIPTOR UsbEthDescriptor; + CHAR16 *Data; + CHAR16 *DataPtr; + CHAR16 TmpStr[1]; + UINT8 Index; + UINT8 Hi; + UINT8 Low; + + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); + + Status =3D This->UsbEthFunDescriptor (This, &UsbEthDescriptor); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a:UsbEthFunDescriptor status =3D %r\n", __func_= _, Status)); + return Status; + } + + Status =3D UsbEthDriver->UsbIo->UsbGetStringDescriptor ( + UsbEthDriver->UsbIo, + 0x409, // English= -US Language ID + UsbEthDescriptor.MacAddress, + &Data + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a:UsbGetStringDescriptor status =3D %r\n", __fu= nc__, Status)); + return Status; + } + + DataPtr =3D Data; + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { + CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); + DataPtr++; + Hi =3D (UINT8)StrHexToUintn (TmpStr); + CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); + DataPtr++; + Low =3D (UINT8)StrHexToUintn (TmpStr); + MacAddress->Addr[Index] =3D (Hi << 4) | Low; + } + + return Status; +} + +/** + Get the USB NCM max NTB size. + + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROTOCOL i= nstance. + @param[out] BulkSize A pointer to the Bulk transfer data size. + + @retval EFI_SUCCESS Get the USB NCM max NTB size successfully. + +**/ +EFI_STATUS +EFIAPI +UsbEthNcmBulkSize ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + OUT UINTN *BulkSize + ) +{ + *BulkSize =3D USB_NCM_MAX_NTB_SIZE; + return EFI_SUCCESS; +} + +/** + Retrieves the USB Header functional Descriptor. + + @param[in] This A pointer to the EDKII_USB_ETHERNET_P= ROTOCOL instance. + @param[out] UsbHeaderFunDescriptor A pointer to the caller allocated USB= Header Functional Descriptor. + + @retval EFI_SUCCESS The USB Header Functional descriptor was r= etrieved successfully. + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. + @retval EFI_NOT_FOUND The USB Header Functional descriptor was n= ot found. + +**/ +EFI_STATUS +EFIAPI +GetUsbHeaderFunDescriptor ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor + ) +{ + EFI_STATUS Status; + USB_ETHERNET_DRIVER *UsbEthDriver; + + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); + + if (UsbHeaderFunDescriptor =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + Status =3D GetFunctionalDescriptor (UsbEthDriver->Config, HEADER_FUN_DES= CRIPTOR, UsbHeaderFunDescriptor); + return Status; +} + +/** + Retrieves the USB Union functional Descriptor. + + @param[in] This A pointer to the EDKII_USB_ETHERNET_P= ROTOCOL instance. + @param[out] UsbUnionFunDescriptor A pointer to the caller allocated USB= Union Functional Descriptor. + + @retval EFI_SUCCESS The USB Union Functional descriptor was re= trieved successfully. + @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL. + @retval EFI_NOT_FOUND The USB Union Functional descriptor was no= t found. + +**/ +EFI_STATUS +EFIAPI +GetUsbUnionFunDescriptor ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor + ) +{ + EFI_STATUS Status; + USB_ETHERNET_DRIVER *UsbEthDriver; + + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); + + if (UsbUnionFunDescriptor =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + Status =3D GetFunctionalDescriptor (UsbEthDriver->Config, UNION_FUN_DESC= RIPTOR, UsbUnionFunDescriptor); + return Status; +} + +/** + Retrieves the USB Ethernet functional Descriptor. + + This function get the Mac Address, Ethernet statistics, maximum segment = size, + number of multicast filters, and number of pattern filters from Ethernet + functional Descriptor. + + @param[in] This A pointer to the EDKII_USB_ETHERNET_P= ROTOCOL instance. + @param[out] UsbEthFunDescriptor A pointer to the caller allocated USB= Ethernet Functional Descriptor. + + @retval EFI_SUCCESS The USB Ethernet Functional descriptor was= retrieved successfully. + @retval EFI_INVALID_PARAMETER UsbEthFunDescriptor is NULL. + @retval EFI_NOT_FOUND The USB Ethernet Functional descriptor was= not found. + +**/ +EFI_STATUS +EFIAPI +GetUsbEthFunDescriptor ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor + ) +{ + EFI_STATUS Status; + USB_ETHERNET_DRIVER *UsbEthDriver; + + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); + + if (UsbEthFunDescriptor =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + Status =3D GetFunctionalDescriptor (UsbEthDriver->Config, ETHERNET_FUN_D= ESCRIPTOR, UsbEthFunDescriptor); + return Status; +} + +/** + This request sets the Ethernet device multicast filters as specified in = the + sequential list of 48 bit Ethernet multicast addresses. + + @param[in] This A pointer to the EDKII_USB_ETHERNET_P= ROTOCOL instance. + @param[in] Value Number of filters. + @param[in] McastAddr A pointer to the value of the multica= st addresses. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value= . + @retval EFI_UNSUPPORTED Not supported. + +**/ +EFI_STATUS +EFIAPI +SetUsbEthMcastFilter ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + IN UINT16 Value, + IN VOID *McastAddr + ) +{ + EFI_STATUS Status; + EFI_USB_DEVICE_REQUEST Request; + UINT32 TransStatus; + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; + USB_ETHERNET_DRIVER *UsbEthDriver; + + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); + + Status =3D This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); + if (EFI_ERROR (Status)) { + return Status; + } + + if ((UsbEthFunDescriptor.NumberMcFilters << 1) =3D=3D 0) { + return EFI_UNSUPPORTED; + } + + Request.RequestType =3D USB_ETHERNET_SET_REQ_TYPE; + Request.Request =3D SET_ETH_MULTICAST_FILTERS_REQ; + Request.Value =3D Value; + Request.Index =3D UsbEthDriver->NumOfInterface; + Request.Length =3D Value * 6; + + return UsbEthDriver->UsbIo->UsbControlTransfer ( + UsbEthDriver->UsbIo, + &Request, + EfiUsbDataOut, + USB_ETHERNET_TRANSFER_TIMEOUT, + McastAddr, + Request.Length, + &TransStatus + ); +} + +/** + This request sets up the specified Ethernet power management pattern fil= ter as + described in the data structure. + + @param[in] This A pointer to the EDKII_USB_ETHERNET_PR= OTOCOL instance. + @param[in] Value Number of filters. + @param[in] Length Size of the power management pattern f= ilter data. + @param[in] PatternFilter A pointer to the power management patt= ern filter structure. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value= . + @retval EFI_UNSUPPORTED Not supported. + +**/ +EFI_STATUS +EFIAPI +SetUsbEthPowerFilter ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + IN UINT16 Value, + IN UINT16 Length, + IN VOID *PatternFilter + ) +{ + EFI_USB_DEVICE_REQUEST Request; + UINT32 TransStatus; + USB_ETHERNET_DRIVER *UsbEthDriver; + + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); + + Request.RequestType =3D USB_ETHERNET_SET_REQ_TYPE; + Request.Request =3D SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; + Request.Value =3D Value; + Request.Index =3D UsbEthDriver->NumOfInterface; + Request.Length =3D Length; + + return UsbEthDriver->UsbIo->UsbControlTransfer ( + UsbEthDriver->UsbIo, + &Request, + EfiUsbDataOut, + USB_ETHERNET_TRANSFER_TIMEOUT, + PatternFilter, + Length, + &TransStatus + ); +} + +/** + This request retrieves the status of the specified Ethernet power manage= ment + pattern filter from the device. + + @param[in] This A pointer to the EDKII_USB_ETHERNET_P= ROTOCOL instance. + @param[in] Value The filter number. + @param[out] PatternActive A pointer to the pattern active boole= an. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value= . + @retval EFI_UNSUPPORTED Not supported. + +**/ +EFI_STATUS +EFIAPI +GetUsbEthPowerFilter ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + IN UINT16 Value, + OUT BOOLEAN *PatternActive + ) +{ + EFI_USB_DEVICE_REQUEST Request; + UINT32 TransStatus; + USB_ETHERNET_DRIVER *UsbEthDriver; + + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); + + Request.RequestType =3D USB_ETHERNET_GET_REQ_TYPE; + Request.Request =3D GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; + Request.Value =3D Value; + Request.Index =3D UsbEthDriver->NumOfInterface; + Request.Length =3D USB_ETH_POWER_FILTER_LENGTH; + + return UsbEthDriver->UsbIo->UsbControlTransfer ( + UsbEthDriver->UsbIo, + &Request, + EfiUsbDataIn, + USB_ETHERNET_TRANSFER_TIMEOUT, + PatternActive, + USB_ETH_POWER_FILTER_LENGTH, + &TransStatus + ); +} + +BIT_MAP gTable[] =3D { + { PXE_OPFLAGS_RECEIVE_FILTER_UNICAST, USB_ETH_PACKET_TYPE_DIR= ECTED }, + { PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST, USB_ETH_PACKET_TYPE_BRO= ADCAST }, + { PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST, USB_ETH_PACKET_TYPE_MUL= TICAST }, + { PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS, USB_ETH_PACKET_TYPE_PRO= MISCUOUS }, + { PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST, USB_ETH_PACKET_TYPE_ALL= _MULTICAST }, +}; + +/** + Convert value between PXE receive filter and USB ETH packet filter. + + @param[in] Value PXE filter data. + @param[out] CdcFilter A pointer to the Ethernet Packet Filter Bitmap va= lue converted by PXE_OPFLAGS. + +**/ +VOID +ConvertFilter ( + IN UINT16 Value, + OUT UINT16 *CdcFilter + ) +{ + UINT32 Index; + UINT32 Count; + + Count =3D sizeof (gTable)/sizeof (gTable[0]); + + for (Index =3D 0; (gTable[Index].Src !=3D 0) && (Index < Count); Index++= ) { + if (gTable[Index].Src & Value) { + *CdcFilter |=3D gTable[Index].Dst; + } + } +} + +/** + This request is used to configure device Ethernet packet filter settings= . + + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROTOC= OL instance. + @param[in] Value Packet Filter Bitmap. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value= . + @retval EFI_UNSUPPORTED Not supported. + +**/ +EFI_STATUS +EFIAPI +SetUsbEthPacketFilter ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + IN UINT16 Value + ) +{ + EFI_USB_DEVICE_REQUEST Request; + UINT32 TransStatus; + USB_ETHERNET_DRIVER *UsbEthDriver; + UINT16 CommandFilter; + + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); + CommandFilter =3D 0; + + ConvertFilter (Value, &CommandFilter); + + Request.RequestType =3D USB_ETHERNET_SET_REQ_TYPE; + Request.Request =3D SET_ETH_PACKET_FILTER_REQ; + Request.Value =3D CommandFilter; + Request.Index =3D UsbEthDriver->NumOfInterface; + Request.Length =3D USB_ETH_PACKET_FILTER_LENGTH; + + return UsbEthDriver->UsbIo->UsbControlTransfer ( + UsbEthDriver->UsbIo, + &Request, + EfiUsbNoData, + USB_ETHERNET_TRANSFER_TIMEOUT, + NULL, + USB_ETH_PACKET_FILTER_LENGTH, + &TransStatus + ); +} + +/** + This request is used to retrieve a statistic based on the feature select= or. + + @param[in] This A pointer to the EDKII_USB_ETHERNET_PR= OTOCOL instance. + @param[in] FeatureSelector Value of the feature selector. + @param[out] Statistic A pointer to the 32 bit unsigned integ= er. + + @retval EFI_SUCCESS The request executed successfully. + @retval EFI_TIMEOUT A timeout occurred executing the request. + @retval EFI_DEVICE_ERROR The request failed due to a device error. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value= . + @retval EFI_UNSUPPORTED Not supported. + +**/ +EFI_STATUS +EFIAPI +GetUsbEthStatistic ( + IN EDKII_USB_ETHERNET_PROTOCOL *This, + IN UINT16 FeatureSelector, + OUT VOID *Statistic + ) +{ + EFI_STATUS Status; + EFI_USB_DEVICE_REQUEST Request; + UINT32 TransStatus; + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; + USB_ETHERNET_DRIVER *UsbEthDriver; + + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); + + Status =3D This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); + if (EFI_ERROR (Status)) { + return Status; + } + + if (UsbEthFunDescriptor.EthernetStatistics =3D=3D 0) { + return EFI_UNSUPPORTED; + } + + Request.RequestType =3D USB_ETHERNET_GET_REQ_TYPE; + Request.Request =3D GET_ETH_STATISTIC_REQ; + Request.Value =3D FeatureSelector; + Request.Index =3D UsbEthDriver->NumOfInterface; + Request.Length =3D USB_ETH_STATISTIC; + + return UsbEthDriver->UsbIo->UsbControlTransfer ( + UsbEthDriver->UsbIo, + &Request, + EfiUsbDataIn, + USB_ETHERNET_TRANSFER_TIMEOUT, + Statistic, + USB_ETH_STATISTIC, + &TransStatus + ); +} -- 2.35.1.windows.2 -The information contained in this message may be confidential and propriet= ary to American Megatrends (AMI). This communication is intended to be read= only by the individual or entity to whom it is addressed or by their desig= nee. If the reader of this message is not the intended recipient, you are o= n notice that any distribution of this message, in any form, is strictly pr= ohibited. Please promptly notify the sender by reply e-mail or by telephone= at 770-246-8600, and then delete or destroy all copies of the transmission= .