0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

USB Gadget zero應用實例程序

麥辣雞腿堡 ? 來源:嵌入式Linux系統(tǒng)開發(fā) ? 作者:嵌入式Linux系統(tǒng)開 ? 2023-07-13 11:14 ? 次閱讀

1. 編寫程序

1.1 編程思路

涉及的程序如下圖所示:

圖片

PC 端基于 libusb 編寫應用程序,開發(fā)板端直接使用 Linux 自帶的 USB Gadget 驅動 zero.c【/drivers/usb/gadget/legacy/zero.c】。

應用程序編程框架如下:

  • 找到設備
  • 選擇配置:zero.c 提供了兩種配置,loopback、sourcesink
  • 得到端點:找到 interface 進而得到 endpoint
  • 讀寫數(shù)據(jù):操作 endpoint

1.2 zero 設備的描述符

在 Ubuntu 里執(zhí)行如下命令,根據(jù) VID:PID 獲取設備信息

$ lsusb -v -d 0525:a4a0

可以列出 zero 設備的描述符:

Bus 001 Device 002: ID 0525:a4a0 Netchip Technology, Inc. Linux-USB "Gadget Zero"
Couldn't open device, some information will be missing
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass          255 Vendor Specific Class
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0        64
  idVendor           0x0525 Netchip Technology, Inc.
  idProduct          0xa4a0 Linux-USB "Gadget Zero"
  bcdDevice            4.09
  iManufacturer           1
  iProduct                2
  iSerial                 3
  bNumConfigurations      2
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           69
    bNumInterfaces          1
    bConfigurationValue     3
    iConfiguration          4
    bmAttributes         0xc0
      Self Powered
    MaxPower                2mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       1
      bNumEndpoints           4
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            1
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               4
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            1
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               4
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           32
    bNumInterfaces          1
    bConfigurationValue     2
    iConfiguration          5
    bmAttributes         0xc0
      Self Powered
    MaxPower                2mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              6
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0

它有 2 個配置:

  • 第 1 個配置(bConfigurationValue = 2)對應 loopback 功能:里面有 1 個接口,接口有 1 個 setting,下面有 2 個 endpoint
  • 第 2 個配置(bConfigurationValue = 3)對應 SourceSink 功能:里面有 1 個接口,接口有 2 個 setting
    • 第 1 個 setting 下面有 2 個 endpoint:都是 bulk 端點
    • 第 2 個 setting 下面有 4 個 endpoint:2 個是 bulk 端點,另外 2 個是 Isochronous 端點

1.3 編程

參考 libusb 示例:libusbexamplesxusb.c

#include < errno.h >
#include < signal.h >
#include < stdio.h >
#include < stdlib.h >
#include < string.h >
#include < libusb-1.0/libusb.h >

#define DRIVER_VENDOR_NUM 0x0525  /* NetChip */
#define DRIVER_PRODUCT_NUM 0xa4a0  /* Linux-USB "Gadget Zero" */

