Linux那些事儿 之 戏说USB(31)设备的生命线(十)

转载地址:http://blog.csdn.net/fudan_abc/article/details/1837722

经过了许多事

你是不是觉得累

这样的心情

我曾有过几回

现在的你我想一定

很疲惫

内核代码就象酒

有的苦有的烈

这样的滋味

你我早晚要体会

把那内核当作一场宿醉

明日的代码莫再要装着昨天的伤悲

请与我举起杯

跟内核干杯

跟着设备的生命线走到现在,我算是明白了,什么东西的发展都是越往后越高级越复杂,就好像人一样,从Attached走到Powered只是弹指一挥间,从Powered再到Default虽说要复位一下,也算是三下五除二了,再从Default走到Address简直练吃奶劲儿都使出来了,应该把阿Q拉过来念叨两句“Address?有趣!来了一群鬼佬,叫到,Address,Address,于是就Address了。”再给张小表,看看现在和上次那张表出现的时候有什么变化。

state

USB_STATE_ADDRESS

speed

taken

ep0

ep0.urb_list,描述符长度/类型,wMaxPacketSize

接下来设备的目标当然就是Configured了,My god!又要经过多少事,遇到多少人?如果实在觉得辛苦,可以去穿件绿衣服,因为忍者神龟先生说了:要想生活过得去,背上就得带点绿!

要进入Configured状态,你得去配置设备,当然不能是盲目的去配置,要知道设备是可能有多个配置的,所以你要有选择有目的有步骤有计划的去配置,要做这样一个四有新人,就要先去获得设备的设备描述符,message.c中的usb_get_device_descriptor()就是core里专门干这个的。

842  /*
843   * usb_get_device_descriptor - (re)reads the device descriptor (usbcore)
844   * @dev: the device whose device descriptor is being updated
845   * @size: how much of the descriptor to read
846   * Context: !in_interrupt ()
847   *
848   * Updates the copy of the device descriptor stored in the device structure,
849   * which dedicates space for this purpose.
850   *
851   * Not exported, only for use by the core.  If drivers really want to read
852   * the device descriptor directly, they can call usb_get_descriptor() with
853   * type = USB_DT_DEVICE and index = 0.
854   *
855   * This call is synchronous, and may not be used in an interrupt context.
856   *
857   * Returns the number of bytes received on success, or else the status code
858   * returned by the underlying usb_control_msg() call.
859   */
860  int  usb_get_device_descriptor (struct  usb_device  * dev , unsigned int  size )
861  {
862          struct  usb_device_descriptor  * desc ;
863          int  ret ;
864
865          if ( size  > sizeof(* desc ))
866                  return - EINVAL ;
867           desc  =  kmalloc (sizeof(* desc ),  GFP_NOIO );
868          if (! desc )
869                  return - ENOMEM ;
870
871           ret  =  usb_get_descriptor ( dev USB_DT_DEVICE , 0,  desc size );
872          if ( ret  >= 0)
873                   memcpy (& dev -> descriptor desc size );
874           kfree ( desc );
875          return  ret ;
876  }

这个函数比较的精悍,先是准备了一个struct usb_device_descriptor结构体,然后就用它去调用message.c里的usb_get_descriptor()获得设备描述符,获得之后再把得到的描述符复制到设备struct usb_device结构体的descriptor成员里。因此,这个函数成功与否的关键就在usb_get_descriptor()。其实对于写驱动的来说,眼里是只有usb_get_descriptor()没有usb_get_device_descriptor()的,不管你想获得哪种描述符都是要通过usb_get_descriptor(),而usb_get_device_descriptor()是专属内核用的接口。

