ANDROID: usb: gadget: Accessory:Migrate to USB_FUNCTION API

This patch adds support to use Android accessory
gadget function through the
DECLARE_USB_FUNCTION_INIT interface.

Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
Change-Id: Ib352752d5bc905fa1df9049b53eabf1294930db7
tirimbino
Badhri Jagan Sridharan 10 years ago committed by Amit Pundir
parent 0e0ff4bb03
commit d5ae1986bd
  1. 12
      drivers/usb/gadget/Kconfig
  2. 3
      drivers/usb/gadget/Makefile
  3. 153
      drivers/usb/gadget/f_accessory.c

@ -224,6 +224,9 @@ config USB_F_PTP
config USB_F_AUDIO_SRC
tristate
config USB_F_ACC
tristate
# this first set of drivers all depend on bulk-capable hardware.
config USB_CONFIGFS
@ -391,9 +394,16 @@ config USB_CONFIGFS_F_PTP
help
USB gadget PTP support
config USB_CONFIGFS_F_ACC
boolean "Accessory gadget"
depends on USB_CONFIGFS
select USB_F_ACC
help
USB gadget Accessory support
config USB_CONFIGFS_F_AUDIO_SRC
boolean "Audio Source gadget"
depends on USB_CONFIGFS
depends on USB_CONFIGFS && USB_CONFIGFS_F_ACC
select USB_F_AUDIO_SRC
help
USB gadget Audio Source support

@ -9,4 +9,7 @@ obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o
libcomposite-y := usbstring.o config.o epautoconf.o
libcomposite-y += composite.o functions.o configfs.o u_f.o
usb_f_accessory-y := f_accessory.o
obj-$(CONFIG_USB_F_ACC) += usb_f_accessory.o
obj-$(CONFIG_USB_GADGET) += udc/ function/ legacy/

