USB gadget设备驱动解析(1) [精华]

来源:互联网 发布:js控制浏览器最小化 编辑:程序博客网 时间:2024/04/18 23:33

分类: LINUX

作者:刘洪涛,华清远见嵌入式学院金牌讲师。

利用Linux USB gadget设备驱动可以实现一些比较有意思的功能,举两个例子: 1、一个嵌入式产品中的某个存储设备,或是一个存储设备的某个分区,可以作为一个U盘被PC;设别,从而非常方便的完成文件交互,这个功能被广泛的应用于手机、数码相机等产品中。2、一个嵌入式设备通过USB连接到你的PC后,在你的PC端会出现一个新的网络连接,在嵌入式设备上也会有一个网卡设备,你可以配置它们的IP地址,并进行网络通讯,俗称USBNET。

所有USB通讯的设备端都有usb device程序,通常称它们为usb固件。在一些功能简单的设备里,用一些专用的可编程USB控制器就可以了。而在一些运行了类似linux操作系统的复杂的嵌入式系统中,要完成usb device程序,就会要求你不仅熟悉usb device控制器的操作,还要熟悉操作系统的驱动架构。

我想通过 “功能体验”、“驱动调试”、“gadget驱动结构分析”、“编写一个自己的gadget驱动”这4个方面解析linux usb gadget设备驱动的编写方法。

一、linux模拟U盘功能的实现

在硬件环境为华清远见的fs2410平台,软件环境为linux-2.6.26的linux系统上,实现模拟U盘的功能。

向内核添加代码

#include <asm/arch/regs-gpio.h>
    #include <asm/arch/regs-clock.h>
    #include <asm/plat-s3c24xx/udc.h>

修改arch/arm/mach-s3c2410/mach-smdk2410.c

/*USB device上拉电阻处理 */
    static void smdk2410_udc_pullup(enum s3c2410_udc_cmd_e cmd)
    {
        u8 *s3c2410_pullup_info[] = {
            " ",
            "Pull-up enable",
            "Pull-up disable",
            "UDC reset, in case of"
        };
        printk("smdk2410_udc: %s\n",s3c2410_pullup_info[cmd]);
        s3c2410_gpio_cfgpin(S3C2410_GPG9, S3C2410_GPG9_OUTP);
        switch (cmd)
        {
            case S3C2410_UDC_P_ENABLE :
                
            s3c2410_gpio_setpin(S3C2410_GPG9, 1);   //set gpg9 output HIGH
                break;
            case S3C2410_UDC_P_DISABLE :
                s3c2410_gpio_setpin(S3C2410_GPG9, 0);   //set gpg9 output LOW
                break;
            case S3C2410_UDC_P_RESET :
                //FIXME!!!
                break;
            default:
                break;
        }
    }

static struct s3c2410_udc_mach_info smdk2410_udc_cfg __initdata = {
        .udc_command    = smdk2410_udc_pullup,
    };

static struct platform_device *smdk2410_devices[] __initdata = {
    …,
    &s3c_device_usbgadget,  /*USB gadget device设备登记*/
    };

static void __init sdmk2410_init(void)    
    {
       u32 upll_value;
       set_s3c2410fb_info(&smdk2410_lcdcfg);
      s3c24xx_udc_set_platdata(&smdk2410_udc_cfg); /* 初始化*/
       s3c_device_sdi.dev.platform_data = &smdk2410_mmc_cfg;
       /* Turn off suspend on both USB ports, and switch the
        * selectable USB port to USB device mode. */

   s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
                 S3C2410_MISCCR_USBSUSPND0 |
                 S3C2410_MISCCR_USBSUSPND1, 0x0);
      /* 设置USB时钟 */
      upll_value = (
           0x78 << S3C2410_PLLCON_MDIVSHIFT)
            | (0x02 << S3C2410_PLLCON_PDIVSHIFT)
            | (0x03 << S3C2410_PLLCON_SDIVSHIFT);
      while (upll_value != readl(S3C2410_UPLLCON)) {
          writel(upll_value, S3C2410_UPLLCON);
          udelay(20);       
        }
    }

修改drivers/usb/gadget/file_storage.c

static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
                struct usb_request *req, int *pbusy,
                enum fsg_buffer_state *state)
    {
        int     rc;
        udelay(800);
    …… 
    }