596  /**
597   * usb_get_descriptor - issues a generic GET_DESCRIPTOR request
598   * @dev: the device whose descriptor is being retrieved
599   * @type: the descriptor type (USB_DT_*)
600   * @index: the number of the descriptor
601   * @buf: where to put the descriptor
602   * @size: how big is "buf"?
603   * Context: !in_interrupt ()
604   *
605   * Gets a USB descriptor.  Convenience functions exist to simplify
606   * getting some types of descriptors.  Use
607   * usb_get_string() or usb_string() for USB_DT_STRING.
608   * Device (USB_DT_DEVICE) and configuration descriptors (USB_DT_CONFIG)
609   * are part of the device structure.
610   * In addition to a number of USB-standard descriptors, some
611   * devices also use class-specific or vendor-specific descriptors.
612   *
613   * This call is synchronous, and may not be used in an interrupt context.
614   *
615   * Returns the number of bytes received on success, or else the status code
616   * returned by the underlying usb_control_msg() call.
617   */
618  int  usb_get_descriptor (struct  usb_device  * dev , unsigned char  type , unsigned char  index , void * buf , int  size )
619  {
620          int  i ;
621          int  result ;
622         
623           memset ( buf ,0, size );     // Make sure we parse really received data
624
625          for ( i  = 0;  i  < 3; ++ i ) {
626                  /* retry on length 0 or stall; some devices are flakey */
627                   result  =  usb_control_msg ( dev usb_rcvctrlpipe ( dev , 0),
628                                   USB_REQ_GET_DESCRIPTOR USB_DIR_IN ,
629                                  ( type  << 8) +  index , 0,  buf size ,
630                                   USB_CTRL_GET_TIMEOUT );
631                  if ( result  == 0 ||  result  == - EPIPE )
632                          continue;
633                  if ( result  > 1 && (( u8  *) buf )[1] !=  type ) {
634                           result  = - EPROTO ;
635                          continue;
636                  }
637                  break;
638          }
639          return  result ;
640  }

参数type就是用来区分不同的描述符的,协议里说了,GET_DESCRIPTOR请求主要就是适用于三种描述符,设备描述符,配置描述符和字符串描述符。参数index是要获得的描述符的序号,如果希望得到的这种描述符设备里可以有多个,你需要指定获得其中的哪个,比如配置描述符就可以有多个,不过对于设备描述符来说,是只有一个的,所以这里的index应该为0。参数buf和size就是描述你用来放置获得的描述符的缓冲区的。

这个函数的内容挺单调的,主要就是调用了一个usb_control_msg(),你如果到现在还觉得usb_control_msg()只是个熟悉的陌生人,那俺也就太失败了。这里要说的第一个问题是它的一堆参数,这就需要认真了解一下spec 9.4.3里的这张表

GET_DESCRIPTOR请求的数据传输方向很明显是device-to-host的,而且还是协议里规定所有设备都要支持的标准请求,也不是针对端点或者接口什么的,而是针对设备的,所以bRequestType只能为0x80,就是上面表里的10000000B,也等于628行的USB_DIR_IN。wValue的高位字节表示描述符的类型,低位字节表示描述符的序号,所以就有629行的(type << 8) + index。wIndex对于字符串描述符应该设置为使用语言的ID,对于其它的描述符应该设置为0,所以也有了629行中间的那个0。至于wLength,就是描述符的长度,对于设备描述符,一般来说你都会指定为USB_DT_DEVICE_SIZE吧。

USB_CTRL_GET_TIMEOUT是定义在include/linux/usb.h里的一个宏,值为5000,表示有5s的超时时间。

1324  /*
1325   * timeouts, in milliseconds, used for sending/receiving control messages
1326   * they typically complete within a few frames (msec) after they're issued
1327   * USB identifies 5 second timeouts, maybe more in a few cases, and a few
1328   * slow devices (like some MGE Ellipse UPSes) actually push that limit.
1329   */
1330  #define  USB_CTRL_GET_TIMEOUT     5000
1331  #define  USB_CTRL_SET_TIMEOUT     5000

第二个问题就是为什么会有3次循环。这个又要归咎于一些不守规矩的厂商了,搞出的设备古里古怪的,比如一些usb读卡器,一次请求还不定能成功,但是设备描述符拿不到接下来就没法子走了,所以这里多试几次,再不成功,就成鬼了。至于631到636行之间的代码都是判断是不是成功得到请求的描述符的,这个版本的内核这里的判断还比较混乱,就不多说了,你只要知道((u8 *)buf)[1] != type是用来判断获得描述符是不是请求的类型就可以了。

 

