Hi Add a parameter to file_storage usb gadget module to be able to specify the serial number of a device (for example, the serial number of an emulated usb stick). Things i'm not sure i've done well about : - 12 chars limitation for CBI transport : I need more (24 chars) for sticks serial, so i've modified the static serial declaration, and cut this string (\0 in serial[12]) if CBI is selected. - i've keep the serial static, but now that it can be modified, perhaps it should be integrated in the mod_data struct. - DRIVER_SERIAL_NUM_NOT_SET : i need a way to know if the parameter have been passed, only find that. - hexadecimal characters check : is there a better way ? - The string copy handling between char array (serial) and char pointer (serial_parm). I'm not sure it's rock-solid. - I keep the dead (moved) code enclosed in /* */ Be smart, it's my first day :) --- linux-2.6.31/drivers/usb/gadget/file_storage.c.orig 2009-09-10 00:13:59.000000000 +0200 +++ linux-2.6.31/drivers/usb/gadget/file_storage.c 2010-05-24 01:30:44.000000000 +0200 @@ -56,7 +56,7 @@ * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03), * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by * the optional "protocol" module parameter. In addition, the default - * Vendor ID, Product ID, and release number can be overridden. + * Vendor ID, Product ID, release and serial number can be overridden. * * There is support for multiple logical units (LUNs), each of which has * its own backing file. The number of LUNs can be set using the optional @@ -106,6 +106,8 @@ * vendor=0xVVVV Default 0x0525 (NetChip), USB Vendor ID * product=0xPPPP Default 0xa4a5 (FSG), USB Product ID * release=0xRRRR Override the USB release number (bcdDevice) + * serial=112233445566778899AABBCC + * Override serial number * buflen=N Default N=16384, buffer size used (will be * rounded down to a multiple of * PAGE_CACHE_SIZE) @@ -288,6 +290,8 @@ MODULE_LICENSE("Dual BSD/GPL"); #define DRIVER_VENDOR_ID 0x0525 // NetChip #define DRIVER_PRODUCT_ID 0xa4a5 // Linux-USB File-backed Storage Gadget +/* Serial number test string. */ +#define DRIVER_SERIAL_NUM_NOT_SET "Not set" /* * This driver assumes self-powered hardware and has no way for users to @@ -356,6 +360,7 @@ static struct { char *transport_parm; char *protocol_parm; + char *serial_parm; unsigned short vendor; unsigned short product; unsigned short release; @@ -369,6 +374,7 @@ static struct { } mod_data = { // Default values .transport_parm = "BBB", .protocol_parm = "SCSI", + .serial_parm = DRIVER_SERIAL_NUM_NOT_SET, .removable = 0, .can_stall = 1, .cdrom = 0, @@ -419,6 +425,9 @@ MODULE_PARM_DESC(product, "USB Product I module_param_named(release, mod_data.release, ushort, S_IRUGO); MODULE_PARM_DESC(release, "USB release number"); +module_param_named(serial, mod_data.serial_parm, charp, S_IRUGO); +MODULE_PARM_DESC(serial, "USB serial number"); + module_param_named(buflen, mod_data.buflen, uint, S_IRUGO); MODULE_PARM_DESC(buflen, "I/O buffer size"); @@ -996,8 +1005,10 @@ ep_desc(struct usb_gadget *g, struct usb /* The CBI specification limits the serial string to 12 uppercase hexadecimal * characters. */ +/* Others can handle more : Typically 12 uppercase hexadecimal *bytes* for + * usb sticks, ie 24 characters. */ static char manufacturer[64]; -static char serial[13]; +static char serial[25]; /* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */ static struct usb_string strings[] = { @@ -3853,11 +3864,11 @@ static void /* __init_or_exit */ fsg_unb set_gadget_data(gadget, NULL); } - static int __init check_parameters(struct fsg_dev *fsg) { int prot; int gcnum; + int i; /* Store the default values */ mod_data.transport_type = USB_PR_BULK; @@ -3937,6 +3948,41 @@ static int __init check_parameters(struc ERROR(fsg, "invalid buflen\n"); return -ETOOSMALL; } + + /* Serial string handling */ + memset(&serial, 0, sizeof(serial)); + if (strncmp(mod_data.serial_parm, DRIVER_SERIAL_NUM_NOT_SET, 10) == 0) { + /* Serial number not specified, make our own. */ + /* On a real device, serial[] would be loaded from permanent + * storage. We just encode it from the driver version string. + */ + for (i = 0; i < sizeof(serial) - 2; i += 2) { + unsigned char c = DRIVER_VERSION[i / 2]; + + if (!c) + break; + sprintf(&serial[i], "%02X", c); + } + } else { + int slength = min(sizeof(serial), strlen(mod_data.serial_parm)); + for (i = 0; i < slength; i += 1) { + unsigned char c = mod_data.serial_parm[i]; + if (!((c >= '0' && c <= '9') || + (c >= 'A' && c <= 'F'))) { + ERROR(fsg, "invalid serial string: %s\n", mod_data.serial_parm); + return -EINVAL; + } + sprintf(&serial[i], "%c", c); + } + } + + /* The CBI specification limits the serial string to 12 uppercase + * hexadecimal characters. */ + if (mod_data.transport_type == USB_PR_CBI && strlen(serial) > 12) { + WARNING(fsg, "Cutting the serial string to 12 characters (See CBI spec).\n"); + serial[12] = '\0'; + } + #endif /* CONFIG_USB_FILE_STORAGE_TEST */ return 0; @@ -4110,8 +4156,10 @@ static int __init fsg_bind(struct usb_ga init_utsname()->sysname, init_utsname()->release, gadget->name); + /* Serial string handling moved to __init check_parameters */ /* On a real device, serial[] would be loaded from permanent * storage. We just encode it from the driver version string. */ + /* for (i = 0; i < sizeof(serial) - 2; i += 2) { unsigned char c = DRIVER_VERSION[i / 2]; @@ -4119,6 +4167,7 @@ static int __init fsg_bind(struct usb_ga break; sprintf(&serial[i], "%02X", c); } + */ fsg->thread_task = kthread_create(fsg_main_thread, fsg, "file-storage-gadget"); -- Yann Cantin A4FEB47F -- -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html