TianoCore EDK2 master
Loading...
Searching...
No Matches
FastbootTransportUsb.c
Go to the documentation of this file.
1
9/*
10 * Implementation of the FASTBOOT_TRANSPORT_PROTOCOL using the USB_DEVICE_PROTOCOL
11 */
12
13#include <Protocol/UsbDevice.h>
16
17#include <Library/BaseLib.h>
19#include <Library/DebugLib.h>
23
24STATIC USB_DEVICE_PROTOCOL *mUsbDevice;
25
26// Configuration attributes:
27// bit 7 reserved and must be 1, bit 6 means self-powered.
28#define CONFIG_DESC_ATTRIBUTES (BIT7 | BIT6)
29
30#define MAX_PACKET_SIZE_BULK 512
31
32STATIC USB_DEVICE_PROTOCOL *mUsbDevice;
33STATIC EFI_EVENT mReceiveEvent = NULL;
34STATIC LIST_ENTRY mPacketList;
35
36// List type for queued received packets
38 LIST_ENTRY Link;
39 VOID *Buffer;
40 UINTN BufferSize;
42
43/*
44 No string descriptors - all string descriptor members are set to 0
45*/
46
47STATIC USB_DEVICE_DESCRIPTOR mDeviceDescriptor = {
48 sizeof (USB_DEVICE_DESCRIPTOR), // Length
49 USB_DESC_TYPE_DEVICE, // DescriptorType
50 0x0200, // BcdUSB
51 0xFF, // DeviceClass
52 0, // DeviceSubClass
53 0, // DeviceProtocol
54 64, // MaxPacketSize0
55 FixedPcdGet32 (PcdAndroidFastbootUsbVendorId), // IdVendor
56 FixedPcdGet32 (PcdAndroidFastbootUsbProductId), // IdProduct
57 0, // BcdDevice
58 0, // StrManufacturer
59 0, // StrProduct
60 0, // StrSerialNumber
61 1 // NumConfigurations
62};
63
64/*
65 We have one configuration, one interface, and two endpoints (one IN, one OUT)
66*/
67
68// Lazy (compile-time) way to concatenate descriptors to pass to the USB device
69// protocol
70
71#pragma pack(1)
72typedef struct {
73 USB_CONFIG_DESCRIPTOR ConfigDescriptor;
74 USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
75 USB_ENDPOINT_DESCRIPTOR EndpointDescriptor1;
76 USB_ENDPOINT_DESCRIPTOR EndpointDescriptor2;
78#pragma pack()
79
80STATIC 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;
85 1, // NumInterfaces;
86 1, // ConfigurationValue;
87 0, // Configuration;
88 CONFIG_DESC_ATTRIBUTES, // Attributes;
89 0 // MaxPower;
90 },
91 { // USB_INTERFACE_DESCRIPTOR
92 sizeof (USB_INTERFACE_DESCRIPTOR), // Length;
93 USB_DESC_TYPE_INTERFACE, // DescriptorType;
94 0, // InterfaceNumber;
95 0, // AlternateSetting;
96 2, // NumEndpoints;
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;
103 0 // Interface;
104 },
105 { // USB_ENDPOINT_DESCRIPTOR (In Endpoint)
106 sizeof (USB_ENDPOINT_DESCRIPTOR), // Length;
107 USB_DESC_TYPE_ENDPOINT, // DescriptorType;
108 1 | BIT7, // EndpointAddress;
109 0x2, // Attributes;
110 MAX_PACKET_SIZE_BULK, // MaxPacketSize;
111 16 // Interval;
112 },
113 { // STATIC USB_ENDPOINT_DESCRIPTOR (Out Endpoint)
114 sizeof (USB_ENDPOINT_DESCRIPTOR), // Length;
115 USB_DESC_TYPE_ENDPOINT, // DescriptorType;
116 1, // EndpointAddress;
117 0x2, // Attributes;
118 MAX_PACKET_SIZE_BULK, // MaxPacketSize;
119 16 // Interval;
120 }
121};
122
123STATIC
124VOID
125DataReceived (
126 IN UINTN Size,
127 IN VOID *Buffer
128 )
129{
130 FASTBOOT_USB_PACKET_LIST *NewEntry;
131
132 NewEntry = AllocatePool (sizeof (*NewEntry));
133 ASSERT (NewEntry != NULL);
134
135 NewEntry->Buffer = Buffer;
136 NewEntry->BufferSize = Size;
137
138 InsertTailList (&mPacketList, &NewEntry->Link);
139
140 if (mReceiveEvent) {
141 gBS->SignalEvent (mReceiveEvent);
142 }
143}
144
145STATIC
146VOID
147DataSent (
148 IN UINT8 EndpointIndex
149 )
150{
151 // Don't care.
152}
153
154/*
155 Set up the transport system for use by Fastboot.
156 e.g. For USB this probably means making the device enumerable.
157*/
159FastbootTransportUsbStart (
160 EFI_EVENT ReceiveEvent
161 )
162{
164
165 mReceiveEvent = ReceiveEvent;
166
167 mGetConfigDescriptorResponse.ConfigDescriptor.TotalLength = sizeof (GET_CONFIG_DESCRIPTOR_RESPONSE);
168 Responses = &mGetConfigDescriptorResponse;
169
170 InitializeListHead (&mPacketList);
171
172 return mUsbDevice->Start (&mDeviceDescriptor, (VOID **)&Responses, DataReceived, DataSent);
173}
174
175/*
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
179 a USB host.
180*/
182FastbootTransportUsbStop (
183 VOID
184 )
185{
186 // not yet implemented in USB
187 return EFI_SUCCESS;
188}
189
190/*
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)
194 */
196FastbootTransportUsbSend (
197 IN UINTN BufferSize,
198 IN CONST VOID *Buffer,
199 IN EFI_EVENT *FatalErrorEvent
200 )
201{
202 // Current USB protocol is blocking, so ignore FatalErrorEvent
203 return mUsbDevice->Send (1, BufferSize, Buffer);
204}
205
206/*
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.
213
214 Parameters:
215 Buffer - The buffer in which to place data
216 BufferSize - The size of Buffer in bytes
217
218 Return EFI_NOT_READY if there is no data available
219*/
221FastbootTransportUsbReceive (
222 OUT UINTN *BufferSize,
223 OUT VOID **Buffer
224 )
225{
227
228 if (IsListEmpty (&mPacketList)) {
229 return EFI_NOT_READY;
230 }
231
232 Entry = (FASTBOOT_USB_PACKET_LIST *)GetFirstNode (&mPacketList);
233
234 *BufferSize = Entry->BufferSize;
235 *Buffer = Entry->Buffer;
236
237 RemoveEntryList (&Entry->Link);
238 FreePool (Entry);
239
240 return EFI_SUCCESS;
241}
242
243STATIC FASTBOOT_TRANSPORT_PROTOCOL mTransportProtocol = {
244 FastbootTransportUsbStart,
245 FastbootTransportUsbStop,
246 FastbootTransportUsbSend,
247 FastbootTransportUsbReceive
248};
249
251FastbootTransportUsbEntryPoint (
252 IN EFI_HANDLE ImageHandle,
253 IN EFI_SYSTEM_TABLE *SystemTable
254 )
255{
256 EFI_STATUS Status;
257
258 // Assume there's only one USB peripheral controller.
259 Status = gBS->LocateProtocol (&gUsbDeviceProtocolGuid, NULL, (VOID **)&mUsbDevice);
260 if (EFI_ERROR (Status)) {
261 return Status;
262 }
263
264 Status = gBS->InstallProtocolInterface (
265 &ImageHandle,
266 &gAndroidFastbootTransportProtocolGuid,
268 &mTransportProtocol
269 );
270 return Status;
271}
UINT64 UINTN
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define FixedPcdGet32(TokenName)
Definition: PcdLib.h:92
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
@ EFI_NATIVE_INTERFACE
Definition: UefiSpec.h:1193