FMラジオマウス

確か2002,3年くらいに秋葉原で購入した、マウスにFMラジオが入ったモジュールがあって、長らく放置してありました。

![写真（2020-05-21 4.06）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/6217fab1-6bc5-ff13-e6d6-56a3ca2dd65b.jpeg)

当時はradikoなどもなく仕事中にJ-Waveとか聞きたいな思って買ったような気がします。

WindowsのアプリはありますがMacのアプリはなく、いろいろ探してみたのですが、Hackしてる人も見つかりませんでした。

![fmmous.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/3d5e9579-cc94-c2f1-90bd-02c9040abd91.png)

モジュールGemTek社製造で、Cypress CY7C63001にラジオのチップPHILIPS TEA5759HがついたものでCY7C63001からTEA5759Hを3本のコントロール用の信号で制御しているようです。GemTekは他にもUSBのFMラジオを作っていたようですが、コントローラーが違うようです。

![写真（2020-05-20 10.33）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/860d5c7a-1c64-fc14-7773-53ee49eef63d.jpeg)

上側の真ん中の3本が制御線のようです。

TEA5759Hはネットでデーターシートが手に入ります。このチップにはAMの回路も入っているようですが、このモジュールでは使っていないようです。

ネットで探したらTEA5759Hを剥がして別のモジュールに貼っていた人をみつけましたが、うまくいってないようでした。

コントローラを変えるのも大変なのでやはりできるだけ、このままで使えるようにするのが現実的な攻略方法と考えました。

Windows用のアプリは98とかの頃のものですが、Windows 7で動いたので、いつものようにwiresharkでusbスヌープしてみます。

当初HIDのレポートを使ってコントロールしていると考えていたのですが、違っていました。WindowsにHIDのAPIが用意される前の製品だったのかもしれません。

HIDなインターフェースはシステムが握るので、GET DESCRIPTORでコントロールしていました。私は初めて見るタイプのデバイスです。

ラジオ受信時には以下の二つのGET DESCRIPTORが1秒おきくらいで流れていました。

```
No.     Time           Source                Destination           Protocol Length Info
     13 0.905037       host                  1.1.0                 USB      36     GET DESCRIPTOR Request STRING

Frame 13: 36 bytes on wire (288 bits), 36 bytes captured (288 bits) on interface wireshark_extcap1108, id 0
USB URB
Setup Data
    bmRequestType: 0x80
    bRequest: GET DESCRIPTOR (6)
    Descriptor Index: 0x02
    bDescriptorType: STRING (0x03)
    Language Id: English (United States) (0x0409)
    wLength: 202

No.     Time           Source                Destination           Protocol Length Info
     14 0.907037       1.1.0                 host                  USB      46     GET DESCRIPTOR Response STRING

Frame 14: 46 bytes on wire (368 bits), 46 bytes captured (368 bits) on interface wireshark_extcap1108, id 0
USB URB
STRING DESCRIPTOR
    bLength: 16
    bDescriptorType: 0x03 (STRING)
    bString: FM Mous
Leftover Capture Data: 6500

No.     Time           Source                Destination           Protocol Length Info
     15 0.907037       host                  1.1.0                 USB      36  
   GET DESCRIPTOR Request STRING

Frame 15: 36 bytes on wire (288 bits), 36 bytes captured (288 bits) on interface wireshark_extcap1108, id 0
USB URB
Setup Data
    bmRequestType: 0x80
    bRequest: GET DESCRIPTOR (6)
    Descriptor Index: 0x78
    bDescriptorType: STRING (0x03)
    Language Id: English (United States) (0x0409)
    wLength: 402

No.     Time           Source                Destination           Protocol Length Info
     16 0.908037       1.1.0                 host                  USB      34     GET DESCRIPTOR Response STRING

Frame 16: 34 bytes on wire (272 bits), 34 bytes captured (272 bits) on interface wireshark_extcap1108, id 0
USB URB
STRING DESCRIPTOR
    bLength: 6
    bDescriptorType: 0x03 (STRING)
    bString: 缀ဖ
```

一つ目のGET DESCRIPTORはRequestに対し、Responseで固定のUTF16の文字列を返しています。二つ目の方はResponseが文字化けしていますが、4バイトのバイナリーのようです。RequestのDescriptor Indexに対しての反応になっているようです。

いろいろ試してみるとバイナリは以下のようなデータになっています。

|放送局|周波数|データ|
|:--|:--|:--|
|Tokyo-FM|80.0|0x00,0xff,0x15,0xa8|
|J-wave|81.3|0x00,0x7f,0x16,0x10|
|NHK-FM|82.5|0x00,0x7f,0x16,0x70|

どうも最後の2バイトは周波数ぽいです。2バイト目は受信状態のようです。

NHK-FMの0x1670からJ-waveの0x1610を引くと96で8で割ると12になり10倍した周波数の差に一致します。同じようにJ-waveとTokyo-FMの間も同じロジックで計算できます。

MacのIOUSBで同じリクエストを作ってみます。

```c
    kern_return_t               kr;
    IOUSBDevRequest request;
    char devDesc[1024];

    request.bmRequestType = 0x80;
    request.bRequest = kUSBRqGetDescriptor;
    request.wValue = kUSBStringDesc << 8 | 0x02;
    request.wIndex = 0x0409;
    request.wLength = sizeof(devDesc);
    request.pData = &devDesc;
    request.wLenDone = 0;

    kr = (*dev)->DeviceRequest(dev, &request);
    if (kr != kIOReturnSuccess)
    {
            printf("Unable to DeviceRequest: %08x\n", kr);
    }
```

0x78の方も同じようにして作って、AppleのUSBのサンプルコートに突っ込んでみました。

libusbで作っても良かったのですが、すぐにコンパイルできるIOUSBで作りました。

ラジオが鳴るようになりました。どうも最後に選局した周波数をEPROMなどに入れているようで、上の二つのリクエストで、前に選局していた放送局を受信し始めるようです。

後は選局ですが、これもwiresharkで調べたら以下のようなデータが流れていました。

kUSBRqGetDescriptor 0x79 -> kUSBRqGetDescriptor 周波数上位バイト -> kUSBRqGetDescriptor 周波数下位バイト

選局できました。

コードはここに置いてあります。

https://github.com/yamori813/fmmou

アンテナの調整とパソコンからのノイズの対策が必要です。パソコンと接続しているので、ノイズがちょっと厳しい気がします。

ワイドFM入るようです。

今はストリーミングもありますがStay Homeにはラジオもよいですよ。

PCMCIAのFMラジオカードもあるのですが、もはやPCMCIAは普通に使えません。USBは素晴らしいと思います。