3 Copyright (C) Dean Camera, 2011.
5 dean [at] fourwalledcubicle [dot] com
10 Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
12 Permission to use, copy, modify, distribute, and sell this
13 software and its documentation for any purpose is hereby granted
14 without fee, provided that the above copyright notice appear in
15 all copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
21 The author disclaim all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
31 #define __INCLUDE_FROM_USB_DRIVER
32 #include "../../Core/USBMode.h"
34 #if defined(USB_CAN_BE_HOST)
36 #define __INCLUDE_FROM_MS_DRIVER
37 #define __INCLUDE_FROM_MASSSTORAGE_HOST_C
38 #include "MassStorage.h"
40 uint8_t MS_Host_ConfigurePipes(USB_ClassInfo_MS_Host_t
* const MSInterfaceInfo
,
41 uint16_t ConfigDescriptorSize
,
42 void* ConfigDescriptorData
)
44 USB_Descriptor_Endpoint_t
* DataINEndpoint
= NULL
;
45 USB_Descriptor_Endpoint_t
* DataOUTEndpoint
= NULL
;
46 USB_Descriptor_Interface_t
* MassStorageInterface
= NULL
;
48 memset(&MSInterfaceInfo
->State
, 0x00, sizeof(MSInterfaceInfo
->State
));
50 if (DESCRIPTOR_TYPE(ConfigDescriptorData
) != DTYPE_Configuration
)
51 return MS_ENUMERROR_InvalidConfigDescriptor
;
53 while (!(DataINEndpoint
) || !(DataOUTEndpoint
))
55 if (!(MassStorageInterface
) ||
56 USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
57 DCOMP_MS_Host_NextMSInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
)
59 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
60 DCOMP_MS_Host_NextMSInterface
) != DESCRIPTOR_SEARCH_COMP_Found
)
62 return MS_ENUMERROR_NoCompatibleInterfaceFound
;
65 MassStorageInterface
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
);
67 DataINEndpoint
= NULL
;
68 DataOUTEndpoint
= NULL
;
73 USB_Descriptor_Endpoint_t
* EndpointData
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Endpoint_t
);
75 if ((EndpointData
->EndpointAddress
& ENDPOINT_DIR_MASK
) == ENDPOINT_DIR_IN
)
76 DataINEndpoint
= EndpointData
;
78 DataOUTEndpoint
= EndpointData
;
81 for (uint8_t PipeNum
= 1; PipeNum
< PIPE_TOTAL_PIPES
; PipeNum
++)
86 uint8_t EndpointAddress
;
89 if (PipeNum
== MSInterfaceInfo
->Config
.DataINPipeNumber
)
91 Size
= le16_to_cpu(DataINEndpoint
->EndpointSize
);
92 EndpointAddress
= DataINEndpoint
->EndpointAddress
;
93 Token
= PIPE_TOKEN_IN
;
95 DoubleBanked
= MSInterfaceInfo
->Config
.DataINPipeDoubleBank
;
97 MSInterfaceInfo
->State
.DataINPipeSize
= DataINEndpoint
->EndpointSize
;
99 else if (PipeNum
== MSInterfaceInfo
->Config
.DataOUTPipeNumber
)
101 Size
= le16_to_cpu(DataOUTEndpoint
->EndpointSize
);
102 EndpointAddress
= DataOUTEndpoint
->EndpointAddress
;
103 Token
= PIPE_TOKEN_OUT
;
105 DoubleBanked
= MSInterfaceInfo
->Config
.DataOUTPipeDoubleBank
;
107 MSInterfaceInfo
->State
.DataOUTPipeSize
= DataOUTEndpoint
->EndpointSize
;
114 if (!(Pipe_ConfigurePipe(PipeNum
, Type
, Token
, EndpointAddress
, Size
,
115 DoubleBanked ? PIPE_BANK_DOUBLE
: PIPE_BANK_SINGLE
)))
117 return MS_ENUMERROR_PipeConfigurationFailed
;
121 MSInterfaceInfo
->State
.InterfaceNumber
= MassStorageInterface
->InterfaceNumber
;
122 MSInterfaceInfo
->State
.IsActive
= true;
124 return MS_ENUMERROR_NoError
;
127 static uint8_t DCOMP_MS_Host_NextMSInterface(void* const CurrentDescriptor
)
129 USB_Descriptor_Header_t
* Header
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
);
131 if (Header
->Type
== DTYPE_Interface
)
133 USB_Descriptor_Interface_t
* Interface
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Interface_t
);
135 if ((Interface
->Class
== MS_CSCP_MassStorageClass
) &&
136 (Interface
->SubClass
== MS_CSCP_SCSITransparentSubclass
) &&
137 (Interface
->Protocol
== MS_CSCP_BulkOnlyTransportProtocol
))
139 return DESCRIPTOR_SEARCH_Found
;
143 return DESCRIPTOR_SEARCH_NotFound
;
146 static uint8_t DCOMP_MS_Host_NextMSInterfaceEndpoint(void* const CurrentDescriptor
)
148 USB_Descriptor_Header_t
* Header
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Header_t
);
150 if (Header
->Type
== DTYPE_Endpoint
)
152 USB_Descriptor_Endpoint_t
* Endpoint
= DESCRIPTOR_PCAST(CurrentDescriptor
, USB_Descriptor_Endpoint_t
);
154 uint8_t EndpointType
= (Endpoint
->Attributes
& EP_TYPE_MASK
);
156 if ((EndpointType
== EP_TYPE_BULK
) && (!(Pipe_IsEndpointBound(Endpoint
->EndpointAddress
))))
158 return DESCRIPTOR_SEARCH_Found
;
161 else if (Header
->Type
== DTYPE_Interface
)
163 return DESCRIPTOR_SEARCH_Fail
;
166 return DESCRIPTOR_SEARCH_NotFound
;
169 static uint8_t MS_Host_SendCommand(USB_ClassInfo_MS_Host_t
* const MSInterfaceInfo
,
170 MS_CommandBlockWrapper_t
* const SCSICommandBlock
,
171 const void* const BufferPtr
)
173 uint8_t ErrorCode
= PIPE_RWSTREAM_NoError
;
175 if (++MSInterfaceInfo
->State
.TransactionTag
== 0xFFFFFFFF)
176 MSInterfaceInfo
->State
.TransactionTag
= 1;
178 SCSICommandBlock
->Signature
= CPU_TO_LE32(MS_CBW_SIGNATURE
);
179 SCSICommandBlock
->Tag
= cpu_to_le32(MSInterfaceInfo
->State
.TransactionTag
);
181 Pipe_SelectPipe(MSInterfaceInfo
->Config
.DataOUTPipeNumber
);
184 if ((ErrorCode
= Pipe_Write_Stream_LE(SCSICommandBlock
, sizeof(MS_CommandBlockWrapper_t
),
185 NULL
)) != PIPE_RWSTREAM_NoError
)
189 Pipe_WaitUntilReady();
193 if ((BufferPtr
!= NULL
) &&
194 ((ErrorCode
= MS_Host_SendReceiveData(MSInterfaceInfo
, SCSICommandBlock
, (void*)BufferPtr
)) != PIPE_RWSTREAM_NoError
))
203 static uint8_t MS_Host_WaitForDataReceived(USB_ClassInfo_MS_Host_t
* const MSInterfaceInfo
)
205 uint16_t TimeoutMSRem
= MS_COMMAND_DATA_TIMEOUT_MS
;
206 uint16_t PreviousFrameNumber
= USB_Host_GetFrameNumber();
208 Pipe_SelectPipe(MSInterfaceInfo
->Config
.DataINPipeNumber
);
211 while (!(Pipe_IsINReceived()))
213 uint16_t CurrentFrameNumber
= USB_Host_GetFrameNumber();
215 if (CurrentFrameNumber
!= PreviousFrameNumber
)
217 PreviousFrameNumber
= CurrentFrameNumber
;
219 if (!(TimeoutMSRem
--))
220 return PIPE_RWSTREAM_Timeout
;
224 Pipe_SelectPipe(MSInterfaceInfo
->Config
.DataOUTPipeNumber
);
227 if (Pipe_IsStalled())
229 USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress());
230 return PIPE_RWSTREAM_PipeStalled
;
234 Pipe_SelectPipe(MSInterfaceInfo
->Config
.DataINPipeNumber
);
237 if (Pipe_IsStalled())
239 USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress());
240 return PIPE_RWSTREAM_PipeStalled
;
243 if (USB_HostState
== HOST_STATE_Unattached
)
244 return PIPE_RWSTREAM_DeviceDisconnected
;
247 Pipe_SelectPipe(MSInterfaceInfo
->Config
.DataINPipeNumber
);
250 Pipe_SelectPipe(MSInterfaceInfo
->Config
.DataOUTPipeNumber
);
253 return PIPE_RWSTREAM_NoError
;
256 static uint8_t MS_Host_SendReceiveData(USB_ClassInfo_MS_Host_t
* const MSInterfaceInfo
,
257 MS_CommandBlockWrapper_t
* const SCSICommandBlock
,
260 uint8_t ErrorCode
= PIPE_RWSTREAM_NoError
;
261 uint16_t BytesRem
= le32_to_cpu(SCSICommandBlock
->DataTransferLength
);
263 if (SCSICommandBlock
->Flags
& MS_COMMAND_DIR_DATA_IN
)
265 if ((ErrorCode
= MS_Host_WaitForDataReceived(MSInterfaceInfo
)) != PIPE_RWSTREAM_NoError
)
271 Pipe_SelectPipe(MSInterfaceInfo
->Config
.DataINPipeNumber
);
274 if ((ErrorCode
= Pipe_Read_Stream_LE(BufferPtr
, BytesRem
, NULL
)) != PIPE_RWSTREAM_NoError
)
281 Pipe_SelectPipe(MSInterfaceInfo
->Config
.DataOUTPipeNumber
);
284 if ((ErrorCode
= Pipe_Write_Stream_LE(BufferPtr
, BytesRem
, NULL
)) != PIPE_RWSTREAM_NoError
)
289 while (!(Pipe_IsOUTReady()))
291 if (USB_HostState
== HOST_STATE_Unattached
)
292 return PIPE_RWSTREAM_DeviceDisconnected
;
301 static uint8_t MS_Host_GetReturnedStatus(USB_ClassInfo_MS_Host_t
* const MSInterfaceInfo
,
302 MS_CommandStatusWrapper_t
* const SCSICommandStatus
)
304 uint8_t ErrorCode
= PIPE_RWSTREAM_NoError
;
306 if ((ErrorCode
= MS_Host_WaitForDataReceived(MSInterfaceInfo
)) != PIPE_RWSTREAM_NoError
)
309 Pipe_SelectPipe(MSInterfaceInfo
->Config
.DataINPipeNumber
);
312 if ((ErrorCode
= Pipe_Read_Stream_LE(SCSICommandStatus
, sizeof(MS_CommandStatusWrapper_t
),
313 NULL
)) != PIPE_RWSTREAM_NoError
)
321 if (SCSICommandStatus
->Status
!= MS_SCSI_COMMAND_Pass
)
322 ErrorCode
= MS_ERROR_LOGICAL_CMD_FAILED
;
327 uint8_t MS_Host_ResetMSInterface(USB_ClassInfo_MS_Host_t
* const MSInterfaceInfo
)
331 USB_ControlRequest
= (USB_Request_Header_t
)
333 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_CLASS
| REQREC_INTERFACE
),
334 .bRequest
= MS_REQ_MassStorageReset
,
336 .wIndex
= MSInterfaceInfo
->State
.InterfaceNumber
,
340 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
342 if ((ErrorCode
= USB_Host_SendControlRequest(NULL
)) != HOST_SENDCONTROL_Successful
)
345 Pipe_SelectPipe(MSInterfaceInfo
->Config
.DataINPipeNumber
);
347 if ((ErrorCode
= USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress())) != HOST_SENDCONTROL_Successful
)
350 Pipe_SelectPipe(MSInterfaceInfo
->Config
.DataOUTPipeNumber
);
352 if ((ErrorCode
= USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress())) != HOST_SENDCONTROL_Successful
)
355 return HOST_SENDCONTROL_Successful
;
358 uint8_t MS_Host_GetMaxLUN(USB_ClassInfo_MS_Host_t
* const MSInterfaceInfo
,
359 uint8_t* const MaxLUNIndex
)
361 uint8_t ErrorCode
= HOST_SENDCONTROL_Successful
;
363 USB_ControlRequest
= (USB_Request_Header_t
)
365 .bmRequestType
= (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
),
366 .bRequest
= MS_REQ_GetMaxLUN
,
368 .wIndex
= MSInterfaceInfo
->State
.InterfaceNumber
,
372 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
374 if ((ErrorCode
= USB_Host_SendControlRequest(MaxLUNIndex
)) == HOST_SENDCONTROL_SetupStalled
)
377 ErrorCode
= HOST_SENDCONTROL_Successful
;
383 uint8_t MS_Host_GetInquiryData(USB_ClassInfo_MS_Host_t
* const MSInterfaceInfo
,
384 const uint8_t LUNIndex
,
385 SCSI_Inquiry_Response_t
* const InquiryData
)
387 if ((USB_HostState
!= HOST_STATE_Configured
) || !(MSInterfaceInfo
->State
.IsActive
))
388 return HOST_SENDCONTROL_DeviceDisconnected
;
392 MS_CommandBlockWrapper_t SCSICommandBlock
= (MS_CommandBlockWrapper_t
)
394 .DataTransferLength
= CPU_TO_LE32(sizeof(SCSI_Inquiry_Response_t
)),
395 .Flags
= MS_COMMAND_DIR_DATA_IN
,
397 .SCSICommandLength
= 6,
404 sizeof(SCSI_Inquiry_Response_t
), // Allocation Length
405 0x00 // Unused (control)
409 MS_CommandStatusWrapper_t SCSICommandStatus
;
411 if ((ErrorCode
= MS_Host_SendCommand(MSInterfaceInfo
, &SCSICommandBlock
, InquiryData
)) != PIPE_RWSTREAM_NoError
)
414 if ((ErrorCode
= MS_Host_GetReturnedStatus(MSInterfaceInfo
, &SCSICommandStatus
)) != PIPE_RWSTREAM_NoError
)
417 return PIPE_RWSTREAM_NoError
;
420 uint8_t MS_Host_TestUnitReady(USB_ClassInfo_MS_Host_t
* const MSInterfaceInfo
,
421 const uint8_t LUNIndex
)
423 if ((USB_HostState
!= HOST_STATE_Configured
) || !(MSInterfaceInfo
->State
.IsActive
))
424 return HOST_SENDCONTROL_DeviceDisconnected
;
428 MS_CommandBlockWrapper_t SCSICommandBlock
= (MS_CommandBlockWrapper_t
)
430 .DataTransferLength
= CPU_TO_LE32(0),
431 .Flags
= MS_COMMAND_DIR_DATA_IN
,
433 .SCSICommandLength
= 6,
436 SCSI_CMD_TEST_UNIT_READY
,
441 0x00 // Unused (control)
445 MS_CommandStatusWrapper_t SCSICommandStatus
;
447 if ((ErrorCode
= MS_Host_SendCommand(MSInterfaceInfo
, &SCSICommandBlock
, NULL
)) != PIPE_RWSTREAM_NoError
)
450 if ((ErrorCode
= MS_Host_GetReturnedStatus(MSInterfaceInfo
, &SCSICommandStatus
)) != PIPE_RWSTREAM_NoError
)
453 return PIPE_RWSTREAM_NoError
;
456 uint8_t MS_Host_ReadDeviceCapacity(USB_ClassInfo_MS_Host_t
* const MSInterfaceInfo
,
457 const uint8_t LUNIndex
,
458 SCSI_Capacity_t
* const DeviceCapacity
)
460 if ((USB_HostState
!= HOST_STATE_Configured
) || !(MSInterfaceInfo
->State
.IsActive
))
461 return HOST_SENDCONTROL_DeviceDisconnected
;
465 MS_CommandBlockWrapper_t SCSICommandBlock
= (MS_CommandBlockWrapper_t
)
467 .DataTransferLength
= CPU_TO_LE32(sizeof(SCSI_Capacity_t
)),
468 .Flags
= MS_COMMAND_DIR_DATA_IN
,
470 .SCSICommandLength
= 10,
473 SCSI_CMD_READ_CAPACITY_10
,
475 0x00, // MSB of Logical block address
478 0x00, // LSB of Logical block address
481 0x00, // Partial Medium Indicator
482 0x00 // Unused (control)
486 MS_CommandStatusWrapper_t SCSICommandStatus
;
488 if ((ErrorCode
= MS_Host_SendCommand(MSInterfaceInfo
, &SCSICommandBlock
, DeviceCapacity
)) != PIPE_RWSTREAM_NoError
)
491 DeviceCapacity
->Blocks
= BE32_TO_CPU(DeviceCapacity
->Blocks
);
492 DeviceCapacity
->BlockSize
= BE32_TO_CPU(DeviceCapacity
->BlockSize
);
494 if ((ErrorCode
= MS_Host_GetReturnedStatus(MSInterfaceInfo
, &SCSICommandStatus
)) != PIPE_RWSTREAM_NoError
)
497 return PIPE_RWSTREAM_NoError
;
500 uint8_t MS_Host_RequestSense(USB_ClassInfo_MS_Host_t
* const MSInterfaceInfo
,
501 const uint8_t LUNIndex
,
502 SCSI_Request_Sense_Response_t
* const SenseData
)
504 if ((USB_HostState
!= HOST_STATE_Configured
) || !(MSInterfaceInfo
->State
.IsActive
))
505 return HOST_SENDCONTROL_DeviceDisconnected
;
509 MS_CommandBlockWrapper_t SCSICommandBlock
= (MS_CommandBlockWrapper_t
)
511 .DataTransferLength
= CPU_TO_LE32(sizeof(SCSI_Request_Sense_Response_t
)),
512 .Flags
= MS_COMMAND_DIR_DATA_IN
,
514 .SCSICommandLength
= 6,
517 SCSI_CMD_REQUEST_SENSE
,
521 sizeof(SCSI_Request_Sense_Response_t
), // Allocation Length
522 0x00 // Unused (control)
526 MS_CommandStatusWrapper_t SCSICommandStatus
;
528 if ((ErrorCode
= MS_Host_SendCommand(MSInterfaceInfo
, &SCSICommandBlock
, SenseData
)) != PIPE_RWSTREAM_NoError
)
531 if ((ErrorCode
= MS_Host_GetReturnedStatus(MSInterfaceInfo
, &SCSICommandStatus
)) != PIPE_RWSTREAM_NoError
)
534 return PIPE_RWSTREAM_NoError
;
537 uint8_t MS_Host_PreventAllowMediumRemoval(USB_ClassInfo_MS_Host_t
* const MSInterfaceInfo
,
538 const uint8_t LUNIndex
,
539 const bool PreventRemoval
)
541 if ((USB_HostState
!= HOST_STATE_Configured
) || !(MSInterfaceInfo
->State
.IsActive
))
542 return HOST_SENDCONTROL_DeviceDisconnected
;
546 MS_CommandBlockWrapper_t SCSICommandBlock
= (MS_CommandBlockWrapper_t
)
548 .DataTransferLength
= CPU_TO_LE32(0),
549 .Flags
= MS_COMMAND_DIR_DATA_OUT
,
551 .SCSICommandLength
= 6,
554 SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL
,
557 PreventRemoval
, // Prevent flag
559 0x00 // Unused (control)
563 MS_CommandStatusWrapper_t SCSICommandStatus
;
565 if ((ErrorCode
= MS_Host_SendCommand(MSInterfaceInfo
, &SCSICommandBlock
, NULL
)) != PIPE_RWSTREAM_NoError
)
568 if ((ErrorCode
= MS_Host_GetReturnedStatus(MSInterfaceInfo
, &SCSICommandStatus
)) != PIPE_RWSTREAM_NoError
)
571 return PIPE_RWSTREAM_NoError
;
574 uint8_t MS_Host_ReadDeviceBlocks(USB_ClassInfo_MS_Host_t
* const MSInterfaceInfo
,
575 const uint8_t LUNIndex
,
576 const uint32_t BlockAddress
,
577 const uint8_t Blocks
,
578 const uint16_t BlockSize
,
581 if ((USB_HostState
!= HOST_STATE_Configured
) || !(MSInterfaceInfo
->State
.IsActive
))
582 return HOST_SENDCONTROL_DeviceDisconnected
;
586 MS_CommandBlockWrapper_t SCSICommandBlock
= (MS_CommandBlockWrapper_t
)
588 .DataTransferLength
= cpu_to_le32((uint32_t)Blocks
* BlockSize
),
589 .Flags
= MS_COMMAND_DIR_DATA_IN
,
591 .SCSICommandLength
= 10,
595 0x00, // Unused (control bits, all off)
596 (BlockAddress
>> 24), // MSB of Block Address
597 (BlockAddress
>> 16),
599 (BlockAddress
& 0xFF), // LSB of Block Address
601 0x00, // MSB of Total Blocks to Read
602 Blocks
, // LSB of Total Blocks to Read
603 0x00 // Unused (control)
607 MS_CommandStatusWrapper_t SCSICommandStatus
;
609 if ((ErrorCode
= MS_Host_SendCommand(MSInterfaceInfo
, &SCSICommandBlock
, BlockBuffer
)) != PIPE_RWSTREAM_NoError
)
612 if ((ErrorCode
= MS_Host_GetReturnedStatus(MSInterfaceInfo
, &SCSICommandStatus
)) != PIPE_RWSTREAM_NoError
)
615 return PIPE_RWSTREAM_NoError
;
618 uint8_t MS_Host_WriteDeviceBlocks(USB_ClassInfo_MS_Host_t
* const MSInterfaceInfo
,
619 const uint8_t LUNIndex
,
620 const uint32_t BlockAddress
,
621 const uint8_t Blocks
,
622 const uint16_t BlockSize
,
623 const void* BlockBuffer
)
625 if ((USB_HostState
!= HOST_STATE_Configured
) || !(MSInterfaceInfo
->State
.IsActive
))
626 return HOST_SENDCONTROL_DeviceDisconnected
;
630 MS_CommandBlockWrapper_t SCSICommandBlock
= (MS_CommandBlockWrapper_t
)
632 .DataTransferLength
= cpu_to_le32((uint32_t)Blocks
* BlockSize
),
633 .Flags
= MS_COMMAND_DIR_DATA_OUT
,
635 .SCSICommandLength
= 10,
639 0x00, // Unused (control bits, all off)
640 (BlockAddress
>> 24), // MSB of Block Address
641 (BlockAddress
>> 16),
643 (BlockAddress
& 0xFF), // LSB of Block Address
645 0x00, // MSB of Total Blocks to Write
646 Blocks
, // LSB of Total Blocks to Write
647 0x00 // Unused (control)
651 MS_CommandStatusWrapper_t SCSICommandStatus
;
653 if ((ErrorCode
= MS_Host_SendCommand(MSInterfaceInfo
, &SCSICommandBlock
, BlockBuffer
)) != PIPE_RWSTREAM_NoError
)
656 if ((ErrorCode
= MS_Host_GetReturnedStatus(MSInterfaceInfo
, &SCSICommandStatus
)) != PIPE_RWSTREAM_NoError
)
659 return PIPE_RWSTREAM_NoError
;