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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html