📝

Python の hid (hidapi) モジュールを理解する

2023/02/05に公開

Python には、(非公式な) hid あるいは hidapi モジュールが複数あって仕様が微妙に異なっているので使う人は困ってしまいます。

仕方がないので把握できる限りをまとめました。

pypi で配布されているパッケージが少なくとも3系統あります。
どれも libusb のサブプロジェクトである hidapi ライブラリを Python から使えるようにすることを意図している点は同じです。

import pypi github debian windows対応 mac対応
hid hid pyhidapi -
hid または hidraw hidapi cython-hidapi python3-hid
hidapi hidapi-cffi hidapi-cffi python3-hidapi

△=Windowsでは要hidapi.dll 、Macでは要hidapiシェアドライブラリ
▽=Macでhidapiシェアドライブラリをインストールするだけでは動きません。 libhidapi.dylib の名前で見えるようにする必要があります。

以下 github でのプロジェクト名で識別します。

これらのうち cython-hidapi では、Linuxプラットフォームの場合モジュールとして hid と hidraw の二つがインストールされます。
cython-hidapi の hid モジュールは、 libusb ベースの hidapi ライブラリを利用し、
cython-hidapi の hidraw モジュールは、 Linux の hidraw ドライバで動作する hidapi ライブラリを利用する点だけが違いです。
cython-hidapi を Windows にインストールした場合は hid.dll を利用する hidapi ライブラリの実装が hid モジュールにリンクされます。
Windows や Mac にインストールした場合 hidraw モジュールはありません。

pyhidapi と hidapi-cffi の場合は、 それぞれ libusb ベースと hidraw ベースの hidapi ライブラリのどちらでもシステムに存在する方を利用するようになっています。
ただ pyhidapi は libusb ベースの方を優先し、hidapi-cffi は hidraw の方を優先するようです。
Windows 環境では、hidapi.dll がロード出来る位置に存在していることを必要とします。

上で云う2種類の hidapi ライブラリは、以下の Debian パッケージに対応します。
libusb ベースの hidapi ライブラリ libhidapi-libusb0
hidraw ベースの hidapi ライブラリ libhidapi-hidraw0
2つのパッケージは、同じソースパッケージ(hidapi)からビルドされています。

それぞれのパッケージが異なるアーキテクチャに基づいているという意味で、
それぞれに存在意義がある、ということにはなっているようです。

improt アーキテクチャ pypi github debian
hid ctypes ( cdll.LoadLibrary() ) hid pyhidapi -
hid または hidraw Cython または cython3 hidapi cython-hidapi python3-hid
hidapi cffi または python3-cffi hidapi-cffi hidapi-cffi python3-hidapi

さまざまに非互換な仕様

主要クラスのクラス名

improt class pypi github debian
hid Device hid pyhidapi -
hid または hidraw device hidapi cython-hidapi python3-hid
hidapi Device hidapi-cffi hidapi-cffi python3-hidapi

デバイス列挙時の情報

improt enumerate() pypi github debian
hid dict の list hid pyhidapi -
hid または hidraw dict の list hidapi cython-hidapi python3-hid
hidapi hidapi.DeviceInfo の list hidapi-cffi hidapi-cffi python3-hidapi

デバイスをオープンする操作

improt open pypi github debian
hid dev = Device(vid=None, pid=None, serial=None, path=None) hid pyhidapi -
hid または hidraw dev = device(); dev.open(int vendor_id=0, int product_id=0, unicode serial_number=None) hidapi cython-hidapi python3-hid
hidapi dev = Device(info=None, path=None, vendor_id=None, product_id=None, serial_number=None, blocking=True) hidapi-cffi hidapi-cffi python3-hidapi

ノンブロッキングの指定方法

improt nonblocking pypi github debian
hid dev.nonblocking = True hid pyhidapi -
hid または hidraw dev.set_nonblocking(1) または dev.set_nonblocking(True) hidapi cython-hidapi python3-hid
hidapi Device オープン時の引数で blocking=False を指定 hidapi-cffi hidapi-cffi python3-hidapi

send_feature_report() 周り

improt report id pypi github debian
hid 先頭バイトで指定 hid pyhidapi -
hid または hidraw 先頭バイトで指定 hidapi cython-hidapi python3-hid
hidapi 引数で指定 (..., report_id=bytes(bytearray([0]))) hidapi-cffi hidapi-cffi python3-hidapi

get_feature_report() 周り

improt 引数 返り値 pypi github debian
hid sizeにはレポートID分を加算して指定 先頭バイトはレポートID hid pyhidapi -
hid または hidraw max_lengthにはレポートID分を加算して指定 先頭バイトはレポートID hidapi cython-hidapi python3-hid
hidapi rebort_id=bytes(bytearray([0])) のように指定 , lengthにはレポートID分を含まない 返り値はレポートIDを含まない hidapi-cffi hidapi-cffi python3-hidapi

エラー処理

improt エラー処理 pypi github debian
hid 例外 HIDException hid pyhidapi -
hid または hidraw 返り値 < 0 hidapi cython-hidapi python3-hid
hidapi 例外 IOError hidapi-cffi hidapi-cffi python3-hidapi

データの取り扱い

各モジュールとも内部では bytes型 が利用されています。
※ Python2 では bytes型 は、str型 で代用されます。

呼び出し側のプログラムでは、簡単に、整数の配列で扱いたいかもしれません。

その場合、
data=bytes(bytearray(data)) と変換することで、
data に b'\x00\x01\x02\x03' が来ても [0,1,2,3] が来ても同じように扱える、
という工夫があるので、知っておくと便利です。
Python3 に限定するなら data=bytes(data) と書いても動きます。

逆に data が b'\x00\x01\x02\x03' でも [0,1,2,3] でも配列にしたい場合は、
data=list(bytearray(data)) と出来ます。
Python3 に限定するなら data=list(data) と書いても動きます。

古い環境の問題

Debian Buster 以前 あるいは Ubuntu focal (20.04LTS) 以前の環境では
最新の hid 1.0.5 はライブラリのロードに失敗します。
pip でインストールする時に python3 -mpip hid==1.0.4 とバージョンを指定するか
ライブラリについても新しいものをビルドしてインストールするか、いずれかが必要です。

Python2の場合

import pypi github debian Python2対応
hid hid pyhidapi -
hid または hidraw hidapi cython-hidapi python-hid ◯ ※注
hidapi hidapi-cffi hidapi-cffi python-hidapi

✕=この問題のため get_feature_report() が機能しません。
  __init__.py を hid.py としてローカルにコピーしパッチを当てれば使うことは出来ます。
※注=pip でインストールする場合には適切にバージョンを指定する必要があります。
   例: python2 -mpip install hidapi==0.7.99.post21

放棄されたパッケージ

python -mpip install pyhidapi とした場合にインストールされるものは、
現状メンテナンスされておらず、少なくとも linux 環境では素直に動かないので注意が必要です。
※ /usr/local/lib/ にライブラリがインストールされている前提になっているようです

import アーキテクチャ pypi github origin archive
pyhidapi ctypes pyhidapi pyhidapi pyhidapi pyhidapi

Discussion