core配置设备使用的是message.c里的usb_set_configuration函数

int usb_set_configuration(struct usb_device *dev, int configuration)
{int i, ret;struct usb_host_config *cp = NULL;struct usb_interface **new_interfaces = NULL;struct usb_hcd *hcd = bus_to_hcd(dev->bus);int n, nintf;if (dev->authorized == 0 || configuration == -1)configuration = 0;else {for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {if (dev->config[i].desc.bConfigurationValue ==configuration) {cp = &dev->config[i];break;}}}if ((!cp && configuration != 0))return -EINVAL;/* The USB spec says configuration 0 means unconfigured.* But if a device includes a configuration numbered 0,* we will accept it as a correctly configured state.* Use -1 if you really want to unconfigure the device.*/if (cp && configuration == 0)dev_warn(&dev->dev, "config 0 descriptor??\n");/* Allocate memory for new interfaces before doing anything else,* so that if we run out then nothing will have changed. */n = nintf = 0;if (cp) {nintf = cp->desc.bNumInterfaces;new_interfaces = kmalloc(nintf * sizeof(*new_interfaces),GFP_NOIO);if (!new_interfaces) {dev_err(&dev->dev, "Out of memory\n");return -ENOMEM;}for (; n < nintf; ++n) {new_interfaces[n] = kzalloc(sizeof(struct usb_interface),GFP_NOIO);if (!new_interfaces[n]) {dev_err(&dev->dev, "Out of memory\n");ret = -ENOMEM;
free_interfaces:while (--n >= 0)kfree(new_interfaces[n]);kfree(new_interfaces);return ret;}}i = dev->bus_mA - usb_get_max_power(dev, cp);if (i < 0)dev_warn(&dev->dev, "new config #%d exceeds power ""limit by %dmA\n",configuration, -i);}/* Wake up the device so we can send it the Set-Config request */ret = usb_autoresume_device(dev);if (ret)goto free_interfaces;/* if it's already configured, clear out old state first.* getting rid of old interfaces means unbinding their drivers.*/if (dev->state != USB_STATE_ADDRESS)usb_disable_device(dev, 1); /* Skip ep0 *//* Get rid of pending async Set-Config requests for this device */cancel_async_set_config(dev);/* Make sure we have bandwidth (and available HCD resources) for this* configuration.  Remove endpoints from the schedule if we're dropping* this configuration to set configuration 0.  After this point, the* host controller will not allow submissions to dropped endpoints.  If* this call fails, the device state is unchanged.*/mutex_lock(hcd->bandwidth_mutex);/* Disable LPM, and re-enable it once the new configuration is* installed, so that the xHCI driver can recalculate the U1/U2* timeouts.*/if (dev->actconfig && usb_disable_lpm(dev)) {dev_err(&dev->dev, "%s Failed to disable LPM\n.", __func__);mutex_unlock(hcd->bandwidth_mutex);ret = -ENOMEM;goto free_interfaces;}ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL);if (ret < 0) {if (dev->actconfig)usb_enable_lpm(dev);mutex_unlock(hcd->bandwidth_mutex);usb_autosuspend_device(dev);goto free_interfaces;}/** Initialize the new interface structures and the* hc/hcd/usbcore interface/endpoint state.*/for (i = 0; i < nintf; ++i) {struct usb_interface_cache *intfc;struct usb_interface *intf;struct usb_host_interface *alt;cp->interface[i] = intf = new_interfaces[i];intfc = cp->intf_cache[i];intf->altsetting = intfc->altsetting;intf->num_altsetting = intfc->num_altsetting;kref_get(&intfc->ref);alt = usb_altnum_to_altsetting(intf, 0);/* No altsetting 0?  We'll assume the first altsetting.* We could use a GetInterface call, but if a device is* so non-compliant that it doesn't have altsetting 0* then I wouldn't trust its reply anyway.*/if (!alt)alt = &intf->altsetting[0];intf->intf_assoc =find_iad(dev, cp, alt->desc.bInterfaceNumber);intf->cur_altsetting = alt;usb_enable_interface(dev, intf, true);intf->dev.parent = &dev->dev;intf->dev.driver = NULL;intf->dev.bus = &usb_bus_type;intf->dev.type = &usb_if_device_type;intf->dev.groups = usb_interface_groups;intf->dev.dma_mask = dev->dev.dma_mask;INIT_WORK(&intf->reset_ws, __usb_queue_reset_device);intf->minor = -1;device_initialize(&intf->dev);pm_runtime_no_callbacks(&intf->dev);dev_set_name(&intf->dev, "%d-%s:%d.%d",dev->bus->busnum, dev->devpath,configuration, alt->desc.bInterfaceNumber);}kfree(new_interfaces);ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),USB_REQ_SET_CONFIGURATION, 0, configuration, 0,NULL, 0, USB_CTRL_SET_TIMEOUT);if (ret < 0 && cp) {/** All the old state is gone, so what else can we do?* The device is probably useless now anyway.*/usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);for (i = 0; i < nintf; ++i) {usb_disable_interface(dev, cp->interface[i], true);put_device(&cp->interface[i]->dev);cp->interface[i] = NULL;}cp = NULL;}dev->actconfig = cp;mutex_unlock(hcd->bandwidth_mutex);if (!cp) {usb_set_device_state(dev, USB_STATE_ADDRESS);/* Leave LPM disabled while the device is unconfigured. */usb_autosuspend_device(dev);return ret;}usb_set_device_state(dev, USB_STATE_CONFIGURED);if (cp->string == NULL &&!(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))cp->string = usb_cache_string(dev, cp->desc.iConfiguration);/* Now that the interfaces are installed, re-enable LPM. */usb_unlocked_enable_lpm(dev);/* Enable LTM if it was turned off by usb_disable_device. */usb_enable_ltm(dev);/* Now that all the interfaces are set up, register them* to trigger binding of drivers to interfaces.  probe()* routines may install different altsettings and may* claim() any interfaces not yet bound.  Many class drivers* need that: CDC, audio, video, etc.*/for (i = 0; i < nintf; ++i) {struct usb_interface *intf = cp->interface[i];dev_dbg(&dev->dev,"adding %s (config #%d, interface %d)\n",dev_name(&intf->dev), configuration,intf->cur_altsetting->desc.bInterfaceNumber);device_enable_async_suspend(&intf->dev);ret = device_add(&intf->dev);if (ret != 0) {dev_err(&dev->dev, "device_add(%s) --> %d\n",dev_name(&intf->dev), ret);continue;}create_intf_ep_devs(intf);}usb_autosuspend_device(dev);return 0;
}

