libusb API學(xué)習(xí)筆記-2

libusb API學(xué)習(xí)筆記-2

源碼API文檔

點(diǎn)擊查看

1. 函數(shù)學(xué)習(xí)

  • 因?yàn)橐彩莿傞_(kāi)始學(xué)習(xí)佑颇,所以就根據(jù)函數(shù)的使用順序來(lái)看源碼低零。

1.1 libusb_init

  • 初始化征绸,獲取libusb的上下文對(duì)象则剃。
  • libusb是支持libusb_init(NULL)的拢切。但是有一點(diǎn)需要注意门扇,如果你在同一個(gè)進(jìn)程內(nèi)init了兩次雹有,你第二次獲得的上下文對(duì)象其實(shí)與第一次init的對(duì)象是同一個(gè)偿渡。且你在釋放上下文對(duì)象的時(shí)候,也需要釋放兩次霸奕。理由也很簡(jiǎn)單溜宽。同一個(gè)上下文對(duì)象其實(shí)是共用引用次數(shù)的,多次init也就是增加了引用次數(shù)质帅。是否的時(shí)候也是同樣的原理适揉。具體的內(nèi)容其實(shí)libusb源碼里注釋已經(jīng)都寫(xiě)的很清楚了。但如果你自己傳上下文對(duì)象進(jìn)來(lái)就沒(méi)有這個(gè)問(wèn)題了煤惩。
  • 代碼注釋libusb-1.0.22/libusb/core.c
/* In order to keep things simple for more simplistic applications, it is
legal to pass NULL to all functions requiring a context pointer (as long as
you're sure no other code will attempt to use libusb from the same process).
When you pass NULL, the default context will be used. The default context
is created the first time a process calls libusb_init() when no other
context is alive. Contexts are destroyed during libusb_exit().
The default context is reference-counted and can be shared. That means that
if libusb_init(NULL) is called twice within the same process, the two
users end up sharing the same context. The deinitialization and freeing of
the default context will only happen when the last user calls libusb_exit().
In other words, the default context is created and initialized when its
reference count goes from 0 to 1, and is deinitialized and destroyed when
its reference count goes from 1 to 0. */
  • 代碼有兩段可以看一下
int API_EXPORTED libusb_init(libusb_context **context)
{
...
...
...
if (!context && usbi_default_context) {//首先判斷一下是否傳進(jìn)來(lái)的是NULL嫉嘀,已經(jīng)默認(rèn)上下文對(duì)象是否已經(jīng)創(chuàng)建,如果是魄揉,就直接引用++剪侮,返回。這明顯是第二次init(NULL)的場(chǎng)景
  usbi_dbg("reusing default context");
  default_context_refcnt++;
  usbi_mutex_static_unlock(&default_context_lock);
  return 0;
}
...
...
...
ctx = calloc(1, sizeof(*ctx) + priv_size);
if (!ctx) {
  r = LIBUSB_ERROR_NO_MEM;
  goto err_unlock;
}
/* default context should be initialized before calling usbi_dbg */
if (!usbi_default_context) {//如果是第一次init(NULL),則進(jìn)行初始化洛退,引用次數(shù)++瓣俯。
  usbi_default_context = ctx;
  default_context_refcnt++;
  usbi_dbg("created default context");
}
...
...
...
}
  • init內(nèi)部
  • 首先第一步是將libusb_context中必要的對(duì)象進(jìn)行了初始化,包括但不限于以下三個(gè)
    • usb_devs usb設(shè)備列表
    • open_devs 已打開(kāi)的設(shè)備列表句柄
    • hotplug_cbs 熱插拔的回調(diào)函數(shù)列表
    list_init(&ctx->usb_devs);
    list_init(&ctx->open_devs);
    list_init(&ctx->hotplug_cbs);
    
  • 如果是進(jìn)程內(nèi)第一個(gè)初始化的上下文對(duì)象兵怯,會(huì)再初始化一個(gè)活躍上下文對(duì)象列表彩匕,然后將初始化后的上下文對(duì)象存進(jìn)去。libusb_context的結(jié)構(gòu)體定義在libusbi.h中媒区。
if (first_init) {
  first_init = 0;
  list_init (&active_contexts_list);
}
list_add (&ctx->list, &active_contexts_list);
  • 初始化libusb_context中io相關(guān)的參數(shù)驼仪,這一塊沒(méi)看懂

