首页 ┆ 网站地图 ┆ 在线留言 ┆ 游戏资讯 ┆ 资源下载 ┆ 端午节祝福 ┆ 迅雷在线影视
设为首页
加入收藏
联系我们
高级搜索
您当前的位置: 主页>操作系统>Unix/Linux>图解Linux环境下USB的原理、驱动和配置
图解Linux环境下USB的原理、驱动和配置
来源: 发布时间:2007-10-15 发布人: 浏览: 人次   字体: [ ]  

提交和控制urb:当驱动程序有数据要发送到USB设备时(大多数情况是在驱动程序的写函数中),要分配一个urb来把数据传输给设备:

 

       /* 创建一个urb,并且给它分配一个缓存*/

       urb = usb_alloc_urb(0, GFP_KERNEL);

       if (!urb) {

              retval = -ENOMEM;

              goto error;

       }

 

urb被成功分配后,还要创建一个DMA缓冲区来以高效的方式发送数据到设备,传递给驱动程序的数据要复制到这块缓冲中去:

 

       buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);

       if (!buf) {

              retval = -ENOMEM;

              goto error;

       }

 

       if (copy_from_user(buf, user_buffer, count)) {

              retval = -EFAULT;

              goto error;

       }

 

当数据从用户空间正确复制到局部缓冲区后,urb必须在可以被提交给USB核心之前被正确初始化:

 

       /* 初始化urb */

       usb_fill_bulk_urb(urb, dev->udev,

                       usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),

                       buf, count, skel_write_bulk_callback, dev);

       urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

 

然后urb就可以被提交给USB核心以传输到设备了:

 

       /* 把数据从批量OUT端口发出 */

       retval = usb_submit_urb(urb, GFP_KERNEL);

       if (retval) {

              err("%s - failed submitting write urb, error %d", __FUNCTION__, retval);

              goto error;

       }

 

urb被成功传输到USB设备之后,urb回调函数将被USB核心调用,在我们的例子中,我们初始化urb,使它指向skel_write_bulk_callback函数,以下就是该函数:

 

static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs)

{

       struct usb_skel *dev;

 

       dev = (struct usb_skel *)urb->context;

 

       if (urb->status &&

           !(urb->status == -ENOENT ||

             urb->status == -ECONNRESET ||

             urb->status == -ESHUTDOWN)) {

              dbg("%s - nonzero write bulk status received: %d",

                  __FUNCTION__, urb->status);

       }

 

       /* 释放已分配的缓冲区 */

       usb_buffer_free(urb->dev, urb->transfer_buffer_length,

                     urb->transfer_buffer, urb->transfer_dma);

}

 

有时候USB驱动程序只是要发送或者接收一些简单的数据,驱动程序也可以不用urb来进行数据的传输,这是里涉及到两个简单的接口函数:usb_bulk_msgusb_control_msg ,在这个USB框架程序里读操作就是这样的一个应用:

 

/* 进行阻塞的批量读以从设备获取数据 */

       retval = usb_bulk_msg(dev->udev,

                           usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),

                           dev->bulk_in_buffer,

                           min(dev->bulk_in_size, count),

                           &count, HZ*10);

 

       /*如果读成功,复制到用户空间 */

       if (!retval) {

              if (copy_to_user(buffer, dev->bulk_in_buffer, count))

                     retval = -EFAULT;

              else

                     retval = count;

       }

usb_bulk_msg接口函数的定义如下:

int usb_bulk_msg(struct usb_device *usb_dev,unsigned int pipe,

void *data,int len,int *actual_length,int timeout);

 

其参数为:

 

struct usb_device *usb_dev:指向批量消息所发送的目标USB设备指针。

unsigned int pipe:批量消息所发送目标USB设备的特定端点,此值是调用usb_sndbulkpipe或者usb_rcvbulkpipe来创建的。

 

void *data:如果是一个OUT端点,它是指向即将发送到设备的数据的指针。如果是IN端点,它是指向从设备读取的数据应该存放的位置的指针。

int lendata参数所指缓冲区的大小。

 

int *actual_length:指向保存实际传输字节数的位置的指针,至于是传输到设备还是从设备接收取决于端点的方向。

 

int timeout:以Jiffies为单位的等待的超时时间,如果该值为0,该函数一直等待消息的结束。

如果该接口函数调用成功,返回值为0,否则返回一个负的错误值。

 

usb_control_msg接口函数定义如下:

 

int usb_control_msg(struct usb_device *dev,unsigned int pipe,__u8    request,__u8requesttype,__u16 value,__u16 index,void *data,__u16 size,int timeout)

除了允许驱动程序发送和接收USB控制消息之外,usb_control_msg函数的运作和usb_bulk_msg函数类似,其参数和usb_bulk_msg的参数有几个重要区别:

struct usb_device *dev:指向控制消息所发送的目标USB设备的指针。

unsigned int pipe:控制消息所发送的目标USB设备的特定端点,该值是调用usb_sndctrlpipeusb_rcvctrlpipe来创建的。

__u8 request:控制消息的USB请求值。

__u8 requesttype:控制消息的USB请求类型值。

__u16 value:控制消息的USB消息值。

__u16 index:控制消息的USB消息索引值。

void *data:如果是一个OUT端点,它是指身即将发送到设备的数据的指针。如果是一个IN端点,它是指向从设备读取的数据应该存放的位置的指针。