说代码前咱们再聊点这个函数背后的人生哲学,你设备不是和usb_generic_driver这个大美女配对成功了么,可是要想保持和她的这种亲密关系,你就得准备着让她去配置,准备着她想让你什么样你就什么样。这个函数就可以泾渭分明的分成三个部分三个阶段,从3到63的这几十行是准备阶段,做做常规检查啊,申请申请内存什么的。70到177这部分可是重头戏,就是在这里设备从Address发展到了Configured,可算是高潮阶段。194到209这阶段也挺重要的,主要就是充实充实设备的每个接口并提交给设备模型,为它们寻找命中注定的接口驱动,usb_generic_driver也就彻底从你设备那儿得到满足了,generic_probe的历史使命也就完成了。
先看第一阶段,9行,configuration是前边儿choose_configuration()那里返回回来的,找到合意的配置的话,就返回那个配置的bConfigurationValue值,没有找到称心的配置的话,就返回-1,所以这里的configuration值就可能有两种情况,或者为-1,或者为配置的bConfigurationValue值。当configuration为-1时这里为啥又要把它改为0捏?要知道configuration这个值是要在后面的阶段里发送SET_CONFIGURATION请求时用的,关于SET_CONFIGURATION请求,spec里说,这个值必须为0或者与配置描述符的bConfigurationValue一致,如果为0,则设备收到SET_CONFIGURATION请求后,仍然会待在Address状态。这里当configuration为-1也就是没有发现满意的配置时,设备不能进入Configured,所以要把configuration的值改为0,以便满足SET_CONFIGURATION请求的要求。
那接下来的问题就出来了,在没有找到合适配置的时候直接给configuration这个参数传个0,也就是让choose_configuration()返回个0不就得了,干吗还这么麻烦先返回个-1再把它改成0,不是脱裤子放屁多此一举么?你别愤怒,这归根结底还是那句话,林子大了什么鸟都有,有些设备就是有拿0当配置bConfigurationValue值的毛病,你又不能不让它用。usb世界里出现几个有毛病的设备也没啥大不了的,这里妥协一下就是了,想让设备回到Address状态时,usb_set_configuration()就别传递0了,传递个-1,里边儿去处理一下。如果configuration值为0或大于0的值,就从设备struct usb_device结构体的config数组里将相应配置的描述信息,也就是struct usb_host_config结构体给取出来。
20行,如果没有拿到配置的内容,configuration值就必须为0了,让设备待在Address那儿别动。这也很好理解,配置的内容都找不到了,还配置个什么劲儿。当然,如果拿到了配置的内容,但同时configuration为0,这就是对应了上面说的那种有毛病的设备的情况,就提出一下警告,告诉你不正常现象出现了。
33行,过了这个if,第一阶段就告结束了。如果配置是实实在在存在的,就为它使用的那些接口都准备一个struct usb_interface结构体。new_interfaces是开头儿就定义好的一个struct usb_interface结构体指针数组,数组的每一项都指向了一个struct usb_interface结构体,所以这里申请内存也要分两步走,先申请指针数组的,再申请每一项的。

