/** * @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