391 lines
17 KiB
C
391 lines
17 KiB
C
#pragma once
|
|
|
|
// packet structures and command
|
|
//
|
|
// created on 2022-12-06
|
|
//
|
|
#if !defined(WIN32)
|
|
#include <bits/stdint-uintn.h>
|
|
#endif
|
|
#include <string.h>
|
|
|
|
#define TEMPORARY_API
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// definitions ...
|
|
#define CONFIG_NAME_MAX_LEN 32 // max bytes of configuration name
|
|
#define FLOAT_PRECISION .000001f
|
|
#define IS_FLOAT_EQUAL(x, y) (-FLOAT_PRECISION <= (x) - (y) && (x) - (y) <= FLOAT_PRECISION)
|
|
#define MAKE_WORD(b0, b1) (((b0) & 0xff) | (((b1) << 8) & 0x0ff00))
|
|
#define MAKE_STR(str) #str
|
|
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
|
|
|
#define ROGER(cmd) cmd##_ROGER
|
|
#define PAIR_COMMAND(cmd) \
|
|
cmd, \
|
|
cmd##_ROGER
|
|
|
|
#define RETURN_STR_ENUM(v, e) \
|
|
if(v == e) \
|
|
return #e;
|
|
|
|
#define STRUCT_CONSTRUCTOR(st_name) \
|
|
st_name() \
|
|
{ \
|
|
memset(this, 0, sizeof(st_name));\
|
|
}
|
|
|
|
// protocol version, The first thing to do after connecting is to check whether the field is compatible !!!
|
|
#define PROTOCOL_VER MAKE_WORD(0, 1)
|
|
|
|
// NOTE: All text transmitted by pack cmd is in UTF-8 format !!!
|
|
|
|
enum cancel_io
|
|
{
|
|
CANCEL_IO_CANCEL = 0x0ca0cel,
|
|
};
|
|
enum ep0_req
|
|
{
|
|
USB_REQ_EP0_HAND_SHAKE = 100, // hand-shake[in/out] with data LPPEERCFG, req = me, ind = 0, val = 0, len = sizeof(PEERCFG)
|
|
USB_REQ_EP0_GOOD_BYE, // disconnect, req = me, ind = 0, val = 0, len = sizeof(PEERCFG)
|
|
USB_REQ_EP0_GET_STATUS, // 获取各工作线程状态, return EP0REPLYSTATUS. req = me, ind = 0, val = bool: whether write log, len = sizeof(EP0REPLYSTATUS)
|
|
USB_REQ_EP0_CANCEL_IO, // 设置当前IO数据的有效性. req = me, ind = 0, val = 0, len = sizeof(uint32_t), discard IO data when data is CANCEL_IO_CANCEL
|
|
// work-flow: write control with 'CANCEL_IO_CANCEL', write bulk with 1 byte, write control with not 'CANCEL_IO_CANCEL' to restore
|
|
USB_REQ_EP0_SET_ENCRYPT, // 设置加密方式, req = me, ind = 0, val = 0, len = sizeof(PACK_BASE)
|
|
};
|
|
enum woker_status
|
|
{
|
|
WORKER_STATUS_NOT_START = 0, // has not start
|
|
WORKER_STATUS_IDLE, // idle
|
|
WORKER_STATUS_BUSY, // in working
|
|
WORKER_STATUS_ERROR, // error occurs
|
|
WORKER_STATUS_RESET, // in reset(close and reopen) process
|
|
WORKER_STATUS_WAIT_RESOURCE, // wait resource
|
|
};
|
|
|
|
enum packet_cmd
|
|
{
|
|
PACK_CMD_NULL,
|
|
|
|
PAIR_COMMAND(PACK_CMD_HEART_BEAT), // notify peers you are still alive, receiver should reply the same pack
|
|
PAIR_COMMAND(PACK_CMD_INVALID), // reply when received an invalid packet
|
|
PAIR_COMMAND(PACK_CMD_SYNC),
|
|
|
|
// attributes get/set, all content in PACK_BASE::payload should be in JSON style - all readonly attributes move to readonly SANE-options on 2023-03-20
|
|
//PACK_CMD_ATTR_SYS_VER_GET = 10, // get system version on device, [in]: PACK_BASE, [out] PACK_BASE::payload - {"os":"linux", "ver":"4.4.194", ...}
|
|
//PACK_CMD_ATTR_FIRMWARE_VER_GET, // get firmware version, [in]: PACK_BASE, [out] PACK_BASE::payload - {"firmware":"G2393A1234", "CIS":"CIS-123", ...}
|
|
//PACK_CMD_ATTR_SERIAL_NUM_GET, // get device serial num, [in]: PACK_BASE, [out] PACK_BASE::payload - {"serial":"20221206001"}
|
|
//PACK_CMD_ATTR_SERIAL_NUM_SET, // set device serial num, [in]: PACK_BASE::payload - {"serial":"20221206001"}, [out] PACK_BASE
|
|
//PACK_CMD_ATTR_MAC_GET, // get mac address, [in]: PACK_BASE, [out] PACK_BASE::payload - {"mac":"12:34:56:78:9a:bc"}
|
|
//PACK_CMD_ATTR_IP_GET, // get ip address, [in]: PACK_BASE, [out] PACK_BASE::payload - {"ipv4":"192.168.1.123", "ipv6":"::1"}
|
|
//PACK_CMD_ATTR_HARDWARE_INFO_GET, // get hardwares information on device, [in]: PACK_BASE, [out] PACK_BASE::payload - {"CPU":"ARM x86", "mem":"16GB", ...}
|
|
//PACK_CMD_ATTR_HISTORY_COUNT_GET, // get history count, [in]: PACK_BASE, [out] PACK_BASE::payload - {"history-count":12345, ...}
|
|
//PACK_CMD_ATTR_ROLLER_COUNT_GET, // get roller count, [in]: PACK_BASE, [out] PACK_BASE::payload - {"roller-count":2345}
|
|
//PACK_CMD_ATTR_ROLLER_COUNT_SET, // set roller count, [in]: PACK_BASE::payload - {"roller-count":2345}, [out] PACK_BASE
|
|
|
|
// configuration get/set
|
|
PACK_CMD_STATUS_ROGER = 100, // device -> host. PACK_BASE::result -> status
|
|
PAIR_COMMAND(PACK_CMD_SETTING_GET), // get all settings supported by the device, [in]: PACK_BASE, [out]: PACK_BASE::payload - configuration JSON, see SANE-configuration format
|
|
PAIR_COMMAND(PACK_CMD_SETTING_GET_CUR), // get current value of given setting, [in]: PACK_BASE::payload - (char*)name, [out]: PACK_BASE::payload - LPCFGVAL
|
|
PAIR_COMMAND(PACK_CMD_SETTING_SET), // set value of given setting, [in]: PACK_BASE::payload - LPCFGVAL, [out]: PACK_BASE::payload - LPCFGVAL
|
|
PAIR_COMMAND(PACK_CMD_SETTING_RESTORE), // restore given settings, [in]: PACK_BASE::payload - LPCFGVAL, [out]: PACK_BASE::payload - LPCFGVAL
|
|
|
|
// scan command
|
|
PACK_CMD_SCAN_BASE = 200,
|
|
PAIR_COMMAND(PACK_CMD_SCAN_START), // start scanning, [in]: PACK_BASE, [out]: PACK_BASE
|
|
PAIR_COMMAND(PACK_CMD_SCAN_IMG), // device -> host, PACK_BASE::payload - LPPACKIMAGE
|
|
PAIR_COMMAND(PACK_CMD_SCAN_PAPER), // device -> host, ONE paper has passed through the CIS. PACK_BASE::data - index of this paper
|
|
PACK_CMD_SCAN_FINISHED_ROGER, // device -> host, PACK_BASE::data is scanner_status
|
|
PAIR_COMMAND(PACK_CMD_SCAN_STOP), // stop scanning, [in]: PACK_BASE, [out]: PACK_BASE
|
|
//PAIR_COMMAND(PACK_CMD_SCAN_IMAGE_REQ), // get image request, [in]: PACK_BASE, [out] PACK_BASE on error, or PACK_BASE::payload - LPPACKIMAGE
|
|
//PAIR_COMMAND(PACK_CMD_SCAN_STATUS), // get scanner status, [in]: PACK_BASE, [out] PACK_BASE::result is status code
|
|
|
|
// file operation
|
|
PACK_CMD_FILE_BASE = 300,
|
|
//PAIR_COMMAND(PACK_CMD_FILE_QUERY), // query file information, [in]: PACK_BASE::payload - (char*)file-path, [out] PACK_BASE::payload - LPFILEINFO
|
|
PAIR_COMMAND(PACK_CMD_FILE_READ_REQ), // read file content, [in]: PACK_BASE::payload - LPTXFILE, [out] PACK_BASE::payload - LPTXFILE
|
|
PAIR_COMMAND(PACK_CMD_FILE_WRITE_REQ), // write a file, [in]: PACK_BASE::payload - LPTXFILE, [out] PACK_BASE
|
|
PAIR_COMMAND(PACK_CMD_FILE_MOVE), // move/rename a file, [in]: PACK_BASE::payload - src\0dst\0\0, [out] PACK_BASE
|
|
PAIR_COMMAND(PACK_CMD_FILE_REMOVE), // delete a file, [in]: PACK_BASE::payload - (char*)file-path, [out] PACK_BASE
|
|
|
|
// process operation
|
|
PACK_CMD_PROCESS_BASE = 400,
|
|
PAIR_COMMAND(PACK_CMD_PROCESS_START), // start a program [in]: PACK_BASE::payload - (char*)pe\0param\0\0, [out]: PACK_BASE::payload - (uint64_t)process-id on success or PACK_BASE on failure
|
|
PAIR_COMMAND(PACK_CMD_PROCESS_STOP), // kill a process [in]: PACK_BASE::payload - (char*)process-id, [out]: PACK_BASE
|
|
PAIR_COMMAND(PACK_CMD_PROCESS_REBOOT), // reboot system, [in]: PACK_BASE, [out]: PACK_BASE
|
|
//PAIR_COMMAND(PACK_CMD_PROCESS_EXEC_RESULT), // get result of a command, [in]: PACK_BASE::payload - (char*)command string, [out]: PACK_BASE::payload - (char*)execute result. popen(), fgets ...
|
|
//PAIR_COMMAND(PACK_CMD_PROCESS_QUERY), // query process information [in]: PACK_BASE::payload - (char*)process-id(-1 for all), [out]: LPPROCINFO
|
|
|
|
PACK_CMD_TOKEN_GET = 900, // Obtain the token of the required command, [in] PACK_BASE, [out] - PACK_BASE::payload - LPOPERTOKEN
|
|
};
|
|
|
|
enum img_cb_type
|
|
{
|
|
IMG_CB_IMAGE = 0,
|
|
IMG_CB_STATUS,
|
|
IMG_CB_STOPPED,
|
|
};
|
|
|
|
enum scanner_status
|
|
{
|
|
SCANNER_STATUS_READY = 0x10000, // status beginning, avoiding conficts with standards/system error code
|
|
SCANNER_STATUS_NOT_OPEN,
|
|
SCANNER_STATUS_LOST_CONNECT,
|
|
SCANNER_STATUS_RESET_BULK,
|
|
SCANNER_STATUS_START_SCANNING, // start ok, but scanning-thread not working
|
|
SCANNER_STATUS_SCANNING, // start ok, and scanning-thread is working
|
|
SCANNER_STATUS_SCAN_FINISHED, // not a persistance status
|
|
SCANNER_STATUS_BUSY, // doing task exclude scanning
|
|
SCANNER_STATUS_COVER_OPENNED,
|
|
SCANNER_STATUS_COVER_CLOSED,
|
|
SCANNER_STATUS_SLEEPING,
|
|
SCANNER_STATUS_WAKED_UP,
|
|
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_PAPER_ON,
|
|
SCANNER_STATUS_STAPLE_ON,
|
|
SCANNER_STATUS_SIZE_ERR,
|
|
SCANNER_STATUS_DOGEAR,
|
|
SCANNER_STATUS_CFG_CHANGED, // PACK_BASE::payload - LPCFGVAL
|
|
};
|
|
|
|
// option affection if value changed, see SANE_INFO_xxx
|
|
enum opt_affect
|
|
{
|
|
OPT_AFFECT_NONE = 0,
|
|
OPT_AFFECT_INEXACT = 1,
|
|
OPT_AFFECT_OTHERS = 2,
|
|
OPT_AFFECT_IMG_PARAM = 4,
|
|
};
|
|
|
|
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, // normal
|
|
IMG_STATUS_DOUBLE = 1 << 0, // double-feeded paper
|
|
IMG_STATUS_JAM = 1 << 1, // jammed paper
|
|
IMG_STATUS_STAPLE = 1 << 2, // staples on the paper
|
|
IMG_STATUS_SIZE_ERR = 1 << 3, // size check failed
|
|
IMG_STATUS_DOGEAR = 1 << 4, // paper has dogear - common
|
|
IMG_STATUS_DOGEAR_PARTIAL = 1 << 5, // dogear - scanned partial
|
|
IMG_STATUS_BLANK = 1 << 6, // blank image
|
|
};
|
|
enum data_type
|
|
{
|
|
DATA_TYPE_BOOL = 0, // (bool*)
|
|
DATA_TYPE_INT4, // (uint32_t*)
|
|
DATA_TYPE_FLOAT, // (double*)
|
|
DATA_TYPE_STRING, // (char*) with max_len space. befor and include me, keep same with SANE_TYPE_BOOL, SANE_TYPE_xxx ...
|
|
|
|
DATA_TYPE_INT1, // (uint8_t*)
|
|
DATA_TYPE_INT2, // (uint16_t*)
|
|
DATA_TYPE_INT8, // (uint64_t*)
|
|
DATA_TYPE_CUSTOM,
|
|
};
|
|
|
|
enum paper_side
|
|
{
|
|
PAPER_SIDE_FRONT = 0, // single side, this is front
|
|
PAPER_SIDE_BACK, // single side, this is back
|
|
PAPER_SIDE_TOP, // VERT-compound sides, and front side is at top
|
|
PAPER_SIDE_BOTTOM, // VERT-compound sides, and front side is at bottom
|
|
PAPER_SIDE_LEFT, // HORZ-compound sides, and front side is at left
|
|
PAPER_SIDE_RIGHT, // HORZ-compound sides, and front side is at right
|
|
|
|
PAPER_SIDE_DSP, // a special type
|
|
};
|
|
enum rot_angle
|
|
{
|
|
ROT_ANGLE_0 = 0,
|
|
ROT_ANGLE_90,
|
|
ROT_ANGLE_180,
|
|
ROT_ANGLE_270,
|
|
};
|
|
enum clr_channel
|
|
{
|
|
COLOR_CHANNEL_RGB = 0,
|
|
COLOR_CHANNEL_RGBA,
|
|
COLOR_CHANNEL_GRAY,
|
|
COLOR_CHANNEL_RED,
|
|
COLOR_CHANNEL_GREEN,
|
|
COLOR_CHANNEL_BLUE,
|
|
COLOR_CHANNEL_ALPHA,
|
|
};
|
|
enum color_mode
|
|
{
|
|
COLOR_MODE_BW = 0,
|
|
COLOR_MODE_GRAY,
|
|
COLOR_MODE_RGB,
|
|
};
|
|
|
|
#pragma pack(push)
|
|
#pragma pack(1)
|
|
typedef struct _ep0_reply
|
|
{
|
|
uint8_t in_status; // BULK-IN status, enum bulk_statu
|
|
uint8_t out_status; // BULK-OUT status, enum bulk_statu
|
|
uint16_t in_err; // valid if in_statu == BULK_STATU_ERROR
|
|
uint16_t out_err; // valid if out_statu == BULK_STATU_ERROR
|
|
uint16_t task_cnt; // tasks in command queue
|
|
uint32_t task_cmd; // the cmd of the task thread is doing
|
|
uint32_t task_pack_id; // packet id of the cmd
|
|
uint32_t task_required_bytes; // required byte of this packet
|
|
uint32_t packets_to_sent; // how many packets in sent queue
|
|
uint32_t bytes_to_sent; // how many bytes data is waiting for be sent in one replying packet
|
|
}EP0REPLYSTATUS, *LPEP0REPLYSTATUS;
|
|
|
|
typedef struct _peer_config
|
|
{
|
|
uint64_t pid; // [in] - host pc process id; [out] - usb service process id
|
|
uint32_t io_size; // IO buffer size
|
|
uint16_t ver; // protocol version
|
|
}PEERCFG, *LPPEERCFG;
|
|
|
|
typedef struct _pack_base // A piece of data has only one header
|
|
{
|
|
uint32_t enc_cmd : 2; // encrypting type, for 'cmd'
|
|
uint32_t encrypt : 3; // encrypting type, for payload content. the payload must cotains self-check if was encrypted packet
|
|
uint32_t enc_data : 5; // data for encrypt
|
|
uint32_t size : 6; // bytes of this structure
|
|
uint32_t cmd : 16; // packet command
|
|
uint32_t data; // simple data in command packet depends 'cmd', or error code in reply packet
|
|
uint32_t pack_id; // maintain by the initiator, the reply packet use the same id
|
|
uint32_t payload_len; // total bytes of payload of this command packet (the data in the range will sent in ONE 'write'),
|
|
// big data can be described in payload and independent communication, and this field should not include them.
|
|
// if encrypted packet, this field is the length after encrypting
|
|
char payload[0]; // payloads, according to 'cmd'
|
|
|
|
STRUCT_CONSTRUCTOR(_pack_base)
|
|
}PACK_BASE, * LPPACK_BASE;
|
|
#define BASE_PACKET_REPLY(reply, command, id, err) \
|
|
(reply).encrypt = 0; \
|
|
(reply).enc_data = 0; \
|
|
(reply).size = sizeof(reply); \
|
|
(reply).data = err; \
|
|
(reply).cmd = command; \
|
|
(reply).pack_id = id; \
|
|
(reply).payload_len = 0;
|
|
|
|
|
|
typedef struct _config_val
|
|
{
|
|
uint8_t type; // same as SANE_Value_Type
|
|
uint8_t name_off; // name offset of the option in data, end with '\0'
|
|
uint8_t val_off; // option value offset in data
|
|
uint8_t after_do; // see SANE_INFO_xxx in sane.h
|
|
uint16_t val_size; // real size of value
|
|
uint16_t max_size; // max size of this option, this value has given in gb_json::size
|
|
char data[0]; // contains value and name. fetch them according name_off and val_off members.
|
|
}CFGVAL, *LPCFGVAL;
|
|
|
|
typedef struct _img_pos
|
|
{
|
|
uint64_t paper_ind : 32; // paper index in this turn/start, based ZERO. (image-collector set)
|
|
uint64_t new_img : 1; // 0 - partial data; 1 - new image data. (image-collector set)
|
|
uint64_t img_over : 1; // 0 - has data yet; 1 - END for the image. (image-collector set)
|
|
uint64_t paper_side : 3; // enum paper_side. front of paper(When scanning multiple sheets, the paper feeding side is the front side). (image-collector set)
|
|
uint64_t back_rot : 2; // back rotation angle, enum rot_angle. (image-collector set)
|
|
uint64_t channel_ind : 4; // index of color channel, enum clr_channel. (image-collector set)
|
|
uint64_t status : 7; // img_status. (image-collector set)
|
|
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 reserved : 3; // reserved
|
|
|
|
STRUCT_CONSTRUCTOR(_img_pos)
|
|
}IMGPOS, * LPIMGPOS;
|
|
typedef struct _pack_img
|
|
{
|
|
IMGPOS pos; // image pos info ...
|
|
uint32_t width; // image width in pixel. (image-collector set)
|
|
uint32_t height; // image height in pixel. (image-collector set)
|
|
uint32_t resolution_x; // image horizontal reolution. (image-collector set)
|
|
uint32_t resolution_y; // image vertical reolution. (image-collector set)
|
|
uint32_t channels : 6; // image channels per pixel. (image-collector set)
|
|
uint32_t format : 6; // image format, see 'img_format'. (image-collector set)
|
|
uint32_t bpp : 6; // bits per pixel. (image-collector set)
|
|
uint32_t bppc : 6; // bits per pixel in this channel, equal to 'bpp' if pos.channel_ind == 0x0f. (image-collector set)
|
|
uint32_t compression : 6; // image data compression, see 'img_compression'. (image-collector set)
|
|
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 .... (image-collector set)
|
|
uint64_t data_size; // image data size in 'data' with bytes. (image-collector set)
|
|
// char data[0]; // two parts: image info (info_size) + image data (data_size)
|
|
|
|
STRUCT_CONSTRUCTOR(_pack_img)
|
|
}PACKIMAGE, * LPPACKIMAGE;
|
|
|
|
typedef struct _oper_token
|
|
{
|
|
uint32_t type; // token type
|
|
char data[128]; // token data
|
|
}OPERTOKEN, * LPOPERTOKEN;
|
|
|
|
typedef struct _tx_file
|
|
{
|
|
uint64_t size; // total size
|
|
uint64_t offset; // offset in the file
|
|
char path[2]; // file full path-name
|
|
}TXFILE, *LPTXFILE;
|
|
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'
|
|
|
|
STRUCT_CONSTRUCTOR(_file_info)
|
|
}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];
|
|
|
|
STRUCT_CONSTRUCTOR(_proc_info)
|
|
}PROCINFO, * LPPROCINFO;
|
|
#pragma pack(pop)
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// configurations ...
|
|
//
|
|
// 1 - App has whole set, group definitions
|
|
//
|
|
// 2 - device provides sub-set, or a customizing item
|
|
//
|