KT24-1110_65E-HA-651B/apps/common/usb/host/usb_storage.c

1802 lines
52 KiB
C
Raw Permalink Normal View History

2024-11-10 10:44:17 +00:00
/** * @file usb_storage.c
* @brief
* @author chenrixin@zh-jieli.com
* @version 1.00
* @date 2017-02-09
*/
#include "asm/includes.h"
#include "system/timer.h"
#include "device/ioctl_cmds.h"
#include "usb/host/usb_host.h"
#include "usb_ctrl_transfer.h"
#include "usb_bulk_transfer.h"
#include "device_drive.h"
#include "usb_storage.h"
#include "usb_config.h"
#include "app_config.h"
#if TCFG_UDISK_ENABLE
#define LOG_TAG_CONST USB
#define LOG_TAG "[USB]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
static int set_stor_power(struct usb_host_device *host_dev, u32 value);
static int get_stor_power(struct usb_host_device *host_dev, u32 value);
const struct interface_ctrl udisk_ops = {
.interface_class = USB_CLASS_MASS_STORAGE,
.set_power = set_stor_power,
.get_power = get_stor_power,
.ioctl = NULL,
};
static struct mass_storage mass_stor = {0};//SEC(.usb_h_udisk);
static const struct usb_interface_info udisk_inf = {
.ctrl = (struct interface_ctrl *) &udisk_ops,
.dev.disk = &mass_stor,
};
static struct device udisk_device ;//SEC(.usb_h_udisk);
static struct udisk_end_desc udisk_ep ;//SEC(.usb_h_udisk);
#define host_device2disk(host_dev) (udisk_inf.dev.disk)
/**
* @brief usb_stor_force_reset
*
* @param device
*
* @return
*/
static int usb_stor_force_reset(const usb_dev usb_id)
{
/* struct usb_host_device *host_dev = device_to_usbdev(device);
const usb_dev usb_id = host_device2id(host_dev); */
log_error("============usb_stor_force_reset===============\n");
return usb_h_force_reset(usb_id);
}
static void usb_stor_set_curlun(struct mass_storage *disk, u32 i)
{
disk->curlun = i;
}
static int usb_stor_get_curlun(struct mass_storage *disk)
{
return disk->curlun;
}
static int usb_stor_txmaxp(struct mass_storage *disk)
{
#if HUSB_MODE
return udisk_ep.txmaxp;
#else
return 0x40;
#endif
}
static int usb_stor_rxmaxp(struct mass_storage *disk)
{
#if HUSB_MODE
return udisk_ep.rxmaxp;
#else
return 0x40;
#endif
}
#define UDISK_MUTEX_TIMEOUT 5000/10 //5s
static int usb_h_mutex_pend(struct usb_host_device *host_dev)
{
struct mass_storage *disk = host_device2disk(host_dev);
/* putchar('{'); */
/* putchar('^'); */
/* putchar('['); */
int r = os_mutex_pend(&disk->mutex, UDISK_MUTEX_TIMEOUT);
if (r) {
log_error("-----------------%d -------------------", r);
}
if (r == OS_TIMEOUT) {
return OS_TIMEOUT;
}
return r;
}
static int usb_h_mutex_post(struct usb_host_device *host_dev)
{
struct mass_storage *disk = host_device2disk(host_dev);
/* putchar(']'); */
/* putchar('^'); */
/* putchar('}'); */
int r = os_mutex_post(&disk->mutex);
return r;
}
static int set_stor_power(struct usb_host_device *host_dev, u32 value)
{
struct mass_storage *disk = host_device2disk(host_dev);
log_debug("%s() %d ", __func__, disk->dev_status);
if (disk == NULL || disk->dev_status == DEV_IDLE) {
return 0;
}
int r = usb_h_mutex_pend(host_dev);
if (disk->dev_status == DEV_READ || disk->dev_status == DEV_WRITE) {
if (value == -1) {
log_error("%s disk busy", __func__);
}
}
disk->dev_status = DEV_CLOSE;
log_debug("%s() %d ", __func__, disk->dev_status);
if (r == OS_TIMEOUT) {
return OS_TIMEOUT;
}
usb_h_mutex_post(host_dev);
return DEV_ERR_NONE;
}
static int get_stor_power(struct usb_host_device *host_dev, u32 value)
{
return DEV_ERR_NONE;
}
/**
* @brief usb_init_cbw
*
* @param device
*/
static void usb_init_cbw(struct device *device, u32 dir, u32 opcode, u32 length)
{
struct mass_storage *disk = host_device2disk(host_dev);
memset(&disk->cbw, 0x00, sizeof(struct usb_scsi_cbw));
u32 curlun = usb_stor_get_curlun(disk);
disk->cbw.dCBWSignature = CBW_SIGNATURE;
disk->cbw.dCBWTag = rand32();
disk->cbw.bCBWLUN = curlun;
disk->cbw.lun = curlun << 5;
disk->cbw.bmCBWFlags = dir;
disk->cbw.operationCode = opcode;
disk->cbw.dCBWDataTransferLength = cpu_to_le32(length);
}
static int usb_stor_check_status(struct usb_host_device *host_dev)
{
struct mass_storage *disk = host_device2disk(host_dev);
if (!host_dev) {
return -DEV_ERR_NOT_MOUNT;
}
if (!disk) {
return -DEV_ERR_NOT_MOUNT;
}
if (disk->dev_status == DEV_IDLE) {
return -DEV_ERR_NOT_MOUNT;
} else if (disk->dev_status == DEV_CLOSE) {
return -DEV_ERR_NOT_MOUNT;
}
return 0;
}
static int usb_stor_reset(struct device *device)
{
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
int ret = DEV_ERR_NONE;
if (disk == NULL) {
return -DEV_ERR_NOT_MOUNT;
}
//mass storage reset request
ret = set_msd_reset(host_dev);
return ret;
}
static int usb_stor_resume(struct device *device)
{
struct usb_device_descriptor device_desc;
struct usb_host_device *host_dev = device_to_usbdev(device);
const usb_dev usb_id = host_device2id(host_dev);
u8 devnum = host_dev->private_data.devnum;
int ret = DEV_ERR_NONE;
ret = usb_stor_check_status(host_dev);
if (ret) {
return ret;
}
usb_h_resume(usb_id);
ret = usb_get_device_descriptor(host_dev, &device_desc);
if (ret == 0) {
return ret;
}
usb_h_force_reset(usb_id);
ret = set_address(host_dev, devnum);
if (ret) {
log_error("%s() @ %d %x\n", __func__, __LINE__, ret);
usb_sie_close(usb_id);
return -ret;
}
ret = usb_get_device_descriptor(host_dev, &device_desc);
if (ret) {
log_error("%s() @ %d %x\n", __func__, __LINE__, ret);
usb_sie_close(usb_id);
return -ret;
}
return ret;
}
/**
* @brief usb_stor_inquiry
*
* @param device
*
* @return
*/
static int _usb_stor_inquiry(struct device *device)
{
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
const usb_dev usb_id = host_device2id(host_dev);
const u32 txmaxp = usb_stor_txmaxp(disk);
const u32 rxmaxp = usb_stor_rxmaxp(disk);
int ret = DEV_ERR_NONE;
struct inquiry_data inquiry;
log_info("usb_stor_inquiry disk =%x", (u32)disk);
u32 total_lun = disk->lun;
u32 init_lun = 0;
for (int i = 0; i <= total_lun; i ++) {
usb_stor_set_curlun(disk, i);
usb_init_cbw(device, USB_DIR_IN, INQUIRY, sizeof(struct inquiry_data));
disk->cbw.bCBWLength = 0x06;
disk->cbw.lba[2] = sizeof(struct inquiry_data);
//cbw
ret = usb_bulk_only_send(device,
udisk_ep.host_epout,
txmaxp,
udisk_ep.target_epout,
(u8 *)&disk->cbw,
sizeof(struct usb_scsi_cbw));
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
//data
ret = usb_bulk_only_receive(device,
udisk_ep.host_epin,
rxmaxp,
udisk_ep.target_epin,
(u8 *)&inquiry,
sizeof(struct inquiry_data));
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
} else if (ret != sizeof(struct inquiry_data)) {
ret = -DEV_ERR_UNKNOW;
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
/* printf_buf(&inquiry, sizeof(struct inquiry_data)); */
//csw
ret = usb_bulk_only_receive(device,
udisk_ep.host_epin,
rxmaxp,
udisk_ep.target_epin,
(u8 *)&disk->csw,
sizeof(struct usb_scsi_csw));
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
} else if (ret != sizeof(struct usb_scsi_csw)) {
ret = -DEV_ERR_UNKNOW;
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
if (inquiry.PeripheralDeviceType) {
if (init_lun == i) {
if (init_lun < total_lun) {
init_lun++;
} else {
init_lun = 0;
}
}
}
}
usb_stor_set_curlun(disk, init_lun);
return DEV_ERR_NONE;
__exit:
log_error("%s---%d\n", __func__, __LINE__);
return ret;
}
static int usb_stor_inquiry(struct device *device)
{
int ret;
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
ret = usb_stor_check_status(host_dev);
if (ret) {
return ret;
}
ret = usb_h_mutex_pend(host_dev);
if (ret == OS_TIMEOUT) {
return -OS_TIMEOUT;
}
ret = _usb_stor_inquiry(device);
usb_h_mutex_post(host_dev);
return ret;
}
/**
* @brief usb_stor_test_unit_ready
*
* @param device
*
* @return
*/
static int _usb_stor_test_unit_ready(struct device *device)
{
int ret = DEV_ERR_NONE;
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
const usb_dev usb_id = host_device2id(host_dev);
const u32 txmaxp = usb_stor_txmaxp(disk);
const u32 rxmaxp = usb_stor_rxmaxp(disk);
usb_init_cbw(device, 0, TEST_UNIT_READY, 0);
disk->cbw.bCBWLength = 6;
//cbw
ret = usb_bulk_only_send(device,
udisk_ep.host_epout,
txmaxp,
udisk_ep.target_epout,
(u8 *)&disk->cbw,
sizeof(struct usb_scsi_cbw));
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
//csw
ret = usb_bulk_only_receive(device,
udisk_ep.host_epin,
rxmaxp,
udisk_ep.target_epin,
(u8 *)&disk->csw,
sizeof(struct usb_scsi_csw));
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
} else if (ret != sizeof(struct usb_scsi_csw)) {
ret = -DEV_ERR_UNKNOW;
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
return DEV_ERR_NONE;
__exit:
log_error("%s---%d\n", __func__, __LINE__);
return ret;
}
static int usb_stor_test_unit_ready(struct device *device)
{
int ret;
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
ret = usb_stor_check_status(host_dev);
if (ret) {
return ret;
}
ret = usb_h_mutex_pend(host_dev);
if (ret == OS_TIMEOUT) {
return -OS_TIMEOUT;
}
ret = _usb_stor_test_unit_ready(device);
usb_h_mutex_post(host_dev);
return ret;
}
/**
* @brief usb_stor_mode_sense6
*
* @param device
*
* @return
*
* @brief disk write protect inquiry
*/
static int _usb_stor_mode_sense6(struct device *device)
{
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
const usb_dev usb_id = host_device2id(host_dev);
u8 *cdb;
int ret = DEV_ERR_NONE;
u8 data_buf[4];
const u32 txmaxp = usb_stor_txmaxp(disk);
const u32 rxmaxp = usb_stor_rxmaxp(disk);
usb_init_cbw(device, USB_DIR_IN, MODE_SENSE, 4);
disk->cbw.bCBWLUN = 6;
cdb = (u8 *)&disk->cbw.operationCode;
cdb[1] = 0; // PC | DBD
cdb[2] = 0x1c; //page code
cdb[3] = 0; //subpage code
cdb[4] = 192; //allocation length
cdb[5] = 0; //control;
//cbw
ret = usb_bulk_only_send(device,
udisk_ep.host_epout,
txmaxp,
udisk_ep.target_epout,
(u8 *)&disk->cbw,
sizeof(struct usb_scsi_cbw));
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
//data
ret = usb_bulk_only_receive(device,
udisk_ep.host_epin,
rxmaxp, udisk_ep.target_epin,
data_buf,
sizeof(data_buf));
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
disk->read_only = data_buf[2] == 0x80 ? 1 : 0; //write protect
//csw
ret = usb_bulk_only_receive(device,
udisk_ep.host_epin,
rxmaxp,
udisk_ep.target_epin,
(u8 *)&disk->csw,
sizeof(struct usb_scsi_csw));
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
} else if (ret != sizeof(struct usb_scsi_csw)) {
ret = -DEV_ERR_NONE;
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
return DEV_ERR_NONE;
__exit:
log_error("%s---%d\n", __func__, __LINE__);
return ret;
}
static int usb_stor_mode_sense6(struct device *device)
{
int ret;
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
ret = usb_stor_check_status(host_dev);
if (ret) {
return ret;
}
ret = usb_h_mutex_pend(host_dev);
if (ret == OS_TIMEOUT) {
return -OS_TIMEOUT;
}
ret = _usb_stor_mode_sense6(device);
usb_h_mutex_post(host_dev);
return ret;
}
/**
* @brief usb_stor_request_sense
*
* @param device
*
* @return
*/
static int _usb_stor_request_sense(struct device *device)
{
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
const usb_dev usb_id = host_device2id(host_dev);
int ret = DEV_ERR_NONE;
const u32 txmaxp = usb_stor_txmaxp(disk);
const u32 rxmaxp = usb_stor_rxmaxp(disk);
usb_init_cbw(device, USB_DIR_IN, REQUEST_SENSE, sizeof(struct request_sense_data));
disk->cbw.bCBWLength = 0xC;
disk->cbw.lba[2] = sizeof(struct request_sense_data);
//cbw
ret = usb_bulk_only_send(device,
udisk_ep.host_epout,
txmaxp,
udisk_ep.target_epout,
(u8 *)&disk->cbw,
sizeof(struct usb_scsi_cbw));
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
//data
ret = usb_bulk_only_receive(device,
udisk_ep.host_epin,
rxmaxp,
udisk_ep.target_epin,
(u8 *)&disk->sense,
sizeof(struct request_sense_data));
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
} else if (ret != sizeof(struct request_sense_data)) {
ret = -DEV_ERR_NONE;
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
/* printf_buf(&private_data->dev.disk->sense, sizeof(struct REQUEST_SENSE_DATA)); */
//csw
ret = usb_bulk_only_receive(device,
udisk_ep.host_epin,
rxmaxp,
udisk_ep.target_epin,
(u8 *)&disk->csw,
sizeof(struct usb_scsi_csw));
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
} else if (ret != sizeof(struct usb_scsi_csw)) {
ret = -DEV_ERR_UNKNOW;
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
return DEV_ERR_NONE;
__exit:
log_error("%s---%d\n", __func__, __LINE__);
return ret;
}
static int usb_stor_request_sense(struct device *device)
{
int ret;
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
ret = usb_stor_check_status(host_dev);
if (ret) {
return ret;
}
ret = usb_h_mutex_pend(host_dev);
if (ret == OS_TIMEOUT) {
return -OS_TIMEOUT;
}
ret = _usb_stor_request_sense(device);
usb_h_mutex_post(host_dev);
return ret;
}
/**
* @brief usb_stor_read_capacity
*
* @param device
*
* @return
*/
static int _usb_stor_read_capacity(struct device *device)
{
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
const usb_dev usb_id = host_device2id(host_dev);
int ret = DEV_ERR_NONE;
if (disk == NULL) {
return -DEV_ERR_NOT_MOUNT;
}
const u32 txmaxp = usb_stor_txmaxp(disk);
const u32 rxmaxp = usb_stor_rxmaxp(disk);
u32 curlun = usb_stor_get_curlun(disk);
usb_init_cbw(device, USB_DIR_IN, READ_CAPACITY, 8);
disk->cbw.bCBWLength = 0xA;
disk->cbw.bmCBWFlags = USB_DIR_IN;
disk->cbw.operationCode = READ_CAPACITY;
disk->capacity[curlun].block_size = 0;
disk->capacity[curlun].block_num = 0;
//cbw
ret = usb_bulk_only_send(device,
udisk_ep.host_epout,
txmaxp,
udisk_ep.target_epout,
(u8 *)&disk->cbw,
sizeof(struct usb_scsi_cbw));
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
//data
ret = usb_bulk_only_receive(device,
udisk_ep.host_epin,
rxmaxp,
udisk_ep.target_epin,
(u8 *)&disk->capacity[curlun],
sizeof(struct read_capacity_data));
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
} else if (ret != sizeof(struct read_capacity_data)) {
ret = -DEV_ERR_UNKNOW;
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
disk->capacity[curlun].block_size = be32_to_cpu(disk->capacity[curlun].block_size);
disk->capacity[curlun].block_num = be32_to_cpu(disk->capacity[curlun].block_num) + 1;
log_info("block_size=%d", disk->capacity[curlun].block_size);
log_info("block_num=%d", disk->capacity[curlun].block_num);
//csw
ret = usb_bulk_only_receive(device,
udisk_ep.host_epin,
rxmaxp,
udisk_ep.target_epin,
(u8 *)&disk->csw,
sizeof(struct usb_scsi_csw));
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
} else if (ret != sizeof(struct usb_scsi_csw)) {
ret = -DEV_ERR_UNKNOW;
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
return DEV_ERR_NONE;
__exit:
log_error("%s---%d\n", __func__, __LINE__);
return ret;
}
static int usb_stor_read_capacity(struct device *device)
{
int ret;
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
ret = usb_stor_check_status(host_dev);
if (ret) {
return ret;
}
ret = usb_h_mutex_pend(host_dev);
if (ret == OS_TIMEOUT) {
return -OS_TIMEOUT;
}
ret = _usb_stor_read_capacity(device);
usb_h_mutex_post(host_dev);
return ret;
}
static int _usb_stro_read_cbw_request(struct device *device, u32 num_lba, u32 lba)
{
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
const u32 txmaxp = usb_stor_txmaxp(disk);
u32 rx_len = num_lba * 512; //filesystem uses the fixed BLOCK_SIZE
u32 cur_lba = lba;
int ret = 0;
disk->dev_status = DEV_READ;
disk->suspend_cnt = 0;
usb_init_cbw(device, USB_DIR_IN, READ_10, rx_len);
disk->cbw.bCBWLength = 0xA;
cur_lba = cpu_to_be32(cur_lba);
memcpy(disk->cbw.lba, &cur_lba, sizeof(cur_lba));
disk->cbw.LengthH = HIBYTE(num_lba);
disk->cbw.LengthL = LOBYTE(num_lba);
//cbw
ret = usb_bulk_only_send(device,
udisk_ep.host_epout,
txmaxp,
udisk_ep.target_epout,
(u8 *)&disk->cbw,
sizeof(struct usb_scsi_cbw));
if (ret < DEV_ERR_NONE) {
if (disk->dev_status != DEV_CLOSE) {
disk->dev_status = DEV_OPEN;
}
log_error("%s---%d", __func__, __LINE__);
return ret;
}
return num_lba;
}
static int _usb_stro_read_csw(struct device *device)
{
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
const u32 rxmaxp = usb_stor_rxmaxp(disk);
int ret = 0;
ret = usb_bulk_only_receive(device,
udisk_ep.host_epin,
rxmaxp,
udisk_ep.target_epin,
(u8 *)&disk->csw,
sizeof(struct usb_scsi_csw));
if (ret < DEV_ERR_NONE) {
log_error("%s:%d ret:%d\n", __func__, __LINE__, ret);
} else if (ret != sizeof(struct usb_scsi_csw)) {
ret = -DEV_ERR_UNKNOW;
log_error("%s:%d\n", __func__, __LINE__);
}
return ret;
}
static int _usb_stor_read_block_finish(struct device *device, u32 remain_len, u8 num_lba, void *pBuf)
{
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
const u32 txmaxp = usb_stor_txmaxp(disk);
const u32 rxmaxp = usb_stor_rxmaxp(disk);
int ret = 0;
int len = num_lba * 512;
while (remain_len) {
//读完剩余的包,再开始下一次请求
ret = usb_bulk_only_receive(device,
udisk_ep.host_epin,
rxmaxp,
udisk_ep.target_epin,
pBuf,
len);
remain_len -= len;
if (remain_len == 0) {
//csw
ret = usb_bulk_only_receive(device,
udisk_ep.host_epin,
rxmaxp,
udisk_ep.target_epin,
(u8 *)&disk->csw,
sizeof(struct usb_scsi_csw));
}
}
return 0;
}
static int _usb_stor_read_big_block(struct device *device, u32 disk_block_size, void *pBuf, u8 num_lba, u32 lba)
{
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
const u32 txmaxp = usb_stor_txmaxp(disk);
const u32 rxmaxp = usb_stor_rxmaxp(disk);
int ret = 0;
u32 rx_len = num_lba * 512; //filesystem uses the fixed BLOCK_SIZE
u8 num_block = disk_block_size / 512; //8
u8 req_offset = lba % num_block; //计算block数据偏移量
u8 send_cbw = 0;
if ((req_offset == 0) || (lba <= disk->prev_lba) || ((lba - disk->prev_lba) > num_block) || (disk->remain_len == 0)) {
//sector 4k地址;或地址不连续时(地址小于上一次地址; 地址和上一次地址不属于同一个sector)
send_cbw = 1;
} else {
//地址连续
send_cbw = 0;
}
/* y_printf("lba===%d prev_lba=%d req_offset===%d cbw:%d %d %d\n", */
/* lba, disk->prev_lba, req_offset, send_cbw, disk_block_size,disk->remain_len); */
disk->prev_lba = lba;
lba = lba / num_block;
if (send_cbw) {
_usb_stor_read_block_finish(device, disk->remain_len, num_lba, pBuf); //确保读完剩余包 */
disk->remain_len = 0;
disk->dev_status = DEV_READ;
disk->suspend_cnt = 0;
usb_init_cbw(device, USB_DIR_IN, READ_10, disk_block_size / 512 * 512);
disk->cbw.bCBWLength = 0xA;
lba = cpu_to_be32(lba);
memcpy(disk->cbw.lba, &lba, sizeof(lba));
disk->cbw.LengthH = HIBYTE(num_lba);
disk->cbw.LengthL = LOBYTE(num_lba);
//cbw
//请求disk_block_size 大小数据
ret = usb_bulk_only_send(device,
udisk_ep.host_epout,
txmaxp,
udisk_ep.target_epout,
(u8 *)&disk->cbw,
sizeof(struct usb_scsi_cbw));
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
disk->remain_len = disk_block_size;
} else {
req_offset = 0; //地址连续时,读一次data
}
//data
do {
//循环读取,直到读取到偏移量所在的数据为止
ret = usb_bulk_only_receive(device,
udisk_ep.host_epin,
rxmaxp,
udisk_ep.target_epin,
pBuf,
rx_len);
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
disk->remain_len -= rx_len;
} while (req_offset--);
if (!disk->remain_len) { //读完data,需要读csw
//csw
ret = usb_bulk_only_receive(device,
udisk_ep.host_epin,
rxmaxp,
udisk_ep.target_epin,
(u8 *)&disk->csw,
sizeof(struct usb_scsi_csw));
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
} else if (ret != sizeof(struct usb_scsi_csw)) {
ret = -DEV_ERR_UNKNOW;
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
}
disk->dev_status = DEV_OPEN;
return num_lba;
__exit:
if (disk->dev_status != DEV_CLOSE) {
disk->dev_status = DEV_OPEN;
}
log_error("%s---%d", __func__, __LINE__);
return 0;
}
int _usb_stor_async_wait_sem(struct usb_host_device *host_dev)
{
int ret = 0;
return ret;
}
#if UDISK_READ_AHEAD_ENABLE
static int _usb_stor_read_ahead_cbw(struct device *device, void *pBuf, u32 num_lba, u32 lba)
{
//log_info("func:%s,line:%d\n", __func__, __LINE__);
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
const u32 curlun = usb_stor_get_curlun(disk);
u8 read_block_num = UDISK_READ_AHEAD_BLOCK_NUM; //需要预读扇区数量
if (lba + read_block_num - 1 >= disk->capacity[curlun].block_num) {
read_block_num = disk->capacity[curlun].block_num - lba;
log_info("usb_read_ahead over capacity!!!%d,%d,%d\n", read_block_num, disk->capacity[curlun].block_num - 1, lba);
}
disk->remain_len = read_block_num * 512;
int ret = 0;
ret = _usb_stro_read_cbw_request(device, read_block_num, lba); //cbw
check_usb_read_ahead(ret);
return 0;
__exit:
return ret;
}
static int _usb_stor_read_ahead_data(struct device *device, void *pBuf, u32 num_lba, u32 lba)
{
//log_info("func:%s,line:%d\n", __func__, __LINE__);
if (num_lba == 0) {
return 0;
}
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
const u32 rxmaxp = usb_stor_rxmaxp(disk);
u32 rx_len = num_lba * 512;
int ret;
if (disk->remain_len != 0) {
ret = usb_bulk_only_receive(device,
udisk_ep.host_epin,
rxmaxp,
udisk_ep.target_epin,
pBuf,
rx_len);
check_usb_read_ahead(ret);
disk->remain_len -= rx_len;
disk->udisk_read_ahead_lba_last = lba + num_lba - 1;
}
if (disk->remain_len == 0) {
ret = _usb_stro_read_csw(device);
check_usb_read_ahead(ret);
}
return 0;
__exit:
return ret;
}
static int _usb_stor_read_ahead(struct device *device, void *pBuf, u32 num_lba, u32 lba)
{
//log_info("func:%s,line:%d\n", __func__, __LINE__);
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
int ret = 0;
if ((lba != disk->udisk_read_ahead_lba_last + 1) || disk->remain_len == 0) {
ret = _usb_stor_read_ahead_data(device, NULL, disk->remain_len / 512, lba); //预读中止,把上一次的剩下的读完
check_usb_read_ahead(ret);
ret = _usb_stor_read_ahead_cbw(device, pBuf, num_lba, lba);
check_usb_read_ahead(ret);
ret = _usb_stor_read_ahead_data(device, pBuf, num_lba, lba);
check_usb_read_ahead(ret);
} else {
ret = _usb_stor_read_ahead_data(device, pBuf, num_lba, lba);
check_usb_read_ahead(ret);
}
return num_lba; //read success
__exit:
return 0; //read error
}
#endif
/**
* @brief usb_stor_read U盘的lba扇区读取num_lba个扇区
*
* @param device
* @param pBuf buffer缓冲区memory都可以
* @param lba
* @param num_lba
*
* @return
* 0(Byte)
*/
static int _usb_stor_read(struct device *device, void *pBuf, u32 num_lba, u32 lba)
{
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
const usb_dev usb_id = host_device2id(host_dev);
const u32 txmaxp = usb_stor_txmaxp(disk);
const u32 rxmaxp = usb_stor_rxmaxp(disk);
const u32 curlun = usb_stor_get_curlun(disk);
u8 read_retry = 0;
int ret;
u32 rx_cnt;
/* u32 rx_len = num_lba * disk->capacity[curlun].block_size; */
u32 rx_len = num_lba * 512; //filesystem uses the fixed BLOCK_SIZE
if (disk->capacity[curlun].block_size > 512) {
// 扇区大于512Byte
return _usb_stor_read_big_block(device, disk->capacity[curlun].block_size, pBuf, num_lba, lba);
}
if (lba + num_lba - 1 >= disk->capacity[curlun].block_num) {
return -DEV_ERR_OVER_CAPACITY;
}
#if UDISK_READ_AHEAD_ENABLE
if (disk->udisk_read_ahead_en) {
return _usb_stor_read_ahead(device, pBuf, num_lba, lba);
}
#endif
ret = _usb_stro_read_cbw_request(device, num_lba, lba);
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
//data
ret = usb_bulk_only_receive(device,
udisk_ep.host_epin,
rxmaxp,
udisk_ep.target_epin,
pBuf,
rx_len);
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
//csw
ret = usb_bulk_only_receive(device,
udisk_ep.host_epin,
rxmaxp,
udisk_ep.target_epin,
(u8 *)&disk->csw,
sizeof(struct usb_scsi_csw));
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
} else if (ret != sizeof(struct usb_scsi_csw)) {
ret = -DEV_ERR_UNKNOW;
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
disk->dev_status = DEV_OPEN;
return num_lba;
__exit:
if (disk->dev_status != DEV_CLOSE) {
disk->dev_status = DEV_OPEN;
}
log_error("%s---%d", __func__, __LINE__);
return 0;
}
static int usb_stor_read(struct device *device, void *pBuf, u32 num_lba, u32 lba)
{
int ret;
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
ret = usb_stor_check_status(host_dev);
if (ret) {
return ret;
}
ret = usb_h_mutex_pend(host_dev);
if (ret == OS_TIMEOUT) {
return -OS_TIMEOUT;
}
ret = _usb_stor_read(device, pBuf, num_lba, lba);
usb_h_mutex_post(host_dev);
return ret;
}
/**
* @brief usb_stor_write U盘
*
* @param device
* @param pBuf buffer
* @param lba
* @param num_lba
*
* @return
* (Byte)
*/
static int _usb_stor_write(struct device *device, void *pBuf, u32 num_lba, u32 lba)
{
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
const usb_dev usb_id = host_device2id(host_dev);
u32 ret;
const u32 txmaxp = usb_stor_txmaxp(disk);
const u32 rxmaxp = usb_stor_rxmaxp(disk);
const u32 curlun = usb_stor_get_curlun(disk);
if (lba + num_lba - 1 >= disk->capacity[curlun].block_num) {
log_error("%s %d", __func__, __LINE__);
return -DEV_ERR_OVER_CAPACITY;
}
if (disk->capacity[curlun].block_size > 512) {
log_error(" %s disk bolock size %d not support write", __func__, disk->capacity[curlun].block_size);
return -DEV_ERR_NO_WRITE;
}
if (disk->read_only) {
log_error("%s %d", __func__, __LINE__);
return -DEV_ERR_NO_WRITE;
}
/* u32 tx_len = num_lba * disk->capacity[curlun].block_size; */
u32 tx_len = num_lba * 512; //filesystem uses the fixed BLOCK_SIZE
#if UDISK_READ_AHEAD_ENABLE
if (disk->remain_len) {
_usb_stor_read_ahead_data(device, NULL, disk->remain_len / 512, disk->udisk_read_ahead_lba_last + 1); //预读中止,把上一次的剩下的读完
disk->udisk_read_ahead_lba_last = -1;
}
#endif
disk->dev_status = DEV_WRITE;
disk->suspend_cnt = 0;
usb_init_cbw(device, USB_DIR_OUT, WRITE_10, tx_len);
disk->cbw.bCBWLength = 0xA;
lba = cpu_to_be32(lba);
memcpy(disk->cbw.lba, &lba, sizeof(lba));
disk->cbw.LengthH = HIBYTE(num_lba);
disk->cbw.LengthL = LOBYTE(num_lba);
//cbw
ret = usb_bulk_only_send(device,
udisk_ep.host_epout,
txmaxp,
udisk_ep.target_epout,
(u8 *)&disk->cbw,
sizeof(struct usb_scsi_cbw));
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
//data
ret = usb_bulk_only_send(device,
udisk_ep.host_epout,
txmaxp,
udisk_ep.target_epout,
pBuf,
tx_len);
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
//csw
ret = usb_bulk_only_receive(device,
udisk_ep.host_epin,
rxmaxp,
udisk_ep.target_epin,
(u8 *)&disk->csw,
sizeof(struct usb_scsi_csw));
if (ret < DEV_ERR_NONE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
} else if (ret != sizeof(struct usb_scsi_csw)) {
ret = -DEV_ERR_UNKNOW;
goto __exit;
}
if (disk->csw.bCSWStatus) {
ret = usb_stor_request_sense(device);
if (ret) {
ret = -DEV_ERR_OFFLINE;
}
if (ret == -DEV_ERR_OFFLINE) {
log_error("%s:%d\n", __func__, __LINE__);
goto __exit;
}
log_info("usb_stor_sense =%x", disk->sense.SenseKey);
return 0;
}
disk->dev_status = DEV_OPEN;
return num_lba;//DEV_ERR_NONE;
__exit:
if (disk->dev_status != DEV_CLOSE) {
disk->dev_status = DEV_OPEN;
}
log_error("%s---%d\n", __func__, __LINE__);
/* usb_stor_force_reset(usb_id); */
return 0;
}
static int usb_stor_write(struct device *device, void *pBuf, u32 num_lba, u32 lba)
{
int ret;
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
ret = usb_stor_check_status(host_dev);
if (ret) {
return ret;
}
ret = usb_h_mutex_pend(host_dev);
if (ret == OS_TIMEOUT) {
return -OS_TIMEOUT;
}
ret = _usb_stor_write(device, pBuf, num_lba, lba);
usb_h_mutex_post(host_dev);
return ret;
}
#if ENABLE_DISK_HOTPLUG
static void usb_stor_tick_handle(void *arg)
{
struct device *device = (struct device *)arg;
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);//(device);
const usb_dev usb_id = host_device2id(host_dev);
int ret;
r_printf("A");
if (disk == NULL) {
return;
}
r_printf("B");
if (disk->dev_status == DEV_OPEN) {
r_printf("C");
ret = usb_stor_read_capacity(device);
r_printf("D");
}
#if 0
#if 1
disk->suspend_cnt++;
if ((disk->suspend_cnt > 6) && (disk->dev_status == DEV_OPEN)) {
usb_h_entry_suspend(usb_id);
disk->suspend_cnt = 0;
disk->dev_status = DEV_SUSPEND;
}
#else
ret = usb_stor_test_unit_ready(device);
if (ret < DEV_ERR_NONE) {
return ;
}
if (disk->csw.bCSWStatus) {
usb_stor_request_sense(device);
/* puts("request sense\n"); */
/* put_buf((u8 *)&disk->sense, sizeof(disk->sense)); */
if ((disk->sense.SenseKey & 0x0f) == NOT_READY) {
if (disk->sense.ASC == 0x3a && disk->sense.ASCQ == 0x00) {
disk->media_sta_cur = 0;
}
} else if ((disk->sense.SenseKey & 0x0f) == UNIT_ATTENTION) {
if (disk->sense.ASC == 0x28 && disk->sense.ASCQ == 0x00) {
disk->media_sta_cur = 1;
}
}
} else {
disk->media_sta_cur = 1;
}
if (disk->media_sta_cur != disk->media_sta_prev) {
if (disk->media_sta_cur) {
log_info("udisk media insert");
usb_stor_read_capacity(device);
usb_stor_mode_sense6(device);
} else {
log_info("udisk media eject");
}
}
disk->media_sta_prev = disk->media_sta_cur;
#endif
#endif
}
#endif
/**
* @brief usb_stor_init
*
* @param device
*
* @return
*/
int usb_stor_init(struct device *device)
{
log_debug("%s---%d\n", __func__, __LINE__);
int ret = DEV_ERR_NONE;
u32 state = 0;
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
#if UDISK_READ_AHEAD_ENABLE
disk->udisk_read_ahead_lba_last = -1;
disk->remain_len = 0;
disk->udisk_read_ahead_en = 0;
#endif
log_error("%s() disk = %x", __func__, disk);
if (!host_dev_status(host_dev)) {
return -DEV_ERR_OFFLINE;
}
const usb_dev usb_id = host_device2id(host_dev);
if (host_dev->private_data.status == 0) {
return -ENODEV;
}
if (!disk) {
log_error("%s not enough memory");
return -DEV_ERR_OUTOFMEMORY;
}
disk->dev_status = DEV_INIT;
const u32 txmaxp = usb_stor_txmaxp(disk);
const u32 rxmaxp = usb_stor_rxmaxp(disk);
u8 lun = 0;
ret = get_msd_max_lun(host_dev, &lun);
if (ret != DEV_ERR_NONE) {
/* disk->dev_status = DEV_IDLE; */
/* usb_stor_force_reset(usb_id); */
log_error("ret = %d\n", ret);
/* return ret; */
}
disk->lun = lun;
int retry = 5;
while (retry) {
retry --;
if (ret == -DEV_ERR_OFFLINE) {
log_error("disk offline");
break;
}
switch (state) {
case 0:
log_info("--- inquery ---");
ret = usb_stor_inquiry(device);
if (ret < DEV_ERR_NONE) {
os_time_dly(retry);
if (retry == 3) {
ret = -DEV_ERR_OFFLINE;
}
} else {
state++;
}
break;
case 1:
log_info("--- test unit ready ---");
ret = usb_stor_test_unit_ready(device);
if (ret < DEV_ERR_NONE) {
os_time_dly(50);
} else if (disk->csw.bCSWStatus) {
os_time_dly(50);
ret = usb_stor_request_sense(device);
if ((disk->sense.SenseKey & 0x0f) != NO_SENSE) {
if (disk->sense.SenseKey == NOT_READY) {
os_time_dly(30);
disk->curlun++;
if (disk->curlun > disk->lun) {
disk->curlun = 0;
}
}
}
} else {
state++;
}
break;
case 2:
log_info("--- read capacity ---");
ret = usb_stor_read_capacity(device);
if (ret < DEV_ERR_NONE) {
os_time_dly(50);
} else if (disk->csw.bCSWStatus) {
os_time_dly(50);
ret = usb_stor_request_sense(device);
if ((disk->sense.SenseKey & 0x0f) != NO_SENSE) {
os_time_dly(30);
}
} else {
log_info("udisk mount succ");
state = 0xff;
}
break;
default:
retry = 0;
break;
}
}
state = 0;
if (ret != DEV_ERR_NONE) {
disk->dev_status = DEV_IDLE;
/* usb_stor_force_reset(usb_id); */
log_error("ret = %d\n", ret);
} else {
/* disk->test_unit_ready_tick = sys_timer_add(device,usb_stor_tick_handle,200); */
#if ENABLE_DISK_HOTPLUG
disk->media_sta_cur = 1;
disk->media_sta_prev = 1;
#endif
}
disk->suspend_cnt = 0;
return ret;
}
/**
* @brief usb_stor_ioctrl
*
* @param device
* @param cmd
* |||
* |---|---|
* |IOCTL_GET_ID|U盘位于总线的地址0表示不在线|
* |IOCTL_GET_BLOCK_SIZE||
* |IOCTL_GET_CAPACITY||
* |IOCTL_GET_MAX_LUN|<>|
* |IOCTL_GET_CUR_LUN||
* |IOCTL_SET_CUR_LUN||
* @param arg
*
* @return 0----
* ----
*/
static int usb_stor_ioctrl(struct device *device, u32 cmd, u32 arg)
{
int ret = DEV_ERR_NONE;
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
const usb_dev usb_id = host_device2id(host_dev);
u32 devnum = host_dev->private_data.devnum;
u32 curlun = usb_stor_get_curlun(disk);
const u32 rxmaxp = usb_stor_rxmaxp(disk);
if (disk == NULL) {
return -ENOTTY;
}
switch (cmd) {
case IOCTL_GET_ID:
*(u32 *)arg = devnum;
break;
case IOCTL_GET_BLOCK_SIZE:
*(u32 *)arg = disk->capacity[curlun].block_size;
break;
case IOCTL_GET_BLOCK_NUMBER:
*(u32 *)arg = disk->capacity[curlun].block_num;
break;
case IOCTL_GET_CAPACITY:
*(u32 *)arg = disk->capacity[curlun].block_num;
break;
case IOCTL_GET_MAX_LUN:
*(u32 *)arg = disk->lun;
break;
case IOCTL_GET_CUR_LUN:
*(u32 *)arg = curlun;
break;
case IOCTL_SET_CUR_LUN:
if (arg > disk->lun) {
return -EINVAL;
}
usb_stor_set_curlun(disk, arg);
ret = usb_stor_read_capacity(device);
if (ret < 0) {
log_error("usb disk unit%d is not ready", curlun);
return -EFAULT;
} else if (disk->csw.bCSWStatus) {
usb_stor_request_sense(device);
if (disk->sense.SenseKey != NO_SENSE) {
log_error("usb disk unit%d is not ready", curlun);
}
return -EFAULT;
}
/* usb_stor_mode_sense6(device); */
break;
case IOCTL_CHECK_WRITE_PROTECT:
if (disk->read_only) {
*(u32 *)arg = 1;
} else {
*(u32 *)arg = 0;
}
break;
case IOCTL_GET_STATUS:
#if ENABLE_DISK_HOTPLUG
if (disk->media_sta_cur) {
#else
if (1) {
#endif
log_info("usb disk unit%d is online", curlun);
*(u32 *)arg = 1;
} else {
log_info("usb disk unit%d is offline", curlun);
*(u32 *)arg = 0;
}
break;
case IOCTL_SET_FORCE_RESET:
ret = usb_stor_force_reset(usb_id);
break;
case IOCTL_SET_ASYNC_MODE:
g_printf(">> UDISK IOCTL_SET_ASYNC_MODE %d\n", arg);
#if UDISK_READ_AHEAD_ENABLE
/* printf("last lba %d, remain_len %d\n", disk->udisk_read_ahead_lba_last, disk->remain_len); */
usb_h_mutex_pend(host_dev);
if (arg == 0) {
u32 lba = disk->udisk_read_ahead_lba_last + 1;
/* printf("remain_len %d, lba %d\n", disk->remain_len, lba); */
ret = _usb_stor_read_ahead_data(device, NULL, disk->remain_len / 512, lba); //预读中止,把上一次的剩下的读完
check_usb_read_ahead(ret);
}
disk->udisk_read_ahead_lba_last = -1;
disk->udisk_read_ahead_en = arg;
usb_h_mutex_post(host_dev);
#endif
break;
default:
return -ENOTTY;
}
return ret;
__exit:
return ret;
}
/**
* @brief usb_msd_parser
*
* @param device
* @param pBuf
*
* @return
*/
int usb_msd_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
{
struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf;
pBuf += sizeof(struct usb_interface_descriptor);
int len = 0;
const usb_dev usb_id = host_device2id(host_dev);
udisk_device.private_data = host_dev;
host_dev->interface_info[interface_num] = &udisk_inf;
for (int endnum = 0; endnum < interface->bNumEndpoints; endnum++) {
struct usb_endpoint_descriptor *end_desc = (struct usb_endpoint_descriptor *)pBuf;
if (end_desc->bDescriptorType != USB_DT_ENDPOINT ||
end_desc->bLength != USB_DT_ENDPOINT_SIZE) {
log_error("ep bDescriptorType = %d bLength = %d", end_desc->bDescriptorType, end_desc->bLength);
return -USB_DT_ENDPOINT;
}
len += USB_DT_ENDPOINT_SIZE;
pBuf += USB_DT_ENDPOINT_SIZE;
if ((end_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
if (end_desc->bEndpointAddress & USB_DIR_IN) {
udisk_ep.host_epin = usb_get_ep_num(usb_id, USB_DIR_IN, USB_ENDPOINT_XFER_BULK);
udisk_ep.target_epin = end_desc->bEndpointAddress & 0x0f;
#if HUSB_MODE
udisk_ep.rxmaxp = end_desc->wMaxPacketSize;
#endif
log_debug("D(%d)->H(%d)", udisk_ep.target_epin, udisk_ep.host_epin);
} else {
udisk_ep.host_epout = usb_get_ep_num(usb_id, USB_DIR_OUT, USB_ENDPOINT_XFER_BULK);
udisk_ep.target_epout = end_desc->bEndpointAddress & 0x0f;
#if HUSB_MODE
udisk_ep.txmaxp = end_desc->wMaxPacketSize;
#endif
log_debug("H(%d)->D(%d)", udisk_ep.host_epout, udisk_ep.target_epout);
}
}
}
u8 *ep_buffer = usb_h_get_ep_buffer(usb_id, udisk_ep.host_epin | USB_DIR_IN);
usb_h_ep_config(usb_id, udisk_ep.host_epin | USB_DIR_IN, USB_ENDPOINT_XFER_BULK, 0, 0, ep_buffer, 64);
ep_buffer = usb_h_get_ep_buffer(usb_id, udisk_ep.host_epout | USB_DIR_OUT);
usb_h_ep_config(usb_id, udisk_ep.host_epout | USB_DIR_OUT, USB_ENDPOINT_XFER_BULK, 0, 0, ep_buffer, 64);
return len;
}
/**
* @brief usb_stor_open
*
* @param node
* @param device
* @param arg
*
* @return
*/
static int usb_stor_open(const char *name, struct device **device, void *arg)
{
int ret;
*device = &udisk_device;
struct usb_host_device *host_dev = device_to_usbdev(*device);
struct mass_storage *disk = host_device2disk(host_dev);
const u32 curlun = usb_stor_get_curlun(disk);
log_debug("=====================usb_stor_open===================== %d", disk->dev_status);
if (disk->dev_status != DEV_IDLE) {
if (disk->dev_status == DEV_CLOSE) {
log_error("%s() fail, disconnect\n", __func__);
return -DEV_ERR_NOT_MOUNT;
} else {
return DEV_ERR_NONE;
}
}
memset(&disk->mutex, 0, sizeof(disk->mutex));
os_mutex_create(&disk->mutex);
disk->remain_len = 0;
disk->prev_lba = 0;
ret = usb_stor_init(*device);
if (ret) {
log_error("usb_stor_init err %d\n", ret);
return -ENODEV;
}
log_debug("device %x", (u32)*device);
usb_h_mutex_pend(host_dev);
if (*device) {
log_error("mass storage dev name %s", name);
disk->dev_status = DEV_OPEN;
usb_h_mutex_post(host_dev);
return DEV_ERR_NONE;
} else {
usb_h_mutex_post(host_dev);
return -ENODEV;
}
}
/**
* @brief usb_stor_close
*
* @param device
*
* @return
*/
static int usb_stor_close(struct device *device)
{
log_debug("%s---%d\n", __func__, __LINE__);
struct usb_host_device *host_dev = device_to_usbdev(device);
struct mass_storage *disk = host_device2disk(host_dev);
int ret;
if (disk->dev_status == DEV_IDLE) {
return 0;
}
log_info("=====================usb_stor_close=====================");
if (disk) {
log_info("=====================usb_stor_close===================== 333");
ret = usb_h_mutex_pend(host_dev);
const usb_dev usb_id = host_device2id(host_dev);
usb_clr_intr_rxe(usb_id, udisk_ep.host_epin);
disk->dev_status = DEV_IDLE;
if (ret != OS_ERR_NONE) {
log_error("disk close pend timeout!!!\n");
} else {
usb_h_mutex_post(host_dev);
}
log_info("=====================usb_stor_close===================== 1222 ");
os_mutex_del(&disk->mutex, 0);
memset(&disk->mutex, 0, sizeof(disk->mutex));
}
return DEV_ERR_NONE;
}
static bool usb_stor_online(const struct dev_node *node)
{
struct device *device = &udisk_device;
struct mass_storage *disk = udisk_inf.dev.disk;;
if (disk) {
return true;//disk->media_sta_cur ? true : false;
}
return false;
}
const struct device_operations mass_storage_ops = {
.init = NULL,
.online = usb_stor_online,
.open = usb_stor_open,
.read = usb_stor_read,
.write = usb_stor_write,
.ioctl = usb_stor_ioctrl,
.close = usb_stor_close,
};
static u8 usb_stor_idle_query(void)
{
struct device *device = &udisk_device;
struct mass_storage *disk = host_device2disk(host_dev);
if (disk) {
return (disk->dev_status == DEV_IDLE) ? true : false;
}
return true;
}
REGISTER_LP_TARGET(usb_stor_lp_target) = {
.name = "udisk",
.is_idle = usb_stor_idle_query,
};
#if 0
u32 usb_host_mount(const usb_dev id, u32 retry, u32 reset_delay, u32 mount_timeout);
extern u8 msd_test_buf[32 * 1024];
void dump_usb_buf();
void usb_host_test()
{
___usb_test:
usb_host_mount(0, 3, 20, 200);
struct device *device;
usb_stor_open("udisk0", &device, NULL);
log_info("%s---%d\n", __func__, __LINE__);
u32 lba = 0;
while (1) {
u32 *p = (u32 *)msd_test_buf;
u32 numOflba = sizeof(msd_test_buf) / 512;
if ((usb_stor_read(device, p, numOflba, lba)) != numOflba) {
printf("read error %d", lba);
while (1);
}
#if 1
if (usb_stor_write(device, p, numOflba, lba) != numOflba) {
printf("write error %d", lba);
while (1);
}
if ((usb_stor_read(device, p, numOflba, lba)) != numOflba) {
printf("read error %d", lba);
while (1);
}
#endif
for (int i = 0; i < numOflba * 512 / 4; i++) {
if (p[i] != (i + lba * 0x80)) {
printf("@lba:%x offset %x %x != %x ", lba, i, p[i], i + lba * 0x80);
/* put_buf(p, numOflba * 512); */
/* while (1); */
}
}
wdt_clear();
lba += numOflba;
}
}
#endif
#endif