diff options
-rw-r--r-- | Documentation/ABI/testing/configfs-usb-gadget-ptp | 7 | ||||
-rw-r--r-- | Documentation/usb/gadget-testing.txt | 25 | ||||
-rw-r--r-- | drivers/usb/gadget/Kconfig | 14 | ||||
-rw-r--r-- | drivers/usb/gadget/function/Makefile | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/function/f_mtp.c | 97 | ||||
-rw-r--r-- | drivers/usb/gadget/function/f_mtp.h | 18 | ||||
-rw-r--r-- | drivers/usb/gadget/function/f_ptp.c | 38 |
7 files changed, 189 insertions, 12 deletions
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-ptp b/Documentation/ABI/testing/configfs-usb-gadget-ptp new file mode 100644 index 0000000..9ae9be5 --- /dev/null +++ b/Documentation/ABI/testing/configfs-usb-gadget-ptp @@ -0,0 +1,7 @@ +What: /config/usb-gadget/gadget/functions/ptp.name +Date: Apr 2016 +KernelVersion: 4.6 +Description: The purpose of this directory is to create and remove it. + + A corresponding USB function instance is created/removed. + There are no attributes here. diff --git a/Documentation/usb/gadget-testing.txt b/Documentation/usb/gadget-testing.txt index 9c39253..d101c42 100644 --- a/Documentation/usb/gadget-testing.txt +++ b/Documentation/usb/gadget-testing.txt @@ -21,6 +21,7 @@ provided by gadgets. 18. UVC function 19. PRINTER function 20. MTP function +21. PTP function 1. ACM function @@ -794,3 +795,27 @@ On the device: enable the gadget, and start the mtp userspace daemon. On the host: if configured correctly the media storage device should auto-mount itself, or use Linux mtp-tools package to browse/transfer the media content instead. + +21. PTP function +=============== + +The function is provided by usb_f_ptp.ko module. + +Function-specific configfs interface +------------------------------------ + +The function name to use when creating the function directory is "ptp". +The function directory is intentionally empty and has no attributes as such. + +This ptp function piggybacks on mtp function so make sure we have created mtp +function before we create ptp function directory. After creating the ptp +function directory, link ptp function with the gadget configuration by creating +symbolic link, enable the gadget by writing a suitable string to +usb_gadget/<gadget>/UDC and start the ptp userspace daemon. + +Testing the ptp function +------------------------ + +On the device: enable the gadget, and start the ptp userspace daemon. +On the host: if configured correctly the photo storage device should auto-mount +itself. diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 5acf0a5..e2a50a9 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -212,6 +212,9 @@ config USB_F_TCM config USB_F_MTP tristate +config USB_F_PTP + tristate + choice tristate "USB Gadget Drivers" default USB_ETH @@ -488,6 +491,17 @@ config USB_CONFIGFS_F_MTP the file level. Thus exposing the relevant content but hiding the system/restricted files. +config USB_CONFIGFS_F_PTP + bool "PTP gadget" + depends on USB_CONFIGFS + depends on USB_CONFIGFS_F_MTP + select USB_F_PTP + help + The Picture Transfer Protocol (PTP) function mounts USB gadget + as a camera gadget to allow transfer of images from Host to + Device and vice-versa. This PTP implementation piggybacks on MTP + function. + source "drivers/usb/gadget/legacy/Kconfig" endchoice diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile index 6089a0f..aea641d 100644 --- a/drivers/usb/gadget/function/Makefile +++ b/drivers/usb/gadget/function/Makefile @@ -48,3 +48,5 @@ usb_f_tcm-y := f_tcm.o obj-$(CONFIG_USB_F_TCM) += usb_f_tcm.o usb_f_mtp-y := f_mtp.o obj-$(CONFIG_USB_F_MTP) += usb_f_mtp.o +usb_f_ptp-y := f_ptp.o +obj-$(CONFIG_USB_F_PTP) += usb_f_ptp.o diff --git a/drivers/usb/gadget/function/f_mtp.c b/drivers/usb/gadget/function/f_mtp.c index 4e04c84..6930f8a 100644 --- a/drivers/usb/gadget/function/f_mtp.c +++ b/drivers/usb/gadget/function/f_mtp.c @@ -125,6 +125,16 @@ static struct usb_interface_descriptor mtp_interface_desc = { .bInterfaceProtocol = 0, }; +static struct usb_interface_descriptor ptp_interface_desc = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bNumEndpoints = 3, + .bInterfaceClass = USB_CLASS_STILL_IMAGE, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 1, +}; + static struct usb_endpoint_descriptor mtp_ss_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -225,6 +235,33 @@ static struct usb_descriptor_header *ss_mtp_descs[] = { NULL, }; +static struct usb_descriptor_header *fs_ptp_descs[] = { + (struct usb_descriptor_header *) &ptp_interface_desc, + (struct usb_descriptor_header *) &mtp_fullspeed_in_desc, + (struct usb_descriptor_header *) &mtp_fullspeed_out_desc, + (struct usb_descriptor_header *) &mtp_intr_desc, + NULL, +}; + +static struct usb_descriptor_header *hs_ptp_descs[] = { + (struct usb_descriptor_header *) &ptp_interface_desc, + (struct usb_descriptor_header *) &mtp_highspeed_in_desc, + (struct usb_descriptor_header *) &mtp_highspeed_out_desc, + (struct usb_descriptor_header *) &mtp_intr_desc, + NULL, +}; + +static struct usb_descriptor_header *ss_ptp_descs[] = { + (struct usb_descriptor_header *) &ptp_interface_desc, + (struct usb_descriptor_header *) &mtp_ss_in_desc, + (struct usb_descriptor_header *) &mtp_ss_in_comp_desc, + (struct usb_descriptor_header *) &mtp_ss_out_desc, + (struct usb_descriptor_header *) &mtp_ss_out_comp_desc, + (struct usb_descriptor_header *) &mtp_intr_desc, + (struct usb_descriptor_header *) &mtp_intr_ss_comp_desc, + NULL, +}; + static struct usb_string mtp_string_defs[] = { /* Naming interface "MTP" so libmtp will recognize us */ [INTERFACE_STRING_INDEX].s = "MTP", @@ -1383,7 +1420,7 @@ static void mtp_free_inst(struct usb_function_instance *fi) kfree(fi_mtp); } -static struct usb_function_instance *mtp_alloc_inst(void) +struct usb_function_instance *alloc_inst_mtp_ptp(bool mtp_config) { struct mtp_instance *fi_mtp; int ret = 0; @@ -1401,12 +1438,15 @@ static struct usb_function_instance *mtp_alloc_inst(void) descs[0] = &fi_mtp->mtp_os_desc; names[0] = "MTP"; - ret = mtp_setup(fi_mtp); - if (ret) { - kfree(fi_mtp); - pr_err("Error setting MTP\n"); - return ERR_PTR(ret); - } + if (mtp_config) { + ret = mtp_setup(fi_mtp); + if (ret) { + kfree(fi_mtp); + pr_err("Error setting MTP\n"); + return ERR_PTR(ret); + } + } else + fi_mtp->dev = _mtp_dev; config_group_init_type_name(&fi_mtp->func_inst.group, "", &mtp_func_type); @@ -1415,6 +1455,12 @@ static struct usb_function_instance *mtp_alloc_inst(void) return &fi_mtp->func_inst; } +EXPORT_SYMBOL_GPL(alloc_inst_mtp_ptp); + +static struct usb_function_instance *mtp_alloc_inst(void) +{ + return alloc_inst_mtp_ptp(true); +} static int mtp_ctrlreq_configfs(struct usb_function *f, const struct usb_ctrlrequest *ctrl) @@ -1427,16 +1473,37 @@ static void mtp_free(struct usb_function *f) /*NO-OP: no function specific resource allocation in mtp_alloc*/ } -static struct usb_function *mtp_alloc(struct usb_function_instance *fi) +struct usb_function *function_alloc_mtp_ptp(struct usb_function_instance *fi, + bool mtp_config) { struct mtp_instance *fi_mtp = to_fi_mtp(fi); - struct mtp_dev *dev = fi_mtp->dev; + struct mtp_dev *dev; + + /* + * PTP piggybacks on MTP function so make sure we have + * created MTP function before we associate this PTP + * function with a gadget configuration. + */ + if (fi_mtp->dev == NULL) { + pr_err("Error: Create MTP func before linking PTP func\n"); + pr_err("\t1: Delete existing PTP function if any\n"); + pr_err("\t2: Create MTP function\n"); + pr_err("\t3: Create & symlink PTP func with a gadget config\n"); + return ERR_PTR(-EINVAL); /* Invalid Configuration */ + } + dev = fi_mtp->dev; dev->function.name = DRIVER_NAME; dev->function.strings = mtp_strings; - dev->function.fs_descriptors = fs_mtp_descs; - dev->function.hs_descriptors = hs_mtp_descs; - dev->function.ss_descriptors = ss_mtp_descs; + if (mtp_config) { + dev->function.fs_descriptors = fs_mtp_descs; + dev->function.hs_descriptors = hs_mtp_descs; + dev->function.ss_descriptors = ss_mtp_descs; + } else { + dev->function.fs_descriptors = fs_ptp_descs; + dev->function.hs_descriptors = hs_ptp_descs; + dev->function.ss_descriptors = ss_ptp_descs; + } dev->function.bind = mtp_function_bind; dev->function.unbind = mtp_function_unbind; dev->function.set_alt = mtp_function_set_alt; @@ -1446,6 +1513,12 @@ static struct usb_function *mtp_alloc(struct usb_function_instance *fi) return &dev->function; } +EXPORT_SYMBOL_GPL(function_alloc_mtp_ptp); + +static struct usb_function *mtp_alloc(struct usb_function_instance *fi) +{ + return function_alloc_mtp_ptp(fi, true); +} DECLARE_USB_FUNCTION_INIT(mtp, mtp_alloc_inst, mtp_alloc); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/function/f_mtp.h b/drivers/usb/gadget/function/f_mtp.h new file mode 100644 index 0000000..7adb1ff --- /dev/null +++ b/drivers/usb/gadget/function/f_mtp.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2014 Google, Inc. + * Author: Badhri Jagan Sridharan <badhri@android.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +extern struct usb_function_instance *alloc_inst_mtp_ptp(bool mtp_config); +extern struct usb_function *function_alloc_mtp_ptp( + struct usb_function_instance *fi, bool mtp_config); diff --git a/drivers/usb/gadget/function/f_ptp.c b/drivers/usb/gadget/function/f_ptp.c new file mode 100644 index 0000000..da3e4d5 --- /dev/null +++ b/drivers/usb/gadget/function/f_ptp.c @@ -0,0 +1,38 @@ +/* + * Gadget Function Driver for PTP + * + * Copyright (C) 2014 Google, Inc. + * Author: Badhri Jagan Sridharan <badhri@android.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/module.h> +#include <linux/types.h> + +#include <linux/configfs.h> +#include <linux/usb/composite.h> + +#include "f_mtp.h" + +static struct usb_function_instance *ptp_alloc_inst(void) +{ + return alloc_inst_mtp_ptp(false); +} + +static struct usb_function *ptp_alloc(struct usb_function_instance *fi) +{ + return function_alloc_mtp_ptp(fi, false); +} + +DECLARE_USB_FUNCTION_INIT(ptp, ptp_alloc_inst, ptp_alloc); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Badhri Jagan Sridharan"); |