Linux那些事儿 之 戏说USB(30)驱动的生命线(二)相关推荐

  1. Linux那些事儿 之 戏说USB(29)驱动的生命线(一)

    现在开始就沿着usb_generic_driver的成名之路走一走,设备的生命线你可以想当然的认为是从你的usb设备连接到hub的某个端口时开始,驱动的生命线就必须得回溯到usb子系统的初始化函数us ...

  2. Linux那些事儿 之 戏说USB(32)驱动的生命线(四)

    设备自从有了Address,拿到了各种描述符,就在那儿看usb_generic_driver忙活了,不过还算没白忙,设备总算是幸福的进入Configured了. Address有点像你合几代人之力辛辛 ...

  3. Linux那些事儿 之 戏说USB(30)设备的生命线(九)

    聊完了struct usb_hcd和struct usb_bus,算是已经向HCD片儿区的老大们拜过山头了,接下来就该看看usb_submit_urb()最后的那个遗留问题usb_hcd_submit ...

  4. Linux那些事儿 之 戏说USB(31)驱动的生命线(三)

    准备工作该做的都做了,别嫌太麻烦,什么事情都要经过这么一个阶段,大家都明白.现在看看第二阶段的重头戏,看看设备是怎么从Address进入Configured的.1501行,如果已经在Configure ...

  5. Linux那些事儿 之 戏说USB(19)设备的生命线(二)

    现在设备的struct usb_device结构体已经准备好了,只是还不怎么饱满,hub接下来就会给它做做整容手术,往里边儿塞点什么,充实一些内容,比如:将设备的状态设置为Powered,也就是加电状 ...

  6. Linux那些事儿 之 戏说USB(23)设备的生命线(二)

    转载地址:http://blog.csdn.net/fudan_abc/article/details/1814938 现在设备的struct usb_device结构体已经准备好了,只是还不怎么饱满 ...

  7. 【转】Linux那些事儿 之 戏说USB(23)设备的生命线(二)

    现在设备的struct usb_device结构体已经准备好了,只是还不怎么饱满,hub接下来就会给它做做整容手术,往里边儿塞点什么,充实一些内容,比如:将设备的状态设置为Powered,也就是加电状 ...

  8. Linux那些事儿 之 戏说USB(28)设备的生命线(十一)

    现在已经使用GET_DESCRIPTOR请求取到了包含一个配置里所有相关描述符内容的一堆数据,这些数据是raw的,即原始的,所有数据不管是配置描述符.接口描述符还是端点描述符都彼此的挤在一起,所以得想 ...

  9. Linux那些事儿 之 戏说USB(25)设备的生命线(八)

    回到struct usb_hcd,继续努力的往下看. 7行,又见kref,usb主机控制器的引用计数.struct usb_hcd也有自己专用的引用计数函数,看drivers/usb/core/hcd ...

最新文章

  1. 多地通知!防止疫情反扑将控制教职工和学生外出,新一轮校园封闭要开始了?...
  2. python装饰器-python装饰器是哪个版本支持的
  3. 低端没出路,请接触高端!
  4. Go的sync.Cond(四)
  5. SignalR第一节-在5分钟内完成通信连接和消息发送
  6. 【渝粤题库】陕西师范大学800001 自然地理学
  7. applicationContext配置文件模板1
  8. linux下的shell多线程用法,shell多线程操作
  9. 【转】Symstore 详细使用
  10. SAP Basic T-Code
  11. 非常规应用之PNP三级管倒置使用
  12. LeetCode(查找元素的第一个和最后一个位置)
  13. 单片机属于嵌入式系统吗?嵌入式开发要学哪些课程?
  14. 动态像素绘画——StarDust
  15. SpringCloud概括
  16. 调频 调幅 与 通信
  17. 互联网APP监控即时报警解决初步方案
  18. QQ浏览器如何设置HTTP代理
  19. android 粗体字体下载,徐静蕾加粗字体
  20. linux arecord录音

热门文章

  1. Android textview 只显示一行,多余部分显示.....
  2. ios5中apple增加了解析JSON的api——NSJSONSerialization。
  3. python学习-day2_课堂作业
  4. 微信第三方平台开发 - 常见问题汇总
  5. 【Spring】bean的作用域(@Scope) - singleton、prototype
  6. oracle的for和i++
  7. Android studio第一次使用配置(三)gradle项目构建
  8. 一个妹子图应用客户端源码
  9. 基于visual Studio2013解决面试题之0901奇偶站队
  10. 实测 Mysql UUID 性能(转)