ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

尝试写gadget zero驱动

2019-09-19 21:06:03  阅读:1106  来源: 互联网

标签:尝试 usb gadget ret zero libusb device ep desc


gadget zero驱动可以用于usb通道测试, 也可以用于gadget 驱动参考。

 

他的功能如下:

1. 他是个双配置的usb设备

     配置1: 有一个接口, 一个altsetting(即没有备选设置)

                接口内有两个bulk端点, 分别对应in/out

     配置2: 一个接口, 两个altsetting,即有两种设置

               设置1: Bulk In + Bulk Out

               设置2: Isoch In + Isoch Out

 

2. 如果内核参数 loopdefaut = 1, 实现loopback回环功能。

即out端点数据发送给in端点。 

也即主机端通过OUT端点发送的数据又可以通过IN端点获取。

 

3. 如何编写gadget zero驱动, 以前直接注册usb_gadget_driver并实现相关回调函数, 

利用gadget api实现descriptor, 控制端点功能及Bulk, Isoch端点功能即可。

最新Linux内核中更改了结构, 内部需要使用f_sourcesink及f_loopback模块。

故后续再去写gadget zero驱动...

 

 

4. 这里主要针对主机端如何进行usb gadget zero回环测试进行说明。

    windows 自带驱动无法识别gadget zero驱动,  网上也未找到。

    Linux主机自带usbtest.ko驱动(drivers/usb/misc/usbtest.c)

    用户态有对应测试程序, 请参考 http://www.linux-usb.org/usbtest/


    由于g_zero是个lagency驱动,  最新版本尝试几次遇到一些问题, 就不去使用usbtest.ko了。

    直接基于usb_skeleton.ko和libusb实现两套可运行的程序。

 

* 基于usb_skeleton.ko, 很简单, 更改下id_table使加载即可....

 #define USB_SKEL_VENDOR_ID› 0x0525                                                                          
 #define USB_SKEL_PRODUCT_ID› 0xa4a0


拔出usb线,
insmod usb_skeleton.ko
插入usb线,

ok...  主机端就会优先加载usb_skeleton驱动, 而不去使用usbtest驱动了。

文件系统产生/dev/skel0节点


echo 123456 > /dev/skel0

cat /dev/skel0

(如果设备端配置了loopdefaut=1, 就能看到loopback的数据)
123456

* 基于libusb自己写个用户态程序, 如下:

#include <stdio.h>
#include <string.h>
#include <libusb.h>

#define TIMEOUT 2000
#define STR_LEN 20

