SSブログ

macOSからPi Picoを使う - その27 [Pi Pico]

libusbのおさらいの続き。ライブラリの初期化とデバイス列挙USB descriptorの読み出し方をみた。

今回はデバイスを特定のオープンして読み書きする方法について...

17.4.1  デバイスのオープン

必要なデバイスが見つかったらデバイスを使用できるようにするためにデバイスをオープンする。
typedef struct libusb_device_handle libusb_device_handle;

int libusb_open(libusb_device        *dev,
                libusb_device_handle **dev_handle);
void libusb_close(libusb_device_handle *dev_handle);
当然済んだらcloseする。デバイスのオープンのためにはもう一つ
libusb_device_handle
*libusb_open_device_with_vid_pid(libusb_context *ctx,
                                 uint16_t     vendor_id,
                                 uint16_t     product_id);
が用意されている。これはvendorIDとprodutIDを決め打ちで直接デバイスをオープンする。相手のデバイスが決まっていれば、列挙する必要がなくなる。

このopaqueなlibusb_device_handle構造体を経由してデータをやりとりする。

ところでこの関数でオープンするとそのままではlibusb_deviceのデータは得られないので、descriptorなどの情報は得られない。そのため逆の
libusb_device* libusb_get_device(libusb_device_handle *dev_handle)	
という関数が用意されている。これで得られたlibusb_deviceへのポインタは列挙の時と違ってlibusb_unref_device()で解放してはいけないようである。

17.4.2  同期転送

データのやり取りのためには転送モードごとに
int libusb_control_transfer(libusb_device_handle *dev_handle,
                            uint8_t         bmRequestType,
                            uint8_t         bRequest,
                            uint16_t        wValue,
                            uint16_t        wIndex,
                            unsigned char   *data,
                            uint16_t        wLength,
                            unsigned int    timeout);

int libusb_bulk_transfer(libusb_device_handle *dev_handle,
                         unsigned char  endpoint,
                         unsigned char  *data,
                         int            length,
                         int            transferred,
                         unsigned int   timeout);
                         
int libusb_interrupt_transfer(libusb_device_handle *dev_handle,
                              unsigned char     endpoint,
                              unsigned char     *data,
                              int               length,
                              int               *transferred,
                              unsigned int      timeout);
の関数が用意されている。これらは「Synchronous device I/O」、つまり転送が終わるまでブロックする関数で、isochronous transfer用の関数だけは用意されていない。基本的にendpointアドレスとデータバッファを指定して転送する。

注意しないといけないのは、TinyUSBではinterface番号とtransferがinかoutかでendpointアドレスを決定していた。従って読み込み関数と書き込み関数が別になっていて、それにinterface番号を渡すようになっていた。libusbではまずendpoint番号を指定して、そのendpointがinなのかoutなのかで同じ関数を呼んでも読み出しと書き込みの動作が変わるようになっている。

仮想的な通信路は読み書きの独立した全二重を想定することが一般的だろうと思うので、TinyUSBのスタイルが多いような気がする。libusbのようなやりかたは面白いけど、混乱しそうである。
nice!(0)  コメント(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。