From 137fe6a839d4a34f92651e6d31b66b2dc550b1a0 Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Wed, 28 Dec 2022 10:40:59 +0800 Subject: [PATCH] scanner module --- common/CMakeLists.txt | 17 + common/event_monitor.h | 55 ++- common/ipc_util.h | 44 ++- common/ipc_wrapper.cpp | 7 +- common/ipc_wrapper.h | 9 - common/log_util.cpp | 9 +- common/log_util.h | 3 - common/packet.h | 214 +++++++++++ common/referer.cpp | 47 ++- common/referer.h | 47 +++ scanner/CMakeLists.txt | 32 +- scanner/img_collector/CMakeLists.txt | 17 + scanner/img_collector/img_collector.cpp | 39 ++ scanner/img_collector/img_collector.h | 38 ++ scanner/img_process/CMakeLists.txt | 17 + scanner/img_process/img_process.cpp | 273 ++++++++++++++ scanner/img_process/img_process.h | 105 ++++++ scanner/main/CMakeLists.txt | 17 + scanner/main/main.cpp | 34 ++ scanner/main/scanner.cpp | 461 ++++++++++++++---------- scanner/main/scanner.h | 88 +++++ scanner/res_monitor/CMakeLists.txt | 17 + scanner/res_monitor/res_monitor.cpp | 29 ++ scanner/res_monitor/res_monitor.h | 33 ++ sln/scanner.vcxproj | 11 +- sln/scanner.vcxproj.filters | 36 ++ 26 files changed, 1443 insertions(+), 256 deletions(-) create mode 100644 common/CMakeLists.txt create mode 100644 common/packet.h create mode 100644 scanner/img_collector/CMakeLists.txt create mode 100644 scanner/img_collector/img_collector.cpp create mode 100644 scanner/img_collector/img_collector.h create mode 100644 scanner/img_process/CMakeLists.txt create mode 100644 scanner/img_process/img_process.cpp create mode 100644 scanner/img_process/img_process.h create mode 100644 scanner/main/CMakeLists.txt create mode 100644 scanner/main/main.cpp create mode 100644 scanner/main/scanner.h create mode 100644 scanner/res_monitor/CMakeLists.txt create mode 100644 scanner/res_monitor/res_monitor.cpp create mode 100644 scanner/res_monitor/res_monitor.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt new file mode 100644 index 0000000..500096d --- /dev/null +++ b/common/CMakeLists.txt @@ -0,0 +1,17 @@ +project(common) +add_compile_options(-std=c++11) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") +aux_source_directory(${PROJECT_SOURCE_DIR} DIR_SRCS) +file(GLOB DIR_HEADS "${PROJECT_SOURCE_DIR}/*.h" "${PROJECT_SOURCE_DIR}/*.cpp") +set(DIR_SRCS ${DIR_SRCS} ${DIR_HEADS}) +add_library(${PROJECT_NAME} STATIC ${DIR_SRCS}) + +target_link_libraries(${PROJECT_NAME} PRIVATE + dl + pthread + rt + ) +target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR} + ) +set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/../scanner/build/) diff --git a/common/event_monitor.h b/common/event_monitor.h index 94ead54..9900bb5 100644 --- a/common/event_monitor.h +++ b/common/event_monitor.h @@ -11,6 +11,49 @@ typedef std::shared_ptr THREAD_PTR; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// event definition ... +enum scanner_event +{ + SCANNER_EVENT_NONE = 0, + + // 1 - IPC + SCANNER_EVENT_IPC_DATA_RECEIVED = 1, + SCANNER_EVENT_IPC_DATA_SENT, + + // 2 - image-collector + SCANNER_EVENT_COLLECTOR_WORKING = 100, // on_event(, nullptr, 0), the first message after start success + + // normal image, double feeding image, jammed image, stapled imge, size-check error image ... + SCANNER_EVENT_COLLECTOR_IMG_BEGIN, // on_event(, LPPACKIMAGE/*data_size can be ZERO*/, (bool)local_display/*show mesaage to local-liquid-crystal screen*/), start a new image data transferring + SCANNER_EVENT_COLLECOTR_GET_BUF, // on_event(, LPREQBUF, len) + SCANNER_EVENT_COLLECTOR_IMG_DATA, // on_event(, (uint8_t*)data, bytes of data), image data transfer + SCANNER_EVENT_COLLECTOR_IMG_END, // on_event(, LPPACKIMAGE, sizeof(PACKIMAGE)), an image data has been transmitted + + SCANNER_EVENT_COLLECTOR_PAPER_ON, // on_event(, (bool*)paper_on, (bool)local_display) + SCANNER_EVENT_COLLECTOR_COVER_OPENNED, // on_event(, (bool*)openned, (bool)local_display) + SCANNER_EVENT_COLLECTOR_SLEEPPING, // on_event(, (bool*)sleepping, (bool)local_display) + SCANNER_EVENT_COLLECTOR_ERROR, // on_event(, (char*)err-msg, (bool)local_display), used when unknown fatal error occurs! + + SCANNER_EVENT_COLLECTOR_STOPPED, // on_event(, (char*)err-msg, (size_t)err-code), the last message after start success + + // 3 - image-process + SCANNER_EVENT_IMAGE_PROC_FINAL_BUF = 200, // on_event(, (void**)buf, (size_t)len), get buffer for store the final image + SCANNER_EVENT_IMAGE_PROC_OK, + SCANNER_EVENT_IMAGE_PROC_ERR, + + // 4 - resource + SCANNER_EVENT_RESOURCE_LOW_MEM = 300, + SCANNER_EVENT_RESOURCE_LOW_DISK, + SCANNER_EVENT_RESOURCE_HIGH_CPU, +}; + +typedef struct _req_buf +{ + size_t len; + uint8_t* buf; +}REQBUF, *LPREQBUF; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // object event_handler // @@ -23,14 +66,14 @@ protected: virtual ~event_handler(); public: - enum - { - EVENT_NONE = 0, - EVENT_READ, // indicates that the 'fd' is readable, you should perform 'read' if data was null - EVENT_WRITE, // indicates that the 'fd' is writeable, data in 'data' has sent 'data_len' bytes, in async-write only - }; virtual int32_t on_event(int32_t ev, void* data, size_t data_len) = 0; virtual int32_t get_fd(void) = 0; + + enum + { + EVENT_READ = 0, + EVENT_WRITE, + }; }; class parent_holder : public refer diff --git a/common/ipc_util.h b/common/ipc_util.h index a9691e1..14c3a8a 100644 --- a/common/ipc_util.h +++ b/common/ipc_util.h @@ -19,7 +19,7 @@ class linux_event : public refer { int32_t err_; sem_t local_sem_; - sem_t *sem_; + sem_t* sem_; bool first_; bool multi_proc_; volatile bool waiting_; @@ -56,34 +56,44 @@ class safe_fifo { MUTEX lock_; std::deque que_; + linux_event* wait_; public: - safe_fifo() + safe_fifo() : wait_(new linux_event("fifo")) {} ~safe_fifo() - {} + { + wait_->release(); + } public: - void save(const T& t) + void save(const T& t, bool notify = false) { LOCKER lock(lock_); - - que_.push_back(t); + + que_.push_back(std::move(t)); + if (notify) + wait_->trigger(); } - bool take(T& t) + bool take(T& t, bool wait = false) { - LOCKER lock(lock_); + if (wait) + wait_->wait(); - if (que_.size()) { - t = que_.front(); - que_.pop_front(); + LOCKER lock(lock_); - return true; - } - else - { - return false; + if (que_.size()) + { + t = std::move(que_.front()); + que_.pop_front(); + + return true; + } + else + { + return false; + } } } size_t size(void) @@ -105,7 +115,7 @@ class shared_mem : public refer std::string name_; int32_t id_; int32_t shm_id_; - char *shm_buf_; + char* shm_buf_; size_t size_; bool first_; diff --git a/common/ipc_wrapper.cpp b/common/ipc_wrapper.cpp index 5180c48..21f57ac 100644 --- a/common/ipc_wrapper.cpp +++ b/common/ipc_wrapper.cpp @@ -34,6 +34,7 @@ class ipc_wrapper_shm : public ipc_wrapper char data[8]; // internal data }SYNCSHM, *LPSYNCSHM; volatile bool run_; + MUTEX write_lock_; int32_t id_; shared_mem* shm_; LPSYNCSHM sync_shm_; @@ -71,12 +72,10 @@ class ipc_wrapper_shm : public ipc_wrapper sprintf(buf, "%d-", id); desc += buf; - printf("Total size: %ld, Head size: %d, pack-head: %d\n", pack.space, head, pack_head); sync_shm_ = (LPSYNCSHM)ptr; ptr += head; pack.space -= head + pack_head * 2; head = ALIGN_INT(pack.space * sent_percent / 100, 16); - printf("%ld * %d%% = %d\n", pack.space, sent_percent, head); if (shm_->is_first()) { SYNCSHM ss; @@ -116,7 +115,6 @@ class ipc_wrapper_shm : public ipc_wrapper buf_out_ = (LPSHMPACK)ptr; buf_in_ = (LPSHMPACK)(ptr + pack_head + buf_out_->space); } - printf("buf in = %p + %ld, buf out = %p + %ld\n", buf_in_, buf_in_->space, buf_out_, buf_out_->space); thread_.reset(new std::thread(&ipc_wrapper_shm::read_thread, this)); // handler_->on_event(event_handler::EVENT_WRITE, buf_out_->data, buf_size_); @@ -134,7 +132,7 @@ class ipc_wrapper_shm : public ipc_wrapper if (!shm_->is_first() && sync_shm_->data[DATA_INTER_CMD] == INTER_CMD_EXIT) break; - handler->on_event(event_handler::EVENT_READ, buf_in_->data, buf_in_->bytes); + handler->on_event(SCANNER_EVENT_IPC_DATA_RECEIVED, buf_in_->data, buf_in_->bytes); notify_write_->trigger(); } handler->release(); @@ -166,6 +164,7 @@ public: if(std::this_thread::get_id() == thread_->get_id()) return EDEADLOCK; + LOCKER lock(write_lock_); size_t rest = *bytes; int32_t ret = 0; diff --git a/common/ipc_wrapper.h b/common/ipc_wrapper.h index adea885..1263de0 100644 --- a/common/ipc_wrapper.h +++ b/common/ipc_wrapper.h @@ -8,15 +8,6 @@ #include "event_monitor.h" -typedef struct _pack_base -{ - uint64_t total_bytes; // total bytes of payload - uint64_t offset; // offset in total of this part - uint64_t bytes; // bytes in data, not include this head - int32_t cmd; // command - char data[0]; // payload -}PACK_BASE, *LPPACK_BASE; - class ipc_wrapper : public parent_holder { diff --git a/common/log_util.cpp b/common/log_util.cpp index c2706e0..4650624 100644 --- a/common/log_util.cpp +++ b/common/log_util.cpp @@ -69,16 +69,15 @@ void log_cls::initialize(const char* path_file, log_level level, int32_t max_siz if (!path_file || *path_file == 0) { size_t pos = 0; - char strpid[20] = {0}; + std::string def_dir(getenv("HOME") + std::string("/.scanner/log")); path = sys_util::get_module_path(); pos = path.rfind('/'); if (pos++ != std::string::npos) path.erase(0, pos); - path.insert(0, "/tmp/scanner/"); - mkdir("/tmp/scanner", S_IREAD | S_IWRITE | S_IEXEC); - sprintf(strpid, "_%p.log", getpid()); - path += strpid; + path.insert(0, def_dir + "/"); + sys_util::create_folder(def_dir.c_str()); + path += ".log"; path_file = path.c_str(); } log_cls::inst_ = new log_cls(path_file, level, max_size); diff --git a/common/log_util.h b/common/log_util.h index 069c246..3778ba0 100644 --- a/common/log_util.h +++ b/common/log_util.h @@ -10,9 +10,6 @@ #include #include -#define SIZE_KB(n) (n) * 1024 -#define SIZE_MB(n) SIZE_KB((n) * 1024) -#define SIZE_GB(n) SIZE_MB((n) * 1024) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/common/packet.h b/common/packet.h new file mode 100644 index 0000000..febd6d0 --- /dev/null +++ b/common/packet.h @@ -0,0 +1,214 @@ +#pragma once + +// packet structures and command +// +// created on 2022-12-06 +// +#include + +/////////////////////////////////////////////////////////////////////////////// +// definitions ... +#define CONFIG_NAME_MAX_LEN 32 // max bytes of configuration name + + +// NOTE: All text transmitted by pack cmd is in UTF-8 format !!! + +enum packet_cmd +{ + PACK_CMD_HEART_BEAT = 0, // notify peers you are still alive, receiver should reply the same pack + + // attributes get/set, all content in PACK_BASE::data should be in JSON style + PACK_CMD_ATTR_SYS_VER_GET = 10, // get system version on device, [in]: PACK_BASE, [out] PACK_BASE::data - {"os":"linux", "ver":"4.4.194", ...} + PACK_CMD_ATTR_FIRMWARE_VER_GET, // get firmware version, [in]: PACK_BASE, [out] PACK_BASE::data - {"firmware":"G2393A1234", "CIS":"CIS-123", ...} + PACK_CMD_ATTR_SERIAL_NUM_GET, // get device serial num, [in]: PACK_BASE, [out] PACK_BASE::data - {"serial":"20221206001"} + PACK_CMD_ATTR_SERIAL_NUM_SET, // set device serial num, [in]: PACK_BASE::data - {"serial":"20221206001"}, [out] PACK_BASE + PACK_CMD_ATTR_MAC_GET, // get mac address, [in]: PACK_BASE, [out] PACK_BASE::data - {"mac":"12:34:56:78:9a:bc"} + PACK_CMD_ATTR_IP_GET, // get ip address, [in]: PACK_BASE, [out] PACK_BASE::data - {"ipv4":"192.168.1.123", "ipv6":"::1"} + PACK_CMD_ATTR_HARDWARE_INFO_GET, // get hardwares information on device, [in]: PACK_BASE, [out] PACK_BASE::data - {"CPU":"ARM x86", "mem":"16GB", ...} + PACK_CMD_ATTR_HISTORY_COUNT_GET, // get history count, [in]: PACK_BASE, [out] PACK_BASE::data - {"history-count":12345, ...} + PACK_CMD_ATTR_ROLLER_COUNT_GET, // get roller count, [in]: PACK_BASE, [out] PACK_BASE::data - {"roller-count":2345} + PACK_CMD_ATTR_ROLLER_COUNT_SET, // set roller count, [in]: PACK_BASE::data - {"roller-count":2345}, [out] PACK_BASE + + // configuration get/set + PACK_CMD_SETTING_GET = 50, // get all settings supported by the device, [in]: PACK_BASE, [out]: PACK_BASE::data - configuration JSON, see SANE-configuration format + PACK_CMD_SETTING_GET_CUR, // get current value of given setting, [in]: PACK_BASE::data - LPCFGVAL, [out]: PACK_BASE::data - LPCFGVAL + PACK_CMD_SETTING_SET, // set value of given setting, [in]: PACK_BASE::data - LPCFGVAL, [out]: PACK_BASE on OK or PACK_BASE::data - LPCFGVAL + PACK_CMD_SETTING_RESTORE, // restore given settings, [in]: PACK_BASE, [out]: PACK_BASE + + // status management + PACK_CMD_STATUS_GET = 60, // get current status of device, [in]: PACK_BASE, [out]: PACK_BASE + PACK_CMD_STATUS_RESTORE, // restore status to initializing, [in]: PACK_BASE, [out]: PACK_BASE + + // scan command + PACK_CMD_SCAN_START = 100, // start scanning, [in]: PACK_BASE, [out]: PACK_BASE + PACK_CMD_SCAN_STOP, // stop scanning, [in]: PACK_BASE, [out]: PACK_BASE + PACK_CMD_SCAN_IMG_SIZE_GET, // get size of the first image, [in]: PACK_BASE, [out]: PACK_BASE::data - (unsigned long long*) + PACK_CMD_SCAN_IMG_READ, // read first image, [in]: PACK_BASE, [out]: PACK_BASE::data - LPPACKIMAGE + PACK_CMD_SCAN_IMG_POP, // discard first image, [in]: PACK_BASE, [out]: PACK_BASE + + // file operation + PACK_CMD_FILE_QUERY = 150, // query file information, [in]: PACK_BASE::data - (char*)file-path, [out] PACK_BASE::data - LPFILEINFO + PACK_CMD_FILE_READ, // read file content, [in]: PACK_BASE::data - (char*)file-path, [out] PACK_BASE::data - file content + PACK_CMD_FILE_WRITE, // write a file, [in]: PACK_BASE::data - LPFILEINFO, [out] PACK_BASE::data - (char*)path-file. should receive whole data even if fails + PACK_CMD_FILE_MOVE, // move/rename a file, [in]: PACK_BASE::data - LPFILEINFO, [out] same data as in + PACK_CMD_FILE_REMOVE, // delete a file, [in]: PACK_BASE::data - (char*)file-path, [out] same data as in + + // process operation + PACK_CMD_PROCESS_REBOOT = 200, // reboot system, [in]: PACK_BASE, [out]: PACK_BASE + PACK_CMD_PROCESS_START, // start a program [in]: PACK_BASE::data - (char*)command string, [out]: PACK_BASE::data - (char*)process-id + PACK_CMD_PROCESS_STOP, // kill a process [in]: PACK_BASE::data - (char*)process-id, [out]: PACK_BASE + PACK_CMD_PROCESS_EXEC_RESULT, // get result of a command, [in]: PACK_BASE::data - (char*)command string, [out]: PACK_BASE::data - (char*)execute result. popen(), fgets ... + PACK_CMD_PROCESS_QUERY, // query process information [in]: PACK_BASE::data - (char*)process-id(-1 for all), [out]: LPPROCINFO + + PACK_CMD_TOKEN_GET = 272, // 0x110, Obtain the token of the required command, [in] PACK_BASE, [out] - PACK_BASE::data - LPOPERTOKEN +}; + +enum scanner_status +{ + SCANNER_STATUS_READY = 0, + SCANNER_STATUS_START_SCANNING, // start ok, but scanning-thread not working + SCANNER_STATUS_WORKING, // start ok, and scanning-thread is working + SCANNER_STATUS_COVER_OPENNED, + SCANNER_STATUS_COUNT_MODE, + SCANNER_STATUS_DOUBLE_FEEDED, + SCANNER_STATUS_PAPER_JAMMED, + SCANNER_STATUS_PAPER_ASKEW, + SCANNER_STATUS_FEED_FAILED, + SCANNER_STATUS_NO_PAPER, + SCANNER_STATUS_CFG_CHANGED, // PACK_BASE::data - LPCFGVAL +}; + +enum img_format +{ + IMG_FMT_UNKNOWN = 0, // unknown format + IMG_FMT_TIFF, + IMG_FMT_BMP, + IMG_FMT_JPEG, + IMG_FMT_PNG, + IMG_FMT_SVG, + IMG_FMT_WEBP, + IMG_FMT_GIF, +}; +enum img_compression +{ + IMG_COMPRESSION_NONE = 0, + IMG_COMPRESSION_GROUP4, + IMG_COMPRESSION_RLE4, + IMG_COMPRESSION_RLE8, + IMG_COMPRESSION_LZW, + IMG_COMPRESSION_ZIP, +}; +enum img_status +{ + IMG_STATUS_OK = 0, + IMG_STATUS_DOUBLE, + IMG_STATUS_JAM, + IMG_STATUS_STAPLE, // staples on the paper + IMG_STATUS_SIZE_ERR, // size check failed + IMG_STATUS_DOGEAR, // paper has dogear +}; +enum data_type +{ + DATA_TYPE_BOOL = 0, // (bool*) + DATA_TYPE_INT1, // (uint8_t*) + DATA_TYPE_INT2, // (uint16_t*) + DATA_TYPE_INT4, // (uint32_t*) + DATA_TYPE_INT8, // (uint64_t*) + DATA_TYPE_FLOAT, // (double*) + DATA_TYPE_STRING, // (char*) with max_len space + DATA_TYPE_CUSTOM, +}; + +#pragma pack(push) +#pragma pack(1) +typedef struct _pack_base // A piece of data has only one header +{ + uint64_t total_bytes : 63; // total bytes of payload + uint64_t thunk : 1; // when was 1, the payloads is stored as THUNKED in 'payload', and total_bytes is data bytes in 'payload' of this packet + uint32_t pack_id; // maintain by the initiator, the reply use the same id + uint32_t timestamp; // time stamp, in milliseconds, maintain by the initiator, used to timeout control + uint32_t cmd; // packet_cmd on initiator side + uint32_t result; // command result(error code) on roger side + char payload[0]; // payloads, according to 'cmd', LPTHUNKD if 'thunk' was 1 +}PACK_BASE, * LPPACK_BASE; + +typedef struct _thunk_data +{ + uint16_t bytes; // bytes in 'data', 0 is end for whole data + char data[0]; // data buffer with length 'bytes' +}THUNKD, *LPTHUNKD; + +typedef struct _cfg_val +{ + uint16_t count; // count of array 'vals' + struct + { + char name[CONFIG_NAME_MAX_LEN]; // configuration name + uint16_t val_buf_len; // capacity of 'val' + char val[2]; // value + }vals[1]; +}CFGVAL, *LPCFGVAL; + +typedef struct _img_pos +{ + uint64_t paper_ind : 32; // paper index in this turn/start, based ZERO + uint64_t paper_side : 1; // 0 - front of paper(When scanning multiple sheets, the paper feeding side is the front side), 1 - back of paper + uint64_t split_ind : 7; // splitting order, from left to right and then top to bottom, based ZERO + uint64_t multiout_ind : 4; // index of multi-out + uint64_t channel_ind : 4; // index of color channel, based ZERO, 0x0f for all channels + uint64_t status : 4; // img_status + uint64_t reserved : 12; // reserved +}IMGPOS, *LPIMGPOS; +typedef struct _pack_img +{ + IMGPOS pos; // image pos info ... + uint32_t width; // image width in pixel + uint32_t height; // image height in pixel + uint32_t resolution_x; // image horizontal reolution + uint32_t resolution_y; // image vertical reolution + uint32_t channels : 6; // image channels per pixel + uint32_t format : 6; // image format, see 'img_format' + uint32_t bpp : 6; // bits per pixel + uint32_t bppc : 6; // bits per pixel in this channel, equal to 'bpp' if pos.channel_ind == 0x0f + uint32_t compression : 6; // image data compression, see 'img_compression' + uint32_t reserve : 2; // unused now + uint32_t info_size; // image information size in bytes, information part is used for quality of JPEG, pallete of BMP ... + uint64_t data_size; // image data size in bytes + char data[0]; // two parts: image info (info_size) + image data (data_size) +}PACKIMAGE, *LPPACKIMAGE; + +typedef struct _oper_token +{ + uint32_t type; // token type + char data[128]; // token data +}OPERTOKEN, *LPOPERTOKEN; + +typedef struct _file_info +{ + OPERTOKEN token; // operation token, returned by command PACK_CMD_TOKEN_GET + uint64_t size; // file size + uint16_t name_len; // bytes of file name string + uint16_t create_time_len; // bytes of create time string: '2022-12-07 12:34:56.789', or target file path in command PACK_CMD_FILE_MOVE + uint16_t modify_time_len; + uint16_t version_len; // bytes of version string + char data[0]; // 4 parts: path-file(name_len) + create-time(create_time_len) + modify-time(modify_time_len) + version(version_len) + // or 5 parts in command PACK_CMD_FILE_WRITE, add content at the last part of bytes 'size' +}FILEINFO, *LPFILEINFO; + +typedef struct _proc_info +{ + OPERTOKEN token; // operation token, returned by command PACK_CMD_TOKEN_GET + uint32_t count; // number of elements in array proc + struct _info + { + uint16_t len; // bytes of this element, include this head + uint64_t pid; // process id + uint64_t ppid; // parent process id + uint64_t start; // started time in ns from 1970-01-01 00:00:00 + uint64_t mem; // memory usage, in bytes + uint64_t cpu_clk; // cpu clock + char path_name[4]; + }proc[1]; +}PROCINFO, *LPPROCINFO; +#pragma pack(pop) + diff --git a/common/referer.cpp b/common/referer.cpp index 52e4738..42925e6 100644 --- a/common/referer.cpp +++ b/common/referer.cpp @@ -275,7 +275,28 @@ namespace sys_util } bool create_folder(const char* dir) { - return mkdir(dir, S_IREAD | S_IWRITE | S_IEXEC) == 0 || errno == EEXIST; + bool ret = mkdir(dir, S_IREAD | S_IWRITE | S_IEXEC) == 0 || errno == EEXIST; + + if(errno == ENOENT) + { + std::string path(dir), cur(""); + size_t pos = path.find("/", 1); + + while(pos != std::string::npos) + { + ret = mkdir(path.substr(0, pos).c_str(), S_IREAD | S_IWRITE | S_IEXEC) == 0 || errno == EEXIST; + if(!ret) + { + printf("mkdir(%s) = %d(%s)\n", path.substr(0, pos).c_str(), errno, strerror(errno)); + break; + } + pos = path.find("/", pos + 1); + } + if(ret) + ret = mkdir(path.c_str(), S_IREAD | S_IWRITE | S_IEXEC) == 0; + } + + return ret; } int32_t get_memory_info(uint64_t* total, uint64_t* available) @@ -351,5 +372,29 @@ namespace sys_util return str; } + std::string get_command_output(const char* cmd, uint16_t max_line_len, bool one_line) + { + FILE* src = popen(cmd, "r"); + std::string ret(""); + + if (src) + { + char* buf = new char[max_line_len + 4]; + if (buf) + { + memset(buf, 0, max_line_len + 4); + fgets(buf, max_line_len, src); + ret = buf; + while (!one_line && fgets(buf, max_line_len, src)) + ret += "\n" + std::string(buf); + + delete[] buf; + } + + pclose(src); + } + + return ret; + } } diff --git a/common/referer.h b/common/referer.h index 2b60b93..dd0748b 100644 --- a/common/referer.h +++ b/common/referer.h @@ -9,7 +9,13 @@ #include #define ALIGN_INT(val, n) ((((val) + (n) - 1) / (n)) * (n)) + +#define SIZE_KB(n) ((n) * 1024) +#define SIZE_MB(n) SIZE_KB((n) * 1024) +#define SIZE_GB(n) SIZE_MB((n) * 1024) + #define WAIT_INFINITE 0 + #define SEC_2_MS(s) ((s) * 1000) #define MSEC_2_US(ms) ((ms) * 1000) #define USEC_2_NS(us) ((us) * 1000) @@ -63,6 +69,46 @@ public: void reset(void); }; +class sane_cfg_provider : public refer +{ +public: + sane_cfg_provider() + {} + virtual ~sane_cfg_provider() + {} + +public: + // Function: get all or given name configuration value + // + // Parameters: buf - to receive the configuration value or all configuration JSON + // + // len - [in] bytes of 'buf', [out] - content bytes in 'buf', or minimum size needed + // + // cfg_name - given configuration name, if set, put current value of the configuration in 'buf', + // or put all configurations JSON text in 'buf' if was nullptr. refer to SANE-config + // + // Return: 0 - on success + // EINVAL - if paramter 'len' was nullptr + // ENOMEM - if size of 'buf' was too small, the minimum size needed is stored in 'len' + // ENOENT - the configuration named 'cfg_name' has not found + virtual int get_config(void* buf, size_t* len, const char* cfg_name = nullptr) = 0; + + // Function: set value of configuration named 'cfg_name' + // + // Parameters: cfg_name - the configuration name + // + // data - the value address, nullptr is for restore to default value + // (bool*), (int*), (double*), (char*) + // + // len - bytes in 'data' + // + // Return: 0 - on success + // EINVAL - parameter was invalid. 'cfg_name' was nullptr + // ENOENT - configuration 'cfg_name' was not found + // EUCLEAN - content in 'data' was not exact, the exact value is stored in 'data', and bytes in 'len' + virtual int set_config(const char* cfg_name, void* data, size_t* len) = 0; +}; + #include namespace sys_util { @@ -117,4 +163,5 @@ namespace sys_util int32_t get_memory_info(uint64_t* total, uint64_t* available); std::string format_readable_bytes(uint64_t bytes); // convert to readable text: 512B, 1.21KB, 1.10MB, 3.45GB, 1,234.56GB ... + std::string get_command_output(const char* cmd, uint16_t max_line_len = 256, bool one_line = true); } diff --git a/scanner/CMakeLists.txt b/scanner/CMakeLists.txt index 1e0bef0..1d04eb5 100644 --- a/scanner/CMakeLists.txt +++ b/scanner/CMakeLists.txt @@ -1,22 +1,14 @@ -project(scanner) -add_compile_options(-std=c++11) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") -aux_source_directory(${PROJECT_SOURCE_DIR} DIR_SRCS) -file(GLOB DIR_HEADS "${PROJECT_SOURCE_DIR}/*.h") -set(DIR_SRCS ${DIR_SRCS} ${DIR_HEADS}) -# add_library(${PROJECT_NAME} SHARED ${DIR_SRCS}) -add_executable(scanner ${PROJECT_SOURCE_DIR}/main/scanner.cpp ${PROJECT_SOURCE_DIR}/../common/event_monitor.cpp ${PROJECT_SOURCE_DIR}/../common/ipc_util.cpp ${PROJECT_SOURCE_DIR}/../common/log_util.cpp ${PROJECT_SOURCE_DIR}/../common/referer.cpp ${PROJECT_SOURCE_DIR}/../common/ipc_wrapper.cpp) -link_libraries(libdl libpthread librt) +project(scanner-prj) +add_subdirectory(img_collector) +add_subdirectory(img_process) +add_subdirectory(main) +add_subdirectory(res_monitor) +add_subdirectory(${CMAKE_SOURCE_DIR}/../common common.out) -target_link_libraries(${PROJECT_NAME} PRIVATE - dl - pthread - rt - ) -target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR} - ${PROJECT_SOURCE_DIR}/main - ${PROJECT_SOURCE_DIR}/../common - ) +link_libraries(common + imgproc + imgsrc + resmon + ) -set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/out) \ No newline at end of file +add_executable(scanner ${CMAKE_SOURCE_DIR}/main/main.cpp ${CMAKE_SOURCE_DIR}/main/scanner.cpp) \ No newline at end of file diff --git a/scanner/img_collector/CMakeLists.txt b/scanner/img_collector/CMakeLists.txt new file mode 100644 index 0000000..0e661ea --- /dev/null +++ b/scanner/img_collector/CMakeLists.txt @@ -0,0 +1,17 @@ +project(imgsrc) +add_compile_options(-std=c++11) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") +aux_source_directory(${PROJECT_SOURCE_DIR} DIR_SRCS) +file(GLOB DIR_HEADS "${PROJECT_SOURCE_DIR}/*.h" "${PROJECT_SOURCE_DIR}/*.cpp") +set(DIR_SRCS ${DIR_SRCS} ${DIR_HEADS}) +add_library(${PROJECT_NAME} STATIC ${DIR_SRCS}) + +target_link_libraries(${PROJECT_NAME} PRIVATE + dl + pthread + rt + ) +target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR} + ) +set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/../build/) diff --git a/scanner/img_collector/img_collector.cpp b/scanner/img_collector/img_collector.cpp new file mode 100644 index 0000000..5e7d7bf --- /dev/null +++ b/scanner/img_collector/img_collector.cpp @@ -0,0 +1,39 @@ +#include "img_collector.h" + +#include "../../common/event_monitor.h" + + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// image_collector +image_collector::image_collector(event_handler* handler) : handler_(handler) +{ + if (handler_) + handler_->add_ref(); +} +image_collector::~image_collector() +{} + +image_collector* image_collector::create_image_collector(event_handler* handler) +{ + return nullptr; +} + + +int32_t image_collector::trigger_event(int32_t ev, void* data, size_t data_len) +{ + if (handler_) + return handler_->on_event(ev, data, data_len); + else + return ENODEV; +} + +int image_collector::stop(void) +{ + if (handler_) + handler_->release(); + handler_ = nullptr; + + return 0; +} + diff --git a/scanner/img_collector/img_collector.h b/scanner/img_collector/img_collector.h new file mode 100644 index 0000000..3834f11 --- /dev/null +++ b/scanner/img_collector/img_collector.h @@ -0,0 +1,38 @@ +#pragma once + +// image collector interface class +// +// created on 2022-12-06 +// + +#include "../../common/referer.h" +#include "../../common/packet.h" + + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// image collector ... +class event_handler; + +class image_collector : public sane_cfg_provider +{ + event_handler* handler_; + +public: + image_collector(event_handler*); + +protected: + virtual ~image_collector(); + + int32_t trigger_event(int32_t ev, void* data, size_t data_len); + +public: + static image_collector* create_image_collector(event_handler* handler); + +public: + virtual int re_init(void) = 0; // can be called many times + virtual int start(void) = 0; + virtual int stop(void); // class derives from this should call me ! + virtual int uninit(void) = 0; +}; + diff --git a/scanner/img_process/CMakeLists.txt b/scanner/img_process/CMakeLists.txt new file mode 100644 index 0000000..b9ed0e0 --- /dev/null +++ b/scanner/img_process/CMakeLists.txt @@ -0,0 +1,17 @@ +project(imgproc) +add_compile_options(-std=c++11) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") +aux_source_directory(${PROJECT_SOURCE_DIR} DIR_SRCS) +file(GLOB DIR_HEADS "${PROJECT_SOURCE_DIR}/*.h" "${PROJECT_SOURCE_DIR}/*.cpp") +set(DIR_SRCS ${DIR_SRCS} ${DIR_HEADS}) +add_library(${PROJECT_NAME} STATIC ${DIR_SRCS}) + +target_link_libraries(${PROJECT_NAME} PRIVATE + dl + pthread + rt + ) +target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR} + ) +set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/../build/) diff --git a/scanner/img_process/img_process.cpp b/scanner/img_process/img_process.cpp new file mode 100644 index 0000000..c7a638d --- /dev/null +++ b/scanner/img_process/img_process.cpp @@ -0,0 +1,273 @@ +#include "img_process.h" + + +#include "../../common/event_monitor.h" +#include + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// class parameter +parameter::parameter() : type_(DATA_TYPE_INT4), bytes_(4) +{ + val_.n32_val = 0; +} +parameter::parameter(bool val) : type_(DATA_TYPE_BOOL), bytes_(sizeof(val)) +{ + val_.b_val = val; +} +parameter::parameter(uint8_t val) : type_(DATA_TYPE_INT1), bytes_(sizeof(val)) +{ + val_.n8_val = val; +} +parameter::parameter(uint16_t val) : type_(DATA_TYPE_INT2), bytes_(sizeof(val)) +{ + val_.n16_val = val; +} +parameter::parameter(uint32_t val) : type_(DATA_TYPE_INT4), bytes_(sizeof(val)) +{ + val_.n32_val = val; +} +parameter::parameter(uint64_t val) : type_(DATA_TYPE_INT8), bytes_(sizeof(val)) +{ + val_.n64_val = val; +} +parameter::parameter(double val) : type_(DATA_TYPE_FLOAT), bytes_(sizeof(val)) +{ + val_.d_val = val; +} +parameter::parameter(char* val, size_t bytes) : type_(DATA_TYPE_STRING), bytes_(bytes) +{ + if (bytes_ == 0) + bytes_ = strlen(val) + 1; + + val_.dyn_val = new char[bytes_]; + memcpy(val_.dyn_val, val, bytes_); +} +parameter::parameter(parameter& r) +{ + copy(r); +} + +parameter::~parameter() +{ + clear(); +} + +void parameter::clear(void) +{ + if ((type_ == DATA_TYPE_STRING || type_ == DATA_TYPE_CUSTOM) && val_.dyn_val) + delete[] val_.dyn_val; + + type_ = DATA_TYPE_INT4; + val_.n32_val = 0; +} +void parameter::copy(const parameter& r) +{ + clear(); + type_ = r.type_; + bytes_ = r.bytes_; + val_.dyn_val = r.val_.dyn_val; + if (type_ == DATA_TYPE_STRING && r.val_.dyn_val) + { + val_.dyn_val = new char[r.bytes_]; + memcpy(val_.dyn_val, r.val_.dyn_val, bytes_); + } +} + +parameter& parameter::operator=(bool val) +{ + clear(); + type_ = DATA_TYPE_BOOL; + bytes_ = sizeof(val); + val_.b_val = val; + + return *this; +} +parameter& parameter::operator=(uint8_t val) +{ + clear(); + type_ = DATA_TYPE_INT1; + bytes_ = sizeof(val); + val_.n8_val = val; + + return *this; +} +parameter& parameter::operator=(uint16_t val) +{ + clear(); + type_ = DATA_TYPE_INT2; + bytes_ = sizeof(val); + val_.n16_val = val; + + return *this; +} +parameter& parameter::operator=(uint32_t val) +{ + clear(); + type_ = DATA_TYPE_INT4; + bytes_ = sizeof(val); + val_.n32_val = val; + + return *this; +} +parameter& parameter::operator=(uint64_t val) +{ + clear(); + type_ = DATA_TYPE_INT8; + bytes_ = sizeof(val); + val_.n64_val = val; + + return *this; +} +parameter& parameter::operator=(double val) +{ + clear(); + type_ = DATA_TYPE_FLOAT; + bytes_ = sizeof(val); + val_.d_val = val; + + return *this; +} +parameter& parameter::operator=(const char* val) +{ + clear(); + bytes_ = strlen(val) + 1; + val_.dyn_val = new char[bytes_]; + memcpy(val_.dyn_val, val, bytes_); + + return *this; +} +parameter& parameter::operator=(const std::string& val) +{ + clear(); + bytes_ = val.length() + 1; + val_.dyn_val = new char[bytes_]; + memcpy(val_.dyn_val, val.c_str(), bytes_); + + return *this; +} +parameter& parameter::operator=(const parameter& r) +{ + copy(r); + + return *this; +} + +void* parameter::reset_buf(size_t bytes) +{ + clear(); + bytes_ = bytes; + val_.dyn_val = new char[bytes_]; + memset(val_.dyn_val, 0, bytes_); + + return val_.dyn_val; +} +void* parameter::value(size_t* len) +{ + if (len) + *len = bytes_; + + void* buf = nullptr; + switch (type_) + { + case DATA_TYPE_BOOL: + buf = &val_.b_val; + break; + case DATA_TYPE_INT1: + buf = &val_.n8_val; + break; + case DATA_TYPE_INT2: + buf = &val_.n16_val; + break; + case DATA_TYPE_INT4: + buf = &val_.n32_val; + break; + case DATA_TYPE_INT8: + buf = &val_.n64_val; + break; + case DATA_TYPE_FLOAT: + buf = &val_.d_val; + break; + case DATA_TYPE_STRING: + default: + buf = val_.dyn_val; + break; + } + + return buf; +} +data_type parameter::type(void) +{ + return type_; +} + + + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// class img_processor +img_processor::img_processor(paremeter_get* get, event_handler* h) : param_get_(get), handler_(h) +{ + if (param_get_) + param_get_->add_ref(); + if (handler_) + handler_->add_ref(); +} +img_processor::~img_processor() +{} + +int img_processor::get_config(void* buf, size_t* len, const char* cfg_name) +{ + int ret = 0; + std::string val(""); + + if (!len) + return EINVAL; + + if (cfg_name) + { + + } + else + { + + } + + if (ret == 0) + { + if (*len >= val.length()) + { + *len = val.length() + 4; + ret = ENOMEM; + } + else + { + memcpy(buf, val.c_str(), val.length()); + *len = val.length(); + } + } + + return ret; +} +int img_processor::set_config(const char* cfg_name, void* data, size_t* len) +{ + int ret = 0; + + return ret; +} + +int img_processor::push_image(LPPACKIMAGE img) +{ + return 0; +} +int img_processor::stop(void) +{ + if (param_get_) + param_get_->release(); + if (handler_) + handler_->release(); + param_get_ = nullptr; + handler_ = nullptr; + + return 0; +} diff --git a/scanner/img_process/img_process.h b/scanner/img_process/img_process.h new file mode 100644 index 0000000..98d571e --- /dev/null +++ b/scanner/img_process/img_process.h @@ -0,0 +1,105 @@ +#pragma once + +// image process interface classes +// +// created on 2022-12-14 +// + +#include "../../common/referer.h" +#include "../../common/packet.h" + +enum img_proc_param +{ + IMG_PROC_PARAM_DPI = 1, // double + IMG_PROC_PARAM_BPP, // uint8_t + IMG_PROC_PARAM_CHANNEL, // uint8_t + IMG_PROC_PARAM_COLOR, // uint8_t + IMG_PROC_PARAM_GAMMA, // (char*), custom structure + IMG_PROC_PARAM_BRIGHT, // double + IMG_PROC_PARAM_CONTRAST, // double +}; + +class parameter : public refer +{ + data_type type_; + size_t bytes_; + union + { + bool b_val; + uint8_t n8_val; + uint16_t n16_val; + uint32_t n32_val; + uint64_t n64_val; + double d_val; + char *dyn_val; + }val_; + + void clear(void); + void copy(const parameter& r); + +protected: + virtual ~parameter(); + +public: + parameter(); + parameter(bool val); + parameter(uint8_t val); + parameter(uint16_t val); + parameter(uint32_t val); + parameter(uint64_t val); + parameter(double val); + parameter(char* val, size_t bytes = 0); + parameter(parameter& r); + +public: + parameter& operator=(bool val); + parameter& operator=(uint8_t val); + parameter& operator=(uint16_t val); + parameter& operator=(uint32_t val); + parameter& operator=(uint64_t val); + parameter& operator=(double val); + parameter& operator=(const char* val); + parameter& operator=(const std::string& val); + parameter& operator=(const parameter& r); + + void* reset_buf(size_t bytes); // reset data type to string and with bytes space + void* value(size_t* len); + data_type type(void); +}; + +class paremeter_get : public refer +{ +protected: + paremeter_get() + {} + virtual ~paremeter_get() + {} + +public: + virtual parameter* get_parameter(img_proc_param ipp) = 0; +}; + + +class event_handler; + +class img_processor : public sane_cfg_provider +{ + paremeter_get* param_get_; + event_handler* handler_; + +public: + img_processor(paremeter_get*, event_handler*); + +protected: + ~img_processor(); + + // sane_cfg_provider +public: + virtual int get_config(void* buf, size_t* len, const char* cfg_name = nullptr) override; + virtual int set_config(const char* cfg_name, void* data, size_t* len) override; + +public: + int push_image(LPPACKIMAGE img); + int stop(void); +}; + diff --git a/scanner/main/CMakeLists.txt b/scanner/main/CMakeLists.txt new file mode 100644 index 0000000..c499e2d --- /dev/null +++ b/scanner/main/CMakeLists.txt @@ -0,0 +1,17 @@ +project(scanner) +add_compile_options(-std=c++11) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") +aux_source_directory(${PROJECT_SOURCE_DIR} DIR_SRCS) +file(GLOB DIR_HEADS "${PROJECT_SOURCE_DIR}/*.h" "${PROJECT_SOURCE_DIR}/*.cpp") +set(DIR_SRCS ${DIR_SRCS} ${DIR_HEADS}) +add_library(${PROJECT_NAME} STATIC ${DIR_SRCS}) + +target_link_libraries(${PROJECT_NAME} PRIVATE + dl + pthread + rt + ) +target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR} + ) +set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/../build/) diff --git a/scanner/main/main.cpp b/scanner/main/main.cpp new file mode 100644 index 0000000..72ffb5d --- /dev/null +++ b/scanner/main/main.cpp @@ -0,0 +1,34 @@ +// scanner.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 +// + +#include +#include +#include +#include + +#include "../../common/log_util.h" +#include "scanner.h" + + +int32_t main(int32_t argc, char *argv[]) +{ + char *oper = argc > 1 ? argv[1] : nullptr; + + log_cls::initialize(nullptr); + log_cls::log(LOG_LEVEL_DEBUG, "----starting...----\n"); + + if (oper) + { + scanner* scnr = nullptr; + int ret = 0; + + std::string id(sys_util::get_module_path() + ":0:104857600"); + scnr = new scanner(id.c_str()); // ("/usr/bin/idtransponder:0:104857600"); + ret = scnr->run(); + scnr->release(); + log_cls::log(LOG_LEVEL_DEBUG, "----stopped with: %s----\n", strerror(ret)); + } + log_cls::log(LOG_LEVEL_DEBUG, "----stopped.----\n"); + + return 0; +} diff --git a/scanner/main/scanner.cpp b/scanner/main/scanner.cpp index c6fe8c0..6766bca 100644 --- a/scanner/main/scanner.cpp +++ b/scanner/main/scanner.cpp @@ -1,201 +1,282 @@ -// scanner.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 -// +#include "scanner.h" -#include -#include -#include -#include -#include "../../common/ipc_util.h" #include "../../common/log_util.h" -#include "../../common/event_monitor.h" #include "../../common/ipc_wrapper.h" +#include "../img_collector/img_collector.h" +#include "../img_process/img_process.h" +#include "../res_monitor/res_monitor.h" -static void test(const char* oper); -int32_t main(int32_t argc, char *argv[]) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// 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_("") { - char *oper = argc > 1 ? argv[1] : nullptr; - - log_cls::initialize(nullptr); - log_cls::log(LOG_LEVEL_DEBUG, "----starting...----\n"); - - test(oper); - - return 0; + exit_ = new linux_event("exit-scanner"); +} +scanner::~scanner() +{ + uninit(); + exit_->release(); } -class rogger : public event_handler +int32_t scanner::init(void) { - linux_event* quit_; - ipc_wrapper* ipc_; - safe_fifo reply_; - volatile bool run_; - - int32_t wait(void) - { - while(quit_->wait()) - { - if(!run_) - break; - - std::string answer(""); - - if (reply_.take(answer)) - { - size_t len = answer.length(); - - if (len) - ipc_->write(answer.c_str(), &len, false, 100); - } - } - } - int32_t run_client(ipc_wrapper* s) - { - size_t len = SIZE_MB(1); - char* buf = (char*)s->get_kbuf(&len); - - printf("--->request 1MB buffer of IPC internal, returned %u\n", len); - do - { - size_t l = 0, count = 0; - chronograph watch; - - printf("Input message: "); - while ((buf[l++] = getchar()) != '\n'); - buf[--l] = 0; - - watch.reset(); - s->write(buf, &l, true); - if(strcmp(buf, "exit") == 0) - break; - - while(1) - { - if(quit_->wait(50)) - { - std::string rcvd(""); - if (reply_.take(rcvd)) - { - if (rcvd.length()) - { - count++; - printf("reply(%d): %s\n", rcvd.length(), rcvd.c_str()); - l = rcvd.length(); - strcpy(buf, rcvd.c_str()); - if(s->write(buf, &l, true, 30) == ETIME) - { - printf("send content timouted(%ld in %ld us)!\n", count, watch.elapse_us()); - break; - } - } - } - if(rcvd.empty()) - printf("reply(0)\n"); - } - else - { - printf("wait reply timeout(%ld in %ld us).\n", count, watch.elapse_us()); - break; - } - } - - } while (1); - s->release_kbuf(buf); - } - -public: - rogger() : quit_(new linux_event("quit")), run_(true) - { - std::string param(sys_util::get_module_path() + ":0:1024:10"); - ipc_ = ipc_wrapper::create_ipc(this, ipc_wrapper::IPC_SHARED_MEM, param.c_str()); - } - -protected: - ~rogger() - { - quit_->release(); - } - -public: - int32_t on_event(int32_t ev, void* data, size_t data_len) override - { - if (ev == EVENT_READ) - { - char* d = (char*)data; - std::string str(d, data_len); - - d[data_len] = 0; - if(ipc_->is_first()) - { - printf("R(%d): %s\n", data_len, d); - for (size_t i = 0; i < str.length() / 2; ++i) - { - char c = str[i]; - - str[i] = str[str.length() - i - 1]; - str[str.length() - i - 1] = c; - } - } - - if (strcmp(d, "exit") == 0) - { - printf("Bye-bye :)\n"); - run_ = false; - // quit_->trigger(); - } - else - reply_.save(str); - quit_->trigger(); - } - - return 0; - } - int32_t get_fd(void) - { - return -1; - } - - void run(void) - { - if (ipc_->is_first()) - { - printf("%p run as server ...\n", getpid()); - wait(); - } - else - { - printf("%p run as client ...\n", getpid()); - run_client(ipc_); - } - - ipc_->stop(); - ipc_->release(); - } - void clear_kobjects(void) - { - ipc_->clear_kernel_objects(); - } - - void test_timed_wait(unsigned ms) - { - for(int i = 0; i < 1; ++i) - { - printf("%s: wait(%u) ...\n", chronograph::now().c_str(), ms); - printf("%s: wait result %d\n\n", chronograph::now().c_str(), quit_->wait(ms)); - } - } -}; - -static void test(const char* oper) -{ - rogger* r = new rogger(); - - r->test_timed_wait(123); - - if(oper && strcmp(oper, "clear") == 0) - r->clear_kobjects(); - else - r->run(); - r->release(); + run_ = true; + img_proc_ = new img_processor(dynamic_cast(this), dynamic_cast(this)); + img_src_ = image_collector::create_image_collector(dynamic_cast(this)); + res_ = new res_mon(dynamic_cast(this)); + ipc_ = ipc_wrapper::create_ipc(dynamic_cast(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_->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) + { + 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; + } + + return pack.length(); +} +int32_t scanner::dispatch_ipc_message(LPPACK_BASE pack) +{ + 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) + { + + } + 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_RESTORE) + { + + } + else if (pack->cmd == PACK_CMD_SCAN_START) + { + + } + 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) + { + + } + + return 0; +} +int32_t scanner::ipc_message_handler(void) +{ + while (run_) + { + std::string msg(""); + + if (!msg_que_.take(msg, true)) + continue; + + from_thunk_data(msg); + 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_COLLECTOR_WORKING: + status_ = SCANNER_STATUS_WORKING; + break; + 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_COVER_OPENNED: + status_ = SCANNER_STATUS_COVER_OPENNED; + break; + case SCANNER_EVENT_COLLECTOR_PAPER_ON: + break; + case SCANNER_EVENT_COLLECOTR_GET_BUF: + 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; } diff --git a/scanner/main/scanner.h b/scanner/main/scanner.h new file mode 100644 index 0000000..b1a93a9 --- /dev/null +++ b/scanner/main/scanner.h @@ -0,0 +1,88 @@ +#pragma once + +// scanner center +// +// created on 2022-12-14 +// + +#include "../../common/event_monitor.h" +#include "../../common/ipc_util.h" +#include "../img_process/img_process.h" +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// scanner ... +#define TRY_GET_WITH_NOMEM(obj, method, buf, size) \ + if(obj->method == ENOMEM) \ + { \ + buf = new char[size + 4]; \ + if(buf) \ + { \ + memset(buf, 0, size + 4); \ + size += 1; \ + if(obj->method) \ + { \ + delete[] buf; \ + buf = nullptr; \ + } \ + } \ + } + +class img_processor; +class image_collector; +class res_mon; +class ipc_wrapper; +class linux_event; +enum scanner_status; + +class scanner : public event_handler, public paremeter_get +{ + std::string ipc_id_; // path-file:id:size + img_processor *img_proc_; + image_collector *img_src_; + res_mon *res_; + ipc_wrapper *ipc_; + linux_event *exit_; + volatile bool run_; + scanner_status status_; + safe_fifo msg_que_; + std::string partial_msg_; + + int32_t init(void); + int32_t uninit(void); + + int32_t get_configuration(const char* name, void* buf, size_t* size); + int32_t set_configuration(const char* name, void* buf, size_t* size); + int32_t start_scanning(void); + int32_t stop_scanning(void); + + int32_t from_thunk_data(std::string& pack); + int32_t dispatch_ipc_message(LPPACK_BASE pack); + int32_t ipc_message_handler(void); + int32_t on_ipc(void* data, size_t data_len, bool in); + +public: + scanner(const char* ipc_id); + +protected: + virtual ~scanner(); + + // refer +public: + virtual int32_t add_ref(void) override; + virtual int32_t release(void) override; + + // event_handler +public: + virtual int32_t on_event(int32_t ev, void* data, size_t data_len) override; + virtual int32_t get_fd(void) override; + + // paremeter_get +public: + virtual parameter* get_parameter(img_proc_param ipp) override; + + // methods +public: + int32_t run(void); + int32_t stop(void); +}; diff --git a/scanner/res_monitor/CMakeLists.txt b/scanner/res_monitor/CMakeLists.txt new file mode 100644 index 0000000..d8df086 --- /dev/null +++ b/scanner/res_monitor/CMakeLists.txt @@ -0,0 +1,17 @@ +project(resmon) +add_compile_options(-std=c++11) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") +aux_source_directory(${PROJECT_SOURCE_DIR} DIR_SRCS) +file(GLOB DIR_HEADS "${PROJECT_SOURCE_DIR}/*.h" "${PROJECT_SOURCE_DIR}/*.cpp") +set(DIR_SRCS ${DIR_SRCS} ${DIR_HEADS}) +add_library(${PROJECT_NAME} STATIC ${DIR_SRCS}) + +target_link_libraries(${PROJECT_NAME} PRIVATE + dl + pthread + rt + ) +target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR} + ) +set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/../build/) diff --git a/scanner/res_monitor/res_monitor.cpp b/scanner/res_monitor/res_monitor.cpp new file mode 100644 index 0000000..32aa9d3 --- /dev/null +++ b/scanner/res_monitor/res_monitor.cpp @@ -0,0 +1,29 @@ +#include "res_monitor.h" + + +#include "../../common/event_monitor.h" + + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// class res_mon +res_mon::res_mon(event_handler* h) : handler_(h) +{ + if (handler_) + handler_->add_ref(); +} +res_mon::~res_mon() +{} + +int res_mon::set_monitor_object(mon_obj obj, uint8_t consume_percent) +{ + return 0; +} +int res_mon::stop(void) +{ + if (handler_) + handler_->release(); + handler_ = nullptr; + + return 0; +} diff --git a/scanner/res_monitor/res_monitor.h b/scanner/res_monitor/res_monitor.h new file mode 100644 index 0000000..4f7416f --- /dev/null +++ b/scanner/res_monitor/res_monitor.h @@ -0,0 +1,33 @@ +#pragma once + +// image process interface classes +// +// created on 2022-12-14 +// + +#include "../../common/referer.h" +#include "../../common/packet.h" + +class event_handler; + +enum mon_obj +{ + MON_OBJ_MEM = 0, + MON_OBJ_CPU, + MON_OBJ_DISK, +}; + +class res_mon : public refer +{ + event_handler* handler_; + +public: + res_mon(event_handler*); + +protected: + virtual ~res_mon(); + +public: + int set_monitor_object(mon_obj obj, uint8_t consume_percent = 0/*0 is no monitor*/); + int stop(void); +}; diff --git a/sln/scanner.vcxproj b/sln/scanner.vcxproj index bc694dc..7864cb3 100644 --- a/sln/scanner.vcxproj +++ b/sln/scanner.vcxproj @@ -1,4 +1,4 @@ - + @@ -24,14 +24,23 @@ + + + + + + + + + diff --git a/sln/scanner.vcxproj.filters b/sln/scanner.vcxproj.filters index 45f3c91..4fd5711 100644 --- a/sln/scanner.vcxproj.filters +++ b/sln/scanner.vcxproj.filters @@ -19,6 +19,15 @@ {e0ad062f-4e6a-4d9a-b010-83ff181576a4} + + {3edeacc8-750f-4b6a-9330-05be99c0e091} + + + {4f3608db-4e86-4208-8138-6fd2c21341e5} + + + {35349bbb-fd1d-453e-b44e-23419326365c} + @@ -39,6 +48,18 @@ common + + img-collector + + + img-proc + + + res-mon + + + main + @@ -56,6 +77,21 @@ common + + common + + + img-collector + + + img-proc + + + res-mon + + + main +