「USB機器の製作」ジョイスティックのボタン増やす



書籍「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関数も対応させて修正してください。


これで動くかどうか、よかったら結果をお教えください。
(無事動きました、とのことです。よかったです。)