• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            USB系列之二:讀取USB設(shè)備的描述符

            在前面的文章中,我們已經(jīng)給出了USB協(xié)議的鏈接地址,從這篇文章起,我們會(huì)涉及到許多USB 1.1的內(nèi)容,我們的指導(dǎo)思想是先從熟悉USB 1.1協(xié)議入手,先使用現(xiàn)成的HCD和USBD,直接面對(duì)客戶端驅(qū)動(dòng)編程,盡快看到成果,使讀者對(duì)USB的開(kāi)發(fā)充滿信心,進(jìn)而去研究USBD和HCD的編程方法。請(qǐng)讀者自行閱讀協(xié)議,文章中有關(guān)協(xié)議的詳細(xì)情況,由于會(huì)涉及非常多的文字,恕不能過(guò)多解釋。
            1、USB系統(tǒng)主機(jī)端的軟件結(jié)構(gòu)
                一般來(lái)說(shuō),教科書(shū)或者協(xié)議上都會(huì)把USB主機(jī)端的軟件說(shuō)成有三層,第一層叫主機(jī)控制器驅(qū)動(dòng)程序HCD(Host Controller Driver),第二層叫USB驅(qū)動(dòng)程序USBD(USB Driver),第三層叫客戶端驅(qū)動(dòng)程序(Client Driver);實(shí)際上,我們實(shí)際看到的東西,往往HCD和USBD是由一個(gè)程序完成的,比如windows就提供了HCD和USBD,如果你自己開(kāi)發(fā)了一個(gè)USB設(shè)備,只需要在HCD和USBD上面開(kāi)發(fā)一個(gè)客戶端驅(qū)動(dòng)程序即可;linux也是同樣,linux內(nèi)核已經(jīng)提供了HCD和USBD;所以在 windows和linux下我們基本上沒(méi)有開(kāi)發(fā)HCD和USBD的必要,而且linux還提供源代碼;但DOS就不一樣了,DOS本身對(duì)USB沒(méi)有任何支持,所以要想在DOS下徹底玩轉(zhuǎn)USB,需要研究HCD、USBD和客戶端驅(qū)動(dòng)程序。
            2、DOSUSB介紹
                很顯然,HCD和USBD更加底層一些,需要理解的東西也更多一些;如果我們能夠繞過(guò)HCD和USBD,直接從客戶端驅(qū)動(dòng)程序入手,將會(huì)容易許多。幸運(yùn)的是我們可以找到一個(gè)免費(fèi)的DOS下的USB驅(qū)動(dòng)程序,叫DOSUSB,該驅(qū)動(dòng)程序?qū)崿F(xiàn)了大部分的HCD和USBD的功能,使我們進(jìn)行USB編程的好幫手。
                DOSUSB目前還沒(méi)有實(shí)現(xiàn)EHIC的驅(qū)動(dòng),也就是說(shuō)還不支持USB2.0,這也是我們從USB 1.1開(kāi)始的原因之一,另一方面,由于USB2.0是兼容USB1.1的,所以,即便你在USB2.0的設(shè)備下,仍然可以使用USB1.1的驅(qū)動(dòng)程序,只不過(guò)不能實(shí)現(xiàn)480MB/秒的傳送速度而已。
                下面我們介紹一下DOSUSB。DOSUSB的官方網(wǎng)站如下:
                http://www.usbdos.net

                可以從其官方網(wǎng)站上下載DOGUSB的最新版本,當(dāng)前版本是1.1.1。或者在下面在下面網(wǎng)址下載這個(gè)版本的DOSUSB。

                http://blog.hengch.com/software/dosusb/dosusb.zip

                DOSUSB可以在非商業(yè)領(lǐng)域免費(fèi)使用,如果肯花費(fèi)費(fèi)用,可以購(gòu)買(mǎi)到源代碼,從其官方網(wǎng)站的論壇上看到,在2006年9月作者開(kāi)出的源代碼的價(jià)格是 1000歐元。

                DOSUSB的安裝十分簡(jiǎn)便,只需要解壓縮到某一個(gè)目錄下即可,比如放在c:\dosusb目錄下,請(qǐng)自行閱讀DOSUSB自帶的文檔,使用也非常簡(jiǎn)單,在DOS提示符下鍵入dosusb執(zhí)行即可。

                c:\dosusb>dosusb

                缺省情況下,DOSUSB使用int 65h作為其驅(qū)動(dòng)的調(diào)用軟中斷,如果和你的系統(tǒng)有沖突,在運(yùn)行dosusb時(shí)可以加參數(shù)/I,請(qǐng)自行閱讀DOSUSB的文檔。

                DOSUSB通過(guò)一個(gè)叫做URB(USB Request Block)的數(shù)據(jù)結(jié)構(gòu)與客戶端驅(qū)動(dòng)程序進(jìn)行通訊,這一點(diǎn)和linux非常相似,估計(jì)作者參考了linux下的源代碼,在DOSUSB文檔里給出了這個(gè)結(jié)構(gòu)的定義,如下:
                struct {
                  BYTE  transaction_type;   // 設(shè)置事務(wù)(控制傳輸)(2Dh),輸入事務(wù)(69h)輸出事務(wù)(E1h)
                  BYTE  chain_end_flag;     // 備用
                  BYTE  dev_add;            // 設(shè)備地址
                  BYTE  end_point;          // 端點(diǎn)號(hào)
                  BYTE  error_code;         // 錯(cuò)誤嗎
                  BYTE  status;             // 設(shè)備狀態(tài)
                  WORD  transaction_flags;  // 備用
                  WORD  buffer_off;         // 接收/發(fā)送緩沖區(qū)偏移地址
                  WORD  buffer_seg;         // 接收/發(fā)送緩沖區(qū)段地址
                  WORD  buffer_length;      // 接收/發(fā)送緩沖區(qū)長(zhǎng)度
                  WORD  actual_length;      // 接收/發(fā)送時(shí)每個(gè)包的最大長(zhǎng)度
                  WORD  setup_buffer_off;   // setup_request結(jié)構(gòu)的偏移地址
                  WORD  setup_buffer_seg;   // setup_request結(jié)構(gòu)的段地址
                  WORD  start_frame;        // 備用
                  WORD  nr_of_packets;      // >0時(shí)會(huì)啟動(dòng)實(shí)時(shí)傳輸
                  WORD  int_interval;       // 備用
                  WORD  error_count;        // 重試的次數(shù)
                  WORD  timeout;            // 備用
                  WORD  next_urb_off;       // 備用
                  WORD  next_urb_seg;       // 備用
                } urb                       // 32字節(jié)
                之所以列出這個(gè)結(jié)構(gòu),是因?yàn)槲覀儗⑹褂眠@個(gè)結(jié)構(gòu)與USBD進(jìn)行交互。關(guān)于結(jié)構(gòu)中字段的定義,在DOSUSB的文檔中有詳細(xì)的說(shuō)明。除備用字段不需要填以外,error_code和status由DOSUSB返回,故填0即可,后面還會(huì)介紹更詳細(xì)的填寫(xiě)方法。

                在DOSUSB的發(fā)行包中,有一個(gè)sample目錄,里面有很多例子,但大多是使用power basic寫(xiě)的,不過(guò)仍然有很好的參考價(jià)值。

            3、 USB 1.1協(xié)議中的一些內(nèi)容

                USB協(xié)議為USB設(shè)備定義了一套描述設(shè)備功能和屬性的固有結(jié)構(gòu)的描述符,包括標(biāo)準(zhǔn)描述符(設(shè)備描述符、培植描述符、接口描述符、端點(diǎn)描述符和字符串描述符),還有費(fèi)標(biāo)準(zhǔn)描述符,如類(lèi)描述符等。按照協(xié)議,設(shè)備描述符下可以有若干個(gè)配置描述符,每個(gè)配置描述符可以有若干個(gè)接口描述符,每個(gè)接口描述符下又可以有若干個(gè)端點(diǎn)描述符,字符串描述符主要用于描述一些文字信息,比如廠家名稱(chēng),產(chǎn)品名稱(chēng)等。這篇文章的目的就是要讀出這些描述符。

                實(shí)際上,所謂描述符就是一個(gè)數(shù)據(jù)結(jié)構(gòu),不管是什么描述符,其前兩個(gè)字節(jié)的含義都是一樣的,第一個(gè)字節(jié)是描述符的長(zhǎng)度,第二個(gè)字節(jié)是描述符的類(lèi)型。

            • 設(shè)備描述符(Device Descriptor):

                struct {
                  BYTE    bLength;            // 描述符的長(zhǎng)度,以字節(jié)為單位
                  BYTE    bDescriptorType;    // 設(shè)備描述符類(lèi)型,0x01
                  WORD    bcdUSB;             // 設(shè)備支持的USB協(xié)議版本,BCD碼
                  BYTE    bDeviceClass;       // 設(shè)備類(lèi)代碼(由USB-IF分配)
                  BYTE    bDeviceSubClass;    // 子類(lèi)代碼
                  BYTE    bDeviceProtocol;    // 協(xié)議碼
                  BYTE    bMaxPacketSize0;    // 端點(diǎn)0的最大包長(zhǎng)度(僅為8,16,32,64)
                  WORD    idVendor;           // 廠商ID(由USB-IF分配)
                  WORD    idProduct;          // 產(chǎn)品ID(由制造商定義)
                  WORD    bcdDevice;          // 設(shè)備發(fā)行號(hào)(BCD碼)
                  BYTE    iManufacture;       // 描述廠商信息的字符串描述符的索引值
                  BYTE    iProduct;           // 描述產(chǎn)品信息的字符串描述符的索引值
                  BYTE    iSerialNumber;      // 描述設(shè)備序列號(hào)信息的字符串描述符的索引值
                  BYTE    bNumConfigurations; // 可能的配置描述符的數(shù)目
                } device_descriptor

            • 配置描述符 (Configuration Descriptor)

                struct {
                  BYTE    bLength;             // 描述符的長(zhǎng)度,以字節(jié)為單位
                  BYTE    bDescriptorType;     // 配置描述符類(lèi)型,0x02
                  WORD    wTotalLength;        // 配置信息的總長(zhǎng)
                  BYTE    bNumInterfaces;      // 該配置所支持的接口數(shù)目
                  BYTE    bConfigurationValue; // 被SetCongiguration()請(qǐng)求用做參數(shù)來(lái)選定該配置
                  BYTE    bConfiguration;      // 描述該配置的字符串描述符的索引值
                  BYTE    bmAttributes;        // 配置特性
                  BYTE    MaxPower;            // 該配置下的總線電源耗費(fèi)量,以2mA為一個(gè)單位 
                }configuration_descriptor;

                bmAttributes :b7:備用,b6:自供電,b5:遠(yuǎn)程喚醒,b4--b0:備用

                另外,在讀取配置描述符時(shí)可以把該配置下的所有描述符全部讀出,這些描述符的總長(zhǎng)度就是wTotalLength字段的值,讀出所有描述符后,在一個(gè)一個(gè)地拆分。

            • 接口描述符(Interface Descriptor):

                struct {
                  BYTE    bLength;            // 描述符的長(zhǎng)度,以字節(jié)為單位
                  BYTE    bDescriptorType;    // 接口描述符類(lèi)型,0x04
                  BYTE    bInterfaceNumber;   // 接口號(hào),從0開(kāi)始
                  BYTE    bAlternateSetting;  // 可選設(shè)置的索引值.
                  BYTE    bNumEndpoints;      // 此接口的端點(diǎn)數(shù)量。 
                  BYTE    bInterfaceClass;    // 接口類(lèi)編碼(由USB-IF分配)
                  BYTE    bInterfaceSubClass; // 接口子類(lèi)編碼(由USB-IF分配)
                  BYTE    bInterfaceProtocol; // 協(xié)議碼(由USB-IF分配)
                  BYTE    iInterface;         // 描述該接口的字符串描述符的索引值
                }interface_descriptor;

                bInterfaceClass:USB協(xié)議根據(jù)功能將不同的接口劃分成不同的類(lèi),如下:

                1:音頻類(lèi),2:CDC控制類(lèi),3:人機(jī)接口類(lèi)(HID),5:物理類(lèi),6:圖像類(lèi),7:打印機(jī)類(lèi),8:大數(shù)據(jù)存儲(chǔ)類(lèi),9:集線器類(lèi),10:CDC數(shù)據(jù)類(lèi),11:智能卡類(lèi),13:安全類(lèi),220:診斷設(shè)備類(lèi),224:無(wú)線控制類(lèi),254:特定應(yīng)用類(lèi),255廠商定義的設(shè)備。

            •  端點(diǎn)描述符(Endpoint Descriptor):

                struct {
                  BYTE    bLength;            // 描述符的長(zhǎng)度,以字節(jié)為單位
                  BYTE    bDescriptorType;    // 端點(diǎn)描述符類(lèi)型,0x05
                  BYTE    bEndpointAddress;   // 端點(diǎn)地址
                  BYTE    bmAttributes;       // 在bconfigurationValue所指的配置下的端點(diǎn)特性.
                  WORD    wMaxPacketSize;     // 接收/發(fā)送的最大數(shù)據(jù)報(bào)長(zhǎng)度. 
                  BYTE    bInterval;          // 周期數(shù)據(jù)傳輸端點(diǎn)的時(shí)間間隙.
                }endpoint_descriptor;

                bmAttributes:bit 1:0--傳送類(lèi)型,00=控制傳輸,01=實(shí)時(shí)傳輸,10=批量傳輸,11=中斷傳輸;所有其他位均保留。

            • 字符串描述符(String Descriptor):

                struct {
                  BYTE    bLength;            // 描述符的長(zhǎng)度,以字節(jié)為單位
                  BYTE    bDescriptorType;    // 字符串描述符類(lèi)型,0x03
                  char    bString[];          // UNICODE編碼的字符串
                }string_descriptor;

            • USB命令請(qǐng)求(USB DEVICE REQUEST)

                為了更好地協(xié)調(diào)USB主機(jī)與設(shè)備之間的數(shù)據(jù)通信,USB規(guī)范定義了一套命令請(qǐng)求,用于完成主機(jī)對(duì)總線上所有USB設(shè)備的統(tǒng)一控制,USB命令請(qǐng)求由統(tǒng)一的格式,其結(jié)構(gòu)如下:

                struct {
                  BYTE  bmRequestType;  // 請(qǐng)求類(lèi)型
                  BYTE  bRequest;       // 命令請(qǐng)求的編碼
                  WORD  wValue;         // 命令不同,含義不同
                  WORD  wIndex;         // 命令不同,含義不同 
                  WORD  wLength;        // 如果有數(shù)據(jù)階段,此字段為數(shù)據(jù)字節(jié)數(shù)

                }
             setup_request;

                后面我們向設(shè)備發(fā)出指令就全靠這個(gè)結(jié)構(gòu)了。作為我們本文要用到的讀取USB設(shè)備描述符的命令請(qǐng)求,該結(jié)構(gòu)各字段的填法如下。

                bmRequestType : b7--數(shù)據(jù)傳輸方向,0=主機(jī)到設(shè)備,1=設(shè)備到主機(jī);b6:5--命令的類(lèi)型,0=標(biāo)準(zhǔn)命令,1=類(lèi)命令,2=廠商提供的命令,3=保留;b4:0--接收對(duì)象,0=設(shè)備,1=接口,2=端點(diǎn),3=其他。我們發(fā)出的得到描述符的命令,數(shù)據(jù)傳輸方向?yàn)樵O(shè)備到主機(jī),標(biāo)準(zhǔn)命令,接收對(duì)象為設(shè)備,所以該字段填0x80。

                bRequest : 標(biāo)準(zhǔn)命令的編碼如下,GET_STATUS=0;CLEAR_FEATURE=1;SET_FEATURE=3; SET_ADDRESS=5;GET_DESCRIPTOR=6;SET_DESCRIPTOR=7;GET_CONFIGURATION=8; SET_CONFIGURATION=9;GET_INTERFACE=10;SET_INTERFACE=11;SYNCH_FRAME=12。我們的命令是GET_DESCRIPTOR,所以應(yīng)該填6。

                wValue : 高字節(jié)表示描述符的類(lèi)型,0x01=設(shè)備描述符,0x02=配置描述符,0x03=字符串描述符,0x04=接口描述符,0x05=端點(diǎn)描述符,0x29=集線器類(lèi)描述符,0x21=人機(jī)接口類(lèi)描述符,0xFF=廠商定義的描述符。

                低字節(jié)表示表示描述符的索引值。所以,當(dāng)讀取設(shè)備描述符時(shí),該字段值為0x100,當(dāng)讀取配置描述符是,應(yīng)為0x03yy,其中yy為描述符的索引值。

                wIndex : 當(dāng)讀取字符串描述符時(shí),填0x0409,表示希望獲得英文字符串,其他情況下填0。

                wLength : 數(shù)據(jù)長(zhǎng)度,一般應(yīng)該填寫(xiě),描述符的第一個(gè)字節(jié),bLength。由于我們?cè)谧x描述符時(shí),并不知道其實(shí)際長(zhǎng)度,通常的做法是先讀取8個(gè)字節(jié),然后根據(jù)第一個(gè)字節(jié)bLength的值在重新讀取一次完整的描述符;注意,當(dāng)讀取配置描述符的錢(qián)8個(gè)字節(jié)后,應(yīng)該使用wTotalLength字段的值作為長(zhǎng)度讀取與該配置有關(guān)的所有描述符。

            4、讀取設(shè)備描述符的范例程序

                按照我們文章的習(xí)慣,幾乎每篇文章都有一個(gè)范例程序,本文也不例外,本文的范例程序請(qǐng)?jiān)谙旅娴刂废螺d:

                http://blog.hengch.com/source/usbview.zip

                程序用C++寫(xiě)成,在DJGPP下編譯通過(guò),所以是32位保護(hù)模式下的代碼,要注意的是,DOSUSB是實(shí)模式下的驅(qū)動(dòng),所以在申請(qǐng)內(nèi)存塊時(shí)要申請(qǐng)1M以內(nèi)實(shí)模式可以讀取的內(nèi)存,否則,在使用int 65h調(diào)用DOSUSB時(shí)一定會(huì)出現(xiàn)問(wèn)題。

                有4個(gè)頭文件,public.h中定義了一些方便使用的數(shù)據(jù)類(lèi)型,比如BYTE為char,WORD為short int等等,可以不必太關(guān)注;x86int.h中定義了調(diào)用DOS中斷所需的函數(shù)和數(shù)據(jù)結(jié)構(gòu),直到怎么使用就可以了;dosmem.h中定義了一個(gè) DOS_MEM類(lèi),主要是為了在保護(hù)模式下申請(qǐng)和使用DOS內(nèi)存塊更為方便,也是知道其中的方法,能夠明白程序中的意義就可以了;usb.h定義了與 USB協(xié)議有關(guān)的所有常數(shù),這些常數(shù)與前面介紹的各種數(shù)據(jù)結(jié)構(gòu)一一對(duì)應(yīng),由于我們是在保護(hù)模式下使用DOS內(nèi)存,所以把一個(gè)內(nèi)存塊映射到一個(gè)數(shù)據(jù)結(jié)構(gòu)上有一些麻煩,讀取各個(gè)字段主要靠在usb.h中定義的這些常數(shù)。

                主要程序在usbview.cc中,主要思路如下:

            • USB 設(shè)備的地址從1--127,所以我們從1--127做一個(gè)循環(huán),逐一讀取USB設(shè)備描述符,直到出現(xiàn)“非法地址”為止。
            • 每一個(gè)USB設(shè)備的設(shè)備描述符只有一個(gè),所以我們從讀取某個(gè)地址下的設(shè)備描述符開(kāi)始。
            • 開(kāi)始我們并不知道設(shè)備描述符的長(zhǎng)度,即便我們知道其長(zhǎng)度為18個(gè)字符,但我們?nèi)匀徊恢蓝它c(diǎn)0允許的包長(zhǎng)度(設(shè)備描述符中bMaxPacketSize0字段),但我們知道包長(zhǎng)度的最小值是8,所以我們先讀取8個(gè)字節(jié)的設(shè)備描述符。
            • 在我們得到8個(gè)字符的設(shè)備描述符后,我們就可以得到該描述符的長(zhǎng)度和端點(diǎn)0的包長(zhǎng)度,在后面發(fā)出的所有命令中,始終要把這個(gè)值填在URB結(jié)構(gòu)的actual_length字段中。
            • buffer用于存放USBD返回的描述符,在使用前建議初始化一下,全部清0。
            • 要向設(shè)備發(fā)出命令請(qǐng)求(Request),需要先填setup_request結(jié)構(gòu),前面講過(guò),bmRequestType=0x80,bRequest=6,這兩個(gè)字段的填法始終不變;我們現(xiàn)在讀取設(shè)備描述符,所以 wValue=0x100,wIndex=0,wLength在首次調(diào)用時(shí)填8,第二次調(diào)用時(shí)填返回的bLength字段(應(yīng)該是18)。
            • 準(zhǔn)備好buffer和setup_request后,我們要填URB一邊與DOSUSB交互;讀取描述符是一個(gè)控制傳輸,所以transaction=0x2D(后面一直是0x2D);dev_add填上面提到的循環(huán)變量;end_point=0,因?yàn)槲覀兛倢?duì)端點(diǎn)0(見(jiàn)USB協(xié)議);buffer_off和buffer_seg分別填buffer的便宜地址和段地址;setup_buffer_off和setup_buffer_seg分別填前面setup_request結(jié)構(gòu)的偏移地址和段地址;buffer_length同setup_request結(jié)構(gòu)中的wLength,也可以把值設(shè)在wLength和buferr的最大長(zhǎng)度之間,如果 buffer的最大長(zhǎng)度小于wLength,我們只能填buffer的最大長(zhǎng)度,但這種情況下我們將得不到完整的描述符;actual_length在第一次調(diào)用時(shí)填8,以后一直填返回的bMaxPacketsize0字段;其他字段均為0。
            • 讓DS:DX指向剛剛填完的URB結(jié)構(gòu),調(diào)用軟中斷65h,DOSUSB將為你處理下面的事情。
            • 如果正常,error_code應(yīng)該返回0,如果非0,含義如下:
              1--非法的設(shè)備地址;2--內(nèi)部錯(cuò)誤;3--非法的transation_type字段;4--非法的buffer長(zhǎng)度。
            • 如果正常,status字段應(yīng)該為0,該字段是是USB控制器返回的狀態(tài)字節(jié),不同的控制器(OHCI或 UHCI)會(huì)返回不同的值。
            • 當(dāng)我們得到設(shè)備描述符后,如果設(shè)備描述符中的iManufacturer字段不為0,我們可以根據(jù)這個(gè)所引值得到相應(yīng)的字符串描述符,從而顯示出廠家信息,要注意的是字符串描述符是 UNICODE編碼,對(duì)于ASCII而言,它是一個(gè)ASSCII碼跟一個(gè)ASCII 0組成;同理我們可以得到產(chǎn)品信息和序列號(hào)信息。
            • 當(dāng)我們得到了設(shè)備的設(shè)備描述符后,我們就可以知道這個(gè)設(shè)備上有多少個(gè)配置(設(shè)備描述符中的 bNumConfigurations),進(jìn)而通過(guò)一個(gè)循環(huán)得到所有的配置描述符及其配置下的所有描述符。
            • 讀取配置描述符的方法與讀取設(shè)備描述符大同小異,也是先讀取8個(gè)字節(jié),然后根據(jù)返回的內(nèi)容再讀取所有的描述符內(nèi)容,要注意的是,實(shí)際上,我們不能單獨(dú)得到接口描述符和端點(diǎn)描述符,唯一的辦法是把一個(gè)配置下的描述符全部讀出來(lái),所以setup_request結(jié)構(gòu)中的wLength字段一定要與配置描述符中返回的wTotalLength值一致才行。
            • 剩下的事情就是如何顯示我們得到的描述符,我想這對(duì)每一位讀者而言都不是什么困難的事。

             

             原文地址 http://hengch.blog.163.com/blog/static/107800672008423111324286/

            posted on 2010-11-21 13:16 wrh 閱讀(1046) 評(píng)論(0)  編輯 收藏 引用


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            導(dǎo)航

            <2009年6月>
            31123456
            78910111213
            14151617181920
            21222324252627
            2829301234
            567891011

            統(tǒng)計(jì)

            常用鏈接

            留言簿(19)

            隨筆檔案

            文章檔案

            收藏夾

            搜索

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            狠狠色丁香久久婷婷综合| 狠狠狠色丁香婷婷综合久久五月| 久久激情五月丁香伊人| 精品久久久久国产免费| 看全色黄大色大片免费久久久 | 18岁日韩内射颜射午夜久久成人| 久久精品国产2020| 国产成人综合久久综合| 久久97久久97精品免视看| 2021久久精品免费观看| 精品999久久久久久中文字幕| 激情久久久久久久久久| 97久久国产综合精品女不卡| 亚洲国产成人久久综合一| 久久精品综合网| 国产精品内射久久久久欢欢| 伊人久久综合无码成人网| 久久久久亚洲AV成人网人人软件 | 欧美777精品久久久久网| 久久久这里有精品| 亚洲欧洲精品成人久久曰影片| av无码久久久久不卡免费网站| 亚洲色大成网站www久久九| 99久久99久久| 亚洲国产精品一区二区三区久久| 一本一道久久精品综合| 久久久国产精品亚洲一区| 一级A毛片免费观看久久精品| 99久久国产免费福利| 999久久久免费精品国产| 97精品依人久久久大香线蕉97| 一级A毛片免费观看久久精品| 久久se精品一区二区影院| 激情综合色综合久久综合| 久久国产精品99久久久久久老狼 | 久久免费99精品国产自在现线 | 超级碰久久免费公开视频| 久久国产精品国产自线拍免费| 亚洲乱码精品久久久久..| 国产成人无码精品久久久性色| 久久久久久国产精品美女|