diff options
author | Yann Cantin <yann.cantin@laposte.net> | 2010-06-05 17:06:31 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-10 17:35:35 -0400 |
commit | 87eb1bead832b9880126fdbea74cc8ecb22b50c0 (patch) | |
tree | bce02f58b229e786a2268abc75b502a564e7b18d /drivers/usb/gadget | |
parent | 83a3ac866d6931611d37ded24a2a2cc99fe36e9f (diff) |
USB: Add a serial number parameter to g_file_storage module
This patch add a serial number parameter to the g_file_storage
module. There's validity checks against the string passed to comply
with the specs.
Signed-off-by: Yann Cantin <yann.cantin@laposte.net>
Cc: MichaĆ Nazarewicz <m.nazarewicz@samsung.com>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r-- | drivers/usb/gadget/file_storage.c | 69 |
1 files changed, 58 insertions, 11 deletions
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index b49d86e3e45b..2b6d3649d02c 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c | |||
@@ -56,7 +56,7 @@ | |||
56 | * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03), | 56 | * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03), |
57 | * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by | 57 | * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by |
58 | * the optional "protocol" module parameter. In addition, the default | 58 | * the optional "protocol" module parameter. In addition, the default |
59 | * Vendor ID, Product ID, and release number can be overridden. | 59 | * Vendor ID, Product ID, release number and serial number can be overridden. |
60 | * | 60 | * |
61 | * There is support for multiple logical units (LUNs), each of which has | 61 | * There is support for multiple logical units (LUNs), each of which has |
62 | * its own backing file. The number of LUNs can be set using the optional | 62 | * its own backing file. The number of LUNs can be set using the optional |
@@ -106,6 +106,7 @@ | |||
106 | * vendor=0xVVVV Default 0x0525 (NetChip), USB Vendor ID | 106 | * vendor=0xVVVV Default 0x0525 (NetChip), USB Vendor ID |
107 | * product=0xPPPP Default 0xa4a5 (FSG), USB Product ID | 107 | * product=0xPPPP Default 0xa4a5 (FSG), USB Product ID |
108 | * release=0xRRRR Override the USB release number (bcdDevice) | 108 | * release=0xRRRR Override the USB release number (bcdDevice) |
109 | * serial=HHHH... Override serial number (string of hex chars) | ||
109 | * buflen=N Default N=16384, buffer size used (will be | 110 | * buflen=N Default N=16384, buffer size used (will be |
110 | * rounded down to a multiple of | 111 | * rounded down to a multiple of |
111 | * PAGE_CACHE_SIZE) | 112 | * PAGE_CACHE_SIZE) |
@@ -270,6 +271,8 @@ | |||
270 | 271 | ||
271 | #define DRIVER_DESC "File-backed Storage Gadget" | 272 | #define DRIVER_DESC "File-backed Storage Gadget" |
272 | #define DRIVER_NAME "g_file_storage" | 273 | #define DRIVER_NAME "g_file_storage" |
274 | /* DRIVER_VERSION must be at least 6 characters long, as it is used | ||
275 | * to generate a fallback serial number. */ | ||
273 | #define DRIVER_VERSION "20 November 2008" | 276 | #define DRIVER_VERSION "20 November 2008" |
274 | 277 | ||
275 | static char fsg_string_manufacturer[64]; | 278 | static char fsg_string_manufacturer[64]; |
@@ -314,6 +317,7 @@ static struct { | |||
314 | unsigned short vendor; | 317 | unsigned short vendor; |
315 | unsigned short product; | 318 | unsigned short product; |
316 | unsigned short release; | 319 | unsigned short release; |
320 | char *serial_parm; | ||
317 | unsigned int buflen; | 321 | unsigned int buflen; |
318 | 322 | ||
319 | int transport_type; | 323 | int transport_type; |
@@ -374,6 +378,9 @@ MODULE_PARM_DESC(product, "USB Product ID"); | |||
374 | module_param_named(release, mod_data.release, ushort, S_IRUGO); | 378 | module_param_named(release, mod_data.release, ushort, S_IRUGO); |
375 | MODULE_PARM_DESC(release, "USB release number"); | 379 | MODULE_PARM_DESC(release, "USB release number"); |
376 | 380 | ||
381 | module_param_named(serial, mod_data.serial_parm, charp, S_IRUGO); | ||
382 | MODULE_PARM_DESC(serial, "USB serial number"); | ||
383 | |||
377 | module_param_named(buflen, mod_data.buflen, uint, S_IRUGO); | 384 | module_param_named(buflen, mod_data.buflen, uint, S_IRUGO); |
378 | MODULE_PARM_DESC(buflen, "I/O buffer size"); | 385 | MODULE_PARM_DESC(buflen, "I/O buffer size"); |
379 | 386 | ||
@@ -3197,6 +3204,7 @@ static int __init check_parameters(struct fsg_dev *fsg) | |||
3197 | { | 3204 | { |
3198 | int prot; | 3205 | int prot; |
3199 | int gcnum; | 3206 | int gcnum; |
3207 | int i; | ||
3200 | 3208 | ||
3201 | /* Store the default values */ | 3209 | /* Store the default values */ |
3202 | mod_data.transport_type = USB_PR_BULK; | 3210 | mod_data.transport_type = USB_PR_BULK; |
@@ -3272,6 +3280,55 @@ static int __init check_parameters(struct fsg_dev *fsg) | |||
3272 | ERROR(fsg, "invalid buflen\n"); | 3280 | ERROR(fsg, "invalid buflen\n"); |
3273 | return -ETOOSMALL; | 3281 | return -ETOOSMALL; |
3274 | } | 3282 | } |
3283 | |||
3284 | /* Serial string handling. | ||
3285 | * On a real device, the serial string would be loaded | ||
3286 | * from permanent storage. */ | ||
3287 | if (mod_data.serial_parm) { | ||
3288 | const char *ch; | ||
3289 | unsigned len = 0; | ||
3290 | |||
3291 | /* Sanity check : | ||
3292 | * The CB[I] specification limits the serial string to | ||
3293 | * 12 uppercase hexadecimal characters. | ||
3294 | * BBB need at least 12 uppercase hexadecimal characters, | ||
3295 | * with a maximum of 126. */ | ||
3296 | for (ch = mod_data.serial_parm; *ch; ++ch) { | ||
3297 | ++len; | ||
3298 | if ((*ch < '0' || *ch > '9') && | ||
3299 | (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */ | ||
3300 | WARNING(fsg, | ||
3301 | "Invalid serial string character: %c; " | ||
3302 | "Failing back to default\n", | ||
3303 | *ch); | ||
3304 | goto fill_serial; | ||
3305 | } | ||
3306 | } | ||
3307 | if (len > 126 || | ||
3308 | (mod_data.transport_type == USB_PR_BULK && len < 12) || | ||
3309 | (mod_data.transport_type != USB_PR_BULK && len > 12)) { | ||
3310 | WARNING(fsg, | ||
3311 | "Invalid serial string length; " | ||
3312 | "Failing back to default\n"); | ||
3313 | goto fill_serial; | ||
3314 | } | ||
3315 | fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial_parm; | ||
3316 | } else { | ||
3317 | fill_serial: | ||
3318 | /* Serial number not specified or invalid, make our own. | ||
3319 | * We just encode it from the driver version string, | ||
3320 | * 12 characters to comply with both CB[I] and BBB spec. | ||
3321 | * Warning : Two devices running the same kernel will have | ||
3322 | * the same fallback serial number. */ | ||
3323 | for (i = 0; i < 12; i += 2) { | ||
3324 | unsigned char c = DRIVER_VERSION[i / 2]; | ||
3325 | |||
3326 | if (!c) | ||
3327 | break; | ||
3328 | sprintf(&fsg_string_serial[i], "%02X", c); | ||
3329 | } | ||
3330 | } | ||
3331 | |||
3275 | #endif /* CONFIG_USB_FILE_STORAGE_TEST */ | 3332 | #endif /* CONFIG_USB_FILE_STORAGE_TEST */ |
3276 | 3333 | ||
3277 | return 0; | 3334 | return 0; |
@@ -3447,16 +3504,6 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
3447 | init_utsname()->sysname, init_utsname()->release, | 3504 | init_utsname()->sysname, init_utsname()->release, |
3448 | gadget->name); | 3505 | gadget->name); |
3449 | 3506 | ||
3450 | /* On a real device, serial[] would be loaded from permanent | ||
3451 | * storage. We just encode it from the driver version string. */ | ||
3452 | for (i = 0; i < sizeof fsg_string_serial - 2; i += 2) { | ||
3453 | unsigned char c = DRIVER_VERSION[i / 2]; | ||
3454 | |||
3455 | if (!c) | ||
3456 | break; | ||
3457 | sprintf(&fsg_string_serial[i], "%02X", c); | ||
3458 | } | ||
3459 | |||
3460 | fsg->thread_task = kthread_create(fsg_main_thread, fsg, | 3507 | fsg->thread_task = kthread_create(fsg_main_thread, fsg, |
3461 | "file-storage-gadget"); | 3508 | "file-storage-gadget"); |
3462 | if (IS_ERR(fsg->thread_task)) { | 3509 | if (IS_ERR(fsg->thread_task)) { |