476 lines
10 KiB
C++
476 lines
10 KiB
C++
#include "scanner.h"
|
|
|
|
|
|
#include "../../common/log_util.h"
|
|
#include "../../common/ipc_wrapper.h"
|
|
#include "../../common/json/json.h"
|
|
#include "../img_collector/img_collector.h"
|
|
#include "../img_process/img_process.h"
|
|
#include "../res_monitor/res_monitor.h"
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// scanner
|
|
scanner::scanner(const char* ipc_id) : img_proc_(nullptr), img_src_(nullptr), res_(nullptr), ipc_(nullptr)
|
|
, exit_(nullptr), run_(true), status_(SCANNER_STATUS_READY), ipc_id_(ipc_id)
|
|
, partial_msg_(""), write_thunk_(false)
|
|
{
|
|
hw_status_.val = 0;
|
|
exit_ = new linux_event("exit-scanner");
|
|
}
|
|
scanner::~scanner()
|
|
{
|
|
uninit();
|
|
exit_->release();
|
|
}
|
|
|
|
int32_t scanner::init(void)
|
|
{
|
|
run_ = true;
|
|
img_proc_ = new img_processor(dynamic_cast<paremeter_get*>(this), dynamic_cast<event_handler*>(this));
|
|
img_src_ = image_collector::create_image_collector(dynamic_cast<event_handler*>(this));
|
|
res_ = new res_mon(dynamic_cast<event_handler*>(this));
|
|
ipc_ = ipc_wrapper::create_ipc(dynamic_cast<event_handler*>(this), ipc_wrapper::IPC_SHARED_MEM, ipc_id_.c_str());
|
|
|
|
return ipc_->is_ok() ? 0 : ENOTCONN;
|
|
}
|
|
int32_t scanner::uninit(void)
|
|
{
|
|
run_ = false;
|
|
if (ipc_)
|
|
{
|
|
ipc_->stop();
|
|
ipc_->release();
|
|
}
|
|
if (res_)
|
|
{
|
|
res_->stop();
|
|
res_->release();
|
|
}
|
|
if (img_src_)
|
|
{
|
|
img_src_->stop();
|
|
img_src_->uninit();
|
|
img_src_->release();
|
|
}
|
|
if (img_proc_)
|
|
{
|
|
img_proc_->stop();
|
|
img_proc_->release();
|
|
}
|
|
|
|
img_proc_ = nullptr;
|
|
img_src_ = nullptr;
|
|
res_ = nullptr;
|
|
ipc_ = nullptr;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int32_t scanner::add_ref(void)
|
|
{
|
|
return event_handler::add_ref();
|
|
}
|
|
int32_t scanner::release(void)
|
|
{
|
|
return event_handler::release();
|
|
}
|
|
|
|
int32_t scanner::from_thunk_data(std::string& pack)
|
|
{
|
|
LPPACK_BASE pk = (LPPACK_BASE)&pack[0];
|
|
|
|
if (pk->thunk && pk->cmd != PACK_CMD_INNER_WRITE)
|
|
{
|
|
std::string d("");
|
|
LPTHUNKD pthk = (LPTHUNKD)pk->payload;
|
|
while (pthk->bytes)
|
|
{
|
|
d += std::string(pthk->data, pthk->bytes);
|
|
pthk = (LPTHUNKD)((char*)pthk + sizeof(THUNKD) + pthk->bytes);
|
|
}
|
|
pack.erase(sizeof(PACK_BASE));
|
|
pack += d;
|
|
((LPPACK_BASE)&pack[0])->thunk = 0;
|
|
((LPPACK_BASE)&pack[0])->total_bytes = d.length();
|
|
}
|
|
|
|
return pack.length();
|
|
}
|
|
int32_t scanner::dispatch_ipc_message(LPPACK_BASE pack)
|
|
{
|
|
if (write_thunk_ && pack->cmd != PACK_CMD_INNER_WRITE)
|
|
{
|
|
return EAGAIN;
|
|
}
|
|
|
|
if (pack->cmd == PACK_CMD_ATTR_HISTORY_COUNT_GET)
|
|
{
|
|
|
|
}
|
|
else if (pack->cmd == PACK_CMD_ATTR_ROLLER_COUNT_GET)
|
|
{
|
|
|
|
}
|
|
else if (pack->cmd == PACK_CMD_ATTR_ROLLER_COUNT_SET)
|
|
{
|
|
|
|
}
|
|
else if (pack->cmd == PACK_CMD_SETTING_GET)
|
|
{
|
|
size_t len = 0;
|
|
char *buf = nullptr;
|
|
json *cis = nullptr, *proc = nullptr;
|
|
int ret = 0;
|
|
std::string cfg("");
|
|
|
|
if (img_src_->get_config(buf, &len) == ENOMEM)
|
|
{
|
|
buf = new char[len + 4];
|
|
if (img_src_->get_config(buf, &len) == 0)
|
|
{
|
|
cis = new json(buf);
|
|
}
|
|
}
|
|
ret = img_proc_->get_config(buf, &len);
|
|
if(ret == ENOMEM)
|
|
{
|
|
if (buf)
|
|
delete[] buf;
|
|
buf = new char[len + 4];
|
|
ret = img_proc_->get_config(buf, &len);
|
|
}
|
|
if (ret == 0)
|
|
{
|
|
proc = new json(buf);
|
|
if (cis)
|
|
{
|
|
json* child = cis->first_child();
|
|
while (child)
|
|
{
|
|
proc->set_value(child->key().c_str(), child);
|
|
child->release();
|
|
child = cis->next_child();
|
|
}
|
|
cis->release();
|
|
}
|
|
cfg = proc->to_string();
|
|
proc->release();
|
|
}
|
|
else if (cis)
|
|
{
|
|
cfg = cis->to_string();
|
|
cis->release();
|
|
}
|
|
if (buf)
|
|
delete[] buf;
|
|
|
|
PACK_BASE reply(*pack);
|
|
reply.result = cfg.empty() ? ENOENT : 0;
|
|
reply.thunk = 0;
|
|
reply.total_bytes = cfg.length();
|
|
cfg.insert(0, std::string((char*)&reply, sizeof(reply)));
|
|
len = cfg.length();
|
|
ipc_->write(cfg.c_str(), &len, false);
|
|
}
|
|
else if (pack->cmd == PACK_CMD_SETTING_GET_CUR)
|
|
{
|
|
|
|
}
|
|
else if (pack->cmd == PACK_CMD_SETTING_SET)
|
|
{
|
|
|
|
}
|
|
else if (pack->cmd == PACK_CMD_SETTING_RESTORE)
|
|
{
|
|
|
|
}
|
|
else if (pack->cmd == PACK_CMD_STATUS_GET)
|
|
{
|
|
PACK_BASE reply(*pack);
|
|
|
|
if (hw_status_.no_paper)
|
|
reply.result = SCANNER_STATUS_NO_PAPER;
|
|
else if (hw_status_.cover_opened)
|
|
reply.result = SCANNER_STATUS_COVER_OPENNED;
|
|
else if (hw_status_.sleeping)
|
|
reply.result = SCANNER_STATUS_SLEEPING;
|
|
else
|
|
reply.result = status_;
|
|
|
|
size_t len = sizeof(reply);
|
|
ipc_->write((char*)&reply, &len, false);
|
|
}
|
|
else if (pack->cmd == PACK_CMD_STATUS_RESTORE)
|
|
{
|
|
PACK_BASE reply(*pack);
|
|
size_t len = sizeof(reply);
|
|
|
|
reply.result = 0;
|
|
ipc_->write((char*)&reply, &len, false);
|
|
|
|
}
|
|
else if (pack->cmd == PACK_CMD_SCAN_START)
|
|
{
|
|
PACK_BASE reply(*pack);
|
|
|
|
if (hw_status_.no_paper)
|
|
reply.result = SCANNER_STATUS_NO_PAPER;
|
|
else if (hw_status_.cover_opened)
|
|
reply.result = SCANNER_STATUS_COVER_OPENNED;
|
|
else if (hw_status_.sleeping)
|
|
reply.result = SCANNER_STATUS_SLEEPING;
|
|
else if (status_ != SCANNER_STATUS_READY)
|
|
reply.result = status_;
|
|
else
|
|
reply.result = img_src_->start();
|
|
|
|
size_t len = sizeof(reply);
|
|
ipc_->write((char*)&reply, &len, false);
|
|
}
|
|
else if (pack->cmd == PACK_CMD_SCAN_STOP)
|
|
{
|
|
|
|
}
|
|
//else if (pack->cmd == PACK_CMD_SCAN_IMG_SIZE_GET)
|
|
//{
|
|
//
|
|
//}
|
|
//else if (pack->cmd == PACK_CMD_SCAN_IMG_READ)
|
|
//{
|
|
//
|
|
//}
|
|
//else if (pack->cmd == PACK_CMD_SCAN_IMG_POP)
|
|
//{
|
|
//
|
|
//}
|
|
else if (pack->cmd == PACK_CMD_INNER_WRITE)
|
|
{
|
|
size_t len = pack->total_bytes;
|
|
|
|
write_thunk_ = pack->thunk;
|
|
ipc_->write(pack->payload, &len, false);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
int32_t scanner::ipc_message_handler(void)
|
|
{
|
|
std::deque<std::string> task;
|
|
|
|
while (run_)
|
|
{
|
|
std::string msg("");
|
|
|
|
if (!msg_que_.take(msg, true))
|
|
continue;
|
|
|
|
from_thunk_data(msg);
|
|
if (dispatch_ipc_message((LPPACK_BASE)&msg[0]) == EAGAIN)
|
|
{
|
|
task.push_back(msg);
|
|
}
|
|
else if (!write_thunk_)
|
|
{
|
|
while (task.size())
|
|
{
|
|
msg = std::move(task.front());
|
|
task.pop_front();
|
|
dispatch_ipc_message((LPPACK_BASE)&msg[0]);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
int32_t scanner::on_ipc(void* data, size_t data_len, bool in)
|
|
{
|
|
int32_t ret = 0;
|
|
|
|
if (in)
|
|
{
|
|
partial_msg_ += std::string((char*)data, data_len);
|
|
|
|
if (partial_msg_.length() >= sizeof(PACK_BASE))
|
|
{
|
|
LPPACK_BASE pack = (LPPACK_BASE)&partial_msg_[0];
|
|
size_t len = sizeof(PACK_BASE) + pack->total_bytes;
|
|
if (pack->thunk)
|
|
{
|
|
LPTHUNKD pthk = (LPTHUNKD)pack->payload;
|
|
|
|
len = partial_msg_.length() - sizeof(PACK_BASE);
|
|
while (len >= sizeof(THUNKD))
|
|
{
|
|
if (pthk->bytes == 0)
|
|
{
|
|
pthk++;
|
|
len = (char*)pthk - (char*)pack;
|
|
|
|
std::string msg(&partial_msg_[0], len);
|
|
|
|
partial_msg_.erase(0, len);
|
|
msg_que_.save(msg, true);
|
|
break;
|
|
}
|
|
if (len < pthk->bytes + sizeof(THUNKD))
|
|
break;
|
|
|
|
len -= pthk->bytes + sizeof(THUNKD);
|
|
pthk = (LPTHUNKD)(pthk->data + pthk->bytes);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (partial_msg_.length() >= len)
|
|
{
|
|
msg_que_.save(partial_msg_.substr(0, len), true);
|
|
partial_msg_.erase(0, len);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// several parts sent ...
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int32_t scanner::on_event(int32_t ev, void* data, size_t data_len)
|
|
{
|
|
// image-process, image-collector, resource-mgr, ipc_wrapper
|
|
int32_t ret = 0;
|
|
|
|
if (!run_)
|
|
return ESHUTDOWN;
|
|
|
|
switch (ev)
|
|
{
|
|
case SCANNER_EVENT_IPC_DATA_RECEIVED:
|
|
on_ipc(data, data_len, true);
|
|
break;
|
|
case SCANNER_EVENT_IPC_DATA_SENT:
|
|
on_ipc(data, data_len, false);
|
|
break;
|
|
case SCANNER_EVENT_COLLECTOR_WORKING:
|
|
status_ = SCANNER_STATUS_WORKING;
|
|
break;
|
|
case SCANNER_EVENT_COLLECTOR_IMG_DATA:
|
|
if (((LPIMGD)data)->info->pos.new_img && ((LPIMGD)data)->info->pos.img_over)
|
|
{
|
|
img_proc_->push_image(((LPIMGD)data)->info, ((LPIMGD)data)->data, data_len);
|
|
}
|
|
else
|
|
{
|
|
// thunked data, send by IPC immediately
|
|
PACK_BASE pk;
|
|
LPIMGD src = (LPIMGD)data;
|
|
std::string msg("");
|
|
THUNKD thunk;
|
|
|
|
pk.cmd = PACK_CMD_INNER_WRITE;
|
|
pk.thunk = !((LPIMGD)data)->info->pos.img_over;
|
|
if (((LPIMGD)data)->info->pos.new_img)
|
|
{
|
|
PACK_BASE head;
|
|
|
|
memset(&head, 0, sizeof(head));
|
|
head.cmd = PACK_CMD_SCAN_IMG_READ;
|
|
head.thunk = 1;
|
|
thunk.bytes = sizeof(head) + sizeof(src->info) + data_len;
|
|
head.total_bytes = thunk.bytes + sizeof(thunk);
|
|
msg = std::string((char*)&pk, sizeof(pk))
|
|
+ std::string((char*)&head, sizeof(head))
|
|
+ std::string((char*)&thunk, sizeof(thunk))
|
|
+ std::string((char*)&src->info, sizeof(src->info));
|
|
}
|
|
else
|
|
{
|
|
thunk.bytes = data_len;
|
|
msg = std::string((char*)&pk, sizeof(pk)) + std::string((char*)&thunk, sizeof(thunk));
|
|
}
|
|
msg += std::string((char*)src->data, data_len);
|
|
if (src->info->pos.img_over)
|
|
{
|
|
thunk.bytes = 0; // THUNK end flag
|
|
msg += std::string((char*)&thunk, sizeof(thunk));
|
|
}
|
|
((LPPACK_BASE)&msg[0])->total_bytes = msg.length() - sizeof(pk);
|
|
|
|
msg_que_.save(msg, true);
|
|
}
|
|
break;
|
|
case SCANNER_EVENT_COLLECTOR_PAPER_ON:
|
|
hw_status_.no_paper = !(*(bool*)data);
|
|
break;
|
|
case SCANNER_EVENT_COLLECTOR_COVER_OPENNED:
|
|
hw_status_.cover_opened = *(bool*)data;
|
|
break;
|
|
case SCANNER_EVENT_COLLECTOR_SLEEPPING:
|
|
hw_status_.sleeping = *(bool*)data;
|
|
break;
|
|
case SCANNER_EVENT_COLLECTOR_ERROR:
|
|
break;
|
|
case SCANNER_EVENT_COLLECTOR_STOPPED:
|
|
status_ = data_len ? (scanner_status)data_len : SCANNER_STATUS_READY;
|
|
break;
|
|
case SCANNER_EVENT_IMAGE_PROC_OK:
|
|
break;
|
|
case SCANNER_EVENT_RESOURCE_LOW_MEM:
|
|
case SCANNER_EVENT_RESOURCE_HIGH_CPU:
|
|
if (*(bool*)data) // low mem or high cpu
|
|
{
|
|
if (status_ == SCANNER_STATUS_WORKING)
|
|
{
|
|
if (img_src_->pause() == 0)
|
|
status_ = SCANNER_STATUS_PAUSING;
|
|
}
|
|
}
|
|
else if (status_ == SCANNER_STATUS_PAUSING)
|
|
{
|
|
if (img_src_->resume() == 0)
|
|
status_ = SCANNER_STATUS_WORKING;
|
|
}
|
|
img_proc_->set_speed_first(!(*(bool*)data));
|
|
break;
|
|
case SCANNER_EVENT_RESOURCE_LOW_DISK:
|
|
// we have no disk write operations, ignore now
|
|
break;
|
|
default:
|
|
ret = EINVAL;
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
int32_t scanner::get_fd(void)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
parameter* scanner::get_parameter(img_proc_param ipp)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
int32_t scanner::run(void)
|
|
{
|
|
int32_t ret = init();
|
|
|
|
if (ret == 0)
|
|
exit_->wait();
|
|
|
|
uninit();
|
|
|
|
return ret;
|
|
}
|
|
int32_t scanner::stop(void)
|
|
{
|
|
run_ = false;
|
|
exit_->trigger();
|
|
|
|
return 0;
|
|
}
|