当前时区为 UTC + 8 小时



发表新帖 回复这个主题  [ 3 篇帖子 ] 
作者 内容
1 楼 
 文章标题 : u盘驱动程序之结构体数组索引号的处理疑问
帖子发表于 : 2015-01-23 12:04 

注册: 2011-08-13 20:03
帖子: 31
送出感谢: 3
接收感谢: 0 次
最近在读linux的u盘驱动程序,遇到了一点疑问。特发此贴,向大家求助。



代码:

#define USB_INTERFACE_INFO(cl,sc,pr) \
   .match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), .bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)


static struct usb_device_id storage_usb_ids [] = {

#   include "unusual_devs.h"
#undef UNUSUAL_DEV
   /* Control/Bulk transport for all SubClass values */
   { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CB) },
   { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CB) },
   { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CB) },
   { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CB) },
   { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CB) },
   { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CB) },

   /* Control/Bulk/Interrupt transport for all SubClass values */
   { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CBI) },
   { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CBI) },
   { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CBI) },
   { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CBI) },
   { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CBI) },
   { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CBI) },

   /* Bulk-only transport for all SubClass values */
   { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_BULK) },
   { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_BULK) },
   { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_BULK) },
   { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_BULK) },
   { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_BULK) },
#if !defined(CONFIG_BLK_DEV_UB) && !defined(CONFIG_BLK_DEV_UB_MODULE)
   { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
#endif

   /* Terminating entry */
   { }
};

/* Probe to see if we can drive a newly-connected USB device */
static int storage_probe(struct usb_interface *intf,
          const struct usb_device_id *id)
{
   struct us_data *us;
   [b][color=#FF0000]const int id_index = id - storage_usb_ids; [/color][/b]
   int result;

   US_DEBUGP("USB Mass Storage device detected\n");

   /* Allocate the us_data structure and initialize the mutexes */
   us = (struct us_data *) kmalloc(sizeof(*us), GFP_KERNEL);
   if (!us) {
      printk(KERN_WARNING USB_STORAGE "Out of memory\n");
      return -ENOMEM;
   }
   memset(us, 0, sizeof(struct us_data));
   init_MUTEX(&(us->dev_semaphore));
   init_MUTEX_LOCKED(&(us->sema));
   init_completion(&(us->notify));
   init_waitqueue_head(&us->dev_reset_wait);
   init_waitqueue_head(&us->scsi_scan_wait);
   init_completion(&us->scsi_scan_done);

   /* Associate the us_data structure with the USB device */
   result = associate_dev(us, intf);
   if (result)
      goto BadDevice;

   /*
    * Get the unusual_devs entries and the descriptors
    *
    * id_index is calculated in the declaration to be the index number
    * of the match from the usb_device_id table, so we can find the
    * corresponding entry in the private table.
    */
   get_device_info(us, id_index);

#ifdef CONFIG_USB_STORAGE_SDDR09
   if (us->protocol == US_PR_EUSB_SDDR09 ||
         us->protocol == US_PR_DPCM_USB) {
      /* set the configuration -- STALL is an acceptable response here */
      if (us->pusb_dev->actconfig->desc.bConfigurationValue != 1) {
         US_DEBUGP("active config #%d != 1 ??\n", us->pusb_dev
            ->actconfig->desc.bConfigurationValue);
         goto BadDevice;
      }
      result = usb_reset_configuration(us->pusb_dev);

      US_DEBUGP("Result of usb_reset_configuration is %d\n", result);
      if (result == -EPIPE) {
         US_DEBUGP("-- stall on control interface\n");
      } else if (result != 0) {
         /* it's not a stall, but another error -- time to bail */
         US_DEBUGP("-- Unknown error.  Rejecting device\n");
         goto BadDevice;
      }
   }
#endif

   /* Get the transport, protocol, and pipe settings */
   result = get_transport(us);
   if (result)
      goto BadDevice;
   result = get_protocol(us);
   if (result)
      goto BadDevice;
   result = get_pipes(us);
   if (result)
      goto BadDevice;

   /* Acquire all the other resources and add the host */
   result = usb_stor_acquire_resources(us);
   if (result)
      goto BadDevice;
   result = scsi_add_host(us->host, &intf->dev);
   if (result) {
      printk(KERN_WARNING USB_STORAGE
         "Unable to add the scsi host\n");
      goto BadDevice;
   }

   /* Start up the thread for delayed SCSI-device scanning */
   result = kernel_thread(usb_stor_scan_thread, us, CLONE_VM);
   if (result < 0) {
      printk(KERN_WARNING USB_STORAGE
             "Unable to start the device-scanning thread\n");
      scsi_remove_host(us->host);
      goto BadDevice;
   }

   return 0;

   /* We come here if there are any problems */
BadDevice:
   US_DEBUGP("storage_probe() failed\n");
   usb_stor_release_resources(us);
   dissociate_dev(us);
   return result;
}


页首
 用户资料  
 
2 楼 
 文章标题 : Re: u盘驱动程序之结构体数组索引号的处理疑问
帖子发表于 : 2015-01-23 12:15 

注册: 2011-08-13 20:03
帖子: 31
送出感谢: 3
接收感谢: 0 次
代码有点长所以分开来说,

在函数storage_probe中有这么一句
const int id_index = id - storage_usb_ids; // 前后的 [b][color=#FF0000]是发帖时弄上去的,不必在意
在后面的函数中,多次用到id_index 变量,将其当成了数组下标。
我的理解是这样的:id是数组成员的地址,storage_usb_ids是数组的起始地址。id - storage_usb_ids得到不应该是数组下标啊。因为数组的成员是数据结构类型的,一个数组成员占用的空间不是4个字节。所以我认为
const int id_index = id - storage_usb_ids;
应该改成:
const int id_index = (id - storage_usb_ids)/sizeof(struct usb_device_id);

不知道我的理解哪里错了,请各位帮我指正一下。

Note:linux内核版本是linux-2.6.10.


页首
 用户资料  
 
3 楼 
 文章标题 : Re: u盘驱动程序之结构体数组索引号的处理疑问
帖子发表于 : 2015-01-23 16:17 
头像

注册: 2008-09-18 13:11
帖子: 2781
送出感谢: 1
接收感谢: 453
C语言中指针相减的结果是两个指针之间的元素数目,所以不需要再去除usb_device_id的大小



_________________
评价: 3.7% chenxitwo
 
页首
 用户资料  
 
显示帖子 :  排序  
发表新帖 回复这个主题  [ 3 篇帖子 ] 

当前时区为 UTC + 8 小时


在线用户

正在浏览此版面的用户:没有注册用户 和 2 位游客


不能 在这个版面发表主题
不能 在这个版面回复主题
不能 在这个版面编辑帖子
不能 在这个版面删除帖子
不能 在这个版面提交附件

前往 :  
本站点为公益性站点,用于推广开源自由软件,由 DiaHosting VPSBudgetVM VPS 提供服务。
我们认为:软件应可免费取得,软件工具在各种语言环境下皆可使用,且不会有任何功能上的差异;
人们应有定制和修改软件的自由,且方式不受限制,只要他们自认为合适。

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
简体中文语系由 王笑宇 翻译