linux内核类型lagency,尝试写gadget zero驱动

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)

由于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

#include

#include

#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_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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值