日期:2014-05-16  浏览次数:20690 次

自娱自乐6之Linux gadget驱动5(自编gadget驱动,包涵与之通讯的主机usb驱动,已调试通过)

这个代码调试,你首先要保证你的udc驱动没用问题,这个有些矛盾,应为我本来要用gadget驱动来调试udc驱动,结果反过来了。

这是在zero基础改的,大概的改动

1. 去掉loop。

2. sink的读写去掉了。

3. 增加了一个misc,通过fs去读写数据。

4. setup的特殊请求去掉了。

之前的文章已经把大部分的东西说完了,所以代码没有太多的注释。请结合之前的文章阅读。

我用了一个完成量,在没有数据时,读可能会死在那。这个可以优化一下,我就不做了。

还有就是主机是虚拟机的usb,linux-2.6.18(无耻的告诉你就是usb-skeleton驱动),gadget是板子的,linux-3.2.36


gadget_transfer.c //linux-3.2.36

/* #define VERBOSE_DEBUG */

#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/utsname.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/completion.h>
#include <linux/fs.h>

#include <asm/uaccess.h>

#define CONFIG_USB_GADGET_VBUS_DRAW 500

#include "composite.c"
#include "usbstring.c"
#include "config.c"
#include "epautoconf.c"

#define BUFLEN 4096

struct f_sourcesink {
    struct usb_function    function;

    struct usb_ep        *in_ep;
    struct usb_ep        *out_ep;

    struct completion gdt_completion;
    char data[BUFLEN];
    unsigned actual;//数据实际长度
};

static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
{
    return container_of(f, struct f_sourcesink, function);
}

/*-------------------------------------*/
//接口描述符
static struct usb_interface_descriptor source_sink_intf = {
    .bLength =        sizeof source_sink_intf,
    .bDescriptorType =    USB_DT_INTERFACE,

    .bNumEndpoints =    2,
    .bInterfaceClass =    USB_CLASS_VENDOR_SPEC,
    /* .iInterface = DYNAMIC */
};

/* full speed support: */
//全速设备端点描述符
static struct usb_endpoint_descriptor fs_source_desc = {
    .bLength =        USB_DT_ENDPOINT_SIZE,
    .bDescriptorType =    USB_DT_ENDPOINT,

    .bEndpointAddress =    USB_DIR_IN,
    .bmAttributes =        USB_ENDPOINT_XFER_BULK,
};

static struct usb_endpoint_descriptor fs_sink_desc = {
    .bLength =        USB_DT_ENDPOINT_SIZE,
    .bDescriptorType =    USB_DT_ENDPOINT,

    .bEndpointAddress =    USB_DIR_OUT,
    .bmAttributes =        USB_ENDPOINT_XFER_BULK,
};

static struct usb_descriptor_header *fs_source_sink_descs[] = {
    (struct usb_descriptor_header *) &source_sink_intf,
    (struct usb_descriptor_header *) &fs_sink_desc,
    (struct usb_descriptor_header *) &fs_source_desc,
    NULL,
};

/* high speed support: */
//高速设备端点描述符
static struct usb_endpoint_descriptor hs_source_desc = {
    .bLength =        USB_DT_ENDPOINT_SIZE,
    .bDescriptorType =    USB_DT_ENDPOINT,

    .bmAttributes =        USB_ENDPOINT_XFER_BULK,
    .wMaxPacketSize =    cpu_to_le16(512),
};

static struct usb_endpoint_descriptor hs_sink_desc = {
    .bLength =        USB_DT_ENDPOINT_SIZE,
    .bDescriptorType =    USB_DT_ENDPOINT,

    .bmAttributes =        USB_ENDPOINT_XFER_BULK,
    .wMaxPacketSize =    cpu_to_le16(512),
};

static struct usb_descriptor_header *hs_source_sink_descs[] = {
    (struct usb_descriptor_header *) &source_sink_intf,
    (struct usb_descriptor_header *) &hs_source_desc,
    (struct usb_descriptor_header *) &hs_sink_desc,
    NULL,
};


/* function-specific strings: */
static struct usb_string strings_sourcesink[] = {
    [0].s = "source and sink data",
    {  }            /* end of list */
};

static struct usb_gadget_strings stringtab_sourcesink = {
    .language    = 0x0409,    /* en-us */
    .strings    = strings_sourcesink,
};

static struct usb_gadget_strings *sourcesink_strings[] = {
    &stringtab_sou