• スポンサードリンク

Android端末でUSB3のUVCカメラを動かしてみたいんじゃぁ〜その3〜

Android Camera USB アプリ

とりあえず結果なのじゃ

その1でも書きましたがPixel3(Android10)とEssential Phone PH-1はUSB3のUVC機器を正常に認識できないので論外でした(これはアプリとはなんの関係もなく端末側の問題)。

それ以外…となるとMoto Z Play(Android 8)とMoto Z2 Play(Android 8)とNvidia SHIELD TV(Android 8)の3機種ですが、それぞれの結果は次の通りになりました。

See3CAMCU50
(バルク転送)
ELP-USB1080P01-LC1100
(アイソクロナス転送)
Moto Z Play
(Android 8)
動く正常に動かない
転送エラーまたは壊れた映像フレームが届く
Moto Z2 Play
(Android 8)
動く正常に動かない
転送エラーまたは壊れた映像フレームが届く
Nvidia SHIELD TV
(Android 8)
動かない動く
ただし少し不安定

使っているプログラム(アプリ・USB/UVCアクセスライブラリ)は同じなのに端末とカメラの組み合わせでくっきりと結果が分かれてしまいました、なんでやねん(´・ω・`) 確定ではないですが、なんとなくOS/カーネルドライバーの挙動がおかしいような気がします。

アイソクロナス転送ではUSB2でもUSB3でも複数のurbで転送要求を仕掛けていいますが、Nvidia SHIELD TVとUSB3機器(UVC機器)を繋いだ場合少しずつエラーで止まっていく、運が悪いと全部止まってしまうという感じなので、エラーからの復帰処理等を工夫するともう少し改善する見込みはあります。 Moto Z PlayとMoto Z2 Playの方はなんとなく帯域が足りてない気がします。もしかすると何かハードウエア的な制約があるのかもしれません。

あと直接は関係ありませんが、以前カメラ屋さんに聞いたところでは、インテルのチップセット内臓のUSB3機能でないと動かないUSB3機器もある/あったようです。今は改善されている…と期待しますがUSB2よりも端末とUSB3機器との相性問題が出やすいのかもしれないです。元々PCに比べるとスマホ/タブレットのUSB周りはトラブルが起きやすいですし。

USB3 / SS(Super Speed)対応で変えたところ

カーネルドライバー側はそう単純じゃないはずだけど、Android/Linuxのユーザーランド側ドライバー(ミドルウエア)でSS対応で変更するところはそれほど多くありません。たぶん、知らんけど?

  1. USB3をサポートする前のlinuxのusbfsカーネルドライバイーの仕様に合わせて作っていたのをUSB3対応以降のusbfs仕様に合わせて変更
  2. 代替設定の選択処理でUSB3時のペイロード毎転送バイト数等の計算を間違えていたのを修正
  3. 転送サイズの計算&代替設定を選択する処理をアイソクロナス転送とバルク転送で同じ処理をしていたのを分離

1つ目のは、アイソクロナス転送用のurbでバッファのサイズが元々は最大32kBだったのがUSB3対応で最大48KBに変更になっていたのと、それに合わせてurbの数の計算処理を修正。

2つ目のは、USB3のアイソクロナス転送でのエンドポイントの1回の最大転送バイト数の計算上の値とwBytesPerIntervalが食い違ってたときの処理を修正。計算上の値は、エンドポイントディスクリプタのwMaxPacketSizeとssエンドポイントコンパニオンディスクリプタのbMaxBurstからmax_burst_bytes = (bMaxBurst+1) * (Mult+1) * wMaxPacketSizeとなります。wBytesPerIntervalがmax_burst_bytesよりも大きい時(機器側から返ってきた設定がどっかおかしい?)に計算上の値であるmax_burst_bytesを使っていたのを常にwBytesPerIntervalを使うようにしました。

3つ目のは、USB2だと問題ないんだけど、USB3だとバルク転送時にもssエンドポイントコンパニオンディスクリプタ関係の処理が入ってしまって正しい転送サイズを計算できなかったのと、See3CAMCU50だと代替設定の選択処理を呼び出すとだめっぽい(その時点ではエラーにはならないけどsubmit処理以降がエラーになる)ので完全に分割しました。

usbfs使ったユーザーランド側のドライバーだと転送サイズの計算・設定以外はUSB2と同じなはずだから、これで動くようになるはずなんだけどなぁ…なぜか最初の結果に(。・_・。)処理が根本的に間違ってるというわけじゃないとは思うんだよね、動く端末・カメラの組み合わせがあるわけだし。
一般向けのUSB2のカメラは世にたくさん市販されているのに対し、USB3のは業務用を除けば数が少ないのとお高めだし、そもそもUSB3自体に対応している端末も少ない、対応していたとしても正常に動作するかどうかわからないって当たりがネックだよな。

ちなみに上で言う変更点てのは今回USB3のUVC機器をテストしてみようと思い立って変更した点という意味で、以前からボチボチ実装している部分もありました。

  • ssエンドポイントコンパニオンディスクリプタの解析処理追加
  • ss iso エンドポイントコンパニオンディスクリプタの解析処理追加
  • USB3機器かどうかの判別処理追加
  • バルクストリーム転送処理の実装(いまだにバルクストリーム転送なUVC機器に出くわしたことはないけど?)
  • USB3の時に代替設定をセットする際に1回目はエラーになる(少し待ってもう一度セットすると成功する)への対応

とかとかだね。

そうだAndroid特有なやつを1つ忘れてた?
Linuxの場合接続した各USB機器に対応するsysfsのspeedアトリビュートへアクセスすることで指定したUSB機器がlow(max 1.5Mbps), full(max 12Mbps), high(max 480Mbps), spuer(max 5Gps), super plus(max 10Gbps)のいずれであるか判断することができます。
しかぁ〜し、Androidの場合rootをとらない限りパーミッションでけられてそのsysfsへはアクセスできません。つまりユーザーランド側のプログラムから物理層がどの速度でネゴシエーションできたかを知ることができないのです。
ということでその2に書いた通りUSB機器側が判断した結果を聞くしかないよねっては話になってしまったのです。残念

おしまい

ということで、市販のAndroid端末(スマホ・タブレット)でUSB3(のUVC)機器を繋いだ場合、

  • そもそもUSB3に対応しているAndroid端末が少ない
  • 民生用でUSB3に対応しているUVC機器は少ない(カメラの一部とキャプチャカードの一部)
  • Android端末とUBS3なUVC機器の組み合わせ次第では運が良ければ動くかも
  • USB3機器はつなぐ相手によってUSB2として動作する場合も多いので、USB2の端末だと動いていたのが機種変更等で端末を変えると動かなくなる可能性もある

というのが現状なようです。
何かまた思いついてチャレンジするまで現状のまましばらく放置かなぁ寝かせるしかないかなぁ(。・_・。)

さよならぁ〜(T_T)/~~~

« »

  • スポンサードリンク