464 lines
22 KiB
C
464 lines
22 KiB
C
/*
|
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
|
* Copyright 2016 NXP
|
|
* All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include "usb_host_config.h"
|
|
#if ((defined USB_HOST_CONFIG_MSD) && (USB_HOST_CONFIG_MSD))
|
|
#include "usb_host.h"
|
|
#include "usb_host_msd.h"
|
|
|
|
/*******************************************************************************
|
|
* Definitions
|
|
******************************************************************************/
|
|
|
|
/* UFI command code */
|
|
#define UFI_FORMAT_UNIT (0x04U)
|
|
#define UFI_INQUIRY (0x12U)
|
|
#define UFI_START_STOP (0x1BU)
|
|
#define UFI_MODE_SELECT (0x55U)
|
|
#define UFI_MODE_SENSE (0x5AU)
|
|
#define UFI_MEDIUM_REMOVAL (0x1EU)
|
|
#define UFI_READ10 (0x28U)
|
|
#define UFI_READ12 (0xA8U)
|
|
#define UFI_READ_CAPACITY (0x25U)
|
|
#define UFI_READ_FORMAT_CAPACITY (0x23U)
|
|
#define UFI_REQUEST_SENSE (0x03U)
|
|
#define UFI_REZERO_UINT (0x01U)
|
|
#define UFI_SEEK (0x2BU)
|
|
#define UFI_SEND_DIAGNOSTIC (0x1DU)
|
|
#define UFI_TEST_UNIT_READY (0x00U)
|
|
#define UFI_VERIFY (0x2FU)
|
|
#define UFI_WRITE10 (0x2AU)
|
|
#define UFI_WRITE12 (0xAAU)
|
|
#define UFI_WRITE_VERIFY (0x2EU)
|
|
|
|
#define GET_BYTE_FROM_LE_LONG(b, n) \
|
|
((uint8_t)((USB_LONG_TO_LITTLE_ENDIAN(b)) >> ((n)*8))) /* get the byte from the long value */
|
|
|
|
/*******************************************************************************
|
|
* Prototypes
|
|
******************************************************************************/
|
|
|
|
/*******************************************************************************
|
|
* Variables
|
|
******************************************************************************/
|
|
|
|
/*******************************************************************************
|
|
* Code
|
|
******************************************************************************/
|
|
|
|
usb_status_t USB_HostMsdRead10(usb_host_class_handle classHandle,
|
|
uint8_t logicalUnit,
|
|
uint32_t blockAddress,
|
|
uint8_t *buffer,
|
|
uint32_t bufferLength,
|
|
uint32_t blockNumber,
|
|
transfer_callback_t callbackFn,
|
|
void *callbackParam)
|
|
{
|
|
uint8_t ufiBytes[] = {UFI_READ10,
|
|
(uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 3),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 2),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 1),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 0),
|
|
0x00,
|
|
GET_BYTE_FROM_LE_LONG(blockNumber, 1),
|
|
GET_BYTE_FROM_LE_LONG(blockNumber, 0),
|
|
0x00};
|
|
return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
|
|
USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes);
|
|
}
|
|
|
|
usb_status_t USB_HostMsdRead12(usb_host_class_handle classHandle,
|
|
uint8_t logicalUnit,
|
|
uint32_t blockAddress,
|
|
uint8_t *buffer,
|
|
uint32_t bufferLength,
|
|
uint32_t blockNumber,
|
|
transfer_callback_t callbackFn,
|
|
void *callbackParam)
|
|
{
|
|
uint8_t ufiBytes[] = {UFI_READ12,
|
|
(uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 3),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 2),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 1),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 0),
|
|
GET_BYTE_FROM_LE_LONG(blockNumber, 3),
|
|
GET_BYTE_FROM_LE_LONG(blockNumber, 2),
|
|
GET_BYTE_FROM_LE_LONG(blockNumber, 1),
|
|
GET_BYTE_FROM_LE_LONG(blockNumber, 0)};
|
|
return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
|
|
USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes);
|
|
}
|
|
|
|
usb_status_t USB_HostMsdWrite10(usb_host_class_handle classHandle,
|
|
uint8_t logicalUnit,
|
|
uint32_t blockAddress,
|
|
uint8_t *buffer,
|
|
uint32_t bufferLength,
|
|
uint32_t blockNumber,
|
|
transfer_callback_t callbackFn,
|
|
void *callbackParam)
|
|
{
|
|
uint8_t ufiBytes[] = {UFI_WRITE10,
|
|
(uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 3),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 2),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 1),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 0),
|
|
0x00,
|
|
GET_BYTE_FROM_LE_LONG(blockNumber, 1),
|
|
GET_BYTE_FROM_LE_LONG(blockNumber, 0),
|
|
0x00};
|
|
return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
|
|
USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, ufiBytes);
|
|
}
|
|
|
|
usb_status_t USB_HostMsdWrite12(usb_host_class_handle classHandle,
|
|
uint8_t logicalUnit,
|
|
uint32_t blockAddress,
|
|
uint8_t *buffer,
|
|
uint32_t bufferLength,
|
|
uint32_t blockNumber,
|
|
transfer_callback_t callbackFn,
|
|
void *callbackParam)
|
|
{
|
|
uint8_t ufiBytes[] = {UFI_WRITE12,
|
|
(uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 3),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 2),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 1),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 0),
|
|
GET_BYTE_FROM_LE_LONG(blockNumber, 3),
|
|
GET_BYTE_FROM_LE_LONG(blockNumber, 2),
|
|
GET_BYTE_FROM_LE_LONG(blockNumber, 1),
|
|
GET_BYTE_FROM_LE_LONG(blockNumber, 0)};
|
|
return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
|
|
USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, ufiBytes);
|
|
}
|
|
|
|
usb_status_t USB_HostMsdReadCapacity(usb_host_class_handle classHandle,
|
|
uint8_t logicalUnit,
|
|
uint8_t *buffer,
|
|
uint32_t bufferLength,
|
|
transfer_callback_t callbackFn,
|
|
void *callbackParam)
|
|
{
|
|
uint8_t ufiBytes[] = {UFI_READ_CAPACITY,
|
|
(uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00};
|
|
return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
|
|
USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes);
|
|
}
|
|
|
|
usb_status_t USB_HostMsdTestUnitReady(usb_host_class_handle classHandle,
|
|
uint8_t logicalUnit,
|
|
transfer_callback_t callbackFn,
|
|
void *callbackParam)
|
|
{
|
|
uint8_t ufiBytes[] = {UFI_TEST_UNIT_READY,
|
|
(uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00};
|
|
return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT,
|
|
ufiBytes);
|
|
}
|
|
|
|
usb_status_t USB_HostMsdRequestSense(usb_host_class_handle classHandle,
|
|
uint8_t logicalUnit,
|
|
uint8_t *buffer,
|
|
uint32_t bufferLength,
|
|
transfer_callback_t callbackFn,
|
|
void *callbackParam)
|
|
{
|
|
uint8_t ufiBytes[] = {UFI_REQUEST_SENSE,
|
|
(uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
|
|
0x00,
|
|
0x00,
|
|
(uint8_t)bufferLength,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00};
|
|
return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
|
|
USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes);
|
|
}
|
|
|
|
usb_status_t USB_HostMsdModeSelect(usb_host_class_handle classHandle,
|
|
uint8_t logicalUnit,
|
|
uint8_t *buffer,
|
|
uint32_t bufferLength,
|
|
transfer_callback_t callbackFn,
|
|
void *callbackParam)
|
|
{
|
|
uint8_t ufiBytes[] = {UFI_MODE_SELECT,
|
|
(uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
GET_BYTE_FROM_LE_LONG(bufferLength, 1),
|
|
GET_BYTE_FROM_LE_LONG(bufferLength, 0),
|
|
0x00};
|
|
return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
|
|
USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, ufiBytes);
|
|
}
|
|
|
|
usb_status_t USB_HostMsdModeSense(usb_host_class_handle classHandle,
|
|
uint8_t logicalUnit,
|
|
uint8_t pageControl,
|
|
uint8_t pageCode,
|
|
uint8_t *buffer,
|
|
uint32_t bufferLength,
|
|
transfer_callback_t callbackFn,
|
|
void *callbackParam)
|
|
{
|
|
uint8_t ufiBytes[] = {UFI_MODE_SENSE,
|
|
(uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
|
|
(uint8_t)(((uint32_t)pageCode << USB_HOST_UFI_MODE_SENSE_PAGE_CONTROL_SHIFT) |
|
|
((uint32_t)pageCode << USB_HOST_UFI_MODE_SENSE_PAGE_CODE_SHIFT)),
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
GET_BYTE_FROM_LE_LONG(bufferLength, 1),
|
|
GET_BYTE_FROM_LE_LONG(bufferLength, 0),
|
|
0x00};
|
|
return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
|
|
USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes);
|
|
}
|
|
|
|
usb_status_t USB_HostMsdInquiry(usb_host_class_handle classHandle,
|
|
uint8_t logicalUnit,
|
|
uint8_t *buffer,
|
|
uint32_t bufferLength,
|
|
transfer_callback_t callbackFn,
|
|
void *callbackParam)
|
|
{
|
|
uint8_t ufiBytes[] = {UFI_INQUIRY,
|
|
(uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
|
|
0x00,
|
|
0x00,
|
|
(uint8_t)bufferLength,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00};
|
|
return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
|
|
USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes);
|
|
}
|
|
|
|
usb_status_t USB_HostMsdReadFormatCapacities(usb_host_class_handle classHandle,
|
|
uint8_t logicalUnit,
|
|
uint8_t *buffer,
|
|
uint32_t bufferLength,
|
|
transfer_callback_t callbackFn,
|
|
void *callbackParam)
|
|
{
|
|
uint8_t ufiBytes[] = {UFI_READ_FORMAT_CAPACITY,
|
|
(uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
GET_BYTE_FROM_LE_LONG(bufferLength, 1),
|
|
GET_BYTE_FROM_LE_LONG(bufferLength, 0),
|
|
0x00};
|
|
return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
|
|
USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes);
|
|
}
|
|
|
|
usb_status_t USB_HostMsdFormatUnit(usb_host_class_handle classHandle,
|
|
uint8_t logicalUnit,
|
|
uint8_t trackNumber,
|
|
uint16_t interLeave,
|
|
uint8_t *buffer,
|
|
uint32_t bufferLength,
|
|
transfer_callback_t callbackFn,
|
|
void *callbackParam)
|
|
{
|
|
uint8_t ufiBytes[] = {UFI_FORMAT_UNIT,
|
|
(uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
|
|
trackNumber,
|
|
GET_BYTE_FROM_LE_LONG(interLeave, 1),
|
|
GET_BYTE_FROM_LE_LONG(interLeave, 0),
|
|
0x00,
|
|
0x00,
|
|
GET_BYTE_FROM_LE_LONG(bufferLength, 1),
|
|
GET_BYTE_FROM_LE_LONG(bufferLength, 0),
|
|
0x00};
|
|
return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
|
|
USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, ufiBytes);
|
|
}
|
|
|
|
usb_status_t USB_HostMsdPreventAllowRemoval(usb_host_class_handle classHandle,
|
|
uint8_t logicalUnit,
|
|
uint8_t prevent,
|
|
transfer_callback_t callbackFn,
|
|
void *callbackParam)
|
|
{
|
|
uint8_t ufiBytes[] = {UFI_MEDIUM_REMOVAL,
|
|
(uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
|
|
0x00,
|
|
0x00,
|
|
prevent,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00};
|
|
return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT,
|
|
ufiBytes);
|
|
}
|
|
|
|
usb_status_t USB_HostMsdWriteAndVerify(usb_host_class_handle classHandle,
|
|
uint8_t logicalUnit,
|
|
uint32_t blockAddress,
|
|
uint8_t *buffer,
|
|
uint32_t bufferLength,
|
|
uint32_t blockNumber,
|
|
transfer_callback_t callbackFn,
|
|
void *callbackParam)
|
|
{
|
|
uint8_t ufiBytes[] = {UFI_WRITE_VERIFY,
|
|
(uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 3),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 2),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 1),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 0),
|
|
0x00,
|
|
GET_BYTE_FROM_LE_LONG(blockNumber, 1),
|
|
GET_BYTE_FROM_LE_LONG(blockNumber, 0),
|
|
0x00};
|
|
return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
|
|
USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, ufiBytes);
|
|
}
|
|
|
|
usb_status_t USB_HostMsdStartStopUnit(usb_host_class_handle classHandle,
|
|
uint8_t logicalUnit,
|
|
uint8_t loadEject,
|
|
uint8_t start,
|
|
transfer_callback_t callbackFn,
|
|
void *callbackParam)
|
|
{
|
|
uint8_t ufiBytes[] = {UFI_START_STOP,
|
|
(uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
|
|
0x00,
|
|
0x00,
|
|
(uint8_t)(((uint32_t)loadEject << USB_HOST_UFI_START_STOP_UNIT_LOEJ_SHIFT) |
|
|
((uint32_t)start << USB_HOST_UFI_START_STOP_UNIT_START_SHIFT)),
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00};
|
|
return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT,
|
|
ufiBytes);
|
|
}
|
|
|
|
usb_status_t USB_HostMsdVerify(usb_host_class_handle classHandle,
|
|
uint8_t logicalUnit,
|
|
uint32_t blockAddress,
|
|
uint16_t verificationLength,
|
|
transfer_callback_t callbackFn,
|
|
void *callbackParam)
|
|
{
|
|
uint8_t ufiBytes[] = {UFI_VERIFY,
|
|
(uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 3),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 2),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 1),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 0),
|
|
0x00,
|
|
GET_BYTE_FROM_LE_LONG(verificationLength, 1),
|
|
GET_BYTE_FROM_LE_LONG(verificationLength, 0),
|
|
0x00};
|
|
return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT,
|
|
ufiBytes);
|
|
}
|
|
|
|
usb_status_t USB_HostMsdRezeroUnit(usb_host_class_handle classHandle,
|
|
uint8_t logicalUnit,
|
|
transfer_callback_t callbackFn,
|
|
void *callbackParam)
|
|
{
|
|
uint8_t ufiBytes[] = {UFI_REZERO_UINT,
|
|
(uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00};
|
|
return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT,
|
|
ufiBytes);
|
|
}
|
|
|
|
usb_status_t USB_HostMsdSeek10(usb_host_class_handle classHandle,
|
|
uint8_t logicalUnit,
|
|
uint32_t blockAddress,
|
|
transfer_callback_t callbackFn,
|
|
void *callbackParam)
|
|
{
|
|
uint8_t ufiBytes[] = {UFI_SEEK,
|
|
(uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 3),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 2),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 1),
|
|
GET_BYTE_FROM_LE_LONG(blockAddress, 0),
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00};
|
|
return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT,
|
|
ufiBytes);
|
|
}
|
|
|
|
usb_status_t USB_HostMsdSendDiagnostic(usb_host_class_handle classHandle,
|
|
uint8_t logicalUnit,
|
|
uint8_t selfTest,
|
|
transfer_callback_t callbackFn,
|
|
void *callbackParam)
|
|
{
|
|
uint8_t ufiBytes[] = {UFI_REZERO_UINT,
|
|
(uint8_t)(((uint32_t)logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION) |
|
|
((uint32_t)selfTest << USB_HOST_UFI_SEND_DIAGNOSTIC_SELF_TEST_SHIFT)),
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00,
|
|
0x00};
|
|
return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT,
|
|
ufiBytes);
|
|
}
|
|
|
|
#endif /* USB_HOST_CONFIG_MSD */
|