1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Linux下hp打印机驱动hplip分析

Linux下hp打印机驱动hplip分析

时间:2018-08-17 05:40:44

相关推荐

Linux下hp打印机驱动hplip分析

Hplip分析

版本号是2.14,源代码位置:。

图的来源:/node/128。

实践中使用的打印机型号:Deskjet 1010.分析的目的就是搞清楚一个灰色地带---打印机通信.

1.D-Bus初始化流程

D-Bus的初始化相同是在ui4/devmgr5.py開始的。

ui4/devmgr5.py

01classDevMgr5(QMainWindow,Ui_MainWindow):

02......

03#TODO:Makesbusinitmandatorysuccess,elseexit

04definitDBus(self):

05self.dbus_loop=DBusQtMainLoop(set_as_default=True)

06self.dbus_avail,self.service,self.session_bus=device.init_dbus(self.dbus_loop)

07......

08#Receiveeventsfromthesessionbus

09self.session_bus.add_signal_receiver(self.handleSessionSignal,sender_keyword='sender',

10destination_keyword='dest',interface_keyword='interface',

11member_keyword='member',path_keyword='path')

12......

这里调用了base/device.py中的init_dbus()。从第9行能够看出handleSessionSignal是D-Busserver端回调函数。

base/device.py

01#

02#DBusSupport

03#

04

05definit_dbus(dbus_loop=None):

06......

07try:

08ifdbus_loopisNone:

09session_bus=dbus.SessionBus()

10else:

11session_bus=dbus.SessionBus(dbus_loop)

12......

13try:

14log.debug("Connectingtocom.hplip.StatusService(try#1)...")

15service=session_bus.get_object('com.hplip.StatusService',"/com/hplip/StatusService")

16dbus_avail=True

17exceptdbus.exceptions.DBusException,e:

18try:

19os.waitpid(-1,os.WNOHANG)

20exceptOSError:

21pass

22

23path=utils.which('hp-systray')

24......

25log.debug("Runninghp-systray:%s--force-startup"%path)

26

27os.spawnlp(os.P_NOWAIT,path,'hp-systray','--force-startup')

28

29log.debug("Waitingforhp-systraytostart...")

30time.sleep(1)

31

32t=2

33whileTrue:

34try:

35log.debug("Connectingtocom.hplip.StatusService(try#%d)..."%t)

36service=session_bus.get_object('com.hplip.StatusService',"/com/hplip/StatusService")

37......

38

39returndbus_avail,service,session_bus

40

41......

42

第27行启动了hp-systray作为d-bus的server端。D-busserver端启动完成。

2.D-busserverhp-systray端启动

启动命令例如以下:

$hp-systray--force-startup-g

说明:-g是调试模式启动

if __name__ == '__main__':......if child_pid1:# parent (UI)os.close(w1)......else: # qt4try:import ui4.systemtray as systrayexcept ImportError:log.error("Unable to load Qt4 support. Is it installed?

") mod.unlockInstance() sys.exit(1) try: systray.run(r1) finally: mod.unlockInstance() else: # child (dbus & device i/o [qt4] or dbus [qt3]) os.close(r1) if ui_toolkit == 'qt4': r2, w2 = os.pipe() r3, w3 = os.pipe() child_pid2 = os.fork() if child_pid2: # parent (dbus) os.close(r2) import hpssd hpssd.run(w1, w2, r3) else: # child (device i/o) os.close(w2) import hpdio hpdio.run(r2, w3) ......

启动了hpssd和hpdio。hpssd前者会从w3管道从读取hpdio写入的打印机状态信息。

以下单说hpdio怎样获取打印机状态当hpdiorun起来的时候会做以下调用run(hpdio.py)->queryDevice(device.py)->status.StatusType10(status.py)->StatusType10Status(status.py)来获取打印机状态。

在queryDevice这个函数中出现了6种与打印机通信方式,各自是:

Type 1/2 (s: or VSTATUS:) statusType 3/9 LaserJet PMLType 6: LJ XMLType 8: LJ PJLType 10: LEDMType 11: LEDM_FF_CC_0

而我眼下分析的这款打印机使用是第5种Type 10: LEDM通信协议HPMUD_S_EWS_LEDM_CHANNEL。每种通信通信都有关于打印机状态值的定义,另外从这款打印机的DeviceId能够看出应该同一时候也是支持PJL的,这里先仅仅说第5种LEDM通信方式.LEDM的大体通信方式是基于HTTP,通信USB传输一个HTTP的GET指令,然后再通过USB读取打印机返回的HTTP超文本,一个是XML.

StatusType10Status调用流程:

StatusType10FetchUrl 从打印机获取状态数据# Parse the product status XML 解析xml,提取状态值StatusType10FetchUrl调用流程:

getUrl_LEDMLocalOpenerEWS_LEDM().openhp()openhp调用流程:(进入LEDM处理流程)

writeEWS_LEDMreadEWS_LEDMreadLEDMData

3.刷新状态的流程

toolbox.py

01else:#qt4

02......

03fromui4.devmgr5importDevMgr5

04......

第三行能够看出启动了ui4文件夹下的devmgr5这个python。

ui4/devmgr5.py

01classDevMgr5(QMainWindow,Ui_MainWindow):

02......

03definitUI(self):

04......

05self.DeviceRefreshAction.setIcon(QIcon(load_pixmap("refresh1","16x16")))

06self.connect(self.DeviceRefreshAction,SIGNAL("triggered()"),self.DeviceRefreshAction_activated)

07......

08defDeviceRefreshAction_activated(self):

09self.DeviceRefreshAction.setEnabled(False)

10self.requestDeviceUpdate()

11self.DeviceRefreshAction.setEnabled(True)

12......

13defrequestDeviceUpdate(self,dev=None,item=None):

14"""Submitdeviceupdaterequesttoupdatethread."""

15

16ifdevisNone:

17dev=self.cur_device

18

19ifdevisnotNone:

20dev.error_state=ERROR_STATE_REFRESHING

21self.updateDevice(dev,update_tab=False)

22

23self.sendMessage(dev.device_uri,'',EVENT_DEVICE_UPDATE_REQUESTED)

24......

25defsendMessage(self,device_uri,printer_name,event_code,username=prop.username,

26job_id=0,title=''):

27

28device.Event(device_uri,printer_name,event_code,username,

29job_id,title).send_via_dbus(self.session_bus)

30.....

从第06行能够看出DeviceRefreshAction的槽是DeviceRefreshAction_activated在行8行,接着调用了requestDeviceUpdate。然后调用了sendMessage。然后调用了device.Event。这个在device.py中。在

