Feature control mechanism allows addition of dynamic features to
gadgetfs.
It provides a user-mode driver the ability to control those features,
by querying the supported and enabled features and enable/disable
features in runtime via ioctl on ep0 fd.
---
drivers/usb/gadget/legacy/inode.c | 67
+++++++++++++++++++++++++++++++++++++--
include/uapi/linux/usb/gadgetfs.h | 29 +++++++++++++++++
2 files changed, 94 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/gadget/legacy/inode.c
b/drivers/usb/gadget/legacy/inode.c
index 16104b5e..f54200d 100644
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -144,6 +144,8 @@ struct dev_data {
wait_queue_head_t wait;
struct super_block *sb;
struct dentry *dentry;
+ struct usb_gadgetfs_features enabled_features;
+ struct usb_gadgetfs_features supported_features;
/* except this scratch i/o buffer for ep0 */
u8 rbuf [256];
@@ -1235,14 +1237,75 @@ out:
return mask;
}
+/* feature control */
+
+static bool
+is_feature_set(struct usb_gadgetfs_features * features, unsigned int
feature)
+{
+ uint64_t feature_bit;
+ /* overflow */
+ if(feature >= (sizeof(*features) * 8))
+ return false;
+ feature_bit = 1 << (feature % 64);
+ return (features->bitmap[feature / 64] & feature_bit) != 0;
+}
+
+/* clear a feature in a feature bitmap */
+static bool
+feature_clear(struct usb_gadgetfs_features * features, unsigned int
feature)
+{
+ uint64_t feature_bit;
+ /* overflow */
+ if(feature >= (sizeof(*features) * 8))
+ return false;
+ feature_bit = 1 << (feature % 64);
+ features->bitmap[feature / 64] &= ~feature_bit;
+ return true;
+}
+
+/* set a feature in a feature bitmap */
+static bool
+feature_set(struct usb_gadgetfs_features * features, unsigned int feature)
+{
+ uint64_t feature_bit;
+ /* overflow */
+ if(feature >= (sizeof(*features) * 8))
+ return false;
+ feature_bit = 1 << (feature % 64);
+ features->bitmap[feature / 64] |= feature_bit;
+ return true;
+}
+
static long dev_ioctl (struct file *fd, unsigned code, unsigned long value)
{
struct dev_data *dev = fd->private_data;
struct usb_gadget *gadget = dev->gadget;
long ret = -ENOTTY;
- if (gadget->ops->ioctl)
- ret = gadget->ops->ioctl (gadget, code, value);
+ switch(code) {
+ case GADGETFS_GET_SUPPORTED_FEATURES:
+ ret = copy_to_user((void*)value, &dev->supported_features,
+ sizeof(dev->supported_features));
+ if (ret != 0)
+ ret = -EFAULT;
+ break;
+ case GADGETFS_GET_ENABLED_FEATURES:
+ ret = copy_to_user((void*)value, &dev->enabled_features,
+ sizeof(dev->enabled_features));
+ if (ret != 0)
+ ret = -EFAULT;
+ break;
+ case GADGETFS_SET_ENABLED_FEATURES:
+ ret = copy_from_user(&dev->enabled_features, (void*)value,
+ sizeof(dev->enabled_features));
+ if (ret != 0)
+ ret = -EFAULT;
+ break;
+ default:
+ if (gadget && gadget->ops && gadget->ops->ioctl)
+ ret = gadget->ops->ioctl (gadget, code, value);
+ break;
+ }
return ret;
}
diff --git a/include/uapi/linux/usb/gadgetfs.h
b/include/uapi/linux/usb/gadgetfs.h
index 0bb12e0..9d304e0 100644
--- a/include/uapi/linux/usb/gadgetfs.h
+++ b/include/uapi/linux/usb/gadgetfs.h
@@ -85,4 +85,33 @@ struct usb_gadgetfs_event {
*/
#define GADGETFS_CLEAR_HALT _IO('g', 3)
+
+
+struct usb_gadgetfs_features {
+ uint64_t bitmap[4];
+};
+
+
+/* device ioctls */
+
+/*
+ * Those IOCTLs are called on the control endpoint fd.
+ */
+
+/*
+ * Returns the supported features bitmap
+ */
+#define GADGETFS_GET_SUPPORTED_FEATURES _IOW('g', 0x10, \
+ struct usb_gadgetfs_features)
+
+/*
+ * Returns enabled features as a bitmap
+ */
+#define GADGETFS_GET_ENABLED_FEATURES _IOW('g', 0x11, \
+ struct usb_gadgetfs_features)
+
+/* sets the enabled features bitmap */
+#define GADGETFS_SET_ENABLED_FEATURES _IOR('g', 0x12, \
+ struct usb_gadgetfs_features)
+
#endif /* __LINUX_USB_GADGETFS_H */
--
2.5.0
--
Binyamin Sharet,
Cisco, STARE-C
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html