0

ソースコードを調べて、 を使用して収集した USB I/O 16 進ダンプと関連付けることで、USB Wi-Fi カードの Linux ドライバーを理解しようとしていますusbmon。これは非常にうまくいっていますが、それに似た数千のバイトのうち、ソース コードとは相関していないように見えるのは 1 バイトだけです。具体的にはLine 726/drivers/staging/rtl8187se/r8180_rtl8225z2.c(Linux カーネル ソース ディレクトリ内) にあります。

write_phy_ofdm(dev, 0x02, 0x62); mdelay(1);

この行は 4 つの USB 書き込み、つまり 3 番目の書き込みペイロードが0x62. 代わりに、ネットワークusbmon上で送信されると報告された 3 番目の書き込みペイロードは0x42(not 0x62) です。説明のために、この特定の呼び出しの出力を次に示しusbmonます (2 行ごとの最後の列は、4 つのペイロード0x000x000x42です0x82)。

ffff88011d317600 2404077138 S Co:2:004:0 s 40 05 ff7f 0000 0001 1 = 00
ffff88011d317600 2404077255 C Co:2:004:0 0 1 >
ffff88008d9a0600 2404077263 S Co:2:004:0 s 40 05 ff7e 0000 0001 1 = 00
ffff88008d9a0600 2404077380 C Co:2:004:0 0 1 >
ffff88011d317000 2404077388 S Co:2:004:0 s 40 05 ff7d 0000 0001 1 = 42
ffff88011d317000 2404077505 C Co:2:004:0 0 1 >
ffff88008d9a09c0 2404077513 S Co:2:004:0 s 40 05 ff7c 0000 0001 1 = 82  

以下は、関連する関数定義です。

/drivers/staging/rtl8187se/r8180_core.c

inline void write_phy_ofdm(struct net_device *dev, u8 adr, u32 data)
{
    data = data & 0xff;
    rtl8185_write_phy(dev, adr, data);
}

void rtl8185_write_phy(struct net_device *dev, u8 adr, u32 data) {  

    u32 phyw;

    adr |= 0x80;

    phyw = ((data<<8) | adr);

    /* Note that, we must write 0xff7c after 0x7d-0x7f to write BB register. */
    write_nic_byte(dev, 0x7f, ((phyw & 0xff000000) >> 24));
    write_nic_byte(dev, 0x7e, ((phyw & 0x00ff0000) >> 16));     
    write_nic_byte(dev, 0x7d, ((phyw & 0x0000ff00) >> 8));  
    write_nic_byte(dev, 0x7c, ((phyw & 0x000000ff)));

    /* this is ok to fail when we write AGC table. check for AGC table might
    be   * done by masking with 0x7f instead 
    of 0xff      */     /* if (phyr != (data&0xff)) 
    DMESGW("Phy write timeout %x %x %x", phyr, data, adr); */ 
}

void write_nic_byte(struct net_device *dev, int x, u8 y)
{
    writeb(y, (u8 *)dev->mem_start + x);
    udelay(20);
}

/arch/xtensa/include/asm/io.h

#define writeb(b, addr) (void)((*(volatile unsigned char *)(addr)) = (b))

呼び出し順序を実行すると、 から始まりwrite_phy_ofdm(dev, 0x02, 0x62);ます。 行でwrite_phy_ofdm()ビットマスクdataしますが、とにかく下位バイトのみを占有するため、これはこの時点では変更されません。したがって、引数として に渡されます。とを u32 の下位 16 ビットにパックします。は8 ビットを上にシフトするだけであり、下位 8 ビットのみを占有するため、それらを OR しても のデータ部分は変更されないことに注意してください。最初の 2 つの呼び出しは、 out の最上位バイトと 2 番目に上位のバイトをそれぞれアドレスandに書き込みます。の上位 2 バイトdata = data & 0xff0x62datawrite_phy_ofdm0x62datartl8185_write_phy()rtl8185_write_phydataadrphyw = ((data << 8) | adr);dataadrphywwrite_nic_byte()phyw0xff7f0xff7ephywが占有されていない場合、これらは0x00予想どおりの 2 つのペイロードになります。 3 番目のwrite_nic_byte()呼び出しは、私に悲しみを与えるものです。0x62データをビットシフトして最下位バイトに戻して送信するだけだと思い0x62ます。なぜそれが送信され0x42ているのかは、私を逃れるものです。

低レベルの呼び出しに対する私の理解writeb()が間違っていることを認めなければなりません。おそらく、ここで予期しないことが起こっているのでしょう。私が見つけることができる唯一の手がかりの匂いは、次の行を含む2009年からの差分にあります:(その醜い頭を育てるwrite_phy_ofdm(dev, 0x02, ((priv->card_type == USB) ? 0x42 : 0x62)); mdelay(1);値に注意してください)。0x42カーネルドライバーを再コンパイルし、rmmod rtl8187/を使用して実行中のカーネルに追加したことにもinsmod /path/to/my/compiled/.ko/file注意してください. 0x420x62

誰かが私が間違っているかもしれない場所を提案できますか? 私はすべてのアイデアがありません。

4

1 に答える 1

1

rtl8225z2_rf_init()したがって、異なるファイルに名前が付けられた 2 つの関数があるため、正しい関数定義を調べていなかったことがわかりました。1つは/drivers/staging/rtl8187se/r8180_rtl8225z2.c(実行されていない、私が見ていたバージョン)にあり、もう1つは/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c(実行されている、私が見ていない正しいバージョン)にあります。それらは微妙に異なるだけですが、一方は を使用write_phy_ofdm(dev, 0x02, 0x62);し、もう一方は を使用しますwrite_phy_ofdm(dev, 0x02, 0x42);。ここでの教訓は、Emacs でタグを使用して関数定義に移動することに依存しないことです。

于 2012-08-28T07:35:07.327 に答える