增加打印机相关接口

This commit is contained in:
wangjingwen 2022-10-12 15:14:58 +08:00
parent a4bf694cf2
commit ffbf9190b6
6 changed files with 440 additions and 4 deletions

9
debian/control vendored
View File

@ -19,7 +19,8 @@ Build-Depends: debhelper-compat (= 12),
libudev-dev,
libopencv-dev,
libarchive-dev,
libtesseract-dev
libtesseract-dev,
libcups2-dev,
Standards-Version: 4.4.1
Homepage: http://gitlab2.kylin.com/kysdk/kysdk-system
@ -172,7 +173,8 @@ Depends: ${shlibs:Depends},
libkysdk-log(>=1.2.0),
libkysdk-config(>=1.2.0),
systemd,
libkysdk-systemcommon
libkysdk-systemcommon,
cups
Multi-Arch: same
Description: 硬件信息获取库
@ -184,7 +186,8 @@ Depends: ${shlibs:Depends},
libkysdk-hardware,
libkysdk-log-dev(>=1.2.0),
libkysdk-config-dev(>=1.2.0),
libsystemd-dev
libsystemd-dev,
libcups2-dev
Multi-Arch: same
Description: 硬件信息获取库 - 开发库

View File

@ -1,3 +1,4 @@
usr/include/kysdk/kysdk-system/libkync.h
usr/include/kysdk/kysdk-system/libkycpu.h
usr/include/kysdk/kysdk-system/libkyprinter.h
development-files/kysdk-hardware.pc usr/share/pkgconfig/

View File

@ -4,9 +4,12 @@ add_library(kyhw SHARED ${SOURCESCODE})
set_target_properties(kyhw PROPERTIES VERSION 1.2.0 SOVERSION 1)
add_executable(kync-test test/kync-test.c)
add_executable(kycpu-test test/kycpu-test.c)
target_link_libraries(kyhw kylog kyconf pthread systemd)
add_executable(kyprinter-test test/kyprinter-test.c)
#
target_link_libraries(kyhw kylog kyconf pthread systemd cups)
target_link_libraries(kync-test kyhw)
target_link_libraries(kycpu-test kyhw)
target_link_libraries(kyprinter-test kyhw)
install(TARGETS kyhw
DESTINATION lib/kysdk/kysdk-system)
@ -15,4 +18,7 @@ install(FILES libkync.h
DESTINATION include/kysdk/kysdk-system)
install(FILES libkycpu.h
DESTINATION include/kysdk/kysdk-system)
install(FILES libkyprinter.h
DESTINATION include/kysdk/kysdk-system)

325
src/hardware/libkyprinter.c Normal file
View File