1.2 libusb_get_device_list

  • 獲取設(shè)備列表,需要注意的是獲取列表的那個(gè)參數(shù)是個(gè)三級(jí)指針袜漩,也就是說(shuō)你需要傳個(gè)二級(jí)指針的地址進(jìn)去绪爸。

  • 獲取的設(shè)備列表包括支持熱插拔和不支持熱插拔的設(shè)備。

    //ctx 上下文對(duì)象
    //list列表指針
    //返回值是設(shè)備數(shù)目
    ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx,
      libusb_device ***list);
    
    

1.3 libusb_get_device_address

  • 獲取列表地址宙攻,不需要說(shuō)太多

1.4 libusb_get_device_descriptor

  • 從代碼來(lái)看毡泻,很簡(jiǎn)單,就四行粘优,將libusb_device的device_descriptor拷貝給我們傳進(jìn)來(lái)的device_descriptor。
    我代碼中使用過(guò)的是idVendor呻顽,idProduct雹顺,我用它們?nèi)ヅ袛嘣O(shè)備是否處于AOA模式,以及是否支持AOA模式廊遍。
    AOA的PID有興趣的可以去Android官網(wǎng)看一下嬉愧。accessory mode Product ID
int API_EXPORTED libusb_get_device_descriptor(libusb_device *dev,
        struct libusb_device_descriptor *desc)
    {
        usbi_dbg("");
        memcpy((unsigned char *) desc, (unsigned char *) &dev->device_descriptor,
               sizeof (dev->device_descriptor));
        return 0;
    }

    /** \ingroup libusb_desc
   * A structure representing the standard USB device descriptor. This
   * descriptor is documented in section 9.6.1 of the USB 3.0 specification.
   * All multiple-byte fields are represented in host-endian format.
   */
  struct libusb_device_descriptor {
    /** Size of this descriptor (in bytes) */
    uint8_t  bLength;

    /** Descriptor type. Will have value
     * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE LIBUSB_DT_DEVICE in this
     * context. */
    uint8_t  bDescriptorType;

    /** USB specification release number in binary-coded decimal. A value of
     * 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1, etc. */
    uint16_t bcdUSB;

    /** USB-IF class code for the device. See \ref libusb_class_code. */
    uint8_t  bDeviceClass;

    /** USB-IF subclass code for the device, qualified by the bDeviceClass
     * value */
    uint8_t  bDeviceSubClass;

    /** USB-IF protocol code for the device, qualified by the bDeviceClass and
     * bDeviceSubClass values */
    uint8_t  bDeviceProtocol;

    /** Maximum packet size for endpoint 0 */
    uint8_t  bMaxPacketSize0;

    /** USB-IF vendor ID */
    uint16_t idVendor;

    /** USB-IF product ID */
    uint16_t idProduct;

    /** Device release number in binary-coded decimal */
    uint16_t bcdDevice;

    /** Index of string descriptor describing manufacturer */
    uint8_t  iManufacturer;

    /** Index of string descriptor describing product */
    uint8_t  iProduct;

    /** Index of string descriptor containing device serial number */
    uint8_t  iSerialNumber;

    /** Number of possible configurations */
    uint8_t  bNumConfigurations; 
};

1.5 libusb_open

  • 打開(kāi)設(shè)備,會(huì)返回一個(gè)handle喉前。為接下來(lái)的發(fā)送控制指令函數(shù)用的没酣。暫時(shí)不展開(kāi)看了王财。