base/device.py

01classEvent(object):

02......

03defsend_via_dbus(self,session_bus,interface='com.hplip.StatusService'):

04ifsession_busisnotNoneanddbus_avail:

05log.debug("Sendingevent%dto%s(viadbus)..."%(self.event_code,interface))

06msg=lowlevel.SignalMessage('/',interface,'Event')

07msg.append(signature=self.dbus_fmt,*self.as_tuple())

08session_bus.send_message(msg)

09......

10

这里调用的send_message是获取的d-bus实例的send_message,它在hpdio.py中。

hpdio.py

01defsend_message(device_uri,event_code,bytes_written=0):

02args=[device_uri,'',event_code,prop.username,0,'','',bytes_written]

03msg=lowlevel.SignalMessage('/','com.hplip.StatusService','Event')

04msg.append(signature='ssisissi',*args)

05SessionBus().send_message(msg)

这里是标准的d-bus通信。D-bus在收到这个消息后,会怎么处理,且看以后分析。以上是向server端请求事件。server端收到事件后会调用handleSessionSignal回调。

handleSessionSignal -> handleStatusReply -> updateDevice。

4.client与server端交互

clienthp-toolbox,server端hp-systray.他们分别启动后,怎样进行交互是一个重点,基于server端是有自己的消息通知和界面显示的,只是仅仅是一般的事件信息。

hp-toolbox能够主动获取打印机信息。

server端会主动向打印机设备获取状态信息,client获取的要是server保存好的状态信息。这个基本属于 生产者-消费者 之间的关系。

5.LEDM通信协议

