]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.c
MdeModulePkg/UsbMass: Not retry if usb bot transfer execution fail
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbMassStorageDxe / UsbMassBot.c
CommitLineData
e237e7ae 1/** @file\r
d80ed2a7 2 Implementation of the USB mass storage Bulk-Only Transport protocol,\r
3 according to USB Mass Storage Class Bulk-Only Transport, Revision 1.0.\r
cc5166ff 4\r
17f3e942 5Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 6This program and the accompanying materials\r
e237e7ae 7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
cc5166ff 14**/\r
e237e7ae 15\r
39840c50 16#include "UsbMass.h"\r
e237e7ae 17\r
d80ed2a7 18//\r
19// Definition of USB BOT Transport Protocol\r
20//\r
21USB_MASS_TRANSPORT mUsbBotTransport = {\r
22 USB_MASS_STORE_BOT,\r
23 UsbBotInit,\r
24 UsbBotExecCommand,\r
25 UsbBotResetDevice,\r
26 UsbBotGetMaxLun,\r
27 UsbBotCleanUp\r
28};\r
e237e7ae 29\r
30/**\r
d80ed2a7 31 Initializes USB BOT protocol.\r
32\r
33 This function initializes the USB mass storage class BOT protocol.\r
e237e7ae 34 It will save its context which is a USB_BOT_PROTOCOL structure\r
35 in the Context if Context isn't NULL.\r
36\r
d80ed2a7 37 @param UsbIo The USB I/O Protocol instance\r
38 @param Context The buffer to save the context to\r
e237e7ae 39\r
d80ed2a7 40 @retval EFI_SUCCESS The device is successfully initialized.\r
e237e7ae 41 @retval EFI_UNSUPPORTED The transport protocol doesn't support the device.\r
d80ed2a7 42 @retval Other The USB BOT initialization fails.\r
e237e7ae 43\r
44**/\r
e237e7ae 45EFI_STATUS\r
46UsbBotInit (\r
d80ed2a7 47 IN EFI_USB_IO_PROTOCOL *UsbIo,\r
e237e7ae 48 OUT VOID **Context OPTIONAL\r
49 )\r
50{\r
51 USB_BOT_PROTOCOL *UsbBot;\r
52 EFI_USB_INTERFACE_DESCRIPTOR *Interface;\r
53 EFI_USB_ENDPOINT_DESCRIPTOR EndPoint;\r
54 EFI_STATUS Status;\r
55 UINT8 Index;\r
56\r
57 //\r
d80ed2a7 58 // Allocate the BOT context for USB_BOT_PROTOCOL and two endpoint descriptors.\r
e237e7ae 59 //\r
3e03cb4d 60 UsbBot = AllocateZeroPool (sizeof (USB_BOT_PROTOCOL) + 2 * sizeof (EFI_USB_ENDPOINT_DESCRIPTOR));\r
d80ed2a7 61 ASSERT (UsbBot != NULL);\r
e237e7ae 62\r
63 UsbBot->UsbIo = UsbIo;\r
64\r
65 //\r
66 // Get the interface descriptor and validate that it\r
d80ed2a7 67 // is a USB Mass Storage BOT interface.\r
e237e7ae 68 //\r
69 Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &UsbBot->Interface);\r
70\r
71 if (EFI_ERROR (Status)) {\r
e237e7ae 72 goto ON_ERROR;\r
73 }\r
74\r
75 Interface = &UsbBot->Interface;\r
76\r
77 if (Interface->InterfaceProtocol != USB_MASS_STORE_BOT) {\r
78 Status = EFI_UNSUPPORTED;\r
79 goto ON_ERROR;\r
80 }\r
81\r
82 //\r
83 // Locate and save the first bulk-in and bulk-out endpoint\r
84 //\r
85 for (Index = 0; Index < Interface->NumEndpoints; Index++) {\r
86 Status = UsbIo->UsbGetEndpointDescriptor (UsbIo, Index, &EndPoint);\r
87\r
88 if (EFI_ERROR (Status) || !USB_IS_BULK_ENDPOINT (EndPoint.Attributes)) {\r
89 continue;\r
90 }\r
91\r
92 if (USB_IS_IN_ENDPOINT (EndPoint.EndpointAddress) &&\r
93 (UsbBot->BulkInEndpoint == NULL)) {\r
94\r
95 UsbBot->BulkInEndpoint = (EFI_USB_ENDPOINT_DESCRIPTOR *) (UsbBot + 1);\r
84b5c78e 96 CopyMem(UsbBot->BulkInEndpoint, &EndPoint, sizeof (EndPoint));\r
e237e7ae 97 }\r
98\r
99 if (USB_IS_OUT_ENDPOINT (EndPoint.EndpointAddress) &&\r
100 (UsbBot->BulkOutEndpoint == NULL)) {\r
101\r
102 UsbBot->BulkOutEndpoint = (EFI_USB_ENDPOINT_DESCRIPTOR *) (UsbBot + 1) + 1;\r
3e03cb4d 103 CopyMem (UsbBot->BulkOutEndpoint, &EndPoint, sizeof(EndPoint));\r
e237e7ae 104 }\r
105 }\r
106\r
d80ed2a7 107 //\r
108 // If bulk-in or bulk-out endpoint is not found, report error.\r
109 //\r
e237e7ae 110 if ((UsbBot->BulkInEndpoint == NULL) || (UsbBot->BulkOutEndpoint == NULL)) {\r
e237e7ae 111 Status = EFI_UNSUPPORTED;\r
112 goto ON_ERROR;\r
113 }\r
114\r
115 //\r
d80ed2a7 116 // The USB BOT protocol uses CBWTag to match the CBW and CSW.\r
e237e7ae 117 //\r
118 UsbBot->CbwTag = 0x01;\r
119\r
120 if (Context != NULL) {\r
121 *Context = UsbBot;\r
122 } else {\r
c92e277d 123 FreePool (UsbBot);\r
e237e7ae 124 }\r
125\r
126 return EFI_SUCCESS;\r
127\r
128ON_ERROR:\r
c92e277d 129 FreePool (UsbBot);\r
e237e7ae 130 return Status;\r
131}\r
132\r
e237e7ae 133/**\r
cc5166ff 134 Send the command to the device using Bulk-Out endpoint.\r
e237e7ae 135\r
d80ed2a7 136 This function sends the command to the device using Bulk-Out endpoint.\r
137 BOT transfer is composed of three phases: Command, Data, and Status.\r
138 This is the Command phase.\r
139\r
e237e7ae 140 @param UsbBot The USB BOT device\r
141 @param Cmd The command to transfer to device\r
d80ed2a7 142 @param CmdLen The length of the command\r
e237e7ae 143 @param DataDir The direction of the data\r
144 @param TransLen The expected length of the data\r
c7e39923 145 @param Lun The number of logic unit\r
e237e7ae 146\r
e237e7ae 147 @retval EFI_SUCCESS The command is sent to the device.\r
d80ed2a7 148 @retval EFI_NOT_READY The device return NAK to the transfer\r
e237e7ae 149 @retval Others Failed to send the command to device\r
150\r
151**/\r
e237e7ae 152EFI_STATUS\r
153UsbBotSendCommand (\r
154 IN USB_BOT_PROTOCOL *UsbBot,\r
155 IN UINT8 *Cmd,\r
156 IN UINT8 CmdLen,\r
157 IN EFI_USB_DATA_DIRECTION DataDir,\r
c7e39923 158 IN UINT32 TransLen,\r
159 IN UINT8 Lun\r
e237e7ae 160 )\r
161{\r
162 USB_BOT_CBW Cbw;\r
163 EFI_STATUS Status;\r
164 UINT32 Result;\r
165 UINTN DataLen;\r
166 UINTN Timeout;\r
167\r
168 ASSERT ((CmdLen > 0) && (CmdLen <= USB_BOT_MAX_CMDLEN));\r
169\r
170 //\r
d80ed2a7 171 // Fill in the Command Block Wrapper.\r
e237e7ae 172 //\r
173 Cbw.Signature = USB_BOT_CBW_SIGNATURE;\r
174 Cbw.Tag = UsbBot->CbwTag;\r
175 Cbw.DataLen = TransLen;\r
d80ed2a7 176 Cbw.Flag = (UINT8) ((DataDir == EfiUsbDataIn) ? BIT7 : 0);\r
c7e39923 177 Cbw.Lun = Lun;\r
e237e7ae 178 Cbw.CmdLen = CmdLen;\r
179\r
180 ZeroMem (Cbw.CmdBlock, USB_BOT_MAX_CMDLEN);\r
181 CopyMem (Cbw.CmdBlock, Cmd, CmdLen);\r
182\r
d80ed2a7 183 Result = 0;\r
184 DataLen = sizeof (USB_BOT_CBW);\r
185 Timeout = USB_BOT_SEND_CBW_TIMEOUT / USB_MASS_1_MILLISECOND;\r
e237e7ae 186\r
187 //\r
d80ed2a7 188 // Use USB I/O Protocol to send the Command Block Wrapper to the device.\r
e237e7ae 189 //\r
190 Status = UsbBot->UsbIo->UsbBulkTransfer (\r
191 UsbBot->UsbIo,\r
192 UsbBot->BulkOutEndpoint->EndpointAddress,\r
193 &Cbw,\r
194 &DataLen,\r
195 Timeout,\r
196 &Result\r
197 );\r
e237e7ae 198 if (EFI_ERROR (Status)) {\r
199 if (USB_IS_ERROR (Result, EFI_USB_ERR_STALL) && DataDir == EfiUsbDataOut) {\r
d80ed2a7 200 //\r
201 // Respond to Bulk-Out endpoint stall with a Reset Recovery,\r
202 // according to section 5.3.1 of USB Mass Storage Class Bulk-Only Transport Spec, v1.0.\r
203 //\r
e237e7ae 204 UsbBotResetDevice (UsbBot, FALSE);\r
205 } else if (USB_IS_ERROR (Result, EFI_USB_ERR_NAK)) {\r
206 Status = EFI_NOT_READY;\r
207 }\r
208 }\r
209\r
210 return Status;\r
211}\r
212\r
213\r
214/**\r
d80ed2a7 215 Transfer the data between the device and host.\r
216\r
217 This function transfers the data between the device and host.\r
218 BOT transfer is composed of three phases: Command, Data, and Status.\r
219 This is the Data phase.\r
e237e7ae 220\r
221 @param UsbBot The USB BOT device\r
222 @param DataDir The direction of the data\r
223 @param Data The buffer to hold data\r
224 @param TransLen The expected length of the data\r
225 @param Timeout The time to wait the command to complete\r
226\r
227 @retval EFI_SUCCESS The data is transferred\r
d80ed2a7 228 @retval EFI_SUCCESS No data to transfer\r
229 @retval EFI_NOT_READY The device return NAK to the transfer\r
e237e7ae 230 @retval Others Failed to transfer data\r
231\r
232**/\r
e237e7ae 233EFI_STATUS\r
234UsbBotDataTransfer (\r
235 IN USB_BOT_PROTOCOL *UsbBot,\r
236 IN EFI_USB_DATA_DIRECTION DataDir,\r
237 IN OUT UINT8 *Data,\r
238 IN OUT UINTN *TransLen,\r
239 IN UINT32 Timeout\r
240 )\r
241{\r
242 EFI_USB_ENDPOINT_DESCRIPTOR *Endpoint;\r
243 EFI_STATUS Status;\r
244 UINT32 Result;\r
245\r
246 //\r
d80ed2a7 247 // If no data to transfer, just return EFI_SUCCESS.\r
e237e7ae 248 //\r
249 if ((DataDir == EfiUsbNoData) || (*TransLen == 0)) {\r
250 return EFI_SUCCESS;\r
251 }\r
252\r
253 //\r
254 // Select the endpoint then issue the transfer\r
255 //\r
256 if (DataDir == EfiUsbDataIn) {\r
257 Endpoint = UsbBot->BulkInEndpoint;\r
258 } else {\r
259 Endpoint = UsbBot->BulkOutEndpoint;\r
260 }\r
261\r
262 Result = 0;\r
41e8ff27 263 Timeout = Timeout / USB_MASS_1_MILLISECOND;\r
e237e7ae 264\r
265 Status = UsbBot->UsbIo->UsbBulkTransfer (\r
266 UsbBot->UsbIo,\r
267 Endpoint->EndpointAddress,\r
268 Data,\r
269 TransLen,\r
270 Timeout,\r
271 &Result\r
272 );\r
273 if (EFI_ERROR (Status)) {\r
e237e7ae 274 if (USB_IS_ERROR (Result, EFI_USB_ERR_STALL)) {\r
efe9186f 275 DEBUG ((EFI_D_INFO, "UsbBotDataTransfer: (%r)\n", Status)); \r
276 DEBUG ((EFI_D_INFO, "UsbBotDataTransfer: DataIn Stall\n"));\r
e237e7ae 277 UsbClearEndpointStall (UsbBot->UsbIo, Endpoint->EndpointAddress);\r
278 } else if (USB_IS_ERROR (Result, EFI_USB_ERR_NAK)) {\r
279 Status = EFI_NOT_READY;\r
efe9186f 280 } else {\r
281 DEBUG ((EFI_D_ERROR, "UsbBotDataTransfer: (%r)\n", Status));\r
282 }\r
283 if(Status == EFI_TIMEOUT){\r
284 UsbBotResetDevice(UsbBot, FALSE);\r
e237e7ae 285 }\r
286 }\r
287\r
288 return Status;\r
289}\r
290\r
291\r
292/**\r
d80ed2a7 293 Get the command execution status from device.\r
294\r
295 This function gets the command execution status from device.\r
296 BOT transfer is composed of three phases: Command, Data, and Status.\r
297 This is the Status phase.\r
e237e7ae 298\r
d80ed2a7 299 This function returns the transfer status of the BOT's CSW status,\r
300 and returns the high level command execution result in Result. So\r
301 even if EFI_SUCCESS is returned, the command may still have failed.\r
e237e7ae 302\r
d80ed2a7 303 @param UsbBot The USB BOT device.\r
304 @param TransLen The expected length of the data.\r
305 @param CmdStatus The result of the command execution.\r
306\r
307 @retval EFI_SUCCESS Command execute result is retrieved and in the Result.\r
308 @retval Other Error occurred when trying to get status.\r
e237e7ae 309\r
310**/\r
e237e7ae 311EFI_STATUS\r
312UsbBotGetStatus (\r
313 IN USB_BOT_PROTOCOL *UsbBot,\r
314 IN UINT32 TransLen,\r
315 OUT UINT8 *CmdStatus\r
316 )\r
317{\r
318 USB_BOT_CSW Csw;\r
319 UINTN Len;\r
320 UINT8 Endpoint;\r
321 EFI_STATUS Status;\r
322 UINT32 Result;\r
323 EFI_USB_IO_PROTOCOL *UsbIo;\r
324 UINT32 Index;\r
325 UINTN Timeout;\r
1c619535 326\r
e237e7ae 327 *CmdStatus = USB_BOT_COMMAND_ERROR;\r
328 Status = EFI_DEVICE_ERROR;\r
329 Endpoint = UsbBot->BulkInEndpoint->EndpointAddress;\r
330 UsbIo = UsbBot->UsbIo;\r
41e8ff27 331 Timeout = USB_BOT_RECV_CSW_TIMEOUT / USB_MASS_1_MILLISECOND;\r
e237e7ae 332\r
41e8ff27 333 for (Index = 0; Index < USB_BOT_RECV_CSW_RETRY; Index++) {\r
e237e7ae 334 //\r
d80ed2a7 335 // Attemp to the read Command Status Wrapper from bulk in endpoint\r
e237e7ae 336 //\r
337 ZeroMem (&Csw, sizeof (USB_BOT_CSW));\r
338 Result = 0;\r
339 Len = sizeof (USB_BOT_CSW);\r
340 Status = UsbIo->UsbBulkTransfer (\r
341 UsbIo,\r
342 Endpoint,\r
343 &Csw,\r
344 &Len,\r
345 Timeout,\r
346 &Result\r
347 );\r
348 if (EFI_ERROR(Status)) {\r
e237e7ae 349 if (USB_IS_ERROR (Result, EFI_USB_ERR_STALL)) {\r
e237e7ae 350 UsbClearEndpointStall (UsbIo, Endpoint);\r
351 }\r
352 continue;\r
353 }\r
354\r
355 if (Csw.Signature != USB_BOT_CSW_SIGNATURE) {\r
356 //\r
d80ed2a7 357 // CSW is invalid, so perform reset recovery\r
e237e7ae 358 //\r
e237e7ae 359 Status = UsbBotResetDevice (UsbBot, FALSE);\r
360 } else if (Csw.CmdStatus == USB_BOT_COMMAND_ERROR) {\r
361 //\r
d80ed2a7 362 // Respond phase error also needs reset recovery\r
e237e7ae 363 //\r
e237e7ae 364 Status = UsbBotResetDevice (UsbBot, FALSE);\r
365 } else {\r
e237e7ae 366 *CmdStatus = Csw.CmdStatus;\r
367 break;\r
368 }\r
369 }\r
370 //\r
d80ed2a7 371 //The tag is increased even if there is an error.\r
e237e7ae 372 //\r
373 UsbBot->CbwTag++;\r
374\r
375 return Status;\r
376}\r
377\r
378\r
379/**\r
d80ed2a7 380 Call the USB Mass Storage Class BOT protocol to issue\r
cc5166ff 381 the command/data/status circle to execute the commands.\r
e237e7ae 382\r
383 @param Context The context of the BOT protocol, that is,\r
384 USB_BOT_PROTOCOL\r
385 @param Cmd The high level command\r
386 @param CmdLen The command length\r
387 @param DataDir The direction of the data transfer\r
388 @param Data The buffer to hold data\r
389 @param DataLen The length of the data\r
c7e39923 390 @param Lun The number of logic unit\r
e237e7ae 391 @param Timeout The time to wait command\r
392 @param CmdStatus The result of high level command execution\r
393\r
d80ed2a7 394 @retval EFI_SUCCESS The command is executed successfully.\r
cc5166ff 395 @retval Other Failed to excute command\r
e237e7ae 396\r
397**/\r
e237e7ae 398EFI_STATUS\r
399UsbBotExecCommand (\r
400 IN VOID *Context,\r
401 IN VOID *Cmd,\r
402 IN UINT8 CmdLen,\r
403 IN EFI_USB_DATA_DIRECTION DataDir,\r
404 IN VOID *Data,\r
405 IN UINT32 DataLen,\r
c7e39923 406 IN UINT8 Lun,\r
e237e7ae 407 IN UINT32 Timeout,\r
408 OUT UINT32 *CmdStatus\r
409 )\r
410{\r
411 USB_BOT_PROTOCOL *UsbBot;\r
412 EFI_STATUS Status;\r
413 UINTN TransLen;\r
414 UINT8 Result;\r
415\r
416 *CmdStatus = USB_MASS_CMD_FAIL;\r
417 UsbBot = (USB_BOT_PROTOCOL *) Context;\r
418\r
419 //\r
420 // Send the command to the device. Return immediately if device\r
421 // rejects the command.\r
422 //\r
c7e39923 423 Status = UsbBotSendCommand (UsbBot, Cmd, CmdLen, DataDir, DataLen, Lun);\r
e237e7ae 424 if (EFI_ERROR (Status)) {\r
1c619535 425 DEBUG ((EFI_D_ERROR, "UsbBotExecCommand: UsbBotSendCommand (%r)\n", Status));\r
e237e7ae 426 return Status;\r
427 }\r
428\r
429 //\r
430 // Transfer the data. Don't return immediately even data transfer\r
431 // failed. The host should attempt to receive the CSW no matter\r
d80ed2a7 432 // whether it succeeds or fails.\r
e237e7ae 433 //\r
434 TransLen = (UINTN) DataLen;\r
17f3e942
FT
435 Status = UsbBotDataTransfer (UsbBot, DataDir, Data, &TransLen, Timeout);\r
436 if (Status == EFI_DEVICE_ERROR) {\r
437 DEBUG ((EFI_D_ERROR, "UsbBotExecCommand: UsbBotDataTransfer (%r)\n", Status));\r
438 return Status;\r
439 }\r
e237e7ae 440\r
441 //\r
442 // Get the status, if that succeeds, interpret the result\r
443 //\r
444 Status = UsbBotGetStatus (UsbBot, DataLen, &Result);\r
445 if (EFI_ERROR (Status)) {\r
1c619535 446 DEBUG ((EFI_D_ERROR, "UsbBotExecCommand: UsbBotGetStatus (%r)\n", Status));\r
e237e7ae 447 return Status;\r
448 }\r
449\r
450 if (Result == 0) {\r
451 *CmdStatus = USB_MASS_CMD_SUCCESS;\r
452 }\r
453\r
454 return EFI_SUCCESS;\r
455}\r
456\r
457\r
458/**\r
d80ed2a7 459 Reset the USB mass storage device by BOT protocol.\r
e237e7ae 460\r
461 @param Context The context of the BOT protocol, that is,\r
cc5166ff 462 USB_BOT_PROTOCOL.\r
d80ed2a7 463 @param ExtendedVerification If FALSE, just issue Bulk-Only Mass Storage Reset request.\r
464 If TRUE, additionally reset parent hub port.\r
e237e7ae 465\r
cc5166ff 466 @retval EFI_SUCCESS The device is reset.\r
467 @retval Others Failed to reset the device..\r
e237e7ae 468\r
469**/\r
e237e7ae 470EFI_STATUS\r
471UsbBotResetDevice (\r
472 IN VOID *Context,\r
d80ed2a7 473 IN BOOLEAN ExtendedVerification\r
e237e7ae 474 )\r
475{\r
476 USB_BOT_PROTOCOL *UsbBot;\r
477 EFI_USB_DEVICE_REQUEST Request;\r
478 EFI_STATUS Status;\r
479 UINT32 Result;\r
480 UINT32 Timeout;\r
481\r
482 UsbBot = (USB_BOT_PROTOCOL *) Context;\r
483\r
484 if (ExtendedVerification) {\r
485 //\r
486 // If we need to do strictly reset, reset its parent hub port\r
487 //\r
488 Status = UsbBot->UsbIo->UsbPortReset (UsbBot->UsbIo);\r
489 if (EFI_ERROR (Status)) {\r
c6e797ae 490 return EFI_DEVICE_ERROR;\r
e237e7ae 491 }\r
492 }\r
493\r
494 //\r
d80ed2a7 495 // Issue a class specific Bulk-Only Mass Storage Reset request,\r
496 // according to section 3.1 of USB Mass Storage Class Bulk-Only Transport Spec, v1.0.\r
e237e7ae 497 //\r
d80ed2a7 498 Request.RequestType = 0x21;\r
e237e7ae 499 Request.Request = USB_BOT_RESET_REQUEST;\r
500 Request.Value = 0;\r
501 Request.Index = UsbBot->Interface.InterfaceNumber;\r
502 Request.Length = 0;\r
41e8ff27 503 Timeout = USB_BOT_RESET_DEVICE_TIMEOUT / USB_MASS_1_MILLISECOND;\r
e237e7ae 504\r
505 Status = UsbBot->UsbIo->UsbControlTransfer (\r
506 UsbBot->UsbIo,\r
507 &Request,\r
508 EfiUsbNoData,\r
509 Timeout,\r
510 NULL,\r
511 0,\r
512 &Result\r
513 );\r
514\r
515 if (EFI_ERROR (Status)) {\r
c6e797ae 516 return EFI_DEVICE_ERROR;\r
e237e7ae 517 }\r
518\r
519 //\r
520 // The device shall NAK the host's request until the reset is\r
521 // complete. We can use this to sync the device and host. For\r
d80ed2a7 522 // now just stall 100ms to wait for the device.\r
e237e7ae 523 //\r
41e8ff27 524 gBS->Stall (USB_BOT_RESET_DEVICE_STALL);\r
e237e7ae 525\r
526 //\r
527 // Clear the Bulk-In and Bulk-Out stall condition.\r
528 //\r
529 UsbClearEndpointStall (UsbBot->UsbIo, UsbBot->BulkInEndpoint->EndpointAddress);\r
530 UsbClearEndpointStall (UsbBot->UsbIo, UsbBot->BulkOutEndpoint->EndpointAddress);\r
d80ed2a7 531\r
e237e7ae 532 return Status;\r
533}\r
534\r
c7e39923 535\r
cc5166ff 536/**\r
d80ed2a7 537 Get the max LUN (Logical Unit Number) of USB mass storage device.\r
c7e39923 538\r
cc5166ff 539 @param Context The context of the BOT protocol, that is, USB_BOT_PROTOCOL\r
d80ed2a7 540 @param MaxLun Return pointer to the max number of LUN. (e.g. MaxLun=1 means LUN0 and\r
541 LUN1 in all.)\r
c7e39923 542\r
d80ed2a7 543 @retval EFI_SUCCESS Max LUN is got successfully.\r
544 @retval Others Fail to execute this request.\r
c7e39923 545\r
cc5166ff 546**/\r
c7e39923 547EFI_STATUS\r
548UsbBotGetMaxLun (\r
549 IN VOID *Context,\r
d80ed2a7 550 OUT UINT8 *MaxLun\r
c7e39923 551 )\r
c7e39923 552{\r
553 USB_BOT_PROTOCOL *UsbBot;\r
554 EFI_USB_DEVICE_REQUEST Request;\r
555 EFI_STATUS Status;\r
556 UINT32 Result;\r
557 UINT32 Timeout;\r
558\r
559 ASSERT (Context);\r
560 \r
561 UsbBot = (USB_BOT_PROTOCOL *) Context;\r
562\r
563 //\r
564 // Issue a class specific Bulk-Only Mass Storage get max lun reqest.\r
d80ed2a7 565 // according to section 3.2 of USB Mass Storage Class Bulk-Only Transport Spec, v1.0.\r
c7e39923 566 //\r
d80ed2a7 567 Request.RequestType = 0xA1;\r
c7e39923 568 Request.Request = USB_BOT_GETLUN_REQUEST;\r
569 Request.Value = 0;\r
570 Request.Index = UsbBot->Interface.InterfaceNumber;\r
571 Request.Length = 1;\r
572 Timeout = USB_BOT_RESET_DEVICE_TIMEOUT / USB_MASS_1_MILLISECOND;\r
573\r
574 Status = UsbBot->UsbIo->UsbControlTransfer (\r
575 UsbBot->UsbIo,\r
576 &Request,\r
577 EfiUsbDataIn,\r
578 Timeout,\r
d80ed2a7 579 (VOID *) MaxLun,\r
c7e39923 580 1,\r
581 &Result\r
582 );\r
583\r
c7e39923 584 return Status;\r
585}\r
e237e7ae 586\r
587/**\r
cc5166ff 588 Clean up the resource used by this BOT protocol.\r
e237e7ae 589\r
d80ed2a7 590 @param Context The context of the BOT protocol, that is, USB_BOT_PROTOCOL.\r
e237e7ae 591\r
d80ed2a7 592 @retval EFI_SUCCESS The resource is cleaned up.\r
e237e7ae 593\r
594**/\r
e237e7ae 595EFI_STATUS\r
d80ed2a7 596UsbBotCleanUp (\r
e237e7ae 597 IN VOID *Context\r
598 )\r
599{\r
c92e277d 600 FreePool (Context);\r
e237e7ae 601 return EFI_SUCCESS;\r
602}\r
603\r