從兩張表得到了我們需要的東西,然後下面的代碼就是圍繞著這兩個指標來展開了。(unusual_dev和id)繼續看get_device_info()。
497行,把unusual_dev給記錄在us裡面,反正us裡面也有這麼一個成員。這樣記錄下來以後使用起來就方便了,因為us是貫穿整個故事的,所以訪問它的成員很方便,隨時都可以,但是us_unusual_dev_list以及storage_usb_ids這兩張表這次之後就不會再用了。因為我們已經得到了我們想要的,所以就不用再去騷擾這兩個數組了。
498行至504行,給us的另外三個成員賦值,subclass、protocol和flags。比如我們的隨身碟,它屬於主流裝置,在us_unusual_dev_list列表中能找到它,其subclass是US_SC_SCSI,而protocol是Bulk-only,即這裡用宏US_PR_BULK代表。
關於US_SC_DEVICE和US_PR_DEVICE在之前講三星的數位相機時已經看到了,它就表示subclass和protocol得從裝置的描述符裡面讀出來。這樣做看起來很滑稽,因為三星完全可以把subclass和protocol在UNUSUAL_DEV中寫清楚,何必讓我們再去讀裝置描述符呢?然而,我們可以想象,這樣的好處是定義一個UNUSUAL_DEV可以代表幾種裝置,即它可以讓幾個不同subclass的裝置共用這麼一個宏,或者幾個不同protocol的裝置共用這麼一個宏。需要特別指出的是us->flags,對於隨身碟來說,它當然沒有什麼flags需要設定,但是unusual_devs.h中的很多裝置都設定了各種flags,稍後在代碼中我們會看到,時不時就得判斷一下是否某個flag設定了,通常是如果設定了,就要多執行某段代碼,以滿足某種要求。
523行到551行,這是一段純粹的調試代碼,對我們理解USB沒有任何意義的。這段代碼檢查unusual_devs.h,看是否這個檔案定義了一行沒有意義的句子。什麼叫沒有意義?我們剛才看見了,如果這個裝置設了US_SC_DEVICE,那麼其subclass將從描述符中讀出來,如果不然,則讓subclass=unusual_dev->useProtocol,但是如果後者又真的和描述符裡讀出來的一樣,那麼這個裝置就沒有必要把自己的useProtocol定義在unusual_devs.h中了,因為反正也可以從描述符裡讀出來。還不如和福士一樣設為US_SC_DEVICE得了。就比如我們來看下面這行代表一個Sony的Memory Stick產品的代碼:
629 UNUSUAL_DEV( 0x054c, 0x0069, 0x0000, 0x9999,
630 "Sony",
631 "Memorystick MSC-U03",
632 US_SC_UFI, US_PR_CB, NULL,
633 US_FL_SINGLE_LUN ),
我們看到其useProtocol這一欄裡寫了US_SC_UFI,這表明它自稱是屬於UFI這個SubClass的,但是如果我們從它的描述符裡面讀出來也是這個,那就沒有必要註明在這裡了,這裡直接寫成US_SC_DEVICE好了。當然,總的來說這段代碼有一些傻。寫代碼的是希望能夠更好地管理unusual_devs.h,希望它不要不斷增加,它總希望能夠從這個檔案中刪除一些行,並且即使不能刪除一行,也希望每一行都看上去整齊一點,讓這個檔案看上去更加小巧玲瓏,更加精緻。而不是無休地增加,不息地擴充。
至此,get_device_info這個函數就結束了它的使命。在USB Storage這部戲裡,它將不再出場。但我想說,對於USB Storage這整個模組來說,主角配角不重要,每個函數都是畫布上的一抹色彩。就像我們每一個人,不也是別人人生中的配角,但總是自己人生的主角嗎?