int get_bulk_endpoint(libusb_device *dev, int *in_ep, int *out_ep, int *in_ep_maxlen)
{
    struct libusb_config_descriptor *config;
    const struct libusb_endpoint_descriptor *ep;
    int r;
    int iface_idx;
    int found = 0;

    r = libusb_get_active_config_descriptor(dev, &config);
    if (r < 0) {
        printf("could not retrieve active config descriptor");
        return LIBUSB_ERROR_OTHER;
    }

 {
  const struct libusb_interface *iface = &config- >interface[0];
  int altsetting_idx = 0;

  const struct libusb_interface_descriptor *altsetting
   = &iface- >altsetting[altsetting_idx];
  int ep_idx;

  for (ep_idx = 0; ep_idx < altsetting- >bNumEndpoints; ep_idx++) {
   const struct libusb_endpoint_descriptor *ep = &altsetting- >endpoint[ep_idx];

  if ((ep- >bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK)
  {
       if (ep- >bEndpointAddress & LIBUSB_ENDPOINT_IN)
       {
        *in_ep = ep- >bEndpointAddress;
        *in_ep_maxlen = ep- >wMaxPacketSize;
         found++;
       }
       else
       {
         *out_ep = ep- >bEndpointAddress;
         found++;
        }
     }
  }
 }

    libusb_free_config_descriptor(config);
    return (found == 2) ? 0 : -1;
}

void PrintUsage(char *name)
{
    printf("Usage:n");
    printf("%s -l : list bConfigurationValue of all configsn", name);
    printf("%s -s , name);
    printf("%s -wstr < string > : write stringn", name);
    printf("%s -rstr : read stringn", name);
    printf("%s -w < val1 val2 .... > : write bytesn", name);
    printf("%s -r : read 32 bytesn", name);
}

int main(int argc, char **argv)
{
    int err = 0;
    libusb_device *dev, **devs;
    int num_devices;
    int endpoint;
    int interface_num = 0;
    int found = 0;
    int transferred;
    int count = 0;
    unsigned char buffer[1024];
    struct libusb_config_descriptor *config_desc;
    struct libusb_device_handle *dev_handle = NULL;
    int i;
    int in_ep, out_ep;
    int in_ep_maxlen;

    if (argc == 1)
    {
        PrintUsage(argv[0]);
        return 0;
    }
    
    /* libusb_init */
    err = libusb_init(NULL);
    if (err < 0) {
        fprintf(stderr, "failed to initialise libusb %d - %sn", err, libusb_strerror(err));
        exit(1);
    }

    /* open device */
    dev_handle = libusb_open_device_with_vid_pid(NULL, DRIVER_VENDOR_NUM, DRIVER_PRODUCT_NUM);
    if (!dev_handle) {
         printf("can not open zero devicen");
    return -1;
 }

 dev = libusb_get_device(dev_handle);
    /* 想選擇某一個配置, 先知道它的bConfigurationValue */
    if (!strcmp(argv[1], "-l"))
    {
        for (i = 0; i < 255; i++)        
        {
            /* parse interface descriptor, find usb mouse */        
            err = libusb_get_config_descriptor(dev, i, &config_desc);
            if (err) {
                //fprintf(stderr, "could not get configuration descriptorn");
                break;
            }
            printf("config %d: bConfigurationValue = %dn", i, config_desc- >bConfigurationValue);
            libusb_free_config_descriptor(config_desc);
        }
        return 0;
    }

    /* 想選擇某一個配置 */
    if (!strcmp(argv[1], "-s") && (argc == 3))
    {
        i = strtoul(argv[2], NULL, 0);
        libusb_set_auto_detach_kernel_driver(dev_handle, 0);  
        libusb_detach_kernel_driver(dev_handle, 0);
        //libusb_release_interface(dev_handle, 0);
        err = libusb_set_configuration(dev_handle, i);
        if (err) {
            fprintf(stderr, "could not set configuration as %d, err = %dn", i, err);
            return -1;
        }
        return 0;
    }

    err = libusb_get_configuration(dev_handle, &i);
    fprintf(stdout, "current config: %dn", i);

    /* 想讀寫數(shù)據(jù)需要得到 endpoint */
    err = get_bulk_endpoint(dev, &in_ep, &out_ep, &in_ep_maxlen);
    if (err) {
        fprintf(stderr, "could not get bulk endpointsn");
        goto exit;
    }
    fprintf(stdout, "in_ep = 0x%x, out_ep = 0x%xn", in_ep, out_ep);

    /* claim interface */
    libusb_set_auto_detach_kernel_driver(dev_handle, 1);  
    err = libusb_claim_interface(dev_handle, interface_num);
    if (err)
    {
        fprintf(stderr, "failed to libusb_claim_interfacen");
        goto exit;
    }

    /* write string */
    if (!strcmp(argv[1], "-wstr") && (argc == 3))
    {
        memset(buffer, 0, 32);
        strncpy(buffer, argv[2], 32);
        err = libusb_bulk_transfer(dev_handle, out_ep,
           buffer, 32, &transferred, 1000);        
        if (err) {
            fprintf(stderr, "libusb_bulk_transfer err = %dn", err);
            goto exit;
        }     
        if (transferred != 32)
        {
            fprintf(stderr, "transferred != 32n");
        }        
        goto exit;
    }

    /* read string */
    if (!strcmp(argv[1], "-rstr"))
    {
        memset(buffer, 0, 32);
        err = libusb_bulk_transfer(dev_handle, in_ep,
           buffer, 32, &transferred, 1000);        
        if (err) {
            fprintf(stderr, "libusb_bulk_transfer err = %dn", err);
            goto exit;
        }     
        if (transferred != 32)
        {
            fprintf(stderr, "transferred != 32n");
        }
        printf("Read string: %sn", buffer);      
        goto exit;
    }

    /* write datas */
    if (!strcmp(argv[1], "-w") && (argc >= 3))
    {
        memset(buffer, 0, 32);
        /* argv[2],... */
        for (i = 2; i < argc; i++)
            buffer[i-2] = strtoul(argv[i], NULL, 0);

        err = libusb_bulk_transfer(dev_handle, out_ep,
           buffer, argc - 2, &transferred, 1000);        
        if (err) {
            fprintf(stderr, "libusb_bulk_transfer err = %dn", err);
            goto exit;
        }     
        if (transferred != argc - 2)
        {
            fprintf(stderr, "transferred != %dn", argc - 2);
        }
        goto exit;
    }
    
    /* read datas */
    if (!strcmp(argv[1], "-r")) /* 讀Source/Sink這個配置里的端點時, 它一次性返回512字節(jié)的數(shù)據(jù) */
    {
        memset(buffer, 0, 1024);
        err = libusb_bulk_transfer(dev_handle, in_ep,
           buffer, in_ep_maxlen, &transferred, 1000);        
        if (err) {
            fprintf(stderr, "libusb_bulk_transfer err = %dn", err);
            goto exit;
        }     
        if (transferred != in_ep_maxlen)
        {
            fprintf(stderr, "transferred != in_ep_maxlenn");
        }
        printf("Read datas: n");
        for (i = 0; i < transferred; i++)
        {
            printf("%02x ", buffer[i]);
            if ((i+1) % 16 == 0)
                printf("n");
        }
        printf("n");
        
        goto exit;
    }

exit:
    /* libusb_close */
    libusb_release_interface(dev_handle, interface_num);
    libusb_close(dev_handle);
    libusb_exit(NULL);
    return err;
}
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 嵌入式
    +關注

    關注

    5086

    文章

    19141

    瀏覽量

    305925
  • Linux
    +關注

    關注

    87

    文章

    11314

    瀏覽量

    209772
  • 程序
    +關注

    關注

    117

    文章

    3789

    瀏覽量

    81134
收藏 人收藏

    評論

    相關推薦

    人力資源管理實例程序源代碼

    人力資源管理實例程序
    發(fā)表于 07-19 11:13 ?8次下載

    進銷存管理實例程序源代碼

    進銷存管理實例程序
    發(fā)表于 07-19 11:14 ?926次下載

    simulink的實例程序

    simulink的實例程序:很多simulink的例程,對于初學者和高手都需要的東西。
    發(fā)表于 02-08 14:57 ?188次下載

    讀寫24LCxx系列的EEPROM的實例程序

    讀寫24LCxx系列的EEPROM的實例程序 ;********************************************************? ;*???????????&nbs
    發(fā)表于 01-16 11:30 ?2262次閱讀

    精品verilog實例程序代碼

    精品verilog實例程序代碼,下來看看。
    發(fā)表于 05-24 10:03 ?46次下載

    LCD實例程序

    微雪電子 LCD實例程序 微雪電子 LCD實例程序
    發(fā)表于 07-12 11:54 ?33次下載

    AVR產生PWM波實例程序

    AVR單片機產生PWM波實例程序
    發(fā)表于 12-29 20:38 ?5次下載

    u盤讀寫模塊實例程序

    本文分享了u盤讀寫模塊的實例程序。
    發(fā)表于 11-16 13:34 ?37次下載

    34461A的USB口驅動工程實例程序等資料免費下載

    本文檔的主要內容詳細介紹的是34461A的USB口驅動工程實例程序等資料免費下載。
    發(fā)表于 01-07 08:00 ?142次下載
    34461A的<b class='flag-5'>USB</b>口驅動工程<b class='flag-5'>實例程序</b>等資料免費下載

    Arduino進行端口通信的實例程序免費下載

    本文檔的主要內容詳細介紹的是Arduino進行端口通信的實例程序免費下載。
    發(fā)表于 05-13 18:12 ?7次下載
    Arduino進行端口通信的<b class='flag-5'>實例程序</b>免費下載

    微雪電子Zero/Zero W USB轉接板簡介

    樹莓派Zero/Zero W/Zero WH USB轉接板 micro USB轉換Type A接口,方便接入計算機,無需連接其他線材或
    的頭像 發(fā)表于 01-06 10:50 ?1694次閱讀
    微雪電子<b class='flag-5'>Zero</b>/<b class='flag-5'>Zero</b> W <b class='flag-5'>USB</b>轉接板簡介

    [嵌入式linux]將linux板卡虛擬為USB網(wǎng)卡設備(Ethernet Gadget

    kernel menuconfig-> Device Drivers ->USB support -> USB Gadget Support 建議最好選成M,作為內核驅動模塊,便于
    發(fā)表于 11-02 11:36 ?12次下載
    [嵌入式linux]將linux板卡虛擬為<b class='flag-5'>USB</b>網(wǎng)卡設備(Ethernet <b class='flag-5'>Gadget</b>)

    AMD Xilinx Linux 2022.1 USB Gadget使用

    有客戶使用Linux中的USB Gadget功能,把MPSoC器件做USB從設備
    的頭像 發(fā)表于 07-07 14:15 ?716次閱讀

    USB Gadget serial應用實例(上)

    USB 口。 然后在板子加載驅動程序后,可以看到新的設備節(jié)點 /dev/ttyGS0: # modprobe g_serial g_serial gadget: Gadget S
    的頭像 發(fā)表于 07-13 11:06 ?2886次閱讀
    <b class='flag-5'>USB</b> <b class='flag-5'>Gadget</b> serial應用<b class='flag-5'>實例</b>(上)

    USB Gadget zero應用上機實驗

    2. 上機實驗 實驗步驟: 先安裝 g_zero 驅動程序:在開發(fā)板上執(zhí)行 modprobe g_zero 然后連接 OTG 線到 PC 在 Ubuntu 中識別出設備 執(zhí)行測試程序
    的頭像 發(fā)表于 07-13 11:15 ?735次閱讀