So-net無料ブログ作成
  • ブログをはじめる
  • ログイン

MS Hands-Free Profile [VGC-RM95S]

Microsoft の Bluetooth Stack で、どうにか Hands-Free の音声入出力ができるようになった。最終的にはMM_WIM と MM_WOW の Call Back で Driver 内の FIFO を読み込むことにした。これで会話内容が別々に録音できるので、それなりの利用価値はある。

SCO_arch_001.jpg

細かい点は山積みであるが、広範囲の知識が必要で実用的な内容なので、学習教材に最適な内容ではないだろうか。

SCO_TRANSFER_DIRECTION_OUT, 0xc000020c [VGC-RM95S]

リアルタイムでの音声の出力をやってみたが 0xc000020c (IO_Lost_Delayed_Write) error となってしまう。

また EVT_WDF_IO_QUEUE_IO_WRITE 経由で出力しようとすると IoWritre まで来ない。これは

  Wdf01000!FxIoQueue::DispatchRequestToDriver

の中で   フラグのチェックをおこなっており 以下で 1 にすると call back される。

  cmp     byte ptr [rdi+93h],r13b

すんなりとはいかないものだ。

MM_WOM_DONE [VGC-RM95S]

マルチバッファによる waveOut をやると音声の途切れはなくなった。 NTT 117 で時報を聞くと、約1秒遅れている。やはりシャーというノイズが入っている。 DigionSound5 で生のデータを聞くと同じように聞こえる。 sox で変換して media_player で聞くと消えている。どこかでノイズカットしているのだろう。

【MM_WOM_DONE でやること】

 //再生終了したバッファの処理
    for(k=0; k<BNUM; k++){
        if((LPWAVEHDR)lp==&whdr[k]){
            buf_num=k;  
            break;
        }
    }

 memcpy(whdr[buf_num].lpData, buf, sum_read);
 waveOutWrite((HWAVEOUT)wp,(LPWAVEHDR)lp,sizeof(WAVEHDR));

 //再生中バッファの処理
 buf_num=(buf_num+1)%BNUM;

続きを読む


SCO HV3 [VGC-RM95S]

SCO で受信したパケットをカーネルランドからユーザランドに転送しファイルを作成した。ドキドキしながら sox で wave に変換したところ、見事に聞こえた。

 sox -t raw -r 8000 -c 1 -w -s audio.raw -w -s a.wav

HCI レイヤのヘッダなどはカットされてくるので、そのままファイル化すればよいようだ。ユーザランドに転送する部分は、考えすぎると泥沼にはまってしまうので、シンプルに考えたところうまくいった。

結論からいえば、ドライバのサンプルプログラムとしてもよいぐらいのレベルではないだろうか。 WinsSock を使う制御部分とは、別プロセスで SCO HV3 を受信できるので、64 bit media player の plugin でも実現できるだろう。

DigiOnSound5 for VAIO で読み込ませたときの設定は、以下のようになっている。

SCO_HV3_002.jpg

waveOutWrite で出力する場合の設定は以下のようになっている。

wf.wFormatTag = WAVE_FORMAT_PCM; // PCM形式
wf.nChannels = 1; // ステレオかモノラルか
wf.nSamplesPerSec = 8000; // サンプリングレート 8.0KHz
wf.wBitsPerSample = 16; // 量子化レベル
wf.nBlockAlign = wf.wBitsPerSample * wf.nChannels / 8; // バイトあたりのビット数[PCMの仕様]
wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign; // 1 秒あたりのバイト数

BRB_SCO_OPEN_CHANNEL_RESPONSE [VGC-RM95S]

RBR の dispatch は以下の階層でおこなっているが、内部でスレッド化しているので完全な追跡は難しい。

  bthport!BthHandleBrbDispatch
    bthport!BthDispatchBrb
    bthport!BthCompleteRequestEx


BRB_SCO_OPEN_CHANNEL_RESPONSE をマニュアルどおりに任意に設定すると c0000030 や c000000d のエラーとなる。以下の設定で音声データの受信まで確認できた。

    brb->Hdr.ClientContext[0] = connectionObject;
    brb->BtAddress = ConnectParams->BtAddress;

    brb->TransmitBandwidth = 8000;
    brb->ReceiveBandwidth = 8000;
    brb->MaxLatency = 0xffff;
    brb->PacketType = SCO_HV3;
    brb->ContentFormat = SCO_VS_SETTING_DEFAULT;
    brb->Reserved = 0;

    brb->RetransmissionEffort = SCO_RETRANSMISSION_NONE;
    brb->ChannelFlags = SCO_CF_LINK_SUPPRESS_PIN;

    brb->CallbackFlags = SCO_CALLBACK_DISCONNECT;
    brb->Callback = &BthEchoSrvConnectionIndicationCallback;
    brb->CallbackContext = connectionObject;
    brb->ReferenceObject = (PVOID) WdfDeviceWdmGetDeviceObject(DevCtx->Header.Device);
    brb->ChannelHandle = ConnectParams->ConnectionHandle;
    brb->Response = SCO_CONNECT_RSP_RESPONSE_SUCCESS;

MS Stack は 64bit での動作も可能で、複数のスマホからの受信もさばけるので、やはり捨てがたい。


MS Stack SCO connection request [VGC-RM95S]

MS Stack でなんとか Hands Free をと思い SCO link のカーネル内部を追跡していると、やはり来ていた。

 bthport!ScoCxnS_ConnectionRequestEvent

ここに bp をかけると break することを確認できた。SCO の driver もどうにか動き始めたので、どのよう driver とつながるかを追いかけてみる。

