打印機其實和Android沒有什么大的關系,和linux內核關聯才是比較強的。
最終的結果是要在Android實現驅動打印機,但是一般調試一個新的驅動的流程是這樣的:1.先在linux PC上進行測試。2.在標准嵌入式linux上進行調試。3.改裝到Android中去。
為什么這么安排?因為資源是遞減的,可以在第一階段確定設備有無問題,以及該設備在linux工作流程;在第二階段是因為標准的嵌入式linux還是遵循GNU規定的,包括大部分,這個階段驗證該設備能否在ARM架構的上順利編譯通過;第三階段就是實用階段了,因為最終要在這個不是怎么遵守GNU規定的Android系統上運行的。
第一階段
我測試了3台打印機:1.Canon iP2780 2.Canon MX428 3.HP Deskjet 1000。由於的我作業系統就是Linux,在Linux PC上很快就逐個搞定。第1台用的是這里的驅動(包括deb包和部分開源源碼)加上這個《iP2700 series IJ Printer Driver Ver. 3.30 for Linux (操作說明)》,機器就可以正常使用了;第2台和第一台驅動模式都是一樣的只不過在這里;第3台用的是這里的一級一級選擇最終下載文件是:hplip-3.14.1.run,直接執行會把所缺失的東西全部安裝,可以成功使用。
如果我僅僅是一個使用者,那么到現在可以就結束了。但是我是一個開發者,我最終的目標是移植到Android中,所以我的目的地不在這里,我要繼續深度挖掘。要挖掘的點很多,這里說一個最迫切的就是如何用命令打印一個文件?這個問題似乎很奇怪,但是我也不知道如何做。不過最終找到了就是:lp或者lpr加文件名,就可以打印出一個文件了。例如:
lp ~/hello.pdf
找這么一個命令我就花費了幾個小時的時間,這里我就有一種很強的預感,前邊的路很還很遙遠。(整理文章的順序和實驗的步驟會稍有不同,其實這個命令在《iP2700 series IJ Printer Driver Ver. 3.30 for Linux (操作說明)》是有的,但是這個“操作說明”是后來才看到的)。
現在看來我不應該草率進行去進行第二個階段,應該好好的研究一下Linux的打印系統。總結文章就按照最好的流程來吧。先說我是怎么了解了linux的打印系統的。
意外發現的這個本書《Linux系統管理技術手冊》,真是對我了解Linux的打印系統幫助是最大的,涵蓋的知識面也是最全的,以后的階段中用到的自認為是新的東西,其實這本書上都詳細講解了。講解打印不是講解如何打印就好了,而是詳細的講解了打印機的原理,要經過哪些步驟,打印機語言等等,如果是國人寫的書一般會說“此內容不在本書要討論的范圍內”一句概括。那一章我反復看了一周時間才算有些眉目。
一切終歸一張圖:
其實到目前為止我應該好好規划一下我要設計的東西,實現中我急功近利了,並沒有做完全的規划就進行了第二階段。
小規划:
打印機選擇:推薦選擇HP的,激光的噴墨的都可以,HP是全力支持Linux的。
打印系統的選擇:
大的架構是CUPS,主要的模塊有:
后台:
過濾器:
PPD:
其實在圖中隨便從上到下連一條線,就可以組合成一套打印系統。下面進入第二階段吧。
在測試過程中還意外發現CUPS一個bug,或者是我還沒有已經有解決方案我還沒有發現而已。那就是CUPS缺少錯誤處理, 一台打印機,如果出現墨盒用完,墨盒實效等等問題的時候,CUPS是沒有告知用戶的。比如我的HP Deskjet 1000,在使用CUPS打印時出現了這個情況:打印機無響應,用lpstat -t查看到的狀態是“Rendering completed”。這就找不到問題所在了,不過同樣的情況下在Windows下找到了答案:
第二階段
調試Canon的打印機的時候我選擇了這樣的架構:CUPS+cnijfilter-source-3.30-1.tar.gz.
1.配置Linux內核(作用:生成設備節點)
make menuconfig 選上USB打印機選項:
Device Drivers --->
[*] USB support --->
<*> USB Printer support
(配置成功后,插入打印機后設備節點會出現在/dev/usb/目錄下一般名字"lp0")
2.交叉編譯CUPS 1.3.9
#!/bin/sh # 1.下載源碼 wget http://www.cups.org/software/1.3.9/cups-1.3.9-source.tar.gz && # 2.解壓並打開 tar xvzf cups-1.3.9-source.tar.gz && cd cups-1.3.9 && # 3.配置 ./configure --host=arm-linux --target=arm-linux --build=i686-linux CC=arm-linux-gcc CXX=arm-linux-g++ LD=arm-linux-ld RANLIB=arm-linux-ranlib AR=arm-linux-ar --disable-gnutls --disable-gssapi --disable-dbus --prefix=/ && # 4.修改Makefile使其不編譯man sed -i '22s/locale man monitor/locale monitor/' ./Makefile && # 5.編譯並安裝 make && make install DSTROOT=/work/rootfs/rootfs_qtopia_qt4 && echo "cups build install ok!"
3.交叉編譯ghostscript 8.15
#!/bin/sh DESTDIR=/work/rootfs/rootfs_qtopia_qt4 # 1.下載源碼 wget http://iweb.dl.sourceforge.net/project/ghostscript/GPL%20Ghostscript/8.15/ghostscript-8.15.tar.gz && # 2.解壓源碼 tar xvzf ghostscript-8.15.tar.gz && # 3.分別拷貝為PC版本和ARM版本 cp ghostscript-8.15 ghostscript-8.15-arm -r && mv ghostscript-8.15 ghostscript-8.15-pc && # 4.編譯PC版本 # -DHAVE_SYS_TIME_H是解決warning: implicit declaration of function 'gettimeofday' cd ghostscript-8.15-pc && ./configure && make XCFLAGS=-DHAVE_SYS_TIME_H=1 && cd ../ && # 5.配置arm版本 cd ghostscript-8.15-arm && ./configure --host=arm-linux && # 6.修改Makefile中STDLIBS=-lm 為STDLIBS=-lm -static sed -i '257s/STDLIBS=-lm/STDLIBS=-lm -static/' ./Makefile && # 7.拷貝PC版本工具 mkdir obj && cp ../ghostscript-8.15-pc/obj/genarch ../ghostscript-8.15-pc/obj/genconf ../ghostscript-8.15-pc/obj/echogs ./obj/ && # 8.編譯 make XCFLAGS=-DHAVE_SYS_TIME_H=1 && # 9.安裝(這個版本不支持make install的DESTDIR指定根目錄所以要手動拷貝,以后要調整目錄) mkdir -p ${DESTDIR}/usr/local/share/ghostscript/8.15/ && cp -r lib ${DESTDIR}/usr/local/share/ghostscript/8.15/ && cp -r Resource ${DESTDIR}/usr/local/share/ghostscript/8.15/ && cp bin/gs ${DESTDIR}/bin/
4.交叉編譯gutenprint 5.2.9
#!/bin/sh # 1.下載源碼 項目地址:http://sourceforge.net/projects/gimp-print/files/gutenprint-5.2/5.2.9/ wget http://softlayer-ams.dl.sourceforge.net/project/gimp-print/gutenprint-5.2/5.2.9/gutenprint-5.2.9.tar.bz2 && # 2.解壓 tar xvjf gutenprint-5.2.9.tar.bz2 && # 3.分別拷貝為PC版本和ARM版本 cp -r gutenprint-5.2.9 gutenprint-5.2.9-arm && mv gutenprint-5.2.9 gutenprint-5.2.9-pc && # 4.編譯PC版本 cd gutenprint-5.2.9-pc && ./configure && make && cd ../ && # 5.配置arm版本 cd gutenprint-5.2.9-arm && ./configure --host=arm-linux --target=arm-linux --build=i686-linux CC=arm-linux-gcc CXX=arm-linux-g++ LD=arm-linux-ld RANLIB=arm-linux-ranlib AR=arm-linux-ar --with-gimp2=no --without-gimp2 --enable-cups-ppds --enable-cups-level3-ppds --without-ghostscript --without-foomatic --disable-libgutenprintui2 && # 6.拷貝PC版本工具 make || cp ../gutenprint-5.2.9-pc/src/xml/.libs/extract-strings ./src/xml/.libs/ && # 7.編譯並安裝 make && make install DSTROOT=/work/rootfs/rootfs_qtopia_qt4 && echo "gutenprint build install ok!"
5.交叉編譯hpijs-2.1.4
#!/bin/sh # 1.下載源碼 項目地址:http://sourceforge.net/projects/hpinkjet/files/ wget http://superb-dca2.dl.sourceforge.net/project/hpinkjet/hpijs/2.1.4/hpijs-2.1.4.tar.gz # 2.解壓源碼 tar xvzf hpijs-2.1.4.tar.gz && cd hpijs-2.1.4 # 3.配置 ./configure --host=arm-linux --target=arm-linux --build=i686-linux CC=arm-linux-gcc CXX=arm-linux-g++ LD=arm-linux-ld RANLIB=arm-linux-ranlib AR=arm-linux-ar # 4.修正語法錯誤 dj3320.cpp第403行和registry.cpp第249行 開頭的char改為const char sed -i '249s/\tchar\t/\tconst char\t/' registry.cpp sed -i '403s/ char/ const char/' dj3320.cpp # 5.編譯並安裝 make && make install DESTDIR=/work/rootfs/rootfs_qtopia_qt4
6.啟動各個模塊
以上是我編譯的源碼所有記錄,它們每個都是可以單獨運行驗證的。
啟動cups:$ /etc/init.d/cups start
CUPS可以將/etc/cups/cupsd.conf的日志級別LogLevel設置為debug,這樣如果啟動失敗會將原因打印到/var/log/cups/error_log中。我沒有遇到什么大的bug,遇到的都是缺少目錄問題。
7.最簡的打印系統ghostscript+hpijs
這個方案主要是參考了《基於嵌入式Linux的打印控制系統的設計》,這個是比較適合嵌入式打印機的,不占資源,不需要一些相比比較雞肋的功能。保存了一份到資源中,下載(注:最好是自己源碼編譯,不保證對所有cpu可用,必須是ARM架構且在ARMv7以上)直接可以用。可以直接安裝主到Android中或者普通的嵌入式Linux中。
8.無系統的打印機實現
這個是更簡的,就是沒有操作系統的控制器來操作打印機,是我在調試這個HP Deskjet 1000意外發現一個牛人實現的《USB HOST+HP DeskJet 1000打印機》。當然我是真實的實驗了他提供的BIN文件,他用是TQ2440,我在MINI2440上直接測試也是沒有問題的,打印出來的內容是“HP802黑色墨盒加墨方法”,這兩款開發板都是采用的S3C2440這個ARM的CPU。雖然沒有提供源碼,不過也算是提供了一種可能,如果以后有這方面的需求可以順這條路研究下去。
第三階段 移植到Android中預留
1. 最簡打印移植到Android中
首先強扭過去,庫不用擔心,都是才用的靜態鏈接編譯的。關鍵是“文件系統層次結構標准”Android沒有遵守,經過實驗強制建立了兩個目錄,才能正常使用/usr和/tmp目錄。
需要優化的幾點:1.關於/tmp目錄的調整 2.關於/usr目錄的調整 3.設備節點的動態創建,。。。。
1.關於/tmp目錄的調整 在stackoverflow上討論出一個解決方案是用/data/local/tmp來代替;
2.關於/usr目錄的調整 重新編譯ghostscript調整的/system/usr/..目錄;
3.設備節點 還沒有調試;
4.打印中英文字庫的問題;
Fix /tmp目錄問題:
為了按照功能區別開來,最終選用/data/misc/printer/tmp/目錄作為/tmp目錄。將gs代碼gp_unifs.c中tmp/目錄更換。
$ sed -i '74s/"\/tmp\/"/"\/data\/misc\/printer\/tmp\/"/' ./src/gp_unifs.c
Fix /usr目錄問題:
一般是usr是在根目錄下的,Android中是在/system/上的,ghostscript編譯時要進行調整,調整的結果是在配置時添加:--prefix=/system/那么ghostscript就會把資源文件調整到/system/usr/share/....目錄下,這樣剛好可以解決問題。
Fix設備節點問題:
根據《Android與標准Linux對比》經驗和實驗得出:Android中用ueventd+VOLD來完成了普通Linux中udev的工作,前者負責創建設備節點,后者用於處理。插入打印機后,會自動創建設備節點/dev/usb/lp0。、
ueventd默認創建出來的是只有root用戶才能夠訪問的權限,Android中改變權限的方法是在uevent.${BOARD}.rc中添加如下:
#For USB printer
/dev/usb/lp0 0666 system system
再次查看設備節點權限,正常。
Fix字體問題:
一直測試打印的都圖片,打印中英文的時候會報錯,根據具體報錯原因打到解決方法。
#!/bin/sh # 說明:本腳本下載並打包GS所需字庫 # 版本:2013-01-17 # 將打包好的字庫放到 # Android: /system/usr/share/ghostscript/8.15/Resource/ 中解壓 # Linux : /usr/local/share/ghostscript/8.15/Resource/ 中解壓 # * 解決了常用中英文打印所需的字庫 DESTDIR=${PWD}/system # 1.下載gs-fonts源碼 項目地址:http://sourceforge.net/projects/gs-fonts/ wget http://superb-dca2.dl.sourceforge.net/project/gs-fonts/gs-fonts/8.11%20%28base%2035%2C%20GPL%29/ghostscript-fonts-std-8.11.tar.gz && # 2.解壓gs-fonts源碼 tar xvzf ghostscript-fonts-std-8.11.tar.gz && # 3.下載gs-9.04,獲取其中的字庫 項目地址:http://sourceforge.net/projects/ghostscript/files/GPL%20Ghostscript/9.04/ wget http://softlayer-ams.dl.sourceforge.net/project/ghostscript/GPL%20Ghostscript/9.04/ghostscript-9.04.tar.bz2 && # 4.解壓gs-9.04源碼 tar xvjf ghostscript-9.04.tar.bz2 && # 5.建立字庫目錄 Font test -d ./Font && rm -rf ./Font ; mkdir ./Font && # 6.拷貝字庫到Font目錄中 # 拷貝gs-fonts cp -rf fonts/* ./Font && # 拷貝gs-9.04的字庫 cp -rf ghostscript-9.04/Resource/Font/* ./Font && # 7.打包字庫 tar cvzf Font.tar.gz Font && echo "Fonts ok!"
字體的問題解決了,Android中也有自己的字體位於/system/fonts中,其中ttf格式居多,而這里用的大多都是pfb格式的。
---------------------
作者:kangear
來源:CSDN
原文:https://blog.csdn.net/kangear/article/details/18141741