usb: gadget: Add per-lun inquiry string

Introduce an attribute "inquiry_string" to the lun.

In some environments, e. g. BIOS boot menus, the inquiry string
is the only information about devices presented to the user. The
default string depends on the "cdrom" bit of the first lun as
well as the kernel version and allows no further customization.
So without access to the client it is not obvious which gadget is
active at a given point and what any of the available luns might
contain.

If "inquiry_string" is ignored or set to the empty string, the
old behavior is preserved.

Signed-off-by: Philipp Gesang <philipp.gesang@intra2net.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
This commit is contained in:
Philipp Gesang 2016-08-01 17:04:19 +02:00 committed by Felipe Balbi
parent f652191be3
commit 6ac47090ee
4 changed files with 57 additions and 6 deletions

View File

@ -311,11 +311,7 @@ struct fsg_common {
/* Gadget's private data. */ /* Gadget's private data. */
void *private_data; void *private_data;
/* char inquiry_string[INQUIRY_STRING_LEN];
* Vendor (8 chars), product (16 chars), release (4
* hexadecimal digits) and NUL byte
*/
char inquiry_string[8 + 16 + 4 + 1];
struct kref ref; struct kref ref;
}; };
@ -1107,7 +1103,12 @@ static int do_inquiry(struct fsg_common *common, struct fsg_buffhd *bh)
buf[5] = 0; /* No special options */ buf[5] = 0; /* No special options */
buf[6] = 0; buf[6] = 0;
buf[7] = 0; buf[7] = 0;
memcpy(buf + 8, common->inquiry_string, sizeof common->inquiry_string); if (curlun->inquiry_string[0])
memcpy(buf + 8, curlun->inquiry_string,
sizeof(curlun->inquiry_string));
else
memcpy(buf + 8, common->inquiry_string,
sizeof(common->inquiry_string));
return 36; return 36;
} }
@ -3209,12 +3210,27 @@ static ssize_t fsg_lun_opts_nofua_store(struct config_item *item,
CONFIGFS_ATTR(fsg_lun_opts_, nofua); CONFIGFS_ATTR(fsg_lun_opts_, nofua);
static ssize_t fsg_lun_opts_inquiry_string_show(struct config_item *item,
char *page)
{
return fsg_show_inquiry_string(to_fsg_lun_opts(item)->lun, page);
}
static ssize_t fsg_lun_opts_inquiry_string_store(struct config_item *item,
const char *page, size_t len)
{
return fsg_store_inquiry_string(to_fsg_lun_opts(item)->lun, page, len);
}
CONFIGFS_ATTR(fsg_lun_opts_, inquiry_string);
static struct configfs_attribute *fsg_lun_attrs[] = { static struct configfs_attribute *fsg_lun_attrs[] = {
&fsg_lun_opts_attr_file, &fsg_lun_opts_attr_file,
&fsg_lun_opts_attr_ro, &fsg_lun_opts_attr_ro,
&fsg_lun_opts_attr_removable, &fsg_lun_opts_attr_removable,
&fsg_lun_opts_attr_cdrom, &fsg_lun_opts_attr_cdrom,
&fsg_lun_opts_attr_nofua, &fsg_lun_opts_attr_nofua,
&fsg_lun_opts_attr_inquiry_string,
NULL, NULL,
}; };

View File

@ -100,6 +100,7 @@ struct fsg_lun_config {
char removable; char removable;
char cdrom; char cdrom;
char nofua; char nofua;
char inquiry_string[INQUIRY_STRING_LEN];
}; };
struct fsg_config { struct fsg_config {

View File

@ -369,6 +369,12 @@ ssize_t fsg_show_removable(struct fsg_lun *curlun, char *buf)
} }
EXPORT_SYMBOL_GPL(fsg_show_removable); EXPORT_SYMBOL_GPL(fsg_show_removable);
ssize_t fsg_show_inquiry_string(struct fsg_lun *curlun, char *buf)
{
return sprintf(buf, "%s\n", curlun->inquiry_string);
}
EXPORT_SYMBOL_GPL(fsg_show_inquiry_string);
/* /*
* The caller must hold fsg->filesem for reading when calling this function. * The caller must hold fsg->filesem for reading when calling this function.
*/ */
@ -499,4 +505,22 @@ ssize_t fsg_store_removable(struct fsg_lun *curlun, const char *buf,
} }
EXPORT_SYMBOL_GPL(fsg_store_removable); EXPORT_SYMBOL_GPL(fsg_store_removable);
ssize_t fsg_store_inquiry_string(struct fsg_lun *curlun, const char *buf,
size_t count)
{
const size_t len = min(count, sizeof(curlun->inquiry_string));
if (len == 0 || buf[0] == '\n') {
curlun->inquiry_string[0] = 0;
} else {
snprintf(curlun->inquiry_string,
sizeof(curlun->inquiry_string), "%-28s", buf);
if (curlun->inquiry_string[len-1] == '\n')
curlun->inquiry_string[len-1] = ' ';
}
return count;
}
EXPORT_SYMBOL_GPL(fsg_store_inquiry_string);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -88,6 +88,12 @@ do { \
#define ASC(x) ((u8) ((x) >> 8)) #define ASC(x) ((u8) ((x) >> 8))
#define ASCQ(x) ((u8) (x)) #define ASCQ(x) ((u8) (x))
/*
* Vendor (8 chars), product (16 chars), release (4 hexadecimal digits) and NUL
* byte
*/
#define INQUIRY_STRING_LEN ((size_t) (8 + 16 + 4 + 1))
struct fsg_lun { struct fsg_lun {
struct file *filp; struct file *filp;
loff_t file_length; loff_t file_length;
@ -112,6 +118,7 @@ struct fsg_lun {
struct device dev; struct device dev;
const char *name; /* "lun.name" */ const char *name; /* "lun.name" */
const char **name_pfx; /* "function.name" */ const char **name_pfx; /* "function.name" */
char inquiry_string[INQUIRY_STRING_LEN];
}; };
static inline bool fsg_lun_is_open(struct fsg_lun *curlun) static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
@ -210,6 +217,7 @@ ssize_t fsg_show_ro(struct fsg_lun *curlun, char *buf);
ssize_t fsg_show_nofua(struct fsg_lun *curlun, char *buf); ssize_t fsg_show_nofua(struct fsg_lun *curlun, char *buf);
ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem, ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
char *buf); char *buf);
ssize_t fsg_show_inquiry_string(struct fsg_lun *curlun, char *buf);
ssize_t fsg_show_cdrom(struct fsg_lun *curlun, char *buf); ssize_t fsg_show_cdrom(struct fsg_lun *curlun, char *buf);
ssize_t fsg_show_removable(struct fsg_lun *curlun, char *buf); ssize_t fsg_show_removable(struct fsg_lun *curlun, char *buf);
ssize_t fsg_store_ro(struct fsg_lun *curlun, struct rw_semaphore *filesem, ssize_t fsg_store_ro(struct fsg_lun *curlun, struct rw_semaphore *filesem,
@ -221,5 +229,7 @@ ssize_t fsg_store_cdrom(struct fsg_lun *curlun, struct rw_semaphore *filesem,
const char *buf, size_t count); const char *buf, size_t count);
ssize_t fsg_store_removable(struct fsg_lun *curlun, const char *buf, ssize_t fsg_store_removable(struct fsg_lun *curlun, const char *buf,
size_t count); size_t count);
ssize_t fsg_store_inquiry_string(struct fsg_lun *curlun, const char *buf,
size_t count);
#endif /* USB_STORAGE_COMMON_H */ #endif /* USB_STORAGE_COMMON_H */