では、gousbを使ってみよう。
exampleを使う。
まあ、まずはデバイスを認識できるかどうかからだ。
libusb-1.0がいるから、事前にaptなりなんなりでインストールしておく。
01: // sudo apt install libusb-1.0 02: 03: package main 04: 05: import ( 06: "fmt" 07: "log" 08: 09: "github.com/google/gousb" 10: ) 11: 12: const ( 13: VID = 0x054c 14: PID = 0x02e1 15: ) 16: 17: // https://github.com/google/gousb/blob/master/example_test.go 18: func exampleSimple() { 19: // Initialize a new Context. 20: ctx := gousb.NewContext() 21: defer ctx.Close() 22: 23: // Open any device with a given VID/PID using a convenience function. 24: dev, err := ctx.OpenDeviceWithVIDPID(VID, PID) 25: if err != nil { 26: log.Fatalf("Could not open a device: %v", err) 27: } 28: defer dev.Close() 29: 30: // Claim the default interface using a convenience function. 31: // The default interface is always #0 alt #0 in the currently active 32: // config. 33: intf, done, err := dev.DefaultInterface() 34: if err != nil { 35: log.Fatalf("%s.DefaultInterface(): %v", dev, err) 36: } 37: defer done() 38: 39: // Open an OUT endpoint. 40: ep, err := intf.OutEndpoint(7) 41: if err != nil { 42: log.Fatalf("%s.OutEndpoint(7): %v", intf, err) 43: } 44: 45: // Generate some data to write. 46: data := make([]byte, 5) 47: for i := range data { 48: data[i] = byte(i) 49: } 50: 51: // Write data to the USB device. 52: numBytes, err := ep.Write(data) 53: if numBytes != 5 { 54: log.Fatalf("%s.Write([5]): only %d bytes written, returned error is %v", ep, numBytes, err) 55: } 56: fmt.Println("5 bytes successfully sent to the endpoint") 57: } 58: 59: func main() { 60: exampleSimple() 61: }
$ go run .
2020/03/07 11:04:01 Could not open a device: libusb: bad access [code -3]
exit status 1
まあ、いきなりは動かんか。
デバイスを使う場合、sudoとかしないといけなさそうな気がするのだが、lsusbなんかはsudoしなくても使える。
wiresharkなんかはグループを作っておけばsudoせずにいけたのだが、libusbはどうだったか。
L.24のctx.OpenDeviceWithVIDPID(VID, PID) で起きている。
C言語で書くとこんな感じだった。
https://github.com/hirokuma/libhknfcrw_c/blob/master/examples/cyg_devaccess_pasori.c#L109
sudoしてみる。
$ sudo ./go_pasori1
2020/03/07 11:11:44 vid=054c,pid=02e1,bus=2,addr=5.DefaultInterface(): failed to select interface #0 alternate setting 0 of config 1 of device vid=054c,pid=02e1,bus=2,addr=5: failed to claim interface 0 on vid=054c,pid=02e1,bus=2,addr=5,config=1: libusb: device or resource busy [code -6]
これはL.35のメッセージだから、権限の問題ということか。
udevで設定を書くことで回避できるようだが、しばらくはsudoでよかろう。
では、次はL.35のエラーについてだ。
Busyっぽいのだが、私はRC-S370をVirtualBoxのデバイス指定で使えるようにしただけだ。
dmesgを見てみる。
[15145.225082] usb 2-2: new full-speed USB device number 6 using ohci-pci
[15146.112505] usb 2-2: New USB device found, idVendor=054c, idProduct=02e1
[15146.112507] usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[15146.112509] usb 2-2: Product: RC-S370/P
[15146.112511] usb 2-2: Manufacturer: Sony
[15146.124738] usb 2-2: NFC: NXP PN533 firmware ver 1.48 now attached
OSがRC-S370をデバイスとして認めてしまっている・・・?
そういえば、いつからかLinuxはNFCデバイス(たぶんReader/Writerだろう)を識別するようになったという記事を見かけた気がする。
RC-S380(Pasori)とLinux NFC Subsystem | 何かできる気がする
https://dekirukigasuru.com/blog/2019/01/05/linux-nfc-subsystem/
Linux NFC Subsystem、ね。
できれば、今回は新しいことは試さず、USBとして動かしたいのだ。
そういえばC言語で書いていたときも、default interfaceみたいなものは使えなかった気がする。
https://github.com/hirokuma/libhknfcrw_c/blob/master/examples/cyg_devaccess_pasori.c#L133-L156
おそらく、この辺りはend pointを探しているところだろう。
なので、便利関数を使うサンプルではなく、その下にある方のサンプルを使おう。
https://github.com/google/gousb/blob/master/example_test.go#L76
ここから下を貼り付けただけなので、コードは省略だ。
2020/03/07 11:47:56 vid=054c,pid=02e1,bus=2,addr=6.Config(2): device vid=054c,pid=02e1,bus=2,addr=6: configuration id 2 not found in the descriptor of the device. Available config ids: [1]
"Config(2)"なので、ここのエラーか。
https://github.com/google/gousb/blob/master/example_test.go#L105
そういえば、なんとなくコードを貼り付けて動かしているのだが・・・この2とか3とかってなんなのだ??
エラーログの一番最後に"[1]"となっているから、2じゃなくて1ならconfigがあるということか。
・・・1にすると進んだ。。。
まあいい、最後まで通してから考えよう。
次のエラーはこれ。
2020/03/07 11:53:06 vid=054c,pid=02e1,bus=2,addr=6,config=1.Interface(3, 0): descriptor of interface (3, 0) in vid=054c,pid=02e1,bus=2,addr=6,config=1: interface 3 not found, available interfaces 0..0
3じゃなくて0ってことか。
が、0にしたらしたで別のエラーになった。
2020/03/07 11:54:51 vid=054c,pid=02e1,bus=2,addr=6,config=1.Interface(3, 0): failed to claim interface 0 on vid=054c,pid=02e1,bus=2,addr=6,config=1: libusb: device or resource busy [code -6]
ダメだ、このやり方じゃダメだ。。。
C言語で書いていたときのやり方がいいだろう。
調べられるリストを作って、先頭から順に調べて使えるものを探す、と。
改めて、openする流れをおさらいしよう。
https://github.com/hirokuma/libhknfcrw_c/blob/master/examples/cyg_devaccess_pasori.c#L47
- libusb_open_device_with_vid_pid()でハンドル取得
- libusb_get_device()でデバイス取得
- libusb_get_config_descriptor()でコンフィグ取得
- コンフィグからinterfaceの数だけEnd Pointを探す?
- libusb_claim_interface()でclaim
自分で書いておきながら理解していないが、当時もlibusbのサンプルから持ってきたやり方を使っただけだろう。
コンフィグ中をぐるぐる探すところも、本当はbreakとかして抜けるべき何じゃなかろうかね。。。
01: // sudo apt install libusb-1.0 02: 03: package main 04: 05: import ( 06: "fmt" 07: "log" 08: 09: "github.com/google/gousb" 10: ) 11: 12: const ( 13: VID = 0x054c 14: PID = 0x02e1 15: ) 16: 17: // https://github.com/google/gousb/blob/master/example_test.go 18: func openUsb() { 19: // Initialize a new Context. 20: ctx := gousb.NewContext() 21: defer ctx.Close() 22: 23: // Open any device with a given VID/PID using a convenience function. 24: dev, err := ctx.OpenDeviceWithVIDPID(VID, PID) 25: if err != nil { 26: log.Fatalf("Could not open a device: %v", err) 27: } 28: defer dev.Close() 29: 30: for _, cfg := range dev.Desc.Configs { 31: for _, inf := range cfg.Interfaces { 32: for _, alt := range inf.AltSettings { 33: for _, endPnt := range alt.Endpoints { 34: fmt.Printf("endpoint=%v\n", endPnt) 35: } 36: } 37: } 38: } 39: } 40: 41: func main() { 42: openUsb() 43: }
$ sudo ./go_pasori1
endpoint=ep #4 OUT (address 0x04) bulk [64 bytes]
endpoint=ep #4 IN (address 0x84) bulk [64 bytes]
最初、for文でinterface数なんかをがんばって取得してぐるぐる回そうとしていたのだが、lsusbサンプルを見てrangeというものがあったことを思い出す。
おそらくこれでUSBデバイスはオープンできたと思う。
だが、C言語でlibusbを使ったときは最後にlibusb_claim_interface()を呼んでいた。
これは何をする関数なのだろうか?
http://libusb.sourceforge.net/api-1.0/group__dev.html#ga32fabedf5f13fdecf1cb33acdb19b57a
制御するデバイスを主張する、なのか?
C言語版では固定で0を使っていたのだが、果たしてうまくいっていたのだろうか・・・。
それはともかく、gousbだとConfig()がそれなのか。
しかし、libusb_bulk_transfer()は無く、代わりにReadStream, WriteStreamを取得してアクセスするようだ。
その辺はサンプルを見た方が早いだろう。
https://github.com/google/gousb/blob/master/example_test.go#L52
Closeするのはdevだけでよさそうな気配がする。
これはまだ確信を得られないので、後で考えよう。
0 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。