#ifndef WRRPER_SANE_SCANNER_H_EX #define WRRPER_SANE_SCANNER_H_EX ///////////////////////////////////////////////////////////////////////////////////////////// // linux SANE协议下 驱动代码结构 // // hg_scanner_sdk // │ //  ├ sdk 开发库 // │ │ // │ ├ include 自定义开发的接口文件路径,用于存放模块间接口文件 // │ │ // │ ├ lib 自定义开发的库文件路径,用于存放自己开发的模块库文件 // │ │ // │ └ sane sane协议标准头文件 // │ //  ├ driver 华高驱动源码 // │ //  ├ sane_hg 应用层 SANE 协议中间件封装源码 // │ //  ├ app 应用层用户交互程序 // │ //  └ Tirdparty 三方文件 // 本文件定义华高驱动层接口,位置:hg_scanner_sdk/sdk/include // //////////////////////////////////////////////////////////////////////////////////////////// #include "huagao/hgscanner_error.h" #include "sane/sane_ex.h" #include #if defined(WIN32) || defined(_WIN64) #include "../../../sdk/include/huagao/brand.h" #ifndef HGSCANNER_EXPORT #pragma comment(lib, "scanner.lib") #endif #define VERSION_MAJOR VERSION_MAIN #define VERSION_MINOR VERSION_SUB #define VERSION_YEAR VERSION_BUILD1 #define VERSION_BUILD VERSION_PATCH #define GET_BUILD_VER VERSION_BUILD #else #define GET_BUILD_VER VERSION_BUILD - 100000 #endif /********************************************************************************************* *时间:2019年9月26日 * *说明: * * 此模块为将C++设备通信层以及图像处理层代码进行封装,封装为C 接口的代码,以整合 * *SANE*到SANE接口中; * *一下做以调用流程说明: * * GetInstance() 创建此模块对象 * * ↓↓ * * Open() 打开USB端口 * * ↓↓ * * Start() 开始扫描 * * ↓↓ * * Get_Image_Info() 获取图像队列最前端图像信息,申请内存pdata * * ↑ → → → ↓ * * ↑Get_ProcedImgQueueEmpty() ↓ 当已处理图像队列不为空的时候循环此流程 * * ↑ ↓ 取图 * * ↑ ← ← ← ↓ * * AquireImage(pdata) 传图图像指针,获取图像数据 * * ↓↓ * * ReleaseInstance() 删除释放相关资源,此处不用调用Close()接口,内部已做处理 * * * * * * ---------Modified on 2022-01-12--------- * * * * BASIC: * * * * 1: hgxxx driver manages all huagao scanner products, for this, we support * * 'hg_scanners_enum' API; * * * * 2: driver should provides exclusive or share access, we add a parameter in 'hg_open' API;* * * * 3: support async-reading, add a async structure data into 'hg_read' API * * * * 4: provide a 'hg_scanner_version' for version controlling * * * * * * ADD on 2022-01-13 * * * * 5: 本接口文件中所有涉及"char"类型的字符,若无特殊说明,均为utf-8编码格式 !!! * * * **********************************************************************************************/ /// /// 错误代码 #define MAX_NAME_LEN 256 #ifdef OEM_HANWANG #define hg_scanner_initialize hw_scanner_initialize #define hg_scanner_uninitialize hw_scanner_uninitialize #define hg_scanner_get_version hw_scanner_get_version #define hg_scanner_enum hw_scanner_enum #define hg_scanner_open hw_scanner_open #define hg_scanner_close hw_scanner_close #define hg_scanner_get_parameter hw_scanner_get_parameter #define hg_scanner_set_parameter hw_scanner_set_parameter #define hg_scanner_start hw_scanner_start #define hg_scanner_stop hw_scanner_stop #define hg_scanner_get_img_info hw_scanner_get_img_info #define hg_scanner_read_img_data hw_scanner_read_img_data #define hg_scanner_get_status hw_scanner_get_status #define hg_scanner_reset hw_scanner_reset #define hg_scanner_control hw_scanner_control #define hg_scanner_set_sane_info hw_scanner_set_sane_info #define hg_scanner_err_name hw_scanner_err_name #define hg_scanner_err_description hw_scanner_err_description #define hg_scanner_log hw_scanner_log #define hg_scanner_log_is_enable hw_scanner_log_is_enable #elif defined(OEM_LISICHENG) #define hg_scanner_initialize lsc_scanner_initialize #define hg_scanner_uninitialize lsc_scanner_uninitialize #define hg_scanner_get_version lsc_scanner_get_version #define hg_scanner_enum lsc_scanner_enum #define hg_scanner_open lsc_scanner_open #define hg_scanner_close lsc_scanner_close #define hg_scanner_get_parameter lsc_scanner_get_parameter #define hg_scanner_set_parameter lsc_scanner_set_parameter #define hg_scanner_start lsc_scanner_start #define hg_scanner_stop lsc_scanner_stop #define hg_scanner_get_img_info lsc_scanner_get_img_info #define hg_scanner_read_img_data lsc_scanner_read_img_data #define hg_scanner_get_status lsc_scanner_get_status #define hg_scanner_reset lsc_scanner_reset #define hg_scanner_control lsc_scanner_control #define hg_scanner_set_sane_info lsc_scanner_set_sane_info #define hg_scanner_err_name lsc_scanner_err_name #define hg_scanner_err_description lsc_scanner_err_description #define hg_scanner_log lsc_scanner_log #define hg_scanner_log_is_enable lsc_scanner_log_is_enable #elif defined(OEM_CANGTIAN) #define hg_scanner_initialize cts_scanner_initialize #define hg_scanner_uninitialize cts_scanner_uninitialize #define hg_scanner_get_version cts_scanner_get_version #define hg_scanner_enum cts_scanner_enum #define hg_scanner_open cts_scanner_open #define hg_scanner_close cts_scanner_close #define hg_scanner_get_parameter cts_scanner_get_parameter #define hg_scanner_set_parameter cts_scanner_set_parameter #define hg_scanner_start cts_scanner_start #define hg_scanner_stop cts_scanner_stop #define hg_scanner_get_img_info cts_scanner_get_img_info #define hg_scanner_read_img_data cts_scanner_read_img_data #define hg_scanner_get_status cts_scanner_get_status #define hg_scanner_reset cts_scanner_reset #define hg_scanner_control cts_scanner_control #define hg_scanner_set_sane_info cts_scanner_set_sane_info #define hg_scanner_err_name cts_scanner_err_name #define hg_scanner_err_description cts_scanner_err_description #define hg_scanner_log cts_scanner_log #define hg_scanner_log_is_enable cts_scanner_log_is_enable #endif #define _TO_STR(str) #str #define MAKE_STR(str) _TO_STR(str) #define GET_BACKEND_NAME MAKE_STR(BACKEND_NAME) typedef struct _device { unsigned short vid; unsigned short pid; char name[MAX_NAME_LEN]; // 设备ANSI名称,驱动需要保证该名称唯一, // 即使在有几台同类设备同时连接上时,也能通过该名称访问指定的设备 // 参考命名:名称+资源,如“HG200 USB1” char vendor[MAX_NAME_LEN]; // 设备制造商 char model[MAX_NAME_LEN]; // model name char type[MAX_NAME_LEN]; // device type }ScannerInfo; // hg_scanner_control 控制码及参数 // enum hg_control_code { HG_CONTROL_CODE_OPTION_ENABLE = IO_CTRL_CODE_LAST + 1, // 配置项使能状态改变. data - OPTEN*, len - unused, be NULL }; typedef struct _opt_val { std::string name; // 配置项名称 void* data; // 配置项数据 }OPTVAL; typedef struct _opt_enabled // 配置项使能状态改变 { std::string name; // 配置项名称 int enabled; // 0 - 禁止;1 - 可用 int master_count; // 该配置项的依赖项数目 OPTVAL master[1]; // 该配置项的依赖项当前值 }OPTEN; // // 可变参数数据,使用JSON格式配置,utf-8编码 // // "option_count" : 41, - 配置项总数,要计上“0”号功能 // "device_type" : "G100", - 型号 //{ // "category":"基本设置", - 建议该配置项所在配置页的标题,UI根据该项可以确定界面分页 // "enable":true, - 是否允许用户设置 // "name" : "颜色", - 该配置项名称 // "title" : "设置颜色", - 该配置项标题 // "desc" : "设置颜色位深", - 该配置项描述或者帮助信息 // "unit" : "bits", - 该配置项的计量单位,没有可设置为空 // "type" : "int", - 数据类型 bool, int, float, string // popup - 告诉UI此处需要一个按钮,弹出一个独立的对话框,此时必须要提供"child"子项,以指明独立对话框中显示哪些配置 // "cur" : 8, - 当前值。值类型应和数据类型匹配。后面的取值范围也一样 // "default":10 - 默认值 // "size":4 - 单个类型值所需要的最小存储空间。如果为字符串,则为最大的字符串长度 // "range" : [ - 限制取值范围,如果不限制则不包含该项。 数组用于列表选择 // 1, 2, 4, 8, 16, 24 // ] // or // "range" : { - 限制取值范围,对象用于范围限制 // "min":1, // "max":24 // } // // "depend_or":[ - 该设置项依赖于其它设置项,满足其中之一用户才可设置 // "2==24位彩色" - 格式:选项+运算符+值。 此处意思为:当选项2的值为“24位彩色”时有效 // ] 值全部为字符串化; // 单个值,可支持==, !=, >, >=, <, <=运算。==和!=支持字符串比较,其余默认为整数或浮点数比较 // 如果在某一区间,则用“[]”或者“[]”,只支持数字作区间运算 // or // // "depend_and":[ - 该设置项依赖于其它设置项,满足所有用户才可设置 // "2!=24位彩色", - 格式:选项+运算符+值。 此处意思为:当选项2的值 不 为“24位彩色”和"256级灰度"时有效 // "2!=256级灰度" // ] 值全部为字符串化; // 单个值,可支持==, !=, >, >=, <, <=运算。==和!=支持字符串比较,其余默认数值比较 // 如果在某一区间,则用“[]”,只支持数字作区间运算. 2=[100, 300] or 2!=[100, 300] // // "child": [ - type为popup时,弹出的界面所要展示的选项功能号 // 3, // 8 //] //} /// typedef void* scanner_handle; #ifdef __cplusplus extern "C"{ #endif // Function: 初始化驱动,在最开始调用,且只调用一次 // // Parameter: callback - 界面异步回调函数 // // reserve - 保留 // // Return: 状态码 scanner_err hg_scanner_initialize(sane_callback callback, void* reserve); // Function: 退出进程前启动驱动清理工作 // // Parameter: 无参 // // Return: 无返回 void hg_scanner_uninitialize(void); // Function: 获取该驱动的版本号,用于版本控制 // // Parameter: 无 // // Return: 驱动版本号 hh.hl.lh.ll // // 31 23 15 7 0 // ┌───┬───┬───┬───┐ // │ hh │ hl │ lh │ ll │ // └───┴───┴───┴───┘ unsigned long long hg_scanner_get_version(void); // Function: 枚举所有本驱动支持的已经连接的设备 // // Parameter: scanner_list - 用户分配的空间 // // count - [in]:'scanner_list' 的以ScannerInfo为单位的空间大小; [out]:scanner_list 中返回的设备个数 // 当'scanner_list'为NULL或者空间小于所需最小长度时,返回所需要的HGScannerInfo元素数 // 该参数必须非空,如果为NULL,则会返回 EPARAMETERINVAL 的错误 // // local_only - 是否只获取本地设备 // // Return: 错误代码, E_OK or E_INSUFFICIENTMEM or E_PARAMETERINVAL // // NOTE: 'name'空间由用户分配,如果空间太小(包含传入NULL),会在len中返回所需要的最小空间字节数,并返回 EINSUFFICIENTMEM scanner_err hg_scanner_enum(ScannerInfo* scanner_list, long* count, bool local_only); // Function: 打开指定的设备 // // Parameter: h - 返回打开的设备句柄 // // name - 设备名称,从 'hg_enum_scanner' 方法返回的设备名称。没有与该名称匹配的设备时,返回 E_DEVICENOTFOUND 的错误 // // shared - 是否以共享方式打开。如果为true而设备不支持共享,则返回 E_NOTSUPPORT 错误代码 // 共享方式可考虑作为一种“嗅探器”访问,只能被动接收数据,不可主动设置参数 // // user - 设备打开过程中,可能需要用到身份验证,该参数用于传入用于身份验证的用户名 // // pwd - 设备打开过程中,可能需要用到身份验证,该参数用于传入用于身份验证的密码 // // check - 验证方式名称,如CRC32…… // // rsc - 用于接收设备打开过程中,可能需要用到身份验证的设备名称,最小80字节 或者 NULL // 通常用于在需要第三方资源身份验证的时候返回,如果不需要或者已经成功打开,则可忽略该返回内容 // // Return: 错误代码,E_OK or E_ACCESSDENIED or E_DEVICENOTFOUND or E_NOTSUPPORT scanner_err hg_scanner_open(scanner_handle* h, const char* name, bool shared, const char* user, const char* pwd, const char* check, char* rsc/*rsc[80]*/); // Function: 关闭打开的设备 // // Parameter: h - hg_open_scanner 返回的设备句柄 // // force - 是否强制关闭(如果设备缓冲区还有数据没被读取,force为false时不会关闭设备,并返回 E_HASDATAYET 错误; // 为true时,则立即关闭设备并返回成功) // // Return: 错误代码,E_OK or E_HASDATAYET scanner_err hg_scanner_close(scanner_handle h, bool force); // Function: 获取设备的配置参数说明及当前的设置值 // // Parameter: h - hg_open_scanner打开的设备句柄 // // name - 参数名称,如果为“null”,在len中返回参数总数量 // // json_data - JSON格式的参数数据(参考可变参数数据), // // len - [in]: 'data' 大小; [out]:data中返回的数据大小 // 当'data'为NULL或者空间小于所需最小长度时,返回所需要的内存长度 // 如果“param_no==0”,则返回最大可配置的参数号 // 该参数必须非空,如果为NULL,则会返回 EPARAMETERINVAL 的错误 // // Return: 错误代码,E_OK or E_INSUFFICIENTMEM or E_PARAMETERINVAL or E_DEVICENOTFOUND or E_OUTOFRANGE // // NOTE: 'data'空间由用户分配,如果空间太小(包含传入NULL),会在len中返回所需要的最小空间字节数,并返回 EINSUFFICIENTMEM scanner_err hg_scanner_get_parameter(scanner_handle h, const char* name, char* json_data, long* len); // Function: 设置设备的配置参数 // // Parameter: h - hg_open_scanner打开的设备句柄 // // name - 参数名称,如果为“null”,忽略后面两个参数,将全部设置项恢复为默认设置 // // data - 参数数据,如果为“NULL”,执行恢复到默认值动作。所有类型的参数按照该功能号的实际类型指针处理 // bool: (bool*)data // int: (int*)data // float: (float*)data // string: (char*)data // // len - 'data' 大小 // // Return: 错误代码,E_OK or E_NOTEXACT or E_ACCESSDENIED or E_NEEDRELOADPARAM // // NOTE: 如果传入的参数不精确,则由驱动选择合适的参数设置并写入到data中,返回 E_NOTEXACT 的错误码。用户需要根据该参数更新UI // 以共享方式打开的设备,没有设置权限,会返回 E_ACCESSDENIED 错误。 scanner_err hg_scanner_set_parameter(scanner_handle h, const char* name, void* data, long len); // Function: 启动设备工作 // // Parameter: h - hg_open_scanner打开的设备句柄 // // async_event - 异步IO通知事件,为空则同步读取。如果不支持异步,则返回 E_NOTSUPPORT 错误 // // Return: 错误代码,E_OK or E_NOTSUPPORT or E_DEVICENOTFOUND(句柄非法), E_COVER_OPEN, E_PAPER_JAMMED, E_DEVICEBUSY // // NOTE: 支持异步IO时,事件需要有[新图片开始(带新图片头信息),新图片数据,出现错误……] 几种基本类型 scanner_err hg_scanner_start(scanner_handle h, void* async_event,int num); // Function: 扫描过程中停止设备工作 // // Parameter: h - hg_open_scanner打开的设备句柄 // // num - 设置扫描页数,-1全部扫描 // // Return: 错误代码,E_OK or E_DEVICENOTFOUND(句柄非法) scanner_err hg_scanner_stop(scanner_handle h); // Function: 读取图片信息 // // Parameter: h - hg_open_scanner打开的设备句柄 // // bmi - 用户分配用于接收图片参数 // // len - 'bmi' 大小 // // Return: 错误代码,E_OK or E_NOTSTART scanner_err hg_scanner_get_img_info(scanner_handle h, SANE_Parameters* bmi, long len); // Function: 读取图片数据 // // Parameter: h - hg_open_scanner打开的设备句柄 // // data - 用户分配用于接收图片数据 // // len - [in]:'data' 大小;[out]:'data'中返回的数据字节数 // // Return: 错误代码。如果为异步IO,没有数据时会立即返回,并返回代码 E_IOPENDING scanner_err hg_scanner_read_img_data(scanner_handle h, unsigned char* data, long* len); // Function: 获取设备状态 // // Parameter: h - hg_open_scanner打开的设备句柄 // // setstutas -设置需要获取状态的条件 // // Return: 状态码 scanner_err hg_scanner_get_status(scanner_handle h, int setstutas); // Function: 复位设备 // // Parameter: h - hg_open_scanner打开的设备句柄 // // Return: 错误码 // // NOTE: 从错误中恢复到正常状态 scanner_err hg_scanner_reset(scanner_handle h); // Function: 直接访问控制 // // Parameter: h - hg_open_scanner打开的设备句柄 // // code - 控制码 // // data - 用户分配的内存,对应于控制码的原始数据 // // len - data中数据长度。如果是获取操作时,长度小于所需要的长度,则返回需要的长度且返回 E_INSUFFICIENTMEM 的错误 // // Return: 错误码 scanner_err hg_scanner_control(scanner_handle h, unsigned long code, void* data, unsigned *len); // Function: 设置SANE组件信息 // // Parameter: name - sane组件名字 // // ver - sane组件版本 // // Return: none void hg_scanner_set_sane_info(const char* name, const char* ver); const char* hg_scanner_err_name(int err); const char* hg_scanner_err_description(int err); enum log_level { LOG_LEVEL_ALL = 0, LOG_LEVEL_DEBUG_INFO, LOG_LEVEL_WARNING, LOG_LEVEL_FATAL, }; bool hg_scanner_log_is_enable(int level); void hg_scanner_log(const char* info); // Function: 获取模块全路径名称 // // Parameters: name - 模块名称(模块名称的一部分即可,不支持通配符) // // buf - 返回的全路径空间,必须保证足够大小 // // Return: 返回buf char* get_file_path(const char* name, char* buf); // Function: 获取磁盘空间 // // Parameters: path - 全路径 // // total - 总空间大小(字节) // // avail - 可用空间大小(字节) // // block - 磁盘单元(块/簇)大小(字节) // // Return: 0 - 成功;其它为失败代码 int get_disk_space(const char* path, unsigned long long* total, unsigned long long* avail, unsigned long long* block); // Function: 图像状态名称 const char* hg_scanner_image_statu_name(int img_statu); // Function: 获取当前时间字符串 // // Parameters: tmbuf - 用于接收时间字符串,不小于40个字符长度 // // t - 用于接收原始的时间结构 // // Return: void void get_current_time(char* tmbuf, struct tm* t = nullptr); void get_current_time_w(wchar_t* tmbuf, struct tm* t = nullptr); #ifdef __cplusplus } #endif ///////////////////////////////////////////////////////////////////////////////////// // log ... #define VLOG_MINI_BYTES 512 #define LOG_INFO(level, info) \ if(hg_scanner_log_is_enable(level)) \ hg_scanner_log(info); #define VLOG_1(level, bytes, fmt, arg1) \ if(hg_scanner_log_is_enable(level)) \ { \ char* msgbuf = (char*)malloc(bytes); \ sprintf(msgbuf, fmt, arg1); \ hg_scanner_log(msgbuf); \ free(msgbuf); \ } #define VLOG_MINI_1(level, fmt, arg1) VLOG_1(level, VLOG_MINI_BYTES, fmt, arg1) #define VLOG_2(level, bytes, fmt, arg1, arg2) \ if(hg_scanner_log_is_enable(level)) \ { \ char* msgbuf = (char*)malloc(bytes); \ sprintf(msgbuf, fmt, arg1, arg2); \ hg_scanner_log(msgbuf); \ free(msgbuf); \ } #define VLOG_MINI_2(level, fmt, arg1, arg2) VLOG_2(level, VLOG_MINI_BYTES, fmt, arg1, arg2) #define VLOG_3(level, bytes, fmt, arg1, arg2, arg3) \ if(hg_scanner_log_is_enable(level)) \ { \ char* msgbuf = (char*)malloc(bytes); \ sprintf(msgbuf, fmt, arg1, arg2, arg3); \ hg_scanner_log(msgbuf); \ free(msgbuf); \ } #define VLOG_MINI_3(level, fmt, arg1, arg2, arg3) VLOG_3(level, VLOG_MINI_BYTES, fmt, arg1, arg2, arg3) #define VLOG_4(level, bytes, fmt, arg1, arg2, arg3, arg4) \ if(hg_scanner_log_is_enable(level)) \ { \ char* msgbuf = (char*)malloc(bytes); \ sprintf(msgbuf, fmt, arg1, arg2, arg3, arg4); \ hg_scanner_log(msgbuf); \ free(msgbuf); \ } #define VLOG_MINI_4(level, fmt, arg1, arg2, arg3, arg4) \ VLOG_4(level, VLOG_MINI_BYTES, fmt, arg1, arg2, arg3, arg4) #define VLOG_5(level, bytes, fmt, arg1, arg2, arg3, arg4, arg5) \ if(hg_scanner_log_is_enable(level)) \ { \ char* msgbuf = (char*)malloc(bytes); \ sprintf(msgbuf, fmt, arg1, arg2, arg3, arg4, arg5); \ hg_scanner_log(msgbuf); \ free(msgbuf); \ } #define VLOG_MINI_5(level, fmt, arg1, arg2, arg3, arg4, arg5) \ VLOG_5(level, VLOG_MINI_BYTES, fmt, arg1, arg2, arg3, arg4, arg5) #define VLOG_6(level, bytes, fmt, arg1, arg2, arg3, arg4, arg5, arg6) \ if(hg_scanner_log_is_enable(level)) \ { \ char* msgbuf = (char*)malloc(bytes); \ sprintf(msgbuf, fmt, arg1, arg2, arg3, arg4, arg5, arg6); \ hg_scanner_log(msgbuf); \ free(msgbuf); \ } #define VLOG_MINI_6(level, fmt, arg1, arg2, arg3, arg4, arg5, arg6) \ VLOG_6(level, VLOG_MINI_BYTES, fmt, arg1, arg2, arg3, arg4, arg5, arg6) #endif // WRRPER_SANE_SCANNER_H_EX