]> git.proxmox.com Git - mirror_edk2.git/blob - EmbeddedPkg/Drivers/AndroidFastbootTransportUsbDxe/FastbootTransportUsb.c
EmbeddedPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / EmbeddedPkg / Drivers / AndroidFastbootTransportUsbDxe / FastbootTransportUsb.c
1 /** @file
2
3 Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
4
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 /*
10 * Implementation of the FASTBOOT_TRANSPORT_PROTOCOL using the USB_DEVICE_PROTOCOL
11 */
12
13 #include <Protocol/UsbDevice.h>
14 #include <Protocol/AndroidFastbootTransport.h>
15 #include <Protocol/SimpleTextOut.h>
16
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>
23
24 STATIC 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
32 STATIC USB_DEVICE_PROTOCOL *mUsbDevice;
33 STATIC EFI_EVENT mReceiveEvent = NULL;
34 STATIC LIST_ENTRY mPacketList;
35
36 // List type for queued received packets
37 typedef struct _FASTBOOT_USB_PACKET_LIST {
38 LIST_ENTRY Link;
39 VOID *Buffer;
40 UINTN BufferSize;
41 } FASTBOOT_USB_PACKET_LIST;
42
43
44 /*
45 No string descriptors - all string descriptor members are set to 0
46 */
47
48 STATIC USB_DEVICE_DESCRIPTOR mDeviceDescriptor = {
49 sizeof (USB_DEVICE_DESCRIPTOR), //Length
50 USB_DESC_TYPE_DEVICE, //DescriptorType
51 0x0200, //BcdUSB
52 0xFF, //DeviceClass
53 0, //DeviceSubClass
54 0, //DeviceProtocol
55 64, //MaxPacketSize0
56 FixedPcdGet32 (PcdAndroidFastbootUsbVendorId), //IdVendor
57 FixedPcdGet32 (PcdAndroidFastbootUsbProductId), //IdProduct
58 0, //BcdDevice
59 0, //StrManufacturer
60 0, //StrProduct
61 0, //StrSerialNumber
62 1 //NumConfigurations
63 };
64
65 /*
66 We have one configuration, one interface, and two endpoints (one IN, one OUT)
67 */
68
69 // Lazy (compile-time) way to concatenate descriptors to pass to the USB device
70 // protocol
71
72 #pragma pack(1)
73 typedef struct {
74 USB_CONFIG_DESCRIPTOR ConfigDescriptor;
75 USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
76 USB_ENDPOINT_DESCRIPTOR EndpointDescriptor1;
77 USB_ENDPOINT_DESCRIPTOR EndpointDescriptor2;
78 } GET_CONFIG_DESCRIPTOR_RESPONSE;
79 #pragma pack()
80
81 STATIC GET_CONFIG_DESCRIPTOR_RESPONSE mGetConfigDescriptorResponse = {
82 { // USB_CONFIG_DESCRIPTOR
83 sizeof (USB_CONFIG_DESCRIPTOR), //Length;
84 USB_DESC_TYPE_CONFIG, //DescriptorType;
85 sizeof (GET_CONFIG_DESCRIPTOR_RESPONSE), //TotalLength;
86 1, //NumInterfaces;
87 1, //ConfigurationValue;
88 0, //Configuration;
89 CONFIG_DESC_ATTRIBUTES, //Attributes;
90 0 //MaxPower;
91 },
92 { // USB_INTERFACE_DESCRIPTOR
93 sizeof (USB_INTERFACE_DESCRIPTOR), //Length;
94 USB_DESC_TYPE_INTERFACE, //DescriptorType;
95 0, //InterfaceNumber;
96 0, //AlternateSetting;
97 2, //NumEndpoints;
98 0xFF, //InterfaceClass;
99 // Vendor specific interface subclass and protocol codes.
100 // I found these values in the Fastboot code
101 // (in match_fastboot_with_serial in fastboot.c).
102 0x42, //InterfaceSubClass;
103 0x03, //InterfaceProtocol;
104 0 //Interface;
105 },
106 { // USB_ENDPOINT_DESCRIPTOR (In Endpoint)
107 sizeof (USB_ENDPOINT_DESCRIPTOR), //Length;
108 USB_DESC_TYPE_ENDPOINT, //DescriptorType;
109 1 | BIT7, //EndpointAddress;
110 0x2, //Attributes;
111 MAX_PACKET_SIZE_BULK, //MaxPacketSize;
112 16 //Interval;
113 },
114 { // STATIC USB_ENDPOINT_DESCRIPTOR (Out Endpoint)
115 sizeof (USB_ENDPOINT_DESCRIPTOR), //Length;
116 USB_DESC_TYPE_ENDPOINT, //DescriptorType;
117 1, //EndpointAddress;
118 0x2, //Attributes;
119 MAX_PACKET_SIZE_BULK, //MaxPacketSize;
120 16 //Interval;
121 }
122 };
123
124 STATIC
125 VOID
126 DataReceived (
127 IN UINTN Size,
128 IN VOID *Buffer
129 )
130 {
131 FASTBOOT_USB_PACKET_LIST *NewEntry;
132
133 NewEntry = AllocatePool (sizeof (*NewEntry));
134 ASSERT (NewEntry != NULL);
135
136 NewEntry->Buffer = Buffer;
137 NewEntry->BufferSize = Size;
138
139 InsertTailList (&mPacketList, &NewEntry->Link);
140
141 if (mReceiveEvent) {
142 gBS->SignalEvent (mReceiveEvent);
143 }
144 }
145
146 STATIC
147 VOID
148 DataSent (
149 IN UINT8 EndpointIndex
150 )
151 {
152 // Don't care.
153 }
154
155 /*
156 Set up the transport system for use by Fastboot.
157 e.g. For USB this probably means making the device enumerable.
158 */
159 EFI_STATUS
160 FastbootTransportUsbStart (
161 EFI_EVENT ReceiveEvent
162 )
163 {
164 GET_CONFIG_DESCRIPTOR_RESPONSE *Responses;
165
166 mReceiveEvent = ReceiveEvent;
167
168 mGetConfigDescriptorResponse.ConfigDescriptor.TotalLength = sizeof (GET_CONFIG_DESCRIPTOR_RESPONSE);
169 Responses = &mGetConfigDescriptorResponse;
170
171 InitializeListHead (&mPacketList);
172
173 return mUsbDevice->Start (&mDeviceDescriptor, (VOID **) &Responses, DataReceived, DataSent);
174 }
175
176 /*
177 Function to be called when all Fastboot transactions are finished, to
178 de-initialise the transport system.
179 e.g. A USB OTG system might want to get out of peripheral mode so it can be
180 a USB host.
181 */
182 EFI_STATUS
183 FastbootTransportUsbStop (
184 VOID
185 )
186 {
187 // not yet implemented in USB
188 return EFI_SUCCESS;
189 }
190
191 /*
192 Send data. This function can be used both for command responses like "OKAY"
193 and for the data phase (the protocol doesn't describe any situation when the
194 latter might be necessary, but does allow it)
195 */
196 EFI_STATUS
197 FastbootTransportUsbSend (
198 IN UINTN BufferSize,
199 IN CONST VOID *Buffer,
200 IN EFI_EVENT *FatalErrorEvent
201 )
202 {
203 // Current USB protocol is blocking, so ignore FatalErrorEvent
204 return mUsbDevice->Send(1, BufferSize, Buffer);
205 }
206
207 /*
208 When the event has been Signalled to say data is available from the host,
209 this function is used to get data. In order to handle the case where several
210 packets are received before ReceiveEvent's notify function is called, packets
211 received are queued, and each call to this function returns the next packet in
212 the queue. It should therefore be called in a loop, the exit condition being a
213 return of EFI_NOT_READY.
214
215 Parameters:
216 Buffer - The buffer in which to place data
217 BufferSize - The size of Buffer in bytes
218
219 Return EFI_NOT_READY if there is no data available
220 */
221 EFI_STATUS
222 FastbootTransportUsbReceive (
223 OUT UINTN *BufferSize,
224 OUT VOID **Buffer
225 )
226 {
227 FASTBOOT_USB_PACKET_LIST *Entry;
228
229 if (IsListEmpty (&mPacketList)) {
230 return EFI_NOT_READY;
231 }
232
233 Entry = (FASTBOOT_USB_PACKET_LIST *) GetFirstNode (&mPacketList);
234
235 *BufferSize = Entry->BufferSize;
236 *Buffer = Entry->Buffer;
237
238 RemoveEntryList (&Entry->Link);
239 FreePool (Entry);
240
241 return EFI_SUCCESS;
242 }
243
244 STATIC FASTBOOT_TRANSPORT_PROTOCOL mTransportProtocol = {
245 FastbootTransportUsbStart,
246 FastbootTransportUsbStop,
247 FastbootTransportUsbSend,
248 FastbootTransportUsbReceive
249 };
250
251 EFI_STATUS
252 FastbootTransportUsbEntryPoint (
253 IN EFI_HANDLE ImageHandle,
254 IN EFI_SYSTEM_TABLE *SystemTable
255 )
256 {
257 EFI_STATUS Status;
258
259 // Assume there's only one USB peripheral controller.
260 Status = gBS->LocateProtocol (&gUsbDeviceProtocolGuid, NULL, (VOID **) &mUsbDevice);
261 if (EFI_ERROR (Status)) {
262 return Status;
263 }
264
265 Status = gBS->InstallProtocolInterface (
266 &ImageHandle,
267 &gAndroidFastbootTransportProtocolGuid,
268 EFI_NATIVE_INTERFACE,
269 &mTransportProtocol
270 );
271 return Status;
272 }