Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1833631
  • 博文数量: 195
  • 博客积分: 4227
  • 博客等级: 上校
  • 技术积分: 2835
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-04 10:39
文章分类

全部博文(195)

文章存档

2013年(1)

2012年(26)

2011年(168)

分类: LINUX

2011-04-02 09:28:07

usb msg

谨以此文纪念过往的岁月

一.  前言

在前文中看过urb的实现的机制,在该文中咱们来看msg的实现。

二.  msg

ldd中说msg是一种轻量级的usb数据传输,个人以为不然,其本质还是采用了urb来实现的,那我们来看其具体的实现,除了iso的没有msg其余的三种usb传输都有。那一一来看其实现。

在该函数的说明中就说明该函数不能使用在中断上下文中。因为该函数会睡眠等待。那先来看其具体的参数:

devusb设备

pipe: 管道 包括一些传输的信息

request usb请求的命令,该值在usb协议中定义

requesttype :请求类型

value usb信息值

index usb信息索引值

data :指向需要发送的数据指针

size:数据大小

timeout:等待时间

int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request,

                  __u8, __u16 value, __u16 , void *data,

                  __u16 size, int timeout)

{

       struct usb_ctrlrequest *dr;

       int ret;

 

       dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);

       if (!dr)

              return -ENOMEM;

 

       dr->bRequestType = requesttype;

       dr->bRequest = request;

       dr->wValue = cpu_to_le16(value);

       dr->wIndex = cpu_to_le16(index);

       dr->wLength = cpu_to_le16(size);

       ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);

       kfree(dr);

       return ret;

}

static int usb_internal_control_msg(struct usb_device *usb_dev,

                                unsigned int pipe,struct usb_ctrlrequest *cmd,

                                void *data, int len, int timeout)

{

       struct urb *urb;

       int retv;

       int length;

       urb = usb_alloc_urb(0, GFP_NOIO);

       if (!urb)

              return -ENOMEM;

       usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data,

                          len, , NULL);

 

       retv = (urb, timeout, &length);

       if (retv < 0)

              return retv;

       else

              return length;

}

从上面的源码可以看出,其实所谓的message就是一个马甲,其就是自己私自创建一个urb用于传输。那我们来看其中还具有一点隐私的函数,咱们不看其具体的实现来猜猜其的作用。嘿嘿,其中一点调用了usb_submit_urb来提交urb不过还应该有一个类似于信号量的东东用来等待urb完成,而在填充urbcomplet域的函数usb_api_blocking_completion中一定会唤醒或完成的东东来唤醒在usb_start_wait_urb中等待的东东。咱们还是来看源码。

static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)

{

       struct api_context ctx;

       unsigned long expire;

       int retval;

 

       init_completion(&ctx.done); --新建和初始化一个完成量

       urb->context = &ctx;       --存储,要不然怎么完成

       urb->actual_length = 0;

       retval = usb_submit_urb(urb, GFP_NOIO); --提交urb

       if (unlikely(retval))

              goto out;

       expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;

       if (!wait_for_completion_timeout(&ctx.done, expire)) {  --如果等待没有结果就

              usb_kill_urb(urb);

              retval = (ctx.status == -ENOENT ? -ETIMEDOUT : ctx.status);

       } else

              retval = ctx.status;

out:

       if (actual_length)

              *actual_length = urb->actual_length;

       usb_free_urb(urb);

       return retval;

}

其实上面的等待将在下面的函数中唤醒。

static void usb_api_blocking_completion(struct urb *urb)

{

       struct api_context *ctx = urb->context;

 

       ctx->status = urb->status;

       complete(&ctx->done);

}

这里理解了为什么msg不能在中断上下文中了吧,呵呵。

intbulkmsg传输与上面类似咱就不看了,不过函数定义还是来看一下。

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

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

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

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

这儿说到了请求,那这儿就来看看usb请求的具体的格式以及具体的请求有什么。

下面结构体定义控制类型传输的格式

struct usb_ctrlrequest {

       __u8;

       __u8 bRequest;

       __le16 wValue;

       __le16 wIndex;

       __le16 wLength;

} __attribute__ ((packed));

bRequestType

bit7     :数据传输方向 0 主机->设备 1 设备->主机

bit6~bit5 :类型 0 标准 1 2 私有 3 保留

bit4~bit0 :接受者 0 usb设备 1 usb接口 2 usb端点 其余保留

如何理解请求的类型,这个很好理解就是0表示是所有usb设备都必须支持的标准请求命令,1表示一类设备所支持的请求命令而2就是该usb设备所特定的请求。Bit4~bit0则表明了数据所对应的目的地。其实在这几个参数中wIndex这个比较难理解。也许下面的表格比较好理解一点。

bRequestTypebit4~bit0值为2时即目的地是端点wIndex则代表:

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

保留(0)

Direction

保留(0)

Endpoint number

bRequestTypebit4~bit0值为1时即目的地是接口wIndex则代表:

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

保留(0)

Interface number

上面的表格够清晰了吧!呵呵。

usb协议中有几种标准的usb请求如下:

#define USB_REQ_GET_STATUS               0x00  -- 获取状态

#define USB_REQ_CLEAR_FEATURE            0x01  --清除或禁止某一特定功能

#define USB_REQ_SET_FEATURE              0x03  --设定或使能某一特定功能

#define USB_REQ_SET_ADDRESS              0x05  --设定地址

#define USB_REQ_GET_DESCRIPTOR          0x06  --获取描述符

#define USB_REQ_SET_DESCRIPTOR           0x07  --设定描述符

#define USB_REQ_GET_CONFIGURATION   0x08  --获取配置

#define USB_REQ_SET_CONFIGURATION    0x09  --设定配置

#define USB_REQ_GET_INTERFACE             0x0A  --获取接口

#define USB_REQ_SET_INTERFACE                  0x0B  --设定接口

#define USB_REQ_SYNCH_FRAME            0x0C  --同步帧

关于上述的请求命令其实在看hub的时候都涉及到了,只不过在这里单独来看了。

 

三.  总结

本文主要是看usbmessage的实现以及其具体的参数说明。

阅读(5665) | 评论(1) | 转发(2) |
0

上一篇:linux urb结束处理

下一篇:usb hub请求

给主人留下些什么吧!~~

wdsshy2013-03-21 11:47:46

非常感谢!