0: kd> k
Child-SP          RetAddr           Call Site
fffff800`00b9c5b8 fffff880`02ce238b bthport!ScoCxnS_ConnectionRequestEvent
fffff800`00b9c5c0 fffff880`02cd8e79 bthport!Fn_EVENT_ConnectionRequest+0x127
fffff800`00b9c670 fffff880`02cee08b bthport!HCI_DoCmdCompletion+0x3d1
fffff800`00b9c750 fffff880`02cfb832 bthport!HCI_ProcessAsynchronousEvent+0x97
fffff800`00b9c7a0 fffff880`02cfb967 bthport!HCI_ProcessEventAtDPC+0x182
fffff800`00b9c810 fffff880`02cc9201 bthport!HCI_ProcessMpBip+0xef
fffff800`00b9c880 fffff880`0686c01e bthport!BTHPORT_RecvMpBip+0x41
fffff800`00b9c8d0 fffff880`0687299f BTHUSB!BthUsb_EventTransferComplete+0xca
fffff800`00b9c930 fffff880`06872c31 BTHUSB!UsbWrapWorkRoutine+0x17b
fffff800`00b9c9b0 fffff800`030d0516 BTHUSB!UsbWrapInterruptReadComplete+0x1dd
fffff800`00b9ca40 fffff880`05d2c5d9 nt!IopfCompleteRequest+0x3a6
fffff800`00b9cb20 fffff880`05d2cab7 USBPORT!USBPORT_Core_iCompleteDoneTransfer+0xa15
fffff800`00b9cc00 fffff880`05d2a64f USBPORT!USBPORT_Core_iIrpCsqCompleteDoneTransfer+0x3a7
fffff800`00b9cc60 fffff880`05d1bf89 USBPORT!USBPORT_Core_UsbIocDpc_Worker+0xf3
fffff800`00b9cca0 fffff800`030d95dc USBPORT!USBPORT_Xdpc_Worker+0x1d9
fffff800`00b9ccd0 fffff800`030d66fa nt!KiRetireDpcList+0x1bc
fffff800`00b9cd80 00000000`00000000 nt!KiIdleLoop+0x5a


ドライバ署名 [VGC-RM95S]

やっと bthecho のサンプルを Windows 7 64bit で動かすことができた。
テストではあるが、ダミーの署名をやってみた。

makecert -r -pe -sv test.pvk -ss PrivateCertStore -n CN=OpenLibSys.org test.cer
certmgr -add test.cer -s -r localMachine PrivateCertStore
cert2spc test.cer test.spc
pvk2pfx -pvk test.pvk -spc test.spc -pfx test.pfx
signtool sign /f test.pfx /v BthEchoSampleCli.sys
signtool sign /f test.pfx /v BthEchoSampleSrv.sys

署名の段階では、何故かこれでエラーにはならなかった。
やっとコンソールに echo が返ってきた。

bthecho_001.jpg

windbg 1394 [VGC-RM95S]

VGC-RM のカーネルレベルのデバッグを 1394 でおこなう場合の注意点をまとめる。 1394 は本体とアクセスユニットの2箇所にある。

(1) TARGET 側

1394 はすべて disable にしておく。カーネルデバッグモードで起動するとデバッグ用としてアクセスユニット側を使いにいってしまう。そのためアクセスユニットを外す必要がある。

(2) HOST 側

1394 のアクセスユニット側を disable にする。本体側は 「PCI バス 12, デバイス 3, 機能 0」となっている。初回に debugger device が自動でインストールされる。

で見つかるが、ほとんどが複数の 1394 を持っている場合のようである。

windbg_1394.jpg

カーネルオタクにとっては最高のオモチャとなる。少し遊んでみよう。


HF console 0.2 [VGC-RM95S]

Bluesoleil 8.0.376.0 と SDK 2.0.5 で HFP と A2DP の GUI を作ってみた。hfconsole というのが Linux 上にあるので "HF console classic" としてみた。

HF_console_0.2.jpg

発信した場合、相手の声は途切れることはない。双方が同時にしゃべった場合、こちらの声が途切れるようだ。A2DP も長時間使っていると、時々途切れる。それでも、留守電をデスクトップ環境で聞けるので個人的には重宝している。

すべて C 言語で書いたので 95KB となっている。使ってみたい人がいれば Vector にアップしてみる。

続きを読む


Bluetooth 3.0 [VGC-RM95S]

アクセスユニット内蔵の Bluetooth で T-01A とハンズフリーをやろうとしてみた。Stack  に Bluesolei 8.0.370.0 をいれてみた。どうやても、強烈なノイズが入って使い物にならない。そこで PLANEX BT-MicroEDR2X でやってみると、まったく問題ない。カーナビと同じ程度の音質で HFP ができている。

せっかくなので Bluetooth 3.0 の PLANEX BT-Micro3E1X にしてみると、ドライバその他はそのまま使えた。これはちょっと驚いた。実は BT-MicroEDR2X と PLANEX BT-Micro3E1X  の VID と PID が同じなので、ドライバから見ると同じに見えるようだ。物理アドレスは当然異なるので、再度ペアリングは必要になる。

まとめると、以下のようになっている。

 【VGC-RM95S アクセスユニット】
  ALPS  UGPZ6
  VID_044E PID_300D REV_1915

 PLANEX BT-MicroEDR2X
  CSR
  VID_0A12 PID_0001 REV_4839

 PLANEX BT-Micro3E1X
  CSR
  VID_0A12 PID_0001 REV_5276

Bluetooth 2.1 と 3.0 だから PID は異なるものだと思っていたが、Revision のみ異なっていたわけだ。HFP をコマンドレベルで、できたので GUI で使いやすくしてみよう。


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