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 */