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