#include "system/includes.h" #include "usb/device/usb_stack.h" #include "usb/device/msd.h" #include "usb/scsi.h" #include "usb_config.h" #include "device/device.h" #include "app_config.h" #if TCFG_DEV_MANAGER_ENABLE #include "dev_manager.h" #endif #if TCFG_USB_APPLE_DOCK_EN #include "apple_dock/iAP.h" #endif #if TCFG_USB_SLAVE_MSD_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" // *INDENT-OFF* #define USB_MSD_BULK_DEV_USE_ASYNC 1 // Mass Storage Class /*********************************************************/ static const u8 sMassDescriptor[] = { //= MAX_MSD_DEV) { cnt = MAX_MSD_DEV; } return cnt; } u32 msd_set_wakeup_handle(void (*handle)(struct usb_device_t *usb_device)) { if (msd_handle) { msd_handle->info.msd_wakeup_handle = handle; return 1; } return 0; } static void msd_wakeup(struct usb_device_t *usb_device, u32 ep) { if ((msd_handle) && (msd_handle->info.msd_wakeup_handle)) { msd_handle->info.msd_wakeup_handle(usb_device); } } static u8 get_cardreader_popup(u32 lun) { return msd_handle->info.bDisk_popup[lun];//弹出 } static void set_cardreader_popup(u32 lun, u8 status) { if (msd_handle->info.dev_handle[lun] != NULL) { msd_handle->info.bDisk_popup[lun] = status;//弹出 } } static void recover_set_cardreader_popup(u32 lun) { if (msd_handle->info.dev_handle[lun] != NULL) { msd_handle->info.bDisk_popup[lun] = 0;//未弹出 } } static void msd_endpoint_init(struct usb_device_t *usb_device, u32 itf) { const usb_dev usb_id = usb_device2id(usb_device); usb_g_ep_config(usb_id, MSD_BULK_EP_IN | USB_DIR_IN, USB_ENDPOINT_XFER_BULK, 0, msd_handle->ep_out_dmabuffer, MAXP_SIZE_BULKIN); usb_g_ep_config(usb_id, MSD_BULK_EP_OUT, USB_ENDPOINT_XFER_BULK, 1, msd_handle->ep_out_dmabuffer, MAXP_SIZE_BULKOUT); usb_g_set_intr_hander(usb_id, MSD_BULK_EP_OUT, msd_wakeup); usb_enable_ep(usb_id, MSD_BULK_EP_IN); } static void msd_reset_wakeup(struct usb_device_t *usb_device, u32 itf_num) { const usb_dev usb_id = usb_device2id(usb_device); if (msd_handle && msd_handle->info.msd_reset_wakeup_handle) { msd_handle->info.msd_reset_wakeup_handle(usb_device, itf_num); } } void msd_set_reset_wakeup_handle(void (*handle)(struct usb_device_t *usb_device, u32 itf_num)) { if (msd_handle) { msd_handle->info.msd_reset_wakeup_handle = handle; } } void msd_reset(struct usb_device_t *usb_device, u32 itf_num) { const usb_dev usb_id = usb_device2id(usb_device); log_debug("%s", __func__); #if USB_ROOT2 usb_disable_ep(usb_id, MSD_BULK_EP_OUT); #else msd_endpoint_init(usb_device, itf_num); #endif } static void *check_disk_status(u8 cur_lun) { u32 ret; u32 online_status; void *dev_fd = msd_handle->info.dev_handle[cur_lun] ; const char *dev_name = msd_handle->info.dev_name[cur_lun]; #if TCFG_DEV_MANAGER_ENABLE if (dev_manager_list_check_by_logo((char *)dev_name)) { if (dev_fd == NULL) { msd_handle->info.dev_handle[cur_lun] = dev_open(dev_name, NULL); } else { //FIXME:need add device state check?? u32 dev_online = 0; ret = dev_ioctl(dev_fd, IOCTL_GET_STATUS, (u32)&dev_online); if (ret || !dev_online) { goto __dev_offline; } } if (get_cardreader_popup(cur_lun)) { return NULL; } } else { if (dev_fd) { goto __dev_offline; } } #else if (dev_fd == NULL) { msd_handle->info.dev_handle[cur_lun] = dev_open(dev_name, NULL); } else { u32 dev_online = 0; ret = dev_ioctl(dev_fd, IOCTL_GET_STATUS, (u32)&dev_online); if (ret || !dev_online) { goto __dev_offline; } } #endif return msd_handle->info.dev_handle[cur_lun]; __dev_offline: dev_close(dev_fd); recover_set_cardreader_popup(cur_lun); msd_handle->info.dev_handle[cur_lun] = NULL; return NULL; } static u32 msd_itf_hander(struct usb_device_t *usb_device, struct usb_ctrlrequest *setup) { u32 tx_len; u8 *tx_payload = usb_get_setup_buffer(usb_device); u32 bRequestType = setup->bRequestType & USB_TYPE_MASK; switch (bRequestType) { case USB_TYPE_STANDARD: switch (setup->bRequest) { case USB_REQ_GET_STATUS: usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP); break; case USB_REQ_GET_INTERFACE: tx_len = 1; u8 i = 0; usb_set_data_payload(usb_device, setup, &i, tx_len); break; case USB_REQ_SET_INTERFACE: usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP); break; default: break; } break; case USB_TYPE_CLASS: switch (setup->bRequest) { case USB_MSD_MAX_LUN: msd_endpoint_init(usb_device, -1); tx_len = 1; tx_payload[0] = __get_max_msd_dev() - 1; usb_set_data_payload(usb_device, setup, tx_payload, tx_len); break; case USB_MSD_RESET : usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP); break; default: break; } break; default: break; } return 0; } u32 msd_desc_config(const usb_dev usb_id, u8 *ptr, u32 *cur_itf_num) { log_debug("%s() %d", __func__, *cur_itf_num); memcpy(ptr, sMassDescriptor, sizeof(sMassDescriptor)); ptr[2] = *cur_itf_num; #if TCFG_USB_APPLE_DOCK_EN if (apple_mfi_chip_online_lib()) { ptr[5] = 0xff; //bInterfaceClass:Vendor-Specific ptr[6] = 0xf0; //bInterfaceSubClass:MFi Accessory ptr[7] = 0x00; //bInterfaceProtocol */ ptr[8] = MSD_STR_INDEX; //bInterfaceString*/ } #endif if (usb_set_interface_hander(usb_id, *cur_itf_num, msd_itf_hander) != *cur_itf_num) { } if (usb_set_reset_hander(usb_id, *cur_itf_num, msd_reset_wakeup) != *cur_itf_num) { } *cur_itf_num = *cur_itf_num + 1; return sizeof(sMassDescriptor); } u32 msd_usb2mcu(const struct usb_device_t *usb_device, u8 *buffer, u32 len) { usb_dev usb_id = usb_device2id(usb_device); return usb_g_bulk_read(usb_id, MSD_BULK_EP_OUT, buffer, len, 1); } u32 msd_mcu2usb(const struct usb_device_t *usb_device, const u8 *buffer, u32 len) { usb_dev usb_id = usb_device2id(usb_device); return usb_g_bulk_write(usb_id, MSD_BULK_EP_IN, buffer, len); } static u32 msd_usb2mcu_64byte_fast(const struct usb_device_t *usb_device, u8 *buffer, u32 len) { usb_dev usb_id = usb_device2id(usb_device); return usb_g_bulk_read64byte_fast(usb_id, MSD_BULK_EP_OUT, buffer, len); } static u32 get_cbw(const struct usb_device_t *usb_device) { msd_handle->cbw.dCBWSignature = 0; memset((u8 *)(&(msd_handle->cbw)), 0, sizeof(struct usb_scsi_cbw)); u32 rx_len = msd_usb2mcu(usb_device, (u8 *)(&(msd_handle->cbw)), sizeof(struct usb_scsi_cbw)); if (rx_len == 0) { return 1; } if (msd_handle->cbw.dCBWSignature ^ CBW_SIGNATURE) { if ((msd_handle->cbw.dCBWSignature ^ CBW_SIGNATURE) != CBW_SIGNATURE) { } return 1; } msd_handle->csw.dCSWTag = msd_handle->cbw.dCBWTag; msd_handle->csw.uCSWDataResidue = msd_handle->cbw.dCBWDataTransferLength; return 0; } static void inquiry(const struct usb_device_t *usb_device) { u32 err; u32 len = min(msd_handle->csw.uCSWDataResidue, sizeof(SCSIInquiryData)); u32 scsiinquirydata[sizeof(SCSIInquiryData) / 4]; //usb dma 不能访问code区域 memcpy(scsiinquirydata, SCSIInquiryData, sizeof(SCSIInquiryData)); err = msd_mcu2usb(usb_device, scsiinquirydata, len); if (err == 0) { log_error("write usb err %d", __LINE__); } msd_handle->csw.uCSWDataResidue -= len; msd_handle->csw.bCSWStatus = 0; } static void send_csw(const struct usb_device_t *usb_device) { u32 err; msd_handle->csw.dCSWSignature = CSW_SIGNATURE; err = msd_mcu2usb(usb_device, (u8 *) & (msd_handle->csw), sizeof(struct usb_scsi_csw)); if (err == 0) { log_error("write usb err %d", __LINE__); } } static void stall_inep(const struct usb_device_t *usb_device) { const usb_dev usb_id = usb_device2id(usb_device); usb_write_txcsr(usb_id, MSD_BULK_EP_IN, TXCSRP_SendStall); u32 ot = 2000; while (1) { if (ot-- == 0) { break; } if (usb_otg_online(usb_id) == DISCONN_MODE) { break; } if ((usb_read_txcsr(usb_id, MSD_BULK_EP_IN) & TXCSRP_SendStall) == 0) { break; } } } static void stall_outep(const struct usb_device_t *usb_device) { const usb_dev usb_id = usb_device2id(usb_device); usb_write_rxcsr(usb_id, MSD_BULK_EP_OUT, RXCSRP_SendStall); u32 ot = 2000; while (1) { if (ot-- == 0) { break; } if (usb_otg_online(usb_id) == DISCONN_MODE) { break; } if ((usb_read_rxcsr(usb_id, MSD_BULK_EP_OUT) & RXCSRP_SendStall) == 0) { break; } } } static void unknow(const struct usb_device_t *usb_device, u8 rw) { if (rw) { stall_outep(usb_device); } else { stall_inep(usb_device); } msd_handle->csw.uCSWDataResidue = 0; msd_handle->csw.bCSWStatus = 0x01; msd_handle->info.bError = 0x1; /* msd_handle->info.bError = 0x2; */ } static void stall_error(const struct usb_device_t *usb_device, u8 rw, u8 error) { msd_handle->csw.bCSWStatus = 0x01; unknow(usb_device, rw); msd_handle->info.bError = error; } static void test_unit_ready(const struct usb_device_t *usb_device) { int err; u8 cur_lun = msd_handle->cbw.bCBWLUN; if (NULL == check_disk_status(cur_lun)) { msd_handle->csw.bCSWStatus = 0x1; msd_handle->info.bError = 0x0f; } else { msd_handle->csw.uCSWDataResidue = 0; msd_handle->csw.bCSWStatus = 0x0; } } static void allow_medium_removal(const struct usb_device_t *usb_device) { msd_handle->csw.bCSWStatus = 0x0; if (msd_handle->cbw.lba[2]) { msd_handle->info.bError = 0x02; msd_handle->csw.bCSWStatus = 0x01; } msd_handle->csw.uCSWDataResidue = 0; } static void request_sense(const struct usb_device_t *usb_device) { u32 err; u32 len; u8 sense_data[0x12]; len = min(msd_handle->csw.uCSWDataResidue, 0x12); if (msd_handle->csw.uCSWDataResidue == 0) { stall_inep(usb_device); msd_handle->info.bError = NOT_READY; msd_handle->csw.uCSWDataResidue = 0; msd_handle->csw.bCSWStatus = 0x01; return; } else { memset(sense_data, 0x0, sizeof(sense_data)); sense_data[2] = msd_handle->info.bSenseKey; sense_data[12] = msd_handle->info.bAdditionalSenseCode; sense_data[13] = msd_handle->info.bAddiSenseCodeQualifier; sense_data[0] = 0x70; sense_data[7] = 0x0a; err = msd_mcu2usb(usb_device, sense_data, len); if (err == 0) { log_error("write usb err %d", __LINE__); } } msd_handle->csw.uCSWDataResidue -= len; msd_handle->csw.bCSWStatus = 0; } static u8 const scsi_mode_sense[4] = { 0x03, 0x00, 0x00, 0x00 }; static void mode_sense(const struct usb_device_t *usb_device) { u32 err; u32 sense; err = msd_mcu2usb(usb_device, (u8 *)scsi_mode_sense, sizeof(scsi_mode_sense)); if (err == 0) { log_error("write usb err %d", __LINE__); } msd_handle->csw.uCSWDataResidue = 0; msd_handle->csw.bCSWStatus = 0; } static void verify(const struct usb_device_t *usb_device) { msd_handle->csw.uCSWDataResidue = 0; msd_handle->csw.bCSWStatus = 0; } #if USB_MSD_BULK_DEV_USE_ASYNC static void msd_write_10_async(const struct usb_device_t *usb_device, u8 cur_lun, u32 lba, u16 lba_num) { u32 err = 0; u16 num = 0; u8 buf_idx = 0; u32 have_send_stall = FALSE; void *dev_fd = NULL; while (lba_num) { wdt_clear(); num = lba_num > MSD_BLOCK_SIZE ? MSD_BLOCK_SIZE : lba_num; if (msd_handle->csw.uCSWDataResidue == 0) { msd_handle->csw.bCSWStatus = 1; break; } if (msd_handle->csw.uCSWDataResidue >= num * 0x200) { msd_handle->csw.uCSWDataResidue -= num * 0x200; } err = msd_usb2mcu_64byte_fast(usb_device, msd_handle->msd_buf + buf_idx * MSD_BUFFER_SIZE, num * 0x200); if (err != num * 0x200) { log_error("read usb_err %d, dev = %s", __LINE__, msd_handle->info.dev_name[cur_lun]); stall_error(usb_device, 1, MEDIUM_ERROR); have_send_stall = TRUE; break; } dev_fd = check_disk_status(cur_lun); if (dev_fd) { dev_ioctl(dev_fd, IOCTL_SET_ASYNC_MODE, 0); err = dev_bulk_write(dev_fd, msd_handle->msd_buf + buf_idx * MSD_BUFFER_SIZE, lba, num); if (err != num) { log_error("write_10 write fail, %d, dev = %s", err, msd_handle->info.dev_name[cur_lun]); stall_error(usb_device, 1, MEDIUM_ERROR); have_send_stall = TRUE; break; } } else { log_error("write_10 disk offline, dev = %s", msd_handle->info.dev_name[cur_lun]); stall_error(usb_device, 1, MEDIUM_ERROR); have_send_stall = TRUE; break; } buf_idx = !buf_idx; lba_num -= num; lba += num; } dev_fd = check_disk_status(cur_lun); if (dev_fd) { //async mode last block flush dev_ioctl(dev_fd, IOCTL_FLUSH, 0); } else { if (have_send_stall == FALSE) { log_error("write_10 disk offline while sync, dev = %s", msd_handle->info.dev_name[cur_lun]); stall_error(usb_device, 1, MEDIUM_ERROR); } } } static void msd_read_10_async(const struct usb_device_t *usb_device, u8 cur_lun, u32 lba, u16 lba_num) { u32 err = 0; u16 num = 0; u8 buf_idx = 0; u32 last_lba = 0, last_num = 0; void *dev_fd = NULL; if (lba_num == 0) { log_error("lba_num == 0\n"); stall_error(usb_device, 0, 0x02); return; } num = lba_num > MSD_BLOCK_SIZE ? MSD_BLOCK_SIZE : lba_num; dev_fd = check_disk_status(cur_lun); if (dev_fd) { dev_ioctl(dev_fd, IOCTL_SET_ASYNC_MODE, 0); err = dev_bulk_read(dev_fd, msd_handle->msd_buf + buf_idx * MSD_BUFFER_SIZE, lba, num); if (err != num) { log_error("read disk error0 = %d, dev = %s\n", err, msd_handle->info.dev_name[cur_lun]); stall_error(usb_device, 0, MEDIUM_ERROR); return; } } else { log_error("read_10 disk offline, dev = %s\n", msd_handle->info.dev_name[cur_lun]); stall_error(usb_device, 0, MEDIUM_ERROR); return; } while (lba_num) { wdt_clear(); last_num = num; last_lba = lba; buf_idx = !buf_idx; lba += num; lba_num -= num; num = lba_num > MSD_BLOCK_SIZE ? MSD_BLOCK_SIZE : lba_num; if (msd_handle->csw.uCSWDataResidue == 0) { msd_handle->csw.bCSWStatus = 1; break; } if (msd_handle->csw.uCSWDataResidue >= last_num * 0x200) { msd_handle->csw.uCSWDataResidue -= last_num * 0x200; } dev_fd = check_disk_status(cur_lun); if (dev_fd) { if (num) { dev_ioctl(dev_fd, IOCTL_SET_ASYNC_MODE, 0); err = dev_bulk_read(dev_fd, msd_handle->msd_buf + buf_idx * MSD_BUFFER_SIZE, lba, num); if (err != num) { log_error("read disk error1 = %d, dev = %s", err, msd_handle->info.dev_name[cur_lun]); stall_error(usb_device, 0, MEDIUM_ERROR); break; } } else { //async mode last block flush dev_ioctl(dev_fd, IOCTL_FLUSH, 0); } } else { log_error("read_10 disk offline, dev = %s", msd_handle->info.dev_name[cur_lun]); stall_error(usb_device, 0, MEDIUM_ERROR); break; } err = msd_mcu2usb(usb_device, msd_handle->msd_buf + !buf_idx * MSD_BUFFER_SIZE, last_num * 0x200); if (err != last_num * 0x200) { log_error("read_10 data transfer err %d, dev = %s", __LINE__, msd_handle->info.dev_name[cur_lun]); stall_error(usb_device, 0, 0x05); if (num) { dev_ioctl(dev_fd, IOCTL_FLUSH, 0); } break; } } } #endif static u32 read_32(u8 *p) { return ((u32)(p[0]) << 24) | ((u32)(p[1]) << 16) | ((u32)(p[2]) << 8) | (p[3]); } static void write_10(const struct usb_device_t *usb_device) { u32 err = 0 ; u32 lba; u16 lba_num; u16 num = 0; lba = read_32(msd_handle->cbw.lba); lba_num = ((u16)(msd_handle->cbw.LengthH) << 8) | (msd_handle->cbw.LengthL); u8 cur_lun = msd_handle->cbw.bCBWLUN; void *dev_fd = msd_handle->info.dev_handle[cur_lun]; /* app_status_handler(APP_STATUS_PC_COPY); */ #if USB_MSD_BULK_DEV_USE_ASYNC /* u32 old_speed; */ /* dev_fd = check_disk_status(cur_lun); */ /* if (dev_fd) { */ /* dev_ioctl(dev_fd, IOCTL_GET_SPEED, (u32)&old_speed); */ /* dev_ioctl(dev_fd, IOCTL_SET_SPEED, 48000000); */ /* } */ msd_write_10_async(usb_device, cur_lun, lba, lba_num); /* if (dev_fd) { */ /* dev_ioctl(dev_fd, IOCTL_SET_SPEED, old_speed); */ /* } */ #else while (lba_num) { wdt_clear(); num = lba_num > MSD_BLOCK_SIZE ? MSD_BLOCK_SIZE : lba_num; if (msd_handle->csw.uCSWDataResidue == 0) { msd_handle->csw.bCSWStatus = 0x1; break; } if (msd_handle->csw.uCSWDataResidue >= (num * 0x200)) { msd_handle->csw.uCSWDataResidue -= (num * 0x200); } err = msd_usb2mcu_64byte_fast(usb_device, msd_handle->msd_buf, num * 0x200); if (err == 0) { stall_error(usb_device, 1, MEDIUM_ERROR); log_error("read usb, dev = %s", err, msd_handle->info.dev_name[cur_lun]); break; } dev_fd = check_disk_status(cur_lun); if (dev_fd) { dev_ioctl(dev_fd, IOCTL_CMD_RESUME, 0); err = dev_bulk_write(dev_fd, msd_handle->msd_buf, lba, num); dev_ioctl(dev_fd, IOCTL_CMD_SUSPEND, 0); if (err != num) { stall_error(usb_device, 1, MEDIUM_ERROR); log_error("write disk error =%d, dev = %s", err, msd_handle->info.dev_name[cur_lun]); break; } else { break; } lba += num; lba_num -= num; } else { log_error("write disk offline, dev = %s", msd_handle->info.dev_name[cur_lun]); stall_error(usb_device, 1, MEDIUM_ERROR); break; } } #endif } static void read_10(const struct usb_device_t *usb_device) { u32 err = 0; u32 lba; u16 lba_num; u16 num = 0; lba = read_32(msd_handle->cbw.lba); lba_num = ((u16)(msd_handle->cbw.LengthH) << 8) | (msd_handle->cbw.LengthL); u8 cur_lun = msd_handle->cbw.bCBWLUN; void *dev_fd = msd_handle->info.dev_handle[cur_lun]; #if USB_MSD_BULK_DEV_USE_ASYNC msd_read_10_async(usb_device, cur_lun, lba, lba_num); #else while (lba_num) { wdt_clear(); num = lba_num > MSD_BLOCK_SIZE ? MSD_BLOCK_SIZE : lba_num; if (msd_handle->csw.uCSWDataResidue == 0) { msd_handle->csw.bCSWStatus = 0x1; break; } if (msd_handle->csw.uCSWDataResidue >= (num * 0x200)) { msd_handle->csw.uCSWDataResidue -= (num * 0x200); } dev_fd = check_disk_status(cur_lun); if (dev_fd) { dev_ioctl(dev_fd, IOCTL_CMD_RESUME, 0); err = dev_bulk_read(dev_fd, msd_handle->msd_buf, lba, num); dev_ioctl(dev_fd, IOCTL_CMD_SUSPEND, 0); if (err != num) { log_error("read disk error =%d, dev = %s", err, msd_handle->info.dev_name[cur_lun]); stall_error(usb_device, 0, MEDIUM_ERROR); break; } } else { log_error("read disk offline, dev = %s", err, msd_handle->info.dev_name[cur_lun]); stall_error(usb_device, 0, MEDIUM_ERROR); break; } err = msd_mcu2usb(usb_device, msd_handle->msd_buf, num * 0x200); if (err == 0) { log_error("write usb err %d, dev = %s", __LINE__, msd_handle->info.dev_name[cur_lun]); stall_error(usb_device, 0, MEDIUM_ERROR); break; } lba += num; lba_num -= num; } #endif } static void read_capacity(const struct usb_device_t *usb_device) { u32 err; u32 capacity_temp; u8 capacity[8] = {0}; u8 cur_lun = msd_handle->cbw.bCBWLUN; void *dev_fd = check_disk_status(cur_lun); if (!dev_fd) { stall_error(usb_device, 0, 0x0f); return; } dev_ioctl(dev_fd, IOCTL_GET_CAPACITY, (u32)&capacity_temp); capacity_temp = cpu_to_be32(capacity_temp - 1); memcpy(capacity, &capacity_temp, 4); dev_ioctl(dev_fd, IOCTL_GET_BLOCK_SIZE, (u32)&capacity_temp); /* r_printf(">>>[test]:capacity_temp2 = %d\n", capacity_temp); */ capacity_temp = cpu_to_be32(capacity_temp); memcpy(&capacity[4], &capacity_temp, 4); err = msd_mcu2usb(usb_device, capacity, 8); if (err == 0) { log_error("write usb err %d", __LINE__); } msd_handle->csw.uCSWDataResidue = 0; msd_handle->csw.bCSWStatus = 0; } static void read_format_capacity(const struct usb_device_t *usb_device) { u32 err; u8 capacity[12] = {0}; u32 capacity_temp; u8 cur_lun = msd_handle->cbw.bCBWLUN; void *dev_fd = check_disk_status(cur_lun); if (!dev_fd) { stall_error(usb_device, 0, 0x0f); return; } dev_ioctl(dev_fd, IOCTL_GET_CAPACITY, (u32)&capacity_temp); capacity_temp = cpu_to_be32(capacity_temp); memcpy(&capacity[4], &capacity_temp, 4); dev_ioctl(dev_fd, IOCTL_GET_BLOCK_SIZE, (u32)&capacity_temp); capacity_temp = cpu_to_be32(capacity_temp); memcpy(&capacity[8], &capacity_temp, 4); capacity[3] = 0x08; capacity[8] = 0x02; err = msd_mcu2usb(usb_device, capacity, 12); if (err == 0) { log_error("write usb err %d", __LINE__); } msd_handle->csw.uCSWDataResidue -= 12; msd_handle->csw.bCSWStatus = 0; } static void stop_start() { int i; u8 loej, start; /* set_cardreader_popup(0, !(msd_handle->cbw.lba[2])); */ loej = msd_handle->cbw.lba[2] & BIT(1); start = msd_handle->cbw.lba[2] & BIT(0); for (i = 0; i < __get_max_msd_dev(); i++) { if (loej && !start) { set_cardreader_popup(i, 1); } else if (loej && start) { set_cardreader_popup(i, 0); } } msd_handle->csw.uCSWDataResidue = 0; msd_handle->csw.bCSWStatus = 0x0; } u32 private_scsi_cmd(const struct usb_device_t *usb_device, struct usb_scsi_cbw *cbw); void USB_MassStorage(const struct usb_device_t *usb_device) { const usb_dev usb_id = usb_device2id(usb_device); usb_clr_intr_rxe(usb_id, MSD_BULK_EP_OUT); if (get_cbw(usb_device)) { usb_set_intr_rxe(usb_id, MSD_BULK_EP_OUT); return; } /* log_debug("opcode %x", msd_handle->cbw.operationCode); */ if (private_scsi_cmd(usb_device, &(msd_handle->cbw))) { msd_handle->info.bError = 0; msd_handle->csw.uCSWDataResidue = 0; msd_handle->csw.bCSWStatus = 0x0; } else { wdt_clear(); switch (msd_handle->cbw.operationCode) { case INQUIRY://0x12 inquiry(usb_device); break; case TEST_UNIT_READY://0x00 test_unit_ready(usb_device); break; case VERIFY://0x2f verify(usb_device); break; case ALLOW_MEDIUM_REMOVAL://0x1e allow_medium_removal(usb_device); break; case REQUEST_SENSE://0x03 request_sense(usb_device); break; case MODE_SENSE://0x1a mode_sense(usb_device); break; case READ_10://0x28 read_10(usb_device); break; case WRITE_10://0x2a write_10(usb_device); break; case READ_CAPACITY://0x25 read_capacity(usb_device); break; case READ_FORMAT_CAPACITIES://0x23 read_format_capacity(usb_device); break; case START_STOP://0x1b stop_start(); break; default: log_error("opcode %x", msd_handle->cbw.operationCode); stall_error(usb_device, 0, !(msd_handle->cbw.bmCBWFlags & 0x80)); break; } } switch (msd_handle->info.bError) { case 0x00: msd_handle->info.bSenseKey = NO_SENSE; msd_handle->info.bAdditionalSenseCode = ASC_NO_ADDITIONAL_SENSE_INFORMATION; msd_handle->info.bAddiSenseCodeQualifier = ASCQ_NO_ADDITIONAL_SENSE_INFORMATION; break; case 0x02: msd_handle->info.bSenseKey = ILLEGAL_REQUEST; msd_handle->info.bAdditionalSenseCode = ASC_INVALID_FIELD_IN_COMMAND_PACKET; msd_handle->info.bAddiSenseCodeQualifier = ASCQ_INVALID_FIELD_IN_COMMAND_PACKET; break; case MEDIUM_ERROR: msd_handle->info.bSenseKey = MEDIUM_ERROR; msd_handle->info.bAdditionalSenseCode = ASC_WRITE_FAULT; msd_handle->info.bAddiSenseCodeQualifier = ASCQ_WRITE_FAULT; break; case 0x0f: case 0x05: msd_handle->info.bSenseKey = NOT_READY; msd_handle->info.bAdditionalSenseCode = ASC_MEDIUM_PRESENT; msd_handle->info.bAddiSenseCodeQualifier = ASCQ_MEDIUM_PRESENT; break; case 0x06: msd_handle->info.bSenseKey = ABORTED_COMMAND; msd_handle->info.bAdditionalSenseCode = ASC_INVALID_COMMAND_OPERATION_CODE; msd_handle->info.bAddiSenseCodeQualifier = ASCQ_INVALID_COMMAND_OPERATION_CODE; break; } usb_set_intr_rxe(usb_id, MSD_BULK_EP_OUT); send_csw(usb_device); } u32 msd_register_disk(const char *name, void *arg) { int i; u32 len, ret = -1; if (msd_handle) { for (i = 0; i < __get_max_msd_dev(); i++) { if (msd_handle->info.dev_name[i][0] == 0) { ASSERT(strlen(name) <= MSD_DEV_NAME_LEN, "MSD_DEV_NAME_LEN too small"); strcpy(msd_handle->info.dev_name[i], name); msd_handle->info.dev_handle[i] = NULL; break; } } if (i == __get_max_msd_dev()) { ret = -3; } } return ret; } u32 msd_unregister_disk(const char *name) { u32 err; int i; if (msd_handle) { for (i = 0; i < __get_max_msd_dev(); i++) { if (!strcmp(msd_handle->info.dev_name[i], name)) { msd_handle->info.dev_name[i][0] = 0; return 0; } } } return -1; } u32 msd_unregister_all() { u32 err; int i; if (msd_handle) { for (i = 0; i < __get_max_msd_dev(); i++) { if (msd_handle->info.dev_handle[i]) { err = dev_close(msd_handle->info.dev_handle[i]); msd_handle->info.dev_handle[i] = NULL; /* memset(msd_handle->info.dev_name[i], 0, MSD_DEV_NAME_LEN); */ } } } return 0; } u32 msd_register(const usb_dev usb_id) { if (msd_handle == NULL) { #if USB_MALLOC_ENABLE msd_handle = (struct usb_msd_handle *)zalloc(sizeof(struct usb_msd_handle)); if (msd_handle == NULL) { log_error("msd_register err"); return -1; } #if USB_MSD_BULK_DEV_USE_ASYNC msd_handle->msd_buf = (u8 *)malloc(MSD_BUFFER_SIZE * 2); #else msd_handle->msd_buf = (u8 *)malloc(MSD_BUFFER_SIZE); #endif if (msd_handle->msd_buf == NULL) { log_error("msd_register err"); return -1; } #else memset(&_msd_handle, 0, sizeof(struct usb_msd_handle)); _msd_handle.msd_buf = msd_buf; msd_handle = &_msd_handle; #endif log_info("msd_handle = %x", msd_handle); msd_handle->ep_out_dmabuffer = usb_alloc_ep_dmabuffer(usb_id, MSD_BULK_EP_OUT, MAXP_SIZE_BULKIN + MAXP_SIZE_BULKOUT); } return 0; } u32 msd_release() { if (msd_handle) { for (int i = 0; i < __get_max_msd_dev(); i++) { void *dev_fd = msd_handle->info.dev_handle[i] ; if (dev_fd) { dev_close(dev_fd); msd_handle->info.dev_handle[i] = NULL; } } #if USB_MALLOC_ENABLE if (msd_handle->msd_buf) { free(msd_handle->msd_buf); msd_handle->msd_buf = NULL; } free(msd_handle); #endif msd_handle = NULL; } return 0; } #if TCFG_USB_APPLE_DOCK_EN int usb_g_ep_read_check(const usb_dev id, u32 ep, u32 rx_len) { if (apple_mfi_chip_online_lib()) { if (ep != MSD_BULK_EP_OUT) { return 0; } u32 dma_size = usb_get_dma_size(id, ep); /* printf("dma:%d, rl:%d, ep:%d \n", dma_size, rx_len, ep); */ if (rx_len < dma_size) { return -1; } } return 0; } void apple_usb_msd_wakeup(struct usb_device_t *usb_device) { msd_wakeup(usb_device, MSD_BULK_EP_IN); } u8 MCU_SRAMToUSB_app(void *hdl, u8 *pBuf, u16 uCount) { return msd_mcu2usb(hdl, pBuf, uCount); } u8 MCU_USBToSRAM_app(void *hdl, u8 *pBuf, u16 uCount) { /* return msd_usb2mcu(hdl, pBuf, uCount); */ usb_dev usb_id = usb_device2id(hdl); int ret; int cnt = 10000; while (cnt--) { ret = usb_g_bulk_read(usb_id, MSD_BULK_EP_OUT, pBuf, uCount, 0); if (ret) { break; } } // printf("%s,%d, ret:%d, cnt:%d \n", __func__, __LINE__, ret, cnt); // put_buf(pBuf, ret); return ret; } #endif #endif