配置内核支持U盘模拟

<*>   USB Gadget Support  --->
            USB Peripheral Controller (S3C2410 USB Device Controller)  --->
             S3C2410 USB Device Controller
    [*]       S3C2410 udc debug messages
    <M>   USB Gadget Drivers 
    <M>     File-backed Storage Gadget

3、编译内核

#make zImage
    #make modules

在目录drivers/usb/gadget下生成g_file_storage.ko

加载驱动,测试功能

利用前面的生成的内核,启动系统后,加载g_file_storage.ko

#insmod g_file_storage.ko
    # insmod g_file_storage.ko file="/dev/mtdblock2" stall="0" removable="1"
    0.03 USB: usb_gadget_register_driver() 'g_file_storage'
    0.04 USB: binding gadget driver 'g_file_storage'
    0.05 USB: s3c2410_set_selfPowered()
    g_file_storage gadget: File-backed Storage Gadget, version: 20 October 2004
    g_file_storage gadget: Number of LUNs="1"
    g_file_storage gadget-lun0: ro="0", file: /dev/mtdblock3
    0.06 USB: udc_enable called
    smdk2410_udc: Pull-up enable

连接设备到windows,windows系统会自动设备到一个新的U盘加入。格式化U盘,存入文件。卸载U盘后,在目标板上执行如下操作:

# mkdir /mnt/gadget
    # mount -t vfat /dev/mtdblock2 /mnt/gadget/ 
    #ls

可以看到windows存入U盘的文件。

二、usbnet功能的实现

配置内核支持usbnet

<*>   USB Gadget Support  --->
            USB Peripheral Controller (S3C2410 USB Device Controller)  --->
             S3C2410 USB Device Controller
    [*]       S3C2410 udc debug messages
    <M>   USB Gadget Drivers
    <M>     Ethernet Gadget (with CDC Ethernet support)
    [*]       RNDIS support

2、编译内核

#make zImage
    #make modules

在目录drivers/usb/gadget下生成g_ether.ko

3、加载驱动,测试功能

利用前面的生成的内核,启动系统后,加载g_ether.ko

#insmod g_ether.ko
    #ifconfig usb0 192.168.1.120
    ……
    usb0 Link encap:Ethernet HWaddr 5E:C5:F6:D4:2B:91
    inet addr:192.168.1.120 Bcast:192.168.1.255 Mask:255.255.255.0
    UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
    RX packets:253 errors:0 dropped:0 overruns:0 frame:0
    TX packets:43 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:1000
    RX bytes:35277 (34.4 KiB) TX bytes:10152 (9.9 KiB)

连接设备到windows,windows系统会提示安装驱动,根据提示安装上RNDIS驱动。这个驱动可以在网络上找到。此时windows会新生成一个网络连接,配置它的ip地址等信息。然后就可以和目标系统通过USB实现网络通讯了。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 微信支付月限额怎么办 微信超额20万怎么办 微信支付超额了怎么办 微信零钱超额了怎么办 微信的充值冲错了怎么办 有流量还扣话费怎么办 自动取款机充值到电子账户怎么办 淘宝qb充错了怎么办 q币冲错了人家不给怎么办 qq充值话费错号怎么办 qq充错号码了怎么办 qq交话费不到账怎么办 充错手机号码而且是空号怎么办 微信钱包充错话费怎么办 QQ充值话费充到空号了怎么办 给别人充错话费怎么办 用qq交错话费对方是空号怎么办 号码变成空号了怎么办 qq冲流量冲错了怎么办 流量冲错了套餐怎么办 微信流量充错号码怎么办 微信支付不进账怎么办 充话费充不进去怎么办 用支付宝充话费没到账怎么办 支付宝充话费未到账怎么办 话费充了不到账怎么办 转转买家不确认收货怎么办 充话费错了怎么办啊 淘宝充值流量没到账怎么办 微信手机充错了怎么办 支付宝充话费没到账怎么办 裤子摔了一个洞怎么办 顾客反应衣服质量不好怎么办 淘宝买的衣服味道很大怎么办 三国杀账号忘了怎么办 宽带连接被删了 怎么办 手机被偷了qq怎么办 手机丢了微信怎么办啊 手机店把手机修坏了怎么办 在手机店买到山寨机手机怎么办 有人在qq群上骂我怎么办