書籍「USB機器の製作」にて、
4章-2の「USBジョイスティック」で
8ボタンにする方法を教えてください、
との問い合わせがありましたので、ここに書いておきます。
dscr.a51を次のように修正します。
DeviceDscr: db DSCR_DEVICE_LEN ;; Descriptor length db DSCR_DEVICE ;; Decriptor type dw 0002H ;; Specification Version (BCD) db 00H ;; Device class db 00H ;; Device sub-class db 00H ;; Device sub-sub-class db 64 ;; Maximum packet size dw 3412H ;; Vendor ID dw 7956H ;; Product ID***ここを修正***** dw 0000H ;; Product version ID db 1 ;; Manufacturer string index db 2 ;; Product string index db 0 ;; Serial number string index db 1 ;; Number of configurations
▲そのままだとドライバがぶつかるので、プロダクトIDを適当な値に修正します。
ここでは0x5679としました
(usb.orgからお金を払って取得したものではなく、趣味用に割り振っただけです。ご注意ください)。
▲レポートディスクリプタのエディットツール「dt.exe」です。usb.orgで公開されています。
レポートディスクリプタを修正します。
ReportDscr: db 05h,01h ;USAGE_PAGE(Generic Desktop) db 09h,05h ;USAGE (Game Pad) db 0a1h,01h ;COLLECTION (Application) db 09h,01h ;USAGE (Pointer) db 0a1h,00h ;COLLECTION (Physical) db 09h,30h ;USAGE (X) db 09h,31h ;USAGE (Y) db 15h,0h ;LOGICAL_MINIMUM (0) db 26h,0ffh,0 ;LOGICAL_MAXIMUM (255) db 95h,02h ;REPORT_COUNT (2) db 75h,08h ;REPORT_SIZE (8) db 81h,02h ;INPUT (Data,Var,Abs) db 0c0h ;END_COLLECTION db 05h,09h ;USAGE_PAGE (Button) db 19h,01h ;USAGE_MINIMUM (Button 1) db 29h,08h ;USAGE_MAXIMUM (Button 8)***修正*** db 15h,00h ;LOGICAL_MINIMUM (0) db 25h,01h ;LOGICAL_MAXIMUM (1) db 95h,08h ;REPORT_COUNT (8)****修正*** db 75h,01h ;REPORT_SIZE (1) db 81h,02h ;INPUT (Data,Var,Abs) ;;; db 95h,06h ;REPORT_COUNT (6);;;****不要! ;;; db 81h,03h ;INPUT (Cnst,Var,Abs);;****不要! db 0c0h ;END_COLLECTION ReportDscrEnd:
▲ボタン数を増やします。
あと、バイト単位の埋め合わせが不要になります。
bulkloop.cのTD_Poll関数を修正します。
void TD_Poll(void) // Called repeatedly while the device is idle { #define JOYUP (1<<0) #define JOYDOWN (1<<1) #define JOYLEFT (1<<2) #define JOYRIGHT (1<<3) #define JOYA (1<<4) #define JOYB (1<<5) BYTE swdata; BYTE x,y; if(!(EP1INCS & bmEPBUSY)) { if((IOA & JOYRIGHT)==0){ x = 255; // x+1 }else{ if((IOA & JOYLEFT)==0){ x = 0; // x-1 }else{ x = 128; // x+0 } } if((IOA & JOYDOWN)==0){ y = 255; // y+1 }else{ if((IOA & JOYUP)==0){ y = 0; // y-1 }else{ y = 128; // y+0 } } swdata = 0; if((IOA & JOYA)==0) swdata |= 1; if((IOA & JOYB)==0) swdata |= 2; if((IOA & (1<<6))==0) swdata |= (1<<2);//ボタンC追加!! if((IOA & (1<<7))==0) swdata |= (1<<3);//ボタンD追加!! //ボタンE/F/G/Hの読み取り(中略) EP1INBUF[0] = x; EP1INBUF[1] = y; EP1INBUF[2] = swdata; EP1INBC = 3; } }
▲こんな感じでボタンを増やします。
Aポートを使いきったので、残りのボタンはBポートを使うといいでしょうか?
工夫してみてください。
あと、
「方向入力を外しても動きますか?」との
お問い合わせもあったのですが、
、、、試してないので分かりません。
HIDは柔軟にできてますので、矛盾なく作れば問題なく動くと思います。
ReportDscr: db 05h,01h ;USAGE_PAGE(Generic Desktop) db 09h,05h ;USAGE (Game Pad) db 0a1h,01h ;COLLECTION (Application) ;;; db 09h,01h ;USAGE (Pointer) ;;; db 0a1h,00h ;COLLECTION (Physical) ;;; db 09h,30h ;USAGE (X) ;;; db 09h,31h ;USAGE (Y) ;;; db 15h,0h ;LOGICAL_MINIMUM (0) ;;; db 26h,0ffh,0 ;LOGICAL_MAXIMUM (255) ;;; db 95h,02h ;REPORT_COUNT (2) ;;; db 75h,08h ;REPORT_SIZE (8) ;;; db 81h,02h ;INPUT (Data,Var,Abs) ;;; db 0c0h ;END_COLLECTION db 05h,09h ;USAGE_PAGE (Button) db 19h,01h ;USAGE_MINIMUM (Button 1) db 29h,08h ;USAGE_MAXIMUM (Button 8)***修正*** db 15h,00h ;LOGICAL_MINIMUM (0) db 25h,01h ;LOGICAL_MAXIMUM (1) db 95h,08h ;REPORT_COUNT (8)****修正*** db 75h,01h ;REPORT_SIZE (1) db 81h,02h ;INPUT (Data,Var,Abs) ;;; db 95h,06h ;REPORT_COUNT (6);;;****不要! ;;; db 81h,03h ;INPUT (Cnst,Var,Abs);;****不要! db 0c0h ;END_COLLECTION ReportDscrEnd:
▲たぶんこれで8ボタンだけを読み取るはずです。
TD_Poll関数も対応させて修正してください。
これで動くかどうか、よかったら結果をお教えください。
(無事動きました、とのことです。よかったです。)