aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/configfs-usb-gadget-ptp7
-rw-r--r--Documentation/usb/gadget-testing.txt25
-rw-r--r--drivers/usb/gadget/Kconfig14
-rw-r--r--drivers/usb/gadget/function/Makefile2
-rw-r--r--drivers/usb/gadget/function/f_mtp.c97
-rw-r--r--drivers/usb/gadget/function/f_mtp.h18
-rw-r--r--drivers/usb/gadget/function/f_ptp.c38
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");