關於打印機狀態的獲取


        關於這個需求非常早就考慮了,一直沒敢下手,也不是不敢,是之前下過一次手可是沒有成功。一直過了幾個月騰出一些空暇來解決問題。另外說明一下,截止到眼下對於這個需求我還沒有一個全然的解決方式。這篇也僅僅是捋下思緒。

        關於打印機狀態的問題我在stackoverflow上也作過提問,結果問題就被刪除了,原因有二有人說這個問題是硬件上的問題,所以不在stackoverflow所討論的范圍。還有一個也許是自己的英文着實爛的不行了,問題都解釋不清楚。

        因為一直沒有死心,所以在平時無聊的時候也會掏出手機搜索一番,當時唯一的收獲是參考文檔[1]中提到的USBHostPrinterGetStatus(),這個奇妙的函數沒有寫不論什么來源,但作者將其描寫敘述成是能夠獲取打印機狀態的,我着實有那么一點興奮。可是苦於沒有來源,有點不知所措。只是我還是將其作為一個方向進行了深挖了的。順便找到了[3]-是和[1]差點兒相同的英文版本號,以及[2]這個現存的這個函數。從整體來說Linux中並沒有這個函數,不知道寫論文的那個是不是先有論文又做的實驗。這個似乎是一個裸機程序,在我找到[5]這樣專業文檔的時候,這個幾個狀態是USB通信協議中就已經規定了的。更加確定這個函數眼下深究下去是一個死路,只是以后做裸機的時候能夠又一次了解。

        以上是走過的錯路,以下說下我這次走能的小路:1.Linux中標准的USB打印機驅動着手;2.HP Device Manager入手。前后者都小有所獲,以下逐個來分析。逐個分析前先把打印機在Windows下的各種問題的狀態列表記錄一下,話說收集這個可不是一個簡單的事,首先是鎖定打印機型號然后制造這樣的故障,使得PC上可以顯示出對於的狀態對話框。(到眼下為至12-14還並非官方的文字,由於制造該故障的條件一直不具備)

 

NO

中文

英文

limit

1

無法與打印機通信

Unable to Communicate with Printer

E

2

出紙盒已關閉

Output Tray Closed

E

3

門己打開

Door Open

E

4

缺紙

Out of Paper

E

5

卡紙

Paper Jam

E

6

墨盒故障-黑色

Ink Cartridge Failure

E

7

墨盒故障-三色

-

E

8

墨盒故障-黑色-三色

-

E

9

墨盒丟失

Ink Cartrideges Missing

E

10

單墨盒模式-缺黑色

Single Ink Cartridge Mode

W

11

單墨盒模式-缺彩色

-

W

12

無墨  黑色

x

E

13

無墨  彩色

x

E

14

無墨  黑色-彩色

x

E

15

已經安裝HP保護墨盒

HP Protected Cartridge Installed

I

16

檢測到使用過的或仿制墨盒

Used or Counterfeit Cartridge Detected

I

(着實不知用wps轉換成的mht格式再粘貼到blog上后表格會變成虛的)

方向1是從usblp.c中的驅動着手

結合打印機內核驅動源代碼usblp.c以及Usb協議[5]規定打印機狀態:

 

驅動的詳細實現是在ioctl方法中的LPGETSTATUS命令中返回的狀態,經過實驗確實能獲得一個比較顯著的狀態Out of Paper/Paper Empty這樣一個狀態,應用層的代碼例如以下:

#include <stdio.h>

#include <sys/types.h>

#include <unistd.h>

#include <sys/wait.h>

#include <dirent.h>

#include <string.h>

#include <signal.h>

#include <fcntl.h>

#include <sys/ioctl.h>

#include <linux/lp.h>

 

void getDeviceStatus(int fd) {

    if(fd < 0)

        return;

    int status = 0;

    ioctl(fd, LPGETSTATUS, &status);

    printf("%x\n", status);

    printf("Hello world\n");

}

 

int main()

{

    int fd = open("/dev/usb/lp0", O_RDWR);

    getDeviceStatus(fd);

    close(fd);

    return 0;

}


只是遺憾的是,這個狀態碼的規律是這種:正常0x18;缺紙 0x38;其他統統是0x10。等於我如今只拿到了一個狀態。我的高興勁頭只持續了幾分鍾。

方向2HP Device Manager的源代碼入手

例如以下圖,該軟件能夠顯示很多其它的狀態,且還是開源的hplib。從實驗得出該神器能夠獲得以上列出的每一個狀態。

推導一下這個神器的真實身份:HP Device Manager -> hp-boolbox -> hplib終於確定了hplib。hplib的架構是這種:


Hplip的源代碼中有這么一段,用到libusb.能夠獲取打印機狀態:

static int device_status(int fd, unsigned int *status)

{

    libusb_device_handle *hd;

    int interface;

    int len, stat=1;

    unsigned char byte;

 

    hd = fd_table[fd].hd;

    interface = fd_table[fd].interface;

 

    if (hd == NULL)

    {

        BUG("invalid device_status state\n");

        goto bugout;

    }

 

    len = libusb_control_transfer(hd,

            LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE/* bmRequestType */

            LIBUSB_REQUEST_CLEAR_FEATURE,        /* bRequest */

            0,        /* wValue */

            interface, /* wIndex */

            &byte, 1, LIBUSB_CONTROL_REQ_TIMEOUT);

 

    if (len < 0)

    {

        BUG("invalid device_status: %m\n");

        goto bugout;

    }

 

    *status = (unsigned int)byte;

    stat = 0;

    DBG("read actual device_status successfully fd=%d\n", fd);

 

bugout:

    return stat;

}


就這幾行代碼,但卻難住了我,還是靜下心來看看<libusb Developers Guide>。回頭再來繼續。從hplib追蹤到APDK(hp官方支持的非PC平台的打印驅動),當中包括了與打印通信以及打印機的錯誤代碼。僅僅Google出這么一個好的資料《APDK Developers Guide Reference Manual》。這個《hpmud》也相當好,能夠清晰的顯示出hplip源代碼結構。

$ sudo apt-get install libhpmud-dev

標准頭文件hpmud.h,基於這個開發。Hp.c就是一個獨立的基於libhpmud的程序。我在libhpmud中加入�的這個調試信息在執行hp.c的時候能夠看到,可是在執行hp-toolbox的時候根本沒有反應,又有點懷疑,它的底層沒實用libhpmud這個庫。

假設能將Door open這句話從打印機到屏幕的流程走通,這個狀態的問題基本就能夠宣告攻克了。可是這個僅僅是設想,真正實現起來並沒有那么easy。這是一個開篇。 


參考文檔:

1.《基於Android平台的無線打印模塊設計

2.USBHostPrinterGetStatus 

3.USB Printer Class on an Embedded Host

4.How to retrieve USB printer status?

5.Universal Serial Bus Device Class Definition for Printing Devices


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM