2015年1月25日

HPLIP bb-soap解析 - 4 - bb_end_page 和 bb_end_scan

前言:
接續前篇,這篇會將bb_end_page和bb_end_scan一起po完,主要會是解析bb_end_scan,
因為從前面的flow可以發現,bb_end_page實際動作應該只有做hpmud_channel_close(),
其他幾乎沒看到在幹嘛,所以這篇主要就變成了bb_end_scan的解析。

在一開始時,嘗試要把Close Code Library自己實做,覺得似乎非常困難,
要知道這可是現成的事務機,要破解它的Protocol應該很難吧......

實際下去理解並dump它的通訊內容後,其實並不難,
整個flow看完理解後,我就在想,真的還需要補充實做bb_soap嗎?
自己參考SANE backends範例寫個CM1015專用的SANE backends算了,
反正底層一樣呼叫hpmud,其他就自己解決了。

而且看到現在,感覺已經偏了,怎麼好像在研究SOAP的感覺(加油,魔王只剩SOAP DIME了),
我並沒有想要理解SOAP啊.........

bb_end_page:
目前瞭解,看起來就只有呼叫hpmud_channel_close()。

所以這裡描述就是:
  • bb_end_page
    • hpmud_channel_close()
結束。

bb_end_scan:
動作流程如下:
  • bb_end_scan
    • hpmud_channel_open()
    • hpmud_channel_write()
    • hpmud_channel_write()
    • hpmud_channel_write()
    • hpmud_channel_write()
    • hpmud_channel_read()
    • hpmud_channel_read()
    • hpmud_channel_read()
    • hpmud_channel_read()
    • hpmud_channel_close()
bb_end_scan解析:
同前面,一樣把它溝通內容列出,共4個write、4個read。

write:
cat hpmud_write_channel_7.dump
POST / HTTP/1.1
Host: http:0
User-Agent: gSOAP/2.7
Content-Type: application/soap+xml; charset=utf-8
Transfer-Encoding: chunked
Connection: close



cat hpmud_write_channel_8.dump
1b9
前面已經知道,多出的部份就只是buffer沒清除,因此只列出神秘HEX數值。

cat hpmud_write_channel_9.dump
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wscn="http://tempuri.org/wscn.xsd"><SOAP-ENV:Body><wscn:CancelJob><ScanIdentifier>scanjob 10153</ScanIdentifier></wscn:CancelJob></SOAP-ENV:Body></SOAP-ENV:Envelope>


cat hpmud_write_channel_10.dump
0

前面已經知道,多出的部份就只是buffer沒清除,因此只列出神秘HEX數值。

read:
cat hpmud_read_channel_16.dump
HTTP/1.1 200 OK
Server: gSOAP/2.7
Content-Type: application/soap+xml; charset=utf-8
Transfer-Encoding: chunked
Connection: close



cat hpmud_read_channel_17.dump
1B7
前面已經知道,多出的部份就只是buffer沒清除,因此只列出神秘HEX數值。

cat hpmud_read_channel_18.dump
<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wscn="http://tempuri.org/wscn.xsd"><SOAP-ENV:Body><wscn:CancelJobResponse><succeeded>false</succeeded></wscn:CancelJobResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>


cat hpmud_read_channel_19.dump
0

前面已經知道,多出的部份就只是buffer沒清除,因此只列出神秘HEX數值。

write解析:
雖然從XML看得出來,明顯很單純,但我們一樣用瀏覽器來看看,如下:

這裡訊息很簡單,就只有CancelJob和ScanIdentifier。
裡面帶的參數,就是前面bb_start_scan裡面帶的scanjob。

所以這裡合理的懷疑,
前面bb_start_scan,除了送出Scan參數外,
會對事務機發出一個掃描工作的request。

當掃描工作結束時,也就是這裡bb_end_scan,
會對事務機發出取消掃描工作的request,
通知事務機,掃描工作已結束或已完成,
事務機應該會在內部把這項掃描工作相關的資料結構刪除。

read解析:
同樣用瀏覽器看看,如下:

這裡可以看到,回傳的參數也很簡單,就只有successed。

這裡的false我不確定是固定回傳false,
還是因為我是測試,所以沒有成功取消。

HPLIP bb-soap解析 - 3 - bb_start_scan - 上集

前言:
接續前篇,通過整個flow的拆解和bb_open內容的解析,
我們大致可以知道CM1015的溝通過程。

針對bb_start_scan,我考慮分成上、下2集,
上集可以先po,下集我不確定能不能po得成,因為目前還沒有參透。

因此,po的順序會是:
  • bb_start_scan上集 
  • bb_end_page 
  • bb_end_scan
最後再回頭看能不能po得出bb_start_scan。

