fix pingstate for highspeed bulk out transfer
temp implementation of msc host --> can issue inquiry command
This commit is contained in:
+28
-2
@@ -76,6 +76,20 @@ enum {
|
||||
MSC_REQUEST_RESET = 255
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
SCSI_CMD_TEST_UNIT_READY = 0x00,
|
||||
SCSI_CMD_INQUIRY = 0x12,
|
||||
SCSI_CMD_READ_CAPACITY_10 = 0x25,
|
||||
SCSI_CMD_READ_10 = 0x28,
|
||||
SCSI_CMD_WRITE_10 = 0x2A,
|
||||
}scsi_cmd_type_t;
|
||||
|
||||
typedef enum {
|
||||
MSC_CSW_STATUS_PASSED = 0,
|
||||
MSC_CSW_STATUS_FAILED,
|
||||
MSC_CSW_STATUS_PHASE_ERROR
|
||||
}msc_csw_status_t;
|
||||
|
||||
typedef ATTR_PACKED_STRUCT(struct) {
|
||||
uint32_t signature; // const 0x43425355
|
||||
uint32_t tag;
|
||||
@@ -100,6 +114,16 @@ STATIC_ASSERT(sizeof(msc_cmd_status_wrapper_t) == 13, "size is not correct");
|
||||
//--------------------------------------------------------------------+
|
||||
// SCSI Primary Command (SPC-4)
|
||||
//--------------------------------------------------------------------+
|
||||
typedef ATTR_PACKED_STRUCT(struct) {
|
||||
uint8_t operation_code;
|
||||
uint8_t reserve;
|
||||
uint8_t page_code;
|
||||
uint16_t alloc_length;
|
||||
uint8_t control;
|
||||
} scsi_inquiry_t;
|
||||
|
||||
STATIC_ASSERT(sizeof(scsi_inquiry_t) == 6, "size is not correct");
|
||||
|
||||
typedef ATTR_PACKED_STRUCT(struct)
|
||||
{
|
||||
uint8_t peripheral_device_type : 5;
|
||||
@@ -141,9 +165,9 @@ typedef ATTR_PACKED_STRUCT(struct)
|
||||
uint8_t vendor_id[8];
|
||||
uint8_t product_id[16];
|
||||
uint8_t product_revision[4];
|
||||
} msc_scsi_inquiry_t;
|
||||
} scsi_inquiry_data_t;
|
||||
|
||||
STATIC_ASSERT(sizeof(msc_scsi_inquiry_t) == 36, "size is not correct");
|
||||
STATIC_ASSERT(sizeof(scsi_inquiry_data_t) == 36, "size is not correct");
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// SCSI Block Command (SBC-3)
|
||||
@@ -153,6 +177,8 @@ typedef struct {
|
||||
uint8_t block_length[4];
|
||||
} msc_scsi_read_capacity10_t;
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -56,8 +56,12 @@ typedef struct {
|
||||
uint8_t interface_number;
|
||||
uint8_t max_lun;
|
||||
|
||||
uint8_t vendor_id[8];
|
||||
uint8_t product_id[16];
|
||||
|
||||
msc_cmd_block_wrapper_t cbw;
|
||||
msc_cmd_status_wrapper_t csw;
|
||||
uint8_t buffer[100];
|
||||
}msch_interface_t;
|
||||
|
||||
STATIC_VAR msch_interface_t msch_data[TUSB_CFG_HOST_DEVICE_MAX] TUSB_CFG_ATTR_USBRAM; // TODO to be static
|
||||
@@ -70,8 +74,24 @@ STATIC_VAR uint8_t msch_buffer[10] TUSB_CFG_ATTR_USBRAM;
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// IMPLEMENTATION
|
||||
// PUBLIC API
|
||||
//--------------------------------------------------------------------+
|
||||
bool tusbh_msc_is_mounted(uint8_t dev_addr)
|
||||
{
|
||||
return tusbh_device_is_configured(dev_addr) &&
|
||||
pipehandle_is_valid(msch_data[dev_addr-1].bulk_in) &&
|
||||
pipehandle_is_valid(msch_data[dev_addr-1].bulk_out);
|
||||
}
|
||||
|
||||
uint8_t const * tusbh_msc_get_vendor_name(uint8_t dev_addr)
|
||||
{
|
||||
return tusbh_msc_is_mounted(dev_addr) ? msch_data[dev_addr-1].vendor_id : NULL;
|
||||
}
|
||||
|
||||
uint8_t const * tusbh_msc_get_product_name(uint8_t dev_addr)
|
||||
{
|
||||
return tusbh_msc_is_mounted(dev_addr) ? msch_data[dev_addr-1].product_id : NULL;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// CLASS-USBH API (don't require to verify parameters)
|
||||
@@ -123,7 +143,37 @@ tusb_error_t msch_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t con
|
||||
msch_data[dev_addr-1].max_lun = msch_buffer[0];
|
||||
|
||||
//------------- SCSI Inquiry -------------//
|
||||
msch_data[dev_addr-1].cbw = (msc_cmd_block_wrapper_t) {
|
||||
.signature = 0x43425355,
|
||||
.tag = 0xCAFECAFE,
|
||||
.xfer_bytes = sizeof(scsi_inquiry_data_t),
|
||||
.flags = TUSB_DIR_DEV_TO_HOST_MASK,
|
||||
.lun = 0,
|
||||
.cmd_len = sizeof(scsi_inquiry_t),
|
||||
};
|
||||
scsi_inquiry_t cmd_inquiry =
|
||||
{
|
||||
.operation_code = SCSI_CMD_INQUIRY,
|
||||
.alloc_length = sizeof(scsi_inquiry_data_t)
|
||||
};
|
||||
memcpy(msch_data[dev_addr-1].cbw.command, &cmd_inquiry, sizeof(scsi_inquiry_t));
|
||||
|
||||
hcd_pipe_xfer(msch_data[dev_addr-1].bulk_out, &msch_data[dev_addr-1].cbw, sizeof(msc_cmd_block_wrapper_t), false);
|
||||
hcd_pipe_xfer(msch_data[dev_addr-1].bulk_in , msch_data[dev_addr-1].buffer, sizeof(scsi_inquiry_data_t), false);
|
||||
hcd_pipe_xfer(msch_data[dev_addr-1].bulk_in , &msch_data[dev_addr-1].csw, sizeof(msc_cmd_status_wrapper_t), true);
|
||||
|
||||
// TODO timeout required, a proper synchronization
|
||||
// while( !hcd_pipe_is_idle(msch_data[dev_addr-1].bulk_in) )
|
||||
{
|
||||
osal_task_delay(2);
|
||||
}
|
||||
|
||||
memcpy(msch_data[dev_addr-1].vendor_id,
|
||||
((scsi_inquiry_data_t*)msch_data[dev_addr-1].buffer)->vendor_id,
|
||||
8);
|
||||
memcpy(msch_data[dev_addr-1].product_id,
|
||||
((scsi_inquiry_data_t*)msch_data[dev_addr-1].buffer)->product_id,
|
||||
16);
|
||||
|
||||
tusbh_msc_mounted_cb(dev_addr);
|
||||
|
||||
@@ -145,5 +195,19 @@ void msch_close(uint8_t dev_addr)
|
||||
memclr_(&msch_data[dev_addr-1], sizeof(msch_interface_t));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// INTERNAL & HELPER
|
||||
//--------------------------------------------------------------------+
|
||||
//static tusb_error_t scsi_command_send(msc_cmd_block_wrapper_t const * cbw, uint8_t * buffer, msc_cmd_status_wrapper_t const * csw)
|
||||
//{
|
||||
// tusb_error_t error;
|
||||
//
|
||||
// OSAL_SUBTASK_BEGIN
|
||||
//
|
||||
// hcd_pipe_xfer()
|
||||
//
|
||||
// OSAL_SUBTASK_END
|
||||
//}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -58,10 +58,12 @@
|
||||
//--------------------------------------------------------------------+
|
||||
// MASS STORAGE Application API
|
||||
//--------------------------------------------------------------------+
|
||||
bool tusbh_msc_is_supported(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
|
||||
tusb_interface_status_t tusbh_msc_status(uint8_t dev_addr, uint8_t instance_num) ATTR_WARN_UNUSED_RESULT;
|
||||
bool tusbh_msc_is_mounted(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
|
||||
tusb_interface_status_t tusbh_msc_status(uint8_t dev_addr) ATTR_WARN_UNUSED_RESULT;
|
||||
uint8_t const * tusbh_msc_get_vendor_name(uint8_t dev_addr);
|
||||
uint8_t const * tusbh_msc_get_product_name(uint8_t dev_addr);
|
||||
|
||||
tusb_error_t tusbh_msc_inquiry(uint8_t dev_addr, uint8_t instance_num, msc_scsi_inquiry_t * p_inquiry_data) ATTR_WARN_UNUSED_RESULT;
|
||||
tusb_error_t tusbh_msc_inquiry(uint8_t dev_addr, uint8_t instance_num, scsi_inquiry_data_t * p_inquiry_data) ATTR_WARN_UNUSED_RESULT;
|
||||
tusb_error_t tusbh_msc_test_unit_ready(uint8_t dev_addr, uint8_t instance_num) ATTR_WARN_UNUSED_RESULT;
|
||||
tusb_error_t tusbh_msc_read_capacity10(uint8_t dev_addr, uint8_t instance_num, msc_scsi_read_capacity10_t * p_buffer) ATTR_WARN_UNUSED_RESULT;
|
||||
tusb_error_t tusbh_msc_read10(uint8_t dev_addr, uint8_t instance_num, void * p_buffer, uint32_t length) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
+13
-10
@@ -373,6 +373,7 @@ pipe_handle_t hcd_pipe_open(uint8_t dev_addr, tusb_descriptor_endpoint_t const *
|
||||
if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS)
|
||||
return null_handle; // TODO not support ISO yet
|
||||
|
||||
//------------- Prepare Queue Head -------------//
|
||||
ehci_qhd_t * const p_qhd = qhd_find_free(dev_addr);
|
||||
ASSERT_PTR(p_qhd, null_handle);
|
||||
|
||||
@@ -380,6 +381,7 @@ pipe_handle_t hcd_pipe_open(uint8_t dev_addr, tusb_descriptor_endpoint_t const *
|
||||
p_endpoint_desc->bmAttributes.xfer, p_endpoint_desc->bInterval );
|
||||
p_qhd->class_code = class_code;
|
||||
|
||||
//------------- Insert to Async List -------------//
|
||||
ehci_link_t * list_head;
|
||||
|
||||
if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_BULK)
|
||||
@@ -413,11 +415,6 @@ tusb_error_t hcd_pipe_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t t
|
||||
qtd_init(p_qtd, (uint32_t) buffer, total_bytes);
|
||||
p_qtd->pid = p_qhd->pid_non_control;
|
||||
p_qtd->int_on_complete = int_on_complete ? 1 : 0;
|
||||
// do PING for Highspeed Bulk OUT, EHCI section 4.11
|
||||
if (pipe_hdl.xfer_type == TUSB_XFER_BULK && p_qhd->endpoint_speed == TUSB_SPEED_HIGH && p_qtd->pid == EHCI_PID_OUT)
|
||||
{
|
||||
p_qtd->pingstate_err = 1;
|
||||
}
|
||||
|
||||
//------------- insert TD to TD list -------------//
|
||||
qtd_insert_to_qhd(p_qhd, p_qtd);
|
||||
@@ -649,6 +646,7 @@ static void xfer_error_isr(uint8_t hostid)
|
||||
max_loop++;
|
||||
}while(p_qhd != async_head && max_loop < EHCI_MAX_QHD); // async list traversal, stop if loop around
|
||||
|
||||
#if EHCI_PERIODIC_LIST
|
||||
//------------- TODO refractor period list -------------//
|
||||
uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1);
|
||||
for (uint8_t interval_ms=1; interval_ms <= EHCI_FRAMELIST_SIZE; interval_ms *= 2)
|
||||
@@ -682,6 +680,7 @@ static void xfer_error_isr(uint8_t hostid)
|
||||
period_max_loop++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------- Host Controller Driver's Interrupt Handler -------------//
|
||||
@@ -910,6 +909,7 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, uint16_t max_packet_si
|
||||
p_qhd->nak_count_reload = 0;
|
||||
|
||||
// Bulk/Control -> smask = cmask = 0
|
||||
// TODO Isochronous
|
||||
if (TUSB_XFER_INTERRUPT == xfer_type)
|
||||
{
|
||||
if (TUSB_SPEED_HIGH == p_qhd->endpoint_speed)
|
||||
@@ -942,11 +942,6 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, uint16_t max_packet_si
|
||||
p_qhd->hub_port = usbh_devices[dev_addr].hub_port;
|
||||
p_qhd->mult = 1; // TODO not use high bandwidth/park mode yet
|
||||
|
||||
//------------- active, but no TD list -------------//
|
||||
p_qhd->qtd_overlay.halted = 0;
|
||||
p_qhd->qtd_overlay.next.terminate = 1;
|
||||
p_qhd->qtd_overlay.alternate.terminate = 1;
|
||||
|
||||
//------------- HCD Management Data -------------//
|
||||
p_qhd->used = 1;
|
||||
p_qhd->is_removing = 0;
|
||||
@@ -954,6 +949,14 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, uint16_t max_packet_si
|
||||
p_qhd->p_qtd_list_tail = NULL;
|
||||
p_qhd->pid_non_control = (endpoint_addr & 0x80) ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint
|
||||
|
||||
//------------- active, but no TD list -------------//
|
||||
p_qhd->qtd_overlay.halted = 0;
|
||||
p_qhd->qtd_overlay.next.terminate = 1;
|
||||
p_qhd->qtd_overlay.alternate.terminate = 1;
|
||||
if (TUSB_XFER_BULK == xfer_type && p_qhd->endpoint_speed == TUSB_SPEED_HIGH && p_qhd->pid_non_control == EHCI_PID_OUT)
|
||||
{
|
||||
p_qhd->qtd_overlay.pingstate_err = 1; // do PING for Highspeed Bulk OUT, EHCI section 4.11
|
||||
}
|
||||
}
|
||||
|
||||
static void qtd_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t total_bytes)
|
||||
|
||||
Reference in New Issue
Block a user