Merge remote-tracking branch 'upstream/master' into edpt_ISO_xfer
Conflicts: src/common/tusb_fifo.h src/osal/osal_none.h
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
||||
@@ -277,7 +277,7 @@ typedef struct TU_ATTR_PACKED
|
||||
struct {
|
||||
uint8_t handle_call : 1; ///< 0 - Device sends/receives call management information only over the Communications Class interface. 1 - Device can send/receive call management information over a Data Class interface.
|
||||
uint8_t send_recv_call : 1; ///< 0 - Device does not handle call management itself. 1 - Device handles call management itself.
|
||||
uint8_t : 0;
|
||||
uint8_t TU_RESERVED : 6;
|
||||
} bmCapabilities;
|
||||
|
||||
uint8_t bDataInterface;
|
||||
@@ -290,7 +290,7 @@ typedef struct TU_ATTR_PACKED
|
||||
uint8_t support_line_request : 1; ///< Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State.
|
||||
uint8_t support_send_break : 1; ///< Device supports the request Send_Break
|
||||
uint8_t support_notification_network_connection : 1; ///< Device supports the notification Network_Connection.
|
||||
uint8_t : 0;
|
||||
uint8_t TU_RESERVED : 4;
|
||||
}cdc_acm_capability_t;
|
||||
|
||||
TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler");
|
||||
@@ -316,7 +316,7 @@ typedef struct TU_ATTR_PACKED
|
||||
uint8_t require_pulse_setup : 1; ///< Device requires extra Pulse_Setup request during pulse dialing sequence to disengage holding circuit.
|
||||
uint8_t support_aux_request : 1; ///< Device supports the request combination of Set_Aux_Line_State, Ring_Aux_Jack, and notification Aux_Jack_Hook_State.
|
||||
uint8_t support_pulse_request : 1; ///< Device supports the request combination of Pulse_Setup, Send_Pulse, and Set_Pulse_Time.
|
||||
uint8_t : 0;
|
||||
uint8_t TU_RESERVED : 5;
|
||||
} bmCapabilities;
|
||||
}cdc_desc_func_direct_line_management_t;
|
||||
|
||||
@@ -344,7 +344,7 @@ typedef struct TU_ATTR_PACKED
|
||||
uint8_t simple_mode : 1;
|
||||
uint8_t standalone_mode : 1;
|
||||
uint8_t computer_centric_mode : 1;
|
||||
uint8_t : 0;
|
||||
uint8_t TU_RESERVED : 5;
|
||||
} bmCapabilities;
|
||||
}cdc_desc_func_telephone_operational_modes_t;
|
||||
|
||||
@@ -363,7 +363,7 @@ typedef struct TU_ATTR_PACKED
|
||||
uint32_t incoming_distinctive : 1; ///< 0 : Reports only incoming ringing. 1 : Reports incoming distinctive ringing patterns.
|
||||
uint32_t dual_tone_multi_freq : 1; ///< 0 : Cannot report dual tone multi-frequency (DTMF) digits input remotely over the telephone line. 1 : Can report DTMF digits input remotely over the telephone line.
|
||||
uint32_t line_state_change : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notification
|
||||
uint32_t : 0;
|
||||
uint32_t TU_RESERVED : 26;
|
||||
} bmCapabilities;
|
||||
}cdc_desc_func_telephone_call_state_reporting_capabilities_t;
|
||||
|
||||
|
||||
@@ -114,15 +114,15 @@ static void _prep_out_transaction (midid_interface_t* p_midi)
|
||||
//--------------------------------------------------------------------+
|
||||
// READ API
|
||||
//--------------------------------------------------------------------+
|
||||
uint32_t tud_midi_n_available(uint8_t itf, uint8_t jack_id)
|
||||
uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num)
|
||||
{
|
||||
(void) jack_id;
|
||||
(void) cable_num;
|
||||
return tu_fifo_count(&_midid_itf[itf].rx_ff);
|
||||
}
|
||||
|
||||
uint32_t tud_midi_n_read(uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bufsize)
|
||||
uint32_t tud_midi_n_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize)
|
||||
{
|
||||
(void) jack_id;
|
||||
(void) cable_num;
|
||||
midid_interface_t* midi = &_midid_itf[itf];
|
||||
|
||||
// Fill empty buffer
|
||||
@@ -158,9 +158,9 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bu
|
||||
return n;
|
||||
}
|
||||
|
||||
void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id)
|
||||
void tud_midi_n_read_flush (uint8_t itf, uint8_t cable_num)
|
||||
{
|
||||
(void) jack_id;
|
||||
(void) cable_num;
|
||||
midid_interface_t* p_midi = &_midid_itf[itf];
|
||||
tu_fifo_clear(&p_midi->rx_ff);
|
||||
_prep_out_transaction(p_midi);
|
||||
@@ -205,7 +205,7 @@ static uint32_t write_flush(midid_interface_t* midi)
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize)
|
||||
uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize)
|
||||
{
|
||||
midid_interface_t* midi = &_midid_itf[itf];
|
||||
if (midi->itf_num == 0) {
|
||||
@@ -228,7 +228,7 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u
|
||||
midi->write_target_length = 4;
|
||||
}
|
||||
} else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) {
|
||||
midi->write_buffer[0] = jack_id << 4 | msg;
|
||||
midi->write_buffer[0] = cable_num << 4 | msg;
|
||||
midi->write_target_length = 4;
|
||||
} else if (msg == 0xf) {
|
||||
if (data == 0xf0) {
|
||||
@@ -246,7 +246,7 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u
|
||||
}
|
||||
} else {
|
||||
// Pack individual bytes if we don't support packing them into words.
|
||||
midi->write_buffer[0] = jack_id << 4 | 0xf;
|
||||
midi->write_buffer[0] = cable_num << 4 | 0xf;
|
||||
midi->write_buffer[2] = 0;
|
||||
midi->write_buffer[3] = 0;
|
||||
midi->write_buffer_length = 2;
|
||||
|
||||
@@ -60,13 +60,13 @@
|
||||
// CFG_TUD_MIDI > 1
|
||||
//--------------------------------------------------------------------+
|
||||
bool tud_midi_n_mounted (uint8_t itf);
|
||||
uint32_t tud_midi_n_available (uint8_t itf, uint8_t jack_id);
|
||||
uint32_t tud_midi_n_read (uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bufsize);
|
||||
void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id);
|
||||
uint32_t tud_midi_n_write (uint8_t itf, uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize);
|
||||
uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num);
|
||||
uint32_t tud_midi_n_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize);
|
||||
void tud_midi_n_read_flush (uint8_t itf, uint8_t cable_num);
|
||||
uint32_t tud_midi_n_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize);
|
||||
|
||||
static inline
|
||||
uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3);
|
||||
uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3);
|
||||
|
||||
bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]);
|
||||
bool tud_midi_n_send (uint8_t itf, uint8_t const packet[4]);
|
||||
@@ -78,8 +78,8 @@ static inline bool tud_midi_mounted (void);
|
||||
static inline uint32_t tud_midi_available (void);
|
||||
static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize);
|
||||
static inline void tud_midi_read_flush (void);
|
||||
static inline uint32_t tud_midi_write (uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize);
|
||||
static inline uint32_t tudi_midi_write24 (uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3);
|
||||
static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize);
|
||||
static inline uint32_t tud_midi_write24 (uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3);
|
||||
static inline bool tud_midi_receive (uint8_t packet[4]);
|
||||
static inline bool tud_midi_send (uint8_t const packet[4]);
|
||||
|
||||
@@ -92,10 +92,10 @@ TU_ATTR_WEAK void tud_midi_rx_cb(uint8_t itf);
|
||||
// Inline Functions
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
static inline uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3)
|
||||
static inline uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3)
|
||||
{
|
||||
uint8_t msg[3] = { b1, b2, b3 };
|
||||
return tud_midi_n_write(itf, jack_id, msg, 3);
|
||||
return tud_midi_n_write(itf, cable_num, msg, 3);
|
||||
}
|
||||
|
||||
static inline bool tud_midi_mounted (void)
|
||||
@@ -118,15 +118,15 @@ static inline void tud_midi_read_flush (void)
|
||||
tud_midi_n_read_flush(0, 0);
|
||||
}
|
||||
|
||||
static inline uint32_t tud_midi_write (uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize)
|
||||
static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize)
|
||||
{
|
||||
return tud_midi_n_write(0, jack_id, buffer, bufsize);
|
||||
return tud_midi_n_write(0, cable_num, buffer, bufsize);
|
||||
}
|
||||
|
||||
static inline uint32_t tudi_midi_write24 (uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3)
|
||||
static inline uint32_t tud_midi_write24 (uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3)
|
||||
{
|
||||
uint8_t msg[3] = { b1, b2, b3 };
|
||||
return tud_midi_write(jack_id, msg, 3);
|
||||
return tud_midi_write(cable_num, msg, 3);
|
||||
}
|
||||
|
||||
static inline bool tud_midi_receive (uint8_t packet[4])
|
||||
|
||||
@@ -47,14 +47,21 @@ enum
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t itf_num;
|
||||
uint8_t ep_in;
|
||||
uint8_t ep_out;
|
||||
uint8_t itf_num;
|
||||
uint8_t ep_in;
|
||||
uint8_t ep_out;
|
||||
|
||||
uint8_t max_lun;
|
||||
uint8_t max_lun;
|
||||
|
||||
volatile bool mounted;
|
||||
volatile bool configured; // Receive SET_CONFIGURE
|
||||
volatile bool mounted; // Enumeration is complete
|
||||
|
||||
struct {
|
||||
uint32_t block_size;
|
||||
uint32_t block_count;
|
||||
} capacity[CFG_TUH_MSC_MAXLUN];
|
||||
|
||||
//------------- SCSI -------------//
|
||||
uint8_t stage;
|
||||
void* buffer;
|
||||
tuh_msc_complete_cb_t complete_cb;
|
||||
@@ -63,14 +70,15 @@ typedef struct
|
||||
msc_csw_t csw;
|
||||
}msch_interface_t;
|
||||
|
||||
CFG_TUSB_MEM_SECTION static msch_interface_t msch_data[CFG_TUSB_HOST_DEVICE_MAX];
|
||||
CFG_TUSB_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUSB_HOST_DEVICE_MAX];
|
||||
|
||||
// buffer used to read scsi information when mounted, largest response data currently is inquiry
|
||||
CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t msch_buffer[sizeof(scsi_inquiry_resp_t)];
|
||||
// buffer used to read scsi information when mounted
|
||||
// largest response data currently is inquiry TODO Inquiry is not part of enum anymore
|
||||
CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)];
|
||||
|
||||
static inline msch_interface_t* get_itf(uint8_t dev_addr)
|
||||
{
|
||||
return &msch_data[dev_addr-1];
|
||||
return &_msch_itf[dev_addr-1];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
@@ -82,34 +90,45 @@ uint8_t tuh_msc_get_maxlun(uint8_t dev_addr)
|
||||
return p_msc->max_lun;
|
||||
}
|
||||
|
||||
uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun)
|
||||
{
|
||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||
return p_msc->capacity[lun].block_count;
|
||||
}
|
||||
|
||||
uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun)
|
||||
{
|
||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||
return p_msc->capacity[lun].block_size;
|
||||
}
|
||||
|
||||
bool tuh_msc_mounted(uint8_t dev_addr)
|
||||
{
|
||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||
|
||||
// is configured can be omitted
|
||||
return tuh_device_is_configured(dev_addr) && p_msc->mounted;
|
||||
return p_msc->mounted;
|
||||
}
|
||||
|
||||
bool tuh_msc_is_busy(uint8_t dev_addr)
|
||||
bool tuh_msc_ready(uint8_t dev_addr)
|
||||
{
|
||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||
return p_msc->mounted && hcd_edpt_busy(dev_addr, p_msc->ep_in);
|
||||
return p_msc->mounted && !hcd_edpt_busy(dev_addr, p_msc->ep_in);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// PUBLIC API: SCSI COMMAND
|
||||
//--------------------------------------------------------------------+
|
||||
static inline void msc_cbw_add_signature(msc_cbw_t *p_cbw, uint8_t lun)
|
||||
static inline void cbw_init(msc_cbw_t *cbw, uint8_t lun)
|
||||
{
|
||||
p_cbw->signature = MSC_CBW_SIGNATURE;
|
||||
p_cbw->tag = 0x54555342; // TUSB
|
||||
p_cbw->lun = lun;
|
||||
tu_memclr(cbw, sizeof(msc_cbw_t));
|
||||
cbw->signature = MSC_CBW_SIGNATURE;
|
||||
cbw->tag = 0x54555342; // TUSB
|
||||
cbw->lun = lun;
|
||||
}
|
||||
|
||||
bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb)
|
||||
{
|
||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||
// TU_VERIFY(p_msc->mounted); // TODO part of the enumeration also use scsi command
|
||||
TU_VERIFY(p_msc->configured);
|
||||
|
||||
// TODO claim endpoint
|
||||
|
||||
@@ -125,12 +144,12 @@ bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tu
|
||||
|
||||
bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb)
|
||||
{
|
||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||
if ( !p_msc->mounted ) return false;
|
||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||
TU_VERIFY(p_msc->configured);
|
||||
|
||||
msc_cbw_t cbw = { 0 };
|
||||
msc_cbw_t cbw;
|
||||
cbw_init(&cbw, lun);
|
||||
|
||||
msc_cbw_add_signature(&cbw, lun);
|
||||
cbw.total_bytes = sizeof(scsi_read_capacity10_resp_t);
|
||||
cbw.dir = TUSB_DIR_IN_MASK;
|
||||
cbw.cmd_len = sizeof(scsi_read_capacity10_t);
|
||||
@@ -139,11 +158,14 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r
|
||||
return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb);
|
||||
}
|
||||
|
||||
bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb)
|
||||
bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb)
|
||||
{
|
||||
msc_cbw_t cbw = { 0 };
|
||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||
TU_VERIFY(p_msc->mounted);
|
||||
|
||||
msc_cbw_t cbw;
|
||||
cbw_init(&cbw, lun);
|
||||
|
||||
msc_cbw_add_signature(&cbw, lun);
|
||||
cbw.total_bytes = sizeof(scsi_inquiry_resp_t);
|
||||
cbw.dir = TUSB_DIR_IN_MASK;
|
||||
cbw.cmd_len = sizeof(scsi_inquiry_t);
|
||||
@@ -160,26 +182,29 @@ bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* re
|
||||
|
||||
bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb)
|
||||
{
|
||||
msc_cbw_t cbw = { 0 };
|
||||
msc_cbw_add_signature(&cbw, lun);
|
||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||
TU_VERIFY(p_msc->configured);
|
||||
|
||||
cbw.total_bytes = 0; // Number of bytes
|
||||
cbw.dir = TUSB_DIR_OUT;
|
||||
cbw.cmd_len = sizeof(scsi_test_unit_ready_t);
|
||||
cbw.command[0] = SCSI_CMD_TEST_UNIT_READY;
|
||||
cbw.command[1] = lun; // according to wiki TODO need verification
|
||||
msc_cbw_t cbw;
|
||||
cbw_init(&cbw, lun);
|
||||
|
||||
cbw.total_bytes = 0;
|
||||
cbw.dir = TUSB_DIR_OUT;
|
||||
cbw.cmd_len = sizeof(scsi_test_unit_ready_t);
|
||||
cbw.command[0] = SCSI_CMD_TEST_UNIT_READY;
|
||||
cbw.command[1] = lun; // according to wiki TODO need verification
|
||||
|
||||
return tuh_msc_scsi_command(dev_addr, &cbw, NULL, complete_cb);
|
||||
}
|
||||
|
||||
bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb)
|
||||
{
|
||||
msc_cbw_t cbw = { 0 };
|
||||
msc_cbw_add_signature(&cbw, lun);
|
||||
msc_cbw_t cbw;
|
||||
cbw_init(&cbw, lun);
|
||||
|
||||
cbw.total_bytes = 18; // TODO sense response
|
||||
cbw.dir = TUSB_DIR_IN_MASK;
|
||||
cbw.cmd_len = sizeof(scsi_request_sense_t);
|
||||
cbw.dir = TUSB_DIR_IN_MASK;
|
||||
cbw.cmd_len = sizeof(scsi_request_sense_t);
|
||||
|
||||
scsi_request_sense_t const cmd_request_sense =
|
||||
{
|
||||
@@ -192,61 +217,54 @@ bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_ms
|
||||
return tuh_msc_scsi_command(dev_addr, &cbw, resposne, complete_cb);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
tusb_error_t tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count)
|
||||
bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb)
|
||||
{
|
||||
msch_interface_t* p_msch = &msch_data[dev_addr-1];
|
||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||
TU_VERIFY(p_msc->mounted);
|
||||
|
||||
//------------- Command Block Wrapper -------------//
|
||||
msc_cbw_add_signature(&p_msch->cbw, lun);
|
||||
|
||||
p_msch->cbw.total_bytes = p_msch->block_size*block_count; // Number of bytes
|
||||
p_msch->cbw.dir = TUSB_DIR_IN_MASK;
|
||||
p_msch->cbw.cmd_len = sizeof(scsi_read10_t);
|
||||
|
||||
//------------- SCSI command -------------//
|
||||
scsi_read10_t cmd_read10 =msch_sem_hdl
|
||||
msc_cbw_t cbw;
|
||||
cbw_init(&cbw, lun);
|
||||
|
||||
cbw.total_bytes = block_count*p_msc->capacity[lun].block_size;
|
||||
cbw.dir = TUSB_DIR_IN_MASK;
|
||||
cbw.cmd_len = sizeof(scsi_read10_t);
|
||||
|
||||
scsi_read10_t const cmd_read10 =
|
||||
{
|
||||
.cmd_code = SCSI_CMD_READ_10,
|
||||
.lba = tu_htonl(lba),
|
||||
.block_count = tu_htons(block_count)
|
||||
.cmd_code = SCSI_CMD_READ_10,
|
||||
.lba = tu_htonl(lba),
|
||||
.block_count = tu_htons(block_count)
|
||||
};
|
||||
|
||||
memcpy(cbw.command, &cmd_read10, cbw.cmd_len);
|
||||
|
||||
return tuh_msc_scsi_command(dev_addr, &cbw, buffer, complete_cb);
|
||||
}
|
||||
|
||||
bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb)
|
||||
{
|
||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||
TU_VERIFY(p_msc->mounted);
|
||||
|
||||
msc_cbw_t cbw;
|
||||
cbw_init(&cbw, lun);
|
||||
|
||||
cbw.total_bytes = block_count*p_msc->capacity[lun].block_size;
|
||||
cbw.dir = TUSB_DIR_OUT;
|
||||
cbw.cmd_len = sizeof(scsi_write10_t);
|
||||
|
||||
scsi_write10_t const cmd_write10 =
|
||||
{
|
||||
.cmd_code = SCSI_CMD_WRITE_10,
|
||||
.lba = tu_htonl(lba),
|
||||
.block_count = tu_htons(block_count)
|
||||
};
|
||||
|
||||
memcpy(p_msch->cbw.command, &cmd_read10, p_msch->cbw.cmd_len);
|
||||
memcpy(cbw.command, &cmd_write10, cbw.cmd_len);
|
||||
|
||||
TU_ASSERT_ERR ( send_cbw(dev_addr, p_msch, p_buffer));
|
||||
|
||||
return TUSB_ERROR_NONE;
|
||||
return tuh_msc_scsi_command(dev_addr, &cbw, (void*) buffer, complete_cb);
|
||||
}
|
||||
|
||||
tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffer, uint32_t lba, uint16_t block_count)
|
||||
{
|
||||
msch_interface_t* p_msch = &msch_data[dev_addr-1];
|
||||
|
||||
//------------- Command Block Wrapper -------------//
|
||||
msc_cbw_add_signature(&p_msch->cbw, lun);
|
||||
|
||||
p_msch->cbw.total_bytes = p_msch->block_size*block_count; // Number of bytes
|
||||
p_msch->cbw.dir = TUSB_DIR_OUT;
|
||||
p_msch->cbw.cmd_len = sizeof(scsi_write10_t);
|
||||
|
||||
//------------- SCSI command -------------//
|
||||
scsi_write10_t cmd_write10 =
|
||||
{
|
||||
.cmd_code = SCSI_CMD_WRITE_10,
|
||||
.lba = tu_htonl(lba),
|
||||
.block_count = tu_htons(block_count)
|
||||
};
|
||||
|
||||
memcpy(p_msch->cbw.command, &cmd_write10, p_msch->cbw.cmd_len);
|
||||
|
||||
TU_ASSERT_ERR ( send_cbw(dev_addr, p_msch, (void*) p_buffer));
|
||||
|
||||
return TUSB_ERROR_NONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// MSC interface Reset (not used now)
|
||||
bool tuh_msc_reset(uint8_t dev_addr)
|
||||
@@ -273,14 +291,14 @@ bool tuh_msc_reset(uint8_t dev_addr)
|
||||
//--------------------------------------------------------------------+
|
||||
void msch_init(void)
|
||||
{
|
||||
tu_memclr(msch_data, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX);
|
||||
tu_memclr(_msch_itf, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX);
|
||||
}
|
||||
|
||||
void msch_close(uint8_t dev_addr)
|
||||
{
|
||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||
tu_memclr(p_msc, sizeof(msch_interface_t));
|
||||
tuh_msc_unmounted_cb(dev_addr); // invoke Application Callback
|
||||
tuh_msc_unmount_cb(dev_addr); // invoke Application Callback
|
||||
}
|
||||
|
||||
bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes)
|
||||
@@ -337,6 +355,7 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32
|
||||
static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
|
||||
static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw);
|
||||
static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw);
|
||||
static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw);
|
||||
|
||||
bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length)
|
||||
{
|
||||
@@ -375,6 +394,8 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num)
|
||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||
TU_ASSERT(p_msc->itf_num == itf_num);
|
||||
|
||||
p_msc->configured = true;
|
||||
|
||||
//------------- Get Max Lun -------------//
|
||||
TU_LOG2("MSC Get Max Lun\r\n");
|
||||
tusb_control_request_t request =
|
||||
@@ -402,12 +423,13 @@ static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t
|
||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||
|
||||
// STALL means zero
|
||||
p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? msch_buffer[0] : 0;
|
||||
p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? _msch_buffer[0] : 0;
|
||||
p_msc->max_lun++; // MAX LUN is minus 1 by specs
|
||||
|
||||
// TODO multiple LUN support
|
||||
TU_LOG2("SCSI Test Unit Ready\r\n");
|
||||
tuh_msc_test_unit_ready(dev_addr, 0, config_test_unit_ready_complete);
|
||||
uint8_t const lun = 0;
|
||||
tuh_msc_test_unit_ready(dev_addr, lun, config_test_unit_ready_complete);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -416,19 +438,16 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* c
|
||||
{
|
||||
if (csw->status == 0)
|
||||
{
|
||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||
|
||||
usbh_driver_set_config_complete(dev_addr, p_msc->itf_num);
|
||||
|
||||
// Unit is ready, Enumeration is complete
|
||||
p_msc->mounted = true;
|
||||
tuh_msc_mounted_cb(dev_addr);
|
||||
// Unit is ready, read its capacity
|
||||
TU_LOG2("SCSI Read Capacity\r\n");
|
||||
tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) _msch_buffer, config_read_capacity_complete);
|
||||
}else
|
||||
{
|
||||
// Note: During enumeration, some device fails Test Unit Ready and require a few retries
|
||||
// with Request Sense to start working !!
|
||||
// TODO limit number of retries
|
||||
TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, msch_buffer, config_request_sense_complete));
|
||||
TU_LOG2("SCSI Request Sense\r\n");
|
||||
TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, _msch_buffer, config_request_sense_complete));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -441,4 +460,24 @@ static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw)
|
||||
{
|
||||
TU_ASSERT(csw->status == 0);
|
||||
|
||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||
|
||||
// Capacity response field: Block size and Last LBA are both Big-Endian
|
||||
scsi_read_capacity10_resp_t* resp = (scsi_read_capacity10_resp_t*) _msch_buffer;
|
||||
p_msc->capacity[cbw->lun].block_count = tu_ntohl(resp->last_lba) + 1;
|
||||
p_msc->capacity[cbw->lun].block_size = tu_ntohl(resp->block_size);
|
||||
|
||||
// Mark enumeration is complete
|
||||
p_msc->mounted = true;
|
||||
tuh_msc_mount_cb(dev_addr);
|
||||
|
||||
usbh_driver_set_config_complete(dev_addr, p_msc->itf_num);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -35,6 +35,15 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Class Driver Configuration
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
#ifndef CFG_TUH_MSC_MAXLUN
|
||||
#define CFG_TUH_MSC_MAXLUN 4
|
||||
#endif
|
||||
|
||||
|
||||
/** \addtogroup ClassDriver_MSC
|
||||
* @{
|
||||
* \defgroup MSC_Host Host
|
||||
@@ -51,73 +60,56 @@ typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, msc_cbw_t const* cbw, ms
|
||||
// This function true after tuh_msc_mounted_cb() and false after tuh_msc_unmounted_cb()
|
||||
bool tuh_msc_mounted(uint8_t dev_addr);
|
||||
|
||||
/** \brief Check if the interface is currently busy or not
|
||||
* \param[in] dev_addr device address
|
||||
* \retval true if the interface is busy meaning the stack is still transferring/waiting data from/to device
|
||||
* \retval false if the interface is not busy meaning the stack successfully transferred data from/to device
|
||||
* \note This function is used to check if previous transfer is complete (success or error), so that the next transfer
|
||||
* can be scheduled. User needs to make sure the corresponding interface is mounted (by \ref tuh_msc_is_mounted)
|
||||
* before calling this function
|
||||
*/
|
||||
bool tuh_msc_is_busy(uint8_t dev_addr);
|
||||
// Check if the interface is currently ready or busy transferring data
|
||||
bool tuh_msc_ready(uint8_t dev_addr);
|
||||
|
||||
// Get Max Lun
|
||||
uint8_t tuh_msc_get_maxlun(uint8_t dev_addr);
|
||||
|
||||
// Carry out a full SCSI command (cbw, data, csw) in non-blocking manner.
|
||||
// `complete_cb` callback is invoked when SCSI op is complete.
|
||||
// Get number of block
|
||||
uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun);
|
||||
|
||||
// Get block size in bytes
|
||||
uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun);
|
||||
|
||||
// Perform a full SCSI command (cbw, data, csw) in non-blocking manner.
|
||||
// Complete callback is invoked when SCSI op is complete.
|
||||
// return true if success, false if there is already pending operation.
|
||||
bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb);
|
||||
|
||||
// Carry out SCSI INQUIRY command in non-blocking manner.
|
||||
bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb);
|
||||
// Perform SCSI Inquiry command
|
||||
// Complete callback is invoked when SCSI op is complete.
|
||||
bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb);
|
||||
|
||||
// Carry out SCSI REQUEST SENSE (10) command in non-blocking manner.
|
||||
// Perform SCSI Test Unit Ready command
|
||||
// Complete callback is invoked when SCSI op is complete.
|
||||
bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb);
|
||||
|
||||
// Carry out SCSI REQUEST SENSE (10) command in non-blocking manner.
|
||||
// Perform SCSI Request Sense 10 command
|
||||
// Complete callback is invoked when SCSI op is complete.
|
||||
bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb);
|
||||
|
||||
// Carry out SCSI READ CAPACITY (10) command in non-blocking manner.
|
||||
// Perform SCSI Read 10 command. Read n blocks starting from LBA to buffer
|
||||
// Complete callback is invoked when SCSI op is complete.
|
||||
bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb);
|
||||
|
||||
// Perform SCSI Write 10 command. Write n blocks starting from LBA to device
|
||||
// Complete callback is invoked when SCSI op is complete.
|
||||
bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb);
|
||||
|
||||
// Perform SCSI Read Capacity 10 command
|
||||
// Complete callback is invoked when SCSI op is complete.
|
||||
// Note: during enumeration, host stack already carried out this request. Application can retrieve capacity by
|
||||
// simply call tuh_msc_get_block_count() and tuh_msc_get_block_size()
|
||||
bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb);
|
||||
|
||||
#if 0
|
||||
/** \brief Perform SCSI READ 10 command to read data from MassStorage device
|
||||
* \param[in] dev_addr device address
|
||||
* \param[in] lun Targeted Logical Unit
|
||||
* \param[out] p_buffer Buffer used to store data read from device. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION)
|
||||
* \param[in] lba Starting Logical Block Address to be read
|
||||
* \param[in] block_count Number of Block to be read
|
||||
* \retval TUSB_ERROR_NONE on success
|
||||
* \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device
|
||||
* \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request)
|
||||
* \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct
|
||||
* \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the interface's callback function
|
||||
*/
|
||||
tusb_error_t tuh_msc_read10 (uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count);
|
||||
|
||||
/** \brief Perform SCSI WRITE 10 command to write data to MassStorage device
|
||||
* \param[in] dev_addr device address
|
||||
* \param[in] lun Targeted Logical Unit
|
||||
* \param[in] p_buffer Buffer containing data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION)
|
||||
* \param[in] lba Starting Logical Block Address to be written
|
||||
* \param[in] block_count Number of Block to be written
|
||||
* \retval TUSB_ERROR_NONE on success
|
||||
* \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device
|
||||
* \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request)
|
||||
* \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct
|
||||
* \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the interface's callback function
|
||||
*/
|
||||
tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffer, uint32_t lba, uint16_t block_count);
|
||||
#endif
|
||||
|
||||
//------------- Application Callback -------------//
|
||||
|
||||
// Invoked when a device with MassStorage interface is mounted
|
||||
void tuh_msc_mounted_cb(uint8_t dev_addr);
|
||||
void tuh_msc_mount_cb(uint8_t dev_addr);
|
||||
|
||||
// Invoked when a device with MassStorage interface is unmounted
|
||||
void tuh_msc_unmounted_cb(uint8_t dev_addr);
|
||||
void tuh_msc_unmount_cb(uint8_t dev_addr);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Internal Class Driver API
|
||||
|
||||
Reference in New Issue
Block a user