1.5 libusb_control_transfer

  • 給usb設(shè)備發(fā)送控制指令,并返回發(fā)送指令的結(jié)果裕便。我目前只用過(guò)AOA模式切換的指令绒净。
    int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle,
    uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
    unsigned char *data, uint16_t wLength, unsigned int timeout)
  • 參數(shù)說(shuō)明
    • dev_handle 這就是之前l(fā)ibopen函數(shù)獲得的句柄。源碼里的解釋:a handle for the device to communicate with偿衰。說(shuō)到底就是通信用的一個(gè)設(shè)備句柄挂疆。
    • bmRequestType 請(qǐng)求字段的類型,比如我使用的是AOA相關(guān)的(LIBUSB_REQUEST_TYPE_VENDOR)下翎。源碼里我看了下缤言,有一些說(shuō)明,但也是不是很詳細(xì)视事。
      首先libusb_control_transfer函數(shù)中調(diào)用了libusb_fill_control_setup函數(shù)胆萧,然后找到了一個(gè)結(jié)構(gòu)體libusb_control_setup,里面的代碼中有一些注釋可以了解下俐东。
      “Request type. Bits 0:4 determine recipient, see ref libusb_request_recipient. Bits 5:6 determine type, see ref libusb_request_type.Bit 7 determines data transfer direction, see ref libusb_endpoint_direction.”跌穗。可以看到0-4位代表接收者的類型犬性,5-6位代表request的類型瞻离,7位代表
      數(shù)據(jù)傳輸?shù)姆较颉1热缥疫x擇是要將AOA的command發(fā)送給usb設(shè)備乒裆,那么首先libusb_request_recipient的類型應(yīng)該是“LIBUSB_RECIPIENT_DEVICE = 0x00”套利,libusb_request_type應(yīng)該是標(biāo)準(zhǔn)類型(我只知道這個(gè),其他沒(méi)研究鹤耍。肉迫。。)“LIBUSB_REQUEST_TYPE_STANDARD = (0x00 << 5)”稿黄,最后傳輸方向輸入喊衫,也就是device-to-host,“LIBUSB_ENDPOINT_IN = 0x80”杆怕,三種加起來(lái)就是“LIBUSB_RECIPIENT_DEVICE|LIBUSB_REQUEST_TYPE_STANDARD|LIBUSB_ENDPOINT_IN”族购,也就是0x40。
      還有我去Android源碼里去看了看陵珍,找到了他們的定義寝杖,比較集中,應(yīng)該包含了所有的使用類型互纯。
  //libusb源碼
  /** \ingroup libusb_desc
   * Endpoint direction. Values for bit 7 of the
   * \ref libusb_endpoint_descriptor::bEndpointAddress "endpoint address" scheme.
   */
  enum libusb_endpoint_direction {
    /** In: device-to-host */
    LIBUSB_ENDPOINT_IN = 0x80,

    /** Out: host-to-device */
    LIBUSB_ENDPOINT_OUT = 0x00
  };
  enum libusb_request_type {
    /** Standard */
    LIBUSB_REQUEST_TYPE_STANDARD = (0x00 << 5),

    /** Class */
    LIBUSB_REQUEST_TYPE_CLASS = (0x01 << 5),

    /** Vendor */
    LIBUSB_REQUEST_TYPE_VENDOR = (0x02 << 5),

    /** Reserved */
    LIBUSB_REQUEST_TYPE_RESERVED = (0x03 << 5)
  };
  /** \ingroup libusb_misc
   * Recipient bits of the
   * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control
   * transfers. Values 4 through 31 are reserved. */
  enum libusb_request_recipient {
    /** Device */
    LIBUSB_RECIPIENT_DEVICE = 0x00,

    /** Interface */
    LIBUSB_RECIPIENT_INTERFACE = 0x01,

    /** Endpoint */
    LIBUSB_RECIPIENT_ENDPOINT = 0x02,

    /** Other */
    LIBUSB_RECIPIENT_OTHER = 0x03,
  };
/** \ingroup libusb_asyncio
   * Setup packet for control transfers. */
  struct libusb_control_setup {
    /** Request type. Bits 0:4 determine recipient, see
     * \ref libusb_request_recipient. Bits 5:6 determine type, see
     * \ref libusb_request_type. Bit 7 determines data transfer direction, see
     * \ref libusb_endpoint_direction.
     */
    uint8_t  bmRequestType;

    /** Request. If the type bits of bmRequestType are equal to
     * \ref libusb_request_type::LIBUSB_REQUEST_TYPE_STANDARD
     * "LIBUSB_REQUEST_TYPE_STANDARD" then this field refers to
     * \ref libusb_standard_request. For other cases, use of this field is
     * application-specific. */
    uint8_t  bRequest;

    /** Value. Varies according to request */
    uint16_t wValue;

    /** Index. Varies according to request, typically used to pass an index
     * or offset */
    uint16_t wIndex;

    /** Number of bytes to transfer */
    uint16_t wLength;
  };
//Android源碼
#define USB_SETUP_HOST_TO_DEVICE                0x00    // Device Request bmRequestType transfer direction - host to device transfer
#define USB_SETUP_DEVICE_TO_HOST                0x80    // Device Request bmRequestType transfer direction - device to host transfer
#define USB_SETUP_TYPE_STANDARD                 0x00    // Device Request bmRequestType type - standard
#define USB_SETUP_TYPE_CLASS                    0x20    // Device Request bmRequestType type - class
#define USB_SETUP_TYPE_VENDOR                   0x40    // Device Request bmRequestType type - vendor
#define USB_SETUP_RECIPIENT_DEVICE              0x00    // Device Request bmRequestType recipient - device
#define USB_SETUP_RECIPIENT_INTERFACE           0x01    // Device Request bmRequestType recipient - interface
#define USB_SETUP_RECIPIENT_ENDPOINT            0x02    // Device Request bmRequestType recipient - endpoint
#define USB_SETUP_RECIPIENT_OTHER               0x03    // Device Request bmRequestType recipient - other
  • bRequest 請(qǐng)求字段的內(nèi)容瑟幕,例如我請(qǐng)求字段的類型是LIBUSB_REQUEST_TYPE_STANDARD時(shí),bRequest的值可能是如下:
  /** \ingroup libusb_misc
 * Standard requests, as defined in table 9-5 of the USB 3.0 specifications */