@ -0,0 +1,325 @@
#include "libkyprinter.h"
#include <errno.h>
#include <libkylog.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <syslog.h>
#include <cups/cups.h>
#include <cups/adminutil.h>
#include <cups/ipp.h>
#include <cups/ppd.h>
#define _IPP_PRIVATE_STRUCTURES 1
cups_option_t *cups_options; // cups设置
int num_options; // cups设置
char **kdk_printer_get_list()
{
printf("[%s] Start\n", __FUNCTION__);
cups_dest_t *dests = NULL;
int num_dests = 0;
int i = 0;
char **printers = NULL;
num_dests = cupsGetDests(&dests);
if (num_dests == 0 &&
(cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST ||
cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED))
{
#ifdef PRT_DEBUG
_cupsLangPrintf(stderr, "Printer: Error - add '/version=1.1' to server name.");
#endif
return NULL;
}
for (i = 0; i < num_dests; i++)
{
printf("[%s] printer name is %s \n", __FUNCTION__, dests[i].name);
char **tmp = realloc(printers, sizeof(char *) * i);
printers = tmp;
printers[i] = malloc(sizeof(char) * (strlen(dests[i].name) + 1));
strcpy(printers[i], dests[i].name);
}
char **tmp = realloc(printers, sizeof(char *) * (i + 1));
printers = tmp;
printers[i] = NULL;
cupsFreeDests(num_dests, dests);
return printers;
}
int kdk_printer_remove_options()
{
printf("[%s] Start\n", __FUNCTION__);
if (num_options != 0 && cups_options != NULL)
{
cupsFreeOptions(num_options, cups_options);
num_options = 0;
cups_options = NULL;
}
printf("[%s] num_options = %d\n", __FUNCTION__, num_options);
return 0;
}
//"two-sided-long-edge","two-sided-short-edge",one-sided
void kdk_printer_set_options(int number_up,
const char *media,
const char *number_up_layout, const char *sides)
{
printf("[%s] Start\n", __FUNCTION__);
kdk_printer_remove_options();
cups_options = NULL;
num_options = 0;
char NumberUp[2] = {0};
snprintf(NumberUp, 2, "%d", number_up);
/* cups options */
num_options = cupsAddOption("number-up", NumberUp, num_options, &cups_options);
num_options = cupsAddOption("media", media, num_options, &cups_options);
num_options = cupsAddOption("number-up-layout", number_up_layout, num_options, &cups_options);
num_options = cupsAddOption("sides", sides, num_options, &cups_options);
}
int kdk_printer_print_file(const char *printername, char *filepath)
{
printf("[%s] Start\n", __FUNCTION__);
printf("[%s] printer_name: %s, file_path: %s\n", __FUNCTION__,
printername,
filepath);
int jobid = cupsPrintFile(printername, filepath, "Print report", num_options, cups_options);
//注意:这里没有设置格式的话会直接用默认格式,一般默认格式是单页打印
// printf("[%s] num_options = %d,name = %s,value = %s",
// __FUNCTION__,num_options,cups_options->name,cups_options->value);
return jobid;
}
int kdk_printer_cancel_all_jobs(const char *printername)
{
printf("[%s] Start\n", __FUNCTION__);
int ret = cupsCancelJob(printername, CUPS_JOBID_ALL); // 1=success 0=fail
if (ret == 0)
{
printf(LOG_ERR, "%s ,job_id = CUPS_JOBID_ALL, find err = %s ", __FUNCTION__, cupsLastErrorString());
return -1;
}
return 0;
}
static int /* O - 1 on match, 0 on no match */
match_list(const char *list, /* I - List of names */
const char *name) /* I - Name to find */
{
const char *nameptr; /* Pointer into name */
/*
* An empty list always matches...
*/
if (!list || !*list)
return (1);
if (!name)
return (0);
while (*list)
{
/*
* Skip leading whitespace and commas...
*/
while (isspace(*list & 255) || *list == ',')
list++;
if (!*list)
break;
/*
* Compare names...
*/
for (nameptr = name;
*nameptr && *list && tolower(*nameptr & 255) == tolower(*list & 255);
nameptr++, list++)
;
if (!*nameptr && (!*list || *list == ',' || isspace(*list & 255)))
return (1);
while (*list && !isspace(*list & 255) && *list != ',')
list++;
}
return (0);
}
static int /* O - 0 on success, 1 on fail */
_show_printer_state(const char *printers /* I - Destinations */
// char* buf, /* I - Number of user-defined dests */
) /* I - User-defined destinations */
{
int i; /* Looping var */
ipp_t *request, /* IPP Request */
*response; /* IPP Response */
ipp_attribute_t *attr; /* Current attribute */
time_t ptime; /* Printer state time */
const char *printer, /* Printer name */
*device; /* Printer device URI */
ipp_pstate_t pstate;
int state_code = 0;
static const char *pattrs[] = /* Attributes we need for printers... */
{
"printer-name",
"printer-state"};
#ifdef PRT_DEBUG
printf(("show_devices(printers=\"%s\")\n", printers));
#endif
if (printers != NULL && !strcmp(printers, "all"))
printers = NULL;
/*
* Build a CUPS_GET_PRINTERS request, which requires the following
* attributes:
*
* attributes-charset
* attributes-natural-language
* requested-attributes
* requesting-user-name
*/
request = ippNewRequest(CUPS_GET_PRINTERS);
ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
"requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]),
NULL, pattrs);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
NULL, cupsUser());
/*
* Do the request and get back a response...
*/
response = cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/");
if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST ||
cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED)
{
#ifdef PRT_DEBUG
_cupsLangPrintf(stderr,
"%s: Error - add '/version=1.1' to server name.",
"lpstat");
#endif
ippDelete(response);
return (1);
}
else if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
{
#ifdef PRT_DEBUG
_cupsLangPrintf(stderr, "lpstat: %s", cupsLastErrorString());
#endif
ippDelete(response);
return (1);
}
if (response)
{
/*
* Loop through the printers returned in the list and display
* their devices...
*/
attr = ippFirstAttribute(response);
for (; attr != NULL; attr = ippNextAttribute(response))
{
/*
* Skip leading attributes until we hit a job...
*/
while (attr != NULL && ippGetGroupTag(attr) != IPP_TAG_PRINTER)
attr = ippNextAttribute(response);
if (attr == NULL)
break;
/*
* Pull the needed attributes from this job...
*/
printer = NULL;
pstate = IPP_PRINTER_IDLE;
while (attr != NULL && ippGetGroupTag(attr) == IPP_TAG_PRINTER)
{
const char *attr_name = ippGetName(attr);
ipp_tag_t value_tag = ippGetValueTag(attr);
if (!strcmp(attr_name, "printer-name") &&
value_tag == IPP_TAG_NAME)
printer = ippGetString(attr, 0, NULL);
else if (!strcmp(attr_name, "printer-state") &&
value_tag == IPP_TAG_ENUM)
{
pstate = (ipp_pstate_t)ippGetInteger(attr, 0);
// printf("statecode: %d\n",ippGetInteger(attr,0));
}
attr = ippNextAttribute(response);
}
/*
* See if we have everything needed...
*/
if (printer == NULL)
{
if (attr == NULL)
break;
else
continue;
}
if (match_list(printers, printer))
{
switch (pstate)
{
case IPP_PRINTER_IDLE:
state_code = CUPS_PRINTER_STATE_IDLE;
// snprintf(buf,buf_len,PRINTER_STATE_IDLE);
break;
case IPP_PRINTER_PROCESSING:
state_code = CUPS_PRINTER_STATE_PROCESSING;
// snprintf(buf,buf_len,PRINTER_STATE_PROCESSING);
break;
case IPP_PRINTER_STOPPED:
state_code = CUPS_PRINTER_STATE_STOPPED;
// snprintf(buf,buf_len,PRINTER_STATE_STOPPED);
break;
case IPP_PRINTER_BUSY:
state_code = CUPS_PRINTER_STATE_PROCESSING;
// snprintf(buf,buf_len,PRINTER_STATE_PROCESSING);
break;
default:
state_code = CUPS_PRINTER_STATE_STOPPED;
// snprintf(buf,buf_len,PRINTER_STATE_STOPPED);
break;
}
}
if (attr == NULL)
break;
}
ippDelete(response);
}
return state_code;
}
int kdk_printer_get_status(const char *printername)
{
printf("[%s] Start\n", __FUNCTION__);
http_t *http; /* Connection to server */
int ret;
if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
cupsEncryption())) != NULL)
{
httpClose(http);
}
else
{
return -2;
}
return _show_printer_state(printername);
}

