usb子系统浅析--urb

urb传输过程

这里写图片描述

/**
    这个函数做了一下事情:
                1 : 分配了内存空间,并清空
                2 : 引用计数被置1,有一个不明白的地方是 :  这里的urb->anchor_list链表是干什么用的?
                                                     他在何时被添加节点,又是何时被移除节点的?

    iso_packets : 这个urb中的等时数据包的数量
                  仅仅用于等时传输中。如果用于其他类型的传输,那么这个参数为0    

    mem_flags : 分配内存的标志,和kmalloc的标志一样,因为他底层就是用kmalloc来分配的
*/
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) {
        printk(KERN_ERR "alloc_urb: kmalloc failed\n");
        return NULL;  //失败返回NULL
        /**
            看他的使用 : 
                acecad->irq = usb_alloc_urb(0, GFP_KERNEL);
                if (!acecad->irq) 
                {
                    err = -ENOMEM;
                    goto fail2;
                }
        */
    }
    /**
        初始化urb,也就是 清空内存、引用计数置1等操作

        那么,urb的引用计数有什么作用呢?
        1 : 
            urb提交到usb主机控制器的时候,他的值被增加1
            urb从主机控制器返回USB驱动程序的时候,他的值减少1

        2 : 
            在下面的usb_free_urb()中也是依据urb的引用计数来释放urb的。

        下面会有实验验证。请往下看。
    */
    usb_init_urb(urb);

    return urb;   //返回urb指针
}

/**
    释放urb,

    这个函数:
            判断urb的引用计数,
            如果为1的时候,就调用urb_destroy()来释放。
*/
void usb_free_urb(struct urb *urb)
{
    if (urb)
    {
        kref_put(&urb->kref, urb_destroy);
    }
}

static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref))
{
    return kref_sub(kref, 1, release);
}

/**
    看他是调用 urb_destroy()函数来释放的。
*/
static inline int kref_sub(struct kref *kref, unsigned int count,void (*release)(struct kref *kref))
{
    WARN_ON(release == NULL);

    /**
        atomic_sub_and_test :从原子类型的变量count中减去1,并判断结果是否为0,如果为0,返回真,否则返回假
        当urb的引用计数为1的时候,会被释放

        前面的usb_alloc_urb()将他置为 1的。
    */
    if (atomic_sub_and_test((int) count, &kref->refcount)) 
    {
        /**
            调用urb_destroy()来释放
        */
        release(kref);
        return 1;
    }
    return 0;
}

static void urb_destroy(struct kref *kref)
{
    struct urb *urb = to_urb(kref);

    if (urb->transfer_flags & URB_FREE_BUFFER)
    {
        /**
            释放缓冲区
        */
        kfree(urb->transfer_buffer);
    }
    /**
        释放urb
    */
    kfree(urb);
}

这里写图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值