添加CancelIO协议

This commit is contained in:
gb 2023-12-14 14:24:15 +08:00
parent 32f830ee94
commit 137ba57a05
3 changed files with 83 additions and 41 deletions

View File

@ -40,16 +40,17 @@
// NOTE: All text transmitted by pack cmd is in UTF-8 format !!! // NOTE: All text transmitted by pack cmd is in UTF-8 format !!!
enum cancel_io
{
CANCEL_IO_CANCEL = 0x0ca0cel,
};
enum ep0_req enum ep0_req
{ {
USB_REQ_EP0_GET_PROTO_VER = 100, // get protocol version (PROTOCOL_VER), req = me, ind = 0, val = 0, len = 2 USB_REQ_EP0_GET_PEER_CONFIG = 100, // get protocol version (PROTOCOL_VER), req = me, ind = 0, val = 0, len = sizeof(PEERCFG)
USB_REQ_EP0_GET_IO_SIZE, // get bulk size of IO buffer, req = me, ind = 0, val = 0, len = sizeof(uint32_t)
USB_REQ_EP0_GET_STATUS, // 获取各工作线程状态, return EP0REPLYSTATUS. req = me, ind = 0, val = 0, len = sizeof(EP0REPLYSTATUS) USB_REQ_EP0_GET_STATUS, // 获取各工作线程状态, return EP0REPLYSTATUS. req = me, ind = 0, val = 0, len = sizeof(EP0REPLYSTATUS)
USB_REQ_EP0_RESET_BULK, // 关闭并重新打开BULK端点, return error number (uint32_t). req = me, ind = 0, val = 0, len = sizeof(uint32_t) USB_REQ_EP0_CANCEL_IO, // 设置当前IO数据的有效性. req = me, ind = 0, val = 0, len = sizeof(uint32_t), discard IO data when data is CANCEL_IO_CANCEL
USB_REQ_EP0_CANCEL_CMD, // 取消当前指令的继续执行(一般用于中止大数据的传输). req = me, ind = 0, val = 0, len = sizeof(uint32_t) * 2 [(uint32_t)cmd + (uint32_t)pack-id] // work-flow: write control with 'CANCEL_IO_CANCEL', write bulk with 1 byte, write control with not 'CANCEL_IO_CANCEL' to restore
USB_REQ_EP0_SET_ENCRYPT, // 设置加密方式, req = me, ind = 0, val = 0, len = sizeof(PACK_BASE) USB_REQ_EP0_SET_ENCRYPT, // 设置加密方式, req = me, ind = 0, val = 0, len = sizeof(PACK_BASE)
USB_REQ_EP0_SET_BULK_BUFFER, // 设置bulk缓冲区大小系数 req = me, ind = coef, val = 0, len = 0
}; };
enum woker_status enum woker_status
{ {
@ -255,6 +256,12 @@ typedef struct _ep0_reply
uint32_t bytes_to_sent; // how many bytes data is waiting for be sent in one replying packet uint32_t bytes_to_sent; // how many bytes data is waiting for be sent in one replying packet
}EP0REPLYSTATUS, *LPEP0REPLYSTATUS; }EP0REPLYSTATUS, *LPEP0REPLYSTATUS;
typedef struct _peer_config
{
uint16_t ver; // protocol version
uint32_t io_size; // IO buffer size
}PEERCFG, *LPPEERCFG;
typedef struct _pack_base // A piece of data has only one header typedef struct _pack_base // A piece of data has only one header
{ {
uint32_t enc_cmd : 2; // encrypting type, for 'cmd' uint32_t enc_cmd : 2; // encrypting type, for 'cmd'

View File

@ -266,10 +266,11 @@ dyn_mem_ptr async_usb_gadget::handle_ctrl_setup(dyn_mem_ptr data)
{ {
switch (pev->u.setup.bRequest) switch (pev->u.setup.bRequest)
{ {
case USB_REQ_EP0_GET_PROTO_VER: case USB_REQ_EP0_GET_PEER_CONFIG:
reply = dyn_mem::memory(sizeof(short)); reply = dyn_mem::memory(sizeof(PEERCFG));
*(short*)reply->ptr() = PROTOCOL_VER; ((LPPEERCFG)reply->ptr())->ver = PROTOCOL_VER;
reply->set_len(sizeof(short)); ((LPPEERCFG)reply->ptr())->io_size = unit_out_;
reply->set_len(sizeof(PEERCFG));
break; break;
case USB_REQ_EP0_GET_STATUS: case USB_REQ_EP0_GET_STATUS:
reply = dyn_mem::memory(sizeof(struct _ep0_reply)); reply = dyn_mem::memory(sizeof(struct _ep0_reply));
@ -278,6 +279,7 @@ dyn_mem_ptr async_usb_gadget::handle_ctrl_setup(dyn_mem_ptr data)
LPEP0REPLYSTATUS lps = (LPEP0REPLYSTATUS)reply->ptr(); LPEP0REPLYSTATUS lps = (LPEP0REPLYSTATUS)reply->ptr();
lps->in_status = statu_in_; lps->in_status = statu_in_;
lps->out_status = statu_out_; lps->out_status = statu_out_;
lps->task_cnt = cmd_que_.size();
lps->task_cmd = task_cmd_; lps->task_cmd = task_cmd_;
lps->task_pack_id = task_packet_id_; lps->task_pack_id = task_packet_id_;
lps->task_required_bytes = want_bytes_task_; lps->task_required_bytes = want_bytes_task_;
@ -286,13 +288,12 @@ dyn_mem_ptr async_usb_gadget::handle_ctrl_setup(dyn_mem_ptr data)
utils::log_mem_info("threads status:", lps, sizeof(*lps), LOG_LEVEL_DEBUG); utils::log_mem_info("threads status:", lps, sizeof(*lps), LOG_LEVEL_DEBUG);
} }
break; break;
case USB_REQ_EP0_GET_IO_SIZE: case USB_REQ_EP0_CANCEL_IO:
reply = dyn_mem::memory(sizeof(unit_out_)); if (pev->u.setup.wLength == sizeof(uint32_t))
reply->put(&unit_out_, sizeof(unit_out_)); {
break; uint32_t val = *(uint32_t*)&pev[1];
case USB_REQ_EP0_RESET_BULK: cancel_io_ = (val == CANCEL_IO_CANCEL);
reply = dyn_mem::memory(sizeof(uint32_t)); }
reply->put(&err, sizeof(err));
break; break;
case USB_REQ_EP0_SET_ENCRYPT: case USB_REQ_EP0_SET_ENCRYPT:
if (pev->u.setup.wLength == sizeof(PACK_BASE)) if (pev->u.setup.wLength == sizeof(PACK_BASE))
@ -304,15 +305,6 @@ dyn_mem_ptr async_usb_gadget::handle_ctrl_setup(dyn_mem_ptr data)
utils::to_log(LOG_LEVEL_DEBUG, "Set encrypting method: command - %d; payload - %d\n", enc_head_, enc_payload_); utils::to_log(LOG_LEVEL_DEBUG, "Set encrypting method: command - %d; payload - %d\n", enc_head_, enc_payload_);
} }
break; break;
case USB_REQ_EP0_SET_BULK_BUFFER:
// if(pev->u.setup.wLength == sizeof(short))
{
uint16_t pre = buf_coef_;
set_buf_coefficient(pev->u.setup.wIndex);
utils::to_log(LOG_LEVEL_DEBUG, "Set bulk buffer size coefficient from %d to %d\n", pre, buf_coef_);
}
break;
default: default:
handled = false; handled = false;
} }
@ -332,7 +324,7 @@ int async_usb_gadget::inner_write_bulk_memory(int fd, uint8_t* buf, uint32_t* le
int w = 0, to = 0, err = 0, total = *len, off = 0, int w = 0, to = 0, err = 0, total = *len, off = 0,
size = *len; size = *len;
while(1) while(!cancel_io_)
{ {
w = write(fd, buf + off, size); w = write(fd, buf + off, size);
if(w == -1) if(w == -1)
@ -491,6 +483,7 @@ void async_usb_gadget::thread_read_bulk(int fd)
while(run_) while(run_)
{ {
statu_out_ = WORKER_STATUS_WAIT_RESOURCE;
dyn_mem_ptr buf = get_io_buffer(); dyn_mem_ptr buf = get_io_buffer();
int l = 0; int l = 0;
@ -508,7 +501,12 @@ void async_usb_gadget::thread_read_bulk(int fd)
buf->set_session_id(session_id_); buf->set_session_id(session_id_);
l = read(fd, buf->ptr(), bulk_size); l = read(fd, buf->ptr(), bulk_size);
statu_out_ = WORKER_STATUS_IDLE; statu_out_ = WORKER_STATUS_IDLE;
if(l <= 0) if (!run_)
{
buf->release();
break;
}
else if(l <= 0)
{ {
free_io_buffer(buf); free_io_buffer(buf);
if(errno) if(errno)
@ -522,17 +520,19 @@ void async_usb_gadget::thread_read_bulk(int fd)
cnt_0++; cnt_0++;
} }
} }
else if (!run_)
{
utils::to_log(LOG_LEVEL_ALL, "thread_read_bulk do reset-bulk ...\n");
buf->release();
break;
}
else else
{
// if(!cancel_io_) // ensure to trigger task thread clean it's work
{ {
buf->set_len(l); buf->set_len(l);
cmd_que_.save(buf, true); cmd_que_.save(buf, true);
} }
// else
// {
// free_io_buffer(buf);
// utils::to_log(LOG_LEVEL_DEBUG, "Cancel read with %u bytes.\n", l);
// }
}
} }
statu_out_ = WORKER_STATUS_NOT_START; statu_out_ = WORKER_STATUS_NOT_START;
} }
@ -550,6 +550,8 @@ void async_usb_gadget::thread_write_bulk(int fd)
if(sent_que_.take(data, true)) if(sent_que_.take(data, true))
{ {
want_bytes_in_ = data->get_rest(); want_bytes_in_ = data->get_rest();
if(!cancel_io_)
{
err = inner_write_bulk(fd, data, mem, bulk_size); err = inner_write_bulk(fd, data, mem, bulk_size);
{ {
file_reader_ptr fr = dynamic_cast<file_reader_ptr>(data); file_reader_ptr fr = dynamic_cast<file_reader_ptr>(data);
@ -558,6 +560,11 @@ void async_usb_gadget::thread_write_bulk(int fd)
utils::to_log(LOG_LEVEL_DEBUG, "Sent file(%s) with error: %d.\n", fr->path_file(), err); utils::to_log(LOG_LEVEL_DEBUG, "Sent file(%s) with error: %d.\n", fr->path_file(), err);
} }
} }
}
else
{
utils::to_log(LOG_LEVEL_DEBUG, "Cancel write with %u bytes.\n", data->get_rest());
}
data->release(); data->release();
if(err) if(err)
{ {
@ -583,6 +590,7 @@ void async_usb_gadget::thread_pump_task(void)
{ {
data = nullptr; data = nullptr;
statu_task_ = WORKER_STATUS_IDLE; statu_task_ = WORKER_STATUS_IDLE;
task_cmd_ = 0;
if(cmd_que_.take(data, true) && data) if(cmd_que_.take(data, true) && data)
{ {
bool pool = true; bool pool = true;
@ -590,6 +598,32 @@ void async_usb_gadget::thread_pump_task(void)
if(max_que < cmd_que_.size()) if(max_que < cmd_que_.size())
max_que = cmd_que_.size(); max_que = cmd_que_.size();
if(cancel_io_)
{
if(prev)
{
utils::to_log(LOG_LEVEL_DEBUG, "Cancel task previous packet with %u bytes.\n", prev->get_rest());
prev->release();
prev = nullptr;
}
if(dh)
{
utils::to_log(LOG_LEVEL_DEBUG, "Cancel task holder need %u bytes.\n", dh->get_required());
dh->cancel();
dh->release();
dh = nullptr;
}
if(reply)
{
reply->release();
reply = nullptr;
}
want_bytes_task_ = 0;
utils::to_log(LOG_LEVEL_DEBUG, "Cancel task with %u bytes.\n", data->get_rest());
data->release();
continue;
}
if(prev) if(prev)
{ {
if(prev->get_session_id() != data->get_session_id()) if(prev->get_session_id() != data->get_session_id())

View File

@ -42,6 +42,7 @@ class usb_device;
class async_usb_gadget : public refer class async_usb_gadget : public refer
{ {
volatile bool run_ = true; volatile bool run_ = true;
volatile bool cancel_io_ = false;
usb_device *dev_ = nullptr; usb_device *dev_ = nullptr;
safe_thread threads_; safe_thread threads_;
size_t unit_in_ = 0x200; size_t unit_in_ = 0x200;