Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
85 usb_stor_access_xfer_buf((unsigned char *) &c, 4, srb,<br />
86 &index, &<strong>of</strong>fset, TO_XFER_BUF);<br />
87 }<br />
应该说看过前面我们如果处理INQRUIY 命令那个bug 的代码的同志们应该能够很容易看懂眼前这段代<br />
码.其中调用的最关键的函数就是usb_stor_access_xfer_buf(),对usb_stor_access_xfer_buf()函数<br />
陌生的同志们可以回过去看看当时咱们是如何分析的.这里75 行的作用就是从request_buffer 里边把数<br />
据copy 到c 里边去,而85 行的作用就是反过来把c 里边的数据copy 到request_buffer 里边去.而在这<br />
之间,最重要的一步自然是79 行和82 行,capacity 被赋为c,而c 再被赋为capacity-1.这样简简单单的<br />
几<br />
行代码就fix 了这么一个bug.<br />
当然,虽然我不喜欢Linux,但是我还是有必要为你解释一些事情.<br />
你是不是看见好些次这样一系列函数了:<br />
be32_to_cpu/cpu_to_be32(),cpu_to_le16(),cpu_to_le32(),此前我们一直没有讲,所以让我们现在<br />
一并来讲吧.反正整个故事的大致走向你已经很清楚了,从现在开始的故事基本上就属于一些小打小闹小修<br />
小补式的细枝末节了.le 叫做Little Endian,be 叫做Big Endian,这是两种字节序.le 就表示地址地位存<br />
储<br />
值的低位,地址高位存储值的高位.be 就表示地址低位存储值的高位,地址高位存储值的低位.我们就以这<br />
里<br />
这个临时变量c 为例.假设c 是这样被存储在内存地址0x0000 开始的地方:<br />
0x0000 0x12<br />
0x0001 0x34<br />
0x0002 0xab<br />
0x0003 0xcd<br />
182<br />
如果你是采用le 的字节序,那么读出来的值就是0xcdab3412,反之,如果你采用的是be 的字节序,那么<br />
读出来的值就是0x1234abcd.同样的,如果你把0x1234abcd 写入0x0000 开始的内存中,那么结果就<br />
是:<br />
big-endian little-endian<br />
0x0000 0x12 0xcd<br />
0x0001 0x23 0xab<br />
0x0002 0xab 0x34<br />
0x0003 0xcd 0x12<br />
为什么这几个函数名字里面都一个”cpu”?谈到字节序不谈cpu 那就好比神采飞扬的谈起超级女声却对<br />
张靓颖是何许人也茫然不知.不同的cpu 采用不同的字节序.看生产商自己喜欢了.其中,big endian 以<br />
Motolora 的PowerPC 系列cpu 为代表,而little endian 则以我家Intel 的x86 系列cpu 为代表.所以<br />
这<br />
几个函数名字里边都会有cpu 的字样,那么毫无疑问对于不同的cpu,这几个函数执行的代码是不一样的.<br />
但是,凡是xx_to_cpu 就说明函数的结果是给cpu 使用的,反之如果是cpu_to_xx 就说明是从cpu 的字<br />
节序转换成目标字节序.<br />
那么目标字节序应该是什么样子?我们先来看usb的情况.usb spec 2.0第八章,白纸黑字的规定了这么一<br />
句,usb总线上使用的是little-endian的字节序.所以,当初我们在处理bcs/bcb的时候一直在调用<br />
lexx_to_cpu/cpu_to_lexx()这样的函数,或者准确地说,这样的宏.(usb spec 2.0, Chapter 8, 8.1<br />
Byte/Bit Ordering:<br />
Bits are sent out onto the bus least-significant bit (LSb) first, followed by the next LSb,