bb_start_scan和hpmud動作流程:
  • bb_open
    • hpmud_channel_open()
    • hpmud_channel_write()
    • hpmud_channel_write()
    • hpmud_channel_read()
    • hpmud_channel_read()
    • hpmud_channel_read()
    • hpmud_channel_read()
    • hpmud_channel_close()
  • bb_start_scan
    • hpmud_channel_open()
    • hpmud_channel_write()
    • hpmud_channel_write()
    • hpmud_channel_write()
    • hpmud_channel_write()
    • hpmud_channel_read()
    • hpmud_channel_read()
    • hpmud_channel_read()
    • hpmud_channel_read()
    • hpmud_channel_read()
    • hpmud_channel_read()
    • hpmud_channel_read()
    • hpmud_channel_read()
    • hpmud_channel_read()
    • hpmud_channel_read()
    • hpmud_channel_read()
  • bb_get_parameters
  • bb_get_parameters
  • bb_end_page
    • hpmud_channel_close()
  • bb_end_scan
    • hpmud_channel_open()
    • hpmud_channel_write()
    • hpmud_channel_write()
    • hpmud_channel_write()
    • hpmud_channel_write()
    • hpmud_channel_read()
    • hpmud_channel_read()
    • hpmud_channel_read()
    • hpmud_channel_read()
    • hpmud_channel_close()
      • bb_close
      • bb_unload
      這裡我們注意到紅字標示的部份,也就是hpmud_channel_open/hpmud_channel_close的部份。

      我們會發現,bb_start_scan和其他幾個bb function的特異之處,
      bb_start_scan只有做hpmud_channel的open,但並沒有close,
      它實際的close動作是到bb_end_page才做。

      bb_start_scan溝通內容:
      照例,我們打印出bb_start_scan的溝通內容,bb_start_scan有4個write,和一堆read,
      上集我們只印出前面3個,
      後面的我還看不懂,而且內容大部分應該是掃描出的圖片內容,
      我就不列了。

      內容:
      write:
      cat hpmud_write_channel_3.dump
      POST / HTTP/1.1
      Host: http:0
      User-Agent: gSOAP/2.7
      Content-Type: application/soap+xml; charset=utf-8
      Transfer-Encoding: chunked
      Connection: close
      
      

      cat hpmud_write_channel_4.dump
      54f

      cat hpmud_write_channel_5.dump
      <?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wscn="http://tempuri.org/wscn.xsd"><SOAP-ENV:Body><wscn:InitiateScanRequest><ScanTicket><JobDescription><JobName>scanjob 10153</JobName><JobOriginatingUsername>Eric Cartman</JobOriginatingUsername></JobDescription><DocumentParameters><Format>scanJFIF</Format><InputSource>scanPlaten</InputSource><ContentType>scanAuto</ContentType><DocumentCompression><CompressionType>scanJPEG</CompressionType><JPEGQualityFactor>10</JPEGQualityFactor></DocumentCompression><Contrast>0</Contrast><Brightness>0</Brightness><ScanRegion><ScanRegionXOffset>0</ScanRegionXOffset><ScanRegionYOffset>0</ScanRegionYOffset><ScanRegionWidth>8499</ScanRegionWidth><ScanRegionHeight>11689</ScanRegionHeight></ScanRegion><ColorProcessing>scanGrayScale8</ColorProcessing><Resolution><ResolutionWidth>75</ResolutionWidth><ResolutionHeight>75</ResolutionHeight></Resolution><PadImage>true</PadImage><GammaCorrection>2.2</GammaCorrection></DocumentParameters></ScanTicket><DestinationID>PC</DestinationID><ScanIdentifier>linux-rocks</ScanIdentifier></wscn:InitiateScanRequest></SOAP-ENV:Body></SOAP-ENV:Envelope>

      cat hpmud_write_channel_6.dump
      0
      
      

      read:
      cat hpmud_read_channel_5.dump
      HTTP/1.1 200 OK
      Server: gSOAP/2.7
      Content-Type: application/dime
      Transfer-Encoding: chunked
      Connection: close
      
      

      cat hpmud_read_channel_6.dump
      800
      1.1 200 OK
      Server: gSOAP/2.7
      Content-Type: application/dime
      Transfer-Encoding: chunked
      Connection: close
      
      

      cat hpmud_read_channel_7.dump
       )▒cid:id0http://schemas.xmlsoap.org/soap/envelope/
      
      linux-rocksid1image/jpeg▒▒▒▒JFIF▒▒C
       $.' ",#(7),01444'9=82<.342▒▒
                                  l}▒▒
      
      ...............
      
      HEX表示:

      write解析:
      送給事務機的XML內容訊息很多,原則上就是提供事務機掃描的參數,
      但這邊有幾個訊息是重點,而且有藏彩蛋,哈.....作者還真是幽默啊......

      一堆不好看,我們把這串另存成XML,用瀏覽器打開看看,如下:

      這裡注意到,裡面除了掃描資訊外,有幾個重點:
      • JobName
      • JobOriginatingUsername
      • DestinationID
      • ScanIdentifier
      這幾條看起來並不像是掃描參數,其中JobName是關鍵,會在後面其他function使用到。

      作者的幽默感來自於JobOriginatingUsername的名稱Eric Cartman,這是誰?
      是作者本人嗎?還是描述什麼?Google看看......
      Google找到他......

      read解析:
      read的內容我還沒搞懂,把目前知道的部份po出來。

      我們從SOAP的HTTP Header理解,從Content-Type: application/dime來看,
      我們可以知道這是一個application/dime類型的資料,
      Google後得知,SOAP有2種夾帶附件的資料格式:
      • MIME
      • DIME
      這裡使用了SOAP DIME做為傳遞的資料格式。

      目前我對SOAP DIME還不清楚,還在解譯中,僅把我找到的參考資料列出,
      其他等解譯後,下集再寫。

      SOAP DIME參考:

      JPEG格式參考:
      http://en.wikipedia.org/wiki/JPEG_File_Interchange_Format
      http://bbs.csdn.net/topics/190036200
      上述2個JPEG參考可以知道,JPEG Header的最開頭是
      FF D8 FF E0
      • FF D8
        • 表示圖片開頭
      • FF E0
        • 表示JPEG APP0的開頭

      HPLIP bb-soap解析 - 2 - bb_open

      前言:
      接續前篇,在前篇大致知道了整個CM1015掃描的flow,
      搭配AAA的印出的訊息, 我們可以知道bb_soap幾個function和hpmud的呼叫關聯。

      進一步搭配從hpmud_read和hpmud_write寫出的dump內容,
      我們可以知道它們溝通的訊息內容。

       這篇,前半段會簡單解析bb_soap和hpmud的動作,
      然後這篇重點會針對bb_open進行描述,
      原則上,bb_open動作知道了,我目前認為和CM1015的溝通,就大致清楚了。

      bb_soap和hpmud動作:
      由前一篇的幾個dump,加上bb_soap整個flow,拆解對照後,可以得到下面的動作流程:
      • bb_open
        • hpmud_channel_open()
        • hpmud_channel_write()
        • hpmud_channel_write()
        • hpmud_channel_read()
        • hpmud_channel_read()
        • hpmud_channel_read()
        • hpmud_channel_read()
        • hpmud_channel_close()
      • bb_start_scan
        • hpmud_channel_open()
        • hpmud_channel_write()
        • hpmud_channel_write()
        • hpmud_channel_write()
        • hpmud_channel_write()
          • 這裡看AAA訊息,中間有摻雜許多function動作,甚至bb_get_parmameters呼叫時,都還有read動作,目前相當懷疑下面的read是在額外的thread處理的
        • hpmud_channel_read()
        • hpmud_channel_read()
        • hpmud_channel_read()
        • hpmud_channel_read()
        • hpmud_channel_read()
        • hpmud_channel_read()
        • hpmud_channel_read()
        • hpmud_channel_read()
        • hpmud_channel_read()
        • hpmud_channel_read()
        • hpmud_channel_read()
      • bb_get_parameters
      • bb_get_parameters
      • bb_end_page
        • hpmud_channel_close()
      • bb_end_scan
        • hpmud_channel_open()
        • hpmud_channel_write()
        • hpmud_channel_write()
        • hpmud_channel_write()
        • hpmud_channel_write()
        • hpmud_channel_read()
        • hpmud_channel_read()
        • hpmud_channel_read()
        • hpmud_channel_read()
        • hpmud_channel_close()
          • bb_close
          • bb_unload
          由這段列出的流程中可以看出來,
          bb_open是第1個關卡,裡面包含了完整的open/write/read/close動作,
          下段開始,我們就進入本篇主題,將bb_open內容列出並解析。

          bb_open解析:
          前面我們得知,bb_open內包含了2個write,4個read,這邊我們按順序列出內容:
          write:
          cat hpmud_write_channel_1.dump
          POST / HTTP/1.1
          Host: http:0
          User-Agent: gSOAP/2.7
          Content-Type: application/soap+xml; charset=utf-8
          Transfer-Encoding: chunked
          Connection: close
          
          
          cat hpmud_write_channel_2.dump
          19E
          <?xml version="1.0" encoding="UTF-8"?>
          <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wscn="http://tempuri.org/wscn.xsd"><SOAP-ENV:Body><wscn:GetScannerElements></wscn:GetScannerElements></SOAP-ENV:Body></SOAP-ENV:Envelope>
          0
          
          

          read:
          cat hpmud_read_channel_1.dump
          HTTP/1.1 200 OK
          Server: gSOAP/2.7
          Content-Type: application/soap+xml; charset=utf-8
          Transfer-Encoding: chunked
          Connection: close
          
          

          cat hpmud_read_channel_2.dump
          7CB
          1.1 200 OK
          Server: gSOAP/2.7
          Content-Type: application/soap+xml; charset=utf-8
          Transfer-Encoding: chunked
          Connection: close
          
          

          cat hpmud_read_channel_3.dump
          <?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wscn="http://tempuri.org/wscn.xsd"><SOAP-ENV:Body><wscn:ScanElements><ScannerConfiguration><DeviceSettings><FormatSupported xsi:type="SOAP-ENC:Array" SOAP-ENC:itemType="xsd:eDocumentFormat" SOAP-ENC:arraySize="3"><item>scanDIB</item><item>scanJFIF</item><item>scanMMRf</item></FormatSupported><CompressionSupported xsi:type="SOAP-ENC:Array" SOAP-ENC:itemType="xsd:eCompressionType" SOAP-ENC:arraySize="3"><item>scanNoCompression</item><item>scanJPEG</item><item>scanMMR</item></CompressionSupported><JPEGQualityFactorSupported>false</JPEGQualityFactorSupported><ContentSupported xsi:type="SOAP-ENC:Array" SOAP-ENC:itemType="xsd:eDocumentType" SOAP-ENC:arraySize="4"><item>scanAuto</item><item>scanText</item><item>scanMixed</item><item>scanPhoto</item></ContentSupported><DocumentSizeAutoDetectSupported>true</DocumentSizeAutoDetectSupported></DeviceSettings><Platen><ColorSupported xsi:type="SOAP-ENC:Array" SOAP-ENC:itemType="xsd:eColorEntryType" SOAP-ENC:arraySize="4"><item>scanBlackandWhite1</item><item>scanGrayScale8</item><item>scanRGB24</item><item>scanRGB48</item></ColorSupported><PlatenMinimumSize><DimensionsWidth>500</DimensionsWidth><DimensionsHeight>300</DimensionsHeight></PlatenMinimumSize><PlatenMaximumSize><DimensionsWidth>8500</DimensionsWidth><DimensionsHeight>11690</DimensionsHeight></PlatenMaximumSize><PlatenOpticalResolution><ResolutionWidth>1200</ResolutionWidth><ResolutionHeight>1200</ResolutionHeight></PlatenOpticalResolution></Platen></ScannerConfiguration><ScannerStatus><ScannerCurrentTime>0001-01-01T01:01:01Z</ScannerCurrentTime><ScannerState>scanIdle</ScannerState><ActiveCondition>scanNone</ActiveCondition></ScannerStatus></wscn:ScanElements></SOAP-ENV:Body></SOAP-ENV:Envelope>

          cat hpmud_read_channel_4.dump
          0
          
          ersion="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wscn="http://tempuri.org/wscn.xsd"><SOAP-ENV:Body><wscn:ScanElements><ScannerConfiguration><DeviceSettings><FormatSupported xsi:type="SOAP-ENC:Array" SOAP-ENC:itemType="xsd:eDocumentFormat" SOAP-ENC:arraySize="3"><item>scanDIB</item><item>scanJFIF</item><item>scanMMRf</item></FormatSupported><CompressionSupported xsi:type="SOAP-ENC:Array" SOAP-ENC:itemType="xsd:eCompressionType" SOAP-ENC:arraySize="3"><item>scanNoCompression</item><item>scanJPEG</item><item>scanMMR</item></CompressionSupported><JPEGQualityFactorSupported>false</JPEGQualityFactorSupported><ContentSupported xsi:type="SOAP-ENC:Array" SOAP-ENC:itemType="xsd:eDocumentType" SOAP-ENC:arraySize="4"><item>scanAuto</item><item>scanText</item><item>scanMixed</item><item>scanPhoto</item></ContentSupported><DocumentSizeAutoDetectSupported>true</DocumentSizeAutoDetectSupported></DeviceSettings><Platen><ColorSupported xsi:type="SOAP-ENC:Array" SOAP-ENC:itemType="xsd:eColorEntryType" SOAP-ENC:arraySize="4"><item>scanBlackandWhite1</item><item>scanGrayScale8</item><item>scanRGB24</item><item>scanRGB48</item></ColorSupported><PlatenMinimumSize><DimensionsWidth>500</DimensionsWidth><DimensionsHeight>300</DimensionsHeight></PlatenMinimumSize><PlatenMaximumSize><DimensionsWidth>8500</DimensionsWidth><DimensionsHeight>11690</DimensionsHeight></PlatenMaximumSize><PlatenOpticalResolution><ResolutionWidth>1200</ResolutionWidth><ResolutionHeight>1200</ResolutionHeight></PlatenOpticalResolution></Platen></ScannerConfiguration><ScannerStatus><ScannerCurrentTime>0001-01-01T01:01:01Z</ScannerCurrentTime><ScannerState>scanIdle</ScannerState><ActiveCondition>scanNone</ActiveCondition></ScannerStatus></wscn:ScanElements></SOAP-ENV:Body></SOAP-ENV:Envelope>

          由上述可以知道下列資訊:

          • 傳送時
            • 傳送的是SOAP格式的HTTP + XML,中間會帶後續資料長度的神秘HEX數值
          • 接收時
            • 第1條是SOAP的HTTP
            • 第2條看起來,內容只有神秘HEX數值,其他應該只是buffer沒清除
            • 第3條是SOAP的XML,也就是實際事務機回應的內容
            • 第4條看起來,內容只是神秘HEX數值0,標示後面沒資料,同樣的,buffer沒清除

          內容我沒有細看,
          粗淺看起來,事務機回覆的內容應該是描述事務機的能力,和支援的項目、格式。

          傳送部份看起來只是制式化的訊息,應該是不用特別處理,
          要掃描時,固定按這個訊息送即可,應該不用特別處理。

          至於回覆的資料要不要parse,目前我還不清楚,可能要看SANE需不需要這些資訊。

          結論:
          bb_open看起來,應該就跟hello沒啥不同,
          大致就是跟事務機通知一下,取得事務機狀態,
          確定事務機目前可以準備掃描工作而已。

          傳遞的訊息雖然是XML,但應該都是制式化的,
          不用特別parse處理,應該都是千篇一律。

          總之,bb_open就是按上述訊息丟,大概確定收到訊息和上面差不多即可。

          2015年1月24日

          HPLIP bb-soap解析 - 1

          前言:
          接續前面2篇網樂通Scanner Server文章
          這篇開始,會將我針對HP Color LaserJet CM1015掃描功能的Close Code解析,
          因為目前尚未破解,所以這系列會不會有完結篇不確定,
          解析到哪,又剛好有空、有興趣,就po到哪。

          背景資訊:
          HP Color LaserJet CM1015這台HP事務機功能如下:
          • USB介面
          • 有彩色掃描功能
          • 有彩色列印功能
          • 是雷射列印
          這台事務機在Linux上,從HPLIP 2.8.10開始支援,Linux上提供
          • 黑白、彩色掃描
          • 黑白、彩色列印
          • 印表機狀態資訊
          相關資訊可以參考:
          HP Color LaserJet cm1015 Multifunction Printer

          而根據HPLIP 2.8.10的Release時間回推,這台應該是在2008年的款式,
          我的購買時間我已經忘了。

          HPLIP本身雖然是OpenSource的專案,但HP並沒有將全部的檔案都OpenSource,
          HPLIP在大部分機種上要求要安裝Driver Plugin,
          這個Driver Plugin提供了這些機種需要的Close Code Library,
          它們包括:
          • bb_marvell-x86_32.so
          • bb_marvell-x86_64.so
          • bb_soapht-x86_32.so
          • bb_soapht-x86_64.so
          • bb_soap-x86_32.so
          • bb_soap-x86_64.so
          • fax_marvell-x86_32.so
          • fax_marvell-x86_64.so
          • hbpl1-x86_32.so
          • hbpl1-x86_64.so
          • lj-x86_32.so
          • lj-x86_64.so
          以CM1015來說,CM1015需要bb_soap。

          從程式碼看起來,
          HP不同機種使用了不同的Protocol,不同Protocol使用不同的Close Code Library檔案,
          CM1015的Protocol看起來只是單純的SOAP,使用的是bb_soap。

          怎麼知道是用bb_soap?
          因為我在網樂通上手動把Driver Plugin放上去,執行scanimage後,
          在/var/log/syslog出現類似如下:
          scanimage: common/utils.c 188: unable to load library /usr/local/hplip/share/hplip/scan/plugins/bb_soap.so: /usr/local/hplip/share/hplip/scan/plugins/bb_soap.so: wrong ELF class: ELFCLASS32

          當然,這是示意訊息,原始錯誤訊息印象中是Segfault,但它的確標明了使用的library。

          因為HP只將Protocol Close,掃描的上層是SANE,下層是HPMUD + libusb,示意圖如下:
          所以透過修改程式,
          可以在HPMUD和sane-hpaio backend加上printf,
          就能知道它的呼叫flow,儘管它沒有Open,
          也能知道傳遞什麼給事務機,步驟是什麼。

          解析開始:
          建立環境:
          建個VM,USB map進去,按網樂通類似步驟把HPLIP、SANE、CUPS build出來。

          找程式起始點:
          首先先找hpaio backend的呼叫點,找到是在
          hplip-3.14.10/scan/sane/

          繼續找bb_soap的呼叫點,找到主要是
          hplip-3.14.10/scan/sane/soap.c

          再來找hpmud,找到是
          hplip-3.14.10/io/hpmud/

          主要應該是
          hplip-3.14.10/io/hpmud/hpmud.c

          至於hplip-3.14.10/io/mudext不用管它,看裡面有註明是給python用的library。

          查看程式,修改程式碼,加printf:
          看soap.c,看到
          • ps->bb_open = get_library_symbol(ps->bb_handle, "bb_open")
          • ps->bb_close = get_library_symbol(ps->bb_handle, "bb_close")
          • ps->bb_get_parameters = get_library_symbol(ps->bb_handle, "bb_get_parameters")
          • ps->bb_is_paper_in_adf = get_library_symbol(ps->bb_handle, "bb_is_paper_in_adf")
          • ps->bb_start_scan = get_library_symbol(ps->bb_handle, "bb_start_scan")
          • ps->bb_end_scan = get_library_symbol(ps->bb_handle, "bb_end_scan")
          • ps->bb_get_image_data = get_library_symbol(ps->bb_handle, "bb_get_image_data")
          • ps->bb_end_page = get_library_symbol(ps->bb_handle, "bb_end_page")
          非常好,它將bb_soap的所有function都列好了,不用辛苦找。
          接著在這些呼叫點前後加上printf,把原本的DBG改成printf。

          hpmud裡面也是,把DBG都改成printf,看到open、close、read、write,都加上printf。

          重新編譯後,執行
          scanimage > AAA

          看看AAA裡面有什麼,如下:
          [10153] hpmud_probe_devices() bus=3
          sane_hpaio_open(/usb/HP_Color_LaserJet_CM1015?serial=00CNF87DL012)
          io_mode = 1
          [10153,13449,0,0,0,0] hpmud_device_open() uri=hp:/usb/HP_Color_LaserJet_CM1015?serial=00CNF87DL012 iomode=1
          bb_open(session)
          [10153] hpmud_channel_open() dd=1 name=HP-SOAP-SCAN
          [10153] hpmud_channel_write() dd=1 cd=19 buf=0x7fca030fd380 size=154 sectime=45
          [10153] hpmud_channel_write() dd=1 cd=19 buf=0x7fca030fd458 size=426 sectime=45
          [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd7b5c8 size=4096 sectime=45
          [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd7b5c8 size=4096 sectime=45
          [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd7b5c8 size=4096 sectime=45
          [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd7b5c8 size=4096 sectime=45
          [10153] hpmud_channel_close() dd=1 cd=19
          bb_open end
          sane_hpaio_control_option (option=mode action=auto value=na)
          sane_hpaio_control_option (option=resolution action=auto value=na)
          sane_hpaio_control_option (option=brightness action=auto value=na)
          sane_hpaio_control_option (option=contrast action=auto value=na)
          sane_hpaio_control_option (option=compression action=auto value=na)
          sane_hpaio_control_option (option=jpeg-quality action=auto value=na)
          sane_hpaio_control_option (option=tl-x action=auto value=na)
          sane_hpaio_control_option (option=tl-y action=auto value=na)
          sane_hpaio_control_option (option=br-x action=auto value=na)
          sane_hpaio_control_option (option=br-y action=auto value=na)
          sane_hpaio_get_option_descriptor(option=option-cnt)
          sane_hpaio_control_option (option=option-cnt action=get value=14)
          sane_hpaio_get_option_descriptor(option=option-cnt)
          sane_hpaio_control_option (option=option-cnt action=get value=14)
          sane_hpaio_get_option_descriptor(option=mode-group)
          sane_hpaio_get_option_descriptor(option=mode)
          sane_hpaio_get_option_descriptor(option=resolution)
          sane_hpaio_get_option_descriptor(option=advanced-group)
          sane_hpaio_get_option_descriptor(option=brightness)
          sane_hpaio_get_option_descriptor(option=contrast)
          sane_hpaio_get_option_descriptor(option=compression)
          sane_hpaio_get_option_descriptor(option=jpeg-quality)
          sane_hpaio_get_option_descriptor(option=geometry-group)
          sane_hpaio_get_option_descriptor(option=tl-x)
          sane_hpaio_get_option_descriptor(option=tl-y)
          sane_hpaio_get_option_descriptor(option=br-x)
          sane_hpaio_get_option_descriptor(option=br-y)
          sane_hpaio_control_option (option=br-x action=get value=14149222)
          sane_hpaio_control_option (option=tl-x action=get value=0)
          sane_hpaio_control_option (option=br-y action=get value=19459342)
          sane_hpaio_control_option (option=tl-y action=get value=0)
          sane_hpaio_control_option (option=tl-x action=get value=0)
          sane_hpaio_get_option_descriptor(option=br-x)
          sane_hpaio_control_option (option=br-x action=set value=14149222)
          sane_hpaio_control_option (option=tl-y action=get value=0)
          sane_hpaio_get_option_descriptor(option=br-y)
          sane_hpaio_control_option (option=br-y action=set value=19459342)
          sane_hpaio_start()
          bb_start_scan
          [10153] hpmud_channel_open() dd=1 name=HP-SOAP-SCAN
          [10153] hpmud_channel_write() dd=1 cd=19 buf=0x7fca030fd380 size=154 sectime=45
          [10153] hpmud_channel_write() dd=1 cd=19 buf=0x7fffda5ca8f0 size=5 sectime=1
          [10153] hpmud_channel_write() dd=1 cd=19 buf=0x7fffda5ca910 size=1359 sectime=1
          [10153] hpmud_channel_write() dd=1 cd=19 buf=0x7fca030fd8a9 size=7 sectime=1
          [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45
          [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45
          [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45
          bb_start_scan end
          bb_get_parameters
          bb_get_parameters end
          set traits iPixelsPerRow=632 iBitsPerPixel=8 lNumRows=876 iComponentsPerPixel=1
          cnt=1024 index=0 input=0xd68e10 inputAvail=1024 inputUsed=1024 inputNextPos=1024 output=(nil) outputAvail=0 outputThisPos=0
          [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45
          cnt=1024 index=0 input=0xd68e10 inputAvail=1024 inputUsed=1024 inputNextPos=2048 output=(nil) outputAvail=0 outputThisPos=0
          cnt=1024 index=0 input=0xd68e10 inputAvail=1024 inputUsed=1024 inputNextPos=3072 output=(nil) outputAvail=0 outputThisPos=0
          [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45
          [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45
          cnt=1024 index=0 input=0xd68e10 inputAvail=1024 inputUsed=1024 inputNextPos=4096 output=(nil) outputAvail=0 outputThisPos=0
          cnt=1024 index=0 input=0xd68e10 inputAvail=1024 inputUsed=1024 inputNextPos=5120 output=(nil) outputAvail=0 outputThisPos=0
          [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45
          cnt=1024 index=0 input=0xd68e10 inputAvail=1024 inputUsed=1024 inputNextPos=6144 output=(nil) outputAvail=0 outputThisPos=0
          cnt=1024 index=0 input=0xd68e10 inputAvail=1024 inputUsed=1024 inputNextPos=7168 output=(nil) outputAvail=0 outputThisPos=0
          [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45
          [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45
          cnt=1024 index=0 input=0xd68e10 inputAvail=1024 inputUsed=1024 inputNextPos=8192 output=(nil) outputAvail=0 outputThisPos=0
          cnt=1024 index=0 input=0xd68e10 inputAvail=1024 inputUsed=1024 inputNextPos=9216 output=(nil) outputAvail=0 outputThisPos=0
          [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45
          cnt=1024 index=0 input=0xd68e10 inputAvail=1024 inputUsed=1024 inputNextPos=10240 output=(nil) outputAvail=0 outputThisPos=0
          [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45
          cnt=450 index=0 input=0xd68e10 inputAvail=450 inputUsed=450 inputNextPos=10690 output=(nil) outputAvail=0 outputThisPos=0
          cnt=0 index=0 input=(nil) inputAvail=0 inputUsed=0 inputNextPos=10690 output=(nil) outputAvail=0 outputThisPos=0
          act traits iPixelsPerRow=637 iBitsPerPixel=1 lNumRows=876 iComponentsPerPixel=1
          bb_getparameters
          bb_getparameters end
          sane_hpaio_get_parameters(): format=0, last_frame=1, lines=876, depth=1, pixels_per_line=637, bytes_per_line=80
          P4
          # SANE data follows
          637 876
          sane_hpaio_read() handle=0xd68720 data=0xd7ba40 maxLength=32768
          cnt=0 index=0 input=(nil) inputAvail=0 inputUsed=0 inputNextPos=10690 output=0xd7ba40 outputAvail=32768 outputThisPos=0
          -sane_hpaio_read() output=0xd7ba40 bytes_read=32768 maxLength=32768 status=0
          ▒       ▒sane_hpaio_read() handle=0xd68720 data=0xd7ba40 maxLength=32768
          cnt=0 index=0 input=(nil) inputAvail=0 inputUsed=0 inputNextPos=10690 output=0xd7ba40 outputAvail=32768 outputThisPos=32768
          -sane_hpaio_read() output=0xd7ba40 bytes_read=32768 maxLength=32768 status=0
          ▒       ▒sane_hpaio_read() handle=0xd68720 data=0xd7ba40 maxLength=32768
          cnt=0 index=0 input=(nil) inputAvail=0 inputUsed=0 inputNextPos=10690 output=0xd7ba40 outputAvail=32768 outputThisPos=65536
          -sane_hpaio_read() output=0xd7ba40 bytes_read=4544 maxLength=32768 status=0
          sane_hpaio_read() handle=0xd68720 data=0xd7ba40 maxLength=32768
          cnt=0 index=0 input=(nil) inputAvail=0 inputUsed=0 inputNextPos=10690 output=0xd7ba40 outputAvail=32768 outputThisPos=70080
          bb_end_page
          [10153] hpmud_channel_close() dd=1 cd=19
          bb_end_page end
          -sane_hpaio_read() output=0xd7ba40 bytes_read=0 maxLength=32768 status=5
          sane_hpaio_cancel()
          bb_end_scan
          [10153] hpmud_channel_open() dd=1 name=HP-SOAP-SCAN
          [10153] hpmud_channel_write() dd=1 cd=19 buf=0x7fca030fd380 size=154 sectime=45
          [10153] hpmud_channel_write() dd=1 cd=19 buf=0x7fffda5cb190 size=5 sectime=1
          [10153] hpmud_channel_write() dd=1 cd=19 buf=0x7fffda5cb1b0 size=442 sectime=1
          [10153] hpmud_channel_write() dd=1 cd=19 buf=0x7fca030fd8a9 size=7 sectime=1
          [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45
          [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45
          [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45
          [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45
          [10153] hpmud_channel_close() dd=1 cd=19
          bb_end_scan end
          sane_hpaio_close()
          bb_close
          close end bb_unload
          bb unload end
          [10153] hpmud_device_close() dd=1
          這整段一長串,會注意到:
          1. bb_soap function呼叫流程,如下:
          • bb_open
          • bb_start_scan
          • bb_get_parameters
          • bb_get_parameters
          • bb_end_page
          • bb_end_scan
          • bb_close
          • bb_unload
          2. 和USB的動作都使用下列這些function:
          • hpmud_channel_open
          • hpmud_channel_close
          • hpmud_channel_read
          • hpmud_channel_write
          查看hpmud傳輸內容:
          修改hpmud.c,在hpmud_channel_read和hpmud_channel_write裡面加上寫檔,
          讀取和寫入的資料統統寫到檔案中,我是如下:
          讀取部份:
          hpmud_read_channel_1.dump
          hpmud_read_channel_2.dump
          .....

          寫入部份:
          hpmud_write_channel_1.dump
          hpmud_write_channel_2.dump
          .....

          精彩的來了,我們看看它到底傳什麼給事務機,又從事務機收什麼回來?
          cat /tmp/hpmud_write_channel_1.dump
          POST / HTTP/1.1
          Host: http:0
          User-Agent: gSOAP/2.7
          Content-Type: application/soap+xml; charset=utf-8
          Transfer-Encoding: chunked
          Connection: close
          

          cat /tmp/hpmud_write_channel_2.dump
          19E
          
          <?xml version="1.0" encoding="UTF-8"?>
          <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wscn="http://tempuri.org/wscn.xsd"><SOAP-ENV:Body><wscn:GetScannerElements></wscn:GetScannerElements></SOAP-ENV:Body></SOAP-ENV:Envelope>
          0
          

          cat /tmp/hpmud_read_channel_1.dump
          HTTP/1.1 200 OK
          Server: gSOAP/2.7
          Content-Type: application/soap+xml; charset=utf-8
          Transfer-Encoding: chunked
          Connection: close
          

          cat /tmp/hpmud_read_channel_2.dump
          7CB
          1.1 200 OK
          Server: gSOAP/2.7
          Content-Type: application/soap+xml; charset=utf-8
          Transfer-Encoding: chunked
          Connection: close
          

          dump出來的訊息好面熟,看起來很像是HTTP和XML啊.....
          Google soap,查到:
          SOAP Wiki

          原來SOAP是以HTTP + XML為核心的物件描述語言,
          而CM1015以SOAP做為溝通的通訊協定。

          這裡有個部份我一開始想不通,它每份資料的斷點在哪裡?為何會出現19E這樣的神秘字串?
          後來比對hpmud_read_channel和hpmud_write_channel的動作,搭配神秘數字0,
          終於搞清楚它神秘字串是表示後面還有多少字要傳送或接收,
          當這段資料後面沒東西時,就傳遞個0,表示後面沒資料,
          有資料時,神秘字串是後一筆資料的字串長度的HEX表示。

          以19E為例,19E表示:
          <?xml version="1.0" encoding="UTF-8"?>
          <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wscn="http://tempuri.org/wscn.xsd"><SOAP-ENV:Body><wscn:GetScannerElements></wscn:GetScannerElements></SOAP-ENV:Body></SOAP-ENV:Envelope>
          
          這整段的資料長度。

          本篇先到此為止,後續再戰。

          2015年1月19日

          網樂通 - HPLIP、CUPS、SANE Scanner Server - HP Color LaserJet CM1015,功敗垂成

          前言:
          去年過年的目標,現在重新開始,但目前仍舊失敗,
          失敗原因在HPLIP部份程式碼沒有OpenSource。
          目前我還在努力,看有沒有辦法把沒有OpenSource的部份自己實做出來。

          功能目標:
          在網樂通上,透過USB連接HP Color LaserJet CM1015,
          達成掃描功能,並進一步做到掃描伺服器。
          也許會問,列印呢?列印都沒達成,做什麼掃描?
          事實上,透過p910nd,應該是能夠輕鬆做到列印,只是還沒實際印過而已。

          實做目標:
          在網樂通上實做出SANE + HPLIP,透過網樂通直接下指令掃描,
          或透過SANE Scanner Server,網路掃描。

          HPLIP、CUPS、SANE需求:

          事實上,HPLIP依賴CUPS和SANE,
          除非單純build HPIJS,否則CUPS是必要的(掃描功能也需要),
          如果要使用掃描功能,SANE是必要的。

          而CUPS、SANE、HPLIP這三者,都需要libusb,它們都使用libusb當作USB溝通的底層。
          libusb可以使用libusb1.0或libusb,我這邊使用libusb1.0。

          SANE還需要jpeg library,tiff library可以裝也可以不裝。
          相依關係如圖:


          實做平台:
          最終使用 網樂通Debian wheezy。

          我實際上sh4twbox、archlinux、debian這3個平台都嘗試移植,
          但sh4twbox、archlinux都遇到問題,導致移植失敗。

          網樂通移植平台限制:
          sh4twbox:
          sh4twbox是我原本最期望使用的平台,也是我花費最多心力的平台,
          同樣,最後功敗垂成。

          sh4twbox的本體實際上是STLinux,但因為原廠不再支援STLinux 2.3,
          會發現STLinux 2.4版的libc使用的是2.14版,
          但網樂通上的libc是2.10版,
          網樂通和開發環境的版本不合,會導致CrossCompiler編譯的程式,執行時可能會有問題。
          另外,STLinux 2.4 CrossCompiler環境,原廠並沒有把libtool和pkg-config的路徑問題做修正,
          因此裝在CrossCompiler環境的library,經常會link到host的x86 library,
          造成過程經常出現問題。

          最後我的解決方法:
          針對pkg-config和libtool問題,
          針對configure出錯時,直接修改configure,讓它指定到正確的路徑,
          同時使用CFLAGS、CPPFLAGS、CXXFLAGS、LIBS這些環境變數,
          強制指定正確library的路徑和正確include的路徑。

          針對libc版本不合的問題,
          我注意到ST Linux 2.4 CrossCompiler的路徑中,有提供static library,
          我強制將shared library( .so檔案)改名,讓程式和library編譯時強制使用靜態編譯,
          編譯出來後,在網樂通上執行看看,看有沒有link到shared library。

          這方式最終看起來,好像能動,但Debug異常麻煩,不確定問題在哪。

          archlinux:
          我按照網路上的教學安裝gcc,網路上說需要另外下載gcc,覆蓋掉archlinux套件安裝的版本,
          我照著做,但在編譯時,會出現錯誤,上網Google結果都是要你重新安裝gcc,
          這我懷疑網上版的gcc和系統的部份library可能不合,後續放棄沒繼續了。

          Debian:
          不愧是Debian,套件夠完整,但系統也實在是肥很多。
          光下指令,就能感受到反應速度明顯比archlinux、sh4twbox慢,
          很可能預設啟動的service太多造成的。

          但Debian最大的好處是,套件庫齊全,針對CUPS、HPLIP、SANE的編譯,
          相依的library幾乎都直接有套件裝,不需要另外自己編譯,
          就library編譯部份省去不少功夫,但網樂通本地編譯,
          真的是等.....等......等......等......等.....

          過程:
          Debian上需要另外編譯CUPS、SANE、HPLIP的主要原因是:
          1. 這幾個套件在Debian上沒有提供套件
          2. 這幾個程式的相依套件庫太多,很多相依套件在sh4平台上沒有提供,這尤其發生在HPLIP上

          因此,我編譯時,只使用幾個功能,相依套件盡量少,最後使用下面這些:
          • libjpeg-dev
          • libtiff-dev
          • libusb-dev
          • libusb-1.0-0-dev 
          • libtool
          • pkg-config
          • gcc
          • g++
          編譯按順序如下:
          SANE:
          1.
          下載sane-backends Source Code並解壓縮,這邊我使用sane-backends-1.0.24版。

          2.
          ./configure --prefix=/usr/local/sane-backends --enable-libusb_1_0

          3.
          make

          4.
          make install

          CUPS:
          1.
          下載CUPS Soruce Code並解壓縮,這邊我使用CUPS-1.7.5版。

          2.
          ./configure --prefix=/usr/local/cups --disable-gssapi --without-perl --without-java --disable-gnutls --enable-libusb --disable-dbus --disable-openssl --enable-libusb --disable-dbus --disable-pam --disable-avahi --with-python=no

          3.
          make

          4.
          make install

          HPLIP:
          1.
          下載hplip Source Code並解壓縮,這邊我使用hplip-3.14.10版。

          2.
          設定環境變數
          export CPPFLAGS="-I/usr/local/sane-backends/include -I/usr/local/cups/include"
          export LIBS="-L/usr/local/sane-backends/lib -lsane -L/usr/local/cups/lib -lcups"


          3.

          將SANE、CUPS Library加入系統參考路徑中

          修改/etc/ld.so.conf.d/libc.conf,修改如下:

          # libc default configuration /usr/local/lib /usr/local/cups/lib /usr/local/sane-backends/lib

          執行ldconfig

          4.
          ./configure --prefix=/usr/local/hplip --enable-lite-build --disable-doc-build --disable-gui-build --disable-fax-build --disable-dbus-build --disable-cups11-build --disable-qt4 --disable-network-build

          5.
          make

          6.
          make install

          上述HPLIP編譯,會編譯HPLIP的列印和掃描功能,其他功能全部不裝。

          7.
          複製HPLIP的hpaio檔案到sane-backends中,如下:
          cp -v /usr/local/hplip/lib/sane/libsane-hpaio.* /usr/local/sane-backends/lib/sane/

          8.
          將hpaio加入到sane-backends的搜尋檔案中
          編輯/usr/local/sane-backends/etc/sane.d/dll.conf
          最後面加入
          hpaio

          9.
          複製HPLIP的model資訊
          從HPLIP的Source Code目錄中複製data到/usr/local/hplip/share/hplip/data
          類似如下:
          cp -v -R /usr/local/printer_system/hplip-3.14.10/data /usr/local/hplip/share/hplip/data

          10.
          將HPLIP的library路徑加入到系統參考路徑中,如下修改:
          修改/etc/ld.so.conf.d/libc.conf,修改如下:
          # libc default configuration
          /usr/local/lib
          /usr/local/cups/lib
          /usr/local/sane-backends/lib
          /usr/local/hplip/lib

          執行ldconfig

          到此安裝完成,接著要Debug。

          除錯方法:
          針對SANE,可以如下除錯:
          1.
          設定環境變數,如下:
          export SANE_DEBUG_DLL="255"

          2.
          執行/usr/local/sane-backends/bin/sane-find-scanner
          如果找到Scanner,表示SANE這關過了,
          如果沒找到,請直接跳到第5步驟,看syslog。

          3.
          執行/usr/local/sane-backends/bin/scanimage -L
          如果找到Scanner,表示HPLIP第1關過了,
          如果沒找到,請直接跳到第5步驟,看syslog。

          4.
          執行/usr/local/sane-backends/bin/scanimage > /tmp/image.img,
          如果/tmp/image.img有檔案產生,表示HPLIP一切正常,
          如果有問題,會顯示錯誤。

          5.
          過程中有錯誤,可以看/var/log/syslog,裡面會列出錯誤原因。

          功敗垂成:
          我家的HP事務機是HP Color LaserJet CM1015,參考:

          它提到這段話:
          Driver Plugin Information:
          This printer REQUIRES a downloadable driver plug-in. Use hp-setup to install the printer, and to download and install the plug-in. In general, required driver plugins are required for printing support. Driver plug-ins are released under a proprietary (non-open) license and are not part of the HPLIP tarball release.

          這台事務機的Linux Driver需要HP的Driver Plugin,
          而Driver Plugin我也手動安裝了,
          但關鍵問題是,Driver Plugin裡面包裹了4個Close Code Library,
          這4個Close Code Library並非全部都需要,這跟HP印表機、掃描器、事務機型號相關,
          更明確的說,這4個是4個不同的Protocol需要的library,
          以我的CM1015而言,CM1015需要的是bb_soap這個library。

          因為這4個library只提供x86 32bits和64bits版本,
          因此無法使用在網樂通上,也無法使用在ARM平台上,
          相關討論參考:

          展望:
          HP Color LaserJet CM1015是舊式的HP事務機,
          這表示它的protocol相對單純,
          目前我透過在HPLIP Source Code加上printf的方式(在libsane-hpaio和hpmud),
          在x86機器上呼叫scanimage後,查看呼叫過程,
          試圖拆解bb_soap內的功能,
          事實上從libsane-hpaio的程式碼看起來,
          bb_soap內其實只有下列function,分別是:
          • bb_open()
          • bb_close()
          • bb_get_parameters()
          • bb_is_paper_in_adf()
          • bb_start_scan()
          • bb_end_scan()
          • bb_get_image_data()
          • bb_end_page()
          我目前應該已經解開bb_open()、bb_close()、bb_start_scan(),
          有成功看到掃描器動作,
          但我目前不清楚收到的資料哪些部份才是圖像,
          圖像和後續bb_get_image_data()、bb_end_scan()、bb_end_page()的行為還不清楚,
          我相信,
          如果我能成功破譯這些function動作,
          修改HPLIP Source Code後,就能讓網樂通成為掃描列印伺服器。

          參考資料:

          2015年1月11日

          Acer Chromebook 13 Ubuntu (Chrubuntu)

          前言:
          Google提供了我們Linux Geek一個好玩具。

          Acer在去年底推出Acer Chromebook 13這台Chromebook,
          我看了規格後覺得,這台非常適合Linux玩家,未來不知道,
          但過去要找到這樣的玩具,還台灣廠商做的,很少很少(根本是沒有啦.....)

          Acer Chromebook 13我是透過網拍買的二手機(我是12月中旬買的),
          但因為距離上市日期不長,加上它的特性,我相信機器都還很乾淨,
          要被操到硬體問題一堆,難度很高,
          在這裡要感謝賣家,用不錯的價格提供了一台好玩具。

          規格:
          Acer Chromebook 13的規格如下:
          • CPU:ARM Cortex-A15 4核心 (Nvidia Tegra K1)
          • Video:Nvidia Kepler架構192核心
          • LCD:13.3吋LED背光LCD (1366x768)
          • RAM:4GB DDR3 (不可擴充)
          • Storage:32GB eMMC
          • Webcam:前置Webcam (1280x720)
          • WiFi:802.11ac
          • Bluetooth:Bluetooth 4.0
          • Card Reader:SD-Card
          • Battery:3220 mAh
          看到第1條相信就傻了,再看第2條,更傻。
          這台Notebook,使用的是ARM處理器,而且是Nvidia出的ARM處理器,所以內含Nvidia顯示。

          這台機器非常有趣,它的真身其實是:
          Tegra-K1
          原價屋NVIDIA Jetson TK1開箱

          它是Nvidia針對行動平台出的ARM處理器,
          除了Acer Chromebook 13外,還使用在下面幾個產品上:
          此外,Nvidia提供的車用電腦開發平台,也是使用這塊Nvidia Tegra K1。


          機器問題點:
          問題1:無法安裝Windows
          Acer Chromebook 13最大的問題,正是它的特色所在,
          它使用的是Nvidia ARM處理器,因此無法在上面安裝Windows,
          這對於大部分玩家而言,就會是個大問題,
          無法安裝Windows,表示無法隨心所欲的安裝程式、系統。

          問題2:ChromeOS有夠難用
          ChromeOS的主要問題是,它全部功能都要透過網路,
          你要寫Word、Excel、PowerPoint:Google Document
          你要記事本:Google Keep
          你要儲存檔案:Google Drive
          你要看影片聽音樂:一個簡易的播放器,並整合Google Drive

          那如果現在沒有網路呢?
          你要寫Word、Excel、PowerPoint:.........
          你要記事本:..........
          你要看影片聽音樂:..........

          那不用說了,這根本就是垃圾,沒有使用者會買單的。



          當上述2個問題同時存在,你買了一台Chromebook,
          只能使用Google線上服務,離線後通通不能用,
          又不准你安裝其他作業系統,
          請問你下個動作是什麼?

          我猜:
          1. 退貨
          2. 網拍賣掉
          3. 丟角落堆灰塵

          ChromeOS的設計有其特色,但目前設計有瑕疵,實用性很糟糕,
          關於它的設計理念,我放在最下面附註。

          Linux Geek禮物:
          雖然機器有上述2個怪問題,但對於Linux Geek來說,這些問題都不是問題。

          Chromebook有2個特別計畫:
          • chrubuntu
          • crouton
          這2個計畫都能讓Chromebook不再用ChromeOS,而改用Ubuntu或其他Linux distribution。

          這2個的區別是:
          • chrubuntu:是「安裝」一個獨立的Ubuntu,開機就直接進入Ubuntu
          • crouton:是「放置」一個Ubuntu,由ChromeOS切換進Ubuntu桌面環境
          2個我都使用過了,crouton不好用,
          而且在Acer Chromebook 13上,crouton無法使用顯示晶片硬體能力,
          我自己是沒有嘗試過,國外網友的意思是,
          Nvidia K1 X11 Driver只能被載入1次,重複載入時,第2次載入無法使用硬體能力。

          目前我是使用chrubuntu的方式,系統運作相當不錯。

          Acer Chromebook 13 Linux軟體(含作業系統)支援情況:
          針對Linux軟體支援情況,我們概括簡單的按下面分類:
          • 硬體驅動與Linux Kernel
          • Linux軟體、Library與ARM

          硬體驅動與Linux Kernel:
          Acer Chromebook 13出廠就是Linux,因此內部的硬體沒有Linux驅動的問題。
          這非常難得,大部分Notebook要裝Linux,都會遇到很多驅動程式不支援或支援不好的情況,
          但在Chromebook上,不會有這樣的問題。

          額外驅動程式,
          Google有提供各Chromebook的Kernel SourceCode,額外裝置的Kernel Module SourceCode只要支援ARM,就可以編譯出Kernel Module。

          這點Google做得相當好,它針對所有Chromebook型號,有提供一整棵Kernel SourceCode Tree,
          我們可以直接根據Chromebook型號,下載到相對應的Kernel SourceCode,也有提供目前使用的config(ChromeOS預載Kernel,直接有/proc/config.gz),可以自己修改Kernel,或編譯Module。

          因為它沒有RJ-45有線網路,我另外插一張USB3.0 Gigabit網路卡,
          驅動程式直接有module可以使用,連build都不用。
          哪一張?
          USB3.0 gigabit網路卡晶片大概只有1、2家,可以直接用的是Axis的晶片,
          很神奇,Axis本業是IP Camera,但竟然業外搞了一顆少見的USB3.0 gigabit chip。

          Linux軟體、Library與ARM:
          目前Ubuntu ARM(當然應該也包括Debian ARM)的套件完整度相當高,
          除了專門針對x86的軟體(例如:wine、VM)沒有之外,
          目前使用上,還沒遇到沒提供的OpenSource軟體或Library,
          哪些叫做有提供的?
          Java、FlashPlayer(Google包在Chromebook內)、GNOME、MPlayer、VLC、Firefox、Chromium、Qt Library、GTK+ Library、python...等,常見的軟體、Library都支援。

          到目前,只遇過一套程式可以裝,但執行會Crash,是畫3D的blender。

          所以使用上幾乎沒遇到問題,目前唯一的問題是,
          它的硬解Nvidia是用OpenMAX,提供的是GStreamer模組,
          MPlayer、VLC不支援OpenMAX,目前還只能ARM軟解。

          但這台ARM四核心很強大,除了H.264不行外,MPEG4以下等級,ARM軟解都直接ok。

          所以結論是,這台Chromebook 13,改用Ubuntu(Chrubuntu)後,整個頭好壯狀,考試都得100分。

          特色與優勢:
          1. 非常省電 (除動態時脈調整外,還動態開啟關閉CPU核心)
          這台是ARM系統,使用起來真的是很省電,
          Nvidia對Tegra K1的支援相當不錯,
          它因為是專門用在手機、平板的行動平台,對於省電有特殊設計。

          根據Tegra-K1描述,
          「理論上」它應該是NVIDIA 4-Plus-1 Quad-Core ARM Cortex-A15,
          這裡指的NVIDIA 4-Plus-1是說,
          「理論上」它應該有2顆ARM,
          1顆是4核心高階高時脈ARM,另一顆是單核心低時脈ARM,稱為LP :p,
          「理論上」它應該可以在閒置時,關閉4核心高階ARM,切換成使用LP ARM。

          「實務上」我找不到文獻說的參數來切換CPU,沒辦法很屌的做到切換成LP ARM,
          原因我有3個猜測:
          1. 我猜Google或Acer測試時發現不穩,把這功能關閉
          2. 這款SoC是閹割版,沒有額外這顆LP    ARM
          3. 工程師研發時,沒注意到這功能,沒開

          但除了這點有點可惜外,這台Chromebook的ARM直接build-in省電module,
          它除了一般PC動態時脈調整外,它可以動態的開啟、關閉CPU核心,
          當CPU工作量低時,就會先關閉1個核心,還是很低就關第2個核心,
          陸續關到剩下單核心。
          當CPU工作量增加時,時脈先拉高,然後開第2個核心,
          還是很高,開第3個核心,最終4個全開。

          開/關的切換過程完全不會有感覺,不會頓也沒遇過程式因為切換發生問題。

          2. 強大顯示運算
          買小筆電,看高解析度影片真的是慘,
          「號稱」可以硬解1080p影片,
          實際情況是,高bitrate影片就是解不動。

          這台是Nvidia血統的SoC,不用說,顯示晶片超強,
          Nvidia主打的特點就是超強繪圖運算,
          Tegra-K1的介紹中描述,它的應用環境包括:
          • 車用電腦中的環境辨識 (包括自動煞車的車前障礙物辨識、循跡系統的標線偵測...等)
          • 機器人的機器視覺 (障礙物辨識、物件辨識)
          所以這台有CUDA,可以直接用這台開發CUDA程式做顯示卡運算,
          雖然不知道意義在哪........

          播放影片部份,如果MPlayer、VLC能支援OpenMAX(正在研究中),
          那就可以丟掉爛爛的播放器,直接用MPlayer、VLC順暢播放H.264影片。

          3. 高CP值
          這台就算是原價,價格也相當實惠。
          客官啊.......
          它的雙胞胎兄弟NVIDIA Jetson TK1原價屋目前特價一塊還要NT 6090,
          你買這台NB,Acer附上13.3吋LCD、3220mAh電池、802.11ac WiFi、藍芽、32GB eMMC,
          只多賣你不到NT 4000,這樣的商品和價格,去哪找啊。

          怎麼改機成Ubuntu (Chrubuntu):
          我完全瞭解,介紹了半天,卻不提供安裝方式,根本是炫耀文,擺明找打。

          我還沒完全把Chrubuntu的script修改完,
          沒辦法提供出簡單、完整的安裝方式出來,
          不過,這裡我先把參考資料,目前建好的檔案放出來,
          高手高手高高手先自己試試看吧!

          參考資料:
          ChrUbuntu on Acer Chromebook 13

          上述參考資料的位址是最關鍵的,裡面開版大大實際上已經把7成的工作完成了,
          他做了下列事情:
          1. Ubuntu放上Acer Chromebook 13
          2. 整合了Nvidia在Linux For Tegra R19提供的Library
          3. 把Google改過針對Acer Chromebook 13的FlashPlayer移入Ubuntu
          4. 放上支援硬解的播放器(可能也是從Google的ChromeOS搬出來的)
          5. 將ChromeOS內的Kernel和modules複製到Ubuntu中

          其他網友在版上補充:
          1. Ubuntu NetworkManager在WiFi運作不正常的修正
          2. 音量快速鍵設定
          3. 開機後預設關閉藍芽
          4. Ubuntu 14.10無法順利安裝和使用,需使用Ubuntu 14.04

          自己安裝心得:
          我自己實際安裝,第1次安裝滿辛苦的,因為它下載網站設到歐洲,很慢.......
          過程失敗,就要重新開機,整個script重跑......很久.....
          所以最後script還自己邊try邊改......直到安裝成功......
          再之後,直接把安裝好,ok得版本tar起來,直接tar解開......

          另外,我自己修正包括:
          1. 修正按Power睡眠後起不來
          2. 除Xfce4外,安裝GNOME Fallback
          3. 輸入法加入新酷音輸入法
          4. 除音量快速鍵外,加入顯示器亮度快速鍵 (針對GNOME設定,Xfce4我不會設自定義快速鍵)
          5. 直接安裝好修正過的NetworkManager
          6. Nvidia的Linux For Tegra(L4T)改用R21.2版 (R21.2版支援CUDA 6.5,R19只支援到CUDA 6.0)
          7. 修正切換耳機沒聲音
          8. 加入CIFS和NFS的modules
          9. 開機後直接設定啟用動態開啟/關閉CPU核心的能力
          10. 安裝、設定思源黑體(Noto Sans)中文字型
          11. 開機後,顯示器亮度設為50%(預設是最亮)
          12. 安裝好Java、Firefox、Chromium、LibreOffice、MPlayer、VLC、aptitude

          我直接將改過得整個系統打包成tar檔案,
          省去chrubuntu script上網下載一堆套件安裝成系統的時間,
          高手高手高高手只需要:
          Step 1. 按chrubuntu教學,將Acer Chromebook 13設成Develop Mode
          Step 2.ChrUbuntu on Acer Chromebook 13執行chrubuntu.sh,變更Partition Size並Format成ext4
          Step 3. 將我改過的系統tar檔傳上去(我自己是用wget放到home目錄),解開到chrubuntu Partition
          Step 4. ChrUbuntu on Acer Chromebook 13,切換開機載入系統的Partition

          打完收工

          預設的帳號密碼和原來chrubuntu一樣:
          帳號:user
          密碼:user

          root預設禁用無法登入,使用sudo su變更後再改密碼。

          檔案壓縮後有1.35GB目前我放在MEGA上,
          未來歡迎幫我分流,或提供給我空間放置,連結如下:
          xubuntu-desktop_lazchrubuntu_l4tr21.tar.bz2

          下一篇,我希望可以修改完針對這個檔案安裝的chrubuntu.sh,
          再把完整步驟寫出來。

          目前使用上尚待解決的問題:
          1. MPlayer、VLC OpenMAX移植和硬解(如果用gstreamer base的播放器,如:totem,可以直接硬解)
          2. 睡眠後可能是顯示晶片沒停止很耗電,我電腦睡眠後丟著,白天上班晚上回來電池竟然沒電了
          3. 闔上螢幕不會關機;但睡眠後,闔上螢幕反而會開機
          4. GNOME環境下,System tray的電池開機後不會顯示;點設定->電源叫出後,睡眠->醒來後又會消失
          5. 睡眠醒來時,畫面會閃3下
          6. Firefox支援Java Plugin不支援FlashPlayer (這是個大哉問,跟Firefox要支援Chrome Plugin格式有關)
          7. Chromium支援FlashPlayer不支援Java Plugin (這是個大哉問,跟Java Plugin格式有關)
          8. 變更alsamixer設定後,切換到耳機模式,耳機有聲音喇叭沒聲音(正常);但在喇叭模式,耳機和喇叭都有聲音(不正常)
          9. 鍵盤沒有Del,同位置是電源,經常按錯啊 (這問題是來鬧的嗎....)
          10. 極少數時候,睡眠醒來後,執行中程式會Crash

          目前注意到大部分問題都發生在睡眠或睡眠醒來,
          我十分懷疑問題點在Systemd和UPower,
          事實上我發現到,Ubuntu預設睡醒的行為,都是針對x86或intel的動作,
          這台是Nvidia ARM,相關的動作都沒有或可能不完全,
          但目前我對Systemd和UPower都不算熟,chubuntu又算是改機成品,
          沒有正常的Ubuntu 14.04對照,不確定正確動作流程。

          題外話之ChromeOS設計理念:
          Google的Android在手機上異常成功的關鍵之一,就是捨棄了傳統的手機平台設計,
          傳統手機平台,都是一般作業系統搭配一個特殊的環境和特殊的SDK,
          像是OpenMoko
          在那個年代,我還在用PocketPC,最方便開發的系統是WinCE,使用VisualC++ Embedded。

          你要開發者在開發App前,要先經過一個複雜的「儀式」,
          才能把開發環境建置出來,環境內的桌面系統可能是Qt Library、GTK+ Library,
          又因為是手機平台,SDK還不大一樣,這開發者怎麼買單?

          Google的創舉在於,你不需要那個複雜的「儀式」,
          你也不需要學習離譜的SDK,你只要會「Java」,而且注意,
          不是Sun設計得莫名其妙的JavaME,而是直接用JavaSE就能開發,
          只要最後經過一道「詭異程序」,就能把Java程式放在Android上執行。
          所以就成功了...........

          Google的作法是,
          它把手機底層全部用一個Google的JavaVM包裹(JavaVM的設計公司是被Google買斷的),
          開發者不需要知道底層在幹嘛,只需要Java程式這個JavaVM能看懂,就能執行,
          那個「詭異程序」,就是負責將一般的Java程式,
          轉換成這個小型化JavaVM能看懂的格式,附帶包入安裝資訊...等。
          Google這作法當時,Java已經是熱門語言,程式開發者多,
          直接用現成語言和現成SDK就能開發,
          加上Google的名號,和當時hTC獨家的硬體工藝,使用者和開發者就買單了。

          事實上,當時Google還是擔心和其他同質平台遇到一樣的問題,
          因此發表前還搞了個Android前100大創意App徵選,
          除了搞聲勢外,就是要讓開發者能認識、熟悉這個平台的開發環境和模式。

          Google聽到有人在PC上,用「瀏覽器」當核心開發OS,
          手法和它在Android上一樣,差別是,
          一個用JavaVM,一個用瀏覽器的WebKit + JavaScript解譯器
          (瀏覽器在現代,幾乎可以視為一種Html + JavaScript語言的VM),
          直接就想複製這樣的模式到PC,要把Windows幹掉,這就是ChromeOS。

          ChromeOS的設計理念不錯,也很特別,
          但它的設計,只整合了網路服務,沒有整合本機程式,
          這讓整個ChromeOS變得失敗。

          我描述個對比,你在Android手機上操作,
          會因為是網路手機,所以沒辦法讀取手機內的影片、聲音、聯絡人、簡訊嗎?
          這當然不會發生吧.......

          但在ChromeOS上,竟然是搞成這樣,這真的是失敗設計,
          你要同一個架構這麼搞,你可以寫個獨立的Local WebServer,
          所有本機相關的操作,都透過Local WebServer呼叫執行。

          更簡單的作法,你直接在架構上開洞,在ChromeOS的SDK上開個API,
          能直接開啟本機程式,同樣可以引入檔案總管、小畫家、MPlayer、VLC...等,
          就不會搞成現在這樣,有新意但不好用。

          2015年1月10日

          HPLIP、SANE、CUPS、p910nd

          前言:
          去年過年前後,打算用網樂通做個列印、掃描伺服器,最後失敗了,
          一轉眼一年過了,
          最近又打算起死回生,再來一次。
          這次不鐵齒,看看OpenWRT上作法後,瞭解HPLIP、CUPS、p910nd後再開工,
          於是就打算把這幾樣寫成心得。

          介紹:
          • HPLIP是HP針對HP掃描器、印表機提供的Linux OpenSource驅動程式組合包。
          • SANE是Linux上的掃描器的軟體,裡面包含了網路掃描、掃描的前端軟體介面、掃描器驅動程式。
          • CUPS、p910nd都是Linux上的列印伺服器,p910nd是non-spooling的列印伺服器,CUPS則是spooling伺服器。
          簡單介紹結束,
          接著先針對CUPS和p910nd描述其架構,
          再介紹SANE架構,
          最後描述HPLIP和它們間的關係。

          p910nd與CUPS區別和兩者架構:

          p910nd:
          參考:
          [Oleg/Lly/CDMA@wifi] p910nd 列印伺服器(無spool)

          從參考的作者文中可以知道,
          p910nd的安裝,主要2個步驟:
          1. 確定Linux Kernel內USB Printer有支援
          2. p910nd daemon有啟動,並指定Port、USB Printer的Device File
          步驟完成,p910nd就會動了,而且p910nd需求極小,
          幾乎沒有相依太多library就能動作。

          再看看下面這個參考:
          DD-WRT Printer Sharing

          裡面描述了p910nd安裝外,也描述了Client端的安裝,
          包括CUPS、Linux、Windows、MacOSX的安裝介紹。

          簡單白話的說,
          p910nd本身只是USB<->Socket的轉譯器,
          它不負責印表機溝通,從Socket來的資料直接轉入USB當中,
          因此所有印表機的溝通,列印資料的轉譯,都要由Client端負責,
          印表機工作的排程,則要由印表機自己負責。

          因此p910nd優點是library相依性低,也不需要複雜的額外工作,
          至於Client端,
          Windows直接有原廠的驅動程式,
          Linux直接有CUPS搭配HPLIP就能達成,
          MacOSX看起來也是有驅動程式,這部份我不熟。

          CUPS:
          直接看系統方塊圖(wiki):

          CUPS是一整套完整的列印伺服器程式,
          裡面包含了使用者管理、列印語言轉譯、列印Queue、網路列印...等多個功能。

          我們單從CUPS的系統方塊圖來看,
          它前面提供了各種檔案格式的轉譯器,轉譯成PostScript,
          中間能將PostScript轉譯成各種列印語言,像是PCL...等,
          後面CUPS backend又能串接包括本機的USB、SerialPort...等,網路的IPP、網路芳鄰、AppleTalk...等網路介面。

          因此可以知道它是非常龐大的列印系統,
          從前端應用程式的檔案開始,就一路透過它層層處理,最後一樣透過它送到印表機上。

          優點當然是系統功能完整,但缺點就是相依的library多,
          程式的設定項目多比較複雜,
          在小型系統上就比較不方便移植,
          因此比較早期的OpenWRT、DD-WRT都只支援p910nd,
          較新的版本則已經有提供cups,
          自行移植則會遇到比較多的編譯問題,我自己最後編譯出來,執行後,網頁點幾下還是會segfault。

          SANE:
          SANE是Linux上最主要的掃描器解決方案,可能也是唯一的解決方案,
          有支援Linux的掃描器,大概都是提供SANE的驅動程式。

          SANE分前端(frontend)和後端(backend),
          SANE frontend主要提供給應用程式,送掃描動作給SANE;
          SANE backend主要就是SANE介面界接掃描器的驅動程式。

          SANE有提供一個特別的SANE frontend,叫做net,
          它能讓SANE能透過網路接收SANE的掃描動作,達成網路控制掃描器掃描。

          HPLIP:
          前面提這麼多,原因是HPLIP相依的東西很多,
          上述幾個是最關鍵的幾個。

          參考:

          直接看參考中的系統方塊圖:

          拆開來看HPLIP各項元件,我們先只看掃描器部份,看hp-scan那個垂直的部份。

          在HPLIP中,HP的掃描器是透過SANE支援的。
          hp-scan:
          hp-scan是HPLIP提供的掃描器工具程式,但hp-scan實際上是個SANE frontend,
          就是透過SANE backend掃描。

          libsane-hpaio:
          HPLIP提供了libsane-hpaio這個SANE backend用的延伸library,
          libsane-hpaio讓SANE backend透過它來操作HP掃描器,
          我不很確定裡面有沒有包含驅動程式,或是否有包含部份的驅動程式,
          但這個library非常重要,SANE需要靠它才能操作HP掃描器,
          在SANE中,它被稱為hpaio的SANE backend。

          hpmud:
          HPLIP實際操作HP印表機、掃描器的I/O library,
          所有的工作都透過這個library傳遞給USB或網路(網路印表機、網路掃描器時),
          它的下層,就是USB library或Socket,直接連結印表機、掃描器。

          D-Bus:
          掃描器這路看完後,我們來看D-BUS。
          在HPLIP中,各個應用程式和元件間溝通都是透過D-BUS,
          這些應用程式包括掃描器左邊那幾個小顆的,
          包括hp-systray、hp-toolbox、hp-sendfax這幾個工具程式,
          還有libsane-hpaio這個SANE backend。

          這些元件和程式的溝通都透過D-Bus,
          而D-Bus本身在HPLIP則是透過hp/hpfax backend管理。

          關於D-Bus,這邊不多介紹,簡單的說,它是Linux上IPC的一種,
          各應用程式可以透過D-Bus互相溝通,
          典型的例子是,播放程式透過D-Bus提供出播放音樂的資訊,
          Skype這類的通訊軟體透過D-Bus可以得到並顯示你正在播放的音樂資訊。

          部份總結:
          到目前為止,
          先整理下HPLIP做了什麼?搞了哪些元件?要在小系統上編譯,需要編譯哪些東西?
          1.
          HPLIP最核心的I/O主要是hpmud,負責最終和硬體通訊

          2.
          HPLIP使用SANE做為掃描器核心,要能掃描,除了SANE要ok之外,
          hpaio backend要確定ok,並有放置在SANE backend的目錄內

          3.
          hp-scan只是個SANE frontend,不用管它,用其他SANE程式效果一樣

          4.
          D-Bus在HPLIP是各程式的溝通平台,單純使用掃描功能,不用管它

          5.
          如果搭配p910nd,到目前為止的資訊已經足夠了,其他元件都只跟列印和CUPS相關

          HPLIP與CUPS:
          前面CUPS提到,CUPS架構很大,CUPS中間有許多轉譯器提供各種轉譯,
          HPLIP針對CUPS實做了hpcups、hpcupsfax...等幾個轉譯器,
          接收了從CUPS收到的列印資料(應該是PostScript)後,
          透過這些轉譯器轉譯,送給hp/hpfax backend,再透過hpmud送到印表機。

          這裡我比較不清楚的地方是,
          轉譯器轉譯後,是直接在轉譯器內送到hp/hpfax backend,
          還是轉譯器轉譯後,回到CUPS,再由CUPS送到hp/hpfax backend進行列印,
          這是圖上沒有表示的部份。