int main(int argc, char *argv[]) {
    int ret = 0;
    libusb_device_handle *handle;
    libusb_device **list;
    libusb_device *usbdev;
    struct libusb_device_descriptor dev_desc;
    struct libusb_config_descriptor *config_desc;
    const struct libusb_endpoint_descriptor *ep_desc;
    unsigned char ep_bulkin = 0 , ep_bulkout = 0;
    int i = 0, is_match = 0;
    int ep_cnt;
    char send_data[STR_LEN] = {0,};
    char recv_data[STR_LEN] = {0,};
    int transfered = 0;
    int count = 0;

    ret = libusb_init(NULL);
    if (ret < 0) {
        fprintf(stderr, "libusb_init failed, ret(%d)\n", ret);

        return -1;
    }

    // get usb device list
    ret = libusb_get_device_list(NULL, &list);
    if (ret < 0) {
        fprintf(stderr, "libusb_get_device_list failed,"
                "ret(%d)\n", ret);

        goto get_failed;
    }

    /* print/check the matched device */
    while ((usbdev = list[i++]) != NULL) {
        libusb_get_device_descriptor(usbdev, &dev_desc);

#if 0
        printf("usb-%d: pid(0x%x), vid(0x%x)\n",
               i++,
               dev_desc.idVendor,
               dev_desc.idProduct);
#endif

        if (dev_desc.idVendor == 0x0525 &&
                dev_desc.idProduct == 0xa4a0) {
            printf("match, break!\n");
            is_match = 1;
            break;
        }
    }

    if (!is_match) {
        fprintf(stderr, "no matched usb device...\n");

        goto match_fail;
    }

    /* open usb device */
    ret = libusb_open(usbdev, &handle);
    if (ret < 0) {
        fprintf(stderr, "libusb_open failed. ret(%d)\n", ret);

        goto open_failed;
    }

    printf("this usb device has %d configs, "
            "but still use default config 0\n",
            dev_desc.bNumConfigurations);

    /* get config descriptor */
    ret = libusb_get_config_descriptor(usbdev, 1, &config_desc);
    if (ret < 0) {
        fprintf(stderr, "get config descriptor failed...\n");
        goto configdesc_fail;
    }

    printf("the config has %d interface..."
            "just use the 1st interface this time\n",
            config_desc->bNumInterfaces);

    ep_cnt = config_desc->interface->altsetting[0].bNumEndpoints;

    printf("this interface has %d endpoint\n", ep_cnt);

    /* get bulk in/out ep */
    for (i=0; i<ep_cnt; i++) {
        ep_desc = &config_desc->interface->altsetting[0].endpoint[i];
        if ((ep_desc->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) & LIBUSB_TRANSFER_TYPE_BULK) {
            if ((ep_desc->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) & LIBUSB_ENDPOINT_IN)  {
                if (!ep_bulkin) {
                    ep_bulkin = ep_desc->bEndpointAddress;
                }
            } else {
                if (!ep_bulkout) {
                    ep_bulkout = ep_desc->bEndpointAddress;
                }
            }

            printf("ep_addr = 0x%x\n", ep_desc->bEndpointAddress);
        }
    }

    if (ep_bulkin) {
        printf("yes, got 1 bulk in endppint!\n");
    }

    if (ep_bulkout) {
        printf("yes, got 1 bulk out endppint!\n");
    }

    /* claim the interface */
    printf("claim usb interface\n");
    ret = libusb_claim_interface(handle, 0);
    if (ret < 0) {
        printf("claim usb interface failed... ret(%d)\n", ret);
        goto claim_failed;
    }


    printf("start bulk transfer...\n");
    /* use bulk trandfer data directly */
    while (count++ < 20) {
        snprintf(send_data, STR_LEN, "hello,world - %d", count);
        ret = libusb_bulk_transfer(handle, ep_bulkout, (unsigned char*)send_data, sizeof(send_data),
                &transfered, TIMEOUT);

        if (ret == 0) {
            ret = libusb_bulk_transfer(handle, ep_bulkin, (unsigned char *)recv_data,
                    sizeof(recv_data), &transfered, TIMEOUT);

            if (ret == 0) {
                printf("recv: %s\n", recv_data);
            } else {
                printf("bulk in failed, ret(%d), transfered(%d)\n",
                        ret, transfered);
            }
        } else {
            printf("bulk out failed, ret(%d), transfered(%d)\n",
                    ret, transfered);
        }
    }

    // libusb_open(dev, &handle);
    libusb_close(handle);

    libusb_free_device_list(list, 1);

    libusb_exit(NULL);

    return 0;

configdesc_fail:
claim_failed:
    libusb_close(handle);

open_failed:
match_fail:
    libusb_free_device_list(list, 1);

get_failed:
    libusb_exit(NULL);

    return ret;
}
CC=gcc
CFLAGS=-g -Wall
CFLAGS+=`pkg-config --cflags libusb-1.0`
LDFLAGS=`pkg-config --libs libusb-1.0`

target=usbtest
objs=$(patsubst %.c, %.o, $(wildcard *.c))

all:$(target)

$(target):$(objs)
	$(CC) $^ -o $@ $(LDFLAGS)

.c.o:
	$(CC) -c $< $(CFLAGS)

.PHONY:
	clean

clean:
	rm *.o $(target) -rf

ok... 程序相对简单, 记录下libusb的函数调用

- libusb_init

- libusb_get_device_list    // 获取设备列表, 返回设备数组

- libusb_get_device_descriptor    // 获取设备描述符, 该结构体下面能找到配置, 接口, 端点,  字符串等描述符

- libusb_open     // 打开设备

- 查看描述信息, 选择自己要用的配置项, libusb_set_configuration

- libusb_claim_interface    // claim(认领, 索取)一个接口,  这个函数是必须调用的, 否则会有一些warning

- libusb_bulk_transfer      // bulk传输, 其他控制, 登时有对应接口

- ****释放各种资源的函数,  暂不列举了....

 

ok,  就写这么多, 后面尽快写个gadget 驱动程序... 以加深gadget api相关。

标签:尝试,usb,gadget,ret,zero,libusb,device,ep,desc
来源: https://blog.csdn.net/nwpu053883/article/details/101034677

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有