u盘驱动程序之结构体数组索引号的处理疑问

内核编译和嵌入式产品的设计与开发
回复
chenxitwo
帖子: 31
注册时间: 2011-08-13 20:03

u盘驱动程序之结构体数组索引号的处理疑问

#1

帖子 chenxitwo » 2015-01-23 12:04

最近在读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;
}
chenxitwo
帖子: 31
注册时间: 2011-08-13 20:03

Re: u盘驱动程序之结构体数组索引号的处理疑问

#2

帖子 chenxitwo » 2015-01-23 12:15

代码有点长所以分开来说,

在函数storage_probe中有这么一句
const int id_index = id - storage_usb_ids; // 前后的 是发帖时弄上去的,不必在意
在后面的函数中,多次用到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.
头像
astolia
论坛版主
帖子: 6540
注册时间: 2008-09-18 13:11

Re: u盘驱动程序之结构体数组索引号的处理疑问

#3

帖子 astolia » 2015-01-23 16:17

C语言中指针相减的结果是两个指针之间的元素数目,所以不需要再去除usb_device_id的大小
回复