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