930 lines
21 KiB
C++
930 lines
21 KiB
C++
#include "scanner_handler.h"
|
|
|
|
|
|
#include "./usb/async_usb_host.h"
|
|
#include <log_util.h>
|
|
#include <json/json.h>
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// cmd_result
|
|
|
|
MUTEX cmd_result::lock_;
|
|
uint32_t cmd_result::pack_id_ = 1;
|
|
|
|
cmd_result::cmd_result(std::function<int(cmd_result*)> call,
|
|
std::function<int(cmd_result*)> clean,
|
|
std::function<dyn_mem_ptr(dyn_mem_ptr, uint32_t*, packet_data_base_ptr*, cmd_result*)> roger,
|
|
void* param, uint32_t id)
|
|
: wait_(new linux_event("wait_reply")), id_(id == 0 ? cmd_result::gen_pack_id() : id)
|
|
, call_(call), clean_(clean), roger_(roger), param_(param), err_(0), to_(1000), over_(false)
|
|
{
|
|
}
|
|
cmd_result::~cmd_result()
|
|
{
|
|
wait_->release();
|
|
}
|
|
|
|
uint32_t cmd_result::gen_pack_id(void)
|
|
{
|
|
LOCKER lock(cmd_result::lock_);
|
|
|
|
return cmd_result::pack_id_++;
|
|
}
|
|
|
|
uint32_t cmd_result::get_id(void)
|
|
{
|
|
return id_;
|
|
}
|
|
uint32_t cmd_result::set_timeout(uint32_t timeout)
|
|
{
|
|
uint32_t prev = to_;
|
|
|
|
to_ = timeout;
|
|
|
|
return prev;
|
|
}
|
|
void* cmd_result::get_param(void)
|
|
{
|
|
return param_;
|
|
}
|
|
void* cmd_result::set_param(void* param)
|
|
{
|
|
void* r = param_;
|
|
|
|
param_ = param;
|
|
|
|
return r;
|
|
}
|
|
bool cmd_result::wait(void)
|
|
{
|
|
return wait_->wait(to_);
|
|
}
|
|
void cmd_result::trigger(void)
|
|
{
|
|
over_ = true;
|
|
wait_->trigger();
|
|
}
|
|
bool cmd_result::is_over(void)
|
|
{
|
|
return over_;
|
|
}
|
|
int cmd_result::get_error_code(void)
|
|
{
|
|
return err_;
|
|
}
|
|
void cmd_result::set_error_code(int err)
|
|
{
|
|
err_ = err;
|
|
}
|
|
|
|
int cmd_result::call(void)
|
|
{
|
|
int ret = call_(this);
|
|
|
|
if (ret == 0)
|
|
{
|
|
if (wait())
|
|
{
|
|
ret = err_;
|
|
}
|
|
else
|
|
{
|
|
ret = ETIMEDOUT;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
dyn_mem_ptr cmd_result::roger(dyn_mem_ptr data, uint32_t* used, packet_data_base_ptr* more)
|
|
{
|
|
LOCKER lock(locker_);
|
|
dyn_mem_ptr ret = nullptr;
|
|
LPPACK_BASE pack = (LPPACK_BASE)data->ptr();
|
|
|
|
err_ = pack->data;
|
|
ret = roger_(data, used, more, this);
|
|
// trigger();
|
|
|
|
return ret;
|
|
}
|
|
int cmd_result::clean(void)
|
|
{
|
|
LOCKER lock(locker_);
|
|
|
|
over_ = true;
|
|
return clean_(this);
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// though all command transferred by BULK are asychronous in transffer level,
|
|
// make BLOCKED in this layer
|
|
#define WAIT_COMMAND(call, clean, roger, param) \
|
|
cmd_result * r = gen_reply(call, clean, roger, param); \
|
|
int ret = r->call(); \
|
|
r->clean(); \
|
|
r->release(); \
|
|
return ret;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// scanner_handler
|
|
scanner_handler::scanner_handler(void) : usb_(nullptr), status_(SCANNER_STATUS_NOT_OPEN)
|
|
, img_receiver_(std::function<data_holder_ptr(LPPACKIMAGE, uint64_t)>())
|
|
, status_notify_(std::function<void(uint32_t)>())
|
|
{
|
|
auto on_reply = [&](dyn_mem_ptr reply, uint32_t* used, packet_data_base_ptr* more) ->dyn_mem_ptr
|
|
{
|
|
LPPACK_BASE pack = (LPPACK_BASE)reply->ptr();
|
|
cmd_result* cmd = take_reply(pack->pack_id);
|
|
dyn_mem_ptr ret = nullptr;
|
|
|
|
*used = reply->get_rest();
|
|
*more = nullptr;
|
|
if (cmd)
|
|
{
|
|
ret = cmd->roger(reply, used, more);
|
|
if (cmd->is_over())
|
|
cmd->release();
|
|
else if (status_ != SCANNER_STATUS_RESET_BULK)
|
|
{
|
|
LOCKER lock(lock_reply_);
|
|
|
|
reply_.push_back(cmd);
|
|
}
|
|
}
|
|
else if (status_ == SCANNER_STATUS_RESET_BULK)
|
|
{
|
|
if (pack->size == sizeof(PACK_BASE) &&
|
|
pack->cmd == PACK_CMD_SYNC_ROGER &&
|
|
pack->payload_len == 0)
|
|
status_ = SCANNER_STATUS_READY;
|
|
}
|
|
else if (pack->size == sizeof(PACK_BASE))
|
|
{
|
|
if (pack->cmd == PACK_CMD_SCAN_IMG_ROGER)
|
|
{
|
|
uint32_t off = sizeof(PACK_BASE) + sizeof(PACKIMAGE);
|
|
if (*used < off)
|
|
{
|
|
*used = 0;
|
|
}
|
|
else
|
|
{
|
|
LPPACKIMAGE pimg = (LPPACKIMAGE)pack->payload;
|
|
data_holder_ptr receiver = nullptr;
|
|
|
|
if(img_receiver_)
|
|
receiver = img_receiver_(pimg, pimg->info_size + pimg->data_size);
|
|
|
|
if (!receiver)
|
|
{
|
|
// usb_->cancel_command(pack->cmd, pack->pack_id);
|
|
receiver = dynamic_cast<data_holder_ptr>(new empty_holer(pimg->info_size + pimg->data_size));
|
|
}
|
|
|
|
*used = off;
|
|
*more = dynamic_cast<packet_data_base_ptr>(receiver);
|
|
}
|
|
}
|
|
else if (pack->cmd == PACK_CMD_SCAN_FINISHED_ROGER)
|
|
{
|
|
if (img_receiver_)
|
|
{
|
|
data_holder_ptr receiver = img_receiver_(NULL, pack->data);
|
|
if (receiver)
|
|
receiver->release();
|
|
}
|
|
*used = sizeof(PACK_BASE);
|
|
status_ = pack->data;
|
|
}
|
|
else if (pack->cmd == PACK_CMD_STATUS_ROGER)
|
|
{
|
|
*used = sizeof(PACK_BASE);
|
|
status_ = pack->data;
|
|
if (status_notify_)
|
|
status_notify_(status_);
|
|
}
|
|
else if (pack->cmd == PACK_CMD_FILE_WRITE_REQ_ROGER)
|
|
{
|
|
*used = sizeof(PACK_BASE);
|
|
log_cls::log(LOG_LEVEL_DEBUG, "Send file finished with error: %d\r\n", pack->data);
|
|
}
|
|
else
|
|
{
|
|
// unknown packet ...
|
|
uint8_t* ptr = reply->ptr();
|
|
log_cls::log(LOG_LEVEL_DEBUG, "Unhandled packet: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X ...\r\n"
|
|
, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7]
|
|
, ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// unknown packet ...
|
|
uint8_t* ptr = reply->ptr();
|
|
log_cls::log(LOG_LEVEL_DEBUG, "Unknown packet received: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X ...\r\n"
|
|
, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7]
|
|
, ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15]);
|
|
}
|
|
|
|
return ret;
|
|
};
|
|
|
|
usb_ = new async_usb_host(on_reply);
|
|
}
|
|
scanner_handler::~scanner_handler()
|
|
{
|
|
for (auto& v : reply_)
|
|
v->release();
|
|
usb_->release();
|
|
}
|
|
|
|
bool scanner_handler::reorder_device_config_json(std::string& cont, const std::map<std::string/*name*/, std::string/*title*/>* groups)
|
|
{
|
|
typedef struct _grp_item
|
|
{
|
|
std::string name;
|
|
std::vector<json*> items;
|
|
|
|
bool operator==(const char* gn)
|
|
{
|
|
return name == gn;
|
|
}
|
|
}GRPITEM;
|
|
std::vector<GRPITEM> items;
|
|
std::vector<json*> nogrp;
|
|
json* jsn = new json(), * child = nullptr;
|
|
bool ret = jsn->attach_text(&cont[0]);
|
|
int cnt = 0;
|
|
|
|
if (ret)
|
|
{
|
|
std::string grp("");
|
|
|
|
child = jsn->first_child();
|
|
while (child)
|
|
{
|
|
cnt++;
|
|
if (child->get_value("group", grp) && !grp.empty())
|
|
{
|
|
std::vector<GRPITEM>::iterator it = std::find(items.begin(), items.end(), grp.c_str());
|
|
if (it == items.end())
|
|
{
|
|
GRPITEM item;
|
|
item.name = grp;
|
|
item.items.push_back(child);
|
|
items.push_back(item);
|
|
}
|
|
else
|
|
{
|
|
it->items.push_back(child);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nogrp.push_back(child);
|
|
}
|
|
|
|
child = jsn->next_child();
|
|
}
|
|
jsn->release();
|
|
|
|
child = new json();
|
|
child->set_value("option_count", cnt);
|
|
jsn = new json();
|
|
jsn->set_value("global", child);
|
|
child->release();
|
|
|
|
for (auto& v : nogrp)
|
|
{
|
|
jsn->set_value(v->key().c_str(), v);
|
|
v->release();
|
|
}
|
|
nogrp.clear();
|
|
|
|
cnt = 1;
|
|
if (groups)
|
|
{
|
|
for (auto& v : *groups)
|
|
{
|
|
std::vector<GRPITEM>::iterator it = std::find(items.begin(), items.end(), v.first.c_str());
|
|
if (it == items.end())
|
|
continue;
|
|
|
|
child = new json();
|
|
child->set_value("category", "base");
|
|
child->set_value("type", "group");
|
|
child->set_value("title", v.second.c_str());
|
|
jsn->set_value(("grp-" + std::to_string(cnt++)).c_str(), child);
|
|
child->release();
|
|
|
|
for (auto& c : it->items)
|
|
{
|
|
jsn->set_value(c->key().c_str(), c);
|
|
c->release();
|
|
}
|
|
items.erase(it);
|
|
}
|
|
}
|
|
|
|
for (auto& v : items)
|
|
{
|
|
child = new json();
|
|
child->set_value("category", "base");
|
|
child->set_value("type", "group");
|
|
child->set_value("title", v.name.c_str());
|
|
jsn->set_value(("grp-" + std::to_string(cnt++)).c_str(), child);
|
|
child->release();
|
|
|
|
for (auto& c : v.items)
|
|
{
|
|
jsn->set_value(c->key().c_str(), c);
|
|
c->release();
|
|
}
|
|
}
|
|
items.clear();
|
|
|
|
cont = std::move(jsn->to_string());
|
|
jsn->release();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
cmd_result* scanner_handler::gen_reply(std::function<int(cmd_result*)> call,
|
|
std::function<int(cmd_result*)> clean,
|
|
std::function<dyn_mem_ptr(dyn_mem_ptr, uint32_t*, packet_data_base_ptr*, cmd_result*)> roger,
|
|
void* param, uint32_t id)
|
|
{
|
|
cmd_result* reply = new cmd_result(call, clean, roger, param, id);
|
|
|
|
{
|
|
LOCKER lock(lock_reply_);
|
|
|
|
reply_.push_back(reply);
|
|
}
|
|
reply->add_ref(); // for reply_ queue storing
|
|
|
|
return reply;
|
|
}
|
|
cmd_result* scanner_handler::take_reply(uint32_t id)
|
|
{
|
|
cmd_result* reply = nullptr;
|
|
LOCKER lock(lock_reply_);
|
|
|
|
for (size_t i = 0; i < reply_.size(); ++i)
|
|
{
|
|
if (reply_[i]->get_id() == id)
|
|
{
|
|
reply = reply_[i];
|
|
reply_.erase(reply_.begin() + i);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return reply;
|
|
}
|
|
int scanner_handler::wait_result(cmd_result* reply)
|
|
{
|
|
if (reply->wait())
|
|
{
|
|
return reply->get_error_code();
|
|
}
|
|
else
|
|
{
|
|
cmd_result* q = take_reply(reply->get_id());
|
|
|
|
if (q)
|
|
{
|
|
q->release();
|
|
}
|
|
else
|
|
{
|
|
// take out by reply just now ? try again ...
|
|
reply->set_timeout(500);
|
|
if (reply->wait())
|
|
return reply->get_error_code();
|
|
}
|
|
|
|
return ETIMEDOUT;
|
|
}
|
|
}
|
|
|
|
int scanner_handler::get_protocol_version(uint16_t* ver)
|
|
{
|
|
if (!is_scanner_available())
|
|
return ENODEV;
|
|
|
|
return usb_->get_peer_protocol_version(ver);
|
|
}
|
|
int scanner_handler::get_scanner_status(LPEP0REPLYSTATUS status)
|
|
{
|
|
if (!is_scanner_available())
|
|
return ENODEV;
|
|
|
|
return usb_->get_peer_status(status);
|
|
}
|
|
int scanner_handler::restart_peer_bulk(uint32_t timeout)
|
|
{
|
|
if (!is_scanner_available())
|
|
return ENODEV;
|
|
|
|
return usb_->restart_peer_bulk(timeout);
|
|
}
|
|
|
|
|
|
int scanner_handler::option_get_all(std::string& json_opts)
|
|
{
|
|
auto call = [&](cmd_result* cmd) -> int
|
|
{
|
|
return usb_->get_settings(cmd->get_id());
|
|
};
|
|
auto clean = [&](cmd_result* cmd) -> int
|
|
{
|
|
return 0;
|
|
};
|
|
auto roger = [&](dyn_mem_ptr data, uint32_t* used, packet_data_base_ptr* more, cmd_result* cmd) ->dyn_mem_ptr
|
|
{
|
|
std::string *ret = (std::string*)cmd->get_param();
|
|
LPPACK_BASE pack = (LPPACK_BASE)data->ptr();
|
|
|
|
if (data->get_rest() < sizeof(PACK_BASE) + pack->payload_len)
|
|
*used = 0;
|
|
else
|
|
{
|
|
if(!cmd->is_over())
|
|
*(std::string*)cmd->get_param() = std::string(pack->payload, pack->payload_len);
|
|
*used = sizeof(*pack) + pack->payload_len;
|
|
cmd->trigger();
|
|
}
|
|
*more = nullptr;
|
|
|
|
return nullptr;
|
|
};
|
|
|
|
if (!is_scanner_available())
|
|
return ENODEV;
|
|
|
|
WAIT_COMMAND(call, clean, roger, &json_opts);
|
|
}
|
|
int scanner_handler::option_value_get(const char* name, void* buf, uint32_t size)
|
|
{
|
|
auto call = [&](cmd_result* cmd) -> int
|
|
{
|
|
return usb_->get_setting_val(cmd->get_id(), name);
|
|
};
|
|
auto clean = [&](cmd_result* cmd) -> int
|
|
{
|
|
return 0;
|
|
};
|
|
auto roger = [&](dyn_mem_ptr data, uint32_t* used, packet_data_base_ptr* more, cmd_result* cmd) ->dyn_mem_ptr
|
|
{
|
|
LPPACK_BASE pack = (LPPACK_BASE)data->ptr();
|
|
LPCFGVAL cfg = (LPCFGVAL)pack->payload;
|
|
|
|
if (data->get_rest() < sizeof(PACK_BASE) + pack->payload_len)
|
|
*used = 0;
|
|
else
|
|
{
|
|
if (!cmd->is_over())
|
|
memcpy(cmd->get_param(), cfg->data + cfg->val_off, cfg->val_size);
|
|
*used = sizeof(*pack) + pack->payload_len;
|
|
cmd->trigger();
|
|
}
|
|
*more = nullptr;
|
|
|
|
return nullptr;
|
|
};
|
|
|
|
if (!is_scanner_available())
|
|
return ENODEV;
|
|
|
|
WAIT_COMMAND(call, clean, roger, buf);
|
|
}
|
|
int scanner_handler::option_value_set(const char* name, uint32_t type, void* buf, uint32_t size, uint32_t val_size, uint8_t* after)
|
|
{
|
|
struct
|
|
{
|
|
void* buf;
|
|
uint8_t* after;
|
|
}param;
|
|
auto call = [&](cmd_result* cmd) -> int
|
|
{
|
|
memcpy(¶m, cmd->get_param(), sizeof(param));
|
|
return usb_->set_setting(cmd->get_id(), name, type, param.buf, val_size, size);
|
|
};
|
|
auto clean = [&](cmd_result* cmd) -> int
|
|
{
|
|
return 0;
|
|
};
|
|
auto roger = [&](dyn_mem_ptr data, uint32_t* used, packet_data_base_ptr* more, cmd_result* cmd) ->dyn_mem_ptr
|
|
{
|
|
struct
|
|
{
|
|
void* buf;
|
|
uint8_t* after;
|
|
}*result = nullptr;
|
|
LPPACK_BASE pack = (LPPACK_BASE)data->ptr();
|
|
LPCFGVAL cfg = (LPCFGVAL)pack->payload;
|
|
|
|
if (data->get_rest() < sizeof(PACK_BASE) + pack->payload_len)
|
|
*used = 0;
|
|
else
|
|
{
|
|
if (!cmd->is_over())
|
|
{
|
|
*(void**)&result = cmd->get_param();
|
|
memcpy(result->buf, cfg->data + cfg->val_off, cfg->val_size);
|
|
*result->after = cfg->after_do;
|
|
}
|
|
*used = sizeof(*pack) + pack->payload_len;
|
|
cmd->trigger();
|
|
}
|
|
*more = nullptr;
|
|
|
|
return nullptr;
|
|
};
|
|
|
|
if (!is_scanner_available())
|
|
return ENODEV;
|
|
|
|
param.buf = buf;
|
|
param.after = after;
|
|
WAIT_COMMAND(call, clean, roger, ¶m);
|
|
}
|
|
int scanner_handler::status_get(void)
|
|
{
|
|
return status_;
|
|
}
|
|
|
|
void scanner_handler::set_image_receiver(std::function<data_holder_ptr(LPPACKIMAGE, uint64_t)> img)
|
|
{
|
|
img_receiver_ = img;
|
|
}
|
|
void scanner_handler::set_status_notifyer(std::function<void(uint32_t)> stntf)
|
|
{
|
|
status_notify_ = stntf;
|
|
}
|
|
int scanner_handler::scan_start(void)
|
|
{
|
|
auto call = [&](cmd_result* cmd) -> int
|
|
{
|
|
cmd->set_timeout(4000);
|
|
return usb_->scan_start(cmd->get_id());
|
|
};
|
|
auto clean = [&](cmd_result* cmd) -> int
|
|
{
|
|
return 0;
|
|
};
|
|
auto roger = [&](dyn_mem_ptr data, uint32_t* used, packet_data_base_ptr* more, cmd_result* cmd) ->dyn_mem_ptr
|
|
{
|
|
LPPACK_BASE pack = (LPPACK_BASE)data->ptr();
|
|
|
|
*used = sizeof(PACK_BASE);
|
|
*more = nullptr;
|
|
status_ = SCANNER_STATUS_START_SCANNING;
|
|
cmd->trigger();
|
|
|
|
return nullptr;
|
|
};
|
|
|
|
if (!is_scanner_available())
|
|
return ENODEV;
|
|
|
|
WAIT_COMMAND(call, clean, roger, nullptr);
|
|
}
|
|
int scanner_handler::scan_stop(void)
|
|
{
|
|
auto call = [&](cmd_result* cmd) -> int
|
|
{
|
|
return usb_->scan_stop(cmd->get_id());
|
|
};
|
|
auto clean = [&](cmd_result* cmd) -> int
|
|
{
|
|
return 0;
|
|
};
|
|
auto roger = [&](dyn_mem_ptr data, uint32_t* used, packet_data_base_ptr* more, cmd_result* cmd) ->dyn_mem_ptr
|
|
{
|
|
*used = sizeof(PACK_BASE);
|
|
*more = nullptr;
|
|
cmd->trigger();
|
|
|
|
return nullptr;
|
|
};
|
|
|
|
if (!is_scanner_available())
|
|
return ENODEV;
|
|
|
|
WAIT_COMMAND(call, clean, roger, nullptr);
|
|
}
|
|
|
|
int scanner_handler::file_transfer(const char* local_path, const char* remote_path, bool to_device, PROGRESS_NOTIFYER progress, uint64_t local_off, uint64_t remote_off)
|
|
{
|
|
if (!is_scanner_available())
|
|
return ENODEV;
|
|
|
|
if (to_device)
|
|
{
|
|
uint64_t size = 0;
|
|
FILE *src = fopen(local_path, "rb");
|
|
|
|
if (!src)
|
|
return errno;
|
|
FSEEK(src, 0, SEEK_END);
|
|
size = FTELL(src);
|
|
FSEEK(src, local_off, SEEK_SET);
|
|
if (size <= local_off)
|
|
{
|
|
fclose(src);
|
|
|
|
return EOVERFLOW;
|
|
}
|
|
size -= local_off;
|
|
log_cls::log(LOG_LEVEL_DEBUG, "Send '%s' to '%s' ...\r\n", local_path, remote_path);
|
|
|
|
auto call = [&](cmd_result* cmd) -> int
|
|
{
|
|
return usb_->file_send(cmd->get_id(), remote_path, size, remote_off);
|
|
};
|
|
auto clean = [&](cmd_result* cmd) -> int
|
|
{
|
|
FILE* src = (FILE*)cmd->get_param();
|
|
|
|
if (src)
|
|
fclose(src);
|
|
|
|
return 0;
|
|
};
|
|
auto roger = [&](dyn_mem_ptr data, uint32_t* used, packet_data_base_ptr* more, cmd_result* cmd) ->dyn_mem_ptr
|
|
{
|
|
LPPACK_BASE pack = (LPPACK_BASE)data->ptr();
|
|
dyn_mem_ptr ret = nullptr;
|
|
|
|
*used = sizeof(PACK_BASE);
|
|
*more = nullptr;
|
|
log_cls::log(LOG_LEVEL_DEBUG, "Send file - Roger of send file result: %d\r\n", pack->data);
|
|
|
|
if (pack->data == 0)
|
|
{
|
|
if (cmd->is_over())
|
|
{
|
|
reset_message_que();
|
|
}
|
|
else
|
|
{
|
|
file_reader_ptr freader = new file_reader();
|
|
|
|
int err = freader->attach((FILE*)cmd->set_param(nullptr));
|
|
freader->set_progress_notify(progress);
|
|
if (err)
|
|
{
|
|
// cancel tx-file ...
|
|
cmd->set_error_code(err);
|
|
freader->release();
|
|
reset_message_que();
|
|
log_cls::log(LOG_LEVEL_DEBUG, "Send file - Attach to source file failed: %d\r\n", err);
|
|
}
|
|
else
|
|
{
|
|
*more = dynamic_cast<packet_data_base_ptr>(freader);
|
|
status_ = SCANNER_STATUS_BUSY;
|
|
log_cls::log(LOG_LEVEL_DEBUG, "Send file - beginning ...\r\n");
|
|
}
|
|
}
|
|
}
|
|
cmd->trigger();
|
|
|
|
return ret;
|
|
};
|
|
|
|
WAIT_COMMAND(call, clean, roger, src);
|
|
}
|
|
else
|
|
{
|
|
auto call = [&](cmd_result* cmd) -> int
|
|
{
|
|
return usb_->file_get(cmd->get_id(), remote_path, remote_off);
|
|
};
|
|
auto clean = [&](cmd_result* cmd) -> int
|
|
{
|
|
return 0;
|
|
};
|
|
auto roger = [&](dyn_mem_ptr data, uint32_t* used, packet_data_base_ptr* more, cmd_result* cmd) ->dyn_mem_ptr
|
|
{
|
|
LPPACK_BASE pack = (LPPACK_BASE)data->ptr();
|
|
LPTXFILE pfi = (LPTXFILE)pack->payload;
|
|
|
|
*used = sizeof(PACK_BASE) + pack->payload_len;
|
|
*more = nullptr;
|
|
log_cls::log(LOG_LEVEL_DEBUG, "Receive file - Roger result: %d\r\n", pack->data);
|
|
if (pack->data == 0)
|
|
{
|
|
if (cmd->is_over())
|
|
{
|
|
log_cls::log(LOG_LEVEL_DEBUG, "Receive file - timeout, user cancelled\r\n");
|
|
reset_message_que();
|
|
}
|
|
else
|
|
{
|
|
file_saver* fsaver = new file_saver();
|
|
int err = fsaver->open(local_path, pfi->size);
|
|
fsaver->set_progress_notify(progress);
|
|
if (err)
|
|
{
|
|
// cancel tx-file ...
|
|
cmd->set_error_code(err);
|
|
fsaver->release();
|
|
reset_message_que();
|
|
log_cls::log(LOG_LEVEL_DEBUG, "Receive file - open local file failed: %d\r\n", err);
|
|
}
|
|
else
|
|
{
|
|
*more = dynamic_cast<packet_data_base_ptr>(fsaver);
|
|
status_ = SCANNER_STATUS_BUSY;
|
|
log_cls::log(LOG_LEVEL_DEBUG, "Receive file - beginning ...\r\n");
|
|
}
|
|
}
|
|
}
|
|
cmd->trigger();
|
|
|
|
return nullptr;
|
|
};
|
|
|
|
log_cls::log(LOG_LEVEL_DEBUG, "Receive '%s' to '%s' ...\r\n", remote_path, local_path);
|
|
|
|
WAIT_COMMAND(call, clean, roger, (void*)local_path);
|
|
}
|
|
}
|
|
int scanner_handler::file_move(const char* rfrom, const char* rto)
|
|
{
|
|
auto call = [&](cmd_result* cmd) -> int
|
|
{
|
|
return usb_->file_move(cmd->get_id(), rfrom, rto);
|
|
};
|
|
auto clean = [&](cmd_result* cmd) -> int
|
|
{
|
|
return 0;
|
|
};
|
|
auto roger = [&](dyn_mem_ptr data, uint32_t* used, packet_data_base_ptr* more, cmd_result* cmd) ->dyn_mem_ptr
|
|
{
|
|
*used = sizeof(PACK_BASE);
|
|
*more = nullptr;
|
|
cmd->trigger();
|
|
|
|
return nullptr;
|
|
};
|
|
|
|
if (!is_scanner_available())
|
|
return ENODEV;
|
|
|
|
WAIT_COMMAND(call, clean, roger, nullptr);
|
|
}
|
|
int scanner_handler::file_delete(const char* remote)
|
|
{
|
|
auto call = [&](cmd_result* cmd) -> int
|
|
{
|
|
return usb_->file_remove(cmd->get_id(), remote);
|
|
};
|
|
auto clean = [&](cmd_result* cmd) -> int
|
|
{
|
|
return 0;
|
|
};
|
|
auto roger = [&](dyn_mem_ptr data, uint32_t* used, packet_data_base_ptr* more, cmd_result* cmd) ->dyn_mem_ptr
|
|
{
|
|
*used = sizeof(PACK_BASE);
|
|
*more = nullptr;
|
|
cmd->trigger();
|
|
|
|
return nullptr;
|
|
};
|
|
|
|
if (!is_scanner_available())
|
|
return ENODEV;
|
|
|
|
WAIT_COMMAND(call, clean, roger, nullptr);
|
|
}
|
|
|
|
int scanner_handler::program_start(const char* remote_pe, const char* param, uint64_t* pid)
|
|
{
|
|
auto call = [&](cmd_result* cmd) -> int
|
|
{
|
|
return usb_->program_start(cmd->get_id(), remote_pe, param);
|
|
};
|
|
auto clean = [&](cmd_result* cmd) -> int
|
|
{
|
|
return 0;
|
|
};
|
|
auto roger = [&](dyn_mem_ptr data, uint32_t* used, packet_data_base_ptr* more, cmd_result* cmd) ->dyn_mem_ptr
|
|
{
|
|
LPPACK_BASE pack = (LPPACK_BASE)data->ptr();
|
|
|
|
if (pack->data == 0 && !cmd->is_over())
|
|
*(uint64_t*)cmd->get_param() = *(uint64_t*)pack->payload;
|
|
*used = sizeof(PACK_BASE) + pack->payload_len;
|
|
*more = nullptr;
|
|
cmd->trigger();
|
|
|
|
return nullptr;
|
|
};
|
|
|
|
if (!is_scanner_available())
|
|
return ENODEV;
|
|
|
|
WAIT_COMMAND(call, clean, roger, pid);
|
|
}
|
|
int scanner_handler::program_stop(uint64_t pid)
|
|
{
|
|
auto call = [&](cmd_result* cmd) -> int
|
|
{
|
|
return usb_->program_stop(cmd->get_id(), pid);
|
|
};
|
|
auto clean = [&](cmd_result* cmd) -> int
|
|
{
|
|
return 0;
|
|
};
|
|
auto roger = [&](dyn_mem_ptr data, uint32_t* used, packet_data_base_ptr* more, cmd_result* cmd) ->dyn_mem_ptr
|
|
{
|
|
*used = sizeof(PACK_BASE);
|
|
*more = nullptr;
|
|
cmd->trigger();
|
|
|
|
return nullptr;
|
|
};
|
|
|
|
if (!is_scanner_available())
|
|
return ENODEV;
|
|
|
|
WAIT_COMMAND(call, clean, roger, nullptr);
|
|
}
|
|
|
|
int scanner_handler::open_usb_scanner(libusb_device* dev)
|
|
{
|
|
int ret = close();
|
|
|
|
if (ret == 0)
|
|
{
|
|
ret = usb_->start(dev);
|
|
if(ret == 0)
|
|
status_ = SCANNER_STATUS_READY;
|
|
//usb_->set_gadget_encrypting_method(ENCRYPT_CMD_XOR_PID);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
int scanner_handler::close(void)
|
|
{
|
|
int ret = usb_->stop();
|
|
|
|
{
|
|
LOCKER lock(lock_reply_);
|
|
for (auto& v : reply_)
|
|
v->release();
|
|
reply_.clear();
|
|
}
|
|
if(ret == 0)
|
|
status_ = SCANNER_STATUS_NOT_OPEN;
|
|
|
|
return ret;
|
|
}
|
|
int scanner_handler::reset_message_que(void)
|
|
{
|
|
int err = usb_->cancel_write();
|
|
|
|
status_ = SCANNER_STATUS_RESET_BULK;
|
|
log_cls::log(LOG_LEVEL_DEBUG, "reset_message_que - send reset command ...\r\n");
|
|
err = usb_->restart_peer_bulk();
|
|
log_cls::log(LOG_LEVEL_DEBUG, "reset_message_que - send reset command = %d\r\n", err);
|
|
if (err == 0)
|
|
{
|
|
EP0REPLYSTATUS s;
|
|
dyn_mem_ptr raw(dyn_mem::memory(sizeof(PACK_BASE)));
|
|
LPPACK_BASE pack = (LPPACK_BASE)raw->ptr();
|
|
|
|
BASE_PACKET_REPLY(*pack, PACK_CMD_SYNC, 0, 0);
|
|
raw->set_len(sizeof(PACK_BASE));
|
|
log_cls::log(LOG_LEVEL_DEBUG, "reset_message_que - wait 100ms ...\r\n");
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
log_cls::log(LOG_LEVEL_DEBUG, "reset_message_que - send SYNC packet ...\r\n");
|
|
usb_->send_bulk_raw_data(raw);
|
|
raw->release();
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
|
if (status_ == SCANNER_STATUS_RESET_BULK)
|
|
err = EFAULT;
|
|
log_cls::log(LOG_LEVEL_DEBUG, "reset_message_que - final status = %d\r\n", status_);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
bool scanner_handler::is_scanner_available(void)
|
|
{
|
|
return status_ != SCANNER_STATUS_NOT_OPEN
|
|
&& status_ != SCANNER_STATUS_LOST_CONNECT
|
|
&& status_ != SCANNER_STATUS_RESET_BULK;
|
|
}
|