博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
尝试写gadget zero驱动
阅读量:3559 次
发布时间:2019-05-20

本文共 6202 字,大约阅读时间需要 20 分钟。

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/skel0cat /dev/skel0(如果设备端配置了loopdefaut=1, 就能看到loopback的数据)123456

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

#include 
#include
#include
#define TIMEOUT 2000#define STR_LEN 20int 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
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=gccCFLAGS=-g -WallCFLAGS+=`pkg-config --cflags libusb-1.0`LDFLAGS=`pkg-config --libs libusb-1.0`target=usbtestobjs=$(patsubst %.c, %.o, $(wildcard *.c))all:$(target)$(target):$(objs)	$(CC) $^ -o $@ $(LDFLAGS).c.o:	$(CC) -c $< $(CFLAGS).PHONY:	cleanclean:	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的理解。

转载地址:http://licrj.baihongyu.com/

你可能感兴趣的文章
Java问题百度/Google记录 2020-2-16
查看>>
【PADS9.5】9,对比ECO核心板,Router移动元件后布线消失,Router找不到自动布线策略文件丢失或损坏
查看>>
【STM32+w5500汇总】23,HTTP_Client 连接到ONENET上传了一段数据之后会断开,数据上传格式的设置
查看>>
【STM32+W5500+MQTT】24,所有功能都可以通过API函数的调用来实现;HTTP接入ONENET,API开发手册和打包函数,串口软件HTTP连接服务器上传数据,2018年12月28日
查看>>
【STM32+W5500+HTTPClient】25,路由器DHCP租赁IP时间为2h,NetBios可以很好的解决IP变化的问题,DNS,2018年12月25日
查看>>
【STM32+MQTT+ONENET】26,MQTT协议接入OneNET
查看>>
【STM32+W5500+MQTT+ONENET】27,MQTT协议接入OneNET实际编程操作 2018年12月27日
查看>>
【STM32Cube+FreeRTOS 】28,KEIL5的F12不起作用;***JLink Error: Can not read register x while CPU is running
查看>>
【STM32CubeMX+FreeRTOS 】29,prtinf卡死;4任务只运行了3个;W5500联网失败(堆栈不能太大或者太小)
查看>>
【STM32+FreeRTOS +W5500移植要点】30,RTOS中断;从TIM2,主TIM3;RTOS主要用在LCD中;RT-Thread;标志重定义问题 2019年01月22日
查看>>
【STM32+FPGA+FSMC】31,FSMC熟练掌握;KEIL5生成bin文件;SDRAM的使用;IAP检验码 2019年04月10日
查看>>
【IC1】【转 非常好】运算放大器使用的六个经验
查看>>
【IC-ADC 3】ADC的选型
查看>>
2019年03月18日 查看数据手册的注意点,极限参数、电气参数、推荐参数
查看>>
HiKey960/970用户手册;HiKey960 Development Board User Manual
查看>>
【书籍推荐】FPGA,xilinx
查看>>
N9-SQL注入(union注入)
查看>>
N10-sql注入(information_schema注入)
查看>>
N1-Kali虚拟机中SQLmap
查看>>
N11-sql注入(http头注入)
查看>>