enum libusb_standard_request {
  /** Request status of the specific recipient */
  LIBUSB_REQUEST_GET_STATUS = 0x00,

  /** Clear or disable a specific feature */
  LIBUSB_REQUEST_CLEAR_FEATURE = 0x01,

  /* 0x02 is reserved */

  /** Set or enable a specific feature */
  LIBUSB_REQUEST_SET_FEATURE = 0x03,

  /* 0x04 is reserved */

  /** Set device address for all future accesses */
  LIBUSB_REQUEST_SET_ADDRESS = 0x05,

  /** Get the specified descriptor */
  LIBUSB_REQUEST_GET_DESCRIPTOR = 0x06,

  /** Used to update existing descriptors or add new descriptors */
  LIBUSB_REQUEST_SET_DESCRIPTOR = 0x07,

  /** Get the current device configuration value */
  LIBUSB_REQUEST_GET_CONFIGURATION = 0x08,

  /** Set device configuration */
  LIBUSB_REQUEST_SET_CONFIGURATION = 0x09,

  /** Return the selected alternate setting for the specified interface */
  LIBUSB_REQUEST_GET_INTERFACE = 0x0A,

  /** Select an alternate interface for the specified interface */
  LIBUSB_REQUEST_SET_INTERFACE = 0x0B,

  /** Set then report an endpoint's synchronization frame */
  LIBUSB_REQUEST_SYNCH_FRAME = 0x0C,

  /** Sets both the U1 and U2 Exit Latency */
  LIBUSB_REQUEST_SET_SEL = 0x30,

  /** Delay from the time a host transmits a packet to the time it is
    * received by the device. */
  LIBUSB_SET_ISOCH_DELAY = 0x31,
};
  • wValue 這個(gè)簡(jiǎn)單理解為請(qǐng)求字段的id,可以隨意設(shè)置只盹。
  • wIndex 簡(jiǎn)單點(diǎn)可以理解為字段內(nèi)容的位置辣往,假設(shè)你選擇準(zhǔn)備發(fā)送string類型的話,可以會(huì)有多個(gè)string殖卑,分開(kāi)發(fā)送站削,那肯定就會(huì)出現(xiàn)index從0開(kāi)始到N結(jié)束。
  • data 字段內(nèi)容
  • wLength 字段內(nèi)容長(zhǎng)度懦鼠,記得+1
  • timeout 超時(shí)設(shè)置钻哩,以毫秒為單位。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末肛冶,一起剝皮案震驚了整個(gè)濱河市街氢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌睦袖,老刑警劉巖珊肃,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異馅笙,居然都是意外死亡伦乔,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)董习,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)烈和,“玉大人,你說(shuō)我怎么就攤上這事皿淋≌猩玻” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵窝趣,是天一觀的道長(zhǎng)疯暑。 經(jīng)常有香客問(wèn)我,道長(zhǎng)哑舒,這世上最難降的妖魔是什么妇拯? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮洗鸵,結(jié)果婚禮上越锈,老公的妹妹穿的比我還像新娘。我一直安慰自己膘滨,他們只是感情好瞪浸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著吏祸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上贡翘,一...
    開(kāi)封第一講書(shū)人閱讀 51,287評(píng)論 1 301
  • 那天蹈矮,我揣著相機(jī)與錄音,去河邊找鬼鸣驱。 笑死泛鸟,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的踊东。 我是一名探鬼主播北滥,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼闸翅!你這毒婦竟也來(lái)了再芋?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤坚冀,失蹤者是張志新(化名)和其女友劉穎济赎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體记某,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡司训,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了液南。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壳猜。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖滑凉,靈堂內(nèi)的尸體忽然破棺而出统扳,到底是詐尸還是另有隱情,我是刑警寧澤譬涡,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布闪幽,位于F島的核電站,受9級(jí)特大地震影響涡匀,放射性物質(zhì)發(fā)生泄漏盯腌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一陨瘩、第九天 我趴在偏房一處隱蔽的房頂上張望腕够。 院中可真熱鬧,春花似錦舌劳、人聲如沸帚湘。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)大诸。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間资柔,已是汗流浹背焙贷。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留贿堰,地道東北人辙芍。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像羹与,于是被迫代替她去往敵國(guó)和親故硅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容