aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmit Pundir <amit.pundir@linaro.org>2016-04-28 20:04:20 +0530
committerWolfgang Wiedmeyer <wolfgit@wiedmeyer.de>2016-09-27 02:50:40 +0200
commit8aaa1f0300049fc987e5968cc91fb6bdd8ea444c (patch)
treedd48717f1eb26c50b9ff4c60a71c7b4276027f65
parent26af6d79b253dabe34bd88f05a0736214b1d6826 (diff)
downloadkernel_i9300_mainline-8aaa1f0300049fc987e5968cc91fb6bdd8ea444c.zip
kernel_i9300_mainline-8aaa1f0300049fc987e5968cc91fb6bdd8ea444c.tar.gz
kernel_i9300_mainline-8aaa1f0300049fc987e5968cc91fb6bdd8ea444c.tar.bz2
ANDROID: usb: gadget: configfs: add PTP function
This PTP function is based on the MTP+PTP work originally done in the Android kernel tree. This PTP implementation piggybacks on MTP function so make sure we have created MTP function before we associate this PTP function with a gadget configuration. Signed-off-by: Amit Pundir <amit.pundir@linaro.org> Signed-off-by: John Stultz <john.stultz@linaro.org>
-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");