Linux中国 Linux中国门户站!
设为主页 设为主页
收藏本站 收藏本站
 
当前位置 :首页 ->Linux技术 ->嵌入式系统 ->正文

Linux下的硬件驱动——USB设备(下)

来源:IBM DW中国 作者:赵明  时间:2007-04-22 点击: [收藏] [投稿]


/* initialize the devfs node for this device
   and register it */
sprintf(name, "skel%d", skel->minor);
skel->devfs = devfs_register 
              (usb_devfs_handle, name,
               DEVFS_FL_DEFAULT, USB_MAJOR,
               USB_SKEL_MINOR_BASE + skel->minor,
               S_IFCHR | S_IRUSR | S_IWUSR |
               S_IRGRP | S_IWGRP | S_IROTH,
               &skel_fops, NULL);


如果devfs_register函数失败,不用担心,devfs子系统会将此情况报告给用户。

当然最后,如果设备从usb总线拔掉,设备指针会调用disconnect 函数。驱动程序就需要清除那些被分配了的所有私有数据、关闭urbs,并且从devfs上注销调自己。


/* remove our devfs node */
devfs_unregister(skel->devfs);


现在,skeleton 驱动就已经和设备绑定上了,任何用户态程序要操作此设备都可以通过file_operations结构所定义的函数进行了。首先,我们要open此设备。在open函数中MODULE_INC_USE_COUNT 宏是一个关键,它的作用是起到一个计数的作用,有一个用户态程序打开一个设备,计数器就加一,例如,我们以模块方式加入一个驱动,若计数器不为零,就说明仍然有用户程序在使用此驱动,这时候,你就不能通过rmmod命令卸载驱动模块了。



/* increment our usage count for the module */
MOD_INC_USE_COUNT;
++skel->open_count;
/* save our object in the file's private structure */
file->private_data = skel;


当open完设备后,read、write函数就可以收、发数据了。

  • skel的write、和read函数

    他们是完成驱动对读写等操作的响应。

    在skel_write 中,一个FILL_BULK_URB函数,就完成了urb 系统callbak和我们自己的skel_write_bulk_callback之间的联系。注意skel_write_bulk_callback是中断方式,所以要注意时间不能太久,本程序中它就只是报告一些urb的状态等。

    read 函数与write 函数稍有不同在于:程序并没有用urb 将数据从设备传送到驱动程序,而是我们用usb_bulk_msg 函数代替,这个函数能够不需要创建urbs 和操作urb函数的情况下,来发送数据给设备,或者从设备来接收数据。我们调用usb_bulk_msg函数并传提一个存储空间,用来缓冲和放置驱动收到的数据,若没有收到数据,就失败并返回一个错误信息。

  • usb_bulk_msg函数

    当对usb设备进行一次读或者写时,usb_bulk_msg 函数是非常有用的; 然而, 当你需要连续地对设备进行读/写时,建议你建立一个自己的urbs,同时将urbs 提交给usb子系统。

  • skel_disconnect函数

    当我们释放设备文件句柄时,这个函数会被调用。MOD_DEC_USE_COUNT宏会被用到(和MOD_INC_USE_COUNT刚好对应,它减少一个计数器),首先确认当前是否有其它的程序正在访问这个设备,如果是最后一个用户在使用,我们可以关闭任何正在发生的写,操作如下:

    
    
    /* decrement our usage count for the device */
    --skel->open_count;
    if (skel->open_count <= 0) {
       /* shutdown any bulk writes that might be
          going on */
       usb_unlink_urb (skel->write_urb);
       skel->open_count = 0;
    }
    /* decrement our usage count for the module */
    MOD_DEC_USE_COUNT;
    

    最困难的是,usb 设备可以在任何时间点从系统中取走,即使程序目前正在访问它。usb驱动程序必须要能够很好地处理解决此问题,它需要能够切断任何当前的读写,同时通知用户空间程序:usb设备已经被取走。

    如果程序有一个打开的设备句柄,在当前结构里,我们只要把它赋值为空,就像它已经消失了。对于每一次设备读写等其它函数操作,我们都要检查 usb_device结构是否存在。如果不存在,就表明设备已经消失,并返回一个-ENODEV错误给用户程序。当最终我们调用release 函数时,在没有文件打开这个设备时,无论usb_device结构是否存在、它都会清空skel_disconnect函数所作工作。

    Usb 骨架驱动程序,提供足够的例子来帮助初始人员在最短的时间里开发一个驱动程序。更多信息你可以到linux usb开发新闻组去寻找。

  • U盘、USB读卡器、MP3、数码相机驱动

    对于一款windows下用的很爽的U盘、USB读卡器、MP3或数码相机,可能Linux下却不能支持。怎么办?其实不用伤心,也许经过一点点的工作,你就可以很方便地使用它了。通常是此U盘、USB读卡器、MP3或数码相机在WindowsXP中不需要厂商专门的驱动就可以识别为移动存储设备,这样的设备才能保证成功,其他的就看你的运气了。

    USB存储设备,他们的read、write等操作都是通过上章节中提到的钩子,把自己的操作钩到SCSI设备上去的。我们就不需要对其进行具体的数据读写处理了。

    第一步:我们通过cat /proc/bus/usb/devices得到当前系统探测到的USB总线上的设备信息。它包括Vendor、ProdID、Product等。下面是我买的一款杂牌CF卡读卡器插入后的信息片断:

    
    
    T: Bus=01 Lev=01 Prnt=01 Port=01 Cnt=02 Dev#= 5 Spd=12 MxCh= 0 
    D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=8 #Cfgs= 1 
    P: Vendor=07c4 ProdID=a400 Rev= 1.13 
    S: Manufacturer=USB 
    S: Product=Mass Storage 
    C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=70mA 
    I: If#= 0 Alt= 0 #EPs= 2 Cls=08(vend.) Sub=06 Prot=50 Driver=usb-storage 
    E: Ad=81(I) Atr=02(Bulk) MxPS= 64 Ivl= 0ms
    E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl= 0ms
    
    


     如果您对本文有任何疑问或者建议,请到讨论区发表您的意见: >> 论坛入口 <<



    上一篇:四种实时操作系统特性进行分析和比较   下一篇:Linux下PCI设备驱动程序开发

    文章评论】 【收藏本文】 【推荐好友】 【打印本文】 【我要投稿】 【论坛讨论
    更多相关文章