NanoPi NEOをSIP電話機にする 後編 (その1)

NanoPi NEO2とUSBハンドセット

前々回でUSBハンドセットをNanoPi NEOに接続すると/dev/hidraw*として認識されることが判っている。
で、ハンドセットのマイクとスピーカーは特になにも手を加えずともサウンドデバイスとして認識されることも判っている(既に使えている)。
今回はハンドセットのボタンを使えるようにするのと液晶に表示できるようにしたい。

ボタン入力

まずはボタンを押したときにどういう信号が来るのかを確認する。

USBハンドセット 1

# hexdump /dev/hidraw0
0000000 0301 0100 0101 0101 0001 0100 0101 0101 ← [1]
0000010 0901 0100 0101 0101 0001 0100 0101 0101 ← [2]
0000020 0f01 0100 0101 0101 0001 0100 0101 0101 ← [3]
0000030 0401 0100 0101 0101 0001 0100 0101 0101 ← [4]
0000040 0a01 0100 0101 0101 0001 0100 0101 0101 ← [5]
0000050 1001 0100 0101 0101 0001 0100 0101 0101 ← [6]
0000060 0501 0100 0101 0101 0001 0100 0101 0101 ← [7]
0000070 0b01 0100 0101 0101 0001 0100 0101 0101 ← [8]
0000080 1101 0100 0101 0101 0001 0100 0101 0101 ← [9]
0000090 0601 0100 0101 0101 0001 0100 0101 0101 ← [*]
00000a0 0c01 0100 0101 0101 0001 0100 0101 0101 ← [0]
00000b0 1201 0100 0101 0101 0001 0100 0101 0101 ← [#]
00000c0 0201 0100 0101 0101 0001 0100 0101 0101 ← ① [Off-hook]
00000d0 1301 0100 0101 0101 0001 0100 0101 0101 ← ② [Up]
00000e0 1601 0100 0101 0101 0001 0100 0101 0101 ← ③ [Down]
00000f0 0e01 0100 0101 0101 0001 0100 0101 0101 ← ④ [On-hook]
0000100 0101 0100 0101 0101 0001 0100 0101 0101 ← ⑤[yes]
0000110 0701 0100 0101 0101 0001 0100 0101 0101 ← ⑥[+]
0000120 0d01 0100 0101 0101 0001 0100 0101 0101 ← ⑦[no]
0000130 1b01 0100 0101 0101 0001 0100 0101 0101 ← [mute]
0000140 1901 0100 0101 0101 0001 0100 0101 0101 ← [Vol +]
0000150 1c01 0100 0101 0101 0001 0100 0101 0101 ← [Vol -]
         ↑ この列                     ↑押したボタン

コマンドを入力後、ハンドセットのボタンを1つ押すごとに送信された信号(データ)が1行で表示される。
どのボタンを押したときに何が送信されてくるかメモしておく。

pythonが使えることを確認。

$ python -V
Python 2.7.9

Cheap USB Skype/VoIP phone protocol discoveryのページのpythonスクリプトの1つめを貰ってくる。そのスクリプトでは対象デバイスが/dev/hidraw1になっているので自分の環境に合わせる。

1
2
- file = open( "/dev/hidraw1", "w+b" );
+ file = open( "/dev/hidraw0", "w+b" );

ボタンを押した時に送信される信号(データ)はハンドセットの機種ごとに違う筈なので先ほど調べた信号に書き換える。
例えば「がとらぼ」の中の人のハンドセットはYesとNoの間のボタンが[+]という表示ものだが、上の方で取得したコードのとおり[+]ボタンは 0x07なのでリンクのページから得たスクリプトの[S](0x08)とは違う。その他のボタンは偶然だろうが同じだった

1
2
- 0x08 : "S",
+ 0x07 : "+",

script 1

スクリプト名をscript1.pyとして

# chmod +x script1.py
# ./script1.py

この状態でUSBハンドセットのボタンを押しまくり、押したボタンのラベルがターミナル(PC側)に正しく表示されることを確認。

これでボタン押しによる入力側は全部利用できることが確認できた。

液晶画面出力

Cheap USB Skype/VoIP phone protocol discoveryのページのpythonスクリプトの2つめを貰ってくる。
スクリプトを見るとimport Image, ImageDraw, ImageFontとあるのでイメージ系ライブラリが要るようだがこの手のはPillowでイケる筈。

# apt install python-pil

スクリプトを3箇所変更

1
2
3
4
5
6
7
8
- import Image, ImageDraw, ImageFont
+ from PIL import Image, ImageDraw, ImageFont

- file = open( "/dev/hidraw1", "w+b" );
+ file = open( "/dev/hidraw0", "w+b" );

- font = ImageFont.truetype("/usr/share/fonts/truetype/msttcorefonts/arial.ttf", 20)
+ font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 20)

後はダミーのlogo.pngをカレントディレクトリに用意。
先と同様にボタンを押したときのコードも必要に応じて変更。

1
2
- 0x08 : "S",
+ 0x07 : "+",

script 2

スクリプト名をscript2.pyとして

# chmod +x script2.py
# ./script2.py

今度はUSBハンドセットのボタンを押すとハンドセットの液晶画面に押したボタンのラベルが表示される。表示範囲は1行だけで溢れ制御はないので表示範囲が文字で埋まったらオンフック(通話終了)ボタンを押して液晶の表示をクリアする。

USBハンドセット 2
上の写真はボタンを押した時の表示じゃないけど1行にこんな風に表示される。

出力側のメインの処理は以下の部分なので「16進数で適当に」の部分にいろいろ入れて試してみることになるかと思う。

1
2
3
4
5
6
7
#!/usr/bin/python
import struct
file = open( "/dev/hidraw0", "w+b" );
buf="16進数で適当に".decode("hex")
file.write(buf)
file.flush()
file.close();

たとえば「がとらぼ」の中の人のUSBハンドセットだと 0400 を送信すると液晶バックライトOff、 040f を送信すると液晶バックライトOnというのが判明した。当然だけど、ある程度は目星を付けて試さないと干し草の山の中から針を探すようなことになるかと。

全く目星がつかない場合はランダムにデータを送信してみる。それで数秒内にハンドセット側に何か反応があればその機能は比較的簡単に探せるものだと思われる。そういうのを幾つか見つけたら共通する部分からある程度は目星が付くかと。

# cat /dev/random > /dev/hidraw0

USBハンドセット 3
制御方法が解ってしまえばいろいろできちゃう。
なんか液晶画面が傷だらけで汚いけど、何年も押し入れの屑入れの中で他のゴミと擦れてたから。

今回はUSBハンドセットの制御だけ。このハンドセットをSIP電話機にするのは次の記事で。

関連記事: