由kernel/drivers/usb/gadget/android.c
static int android_probe(struct platform_device *pdev)
{
struct android_usb_platform_data *pdata = pdev->dev.platform_data;
struct android_dev *dev = _android_dev;
printk(KERN_INFO "android_probe pdata: %p\n", pdata);
if (pdata) {
dev->products = pdata->products;
dev->num_products = pdata->num_products;
dev->functions = pdata->functions;
dev->num_functions = pdata->num_functions;
if (pdata->vendor_id)
device_desc.idVendor =
__constant_cpu_to_le16(pdata->vendor_id);
if (pdata->product_id) {
dev->product_id = pdata->product_id;
device_desc.idProduct =
__constant_cpu_to_le16(pdata->product_id);
}
if (pdata->version)
dev->version = pdata->version;
if (pdata->product_name)
strings_dev[STRING_PRODUCT_IDX].s = pdata->product_name;
if (pdata->manufacturer_name)
strings_dev[STRING_MANUFACTURER_IDX].s =
pdata->manufacturer_name;
if (pdata->serial_number)
strings_dev[STRING_SERIAL_IDX].s = pdata->serial_number;
}
return usb_composite_register(&android_usb_driver);
}
可以知道serial_number是透過pdata->serial_number得到
而pdata則是在arch/arm/mach-omap2/usb-musb.c被註冊
/* standard android USB platform data */
static struct android_usb_platform_data andusb_plat = {
.vendor_id = OMAP_VENDOR_ID,
.product_id = OMAP_UMS_PRODUCT_ID,
.manufacturer_name = "Texas Instruments Inc.",
.product_name = "OMAP-3/4",
.serial_number = device_serial,
.num_products = ARRAY_SIZE(usb_products),
.products = usb_products,
.num_functions = ARRAY_SIZE(usb_functions_all),
.functions = usb_functions_all,
};
static struct platform_device androidusb_device = {
.name = "android_usb",
.id = -1,
.dev = {
.platform_data = &andusb_plat,
},
};
在andusb_plat的struct中可以發現.
serial_number,在深入追下去便發現
static void usb_gadget_init(void)
{
unsigned int val[4] = { 0 };
unsigned int reg;
#ifdef CONFIG_USB_ANDROID_RNDIS
int i;
char *src;
#endif
reg = DIE_ID_REG_BASE + DIE_ID_REG_OFFSET;
if (cpu_is_omap44xx()) {
val[0] = omap_readl(reg);
val[1] = omap_readl(reg + 0x8);
val[2] = omap_readl(reg + 0xC);
val[3] = omap_readl(reg + 0x10);
} else if (cpu_is_omap34xx()) {
val[0] = omap_readl(reg);
val[1] = omap_readl(reg + 0x4);
val[2] = omap_readl(reg + 0x8);
val[3] = omap_readl(reg + 0xC);
}
snprintf(device_serial, MAX_USB_SERIAL_NUM, "%08X%08X%08X%08X",
val[3], val[2], val[1], val[0]);
#ifdef CONFIG_USB_ANDROID_RNDIS
/* create a fake MAC address from our serial number.
* first byte is 0x02 to signify locally administered.
*/
rndis_pdata.ethaddr[0] = 0x02;
src = device_serial;
for (i = 0; *src; i++) {
/* XOR the USB serial across the remaining bytes */
rndis_pdata.ethaddr[i % (ETH_ALEN - 1) + 1] ^= *src++;
}
platform_device_register(&rndis_device);
#endif
#ifdef CONFIG_USB_ANDROID_MASS_STORAGE
platform_device_register(&usb_mass_storage_device);
#endif
platform_device_register(&androidusb_device);
}
原來serial_number是讀取CPU暫存器在丟回serial_number。
詳細的source code可以到
gitorious
另外因工作的關係發現異想不到的問題,工作上的需求是出貨時每台serial number都要不一樣以便區分每台,而問題在於第一台插上windows XP並安裝adb driver後,第二台在插上結果卻需要在安裝新的adb driver,這問題看似沒什麼,但對於工廠來說時間就是金錢且windows 7不會有這問題。
參考
自製USB問題排困解難指南最後面那段
步驟:
- regedit 並到[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\UsbFlags]
- 確認GlobalDisableSerNumGen的值是否為1
- 新增機碼IgnoreHWSerNum[VID][PID]定設為1
EX: VID=0x451 PID=0xD101 => IgnoreHWSerNum0451D101 = 1
- 開機