LoginSignup
1
1

More than 5 years have passed since last update.

FS01BU を USB シリアルに切り替える

Last updated at Posted at 2016-05-11

FS01BU は初期状態では Mass Storage (USB メモリ) である

FS01BU を単純に USB ポートに差し込むと Mass Storage であるとだけしか認識されない。モデムになってほしい。どうやら Linux では usb-modeswitch なるものをインストールするとベンダー特有のコマンドを発行してモードを切り替えることが出来るらしい。

usb-modeswitch は使ったことがないので上のリンク先を見てもらうことにして、ここでは Zynq で直に USB しりあるに切り替えてみたい。

USB-modeswitch から情報得る

USB-modeswitch のサイトから usb-modeswitch-data をとってくる。このファイルを展開すると、usb_modeswitch.d というディレクトリになにやら ID をそのまま名前にしたファイルがある。FS01BU は 1c9e:98ff 。

1c9e|98ff
# Telewell TW-3G HSPA+, FS01BU 3G, SmartBro WM66E
TargetVendor=0x1c9e
TargetProductList="6801,9801,9803"
MessageContent="55534243123456780000000080000606f50402527000000000000000000000"

55 53 42 43 は CBW のパケットだ。この Mass Storage 用のパケットを送ってやればシリアルに切り替わるに違いない。

まずは普通に GET DESCRIPTOR (DEVICE)

device.txt
12
01
00 02
00
00
00
40
9e 1c (Vendor ID = 0x1c9e)
ff 98 (Product ID = 0x98ff)
00 00
03
02
04
01

作業は Zynq で行った。過去の記録が参考になる。(FS01BU (Mass Storage)を解析してみた )

Bulk 転送でデータを投げてみる。

Bluk 転送で上のデータを endpoint 1 になげてみる(OUTトランザクション)。

bulk.c
    dbp[0] = 0x55;
    dbp[1] = 0x53;
    dbp[2] = 0x42;
    dbp[3] = 0x43;

    dbp[4] = 0x12;
    dbp[5] = 0x34;
    dbp[6] = 0x56;
    dbp[7] = 0x78;

    dbp[8] = 0x0;
    dbp[9] = 0x0;
    dbp[10] = 0x0;
    dbp[11] = 0x0;

    dbp[12] = 0x80;
    dbp[13] = 0x00;
    dbp[14] = 0x06;

    dbp[15] = 0x06;
    dbp[16] = 0xf5;
    dbp[17] = 0x04;
    dbp[18] = 0x02;
    dbp[19] = 0x52;
    dbp[20] = 0x70;
    for( i = 21 ; i < 32; ++i ) {
        dbp[i] = 0;
    }

転送するバイト数は 31 バイト。(上では 32 バイト目まで初期化しているが)00 も必要なので注意(21 バイトだと完了しない)。

通常は CBW を送るとその後データのやり取りやら、CSW の受信などをするのだが、このケースでは FS01BU は突然状態を変える(みたい)。具体的には USBSTS(0x144) の PCD ビット(2ビット目) を 1 にする。PCD = Port Change Detect。(Zynq の仕様書では PCI になっている気が、、、ついでに書くと OUT が DUT になってたりもする)。

ポートの活性化

更に、PORTSC1 の状態を xmd 見ると次のようになっている。

xmd
XMD% mrd 0xe0002184
E0002184:   8000180B

これをざっくり読むと Full Speed で Port Enabled Change が 1 になっている。Port Enable は 0 でまだ初期化されていない。そこで、0x100 を書き込んでポートを使えるようにする。その結果、PORTSC1 は次のようになる。

xmd
XMD% mrd 0xe0002184
E0002184:   80001805

あらためて GET DESCRIPTOR してみる

GET DESCRIPTOR のコントロール転送をして FS01BU からの返事をもらおう。それが次の結果。

gdb.txt
(gdb) next
1160        iQH[0] = (uint32_t)iQH | 0x2 ;
(gdb)
1162        vid = dbp[4096 + 8];
(gdb)
1163        vid += dbp[4096 + 9] << 8;
(gdb)
1164        printf("Vendor ID 0x%04x\n", vid);
(gdb) p /x vid
$22 = 0x1c9e
(gdb) next
1165        if ( vid != 0x1c9e ) {
(gdb)
1169        pid = dbp[4096 + 10];
(gdb)
1170        pid += dbp[4096 + 11] << 8;
(gdb)
1171        printf("Product ID 0x%04x\n", pid);
(gdb) p /x pid
$23 = 0x6801

見事に pid は 0x6801 になってくれた。(え?プログラムがダサい?そのうち改良されるでしょう、、、、)

結論:FS01BU は特別な処理をすることでモデムになる

Linux で使うなら、こんなことしなくても usb-modeswitch でかんたんにできる(はず)。

1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1