__u16 sizedata参数所指缓冲区的大小。

int timeout:以Jiffies为单位的应该等待的超时时间,如果为0,该函数将一直等待消息结束。

 

如果该接口函数调用成功,返回传输到设备或者从设备读取的字节数;如果不成功它返回一个负的错误值。

 

这两个接口函数都不能在一个中断上下文中或者持有自旋锁的情况下调用,同样,该函数也不能被任何其它函数取消,使用时要谨慎。

 

我们要给未知的USB设备写驱动程序,只需要把这个框架程序稍做修改就可以用了,前面我们已经说过要修改制造商和产品的ID号,把0xfff0这两个值改为未知USBID号。

 #define USB_SKEL_VENDOR_ID      0xfff0

     #define USB_SKEL_PRODUCT_ID     0xfff0

还有就是在探测函数中把需要探测的接口端点类型写好,在这个框架程序中只探测了批量(USB_ENDPOINT_XFER_BULKINOUT端点,可以在此处使用掩码(USB_ENDPOINT_XFERTYPE_MASK)让其探测其它的端点类型,驱动程序会对USB设备的每一个接口进行一次探测,当探测成功后,驱动程序就被绑定到这个接口上。再有就是urb的初始化问题,如果你只写简单的USB驱动,这块不用多加考虑,框架程序里的东西已经够用了,这里我们简单介绍三个初始化urb的辅助函数:

 

usb_fill_int_urb 它的函数原型是这样的:

void usb_fill_int_urb(struct urb *urb,struct usb_device *dev,

unsigned int pipe,void *transfer_buff,

int buffer_length,usb_complete_t complete,

void *context,int interval);

这个函数用来正确的初始化即将被发送到USB设备的中断端点的urb

usb_fill_bulk_urb 它的函数原型是这样的:

void usb_fill_bulk_urb(struct urb *urb,struct usb_device *dev,

unsigned int pipe,void *transfer_buffer,

int buffer_length,usb_complete_t complete)

这个函数是用来正确的初始化批量urb端点的。

usb_fill_control_urb 它的函数原型是这样的:

void usb_fill_control_urb(struct urb *urb,struct usb_device *dev,unsigned int pipe,unsigned char *setup_packet,void *transfer_buffer,int buffer_length,usb_complete_t complete,void *context);

这个函数是用来正确初始化控制urb端点的。

还有一个初始化等时urb的,它现在还没有初始化函数,所以它们在被提交到USB核心前,必须在驱动程序中手工地进行初始化,可以参考内核源代码树下的/usr/src/~/drivers/usb/media下的konicawc.c文件。


共4页: 上一页 [1] [2] 3 [4] 下一页
相 关 文 章   发布商链接
·通过mount方式访问两台Linux操作系统...
·Linux下常见音频格式之间的转换方法
·Linux操作系统中使用nmap命令小解
·redhat9中默认的vsftpd服务器配置实...
·如何在Linux系统中增加一个新的系统...
·linux统计文件目录及其相应的文件个...
·详解Linux系统下挂载U盘和硬盘光驱的...
·如何改变linux默认目录在命令行下显...
·如何修改Linux ssh端口22和禁止ROOT...
·Linux系统打开带flash的网页后自动关...
 §最新评论:(评论内容只代表网友观点,与本站立场无关!)
网名: 验证码:  【所有评论】【↑返回顶部
评 分: 12 345
评论内容:(不能超过500字,请自觉遵守互联网相关政策法规。[按 Ctrl+Enter 可直接提交]
注意:请勿在本站发布政治话题、色情及违反法律的内容。
IT知道网 声明:刊登此文章是为了传递更多信息,文章内容仅供参考,转载请注明出处。
推 荐 文 章
·如何在Linux系统下对proftpd...
·当Linux系统启动不了时采取哪
·实例讲解linux下无线网卡上网
·实例详解Linux和Windows系统...
·虚拟机中装个Linux系统不能正
·如何在在Ubuntu下建立FTP服务
·实例讲解在Linux操作系统下安
·linux系统下巧法删除U盘病毒
·图解linux操作系统光盘镜像文
·Linux系统打开带flash的网页...
·如何修改Linux ssh端口22和禁
·如何改变linux默认目录在命令
·详解Linux系统下挂载U盘和硬...
·linux统计文件目录及其相应的
·如何在Linux系统中增加一个新
热 门 文 章
·如何修改Linux ssh端口22和禁...
·图解linux操作系统光盘镜像文...
·Linux下常见音频格式之间的转...
·Linux操作系统下如何制作Imag...
·如何管理Linux 操作系统日志...
·如何改变linux默认目录在命令...
·redhat9中默认的vsftpd服务器...
·让Linux也能运行C#的方案
·如何在在Ubuntu下建立FTP服务...
·Linux操作系统上WebLogic的安...
·详解Linux系统下挂载U盘和硬...
·linux统计文件目录及其相应的...
·如何在Linux系统中增加一个新...
·通过mount方式访问两台Linux...
·实例讲解linux下无线网卡上网...
网站首页 - 关于本站 - 加入收藏 - 网站地图 - 友情连接 - 在线留言 - 联系我们 - 返回顶部
Copyright © 2007 IT知道网.[冀ICP备07026896号]. All Rights Reserved .