@ -39,6 +39,10 @@
#include <linux/usb/ch9.h>
#include <linux/usb/f_accessory.h>
#include <linux/configfs.h>
#include <linux/usb/composite.h>
#define MAX_INST_NAME_LEN 40
#define BULK_BUFFER_SIZE 16384
#define ACC_STRING_SIZE 256
@ -194,6 +198,11 @@ static struct usb_gadget_strings *acc_strings[] = {
/* temporary variable used between acc_open() and acc_gadget_bind() */
static struct acc_dev *_acc_dev;
struct acc_instance {
struct usb_function_instance func_inst;
const char *name;
};
static inline struct acc_dev *func_to_dev(struct usb_function *f)
{
return container_of(f, struct acc_dev, function);
@ -775,7 +784,7 @@ static struct hid_driver acc_hid_driver = {
.probe = acc_hid_probe,
};
static int acc_ctrlrequest(struct usb_composite_dev *cdev,
int acc_ctrlrequest(struct usb_composite_dev *cdev,
const struct usb_ctrlrequest *ctrl)
{
struct acc_dev *dev = _acc_dev;
@ -879,9 +888,11 @@ err:
w_value, w_index, w_length);
return value;
}
EXPORT_SYMBOL_GPL(acc_ctrlrequest);
static int
acc_function_bind(struct usb_configuration *c, struct usb_function *f)
__acc_function_bind(struct usb_configuration *c,
struct usb_function *f, bool configfs)
{
struct usb_composite_dev *cdev = c->cdev;
struct acc_dev *dev = func_to_dev(f);
@ -890,6 +901,16 @@ acc_function_bind(struct usb_configuration *c, struct usb_function *f)
DBG(cdev, "acc_function_bind dev: %p\n", dev);
if (configfs) {
if (acc_string_defs[INTERFACE_STRING_INDEX].id == 0) {
ret = usb_string_id(c->cdev);
if (ret < 0)
return ret;
acc_string_defs[INTERFACE_STRING_INDEX].id = ret;
acc_interface_desc.iInterface = ret;
}
dev->cdev = c->cdev;
}
ret = hid_register_driver(&acc_hid_driver);
if (ret)
return ret;
@ -922,6 +943,17 @@ acc_function_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
}
static int
acc_function_bind(struct usb_configuration *c, struct usb_function *f) {
return __acc_function_bind(c, f, false);
}
static int
acc_function_bind_configfs(struct usb_configuration *c,
struct usb_function *f) {
return __acc_function_bind(c, f, true);
}
static void
kill_all_hid_devices(struct acc_dev *dev)
{
@ -1179,11 +1211,12 @@ err:
return ret;
}
static void acc_disconnect(void)
void acc_disconnect(void)
{
/* unregister all HID devices if USB is disconnected */
kill_all_hid_devices(_acc_dev);
}
EXPORT_SYMBOL_GPL(acc_disconnect);
static void acc_cleanup(void)
{
@ -1191,3 +1224,117 @@ static void acc_cleanup(void)
kfree(_acc_dev);
_acc_dev = NULL;
}
static struct acc_instance *to_acc_instance(struct config_item *item)
{
return container_of(to_config_group(item), struct acc_instance,
func_inst.group);
}
static void acc_attr_release(struct config_item *item)
{
struct acc_instance *fi_acc = to_acc_instance(item);
usb_put_function_instance(&fi_acc->func_inst);
}
static struct configfs_item_operations acc_item_ops = {
.release = acc_attr_release,
};
static struct config_item_type acc_func_type = {
.ct_item_ops = &acc_item_ops,
.ct_owner = THIS_MODULE,
};
static struct acc_instance *to_fi_acc(struct usb_function_instance *fi)
{
return container_of(fi, struct acc_instance, func_inst);
}
static int acc_set_inst_name(struct usb_function_instance *fi, const char *name)
{
struct acc_instance *fi_acc;
char *ptr;
int name_len;
name_len = strlen(name) + 1;
if (name_len > MAX_INST_NAME_LEN)
return -ENAMETOOLONG;
ptr = kstrndup(name, name_len, GFP_KERNEL);
if (!ptr)
return -ENOMEM;
fi_acc = to_fi_acc(fi);
fi_acc->name = ptr;
return 0;
}
static void acc_free_inst(struct usb_function_instance *fi)
{
struct acc_instance *fi_acc;
fi_acc = to_fi_acc(fi);
kfree(fi_acc->name);
acc_cleanup();
}
static struct usb_function_instance *acc_alloc_inst(void)
{
struct acc_instance *fi_acc;
struct acc_dev *dev;
int err;
fi_acc = kzalloc(sizeof(*fi_acc), GFP_KERNEL);
if (!fi_acc)
return ERR_PTR(-ENOMEM);
fi_acc->func_inst.set_inst_name = acc_set_inst_name;
fi_acc->func_inst.free_func_inst = acc_free_inst;
err = acc_setup();
if (err) {
kfree(fi_acc);
pr_err("Error setting ACCESSORY\n");
return ERR_PTR(err);
}
config_group_init_type_name(&fi_acc->func_inst.group,
"", &acc_func_type);
dev = _acc_dev;
return &fi_acc->func_inst;
}
static void acc_free(struct usb_function *f)
{
/*NO-OP: no function specific resource allocation in mtp_alloc*/
}
int acc_ctrlrequest_configfs(struct usb_function *f,
const struct usb_ctrlrequest *ctrl) {
if (f->config != NULL && f->config->cdev != NULL)
return acc_ctrlrequest(f->config->cdev, ctrl);
else
return -1;
}
static struct usb_function *acc_alloc(struct usb_function_instance *fi)
{
struct acc_dev *dev = _acc_dev;
pr_info("acc_alloc\n");
dev->function.name = "accessory";
dev->function.strings = acc_strings,
dev->function.fs_descriptors = fs_acc_descs;
dev->function.hs_descriptors = hs_acc_descs;
dev->function.bind = acc_function_bind_configfs;
dev->function.unbind = acc_function_unbind;
dev->function.set_alt = acc_function_set_alt;
dev->function.disable = acc_function_disable;
dev->function.free_func = acc_free;
dev->function.setup = acc_ctrlrequest_configfs;
return &dev->function;
}
DECLARE_USB_FUNCTION_INIT(accessory, acc_alloc_inst, acc_alloc);
MODULE_LICENSE("GPL");

Loading…
Cancel
Save