add file_map

This commit is contained in:
gb 2023-12-09 18:21:05 +08:00
parent 4dc3d7ccc1
commit 1ca053bea6
12 changed files with 625 additions and 103 deletions

View File

@ -71,6 +71,10 @@ async_scanner::~async_scanner()
cfg_mgr_->clear(); cfg_mgr_->clear();
delete cfg_mgr_; delete cfg_mgr_;
} }
for(auto& v: send_files_)
v->release();
send_files_.clear();
utils::uninit(); utils::uninit();
} }
@ -114,6 +118,9 @@ dyn_mem_ptr async_scanner::handle_bulk_cmd(LPPACK_BASE pack, uint32_t* used, pac
case PACK_CMD_FILE_READ_REQ: case PACK_CMD_FILE_READ_REQ:
reply = handle_file_send(pack, used, required); reply = handle_file_send(pack, used, required);
break; break;
case PACK_CMD_FILE_READ_REQ_ROGER:
reply = handle_file_send_roger(pack, used, required);
break;
case PACK_CMD_SCAN_START: case PACK_CMD_SCAN_START:
reply = handle_scan_start(pack, used, required); reply = handle_scan_start(pack, used, required);
break; break;
@ -256,7 +263,7 @@ dyn_mem_ptr async_scanner::handle_file_receive(LPPACK_BASE pack, uint32_t* used,
int err = 0; int err = 0;
file_saver *saver = new file_saver(); file_saver *saver = new file_saver();
err = saver->open(path.c_str(), pfi->size); err = saver->open(path.c_str(), pfi->size, true, pfi->offset);
reply = dyn_mem::memory(base_head_size); reply = dyn_mem::memory(base_head_size);
reply->set_len(base_head_size); reply->set_len(base_head_size);
BASE_PACKET_REPLY(*((LPPACK_BASE)reply->ptr()), pack->cmd + 1, pack->pack_id, err); BASE_PACKET_REPLY(*((LPPACK_BASE)reply->ptr()), pack->cmd + 1, pack->pack_id, err);
@ -293,7 +300,7 @@ dyn_mem_ptr async_scanner::handle_file_send(LPPACK_BASE pack, uint32_t* used, pa
int err = 0; int err = 0;
file_reader *reader = new file_reader(); file_reader *reader = new file_reader();
err = reader->open(path.c_str()); err = reader->open(path.c_str(), true, pfi->offset);
reply = dyn_mem::memory(base_head_size + sizeof(TXFILE)); reply = dyn_mem::memory(base_head_size + sizeof(TXFILE));
reply->set_len(base_head_size + sizeof(TXFILE)); reply->set_len(base_head_size + sizeof(TXFILE));
BASE_PACKET_REPLY(*((LPPACK_BASE)reply->ptr()), pack->cmd + 1, pack->pack_id, err); BASE_PACKET_REPLY(*((LPPACK_BASE)reply->ptr()), pack->cmd + 1, pack->pack_id, err);
@ -309,12 +316,52 @@ dyn_mem_ptr async_scanner::handle_file_send(LPPACK_BASE pack, uint32_t* used, pa
((LPPACK_BASE)reply->ptr())->payload_len = sizeof(TXFILE); ((LPPACK_BASE)reply->ptr())->payload_len = sizeof(TXFILE);
((LPTXFILE)((LPPACK_BASE)reply->ptr())->payload)->size = reader->get_rest(); ((LPTXFILE)((LPPACK_BASE)reply->ptr())->payload)->size = reader->get_rest();
reader->set_packet_param(pack->cmd, pack->pack_id); reader->set_packet_param(pack->cmd, pack->pack_id);
{
// move to PACK_CMD_FILE_READ_REQ_ROGER
SIMPLE_LOCK(fsender_);
send_files_.push_back(reader);
reader = nullptr;
}
} }
*required = dynamic_cast<packet_data_base_ptr>(reader); *required = dynamic_cast<packet_data_base_ptr>(reader);
} }
return reply; return reply;
} }
dyn_mem_ptr async_scanner::handle_file_send_roger(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required)
{
uint32_t base_head_size = sizeof(PACK_BASE);
dyn_mem_ptr reply = nullptr;
if(*used < base_head_size)
{
*used = 0;
}
else
{
file_reader* reader = nullptr;
{
SIMPLE_LOCK(fsender_);
for(size_t i = 0; i < send_files_.size(); ++i)
{
if(send_files_[i]->get_packet_id() == pack->pack_id)
{
reader = send_files_[i];
send_files_.erase(send_files_.begin() + i);
break;
}
}
}
*used = base_head_size;
*required = dynamic_cast<packet_data_base_ptr>(reader);
// if reader was nullptr, notify failed by INT or control ?
utils::to_log(LOG_LEVEL_DEBUG, "File Send beginning (%p) ...\n", reader);
}
return reply;
}
dyn_mem_ptr async_scanner::handle_scan_start(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required) dyn_mem_ptr async_scanner::handle_scan_start(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required)
{ {
if(!used) if(!used)

View File

@ -28,6 +28,9 @@ class async_scanner : public refer
volatile bool reply_start_; volatile bool reply_start_;
int last_err_ = 0; int last_err_ = 0;
MUTEX fsender_;
std::vector<file_reader*> send_files_;
dyn_mem_ptr handle_bulk_cmd(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required); dyn_mem_ptr handle_bulk_cmd(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required);
void init(void); void init(void);
@ -37,6 +40,7 @@ class async_scanner : public refer
dyn_mem_ptr handle_set_opt(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required); dyn_mem_ptr handle_set_opt(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required);
dyn_mem_ptr handle_file_receive(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required); dyn_mem_ptr handle_file_receive(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required);
dyn_mem_ptr handle_file_send(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required); dyn_mem_ptr handle_file_send(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required);
dyn_mem_ptr handle_file_send_roger(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required);
dyn_mem_ptr handle_scan_start(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required); dyn_mem_ptr handle_scan_start(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required);
dyn_mem_ptr handle_scan_stop(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required); dyn_mem_ptr handle_scan_stop(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required);
dyn_mem_ptr handle_process_cmd(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required); dyn_mem_ptr handle_process_cmd(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required);

View File

@ -3,10 +3,11 @@
#include <string.h> #include <string.h>
#if defined(WIN32) || defined(_WIN64) #if OS_WIN
#else #else
#include <sys/fcntl.h> #include <sys/fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <sys/mman.h>
#endif #endif
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -20,7 +21,7 @@ packet_data_base::~packet_data_base()
int packet_data_base::notify_progress(uint64_t total, uint64_t cur_size, uint32_t err) int packet_data_base::notify_progress(uint64_t total, uint64_t cur_size, uint32_t err)
{ {
if (progress_notify_) if (progress_notify_)
progress_notify_(total, cur_size, err, user_data_); return progress_notify_(total, cur_size, err, user_data_);
else else
return ENOENT; return ENOENT;
} }
@ -148,11 +149,16 @@ file_saver::file_saver(void) : size_(0), wrote_(0), path_(""), check_(""), dst_(
{} {}
file_saver::~file_saver() file_saver::~file_saver()
{ {
utils::to_log(LOG_LEVEL_DEBUG, "Write file(%s) over(%ld/%ld).\n", path_.c_str(), wrote_, size_);
close(); close();
} }
void file_saver::close(void) void file_saver::close(void)
{ {
if (map_)
map_->release();
map_ = nullptr;
if(dst_) if(dst_)
fclose(dst_); fclose(dst_);
dst_ = nullptr; dst_ = nullptr;
@ -161,17 +167,48 @@ void file_saver::close(void)
path_ = check_ = ""; path_ = check_ = "";
} }
int file_saver::open(const char* path, uint64_t size, const char* check) int file_saver::set_verify_data(const char* data, size_t len)
{
if (data)
check_ = std::string(data, len);
else
check_ = "";
return 0;
}
int file_saver::open(const char* path, uint64_t size, bool in_mem, size_t off)
{ {
int err = 0; int err = 0;
close(); close();
dst_ = fopen(path, "wb"); wrote_ = off;
if(dst_) path_ = path;
size_ = size;
if (in_mem)
{
map_ = new file_map();
err = map_->open(path, size, false);
if (err || !map_->map())
{
map_->release();
map_ = nullptr;
}
else
return err;
}
err = utils::make_file_size(path, wrote_);
dst_ = fopen(path, "ab+");
if (dst_)
{ {
unsigned long long space = 0; unsigned long long space = 0;
std::string dir(path);
size_t pos = dir.rfind(PATH_SEPARATOR[0]);
err = utils::get_disk_space(path, nullptr, &space, nullptr); if (pos != std::string::npos)
dir.erase(pos);
err = utils::get_disk_space(dir.c_str(), nullptr, &space, nullptr);
if (err || space < size * 1.5) if (err || space < size * 1.5)
{ {
fclose(dst_); fclose(dst_);
@ -180,12 +217,6 @@ int file_saver::open(const char* path, uint64_t size, const char* check)
if (err == 0) if (err == 0)
err = ENOSPC; err = ENOSPC;
} }
else
{
path_ = path;
size_ = size;
check_ = check ? check : "";
}
} }
else else
{ {
@ -197,8 +228,22 @@ int file_saver::open(const char* path, uint64_t size, const char* check)
int file_saver::put_data(const void* data, uint32_t* size/*[in] - total bytes of data; [out] - used bytes*/) int file_saver::put_data(const void* data, uint32_t* size/*[in] - total bytes of data; [out] - used bytes*/)
{ {
if(!dst_) if (!dst_)
{
if (map_)
{
// fix me: we consider whole file is all mapped in memory
int w = *size > size_ - wrote_ ? size_ - wrote_ : *size;
memcpy(map_->buffer() + wrote_, data, w);
*size = w;
wrote_ += w;
notify_progress(size_, wrote_, 0);
return 0;
}
return ENOENT; return ENOENT;
}
int w = *size > size_ - wrote_ ? size_ - wrote_ : *size, int w = *size > size_ - wrote_ ? size_ - wrote_ : *size,
real_w = fwrite(data, 1, w, dst_), // should handle error here ! real_w = fwrite(data, 1, w, dst_), // should handle error here !
@ -229,9 +274,11 @@ uint32_t file_saver::get_required(void)
} }
void file_saver::cancel(void) void file_saver::cancel(void)
{ {
std::string discard(path_);
utils::to_log(LOG_LEVEL_DEBUG, "Discard receiving file (%u/%u): '%s'.\n", wrote_, size_, path_.c_str()); utils::to_log(LOG_LEVEL_DEBUG, "Discard receiving file (%u/%u): '%s'.\n", wrote_, size_, path_.c_str());
close(); close();
remove(path_.c_str()); remove(discard.c_str());
} }
@ -401,12 +448,41 @@ file_reader::~file_reader()
{ {
if(src_) if(src_)
fclose(src_); fclose(src_);
if (map_)
map_->release();
utils::to_log(LOG_LEVEL_DEBUG, "Read file(%s) over(%ld/%ld).\n", path_.c_str(), consume_, len_);
} }
int file_reader::open(const char* file) int file_reader::open(const char* file, bool in_mem, size_t off)
{ {
if(src_) if(src_)
fclose(src_); fclose(src_);
src_ = nullptr;
consume_ = off;
if (in_mem)
{
map_ = new file_map();
if (map_->open(file, 0, true) || !map_->map())
{
map_->release();
map_ = nullptr;
}
else
{
if (map_->total_size() <= off)
{
map_->release();
map_ = nullptr;
return EOVERFLOW;
}
path_ = file;
len_ = map_->total_size();
return 0;
}
}
src_ = fopen(file, "rb"); src_ = fopen(file, "rb");
if(!src_) if(!src_)
@ -414,9 +490,15 @@ int file_reader::open(const char* file)
FSEEK(src_, 0, SEEK_END); FSEEK(src_, 0, SEEK_END);
len_ = FTELL(src_); len_ = FTELL(src_);
FSEEK(src_, 0, SEEK_SET); FSEEK(src_, consume_, SEEK_SET);
path_ = file; path_ = file;
consume_ = 0; if (len_ <= consume_)
{
fclose(src_);
src_ = nullptr;
return EOVERFLOW;
}
return 0; return 0;
} }
@ -427,6 +509,11 @@ int file_reader::attach(FILE* f)
fclose(src_); fclose(src_);
src_ = nullptr; src_ = nullptr;
} }
if (map_)
{
map_->release();
map_ = nullptr;
}
uint64_t cur = FTELL(f); uint64_t cur = FTELL(f);
@ -455,7 +542,7 @@ FILE* file_reader::detach(void)
bool file_reader::is_memory_block(void) bool file_reader::is_memory_block(void)
{ {
return false; return map_ != nullptr;
} }
uint32_t file_reader::get_rest(void) uint32_t file_reader::get_rest(void)
{ {
@ -465,14 +552,27 @@ uint32_t file_reader::get_rest(void)
// following API valid when is_memory_block() return true // following API valid when is_memory_block() return true
uint8_t* file_reader::ptr(void) uint8_t* file_reader::ptr(void)
{ {
return nullptr; return map_ ? map_->buffer() : nullptr;
} }
// following API valid when is_memory_block() return false // following API valid when is_memory_block() return false
int file_reader::fetch_data(void* buf, uint32_t* size) int file_reader::fetch_data(void* buf, uint32_t* size)
{ {
if (!src_) if (!src_)
{
if (map_)
{
if (*size + consume_ >= len_)
*size = len_ - consume_;
memcpy(buf, map_->buffer() + consume_, *size);
consume_ += *size;
notify_progress(len_, consume_, 0);
return 0;
}
return ENODATA; return ENODATA;
}
size_t r = fread(buf, 1, *size, src_); // fix me if ERROR occurs !!! size_t r = fread(buf, 1, *size, src_); // fix me if ERROR occurs !!!
@ -487,3 +587,200 @@ int file_reader::fetch_data(void* buf, uint32_t* size)
return 0; return 0;
} }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
file_map::file_map()
{
utils::get_page_size(&os_map_size_);
}
file_map::~file_map()
{
close();
}
void file_map::unmap(void)
{
if (buf_)
#if OS_WIN
UnmapViewOfFile(buf_);
#else
munmap(buf_, map_size_);
#endif
buf_ = nullptr;
map_off_ = map_size_ = off_ = 0;
}
int file_map::open(const char* file, uint64_t size, bool readonly)
{
close();
std::string oper(readonly ? "open" : "create");
#if OS_WIN
HANDLE h = INVALID_HANDLE_VALUE;
DWORD access = PAGE_READONLY;
if (readonly)
{
h = CreateFileA(file, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
}
else
{
access = PAGE_READWRITE;
h = CreateFileA(file, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
}
if (h == INVALID_HANDLE_VALUE)
{
utils::to_log(LOG_LEVEL_WARNING, "FileMapping: %s '%s' failed: %d\n", oper.c_str(), file, GetLastError());
return EFAULT;
}
if (readonly)
{
DWORD* hi = (DWORD*)&size + 1,
* lo = (DWORD*)&size;
*lo = GetFileSize(h, hi);
}
else
{
LONG lo = size & 0x0ffffffff,
hi = size >> 32;
DWORD ret = SetFilePointer(h, lo, &hi, FILE_BEGIN);
if (ret == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
{
CloseHandle(h);
remove(file);
utils::to_log(LOG_LEVEL_WARNING, "FileMapping: no space(%ld) for '%s'.\n", size, file);
return ENOSPC;
}
else
{
// write a byte to ensure map success
SetFilePointer(h, -1, NULL, FILE_CURRENT);
lo = 0;
WriteFile(h, &lo, 1, &ret, NULL);
}
}
map_ = CreateFileMappingA(h, NULL, access, 0, 0, NULL);
access = GetLastError();
CloseHandle(h);
if (!map_)
{
remove(file);
map_ = INVALID_HANDLE_VALUE;
utils::to_log(LOG_LEVEL_WARNING, "FileMapping: create mapping object for '%s' failed: %d.\n", file, access);
return EFAULT;
}
#else
if (readonly)
map_ = (HANDLE)::open(file, O_RDONLY, 0644);
else
{
int err = utils::make_file_size(file, size);
if(err)
{
utils::to_log(LOG_LEVEL_FATAL, "FileMapping: make file(%s) size(%ld) = %d\n", file, size, err);
return err;
}
map_ = (HANDLE)::open(file, O_RDWR, 0666);
utils::to_log(LOG_LEVEL_DEBUG, "FileMapping: open('%s', O_APPEND, 0666) = %p\n", file, map_);
}
if (map_ == INVALID_HANDLE_VALUE)
{
int err = errno;
if(!readonly)
remove(file);
utils::to_log(LOG_LEVEL_WARNING, "FileMapping: create mapping object for '%s' failed: %d.\n", file, err);
return err;
}
#endif
path_file_ = file;
total_ = size;
read_only_ = readonly;
return 0;
}
int file_map::close(void)
{
unmap();
if (map_ != INVALID_HANDLE_VALUE)
#if OS_WIN
CloseHandle(map_);
#else
::close((int)(long)map_);
#endif
map_ = INVALID_HANDLE_VALUE;
total_ = 0;
return 0;
}
uint64_t file_map::total_size(void)
{
return total_;
}
uint8_t* file_map::map(uint64_t off, uint32_t* size)
{
uint32_t len = 0;
unmap();
if (!size)
size = &len;
if (off < total_)
{
DWORD hi = 0,
lo = 0,
cnt = 0;
map_off_ = off / os_map_size_ * os_map_size_;
off_ = off - map_off_;
hi = map_off_ >> 32;
lo = map_off_;
cnt = total_ - map_off_;
if (cnt - off > *size && *size)
{
cnt = ALIGN_TO(*size + off, os_map_size_);
if(cnt > total_ - map_off_)
cnt = total_ - map_off_;
}
map_size_ = cnt;
#if OS_WIN
buf_ = (uint8_t*)MapViewOfFile(map_, read_only_ ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE, hi, lo, map_size_);
#else
int priv = PROT_READ, prot = MAP_PRIVATE;
if (!read_only_)
{
priv |= PROT_WRITE;
prot = MAP_SHARED;
}
buf_ = (uint8_t*)mmap(nullptr, map_size_, priv, prot, (int)(long)map_, map_off_);
if(buf_ == INVALID_HANDLE_VALUE)
buf_ = nullptr;
#endif
if (!buf_)
{
utils::to_log(LOG_LEVEL_WARNING, "FileMapping: request map(%p + %u), real map(%p + %u) failed: %d\n"
, off, *size, map_off_, map_size_, GetLastError());
*size = 0;
}
else
*size = cnt - off;
}
return buf_ ? buf_ + off_ : nullptr;
}
uint8_t* file_map::buffer(void)
{
return buf_ ? buf_ + off_ : nullptr;
}

View File

@ -47,6 +47,35 @@ public:
void set_progress_notify(PROGRESS_NOTIFYER notify = PROGRESS_NOTIFYER(), void* param = nullptr); void set_progress_notify(PROGRESS_NOTIFYER notify = PROGRESS_NOTIFYER(), void* param = nullptr);
}; };
class file_map : public refer
{
bool read_only_ = false; //
uint32_t os_map_size_ = 0; // desired mapping size of OS
uint64_t total_ = 0; // total size of the whole file
HANDLE map_ = INVALID_HANDLE_VALUE; // handle of the map-object
std::string path_file_; // local file
uint64_t map_off_ = 0; // offset in the file of current mapping buffer
uint32_t map_size_ = 0; // size of current mapping buffer
uint32_t off_ = 0; // offset to align to os_map_size_
uint8_t* buf_ = nullptr; // current mapping buffer
void unmap(void);
public:
file_map();
protected:
~file_map();
public:
int open(const char* file, uint64_t size, bool readonly);
int close(void);
uint64_t total_size(void);
uint8_t* map(uint64_t off = 0, uint32_t* size = 0); // size - in: desired size, 0 is from off to end; out: real size
uint8_t* buffer(void);
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //
/* data_holder, used when data is also required for a certain packet /* data_holder, used when data is also required for a certain packet
@ -112,6 +141,7 @@ class file_saver : public data_holder
std::string path_; std::string path_;
std::string check_; std::string check_;
FILE *dst_; FILE *dst_;
file_map *map_ = nullptr;
uint32_t pack_cmd_; uint32_t pack_cmd_;
uint32_t pack_id_; uint32_t pack_id_;
@ -123,7 +153,8 @@ protected:
~file_saver(); ~file_saver();
public: public:
int open(const char* path, uint64_t size, const char* check = nullptr); int set_verify_data(const char* data, size_t len);
int open(const char* path, uint64_t size, bool in_mem = false, size_t off = 0);
public: public:
virtual int put_data(const void* data, uint32_t* size/*[in] - total bytes of data; [out] - used bytes*/) override; virtual int put_data(const void* data, uint32_t* size/*[in] - total bytes of data; [out] - used bytes*/) override;
@ -204,9 +235,10 @@ public:
class file_reader : public data_source class file_reader : public data_source
{ {
size_t len_; size_t len_;
size_t consume_; size_t consume_;
FILE *src_; FILE *src_ = nullptr;
file_map *map_ = nullptr;
std::string path_; std::string path_;
public: public:
@ -216,7 +248,7 @@ protected:
~file_reader(); ~file_reader();
public: public:
int open(const char* file); int open(const char* file, bool in_mem, size_t off = 0);
int attach(FILE* f); int attach(FILE* f);
FILE* detach(void); FILE* detach(void);
@ -231,6 +263,7 @@ public:
virtual int fetch_data(void* buf, uint32_t* size) override; virtual int fetch_data(void* buf, uint32_t* size) override;
}; };
CLS_PTR(packet_data_base); CLS_PTR(packet_data_base);
CLS_PTR(data_holder); CLS_PTR(data_holder);
CLS_PTR(mem_holder); CLS_PTR(mem_holder);
@ -251,7 +284,7 @@ CLS_PTR(file_reader);
// //
// when invalid packet, suggest use the entire data // when invalid packet, suggest use the entire data
// //
// packet_data_base_ptr* - return data_holder or data_source or nullptr <EFBFBD><EFBFBD>The number of bytes required for this packet, 0 is over for this packet<65><74> // packet_data_base_ptr* - return data_holder or data_source or nullptr £¨The number of bytes required for this packet, 0 is over for this packet£©
// //
// data_holder: the packet/command need more data than dyn_mem_ptr provides to complete the business. such as 'write a large file' // data_holder: the packet/command need more data than dyn_mem_ptr provides to complete the business. such as 'write a large file'
// //

View File

@ -50,13 +50,13 @@ enum ep0_req
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 USB_REQ_EP0_SET_BULK_BUFFER, // 设置bulk缓冲区大小系数 req = me, ind = coef, val = 0, len = 0
}; };
enum bulk_status enum woker_status
{ {
BULK_STATUS_NOT_START = 0, // has not initialized WORKER_STATUS_NOT_START = 0, // has not start
BULK_STATUS_IDLE, // wait IO WORKER_STATUS_IDLE, // idle
BULK_STATUS_IO, // in reading or writing WORKER_STATUS_BUSY, // in working
BULK_STATUS_ERROR, // error occurs WORKER_STATUS_ERROR, // error occurs
BULK_STATUS_RESET, // in reset(close and reopen) process WORKER_STATUS_RESET, // in reset(close and reopen) process
}; };
enum packet_cmd enum packet_cmd

View File

@ -24,6 +24,7 @@
#if !OS_WIN // migrate codes from windows to linux ... #if !OS_WIN // migrate codes from windows to linux ...
#include <unistd.h> #include <unistd.h>
#include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#include <dlfcn.h> #include <dlfcn.h>
#include <semaphore.h> #include <semaphore.h>
@ -97,6 +98,7 @@ typedef int BOOL;
#define USB_TIMEOUT_INFINITE 0 #define USB_TIMEOUT_INFINITE 0
#define FSEEK fseek #define FSEEK fseek
#define FTELL ftell #define FTELL ftell
#define INVALID_HANDLE_VALUE ((HANDLE)(-1))
extern DWORD GetLastError(void); extern DWORD GetLastError(void);
@ -104,8 +106,8 @@ extern DWORD GetPrivateProfileIntA(const char* app, const char* key, DWORD def,
extern DWORD GetPrivateProfileStringA(const char* app, const char* key, const char* init, char* buf, size_t len, const char* file); extern DWORD GetPrivateProfileStringA(const char* app, const char* key, const char* init, char* buf, size_t len, const char* file);
extern void Sleep(DWORD milliseconds); extern void Sleep(DWORD milliseconds);
extern int GetModuleFileNameA(HMODULE module, char* buf, size_t len); // NOTE: parameter 'module' is consinder as a part of the module file name extern int GetModuleFileNameA(HMODULE module, char* buf, size_t len); // NOTE: parameter 'module' is consinder as a part of the module file name
extern int GetCurrentProcessId(void); extern uint64_t GetCurrentProcessId(void);
extern int GetCurrentThreadId(void); extern uint64_t GetCurrentThreadId(void);
#else #else
#include <Windows.h> #include <Windows.h>

View File

@ -196,13 +196,13 @@ int GetModuleFileNameA(HMODULE module, char* buf, size_t len)
return len; return len;
} }
int GetCurrentThreadId(void) uint64_t GetCurrentThreadId(void)
{ {
return pthread_self(); return (uint64_t)pthread_self();
} }
int GetCurrentProcessId(void) uint64_t GetCurrentProcessId(void)
{ {
return getpid(); return (uint64_t)getpid();
} }
#endif #endif
@ -236,7 +236,7 @@ class log_cls
} }
else else
{ {
std::string sep("\n\n===================================================================================================================\n"); std::string sep("\n\n========================================================================================================================\n");
fwrite(sep.c_str(), sizeof(sep[0]), sep.length(), file_); fwrite(sep.c_str(), sizeof(sep[0]), sep.length(), file_);
} }
@ -575,10 +575,18 @@ namespace utils
} }
rv = fread(buf, 1, sizeof(buf) - 1, src); rv = fread(buf, 1, sizeof(buf) - 1, src);
} }
if(rv == -1 && err)
{
*err = errno;
utils::to_log(LOG_LEVEL_DEBUG, "Failed to excute shell command '%s' in read pipe: %d - %s\n", cmd, errno, strerror(errno));
}
pclose(src); pclose(src);
} }
else if(err) else if(err)
{
*err = errno; *err = errno;
utils::to_log(LOG_LEVEL_DEBUG, "Failed to excute shell command '%s' in open pipe: %d - %s\n", cmd, errno, strerror(errno));
}
#endif #endif
return std::move(result); return std::move(result);
@ -978,6 +986,36 @@ namespace utils
{ {
return rename(from, to); return rename(from, to);
} }
int make_file_size(const char* file, uint64_t size)
{
int err = 0;
get_command_result(("fallocate -l " + std::to_string(size) + " " + file).c_str(), -1, &err);
if(err == 0)
{
get_command_result(("truncate -s " + std::to_string(size) + " " + file).c_str(), -1, &err);
if(err == 0)
{
FILE* dst = fopen(file, "rb");
if(dst)
{
uint64_t rs = 0;
FSEEK(dst, 0, SEEK_END);
rs = FTELL(dst);
fclose(dst);
if(rs != size)
err = ENOSPC;
}
else
err = errno;
}
}
if(err)
remove(file);
return err;
}
int get_disk_space(const char* path, unsigned long long* total, unsigned long long* avail, unsigned long long* block) int get_disk_space(const char* path, unsigned long long* total, unsigned long long* avail, unsigned long long* block)
{ {
@ -1049,7 +1087,7 @@ namespace utils
return ps; return ps;
} }
void init_log(log_type type, log_level level, const char* fn_appendix) std::string init_log(log_type type, log_level level, const char* fn_appendix)
{ {
std::string file(""); std::string file("");
@ -1072,6 +1110,8 @@ namespace utils
log_cls::instance()->set_log_type(type, &file[0]); log_cls::instance()->set_log_type(type, &file[0]);
log_cls::instance()->set_log_level(level); log_cls::instance()->set_log_level(level);
return std::move(file);
} }
void uninit(void) void uninit(void)
{ {
@ -1872,22 +1912,22 @@ safe_thread::~safe_thread()
threads_.clear(); threads_.clear();
} }
void safe_thread::thread_worker(std::function<void(void)> func, std::string name) void safe_thread::thread_worker(std::function<void(void)> func, std::string name, void* addr)
{ {
try try
{ {
utils::to_log(LOG_LEVEL_DEBUG, "+++ safe_thread of '%s' is running ...\n", name.c_str()); utils::to_log(LOG_LEVEL_DEBUG, "+++ safe_thread of '%s(%p) - %p' is running ...\n", name.c_str(), addr, GetCurrentThreadId());
func(); func();
utils::to_log(LOG_LEVEL_DEBUG, "--- safe_thread of '%s' exited.\n", name.c_str()); utils::to_log(LOG_LEVEL_DEBUG, "--- safe_thread of '%s - %p' exited.\n", name.c_str(), GetCurrentThreadId());
return; return;
} }
catch (std::exception e) catch (std::exception e)
{ {
utils::to_log(LOG_LEVEL_FATAL, "Exception in thread '%s': %s\n", name.c_str(), e.what()); utils::to_log(LOG_LEVEL_FATAL, "Exception in thread '%p - %s': %s\n", GetCurrentThreadId(), name.c_str(), e.what());
} }
catch (...) catch (...)
{ {
utils::to_log(LOG_LEVEL_FATAL, "Unknown exception in thread '%s'!\n", name.c_str()); utils::to_log(LOG_LEVEL_FATAL, "Unknown exception in thread '%p - %s'!\n", GetCurrentThreadId(), name.c_str());
} }
excep_que_.save(name, true); excep_que_.save(name, true);
} }
@ -1908,12 +1948,12 @@ void safe_thread::set_exception_handler(std::function<void(const char*)> on_exce
{ {
excep_handler_ = on_exception; excep_handler_ = on_exception;
} }
int safe_thread::start(std::function<void(void)> f, const char* thread_name) int safe_thread::start(std::function<void(void)> f, const char* thread_name, void* addr)
{ {
SAFETHRD st; SAFETHRD st;
st.name = thread_name ? thread_name : ""; st.name = thread_name ? thread_name : "";
st.thread.reset(new std::thread(&safe_thread::thread_worker, this, f, thread_name)); st.thread.reset(new std::thread(&safe_thread::thread_worker, this, f, thread_name, addr));
{ {
SIMPLE_LOCK(lock_); SIMPLE_LOCK(lock_);

View File

@ -57,11 +57,13 @@ namespace utils
void set_ini_value(const char* seg, const char* key, const char* val, const char* cfg_file); void set_ini_value(const char* seg, const char* key, const char* val, const char* cfg_file);
int enum_file(const char* folder, bool recursive, bool/*return false to stop enumeration*/(STDCALL* found)(const char* path_name, bool dir, void* param), void* param); int enum_file(const char* folder, bool recursive, bool/*return false to stop enumeration*/(STDCALL* found)(const char* path_name, bool dir, void* param), void* param);
int move_file(const char* from, const char* to); int move_file(const char* from, const char* to);
int make_file_size(const char* file, uint64_t size); // truncate or extend file size to 'size', create if not exist
int get_disk_space(const char* path, unsigned long long* total, unsigned long long* avail, unsigned long long* block); int get_disk_space(const char* path, unsigned long long* total, unsigned long long* avail, unsigned long long* block);
unsigned int get_page_size(unsigned int* map_unit = nullptr); unsigned int get_page_size(unsigned int* map_unit = nullptr);
void init_log(log_type type, log_level level = LOG_LEVEL_ALL, const char* fn_appendix = nullptr/*appendix to default log-file-name*/); // return logging file path if 'type' was LOG_TYPE_FILE
std::string init_log(log_type type, log_level level = LOG_LEVEL_ALL, const char* fn_appendix = nullptr/*appendix to default log-file-name*/);
void uninit(void); void uninit(void);
void log_info(const char* info, int level = LOG_LEVEL_ALL); void log_info(const char* info, int level = LOG_LEVEL_ALL);
void log_mem_info(const char* desc, const void* data, size_t bytes, int level = LOG_LEVEL_ALL); // log as 0x12345678 00 01 02 ... void log_mem_info(const char* desc, const void* data, size_t bytes, int level = LOG_LEVEL_ALL); // log as 0x12345678 00 01 02 ...
@ -354,7 +356,7 @@ class safe_thread
safe_fifo<std::string> excep_que_; safe_fifo<std::string> excep_que_;
std::function<void(const char*)> excep_handler_ = std::function<void(const char*)>(); std::function<void(const char*)> excep_handler_ = std::function<void(const char*)>();
void thread_worker(std::function<void(void)> func, std::string name); void thread_worker(std::function<void(void)> func, std::string name, void* addr);
void thread_notify_exception(void); void thread_notify_exception(void);
public: public:
@ -363,6 +365,6 @@ public:
public: public:
void set_exception_handler(std::function<void(const char*)> on_exception = std::function<void(const char*)>()); void set_exception_handler(std::function<void(const char*)> on_exception = std::function<void(const char*)>());
int start(std::function<void(void)> f, const char* thread_name); int start(std::function<void(void)> f, const char* thread_name, void* addr = nullptr);
int stop(const char* thread_name); int stop(const char* thread_name);
}; };

View File

@ -1158,13 +1158,42 @@ void device_option::insert_option(gb_json* opt, sane_opt_provider* from, const c
} }
else else
{ {
int index = -1; int index = -1, pos = -1;
if (group) if (group)
index = insert_group(group, group); index = insert_group(group, group);
index = next_group(index + 1);
// insert poisition according to 'ui-pos'
if (!opt->get_value("ui-pos", pos) || pos == -1)
{
index = next_group(index + 1);
}
else
{
for (index++; index < origin_->children(); ++index)
{
gb_json* sib = origin_->child(index);
std::string t("");
int sit = -1;
if (!sib->get_value("type", t) || t == JSON_SANE_TYPE_GROUP)
{
sib->release();
break;
}
if (!sib->get_value("ui-pos", sit) || sit == -1)
{
sib->release();
break;
}
sib->release();
if (pos < sit)
break;
}
}
origin_->insert(index, opt->key().c_str(), opt); origin_->insert(index, opt->key().c_str(), opt);
src_[opt->key()] = from; src_[opt->key()] = from;
from->add_ref(); from->add_ref();
} }
@ -1310,7 +1339,24 @@ gb_json* device_option::copy_opt(gb_json* from)
// 2: enabled ... // 2: enabled ...
if (slaver_.count(to->key())) if (slaver_.count(to->key()))
to->set_value("enabled", slaver_[to->key()]->value(&device_option::calc_simple_logic_expression, this)); {
bool enable = slaver_[to->key()]->value(&device_option::calc_simple_logic_expression, this);
to->set_value("enabled", enable);
if (src_.count(to->key()))
{
src_[to->key()]->enable(to->key().c_str(), enable);
sane_opt_provider* next = src_[to->key()]->get_following(to->key().c_str());
while (next)
{
next->enable(to->key().c_str(), enable);
sane_opt_provider* next1 = next->get_following(to->key().c_str());
next->release();
next = next1;
}
}
}
// 3: default value ... // 3: default value ...
if (init_value_.count(to->key())) if (init_value_.count(to->key()))

View File

@ -688,6 +688,25 @@ int usb_device::close_device(void)
} }
int usb_device::pull_up(std::string* msg) int usb_device::pull_up(std::string* msg)
{ {
{
int dst = open(udc_.c_str(), O_RDWR);
if(dst == -1)
utils::to_log(LOG_LEVEL_DEBUG, "Try write '%s' to '%s' failed(open): %s\n", dwc3_.c_str(), udc_.c_str(), strerror(errno));
else
{
int l = write(dst, dwc3_.c_str(), dwc3_.length()),
err = errno;
close(dst);
if(l == dwc3_.length())
{
utils::to_log(LOG_LEVEL_DEBUG, "pull up device by write '%s' to '%s' directly success.\n", dwc3_.c_str(), udc_.c_str());
return 0;
}
else
utils::to_log(LOG_LEVEL_DEBUG, "Try write '%s' to '%s' failed(write): %s\n", dwc3_.c_str(), udc_.c_str(), strerror(errno));
}
}
std::string cmd("echo " + pwd_ + " | sudo -S sh -c \"echo " + dwc3_ + " > " + udc_ + "\""); std::string cmd("echo " + pwd_ + " | sudo -S sh -c \"echo " + dwc3_ + " > " + udc_ + "\"");
int err = 0; int err = 0;
std::string info(utils::get_command_result(cmd.c_str(), -1, &err)); std::string info(utils::get_command_result(cmd.c_str(), -1, &err));

View File

@ -21,7 +21,8 @@ async_usb_gadget::async_usb_gadget(std::function<FUNCTION_PROTO_COMMAND_HANDLE>
, cmd_que_("in-queue"), sent_que_("out-queue") , cmd_que_("in-queue"), sent_que_("out-queue")
, wait_in_("wait_usb_enable_in"), wait_out_("wait_usb_enable_out") , wait_in_("wait_usb_enable_in"), wait_out_("wait_usb_enable_out")
{ {
memset((void*)&status_, 0, sizeof(status_)); cmd_que_.enable_wait_log(false);
sent_que_.enable_wait_log(false);
dev_ = new usb_device("fe900000.dwc3", "/opt/cfg/usb_gadget/g1/UDC", "linaro"); dev_ = new usb_device("fe900000.dwc3", "/opt/cfg/usb_gadget/g1/UDC", "linaro");
dev_->add_endpoint(USB_EP_BULK_IN, true, true); dev_->add_endpoint(USB_EP_BULK_IN, true, true);
@ -87,10 +88,10 @@ async_usb_gadget::async_usb_gadget(std::function<FUNCTION_PROTO_COMMAND_HANDLE>
threads_.set_exception_handler(excep); threads_.set_exception_handler(excep);
unit_in_ = unit_out_ = dev_->get_max_packet(); unit_in_ = unit_out_ = dev_->get_max_packet();
threads_.start(task, "thread_pump_task"); threads_.start(task, "thread_pump_task", (void*)&async_usb_gadget::thread_pump_task);
threads_.start(bulkw, "thread_read_bulk"); threads_.start(bulkw, "thread_write_bulk", (void*)&async_usb_gadget::thread_write_bulk);
threads_.start(bulkr, "thread_write_bulk"); threads_.start(bulkr, "thread_read_bulk", (void*)&async_usb_gadget::thread_read_bulk);
threads_.start(ep0, "thread_read_ep0"); threads_.start(ep0, "thread_read_ep0", (void*)&async_usb_gadget::thread_read_ep0);
} }
async_usb_gadget::~async_usb_gadget() async_usb_gadget::~async_usb_gadget()
@ -149,19 +150,19 @@ dyn_mem_ptr async_usb_gadget::handle_ctrl_message(dyn_mem_ptr data)
switch (pev->type) switch (pev->type)
{ {
case FUNCTIONFS_ENABLE: case FUNCTIONFS_ENABLE:
utils::to_log(LOG_LEVEL_ALL, "EP0 FFS ENABLE\n");
online_ = true;
session_id_++; session_id_++;
utils::to_log(LOG_LEVEL_DEBUG, "////////////// EP0 FFS ENABLE, start session %u ...\n", session_id_);
online_ = true;
wait_in_.trigger(); wait_in_.trigger();
wait_out_.trigger(); wait_out_.trigger();
if(dev_connect_) if(dev_connect_)
dev_connect_(true); dev_connect_(online_);
break; break;
case FUNCTIONFS_DISABLE: case FUNCTIONFS_DISABLE:
utils::to_log(LOG_LEVEL_ALL, "EP0 FFS DISABLE\n");
online_ = false; online_ = false;
if(dev_connect_) if(dev_connect_)
dev_connect_(false); dev_connect_(online_);
utils::to_log(LOG_LEVEL_DEBUG, "////////////// EP0 FFS DISABLE, end session %u ...\n\n", session_id_);
break; break;
case FUNCTIONFS_SETUP: case FUNCTIONFS_SETUP:
reply = handle_ctrl_setup(data); reply = handle_ctrl_setup(data);
@ -219,8 +220,17 @@ dyn_mem_ptr async_usb_gadget::handle_ctrl_setup(dyn_mem_ptr data)
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));
reply->set_len(sizeof(struct _ep0_reply));
{ {
reply->put((void*)&status_, sizeof(status_)); LPEP0REPLYSTATUS lps = (LPEP0REPLYSTATUS)reply->ptr();
lps->in_status = statu_in_;
lps->out_status = statu_out_;
lps->task_cmd = task_cmd_;
lps->task_pack_id = task_packet_id_;
lps->task_required_bytes = want_bytes_task_;
lps->packets_to_sent = sent_que_.size();
lps->bytes_to_sent = want_bytes_in_;
utils::log_mem_info("threads status:", lps, sizeof(*lps), LOG_LEVEL_DEBUG);
} }
break; break;
case USB_REQ_EP0_RESET_BULK: case USB_REQ_EP0_RESET_BULK:
@ -255,6 +265,8 @@ dyn_mem_ptr async_usb_gadget::handle_ctrl_setup(dyn_mem_ptr data)
utils::to_log(LOG_LEVEL_ALL, "EP0 event(0x%x, 0x%x, 0x%x, 0x%x, 0x%x) has not handled by user business.\n" utils::to_log(LOG_LEVEL_ALL, "EP0 event(0x%x, 0x%x, 0x%x, 0x%x, 0x%x) has not handled by user business.\n"
, pev->u.setup.bRequestType, pev->u.setup.bRequest, pev->u.setup.wValue, pev->u.setup.wIndex, pev->u.setup.wLength); , pev->u.setup.bRequestType, pev->u.setup.bRequest, pev->u.setup.wValue, pev->u.setup.wIndex, pev->u.setup.wLength);
} }
if(reply)
reply->set_session_id(data->get_session_id());
return reply; return reply;
} }
@ -264,13 +276,16 @@ int async_usb_gadget::inner_write_bulk(int fd, data_source_ptr data, int* err)
size_t bulk_size = unit_in_ * get_buf_coefficient(), size_t bulk_size = unit_in_ * get_buf_coefficient(),
total = data->get_rest(), off = 0, size = total > bulk_size ? bulk_size : total; total = data->get_rest(), off = 0, size = total > bulk_size ? bulk_size : total;
int w = 0; int w = 0;
bool fail = false;
statu_in_ = WORKER_STATUS_BUSY;
want_bytes_in_ = total;
if(data->is_memory_block()) if(data->is_memory_block())
{ {
while((w = write(fd, ptr + off, size)) > 0) while((w = write(fd, ptr + off, size)) > 0)
{ {
off += w; off += w;
status_.bytes_to_sent -= w; want_bytes_in_ -= w;
if(off >= total) if(off >= total)
break; break;
if(off + bulk_size < total) if(off + bulk_size < total)
@ -279,7 +294,10 @@ int async_usb_gadget::inner_write_bulk(int fd, data_source_ptr data, int* err)
size = total - off; size = total - off;
} }
if(w <= 0 && err) if(w <= 0 && err)
{
*err = errno; *err = errno;
}
fail = w <= 0;
} }
else else
{ {
@ -296,7 +314,7 @@ int async_usb_gadget::inner_write_bulk(int fd, data_source_ptr data, int* err)
w = write(fd, ptr + off, len); w = write(fd, ptr + off, len);
while(w > 0 && w + off < len) while(w > 0 && w + off < len)
{ {
status_.bytes_to_sent -= w; want_bytes_in_ -= w;
total += w; total += w;
off += w; off += w;
w = write(fd, ptr + off, len - off); w = write(fd, ptr + off, len - off);
@ -304,14 +322,14 @@ int async_usb_gadget::inner_write_bulk(int fd, data_source_ptr data, int* err)
if(w <= 0) if(w <= 0)
{ {
fail = true;
if(err) if(err)
*err = errno; *err = errno;
utils::to_log(LOG_LEVEL_ALL, "inner_write_bulk error(%d/%d): %d (%s)\n", off, len, errno, strerror(errno));
break; break;
} }
else else
{ {
status_.bytes_to_sent -= w; want_bytes_in_ -= w;
total += w; total += w;
} }
@ -322,6 +340,8 @@ int async_usb_gadget::inner_write_bulk(int fd, data_source_ptr data, int* err)
buf->release(); buf->release();
off = total; off = total;
} }
statu_in_ = fail ? WORKER_STATUS_ERROR : WORKER_STATUS_IDLE;
want_bytes_in_ = 0;
return off; return off;
} }
@ -358,7 +378,6 @@ void async_usb_gadget::thread_read_ep0(void)
std::string msg(""); std::string msg("");
struct usb_functionfs_event* pe = (struct usb_functionfs_event*)ptr; struct usb_functionfs_event* pe = (struct usb_functionfs_event*)ptr;
utils::to_log(LOG_LEVEL_ALL, "EP0 monitoring thread(%p of id %lx) started ...\n", &async_usb_gadget::thread_read_ep0, getpid());
ret = dev_->pull_up(&msg); ret = dev_->pull_up(&msg);
while(run_) while(run_)
{ {
@ -424,17 +443,17 @@ void async_usb_gadget::thread_read_bulk(int fd)
dyn_mem_ptr buf(dyn_mem::memory(bulk_size)); dyn_mem_ptr buf(dyn_mem::memory(bulk_size));
int l = 0; int l = 0;
status_.out_status = BULK_STATUS_IO; statu_out_ = WORKER_STATUS_BUSY;
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;
if(l <= 0) if(l <= 0)
{ {
buf->release(); buf->release();
if(errno) if(errno)
{ {
utils::to_log(LOG_LEVEL_ALL, "read bulk(%d) failed: %d(%s)\n", l, errno, strerror(errno)); utils::to_log(LOG_LEVEL_ALL, "read bulk(%d) failed: %d(%s)\n", l, errno, strerror(errno));
status_.out_status = BULK_STATUS_ERROR; statu_out_ = WORKER_STATUS_ERROR;
status_.out_err = errno;
break; break;
} }
else else
@ -446,22 +465,19 @@ void async_usb_gadget::thread_read_bulk(int fd)
{ {
utils::to_log(LOG_LEVEL_ALL, "thread_read_bulk do reset-bulk ...\n"); utils::to_log(LOG_LEVEL_ALL, "thread_read_bulk do reset-bulk ...\n");
buf->release(); buf->release();
if(!run_) break;
break;
} }
else else
{ {
status_.out_status = BULK_STATUS_IDLE;
buf->set_len(l); buf->set_len(l);
cmd_que_.save(buf, true); cmd_que_.save(buf, true);
} }
} }
if(status_.out_status == BULK_STATUS_IDLE) statu_out_ = WORKER_STATUS_NOT_START;
status_.out_status = BULK_STATUS_NOT_START;
} }
void async_usb_gadget::thread_write_bulk(int fd) void async_usb_gadget::thread_write_bulk(int fd)
{ {
status_.in_status = BULK_STATUS_IDLE; statu_in_ = WORKER_STATUS_IDLE;
while(run_) while(run_)
{ {
data_source_ptr data; data_source_ptr data;
@ -469,24 +485,17 @@ void async_usb_gadget::thread_write_bulk(int fd)
if(sent_que_.take(data, true)) if(sent_que_.take(data, true))
{ {
status_.packets_to_sent = sent_que_.size(); want_bytes_in_ = data->get_rest();
status_.bytes_to_sent = data->get_rest();
status_.in_status = BULK_STATUS_IO;
inner_write_bulk(fd, data, &err); inner_write_bulk(fd, data, &err);
status_.in_status = BULK_STATUS_IDLE;
status_.bytes_to_sent = 0;
data->release(); data->release();
if(err) if(err)
{ {
utils::to_log(LOG_LEVEL_ALL, "write bulk failed: %d(%s)\n", errno, strerror(errno)); utils::to_log(LOG_LEVEL_ALL, "write bulk failed: %d(%s)\n", errno, strerror(errno));
status_.in_status = BULK_STATUS_ERROR;
status_.in_err = err;
break; break;
} }
} }
} }
if(status_.in_status == BULK_STATUS_IDLE) statu_in_ = WORKER_STATUS_NOT_START;
status_.in_status = BULK_STATUS_NOT_START;
} }
void async_usb_gadget::thread_pump_task(void) void async_usb_gadget::thread_pump_task(void)
{ {
@ -500,11 +509,12 @@ void async_usb_gadget::thread_pump_task(void)
while(run_) while(run_)
{ {
data = nullptr; data = nullptr;
statu_task_ = WORKER_STATUS_IDLE;
if(cmd_que_.take(data, true) && data) if(cmd_que_.take(data, true) && data)
{ {
status_.task_cnt = cmd_que_.size(); statu_task_ = WORKER_STATUS_BUSY;
if(max_que < status_.task_cnt) if(max_que < cmd_que_.size())
max_que = status_.task_cnt; max_que = cmd_que_.size();
if(prev) if(prev)
{ {
@ -549,8 +559,9 @@ void async_usb_gadget::thread_pump_task(void)
else else
{ {
pack = (LPPACK_BASE)data->ptr(); pack = (LPPACK_BASE)data->ptr();
status_.task_cmd = pack->cmd; task_cmd_ = pack->cmd;
status_.task_pack_id = pack->pack_id; task_packet_id_ = pack->pack_id;
want_bytes_task_ = 0;
used = data->get_rest(); used = data->get_rest();
reply = handle_bulk_command(data, &used, &pack_data); reply = handle_bulk_command(data, &used, &pack_data);
notify_reply_ok = used & (INT32_MAX + 1); notify_reply_ok = used & (INT32_MAX + 1);
@ -564,9 +575,14 @@ void async_usb_gadget::thread_pump_task(void)
ds = dynamic_cast<data_source_ptr>(pack_data); ds = dynamic_cast<data_source_ptr>(pack_data);
if(!ds) if(!ds)
pack_data->release(); pack_data->release();
else
want_bytes_task_ = ds->get_rest();
} }
else else
{
total_size = 0; total_size = 0;
want_bytes_task_ = dh->get_required();
}
} }
} }
} }
@ -588,10 +604,15 @@ void async_usb_gadget::thread_pump_task(void)
BASE_PACKET_REPLY(*pack, dh->get_packet_command() + 1, dh->get_packet_id(), err); BASE_PACKET_REPLY(*pack, dh->get_packet_command() + 1, dh->get_packet_id(), err);
reply->set_len(sizeof(PACK_BASE)); reply->set_len(sizeof(PACK_BASE));
utils::to_log(LOG_LEVEL_ALL, "Finished receiving file with error(Max queue size is %u): %d, total size = 0x%x\n", max_que, err, total_size); utils::to_log(LOG_LEVEL_ALL, "Finished receiving large data with error(Max queue size is %u): %d, total size = 0x%x\n", max_que, err, total_size);
dh->release(); dh->release();
dh = nullptr; dh = nullptr;
want_bytes_task_ = 0;
}
else
{
want_bytes_task_ = dh->get_required();
} }
used = len; used = len;
@ -612,7 +633,7 @@ void async_usb_gadget::thread_pump_task(void)
reply->release(); reply->release();
reply = enc; reply = enc;
} }
reply->set_session_id(data->get_session_id());
write_bulk(dynamic_cast<data_source_ptr>(reply)); write_bulk(dynamic_cast<data_source_ptr>(reply));
if(notify_reply_ok) if(notify_reply_ok)
handle_bulk_command(data, nullptr, nullptr); handle_bulk_command(data, nullptr, nullptr);
@ -628,17 +649,19 @@ void async_usb_gadget::thread_pump_task(void)
ds = nullptr; ds = nullptr;
} }
status_.task_required_bytes = dh ? dh->get_required() : 0;
if(status_.task_required_bytes == 0)
status_.task_cmd = status_.task_pack_id = 0;
data->used(used); data->used(used);
}while(used && data->get_rest()); }while(used && data->get_rest());
if(data->get_rest()) if(data->get_rest())
prev = data; prev = data;
else else
{
if(!dh)
{
task_cmd_ = task_packet_id_ = want_bytes_task_ = 0;
}
data->release(); data->release();
}
} }
} }
if(prev) if(prev)
@ -674,7 +697,7 @@ int async_usb_gadget::write_bulk(data_source_ptr data)
{ {
if(data->get_session_id() != session_id_ || !online_) if(data->get_session_id() != session_id_ || !online_)
{ {
utils::to_log(LOG_LEVEL_DEBUG, "Discard packet for the session ID(%u) is not equal current session(%u) or is offline.\n", data->get_session_id(), session_id_); utils::to_log(LOG_LEVEL_DEBUG, "Discard reply packet for the session ID(%u) is not equal current session(%u) or is offline.\n", data->get_session_id(), session_id_);
data->release(); data->release();
return sent_que_.size(); return sent_que_.size();
@ -692,4 +715,4 @@ int async_usb_gadget::write_bulk(data_source_ptr data)
int async_usb_gadget::last_error(void) int async_usb_gadget::last_error(void)
{ {
return last_err_; return last_err_;
} }

View File

@ -59,7 +59,16 @@ class async_usb_gadget : public refer
uint8_t enc_data_; uint8_t enc_data_;
int last_err_ = 0; int last_err_ = 0;
volatile EP0REPLYSTATUS status_; uint8_t statu_in_ = WORKER_STATUS_NOT_START;
uint32_t want_bytes_in_ = 0;
uint8_t statu_out_ = WORKER_STATUS_NOT_START;
uint8_t statu_task_ = WORKER_STATUS_NOT_START;
uint32_t want_bytes_task_ = 0;
uint32_t task_cmd_ = 0;
uint32_t task_packet_id_ = 0;
safe_fifo<dyn_mem_ptr> cmd_que_; safe_fifo<dyn_mem_ptr> cmd_que_;
safe_fifo<data_source_ptr> sent_que_; safe_fifo<data_source_ptr> sent_que_;