You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2023/09/16 06:40:15 UTC
[nuttx] branch master updated: usbdev/mtp: support mtp class driver
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 8ababfc310 usbdev/mtp: support mtp class driver
8ababfc310 is described below
commit 8ababfc3103fd6f65fc2cb09b0c154fde1a4e687
Author: dongjiuzhu1 <do...@xiaomi.com>
AuthorDate: Tue Jul 11 22:03:01 2023 +0800
usbdev/mtp: support mtp class driver
Signed-off-by: dongjiuzhu1 <do...@xiaomi.com>
---
boards/sim/sim/sim/src/sim_bringup.c | 5 +
drivers/usbdev/Kconfig | 153 ++++++++++++
drivers/usbdev/Make.defs | 4 +
drivers/usbdev/mtp.c | 467 +++++++++++++++++++++++++++++++++++
include/nuttx/usb/mtp.h | 89 +++++++
5 files changed, 718 insertions(+)
diff --git a/boards/sim/sim/sim/src/sim_bringup.c b/boards/sim/sim/sim/src/sim_bringup.c
index b7c1343546..4d85affd9c 100644
--- a/boards/sim/sim/sim/src/sim_bringup.c
+++ b/boards/sim/sim/sim/src/sim_bringup.c
@@ -54,6 +54,7 @@
#include <nuttx/wireless/bluetooth/bt_uart_shim.h>
#include <nuttx/wireless/ieee802154/ieee802154_loopback.h>
#include <nuttx/usb/adb.h>
+#include <nuttx/usb/mtp.h>
#include <nuttx/usb/rndis.h>
#ifdef CONFIG_LCD_DEV
@@ -506,6 +507,10 @@ int sim_bringup(void)
usbdev_adb_initialize();
#endif
+#if defined(CONFIG_USBMTP) && !defined(CONFIG_USBMTP_COMPOSITE)
+ usbdev_mtp_initialize();
+#endif
+
#if defined(CONFIG_RNDIS) && !defined(CONFIG_RNDIS_COMPOSITE)
/* Set up a MAC address for the RNDIS device. */
diff --git a/drivers/usbdev/Kconfig b/drivers/usbdev/Kconfig
index ae238e5a54..7863063c0d 100644
--- a/drivers/usbdev/Kconfig
+++ b/drivers/usbdev/Kconfig
@@ -1234,4 +1234,157 @@ config USBDEV_FS_NPOLLWAITERS
endif #USBDEV_FS
+menuconfig USBMTP
+ bool "USB Media Transfer Protocol (MTP) support"
+ default n
+ select USBDEV_FS
+ ---help---
+ Enables USB Media Transfer Protocol (MTP) support
+
+if USBMTP
+
+menuconfig USBMTP_COMPOSITE
+ bool "USBMTP composite support"
+ default n
+ depends on USBDEV_COMPOSITE
+ ---help---
+ Configure the MTP driver as part of a composite driver
+ (only if USBDEV_COMPOSITE is also defined)
+
+if !USBMTP_COMPOSITE
+
+# In a composite device the EP0 config comes from the composite device
+# and the EP-Number is configured dynamically via composite_initialize
+
+config USBMTP_EP0MAXPACKET
+ int "Endpoint 0 max packet size"
+ default 64
+ ---help---
+ Endpoint 0 max packet size. Default 64.
+
+# In a composite device the EP-Numbers are configured dynamically via
+# composite_initialize
+
+config USBMTP_EPBULKIN
+ int "Bulk IN endpoint number"
+ default 1
+ ---help---
+ The logical 7-bit address of a hardware endpoint that supports
+ bulk IN operation. Default: 1
+
+config USBMTP_EPBULKOUT
+ int "Bulk OUT endpoint number"
+ default 2
+ ---help---
+ The logical 7-bit address of a hardware endpoint that supports
+ bulk OUT operation. Default: 2
+
+config USBMTP_EPINTIN
+ int "Interrupt IN endpoint number"
+ default 5
+ ---help---
+ The logical 7-bit address of a hardware endpoint that supports
+ interrupt IN operation. Default: 5
+
+endif
+
+config USBMTP_EPBULKOUT_FSSIZE
+ int "Bulk OUT Full Speed MAXPACKET size"
+ default 64
+ ---help---
+ Max package size for the bulk OUT endpoint if Full Speed mode.
+ Default 64.
+
+if USBDEV_DUALSPEED
+
+config USBMTP_EPBULKOUT_HSSIZE
+ int "Bulk OUT High Speed MAXPACKET size"
+ default 512
+ ---help---
+ Max package size for the bulk OUT endpoint if High Speed mode.
+ Default 512.
+
+endif # USBDEV_DUALSPEED
+
+config USBMTP_EPBULKIN_FSSIZE
+ int "Bulk IN Full Speed MAXPACKET size"
+ default 64
+ ---help---
+ Max package size for the bulk IN endpoint if Full Speed mode.
+ Default 64.
+
+if USBDEV_DUALSPEED
+
+config USBMTP_EPBULKIN_HSSIZE
+ int "Bulk IN High Speed MAXPACKET size"
+ default 512
+ ---help---
+ Max package size for the bulk IN endpoint if High Speed mode.
+ Default 512.
+
+endif # USBDEV_DUALSPEED
+
+config USBMTP_EPINTIN_SIZE
+ int "Interrupt IN MAXPACKET size"
+ default 28
+ ---help---
+ Max package size for the Interrupt IN endpoint, Default 28.
+
+config USBMTP_EPINTIN_INTERVAL
+ int "Interrupt IN poll interval"
+ default 10
+ ---help---
+ The poll interval for the Interrupt IN endpoint, Default 10.
+
+config USBMTP_NRDREQS
+ int "Number of read requests that can be in flight"
+ default 4
+ ---help---
+ The number of read requests that can be in flight
+
+config USBMTP_NWRREQS
+ int "Number of write requests that can be in flight"
+ default 4
+ ---help---
+ The number of write/read requests that can be in flight
+
+if !USBMTP_COMPOSITE
+
+config USBMTP_VENDORID
+ hex "Vendor ID"
+ default 0x18d1
+ ---help---
+ The vendor ID code/string. Default is Google Inc.
+
+config USBMTP_PRODUCTID
+ hex "Product ID"
+ default 0x4e11
+ ---help---
+ The product ID code/string. Default is Nexus One.
+
+config USBMTP_VENDORSTR
+ string "Vendor string"
+ default "NuttX"
+
+config USBMTP_PRODUCTSTR
+ string "Product string"
+ default "Nuttx MTP"
+
+config USBMTP_SERIALSTR
+ string "Serial string"
+ default "1234"
+ depends on !USBMTP_BOARD_SERIALSTR
+
+endif # !USBMTP_COMPOSITE
+
+config USBMTP_CONFIGSTR
+ string "Configuration descriptor string"
+ default "MTP Config"
+
+config USBMTP_INTERFACESTR
+ string "Interface descriptor string"
+ default "MTP Interface"
+
+endif # USBMTP
+
endif # USBDEV
diff --git a/drivers/usbdev/Make.defs b/drivers/usbdev/Make.defs
index 7820e64723..7108c5d4ea 100644
--- a/drivers/usbdev/Make.defs
+++ b/drivers/usbdev/Make.defs
@@ -54,6 +54,10 @@ ifeq ($(CONFIG_USBADB),y)
CSRCS += adb.c
endif
+ifeq ($(CONFIG_USBMTP),y)
+ CSRCS += mtp.c
+endif
+
ifeq ($(CONFIG_NET_CDCECM),y)
CSRCS += cdcecm.c
endif
diff --git a/drivers/usbdev/mtp.c b/drivers/usbdev/mtp.c
new file mode 100644
index 0000000000..a96022902f
--- /dev/null
+++ b/drivers/usbdev/mtp.c
@@ -0,0 +1,467 @@
+/****************************************************************************
+ * drivers/usbdev/mtp.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/nuttx.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/usb/usb.h>
+#include <nuttx/usb/usbdev.h>
+#include <nuttx/usb/usbdev_trace.h>
+#include <nuttx/usb/mtp.h>
+#include <nuttx/fs/fs.h>
+
+#ifdef CONFIG_BOARD_USBDEV_SERIALSTR
+#include <nuttx/board.h>
+#endif
+
+#include "usbdev_fs.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define USBMTP_CHARDEV_PATH "/dev/mtp"
+
+#define USBMTP_NUM_EPS (3)
+#define USBMTP_EP_BULKIN_IDX (0)
+#define USBMTP_EP_BULKOUT_IDX (1)
+#define USBMTP_EP_INTIN_IDX (2)
+
+/* USB Controller */
+
+#ifdef CONFIG_USBDEV_SELFPOWERED
+# define USBMTP_SELFPOWERED USB_CONFIG_ATTR_SELFPOWER
+#else
+# define USBMTP_SELFPOWERED (0)
+#endif
+
+#ifdef CONFIG_USBDEV_REMOTEWAKEUP
+# define USBMTP_REMOTEWAKEUP USB_CONFIG_ATTR_WAKEUP
+#else
+# define USBMTP_REMOTEWAKEUP (0)
+#endif
+
+/* Buffer big enough for any of our descriptors (the config descriptor is the
+ * biggest).
+ */
+
+#define USBMTP_MXDESCLEN (64)
+#define USBMTP_MAXSTRLEN (USBMTP_MXDESCLEN - 2)
+
+/* Device descriptor values */
+
+#define USBMTP_VERSIONNO (0x0101) /* Device version number 1.1 (BCD) */
+
+/* String language */
+
+#define USBMTP_STR_LANGUAGE (0x0409) /* en-us */
+
+/* Descriptor strings. If this MTP device is part of a composite device
+ * then the manufacturer, product, and serial number strings will be provided
+ * by the composite logic.
+ */
+
+#ifndef CONFIG_USBMTP_COMPOSITE
+# define USBMTP_MANUFACTURERSTRID (1)
+# define USBMTP_PRODUCTSTRID (2)
+# define USBMTP_SERIALSTRID (3)
+# define USBMTP_CONFIGSTRID (4)
+# define USBMTP_INTERFACESTRID (5)
+# define USBMTP_NSTRIDS (5)
+#else
+# define USBMTP_INTERFACESTRID (1)
+# define USBMTP_NSTRIDS (1)
+#endif
+
+#define USBMTP_NCONFIGS (1)
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* USB descriptor ***********************************************************/
+
+#ifndef CONFIG_USBMTP_COMPOSITE
+static const struct usb_devdesc_s g_mtp_devdesc =
+{
+ .len = USB_SIZEOF_DEVDESC, /* Descriptor length */
+ .type = USB_DESC_TYPE_DEVICE, /* Descriptor type */
+ .usb = /* USB version */
+ {
+ LSBYTE(0x0200),
+ MSBYTE(0x0200)
+ },
+ .classid = 0, /* Device class */
+ .subclass = 0, /* Device sub-class */
+ .protocol = 0, /* Device protocol */
+ .mxpacketsize = CONFIG_USBMTP_EP0MAXPACKET, /* Max packet size (ep0) */
+ .vendor = /* Vendor ID */
+ {
+ LSBYTE(CONFIG_USBMTP_VENDORID),
+ MSBYTE(CONFIG_USBMTP_VENDORID)
+ },
+ .product = /* Product ID */
+ {
+ LSBYTE(CONFIG_USBMTP_PRODUCTID),
+ MSBYTE(CONFIG_USBMTP_PRODUCTID)
+ },
+ .device = /* Device ID */
+ {
+ LSBYTE(USBMTP_VERSIONNO),
+ MSBYTE(USBMTP_VERSIONNO)
+ },
+ .imfgr = USBMTP_MANUFACTURERSTRID, /* Manufacturer */
+ .iproduct = USBMTP_PRODUCTSTRID, /* Product */
+ .serno = USBMTP_SERIALSTRID, /* Serial number */
+ .nconfigs = USBMTP_NCONFIGS, /* Number of configurations */
+};
+
+static const struct usb_cfgdesc_s g_mtp_cfgdesc =
+{
+ .len = USB_SIZEOF_CFGDESC, /* Descriptor length */
+ .type = USB_DESC_TYPE_CONFIG, /* Descriptor type */
+ .cfgvalue = 1, /* Configuration value */
+ .icfg = USBMTP_CONFIGSTRID, /* Configuration */
+ .attr = USB_CONFIG_ATTR_ONE |
+ USBMTP_SELFPOWERED |
+ USBMTP_REMOTEWAKEUP, /* Attributes */
+ .mxpower = (CONFIG_USBDEV_MAXPOWER + 1) / 2
+};
+
+# ifdef CONFIG_USBDEV_DUALSPEED
+static const struct usb_qualdesc_s g_mtp_qualdesc =
+{
+ .len = USB_SIZEOF_QUALDESC, /* Descriptor length */
+ .type = USB_DESC_TYPE_DEVICEQUALIFIER, /* Descriptor type */
+ .usb = /* USB version */
+ {
+ LSBYTE(0x0200),
+ MSBYTE(0x0200)
+ },
+ .classid = 0, /* Device class */
+ .subclass = 0, /* Device sub-class */
+ .protocol = 0, /* Device protocol */
+ .mxpacketsize = CONFIG_USBMTP_EP0MAXPACKET, /* Max packet size (ep0) */
+ .nconfigs = USBMTP_NCONFIGS, /* Number of configurations */
+ .reserved = 0,
+};
+# endif
+
+static const struct usbdev_strdesc_s g_mtp_strdesc[] =
+{
+ {USBMTP_MANUFACTURERSTRID, CONFIG_USBMTP_VENDORSTR},
+ {USBMTP_PRODUCTSTRID, CONFIG_USBMTP_PRODUCTSTR},
+# ifdef CONFIG_USBMTP_SERIALSTR
+ {USBMTP_SERIALSTRID, CONFIG_USBMTP_SERIALSTR},
+# else
+ {USBMTP_SERIALSTRID, ""},
+# endif
+ {USBMTP_CONFIGSTRID, CONFIG_USBMTP_CONFIGSTR},
+ {}
+};
+
+static const struct usbdev_strdescs_s g_mtp_strdescs =
+{
+ .language = USBMTP_STR_LANGUAGE,
+ .strdesc = g_mtp_strdesc,
+};
+
+static const struct usbdev_devdescs_s g_mtp_devdescs =
+{
+ .cfgdesc = &g_mtp_cfgdesc,
+ .strdescs = &g_mtp_strdescs,
+ .devdesc = &g_mtp_devdesc,
+# ifdef CONFIG_USBDEV_DUALSPEED
+ .qualdesc = &g_mtp_qualdesc,
+# endif
+};
+#endif
+
+static const struct usb_ifdesc_s g_mtp_ifdesc =
+{
+ .len = USB_SIZEOF_IFDESC,
+ .type = USB_DESC_TYPE_INTERFACE,
+ .ifno = 0,
+ .alt = 0,
+ .neps = 3,
+ .classid = USB_CLASS_STILL_IMAGE,
+ .subclass = 0x01,
+ .protocol = 0x01,
+ .iif = 0x05
+};
+
+static const struct usbdev_epinfo_s g_mtp_epbulkin =
+{
+ .desc =
+ {
+ .len = USB_SIZEOF_EPDESC,
+ .type = USB_DESC_TYPE_ENDPOINT,
+ .addr = USB_DIR_IN,
+ .attr = USB_EP_ATTR_XFER_BULK |
+ USB_EP_ATTR_NO_SYNC |
+ USB_EP_ATTR_USAGE_DATA,
+ .interval = 0,
+ },
+ .fssize = CONFIG_USBMTP_EPBULKIN_FSSIZE,
+#ifdef CONFIG_USBDEV_DUALSPEED
+ .hssize = CONFIG_USBMTP_EPBULKIN_HSSIZE,
+#endif
+ .reqnum = CONFIG_USBMTP_NWRREQS,
+};
+
+static const struct usbdev_epinfo_s g_mtp_epbulkout =
+{
+ .desc =
+ {
+ .len = USB_SIZEOF_EPDESC,
+ .type = USB_DESC_TYPE_ENDPOINT,
+ .addr = USB_DIR_OUT,
+ .attr = USB_EP_ATTR_XFER_BULK |
+ USB_EP_ATTR_NO_SYNC |
+ USB_EP_ATTR_USAGE_DATA,
+ .interval = 0,
+ },
+ .fssize = CONFIG_USBMTP_EPBULKOUT_FSSIZE,
+#ifdef CONFIG_USBDEV_DUALSPEED
+ .hssize = CONFIG_USBMTP_EPBULKOUT_HSSIZE,
+#endif
+ .reqnum = CONFIG_USBMTP_NRDREQS,
+};
+
+static const struct usbdev_epinfo_s g_mtp_epbulkintin =
+{
+ .desc =
+ {
+ .len = USB_SIZEOF_EPDESC,
+ .type = USB_DESC_TYPE_ENDPOINT,
+ .addr = USB_DIR_IN,
+ .attr = USB_EP_ATTR_XFER_INT |
+ USB_EP_ATTR_NO_SYNC |
+ USB_EP_ATTR_USAGE_DATA,
+ .interval = CONFIG_USBMTP_EPINTIN_INTERVAL,
+ },
+ .fssize = CONFIG_USBMTP_EPINTIN_SIZE,
+#ifdef CONFIG_USBDEV_DUALSPEED
+ .hssize = CONFIG_USBMTP_EPINTIN_SIZE,
+#endif
+ .reqnum = CONFIG_USBMTP_NWRREQS,
+};
+
+static const FAR struct usbdev_epinfo_s *g_mtp_epinfos[USBMTP_NUM_EPS] =
+{
+ &g_mtp_epbulkin,
+ &g_mtp_epbulkout,
+ &g_mtp_epbulkintin,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: usbclass_mkcfgdesc
+ *
+ * Description:
+ * Construct the configuration descriptor
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_USBDEV_DUALSPEED
+static int16_t usbclass_mkcfgdesc(FAR uint8_t *buf,
+ FAR struct usbdev_devinfo_s *devinfo,
+ uint8_t speed, uint8_t type)
+#else
+static int16_t usbclass_mkcfgdesc(FAR uint8_t *buf,
+ FAR struct usbdev_devinfo_s *devinfo)
+#endif
+{
+ bool hispeed = false;
+ FAR struct usb_epdesc_s *epdesc;
+ FAR struct mtp_cfgdesc_s *dest;
+
+#ifdef CONFIG_USBDEV_DUALSPEED
+ hispeed = (speed == USB_SPEED_HIGH);
+
+ /* Check for switches between high and full speed */
+
+ if (type == USB_DESC_TYPE_OTHERSPEEDCONFIG)
+ {
+ hispeed = !hispeed;
+ }
+#endif
+
+ dest = (FAR struct mtp_cfgdesc_s *)buf;
+ epdesc = (FAR struct usb_epdesc_s *)(buf + sizeof(g_mtp_ifdesc));
+
+ memcpy(dest, &g_mtp_ifdesc, sizeof(g_mtp_ifdesc));
+
+ usbdev_copy_epdesc(&epdesc[0], devinfo->epno[USBMTP_EP_BULKIN_IDX],
+ hispeed, &g_mtp_epbulkin);
+ usbdev_copy_epdesc(&epdesc[1], devinfo->epno[USBMTP_EP_BULKOUT_IDX],
+ hispeed, &g_mtp_epbulkout);
+ usbdev_copy_epdesc(&epdesc[2], devinfo->epno[USBMTP_EP_INTIN_IDX],
+ hispeed, &g_mtp_epbulkintin);
+
+#ifdef CONFIG_USBMTP_COMPOSITE
+ /* For composite device, apply possible offset to the interface numbers */
+
+ dest->ifdesc.ifno = devinfo->ifnobase;
+ dest->ifdesc.iif = devinfo->strbase + USBMTP_INTERFACESTRID;
+#endif
+
+ return sizeof(g_mtp_ifdesc) + 3 * USB_SIZEOF_EPDESC;
+}
+
+/****************************************************************************
+ * Name: usbclass_mkstrdesc
+ *
+ * Description:
+ * Construct the string descriptor
+ *
+ ****************************************************************************/
+
+static int usbclass_mkstrdesc(uint8_t id, FAR struct usb_strdesc_s *strdesc)
+{
+ FAR uint8_t *data = (FAR uint8_t *)(strdesc + 1);
+ FAR const char *str;
+ int len;
+ int ndata;
+ int i;
+
+ switch (id)
+ {
+ /* Composite driver removes offset before calling mkstrdesc() */
+
+ case USBMTP_INTERFACESTRID:
+ str = CONFIG_USBMTP_INTERFACESTR;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /* The string is utf16-le. The poor man's utf-8 to utf16-le
+ * conversion below will only handle 7-bit en-us ascii
+ */
+
+ len = strlen(str);
+ if (len > (USBMTP_MAXSTRLEN / 2))
+ {
+ len = (USBMTP_MAXSTRLEN / 2);
+ }
+
+ for (i = 0, ndata = 0; i < len; i++, ndata += 2)
+ {
+ data[ndata] = str[i];
+ data[ndata + 1] = 0;
+ }
+
+ strdesc->len = ndata + 2;
+ strdesc->type = USB_DESC_TYPE_STRING;
+ return strdesc->len;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+#ifndef CONFIG_USBMTP_COMPOSITE
+/****************************************************************************
+ * Name: usbdev_mtp_initialize
+ *
+ * Description:
+ * Initialize the Media Transfer protocol USB device driver.
+ *
+ * Returned Value:
+ * A non-NULL "handle" is returned on success.
+ *
+ ****************************************************************************/
+
+FAR void *usbdev_mtp_initialize(void)
+{
+ struct composite_devdesc_s devdesc;
+
+ usbdev_mtp_get_composite_devdesc(&devdesc);
+
+ devdesc.devinfo.epno[USBMTP_EP_BULKIN_IDX] =
+ USB_EPNO(CONFIG_USBMTP_EPBULKIN);
+ devdesc.devinfo.epno[USBMTP_EP_BULKOUT_IDX] =
+ USB_EPNO(CONFIG_USBMTP_EPBULKOUT);
+ devdesc.devinfo.epno[USBMTP_EP_INTIN_IDX] =
+ USB_EPNO(CONFIG_USBMTP_EPINTIN);
+
+ return usbdev_fs_initialize(&g_mtp_devdescs, &devdesc);
+}
+
+/****************************************************************************
+ * Name: usbdev_mtp_uninitialize
+ *
+ * Description:
+ * Uninitialize the Media Transfer protocol USB device driver.
+ *
+ ****************************************************************************/
+
+void usbdev_mtp_uninitialize(FAR void *handle)
+{
+ usbdev_fs_uninitialize(handle);
+}
+#endif
+
+/****************************************************************************
+ * Name: usbdev_mtp_get_composite_devdesc
+ *
+ * Description:
+ * Helper function to fill in some constants into the composite
+ * configuration struct.
+ *
+ * Input Parameters:
+ * dev - Pointer to the configuration struct we should fill
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void usbdev_mtp_get_composite_devdesc(FAR struct composite_devdesc_s *dev)
+{
+ memset(dev, 0, sizeof(struct composite_devdesc_s));
+
+ dev->mkconfdesc = usbclass_mkcfgdesc;
+ dev->mkstrdesc = usbclass_mkstrdesc;
+ dev->classobject = usbdev_fs_classobject;
+ dev->uninitialize = usbdev_fs_classuninitialize;
+ dev->nconfigs = USBMTP_NCONFIGS;
+ dev->configid = 1;
+ dev->cfgdescsize = sizeof(g_mtp_ifdesc) + 3 * USB_SIZEOF_EPDESC;
+ dev->devinfo.ninterfaces = 1;
+ dev->devinfo.nstrings = USBMTP_NSTRIDS;
+ dev->devinfo.nendpoints = USBMTP_NUM_EPS;
+ dev->devinfo.epinfos = g_mtp_epinfos;
+ dev->devinfo.name = USBMTP_CHARDEV_PATH;
+}
diff --git a/include/nuttx/usb/mtp.h b/include/nuttx/usb/mtp.h
new file mode 100644
index 0000000000..0e07a88ee7
--- /dev/null
+++ b/include/nuttx/usb/mtp.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+ * include/nuttx/usb/mtp.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_USB_MTP_H
+#define __INCLUDE_NUTTX_USB_MTP_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/usb/usbdev.h>
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+# define EXTERN extern "C"
+extern "C"
+{
+#else
+# define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Name: usbdev_mtp_initialize
+ *
+ * Description:
+ * Initialize the Media Transfer Protocol USB device driver.
+ *
+ * Returned Value:
+ * A non-NULL "handle" is returned on success.
+ *
+ ****************************************************************************/
+
+FAR void *usbdev_mtp_initialize(void);
+
+/****************************************************************************
+ * Name: usbdev_mtp_uninitialize
+ *
+ * Description:
+ * Uninitialize the Media Transfer Protocol USB device driver.
+ *
+ ****************************************************************************/
+
+void usbdev_mtp_uninitialize(FAR void *handle);
+
+/****************************************************************************
+ * Name: usbdev_mtp_get_composite_devdesc
+ *
+ * Description:
+ * Helper function to fill in some constants into the composite
+ * configuration struct.
+ *
+ * Input Parameters:
+ * dev - Pointer to the configuration struct we should fill
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void usbdev_mtp_get_composite_devdesc(FAR struct composite_devdesc_s *dev);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __INCLUDE_NUTTX_USB_ADB_H */