现在设备描述符已经有了,但是只有设备描述符是远远不够的,你从设备描述符里只能知道它一共支持几个配置,具体每个配置是何方神圣,是公的还是母的都不知道,你要配置一个设备总得知道这些吧,总不能学李湘说“其实新郎是谁并不重要”,那种酷劲儿不是人人都能学来的。所以接下来就要获得各个配置的配置描述符,并且拿结果去充实struct usb_device的config、rawdescriptors等相关元素。core内部并不直接调用上面的usb_get_descriptor()去完成这个任务,而是调用config.c里的usb_get_configuration(),为什么?core总是需要做更多的事情,不然就不叫core了。

474  // hub-only!! ... and only in reset path, or usb_new_device()
475  // (used by real hubs and virtual root hubs)
476  int  usb_get_configuration (struct  usb_device  * dev )
477  {
478          struct  device  *ddev = & dev -> dev ;
479          int ncfg =  dev -> descriptor .bNumConfigurations;
480          int  result  = - ENOMEM ;
481          unsigned int cfgno,  length ;
482          unsigned char * buffer ;
483          unsigned char *bigbuffer;
484          struct  usb_config_descriptor  * desc ;
485
486          if (ncfg >  USB_MAXCONFIG ) {
487                   dev_warn (ddev, "too many configurations: %d, "
488                      "using maximum allowed: %d/n", ncfg,  USB_MAXCONFIG );
489                   dev -> descriptor .bNumConfigurations = ncfg =  USB_MAXCONFIG ;
490          }
491
492          if (ncfg < 1) {
493                   dev_err (ddev, "no configurations/n");
494                  return - EINVAL ;
495          }
496
497           length  = ncfg * sizeof(struct  usb_host_config );
498           dev -> config  =  kzalloc ( length GFP_KERNEL );
499          if (! dev -> config )
500                  goto err2;
501
502           length  = ncfg * sizeof(char *);
503           dev ->rawdescriptors =  kzalloc ( length GFP_KERNEL );
504          if (! dev ->rawdescriptors)
505                  goto err2;
506
507           buffer  =  kmalloc ( USB_DT_CONFIG_SIZE GFP_KERNEL );
508          if (! buffer )
509                  goto err2;
510           desc  = (struct  usb_config_descriptor  *) buffer ;
511
512          for (cfgno = 0; cfgno < ncfg; cfgno++) {
513                  /* We grab just the first descriptor so we know how long
514                   * the whole configuration is */
515                   result  =  usb_get_descriptor ( dev USB_DT_CONFIG , cfgno,
516                       buffer USB_DT_CONFIG_SIZE );
517                  if ( result  < 0) {
518                           dev_err (ddev, "unable to read config index %d "
519                              "descriptor/%s/n", cfgno, "start");
520                           dev_err (ddev, "chopping to %d config(s)/n", cfgno);
521                           dev -> descriptor .bNumConfigurations = cfgno;
522                          break;
523                  } else if ( result  < 4) {
524                           dev_err (ddev, "config index %d descriptor too short "
525                              "(expected %i, got %i)/n", cfgno,
526                               USB_DT_CONFIG_SIZE result );
527                           result  = - EINVAL ;
528                          goto  err ;
529                  }
530                   length  =  max ((int)  le16_to_cpu ( desc ->wTotalLength),
531                       USB_DT_CONFIG_SIZE );
532
533                  /* Now that we know the length, get the whole thing */
534                  bigbuffer =  kmalloc ( length GFP_KERNEL );
535                  if (!bigbuffer) {
536                           result  = - ENOMEM ;
537                          goto  err ;
538                  }
539                   result  =  usb_get_descriptor ( dev USB_DT_CONFIG , cfgno,
540                      bigbuffer,  length );
541                  if ( result  < 0) {
542                           dev_err (ddev, "unable to read config index %d "
543                              "descriptor/%s/n", cfgno, "all");
544                           kfree (bigbuffer);
545                          goto  err ;
546                  }
547                  if ( result  <  length ) {
548                           dev_warn (ddev, "config index %d descriptor too short "
549                              "(expected %i, got %i)/n", cfgno,  length result );
550                           length  =  result ;
551                  }
552
553                   dev ->rawdescriptors[cfgno] = bigbuffer;
554
555                   result  =  usb_parse_configuration (& dev -> dev , cfgno,
556                      & dev -> config [cfgno], bigbuffer,  length );
557                  if ( result  < 0) {
558                          ++cfgno;
559                          goto  err ;
560                  }
561          }
562           result  = 0;
563
564   err :
565           kfree ( buffer );
566           dev -> descriptor .bNumConfigurations = cfgno;
567  err2:
568          if ( result  == - ENOMEM )
569                   dev_err (ddev, "out of memory/n");
570          return  result ;
571  }