全称:Low End Data Model(在hplib的status.py中有介绍:def StatusType10(func): # Low End Data Model)。

眼下已经是HP一个专利:专利EP2556480A1.

打开channel调用流程:

openEWS_LEDM -> __openChannel -> hpmudext.open_channel -> hpmud处理

读数据流程:

readEWS_LEDM -> __readChannel -> hpmudext.read_channel -> hpmud处理

写命令流程:

writeEWS_LEDM -> __writeChannel -> hpmudext.write_channel -> hpmud处理

以获取ProductStatusDyn记录一下收发数据的情况。

发送命令(报文):

GET /DevMgmt/ProductStatusDyn.xml HTTP/1.1#015#012Accept: text/plain#015#012Host:localhost#015#012User-Agent:hplip#015#012#015#012

接收数据:

<?xml version="1.0" encoding="UTF-8"?><!-- THIS DATA SUBJECT TO DISCLAIMER(S) INCLUDED WITH THE PRODUCT OF ORIGIN. --><psdyn:ProductStatusDyn xmlns:xsi="/2001/XMLSchema-instance" xmlns:xsd="/2001/XMLSchema" xmlns:dd="/schemas/imaging/con/dictionaries/1.0/" xmlns:ad="/schemas/imaging/con/ledm/alertdetails//10/31" xmlns:pscat="/schemas/imaging/con/ledm/productstatuscategories//10/31" xmlns:locid="/schemas/imaging/con/ledm/localizationids//10/31" xmlns:psdyn="/schemas/imaging/con/ledm/productstatusdyn//10/31" xsi:schemaLocation="/schemas/imaging/con/dictionaries/1.0/ ../schemas/dd/DataDictionaryMasterLEDM.xsd /schemas/imaging/con/ledm/alertdetails//10/31 ../schemas/AlertDetails.xsd /schemas/imaging/con/ledm/productstatuscategories//10/31 ../schemas/ProductStatusCategories.xsd /schemas/imaging/con/ledm/localizationids//10/31 ../schemas/LocalizationIds.xsd /schemas/imaging/con/ledm/productstatusdyn//10/31 ../schemas/ProductStatusDyn.xsd"><dd:Version><dd:Revision>SVN-IPG-LEDM.216</dd:Revision><dd:Date>-02-08</dd:Date></dd:Version><psdyn:Status><pscat:StatusCategory>closeDoorOrCover</pscat:StatusCategory><locid:StringId>65568</locid:StringId></psdyn:Status><psdyn:AlertTable><dd:ModificationNumber>6</dd:ModificationNumber><psdyn:Alert><ad:ProductStatusAlertID>closeDoorOrCover</ad:ProductStatusAlertID><locid:StringId>65568</locid:StringId><dd:SequenceNumber>5</dd:SequenceNumber><ad:Severity>Error</ad:Severity><ad:AlertPriority>1</ad:AlertPriority><ad:AlertDetails><ad:AlertDetailsDoorCoverLocation>cover</ad:AlertDetailsDoorCoverLocation></ad:AlertDetails><dd:ResourceURI>/DevMgmt/ProductConfigDyn.xml</dd:ResourceURI><dd:ResourceType>ledm:hpLedmProductConfigDyn</dd:ResourceType></psdyn:Alert><psdyn:Alert><ad:ProductStatusAlertID>cartridgeMissing</ad:ProductStatusAlertID><locid:StringId>65537</locid:StringId><dd:SequenceNumber>4</dd:SequenceNumber><ad:Severity>Error</ad:Severity><ad:AlertPriority>11</ad:AlertPriority><ad:AlertDetails><ad:AlertDetailsMarkerColor>Black</ad:AlertDetailsMarkerColor><ad:AlertDetailsConsumableTypeEnum>inkCartridge</ad:AlertDetailsConsumableTypeEnum><ad:AlertDetailsMarkerLocation>1</ad:AlertDetailsMarkerLocation></ad:AlertDetails><dd:ResourceURI>/DevMgmt/ConsumableConfigDyn.xml</dd:ResourceURI><dd:ResourceType>ledm:hpLedmConsumableConfigDyn</dd:ResourceType></psdyn:Alert><psdyn:Alert><ad:ProductStatusAlertID>cartridgeMissing</ad:ProductStatusAlertID><locid:StringId>65537</locid:StringId><dd:SequenceNumber>3</dd:SequenceNumber><ad:Severity>Error</ad:Severity><ad:AlertPriority>11</ad:AlertPriority><ad:AlertDetails><ad:AlertDetailsMarkerColor>CyanMagentaYellow</ad:AlertDetailsMarkerColor><ad:AlertDetailsConsumableTypeEnum>inkCartridge</ad:AlertDetailsConsumableTypeEnum><ad:AlertDetailsMarkerLocation>0</ad:AlertDetailsMarkerLocation></ad:AlertDetails><dd:ResourceURI>/DevMgmt/ConsumableConfigDyn.xml</dd:ResourceURI><dd:ResourceType>ledm:hpLedmConsumableConfigDyn</dd:ResourceType></psdyn:Alert></psdyn:AlertTable></psdyn:ProductStatusDyn>

pscat:StatusCategory字段记录的正是打印机的当前状态。

6.hpmud分析

MUlti-point transport Driver orHPMUDrepresents the I/O layer for HPLIP.HPMUDdoes not depend on Linux specific libusb extensions. This means any UNIX/Linux derivative that supports libusb may work with HPLIP. A public HPLIP "C" API is exposed through hpmud. See hpmud.h for documentation. A python wrapper for hpmud, calledhpmudext, is also available.

以上是官网介绍,如开头图中所看到的,hpmud是负责真正和打印机设备进行通信的,它基于libusb开发,所以能够执行于所以含libusb的系统中。

hpmud相同实现了多种通信方式:

musb 基于眼下经常使用的libusb通信.(本次採用打印机正是用这样的方式)musb_libusb01 基于眼下较老版本号的libusb通信.jd基于jetdirect 的打印机通信.pml 和python层相应。是一种打印语言pp Parallel port 并口通信方式这里仅仅说musb通信方式。因为基于libusb,所以这里的musb就类似于java和c中的jni仅仅是一个接口的转接,musb会把python传送过来的指令通过libusb直接丢给打印机设备。 另符上hpmud的调试方法,调试宏DBG的实现是syslog,把这个宏打开会将log信息输出到/var/log/syslog中。

7.C语言实现状态获取

经过20多天的,无情的看源代码,最终有所获。最终把Device.py中获取状态的部分用C语言实现了。提取了关键部分。如今能够正常获取打印机状态。因为之前没有接触过HTTP协议,一个错误的报文格式使得我连续非常多天都处于迷茫之中,如今看来在于心智还是不全然成熟。在感觉要成功的时候就静不下心来了,不在阅读最后一段代码,然后有时那段代码才是最重要的。"Door Open"从打印机到PC屏幕的流程最终走通了。

#include <stdio.h>#include <string.h>#include <hpmud.h>#include <malloc.h>#ifdef DEBUG#define debug(fmt,args...) debug (fmt ,##args)#define debugX(level,fmt,args...) if (DEBUG>=level) debug(fmt,##args);#else#define debug(fmt,args...)#define debugX(level,fmt,args...)#endif /* DEBUG */static HPMUD_DEVICE dd;static HPMUD_CHANNEL cd;#define MALLOC(type, n) (type*)malloc(n*sizeof(type))static int __readChannel(int bytes_to_read, int* reply, int allow_short_read, int timeout){bytes_to_read = 1024;char data[1024] = {0};int ret = 0;int num_bytes = 0;int len = 0;int *p = reply;while (1){ret = hpmud_read_channel(dd, cd, data, 1024, timeout, &num_bytes);debug("Result code=%d\n", ret);len = strlen(data);if(ret == HPMUD_R_IO_TIMEOUT){debug("I/O timeout\n");break;}if(ret != HPMUD_R_OK){debug("Channel read error\n");break;}//debug("read_buf:%s\n", data);if(!len){debug("End of data\n");break;}memcpy(p, data, len);if (num_bytes == bytes_to_read){debug("Full read complete.\n");break;}if (allow_short_read && (num_bytes < bytes_to_read)){debug("Allowed short read of %d of %d bytes complete.\n", num_bytes, bytes_to_read);break;}}debug("Saved %d total bytes to stream.\n", num_bytes);return num_bytes;}void readLEDMData(){int timeout = 6;const char* END_OF_DATA="0\r\n\r\n";int bytes_read = 0;int bytes_requested = 1024;char temp_buf[1024] = {0}; //大小要一致int chunkedFlag = 1;char* result = NULL;char *reply = (int*)MALLOC(unsigned char, 5*1024);char *offset = reply;if(reply == NULL){fprintf(stderr, "MALLC FAILURE!\n");return;}bytes_read = __readChannel(bytes_requested, reply, 1, timeout);offset += bytes_read;//debug("%s:%s\n", __func__, reply);// 默认chunked分块.chunkedFlag = 1;//result = strtok(reply, "\n");//debug("result=%s\n", result);while (bytes_read > 0){bytes_read = __readChannel(bytes_requested, (int*)temp_buf, 1, timeout);//reply.write(temp_buf.getvalue());memcpy(offset, temp_buf, bytes_read);debug("%s:%s\n", __func__, offset);offset += bytes_read;if(!chunkedFlag) // Unchunked data{// do nothing!}else // Chunked data end{//END_OF_DATA == temp_buf.getvalue();if(!strncmp(temp_buf, END_OF_DATA, sizeof(END_OF_DATA)))break;}}printf("%s:%s\n", __func__, reply);free(reply);reply = NULL;}int main(void){enum HPMUD_RESULT res;const char *device_uri = "hp:/usb/Deskjet_1010_series?serial=CN39I18M1805S8";enum HPMUD_IO_MODE io_mode = HPMUD_RAW_MODE;// 打开设备获得res = hpmud_open_device(device_uri, io_mode, &dd);if (res != HPMUD_R_OK){fprintf(stderr, "error opening device (code=%d)\n", res);return 1;}// 打开频道获得频道idres = hpmud_open_channel(dd, HPMUD_S_EWS_LEDM_CHANNEL, &cd);if (res != HPMUD_R_OK){fprintf(stderr, "error opening channel (code=%d)\n", res);return 1;}char buf[1024] = "GET /DevMgmt/ProductStatusDyn.xml HTTP/1.1\r\nAccept: text/plain\r\nHost:localhost\r\nUser-Agent:hplip\r\n\r\n";//char ConsumableConfigDyn[] = "GET /DevMgmt/ConsumableConfigDyn.xml HTTP/1.1#015#012Accept: text/plain#015#012Host:localhost#015#012User-Agent:hplip#015#012#015#012";int bit = 0;// 写入命令res = hpmud_write_channel(dd, cd, buf, 100, 6, &bit);if (res != HPMUD_R_OK){fprintf(stderr, "error hpmud_write_channel (code=%d)\n", res);return 1;}readLEDMData();return 0;hpmud_close_channel(dd, cd);hpmud_close_device(dd);return 0;}

本程序会从打印出所得到状态的数据,pscat:StatusCategory字段中的就是状态值了,事实上能到了如《关于打印机状态的获取》提到15个左右的状态,可是这个协议所规定的状态所有罗列出来:

扩展:眼下仅仅是上一个课题的总结。这之后的应用还有不少的问题,怎样应用。以及和利用设备节点打印是否冲突,以及是否能打印也基于hpmud。

。。

8.意外收获

老天真的会眷恋努力的人,刚在PC上实现基于HPMUD的状态获取,考虑着进行三步走中的更为繁琐的后两步(移植到嵌入式Linux+移植到Android)的时候,上天又送我一份大礼--打印机状态获取的还有一种方式:通过DeviceId。

这个可能不一定适合全部打印机。可是能够确定的是全然适应我如今正在调试的这款。

关于DeviceId从一開始看打印机相关的东西的时候最先接触到的就是这个DeviceId,能够说我对它的感情也是跌宕起伏。从一喜得DeviceId。到认为其作用单一。到如今的强大无比。

以下说点正经的,在《互联网打印协议-rfc2911》的printer-state-reasons章节规定了打印机异常状态码。也就是说除了使用HP自己定义的LEDM获取的状态外,相同还能够通过标准的IPP协议得到状态值。由此也能延伸出一个问题,CUPS应该也能够获取打印机状态了。可是却没有做不论什么显示。至于是为什么。这个还是比較玄乎。

详细来看DeviceID中含有状态的“S”字段:S:038000C484a01021002c1f01100c2881100;首先说明的是这个当中的都是16进制的数。前两位是版本号信息,依据版本号信息不同。状态码所在的位置也不同,比方这里的版本号号为03,那么状态码在第16位的两位数这里为00转换为10进制也是0。这个状态代表空暇。有时候代码比语言更有说服力。

java版本号:

public int getPrinterStatusCode() {String deviceId = getPrinterDeivceId();int ippStatus = -1;int pSf = 2;if(deviceId == null)return ippStatus;// somthingString str[] = deviceId.split(";S:");if(str.length > 1){if(str[1] != null){int ver=Integer.parseInt(str[1].substring(0,2), 16);/* Position pointer to printer state subfield. */switch (ver){case 0:case 1:case 2:pSf+=12;break;case 3:pSf+=14;break;case 4:pSf+=18;break;default:Slog.w(LOG_TAG, "WARNING: unknown S-field version=" + ver + "\n");pSf+=12;break;}ippStatus = Integer.parseInt(str[1].substring(pSf, pSf + 2), 16);}}return ippStatus;}

C版本号:

static int get_printer_status_code(const char* device_id){const char* id = device_id;char *pSf;int ver;int status = 0;/* Check for valid S-field in device id string. */if ((pSf = strstr(id, ";S:")) == NULL){/* No S-field, use status register instead of device id. *//* do nothing */goto bugout;}else{/* Valid S-field, get version number. */pSf+=3;ver = 0;HEX2INT(*pSf, ver);pSf++;ver = ver << 4;HEX2INT(*pSf, ver);pSf++;/* Position pointer to printer state subfield. */switch (ver){case 0:case 1:case 2:pSf+=12;break;case 3:pSf+=14;break;case 4:pSf+=18;break;default:printf("WARNING: unknown S-field version=%d\n", ver);pSf+=12;break;}/* Extract VStatus.*/status = 0;HEX2INT(*pSf, status);pSf++;status = status << 4;HEX2INT(*pSf, status);}printf("status:%d\n", status);bugout:return status;}

状态码相应关系:

VSTATUS_IDLE = 0,VSTATUS_BUSY = 1,VSTATUS_PRNT = 2,/* io printing */VSTATUS_OFFF = 3,/* turning off */VSTATUS_RPRT = 4,/* report printing */VSTATUS_CNCL = 5,/* canceling */VSTATUS_IOST = 6,/* io stall */VSTATUS_DRYW = 7,/* dry time wait */VSTATUS_PENC = 8,/* pen change */VSTATUS_OOPA = 9,/* out of paper */VSTATUS_BNEJ = 10,/* banner eject needed */VSTATUS_BNMZ = 11,/* banner mismatch */VSTATUS_PHMZ = 12,/* photo mismatch */VSTATUS_DPMZ = 13,/* duplex mismatch */VSTATUS_PAJM = 14,/* media jam */VSTATUS_CARS = 15,/* carriage stall */VSTATUS_PAPS = 16,/* paper stall */VSTATUS_PENF = 17,/* pen failure */VSTATUS_ERRO = 18,/* hard error */VSTATUS_PWDN = 19,/* power down */VSTATUS_FPTS = 20,/* front panel test */VSTATUS_CLNO = 21 /* clean out tray missing */

文章至此该结束了。

其他:

Linux打印驱动知识点

1.关于DeviceId各段意义见《ieee_1284》

2.关于LEDM见《DISCOVERINGPC-CONNECTEDDEVICES》

3.Syslog见《syslog-example》经过实践输出到了/var/log/syslog.

4.关于EclipseCD高版本号的MemoryView不能显示相应的Text.换成HeliosServiceRelease2使用NewRendrings->Traditional.

5.关于PJL(打印机控制语言)《Printer Job Language Technical Reference Manual》

6.终于选择了基于deviceId的方法来实现。所以临时不再用hpmud的方法了。可是已经代码已经实现了printDate和基于ledm获取打印机的状态信息。

#include <stdio.h>#include <string.h>#include <hpmud.h>#include <malloc.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <pthread.h>#include <stdlib.h>#include <stdarg.h>//#define DEBUG#ifdef DEBUG#define debug(fmt,args...) printf (fmt ,##args)#define debugX(level,fmt,args...) if (DEBUG>=level) debug(fmt,##args);#else#define debug(fmt,args...)#define debugX(level,fmt,args...)#endif /* DEBUG */// hp printer devicestatic HPMUD_DEVICE hd;#define MALLOC(type, n) (type*)malloc(n*sizeof(type))// HPMUD_I_MAX#define HPMUD_I_MAX 18static int channels[HPMUD_I_MAX] = {0};typedef HPMUD_CHANNEL(open_channel)(void);typedef int(read_func)(int bytes_requested, char* reply, int timeout);enum BACKEND_RESULT{BACKEND_OK = 0,BACKEND_FAILED = 1, /* use error-policy */BACKEND_HOLD = 3, /* hold job */BACKEND_STOP = 4, /* stop queue */BACKEND_CANCEL = 5 /* cancel job */};struct pjl_attributes{int pjl_device; /* 0=disabled, 1=enabled */int current_status;int eoj_pages; /* end-of-job pages */int abort; /* 0=no, 1=yes */int done;/* 0=no, 1=yes */HPMUD_DEVICE dd;HPMUD_CHANNEL cd;pthread_t tid;pthread_mutex_t mutex;pthread_cond_t done_cond;};#define _STRINGIZE(x) #x#define STRINGIZE(x) _STRINGIZE(x)#define BUG(args...) bug(__FILE__ " " STRINGIZE(__LINE__) ": " args)#ifdef HP_DEBUG#define DBG(args...) syslog(LOG_INFO, __FILE__ " " STRINGIZE(__LINE__) ": " args)#define DBG_DUMP(data, size) sysdump((data), (size))#define DBG_SZ(args...) syslog(LOG_INFO, args)#else#define DBG(args...)#define DBG_DUMP(data, size)#define DBG_SZ(args...)#endif#define RETRY_TIMEOUT 30 /* seconds */#define EXCEPTION_TIMEOUT 45 /* seconds */#define NFAULT_BIT 0x08#define PERROR_BIT 0x20#define OOP (NFAULT_BIT | PERROR_BIT)#define JAMMED(PERROR_BIT)#define ERROR_TRAP(0)#define STATUS_MASK (NFAULT_BIT | PERROR_BIT)#define DEVICE_IS_OOP(reg) ((reg & STATUS_MASK) == OOP)#define DEVICE_PAPER_JAMMED(reg) ((reg & STATUS_MASK) == JAMMED)#define DEVICE_IO_TRAP(reg) ((reg & STATUS_MASK) == ERROR_TRAP)#define HEX2INT(x, i) if (x >= '0' && x <= '9')i |= x - '0'; \else if (x >= 'A' && x <= 'F') i |= 0xA + x - 'A'; \else if (x >= 'a' && x <= 'f') i |= 0xA + x - 'a'/* Definitions for hpLogLevel in cupsd.conf. */#define BASIC_LOG1#define SAVE_PCL_FILE2#define SAVE_INPUT_RASTERS 4#define SEND_TO_PRINTER_ALSO 8/* Actual vstatus codes are mapped to 1000+vstatus for DeviceError messages. */typedef enum{VSTATUS_IDLE = 1000,VSTATUS_BUSY,VSTATUS_PRNT,/* io printing */VSTATUS_OFFF,/* turning off */VSTATUS_RPRT,/* report printing */VSTATUS_CNCL,/* canceling */VSTATUS_IOST,/* io stall */VSTATUS_DRYW,/* dry time wait */VSTATUS_PENC,/* pen change */VSTATUS_OOPA,/* out of paper */VSTATUS_BNEJ,/* banner eject needed */VSTATUS_BNMZ,/* banner mismatch */VSTATUS_PHMZ,/* photo mismatch */VSTATUS_DPMZ,/* duplex mismatch */VSTATUS_PAJM,/* media jam */VSTATUS_CARS,/* carriage stall */VSTATUS_PAPS,/* paper stall */VSTATUS_PENF,/* pen failure */VSTATUS_ERRO,/* hard error */VSTATUS_PWDN,/* power down */VSTATUS_FPTS,/* front panel test */VSTATUS_CLNO /* clean out tray missing */} VSTATUS;#define EVENT_START_JOB 500#define EVENT_END_JOB 501//const char pjl_status_cmd[] = "\e%-12345X@PJL INFO STATUS \r\n\e%-12345X";static const char pjl_ustatus_cmd[] = "\e%-12345X@PJL USTATUS DEVICE = ON \r\n@PJL USTATUS JOB = ON \r\n@PJL JOB \r\n\e%-12345X";static const char pjl_job_end_cmd[] = "\e%-12345X@PJL EOJ \r\n\e%-12345X";static const char pjl_ustatus_off_cmd[] = "\e%-12345X@PJL USTATUSOFF \r\n\e%-12345X";static int bug(const char *fmt, ...){char buf[256];va_list args;int n;va_start(args, fmt);if ((n = vsnprintf(buf, 256, fmt, args)) == -1)buf[255] = 0;/* output was truncated */fprintf(stderr, "%s", buf);//syslog(LOG_ERR, "%s", buf);fflush(stderr);va_end(args);return n;}/*** 因为使用的数组来实现python中的字典* 所以要将字符串转化为相应数字* openChannle和closeChannel中会用到*/static int get_service_name_num(char* service_name){int ser_name_id = 0;if(!strncmp(HPMUD_S_PRINT_CHANNEL, service_name, strlen(service_name)))ser_name_id = 1;else if(!strncmp(HPMUD_S_PML_CHANNEL, service_name, strlen(service_name)))ser_name_id = 2;else if(!strncmp(HPMUD_S_SCAN_CHANNEL, service_name, strlen(service_name)))ser_name_id = 3;else if(!strncmp(HPMUD_S_FAX_SEND_CHANNEL, service_name, strlen(service_name)))ser_name_id = 4;else if(!strncmp(HPMUD_S_CONFIG_UPLOAD_CHANNEL, service_name, strlen(service_name)))ser_name_id = 5;else if(!strncmp(HPMUD_S_CONFIG_DOWNLOAD_CHANNEL, service_name, strlen(service_name)))ser_name_id = 6;else if(!strncmp(HPMUD_S_MEMORY_CARD_CHANNEL, service_name, strlen(service_name)))ser_name_id = 7;else if(!strncmp(HPMUD_S_EWS_CHANNEL, service_name, strlen(service_name)))ser_name_id = 8;else if(!strncmp(HPMUD_S_EWS_LEDM_CHANNEL, service_name, strlen(service_name)))ser_name_id = 9;else if(!strncmp(HPMUD_S_SOAP_SCAN, service_name, strlen(service_name)))ser_name_id = 10;else if(!strncmp(HPMUD_S_SOAP_FAX, service_name, strlen(service_name)))ser_name_id = 11;else if(!strncmp(HPMUD_S_DEVMGMT_CHANNEL, service_name, strlen(service_name)))ser_name_id = 12;else if(!strncmp(HPMUD_S_MARVELL_SCAN_CHANNEL, service_name, strlen(service_name)))ser_name_id = 13;else if(!strncmp(HPMUD_S_MARVELL_FAX_CHANNEL, service_name, strlen(service_name)))ser_name_id = 14;else if(!strncmp(HPMUD_S_LEDM_SCAN, service_name, strlen(service_name)))ser_name_id = 15;else if(!strncmp(HPMUD_S_WIFI_CHANNEL, service_name, strlen(service_name)))ser_name_id = 16;elseser_name_id = 0;return ser_name_id;}static int __closeChannel(char* service_name){int result_code = 0;int ser_name_id = get_service_name_num(service_name);//if not self.mq['io-mode'] == IO_MODE_UNI and// if self.io_state == IO_STATE_HP_OPEN:// service_name = service_name.upper();if(channels[ser_name_id] != 0){printf("Closing %s channel...\n", service_name);result_code = hpmud_close_channel(hd, channels[ser_name_id]);if (result_code != HPMUD_R_OK){fprintf(stderr, "error hpmud_close_channel (code=%d)\n", result_code);return 1;}else{channels[ser_name_id] = 0;}}return 0;}/** open channel*/static int __openChannel(char* service_name){int result_code = 0;int channel_id = 0;HPMUD_CHANNEL ret = 0;int ser_name_id = get_service_name_num(service_name);if (channels[ser_name_id] == 0){printf("Opening %s channel...\n", service_name);result_code = hpmud_open_channel(hd, service_name, &channel_id);if (result_code != HPMUD_R_OK){fprintf(stderr, "error opening channel (code=%d)\n", result_code);exit(1);}else{channels[ser_name_id] = channel_id;debug("channel-id=%d\n", channel_id);ret = channel_id;}}else{printf("already open!\n");ret = channels[ser_name_id];}return ret;}/** read channel*/static int __readChannel(open_channel opener, int bytes_to_read, char* reply, int allow_short_read, int timeout){bytes_to_read = 1024;char data[1024] = {0};int ret = 0;int num_bytes = 0;int len = 0;char *p = reply;HPMUD_CHANNEL channel_id = opener();while (1){ret = hpmud_read_channel(hd, channel_id, data, 1024, timeout, &num_bytes);debug("Result code=%d\n", ret);len = strlen(data);if(ret == HPMUD_R_IO_TIMEOUT){debug("I/O timeout\n");break;}if(ret != HPMUD_R_OK){debug("Channel read error\n");break;}//debug("read_buf:%s\n", data);if(!len){debug("End of data\n");break;}memcpy(p, data, len);if (num_bytes == bytes_to_read){debug("Full read complete.\n");break;}if (allow_short_read && (num_bytes < bytes_to_read)){debug("Allowed short read of %d of %d bytes complete.\n", num_bytes, bytes_to_read);break;}}debug("Saved %d total bytes to stream.\n", num_bytes);return num_bytes;}/*** write channel*/static int __writeChannel(open_channel opener, const char* data, int total_bytes_to_write){HPMUD_DEVICE device_id = hd;HPMUD_CHANNEL channel_id = opener();intresult_code = 0;int bytes_written = 0;const char* buffer = data;int bytes_out = 0;intmax_message_len = 16384;int timeout = 45;int bytes_to_write = total_bytes_to_write;while(bytes_to_write > 0){result_code = hpmud_write_channel(device_id, channel_id, buffer, bytes_to_write < max_message_len ? bytes_to_write : max_message_len, timeout, &bytes_written);printf("Result code=%d\n", result_code);if (result_code != HPMUD_R_OK){fprintf(stderr, "Channel write error\n");return -1;}buffer += max_message_len;bytes_out += bytes_written;bytes_to_write -= bytes_written;}if (total_bytes_to_write != bytes_out){printf("total_bytes_to_write =%d =\\= bytes_out=%d\n", total_bytes_to_write, bytes_out);return -1;}//printf("%s end\n", __func__);return bytes_out;}static HPMUD_CHANNEL openEWS_LEDM(){return __openChannel(HPMUD_S_EWS_LEDM_CHANNEL);}static HPMUD_CHANNEL openPrint(){return __openChannel(HPMUD_S_PRINT_CHANNEL);}static int closePrint(void){return __closeChannel(HPMUD_S_PRINT_CHANNEL);}static int closeEWS_LEDM(void){return __closeChannel(HPMUD_S_EWS_LEDM_CHANNEL);}static int readEWS_LEDM(int bytes_requested, char* reply, int timeout){open_channel* opener = openEWS_LEDM;return __readChannel(opener, bytes_requested, reply, 1, timeout);}static int writePrint(const char* data, int len){open_channel* opener = openPrint;int ret = EXIT_FAILURE;int result_code = 0;//TODO:delect hpmud_write_channel/* Enable unsolicited status. *///ret = hpmud_write_channel(hd, channel_id, pjl_ustatus_cmd, sizeof(pjl_ustatus_cmd)-1, 5, &bytes_written);result_code = __writeChannel(opener, data, len);if(result_code != len){printf("ret != len(%s:%u,%s)\n", __FILE__, __LINE__, __func__);goto bugout;}/* Look for job end status. *///ret = hpmud_write_channel(hd, channel_id, pjl_ustatus_off_cmd, sizeof(pjl_ustatus_off_cmd)-1, 5, &bytes_written);result_code = __writeChannel(opener, pjl_job_end_cmd, sizeof(pjl_job_end_cmd)-1);if(result_code != (sizeof(pjl_job_end_cmd)-1)){printf("ret != len(%s:%u,%s)\n", __FILE__, __LINE__, __func__);goto bugout;}ret = EXIT_SUCCESS;bugout:return ret;}static int writeEWS_LEDM(const char* data, int len){open_channel* opener = openEWS_LEDM;return __writeChannel(opener, data, len);}static void readLEDMData(read_func* func, char *reply){int timeout = 6;const char* END_OF_DATA="0\r\n\r\n";int bytes_read = 0;int bytes_requested = 1024;char temp_buf[1024] = {0}; //大小要一致int chunkedFlag = 1;char *offset = reply;if(reply == NULL){fprintf(stderr, "MALLC FAILURE!\n");return;}bytes_read = func(bytes_requested, reply, timeout);offset += bytes_read;//debug("%s:%s\n", __func__, reply);// 默认chunked分块.chunkedFlag = 1;//result = strtok(reply, "\n");//debug("result=%s\n", result);while (bytes_read > 0){bytes_read = readEWS_LEDM(bytes_requested, (char*)temp_buf, timeout);//reply.write(temp_buf.getvalue());memcpy(offset, temp_buf, bytes_read);debug("%s:%s\n", __func__, offset);offset += bytes_read;if(!chunkedFlag) // Unchunked data{// do nothing!}else // Chunked data end{//END_OF_DATA == temp_buf.getvalue();if(!strncmp(temp_buf, END_OF_DATA, sizeof(END_OF_DATA)))break;}}printf("%s:%s\n", __func__, reply);}static int open_hp(const char* url, char* reply){char data[512] = {0};debug("open_hp(%s)\n", url);// match_obj = http_pat_url.search(url)// loc = url.split("=")[url.count("=")]openEWS_LEDM();sprintf(data, "GET %s HTTP/1.1\r\nAccept: text/plain\r\nHost:localhost\r\nUser-Agent:hplip\r\n\r\n", url);writeEWS_LEDM(data, strlen(data));//while dev.readEWS_LEDM(512, reply, timeout=3)://passread_func* func = readEWS_LEDM;readLEDMData(func, reply);//reply.seek(0);//return reply.getvalue();return 0;}void getEWSUrl_LEDM(const char* url, char* reply){// int self, url, stream, footer;// url2 = "%s&loc=%s" % (self.device_uri.replace('hpfax:', 'hp:'), url);// data = self;// opener = LocalOpenerEWS_LEDM({});// opener.open_hp(url2, data);open_hp(url, reply);closeEWS_LEDM();}void printData(){char *buf = (char*)MALLOC(unsigned char, 107968);if(buf == NULL){fprintf(stderr, "MALLC FAILURE!\n");return;}int fd = open("/home/kangear/bin.bin", O_RDONLY);if(fd == -1){fprintf(stderr, "open file error!\n");return;}int num = read(fd, buf, 107968);if(num == -1){fprintf(stderr, "read file error!\n");return;}writePrint(buf, num);close(fd);free(buf);buf = NULL;}/*** device discovery* if there is hp device return EXIT_SUCCESS, but EXIT_FAILURE.*/static int device_discovery(){char buf[HPMUD_LINE_SIZE*64];int cnt=0, bytes_read, r=EXIT_FAILURE;enum HPMUD_RESULT stat;stat = hpmud_probe_devices(HPMUD_BUS_ALL, buf, sizeof(buf), &cnt, &bytes_read);if (stat != HPMUD_R_OK)goto bugout;if (cnt == 0){#ifdef HAVE_CUPS11fprintf(stdout, "direct hp:/no_device_found \"Unknown\" \"hp no_device_found\"\n");#elsefprintf(stdout, "direct hp \"Unknown\" \"HP Printer (HPLIP)\"\n");#endifgoto bugout;}elsefprintf(stdout, "%s", buf);r = EXIT_SUCCESS;bugout:return r;}static int open_device(const char* device_uri){//int io_mode = 0;HPMUD_DEVICE device_id = -1;int result_code = 0, r = EXIT_FAILURE;enum HPMUD_IO_MODE io_mode = HPMUD_RAW_MODE;debug("I/O mode=%d\n", io_mode);// 打开设备获得result_code = hpmud_open_device(device_uri, io_mode, &device_id);if (result_code != HPMUD_R_OK){fprintf(stderr, "error opening device (code=%d)\n", result_code);goto bugout;}hd = device_id; //TODO:delect.r = EXIT_SUCCESS;bugout:return r;}/* Map printer status to IPP printer-state-reasons (see RFC-2911). */static int map_ipp_printer_state_reason(int status, const char **state_msg){if (status >= 1000 && status <= 1999){/* inkjet vstatus */switch (status){case VSTATUS_IDLE:case VSTATUS_PRNT:*state_msg = "none";break;case VSTATUS_OOPA:*state_msg = "media-empty-error";break;case(VSTATUS_PAJM):*state_msg = "media-jam-error";break;default:*state_msg = "other";break;}}else if (status >= 10000 && status <= 55999){/* laserjet pjl status */if (status >= 10000 && status <= 10999)*state_msg = "none";else if (status >= 41000 && status <= 41999)*state_msg = "media-empty-error";else if ((status >= 42000 && status <= 42999) || (status >= 44000 && status <= 44999) || (status == 40022))*state_msg = "media-jam-error";else if (status == 40021)*state_msg = "cover-open-error";else if (status == 40600)*state_msg = "toner-empty-error";else*state_msg = "other";/* 40017 - cartridge E-LABEL is unreadable (ie: ljp1005) */}else{/* Assume hpmud error */*state_msg = "other";}return 0;}/** get_printer_status** inputs:* dd - device descriptor* pa - see pjl_attributes definition** outputs:* return - printer status, 1000 to 1999 = inkjet vstatus, 5000 to 5999 = hpmud error, 10000 to 55999 = pjl status code**/static int get_printer_status(HPMUD_DEVICE dd, HPMUD_CHANNEL cd, struct pjl_attributes *pa){char id[1024];char *pSf;int status, ver, len;enum HPMUD_RESULT r;if (pa->pjl_device){pthread_mutex_lock(&pa->mutex);status = pa->current_status;pthread_mutex_unlock(&pa->mutex);}else{status = VSTATUS_IDLE; /* set default */r = hpmud_get_device_id(dd, id, sizeof(id), &len);//if (!(r == HPMUD_R_OK || r == HPMUD_R_DEVICE_BUSY))if (r != HPMUD_R_OK){status = 5000+r;/* no deviceid, return some error */goto bugout;}/* Check for valid S-field in device id string. */if ((pSf = strstr(id, ";S:")) == NULL){/* No S-field, use status register instead of device id. */unsigned int bit_status;r = hpmud_get_device_status(dd, &bit_status);// if (!(r == HPMUD_R_OK || r == HPMUD_R_DEVICE_BUSY))if (r != HPMUD_R_OK){status = 5000+r;/* no 8-bit status, return some error */goto bugout;}if (DEVICE_IS_OOP(bit_status))status = VSTATUS_OOPA;else if (DEVICE_PAPER_JAMMED(bit_status))status = VSTATUS_PAJM;else if (DEVICE_IO_TRAP(bit_status))status = VSTATUS_CARS;}else{/* Valid S-field, get version number. */pSf+=3;ver = 0;HEX2INT(*pSf, ver);pSf++;ver = ver << 4;HEX2INT(*pSf, ver);pSf++;/* Position pointer to printer state subfield. */switch (ver){case 0:case 1:case 2:pSf+=12;break;case 3:pSf+=14;break;case 4:pSf+=18;break;default:BUG("WARNING: unknown S-field version=%d\n", ver);pSf+=12;break;}/* Extract VStatus.*/status = 0;HEX2INT(*pSf, status);pSf++;status = status << 4;HEX2INT(*pSf, status);status += 1000;}}bugout:return status;}/* Check printer status, if a valid error state, loop until error condition is cleared. */static int loop_test(HPMUD_DEVICE dd, HPMUD_CHANNEL cd, struct pjl_attributes *pa,const char *dev, const char *printer, const char *username, const char *jobid, const char *title){int status, stat;const char *pstate, *old_state=NULL;while (1){status = get_printer_status(dd, cd, pa);map_ipp_printer_state_reason(status, &pstate);/* Check for user intervention errors. */if (strstr(pstate, "error")){if (pstate != old_state){if (old_state){/* Clear old error. *///device_event(dev, printer, status, username, jobid, title);fprintf(stderr, "STATE: -%s\n", old_state);}/* Display error. *///device_event(dev, printer, status, username, jobid, title);fprintf(stderr, "STATE: +%s\n", pstate);old_state = pstate;}BUG("ERROR: %d %s; will retry in %d seconds...\n", status, pstate, RETRY_TIMEOUT);sleep(RETRY_TIMEOUT);continue;}/* Clear any old state. */if (old_state)fprintf(stderr, "STATE: -%s\n", old_state);/* Check for system errors. */if (status >= 5000 && status <= 5999){/* Display error. *///device_event(dev, printer, status, username, jobid, title);BUG("ERROR: %d device communication error!\n", status);stat = 1;}elsestat = 0;break; /* done */}return stat;}int get_device_id(HPMUD_DEVICE hd){char id[1024] = {0};char *pSf;int status, ver, len;enum HPMUD_RESULT r;int ret = EXIT_FAILURE;r = hpmud_get_device_id(hd, id,sizeof(id), &len);printf("device_id:%s\n", id);if (r != HPMUD_R_OK){/* no deviceid, return some error */goto bugout;}/* Check for valid S-field in device id string. */if ((pSf = strstr(id, ";S:")) == NULL){/* No S-field, use status register instead of device id. */unsigned int bit_status;r = hpmud_get_device_status(hd, &bit_status);// if (!(r == HPMUD_R_OK || r == HPMUD_R_DEVICE_BUSY))if (r != HPMUD_R_OK){status = 5000+r;/* no 8-bit status, return some error */goto bugout;}// if (DEVICE_IS_OOP(bit_status))//status = VSTATUS_OOPA;// else if (DEVICE_PAPER_JAMMED(bit_status))//status = VSTATUS_PAJM;// else if (DEVICE_IO_TRAP(bit_status))//status = VSTATUS_CARS;}else{/* Valid S-field, get version number. */pSf+=3;ver = 0;HEX2INT(*pSf, ver);pSf++;ver = ver << 4;HEX2INT(*pSf, ver);pSf++;/* Position pointer to printer state subfield. */switch (ver){case 0:case 1:case 2:pSf+=12;break;case 3:pSf+=14;break;case 4:pSf+=18;break;default:printf("WARNING: unknown S-field version=%d\n", ver);pSf+=12;break;}/* Extract VStatus.*/status = 0;HEX2INT(*pSf, status);pSf++;status = status << 4;HEX2INT(*pSf, status);status += 1000;}printf("status:%d\n", status);ret = EXIT_SUCCESS;bugout:return ret;}static int get_printer_status_code(const char* device_id){const char* id = device_id;char *pSf;int ver;int status = 0;/* Check for valid S-field in device id string. */if ((pSf = strstr(id, ";S:")) == NULL){/* No S-field, use status register instead of device id. *//* do nothing */goto bugout;}else{/* Valid S-field, get version number. */pSf+=3;ver = 0;HEX2INT(*pSf, ver);pSf++;ver = ver << 4;HEX2INT(*pSf, ver);pSf++;/* Position pointer to printer state subfield. */switch (ver){case 0:case 1:case 2:pSf+=12;break;case 3:pSf+=14;break;case 4:pSf+=18;break;default:printf("WARNING: unknown S-field version=%d\n", ver);pSf+=12;break;}/* Extract VStatus.*/status = 0;HEX2INT(*pSf, status);pSf++;status = status << 4;HEX2INT(*pSf, status);status += 1000;}printf("status:%d\n", status);bugout:return status;}static int get_cups_uri(char* cups_uri){char buf[HPMUD_LINE_SIZE*64];int cnt=0, bytes_read, r=EXIT_FAILURE;enum HPMUD_RESULT stat;stat = hpmud_probe_devices(HPMUD_BUS_ALL, buf, sizeof(buf), &cnt, &bytes_read);if (stat != HPMUD_R_OK)goto bugout;if (cnt == 0)fprintf(stdout, "direct hp \"Unknown\" \"HP Printer (HPLIP)\"\n");elsesprintf(cups_uri, buf, strlen(buf));r = EXIT_SUCCESS;bugout:return r;}static int make_device_uri(char* dev_uri){int ret = EXIT_FAILURE;enum HPMUD_RESULT stat;char cups_uri[HPMUD_LINE_SIZE*64];char* p = NULL;stat = get_cups_uri(cups_uri);if (stat != EXIT_SUCCESS)goto bugout;p = strtok(cups_uri, " ");if(p == NULL)goto bugout;p = strtok(NULL, " ");if(p == NULL)goto bugout;// copy only one device uri and others ignore.sprintf(dev_uri, p, strlen(p));debug("dev_uri:%s\n", dev_uri);ret = EXIT_SUCCESS;bugout:return ret;}int main(void){int ret = EXIT_FAILURE;//const char *device_uri = "hp:/usb/Deskjet_1010_series?serial=CN39I18M1805S8";//const char *device_uri = "hp:/usb/Deskjet_1000_J110_series?serial=CN2C818N3605YD";char dev_uri[HPMUD_LINE_SIZE] = {0};// step 1.if(device_discovery() != EXIT_SUCCESS){debug("device discovery failed!\n");goto bugout;}printf("device discovery success!\n");// step 2:解析一个device uri.if(make_device_uri(dev_uri) != EXIT_SUCCESS){debug("make device uri failed!\n");goto bugout;}// step 3:open hp deviceif(open_device(dev_uri) != EXIT_SUCCESS){debug("open_device device failed!\n");goto bugout;}// step 4: get device id.get_device_id(hd);//printData();//readAttributeFromXml_EWS//StatusType10();char* reply = (char*)MALLOC(char, 500*1024);//获取状态XMLgetEWSUrl_LEDM("/DevMgmt/ProductStatusDyn.xml", reply); // 获取状态//getEWSUrl_LEDM("/DevMgmt/ConsumableConfigDyn.xml", reply); // 获取耗材配置free(reply);reply = NULL;if (hd >= 0)hpmud_close_device(hd);ret = EXIT_SUCCESS;bugout:return ret;}

打印机异常状态:

本文转自mfrbuaa博客园博客,原文链接:/mfrbuaa/p/5065783.html,如需转载请自行联系原作者

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。