3 Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
10 * Implementation of the FASTBOOT_TRANSPORT_PROTOCOL using the USB_DEVICE_PROTOCOL
13 #include <Protocol/UsbDevice.h>
14 #include <Protocol/AndroidFastbootTransport.h>
15 #include <Protocol/SimpleTextOut.h>
17 #include <Library/BaseLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/MemoryAllocationLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
22 #include <Library/UefiDriverEntryPoint.h>
24 STATIC USB_DEVICE_PROTOCOL
*mUsbDevice
;
26 // Configuration attributes:
27 // bit 7 reserved and must be 1, bit 6 means self-powered.
28 #define CONFIG_DESC_ATTRIBUTES (BIT7 | BIT6)
30 #define MAX_PACKET_SIZE_BULK 512
32 STATIC USB_DEVICE_PROTOCOL
*mUsbDevice
;
33 STATIC EFI_EVENT mReceiveEvent
= NULL
;
34 STATIC LIST_ENTRY mPacketList
;
36 // List type for queued received packets
37 typedef struct _FASTBOOT_USB_PACKET_LIST
{
41 } FASTBOOT_USB_PACKET_LIST
;
44 No string descriptors - all string descriptor members are set to 0
47 STATIC USB_DEVICE_DESCRIPTOR mDeviceDescriptor
= {
48 sizeof (USB_DEVICE_DESCRIPTOR
), // Length
49 USB_DESC_TYPE_DEVICE
, // DescriptorType
55 FixedPcdGet32 (PcdAndroidFastbootUsbVendorId
), // IdVendor
56 FixedPcdGet32 (PcdAndroidFastbootUsbProductId
), // IdProduct
61 1 // NumConfigurations
65 We have one configuration, one interface, and two endpoints (one IN, one OUT)
68 // Lazy (compile-time) way to concatenate descriptors to pass to the USB device
73 USB_CONFIG_DESCRIPTOR ConfigDescriptor
;
74 USB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
75 USB_ENDPOINT_DESCRIPTOR EndpointDescriptor1
;
76 USB_ENDPOINT_DESCRIPTOR EndpointDescriptor2
;
77 } GET_CONFIG_DESCRIPTOR_RESPONSE
;
80 STATIC GET_CONFIG_DESCRIPTOR_RESPONSE mGetConfigDescriptorResponse
= {
81 { // USB_CONFIG_DESCRIPTOR
82 sizeof (USB_CONFIG_DESCRIPTOR
), // Length;
83 USB_DESC_TYPE_CONFIG
, // DescriptorType;
84 sizeof (GET_CONFIG_DESCRIPTOR_RESPONSE
), // TotalLength;
86 1, // ConfigurationValue;
88 CONFIG_DESC_ATTRIBUTES
, // Attributes;
91 { // USB_INTERFACE_DESCRIPTOR
92 sizeof (USB_INTERFACE_DESCRIPTOR
), // Length;
93 USB_DESC_TYPE_INTERFACE
, // DescriptorType;
94 0, // InterfaceNumber;
95 0, // AlternateSetting;
97 0xFF, // InterfaceClass;
98 // Vendor specific interface subclass and protocol codes.
99 // I found these values in the Fastboot code
100 // (in match_fastboot_with_serial in fastboot.c).
101 0x42, // InterfaceSubClass;
102 0x03, // InterfaceProtocol;
105 { // USB_ENDPOINT_DESCRIPTOR (In Endpoint)
106 sizeof (USB_ENDPOINT_DESCRIPTOR
), // Length;
107 USB_DESC_TYPE_ENDPOINT
, // DescriptorType;
108 1 | BIT7
, // EndpointAddress;
110 MAX_PACKET_SIZE_BULK
, // MaxPacketSize;
113 { // STATIC USB_ENDPOINT_DESCRIPTOR (Out Endpoint)
114 sizeof (USB_ENDPOINT_DESCRIPTOR
), // Length;
115 USB_DESC_TYPE_ENDPOINT
, // DescriptorType;
116 1, // EndpointAddress;
118 MAX_PACKET_SIZE_BULK
, // MaxPacketSize;
130 FASTBOOT_USB_PACKET_LIST
*NewEntry
;
132 NewEntry
= AllocatePool (sizeof (*NewEntry
));
133 ASSERT (NewEntry
!= NULL
);
135 NewEntry
->Buffer
= Buffer
;
136 NewEntry
->BufferSize
= Size
;
138 InsertTailList (&mPacketList
, &NewEntry
->Link
);
141 gBS
->SignalEvent (mReceiveEvent
);
148 IN UINT8 EndpointIndex
155 Set up the transport system for use by Fastboot.
156 e.g. For USB this probably means making the device enumerable.
159 FastbootTransportUsbStart (
160 EFI_EVENT ReceiveEvent
163 GET_CONFIG_DESCRIPTOR_RESPONSE
*Responses
;
165 mReceiveEvent
= ReceiveEvent
;
167 mGetConfigDescriptorResponse
.ConfigDescriptor
.TotalLength
= sizeof (GET_CONFIG_DESCRIPTOR_RESPONSE
);
168 Responses
= &mGetConfigDescriptorResponse
;
170 InitializeListHead (&mPacketList
);
172 return mUsbDevice
->Start (&mDeviceDescriptor
, (VOID
**)&Responses
, DataReceived
, DataSent
);
176 Function to be called when all Fastboot transactions are finished, to
177 de-initialise the transport system.
178 e.g. A USB OTG system might want to get out of peripheral mode so it can be
182 FastbootTransportUsbStop (
186 // not yet implemented in USB
191 Send data. This function can be used both for command responses like "OKAY"
192 and for the data phase (the protocol doesn't describe any situation when the
193 latter might be necessary, but does allow it)
196 FastbootTransportUsbSend (
198 IN CONST VOID
*Buffer
,
199 IN EFI_EVENT
*FatalErrorEvent
202 // Current USB protocol is blocking, so ignore FatalErrorEvent
203 return mUsbDevice
->Send (1, BufferSize
, Buffer
);
207 When the event has been Signalled to say data is available from the host,
208 this function is used to get data. In order to handle the case where several
209 packets are received before ReceiveEvent's notify function is called, packets
210 received are queued, and each call to this function returns the next packet in
211 the queue. It should therefore be called in a loop, the exit condition being a
212 return of EFI_NOT_READY.
215 Buffer - The buffer in which to place data
216 BufferSize - The size of Buffer in bytes
218 Return EFI_NOT_READY if there is no data available
221 FastbootTransportUsbReceive (
222 OUT UINTN
*BufferSize
,
226 FASTBOOT_USB_PACKET_LIST
*Entry
;
228 if (IsListEmpty (&mPacketList
)) {
229 return EFI_NOT_READY
;
232 Entry
= (FASTBOOT_USB_PACKET_LIST
*)GetFirstNode (&mPacketList
);
234 *BufferSize
= Entry
->BufferSize
;
235 *Buffer
= Entry
->Buffer
;
237 RemoveEntryList (&Entry
->Link
);
243 STATIC FASTBOOT_TRANSPORT_PROTOCOL mTransportProtocol
= {
244 FastbootTransportUsbStart
,
245 FastbootTransportUsbStop
,
246 FastbootTransportUsbSend
,
247 FastbootTransportUsbReceive
251 FastbootTransportUsbEntryPoint (
252 IN EFI_HANDLE ImageHandle
,
253 IN EFI_SYSTEM_TABLE
*SystemTable
258 // Assume there's only one USB peripheral controller.
259 Status
= gBS
->LocateProtocol (&gUsbDeviceProtocolGuid
, NULL
, (VOID
**)&mUsbDevice
);
260 if (EFI_ERROR (Status
)) {
264 Status
= gBS
->InstallProtocolInterface (
266 &gAndroidFastbootTransportProtocolGuid
,
267 EFI_NATIVE_INTERFACE
,