说代码前先说点理论,不然要被这么生猛的代码给吓倒了。不管过多少河拐几道弯,要想得到配置描述符,最终都不可避免的要向设备发送GET_DESCRIPTOR请求,这就需要以USB_DT_CONFIG为参数调用usb_get_descriptor函数,也就需要知道该为获得的描述符准备多大的一个缓冲区,本来这个长度应该很明确的为USB_DT_CONFIG_SIZE,它表示的就是配置描述符的大小,但是实际上不是这么回事儿,USB_DT_CONFIG_SIZE只表示配置描述符本身的大小,并不表示GET_DESCRIPTOR请求返回结果的大小。因为向设备发送GET_DESCRIPTOR请求时,设备并不单单返回一个配置描述符了事,而是一股脑儿的将这个配置下面的所有接口描述符,端点描述,还有class-或vendor-specific描述符都返回了给你,这要比商场里那些买300送100的优惠力度大得多。那么这个总长度如何得到那?在神秘的配置描述符里有这样一个神秘的字段wTotalLength,它里面记录的就是这个总长度,那么问题就简单了,可以首先发送USB_DT_CONFIG_SIZE个字节的请求过去,获得这个配置描述符的内容,从而获得那个总长度,然后以这个长度再请求一次,这样就可以获得一个配置下面所有的描述符内容了。上面的usb_get_configuration()采用的就是这个处理方法。

479行,获得设备理配置描述符的数目。

486行,这些检验又来了,在光天化日之下莫明其妙的受到戴大盖帽的盘问很不爽是吧,但这就是他们的规矩他们的工作,不然你让他们做什么。USB_MAXCONFIG是config.c理定义的

14  #define  USB_MAXCONFIG                    8       /* Arbitrary limit */

限制了一个设备最多只能支持8种配置拥有8个配置描述符,如果超出了这个限制,489行就强制它为这个最大值,你一个设备要想在linux里混就得守这里的规矩,自由民主只是相对的。不过如果设备里没有任何一个配置描述符,什么配置都没有,就想裸身蒙混过关,那是不可能的,492行这关就过不去,你设备赤身裸体没错,可是拿出来给人看就有错了,大白天在外滩喷泉里洗澡,以为自己是那个欲望主妇里的伊娃可以随便露啊,不是影响市容影响民风影响上海美好形象么。

498行,struct usb_device里的config表示的是设备拥有的所有配置,你设备有多少个配置就为它准备多大的空间。

503行,rawdescriptors还认识吧,这是个字符指针数组里的每一项都指向一个使用GET_DESCRIPTOR请求去获取配置描述符时所得到的结果。

507行,准备一个大小为USB_DT_CONFIG_SIZE的缓冲区,第一次发送GET_DESCRIPTOR请求要用的。

512行,剩下的主要就是这个for循环了,获取每一个配置的那些描述符。

515行,诚如上面所说的,首先发送USB_DT_CONFIG_SIZE个字节请求,获得配置描述符的内容。然后对返回的结果进行检验,知道为什么523行会判断结果是不是小于4么?答案尽在配置描述符中,里面的3,4字节就是wTotalLength,只要得到前4个字节,就已经完成任务能够获得总长度了。

534行,既然总长度已经有了,那么这里就为接下来的GET_DESCRIPTOR请求准备一个大点的缓冲区。

539行,现在可以获得这个配置相关的所有描述符了。然后是对返回结果的检验,再然后就是将得到的那一堆数据的地址赋给rawdescriptors数组里的指针。

555行,从这个颇有韵味的数字555开始,你将会遇到另一个超级变态的函数,它将对前面GET_DESCRIPTOR请求获得的那堆数据做处理。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值