View File

@ -0,0 +1,72 @@
#ifndef KDK_SYSTEM_HW_NWCARD_H__
#define KDK_SYSTEM_HW_NWCARD_H__
#define CUPS_PRINTER_STATE_BUSY 6 //"Busy"
#define CUPS_PRINTER_STATE_STOPPED 4 //"Stop"
#define CUPS_PRINTER_STATE_IDLE 2 //"Idle"
#define CUPS_PRINTER_STATE_PROCESSING 3 //"Processing"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief
*
* @return char** NULL字符串表示结尾alloc生成kdk_printer_freeall回收NULL
*/
extern char** kdk_printer_get_list();
/**
* @brief ,
*
* @param printername kdk_printer_get_list返回的值
* @param number_up cups属性2 4
* @param media cups属性A4
* @param number_up_layout cups属性lrtb
* @param sides cups属性one-sidedtwo-sided-long-edge(),two-sided-short-edge()
*
* @return
*/
extern void kdk_printer_set_options(int number_up,const char *media,const char *number_up_layout,const char *sides);
/**
* @brief
*
* @param printername kdk_printer_get_list返回的值
* @param filepath
*
* @return id
*
* @notice pdf之外的格式打印的效果都不够好pdf格式的文件
*/
extern int kdk_printer_print_file(const char *printername, char *filepath);
/**
* @brief
*
* @param printername kdk_printer_get_list返回的值
*
*
* @return 0,-1
*/
extern int kdk_printer_cancel_all_jobs(const char *printername);
/**
* @brief
*
* @param printername kdk_printer_get_list返回的值
*
*
* @return
*/
extern int kdk_printer_get_status(const char *printername);
#ifdef __cplusplus
}
#endif
#endif
/**
* @}
*/

View File

@ -0,0 +1,29 @@
#include "../libkyprinter.h"
#include <stdio.h>
int main()
{
int index = 0;
//获取打印机列表
char **printers = kdk_printer_get_list();
while (printers[index])
{
printf("%zd: %s\n", index + 1, printers[index]);
if (kdk_printer_get_status(printers[index]) == CUPS_PRINTER_STATE_IDLE)
{
//取消当前打印机所有打印任务
kdk_printer_cancel_all_jobs(printers[index]);
//设置打印参数(这个参数所有打印机共用)
kdk_printer_set_options(2, "A4", "lrtb", "two-sided-long-edge");
//打印
int job_id = kdk_printer_print_file(printers[index], "/etc/apt/sources.list");
if (job_id == 0)
{
printf("[%s] create print job fail\n", __FUNCTION__);
}
printf("[%s] The jobs_id = %d\n", __FUNCTION__, job_id);
}
index++;
}
return 0;
}