usb驱动开发13——设备生命线

上一节勉勉强强把struct urb这个中心给说完,接着看那三个基本点。

第一个基本点,usb_alloc_urb函数,创建urb的专用函数,为一个urb申请内存并做初始化,在drviers/usb/core/urb.c里定义:
/**

  • usb_alloc_urb - creates a new urb for a USB driver to use

  • @iso_packets: number of iso packets for this urb

  • @mem_flags: the type of memory to allocate, see kmalloc() for a list of

  • valid options for this.

  • Creates an urb for the USB driver to use, initializes a few internal

  • structures, incrementes the usage counter, and returns a pointer to it.

  • If no memory is available, NULL is returned.

  • If the driver want to use this urb for interrupt, control, or bulk

  • endpoints, pass ‘0’ as the number of iso packets.

  • The driver must call usb_free_urb() when it is finished with the urb.
    */
    struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
    {
    struct urb *urb;

    urb = kmalloc(sizeof(struct urb) +
    iso_packets * sizeof(struct usb_iso_packet_descriptor),
    mem_flags);
    if (!urb) {
    err(“alloc_urb: kmalloc failed”);
    return NULL;
    }
    usb_init_urb(urb);
    return urb;
    }
    这函数只做了两件事情,拿kmalloc来为urb申请内存,然后调用usb_init_urb进行初始化。usb_init_urb函数的作用就是初始化urb的引用计数,并用memset顺便把这里给urb申请的内存清零。没什么说的了么?usb_alloc_urb说:别看我简单,我也是很有内涵的。

先看第一个问题,它的第一个参数iso_packets,表示的是struct urb结构最后那个变长数组iso_frame_desc的元素数目,也就是应该与number_of_packets的值相同,所以对于控制/中断/批量传输,这个参数都应该为0。这也算是给咱们示范了下变长数组咋个用法,内核里到处都是C的示范工程。

第二个问题是参数mem_flags的类型gfp_t,早几个版本的内核,这里还是int,当然这里变成gfp_t是因为kmalloc参数里的那个标志参数的类型从int变成gfp_t了,你要用kmalloc来申请内存,就得遵守它的规则。咱们来调查一下它的背景。它在include/linux/types.h里定义。

typedef unsigned bitwise gfp_t;

很显然,要了解gfp_t,关键是要了解__bitwise__,它也在types.h里定义:

#ifdef __CHECKER__

#define __bitwise__ __attribute__((bitwise))

#else

#define __bitwise__

#endif

bitwise__的含义又取决于是否定义了__CHECKER,如果没有定义__CHECKER__,那__bitwise__就啥也不是。哪里定义了__CHECKER__?咱们不找,因为内核代码里就没有哪个地方定义了__CHECKER__,它是有关Sparse工具的,内核编译时的参数决定了是不是使用Sparse工具来做类型检查。那Sparse又是什么?它是一种静态分析工具(static analysis tool), 用于在linux内核源代码中发现各种类型的漏洞,一直都是比较神秘的角色,最初由Linus Torvalds写的,后来linus没有继续维护,直到去年的冬天,它才又有了新的维护者Josh Triplett。有关Sparse再多的东东,咱们还是各自去研究吧,这里不多说了。

可能还会有第三个问题,usb_alloc_urb也没做多少事啊,它做的那些咱们自己很容易就能做了,为什么还说驱动里一定要使用它来创建urb那?按照C++的说法,它就是urb的构造函数,构造函数是创建对象的唯一方式。它将创建urb的工作给包装了,咱们只管调用就是了,孙子兵法里有,以不变应万变。

对应的,当然还会有个析构函数,销毁urb的,也在urb.c里定义。usb_free_urb只调用kref_put将urb的引用计数减一,减了之后如果变为0,也就是没人再用它了,就调用urb_destroy将它销毁掉。

接着看第二个基本点,usb_fill_control_urb函数,初始化刚才创建的控制urb,你要想使用urb进行usb传输,不是光为它申请点内存就够的,你得为它初始化。它是在include/linux/usb.h里定义的内联函数:

static inline 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_fn,
					 void *context)
{
   
	spin_lock_init(&urb->lock);
	urb->dev = dev;
	urb->pipe = pipe;
	urb->setup_packet = setup_packet;
	urb->transfer_buffer = transfer_buffer;
	urb->transfer_buffer_length = buffer_length
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kcyuan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值