newtx/scanner/async_scanner.cpp

788 lines
22 KiB
C++
Raw Permalink Normal View History

2023-12-01 09:17:09 +00:00
#include "async_scanner.h"
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <iostream>
#include <fstream>
#include <usb_io.h>
#include <sane_opt_json/device_opt.h>
#include <sane/sane_ex.h>
#include <huagao/hgscanner_error.h>
2023-12-18 01:39:48 +00:00
#include "scanner_const_opts.h"
#include <hardware.h>
#include <sane_opt_json/user.h>
#include <base/ui.h>
#include <imgprc_mgr.h>
2024-02-25 05:51:52 +00:00
#include "res_mgr.h"
2023-12-01 09:17:09 +00:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
2024-01-27 09:43:13 +00:00
#include <malloc.h>
2023-12-01 09:17:09 +00:00
2024-01-27 09:43:13 +00:00
static void *(*old_malloc_hook)(size_t, const void *) = nullptr;
static void (*old_free_hook)(void *ptr, const void *caller) = nullptr;
static FILE* g_mem_file = nullptr;
static uint64_t total_size = 0;
2024-01-29 06:47:35 +00:00
static bool record_ = false;
2024-01-27 09:43:13 +00:00
static void * my_malloc_hook(size_t size, const void *caller)
{
void *result;
/* Restore all old hooks */
__malloc_hook = old_malloc_hook;
2024-01-29 06:47:35 +00:00
if(__malloc_hook == my_malloc_hook)
__malloc_hook = nullptr;
2024-01-27 09:43:13 +00:00
/* Call recursively */
result = malloc(size);
/* Save underlying hooks */
old_malloc_hook = __malloc_hook;
/* printf() might call malloc(), so protect it too. */
if(g_mem_file)
{
char buf[128] = {0};
sprintf(buf, "+%p from %p (size = %u)\n", result, caller, size);
fwrite(buf, 1, strlen(buf), g_mem_file);
}
else
printf("+%p from %p (size = %u)\n", result, caller, size);
/* Restore our own hooks */
2024-01-29 06:47:35 +00:00
if(record_)
2024-01-27 09:43:13 +00:00
__malloc_hook = my_malloc_hook;
return result;
}
static void my_free_hook(void *ptr, const void *caller)
{
__free_hook = old_free_hook;
2024-01-29 06:47:35 +00:00
if(__free_hook == my_free_hook)
__free_hook = nullptr;
2024-01-27 09:43:13 +00:00
if(ptr)
free(ptr);
if(g_mem_file)
{
char buf[128] = {0};
sprintf(buf, "-%p from %p\n", ptr, caller);
fwrite(buf, 1, strlen(buf), g_mem_file);
}
else
printf("-%p from %p\n", ptr, caller);
old_free_hook = __free_hook;
2024-01-29 06:47:35 +00:00
if(record_)
2024-01-27 09:43:13 +00:00
__free_hook = my_free_hook;
}
2024-01-29 06:47:35 +00:00
void record_malloc(bool enable)
2024-01-27 09:43:13 +00:00
{
if(enable)
{
printf("my_malloc_hook = %p, my_free_hook = %p\n", (void*)my_malloc_hook, (void*)my_free_hook);
if(g_mem_file)
fclose(g_mem_file);
g_mem_file = fopen("/tmp/memlog.txt", "wb");
std::string log(utils::format_current_time() + "\n");
fwrite(log.c_str(), 1, log.length(), g_mem_file);
2024-01-29 06:47:35 +00:00
record_ = true;
2024-01-27 09:43:13 +00:00
old_free_hook = __free_hook;
__free_hook = my_free_hook;
old_malloc_hook = __malloc_hook;
__malloc_hook = my_malloc_hook;
}
else // if(old_malloc_hook)
{
2024-01-29 06:47:35 +00:00
printf("cancel log malloc.\n");
record_ = false;
// __malloc_hook = old_malloc_hook;
// old_malloc_hook = nullptr;
// __free_hook = old_free_hook;
// old_free_hook = nullptr;
2024-01-27 09:43:13 +00:00
if(g_mem_file)
{
2024-01-29 06:47:35 +00:00
// std::string log(utils::format_current_time() + "\n");
// fwrite(log.c_str(), 1, log.length(), g_mem_file);
2024-01-27 09:43:13 +00:00
fclose(g_mem_file);
}
g_mem_file = nullptr;
}
}
2024-01-29 06:47:35 +00:00
2023-12-01 09:17:09 +00:00
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
async_scanner::async_scanner() : usb_(nullptr), cfg_mgr_(nullptr), scan_id_(0)
{
utils::init_log(LOG_TYPE_FILE);
2024-02-20 03:29:26 +00:00
utils::to_log(LOG_LEVEL_DEBUG, "System info: page-size = %u, mapping-page-size = %u, disk-cluster-size = %u, default-stack-size = %u.\n"
, global_info::page_size, global_info::page_map_size, global_info::cluster_size, global_info::stack_size);
2024-02-25 05:51:52 +00:00
res_mgr_.reset(new resource_mgr());
2023-12-01 09:17:09 +00:00
init();
}
async_scanner::~async_scanner()
{
2024-02-25 05:51:52 +00:00
res_mgr_->stop();
res_mgr_.reset(nullptr);
if(cis_)
{
cis_->stop_scan();
cis_->close();
cis_->release();
cis_ = nullptr;
}
2023-12-01 09:17:09 +00:00
if(usb_)
{
usb_->stop();
usb_->release();
usb_ = nullptr;
}
if(img_prcr_)
{
img_prcr_->release();
img_prcr_ = nullptr;
2023-12-01 09:17:09 +00:00
}
if(cfg_mgr_)
{
cfg_mgr_->clear();
2023-12-18 01:39:48 +00:00
cfg_mgr_->release();
cfg_mgr_ = nullptr;
2023-12-01 09:17:09 +00:00
}
2023-12-09 10:21:05 +00:00
for(auto& v: send_files_)
v->release();
send_files_.clear();
2023-12-18 01:39:48 +00:00
const_opts_->release();
user_->release();
2023-12-09 10:21:05 +00:00
2023-12-01 10:03:10 +00:00
utils::uninit();
devui::uninit_ui();
2023-12-01 09:17:09 +00:00
}
bool async_scanner::resource_check(RES_CHK_PROTO)
{
return ((resource_mgr*)param)->is_resource_enable((enum _task)type, wait, to_ms);
}
void async_scanner::image_sender(SENDER_PROTO)
{
async_scanner* obj = (async_scanner*)param;
if(ptr->ptr() && ((LPPACK_BASE)ptr->ptr())->cmd == PACK_CMD_SCAN_FINISHED_ROGER)
{
obj->cis_->close();
obj->res_mgr_->stop();
utils::print_memory_usage("Memory usage when finished scanning", true);
system("sudo cpufreq-set -g ondemand");
}
obj->usb_->write_bulk(ptr);
}
dyn_mem_ptr async_scanner::option_changed_packet(const char* name, void* val, size_t val_len, int pkid, int err)
{
size_t name_len = strlen(name) + 1,
size = sizeof(PACK_BASE) + sizeof(CFGVAL) + name_len + val_len + 1;
dyn_mem_ptr ptr = dyn_mem::memory(size);
LPPACK_BASE pck = (LPPACK_BASE)ptr->ptr();
LPCFGVAL cfg = (LPCFGVAL)pck->payload;
BASE_PACKET_REPLY(*pck, PACK_CMD_SETTING_SET, pkid, err);
pck->payload_len = sizeof(CFGVAL) + name_len + val_len + 1;
cfg->after_do = 0;
cfg->name_off = 0;
cfg->val_size = val_len;
strcpy(cfg->data, name);
cfg->val_off = name_len;
memcpy(cfg->data + cfg->val_off, val, val_len);
ptr->set_len(size);
return ptr;
}
dyn_mem_ptr async_scanner::handle_bulk_cmd(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required, uint32_t session)
2023-12-01 09:17:09 +00:00
{
dyn_mem_ptr reply = nullptr;
LPPACK_BASE pk = nullptr;
size_t base_head_size = sizeof(PACK_BASE);
if(pack->size != base_head_size)
{
if(used)
{
utils::log_mem_info("Invalid packet", (uint8_t*)pack, *used);
}
reply = dyn_mem::memory(base_head_size);
LPPACK_BASE p = (LPPACK_BASE)reply->ptr();
BASE_PACKET_REPLY(*p, PACK_CMD_INVALID, pack->pack_id, pack->cmd);
reply->set_len(base_head_size);
return reply;
}
switch(pack->cmd)
{
case PACK_CMD_SYNC:
reply = handle_simple_roger(pack, used, required, session);
2023-12-01 09:17:09 +00:00
break;
case PACK_CMD_SETTING_GET_CUR:
reply = handle_get_opt_value(pack, used, required, session);
2023-12-01 09:17:09 +00:00
break;
case PACK_CMD_SETTING_GET:
reply = handle_get_opt_all(pack, used, required, session);
2023-12-01 09:17:09 +00:00
break;
case PACK_CMD_SETTING_SET:
reply = handle_set_opt(pack, used, required, session);
2023-12-01 09:17:09 +00:00
break;
case PACK_CMD_FILE_WRITE_REQ:
reply = handle_file_receive(pack, used, required, session);
2023-12-01 09:17:09 +00:00
break;
case PACK_CMD_FILE_READ_REQ:
reply = handle_file_send(pack, used, required, session);
2023-12-01 09:17:09 +00:00
break;
2023-12-09 10:21:05 +00:00
case PACK_CMD_FILE_READ_REQ_ROGER:
reply = handle_file_send_roger(pack, used, required, session);
2023-12-09 10:21:05 +00:00
break;
2023-12-01 09:17:09 +00:00
case PACK_CMD_SCAN_START:
reply = handle_scan_start(pack, used, required, session);
2023-12-01 09:17:09 +00:00
break;
case PACK_CMD_SCAN_STOP:
reply = handle_scan_stop(pack, used, required, session);
2023-12-01 09:17:09 +00:00
break;
default:
if(used)
{
utils::log_mem_info("Unsupported command packet", (uint8_t*)pack, *used);
}
reply = dyn_mem::memory(base_head_size);
LPPACK_BASE p = (LPPACK_BASE)reply->ptr();
BASE_PACKET_REPLY(*p, pack->cmd + 1, pack->pack_id, EINVAL);
reply->set_len(base_head_size);
break;
}
return reply;
}
void async_scanner::init(void)
{
cis_ = new scanner_hw();
const_opts_ = new scanner_const_opts();
auto uicb = [this](devui::LPMSGSTREAM pack) -> void
{
if(devui::UI_STATUS_PEER_CONNECTED == pack->msg)
{
// add feed-strength && time-to-sleep menu ...
add_option_to_ui_menu(SANE_OPT_NAME(FEED_STRENGTH), 0);
add_option_to_ui_menu(SANE_OPT_NAME(TIME_TO_SLEEP), 1);
}
else if(devui::UI_CMD_COUNT_PAPER == pack->msg)
{
auto receiver = [this](CIS_IMAGE_PROTO) -> void
{
img_prcr_->process(data, type, lpinfo);
};
bool auto_scan = true;
std::string prev(cfg_mgr_->get_option_value(SANE_OPT_NAME(WAIT_TO_SCAN), SANE_ACTION_GET_VALUE));
cis_->set_value(SANE_OPT_NAME(WAIT_TO_SCAN), &auto_scan);
2024-02-25 05:51:52 +00:00
cis_->open(receiver, CHK_RES_FUNC(), nullptr, true);
cis_->start_scan();
}
else if(devui::UI_CMD_STOP_SCAN == pack->msg)
{
2024-02-21 03:10:14 +00:00
cis_->stop_scan(true);
bool auto_scan = false;
cis_->set_value(SANE_OPT_NAME(WAIT_TO_SCAN), &auto_scan);
}
else if(devui::UI_CMD_CLEAN_PASSWAY == pack->msg)
{
cis_->clean_paper_passway();
}
else if(devui::UI_CMD_SET_OPTION_VALUE == pack->msg)
{
char *name = (char*)pack->data,
*val = utils::next_string(name);
std::string type(cfg_mgr_->get_option_value_type(name)),
rv(sane_opt_provider::sane_value_from_readable_text(type.c_str(), val));
dyn_mem_ptr ptr = async_scanner::option_changed_packet(name, &rv[0], rv.length());
utils::to_log(LOG_LEVEL_DEBUG, "From UI set '%s' to '%s'.\n", name, val);
cfg_mgr_->update_data(name, &rv[0], true, false);
if(!usb_)
{
int cond = MUST_COND_ROLLER_CNT | MUST_COND_HISTORY_CNT;
if(strcmp(name, SANE_OPT_NAME(ROLLER_COUNT)) == 0)
must_ready_ |= MUST_COND_ROLLER_CNT;
else if(strcmp(name, SANE_OPT_NAME(HISTORY_COUNT)) == 0)
must_ready_ |= MUST_COND_HISTORY_CNT;
if((must_ready_ & cond) == cond)
init_usb();
}
if(usb_)
{
ptr->set_session_id(usb_->current_session());
usb_->write_bulk(ptr);
}
ptr->release();
}
};
auto user = [this](int priv) -> bool
{
return user_->has_privilege(priv);
};
auto on_log = [&](const char* msg) -> void
{
utils::log_info(msg, LOG_LEVEL_DEBUG);
};
cfg_mgr_ = new device_option(true, user, on_log);
utils::to_log(LOG_LEVEL_DEBUG, "OPT - initializing ...\n");
user_ = new user_priv();
cfg_mgr_->add(const_opts_);
cis_->set_value(SANE_OPT_NAME(DEVICE_MODEL), &cfg_mgr_->get_option_value(SANE_OPT_NAME(DEVICE_MODEL), SANE_ACTION_GET_VALUE)[0]);
cfg_mgr_->add(cis_);
cfg_mgr_->add(user_);
img_prcr_ = new imgproc_mgr(cfg_mgr_, &async_scanner::image_sender, (void*)this, &async_scanner::resource_check, (void*)res_mgr_.get());
cfg_mgr_->add(img_prcr_);
utils::to_log(LOG_LEVEL_DEBUG, "OPT - initialized %u options.\n", cfg_mgr_->count());
// init_usb();
devui::init_ui(uicb, false);
devui::send_message(devui::UI_STATUS_READY, nullptr, 0);
}
void async_scanner::init_usb(void)
{
auto bulk_handle = [this](dyn_mem_ptr data, uint32_t* used, packet_data_base_ptr* required) -> dyn_mem_ptr
{
LPPACK_BASE pack = (LPPACK_BASE)data->ptr();
if(used)
*used = data->get_rest();
return handle_bulk_cmd(pack, used, required, data->get_session_id());
};
auto on_connect = [this](bool connected) -> void
{
utils::to_log(LOG_LEVEL_ALL, "USB %s\n", connected ? "connected" : "dis-connected");
connected_ = connected;
if(!connected)
cis_->stop_scan();
};
usb_ = new async_usb_gadget(bulk_handle, on_connect);
last_err_ = usb_->last_error();
}
void async_scanner::add_option_to_ui_menu(const char* name, int pos)
{
SANE_Constraint_Type constraint = SANE_CONSTRAINT_NONE;
std::string vals(cfg_mgr_->get_option_value(name, SANE_ACTION_GET_ALL_VALUES, nullptr, nullptr, &constraint)),
cur(vals.c_str()),
title(cfg_mgr_->get_option_field_string(name, "title"));
const char *val = utils::next_string(vals.c_str());
devui::LPOPTMENU opl = nullptr;
size_t len = sizeof(devui::OPTMENU) + strlen(name) + 1 + title.length() + 1;
val = utils::next_string(val);
if(val)
vals.erase(0, val - vals.c_str());
else
vals = std::string("\0\0\0\0", 4);
len += vals.length();
opl = (devui::LPOPTMENU)malloc(len);
memset(opl, 0, len);
opl->title_off = strlen(name) + 1;
strcpy(opl->name, name);
strcpy(opl->name + opl->title_off, title.c_str());
opl->value_off = opl->title_off + title.length() + 1;
memcpy(opl->name + opl->value_off, vals.c_str(), vals.length());
opl->pos = pos;
val = vals.c_str();
while(val)
{
if(cur == val)
break;
val = utils::next_string(val);
opl->cur_sel++;
}
devui::send_message(devui::UI_CMD_ADD_MENU, (uint8_t*)opl, len);
free(opl);
2023-12-01 09:17:09 +00:00
}
bool async_scanner::on_energy_conservation(bool normal)
{
bool enable = true;
if(normal)
{
}
else
{
if(cis_->is_scanning())
enable = false;
}
return enable;
}
2023-12-01 09:17:09 +00:00
dyn_mem_ptr async_scanner::handle_simple_roger(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required, uint32_t session)
2023-12-01 09:17:09 +00:00
{
uint32_t base_head_size = sizeof(PACK_BASE);
dyn_mem_ptr reply = dyn_mem::memory(base_head_size);
LPPACK_BASE pk = (LPPACK_BASE)reply->ptr();
*used = base_head_size;
BASE_PACKET_REPLY(*pk, pack->cmd + 1, pack->pack_id, 0);
reply->set_len(base_head_size);
return reply;
}
dyn_mem_ptr async_scanner::handle_get_opt_value(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required, uint32_t session)
2023-12-01 09:17:09 +00:00
{
uint32_t base_head_size = sizeof(PACK_BASE);
dyn_mem_ptr reply = nullptr;
LPPACK_BASE pk = nullptr;
if(*used < base_head_size + pack->payload_len)
{
*used = 0;
}
else
{
std::string val(cfg_mgr_->get_option_value(pack->payload, SANE_ACTION_GET_VALUE));
uint32_t err = val.empty() ? SCANNER_ERR_NO_DATA : SCANNER_ERR_OK;
LPCFGVAL cfg = nullptr;
reply = dyn_mem::memory(base_head_size + sizeof(CFGVAL) + strlen(pack->payload) + 1 + val.length() + 1);
pk = (LPPACK_BASE)reply->ptr();
BASE_PACKET_REPLY(*pk, pack->cmd + 1, pack->pack_id, err);
cfg = (LPCFGVAL)pk->payload;
cfg->val_size = val.length();
cfg->val_off = 0;
cfg->name_off = val.length() + 1;
pk->payload_len = sizeof(CFGVAL) + strlen(pack->payload) + 1 + val.length() + 1;
memcpy(cfg->data, val.c_str(), val.length());
strcpy(cfg->data + cfg->name_off, pack->payload);
reply->set_len(base_head_size + pk->payload_len);
*used = base_head_size + pack->payload_len;
}
return reply;
}
dyn_mem_ptr async_scanner::handle_get_opt_all(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required, uint32_t session)
2023-12-01 09:17:09 +00:00
{
uint32_t base_head_size = sizeof(PACK_BASE);
dyn_mem_ptr reply = nullptr;
LPPACK_BASE pk = nullptr;
*used = base_head_size;
{
std::string val(cfg_mgr_->get_option_value(nullptr, SANE_ACTION_GET_ENTIRE_JSON));
uint32_t err = 0;
reply = dyn_mem::memory(base_head_size + val.length() + 1);
pk = (LPPACK_BASE)reply->ptr();
BASE_PACKET_REPLY(*pk, pack->cmd + 1, pack->pack_id, err);
strcpy(pk->payload, val.c_str());
pk->payload_len = val.length() + 1;
reply->set_len(base_head_size + val.length() + 1);
}
return reply;
}
dyn_mem_ptr async_scanner::handle_set_opt(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required, uint32_t session)
{
uint32_t base_head_size = sizeof(PACK_BASE);
2023-12-01 09:17:09 +00:00
dyn_mem_ptr reply = nullptr;
LPPACK_BASE pk = nullptr;
if (*used < base_head_size + pack->payload_len)
*used = 0;
else
{
LPCFGVAL cfg = (LPCFGVAL)pack->payload,
cfg_ret = nullptr;
std::string name(cfg->data + cfg->name_off);
size_t l = base_head_size + sizeof(CFGVAL) + name.length() + 1 + cfg->max_size + 1, val_size = cfg->val_size;
int32_t err = 0;
uint32_t after = 0;
reply = dyn_mem::memory(l);
pk = (LPPACK_BASE)reply->ptr();
cfg_ret = (LPCFGVAL)pk->payload;
cfg_ret->name_off = 0;
strcpy(cfg_ret->data + cfg_ret->name_off, name.c_str());
cfg_ret->val_off = name.length() + 1;
memcpy(cfg_ret->data + cfg_ret->val_off, cfg->data + cfg->val_off, cfg->val_size);
cfg_ret->val_size = cfg->val_size;
cfg_ret->max_size = cfg->max_size;
cfg_ret->type = cfg->type;
err = cfg_mgr_->update_data(cfg->data + cfg->name_off, cfg_ret->data + cfg_ret->val_off);
if(err == SCANNER_ERR_RELOAD_OPT_PARAM || err == SCANNER_ERR_RELOAD_IMAGE_PARAM || err == SCANNER_ERR_CONFIGURATION_CHANGED)
{
after = err;
err = SCANNER_ERR_OK;
}
2023-12-01 09:17:09 +00:00
cfg_ret->after_do = after;
cfg_ret->val_size = val_size;
if(name == SANE_OPT_NAME(LOGIN))
{
int priv = user_->get_current_privilege();
memcpy(cfg_ret->data + cfg_ret->val_off, &priv, sizeof(priv));
}
2023-12-01 09:17:09 +00:00
BASE_PACKET_REPLY(*pk, pack->cmd + 1, pack->pack_id, err);
pk->payload_len = sizeof(CFGVAL) + name.length() + 1 + cfg->max_size + 1;
reply->set_len(l);
}
return reply;
}
dyn_mem_ptr async_scanner::handle_file_receive(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required, uint32_t session)
2023-12-01 09:17:09 +00:00
{
uint32_t base_head_size = sizeof(PACK_BASE);
dyn_mem_ptr reply = nullptr;
LPPACK_BASE pk = nullptr;
if(*used < pack->payload_len + pack->size)
{
*used = 0;
}
else
{
LPTXFILE pfi = (LPTXFILE)pack->payload;
std::string path(pfi->path);
int err = 0;
file_saver *saver = new file_saver();
2023-12-09 10:21:05 +00:00
err = saver->open(path.c_str(), pfi->size, true, pfi->offset);
2023-12-01 09:17:09 +00:00
reply = dyn_mem::memory(base_head_size);
reply->set_len(base_head_size);
BASE_PACKET_REPLY(*((LPPACK_BASE)reply->ptr()), pack->cmd + 1, pack->pack_id, err);
*used = base_head_size + pack->payload_len;
if(err)
{
saver->release();
saver = nullptr;
}
else
{
saver->set_packet_param(pack->cmd, pack->pack_id);
}
2023-12-13 06:57:08 +00:00
utils::to_log(LOG_LEVEL_DEBUG, "Receiving file(%p bytes): %s = %d\n", pfi->size, path.c_str(), err);
2023-12-01 09:17:09 +00:00
*required = dynamic_cast<packet_data_base_ptr>(saver);
}
return reply;
}
dyn_mem_ptr async_scanner::handle_file_send(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required, uint32_t session)
2023-12-01 09:17:09 +00:00
{
uint32_t base_head_size = sizeof(PACK_BASE);
dyn_mem_ptr reply = dyn_mem::memory(base_head_size);
LPPACK_BASE pk = (LPPACK_BASE)reply->ptr();
if(*used < pack->payload_len + pack->size)
{
*used = 0;
}
else
{
LPTXFILE pfi = (LPTXFILE)pack->payload;
std::string path(pfi->path);
int err = 0;
file_reader *reader = new file_reader();
2023-12-09 10:21:05 +00:00
err = reader->open(path.c_str(), true, pfi->offset);
2023-12-01 09:17:09 +00:00
reply = dyn_mem::memory(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);
2023-12-29 08:25:05 +00:00
((LPPACK_BASE)reply->ptr())->payload_len = sizeof(TXFILE);
2023-12-01 09:17:09 +00:00
*used = base_head_size + pack->payload_len;
utils::to_log(LOG_LEVEL_DEBUG, "To send file '%s' with %u bytes = %d\n", path.c_str(), reader->get_rest(), err);
if(err)
{
reader->release();
reader = nullptr;
}
else
{
((LPTXFILE)((LPPACK_BASE)reply->ptr())->payload)->size = reader->get_rest();
reader->set_packet_param(pack->cmd, pack->pack_id);
2023-12-09 10:21:05 +00:00
{
// 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);
}
return reply;
}
dyn_mem_ptr async_scanner::handle_file_send_roger(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required, uint32_t session)
2023-12-09 10:21:05 +00:00
{
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;
}
}
2023-12-01 09:17:09 +00:00
}
2023-12-13 06:57:08 +00:00
2023-12-29 08:25:05 +00:00
if(!reader)
{
utils::log_mem_info("FATAL: Sending file lost source object !!!", pack, *used, LOG_LEVEL_FATAL);
}
else if(pack->data)
2023-12-13 06:57:08 +00:00
{
utils::to_log(LOG_LEVEL_DEBUG, "Sending file '%s' (%p) cancelled with error %d.\n", reader->path_file(), reader, pack->data);
reader->release();
reader = nullptr;
}
2023-12-29 08:25:05 +00:00
else
2023-12-13 06:57:08 +00:00
{
// if reader was nullptr, notify failed by INT or control ?
utils::to_log(LOG_LEVEL_DEBUG, "Sending file '%s' (%p) ...\n", reader->path_file(), reader);
}
2023-12-29 08:25:05 +00:00
*used = base_head_size;
2023-12-01 09:17:09 +00:00
*required = dynamic_cast<packet_data_base_ptr>(reader);
}
return reply;
}
dyn_mem_ptr async_scanner::handle_scan_start(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required, uint32_t session)
2023-12-01 09:17:09 +00:00
{
if(!used)
{
reply_start_ = true;
return nullptr;
}
uint32_t base_head_size = sizeof(PACK_BASE);
dyn_mem_ptr reply = nullptr;
std::string config("");
2023-12-01 09:17:09 +00:00
img_cnt_ = 0;
scan_id_ = pack->pack_id;
scan_err_ = 0;
reply_start_ = false;
auto receiver = [this](CIS_IMAGE_PROTO) -> void
2023-12-29 02:53:04 +00:00
{
img_prcr_->process(data, type, lpinfo);
2023-12-29 02:53:04 +00:00
};
2024-02-25 05:51:52 +00:00
DECL_CHK_RES_FUNC(this, res)
{
return res_mgr_->is_resource_enable((enum _task)task, wait, to_ms);
};
2023-12-29 02:53:04 +00:00
utils::print_memory_usage("Memory usage before scanning", true);
2023-12-01 09:17:09 +00:00
*used = base_head_size;
img_prcr_->start_new_turn(scan_id_, session);
2024-02-25 05:51:52 +00:00
scan_err_ = cis_->open(receiver, res, &config);
reply = dyn_mem::memory(base_head_size + config.length() + 2);
reply->set_len(base_head_size + config.length() + 2);
2023-12-29 02:53:04 +00:00
if(scan_err_ == 0)
scan_err_ = cis_->start_scan();
2024-01-03 09:39:16 +00:00
if(scan_err_)
{
cis_->stop_scan();
2024-01-29 06:47:35 +00:00
cis_->close();
}
else
{
2024-01-29 06:47:35 +00:00
system("echo performance > /sys/devices/system/cpu/cpu5/cpufreq/scaling_governor");
res_mgr_->start();
}
2023-12-01 09:17:09 +00:00
BASE_PACKET_REPLY(*((LPPACK_BASE)reply->ptr()), pack->cmd + 1, pack->pack_id, scan_err_);
((LPPACK_BASE)reply->ptr())->payload_len = config.length() + 2;
strcpy(((LPPACK_BASE)reply->ptr())->payload, config.c_str());
2023-12-01 09:17:09 +00:00
*used |= INT32_MAX + 1;
return reply;
}
dyn_mem_ptr async_scanner::handle_scan_stop(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required, uint32_t session)
2023-12-01 09:17:09 +00:00
{
uint32_t base_head_size = sizeof(PACK_BASE);
dyn_mem_ptr reply = dyn_mem::memory(base_head_size);
int err = 0;
utils::to_log(LOG_LEVEL_DEBUG, "Received command Stop-Scan.\n");
2023-12-29 02:53:04 +00:00
err = cis_->stop_scan();
2023-12-01 09:17:09 +00:00
BASE_PACKET_REPLY(*((LPPACK_BASE)reply->ptr()), pack->cmd + 1, pack->pack_id, err);
reply->set_len(base_head_size);
*used = base_head_size;
return reply;
}
dyn_mem_ptr async_scanner::handle_process_cmd(LPPACK_BASE pack, uint32_t* used, packet_data_base_ptr* required, uint32_t session)
2023-12-01 09:17:09 +00:00
{
uint32_t base_head_size = sizeof(PACK_BASE);
dyn_mem_ptr reply = dyn_mem::memory(base_head_size);
LPPACK_BASE pk = (LPPACK_BASE)reply->ptr();
*used = base_head_size + pack->payload_len;
BASE_PACKET_REPLY(*pk, pack->cmd + 1, pack->pack_id, EINVAL);
reply->set_len(base_head_size);
return reply;
}
uint32_t async_scanner::stop(void)
{
if(img_prcr_)
img_prcr_->stop();
2023-12-01 09:17:09 +00:00
if(usb_)
{
usb_->stop();
}
return 0;
2023-12-01 09:17:09 +00:00
}
2023-12-01 10:03:10 +00:00
int async_scanner::last_error(void)
{
return last_err_;
}
2024-01-27 09:43:13 +00:00
void async_scanner::print_usb_status(void)
{
EP0REPLYSTATUS status;
char *stdesc[] = {"WORKER_STATUS_NOT_START", "WORKER_STATUS_IDLE"
, "WORKER_STATUS_BUSY", "WORKER_STATUS_ERROR", "WORKER_STATUS_RESET"
, "WORKER_STATUS_WAIT_RESOURCE"};
memset(&status, 0, sizeof(status));
usb_->get_ep_status(&status);
printf("Bulk-In status: %s, error = %d, %u bytes in que\n", stdesc[status.in_status], status.in_err, status.bytes_to_sent);
printf("Bulk-Out status: %s, error = %d, need %u bytes data of task %d\n", stdesc[status.out_status]
, status.out_err, status.task_required_bytes, status.task_cmd);
}