Skip to content

Commit 3bb7378

Browse files
committed
samples: subsys: usb: mtp: add new sample
Add a sample application that demonstrates how to use the new USB MTP device class. This shows how to set up the device tree to expose storage partitions to a host over USB using MTP. Files/Dirs can be accessed from host without host supportfor the underlying filesystem like littlefs. Signed-off-by: Mohamed ElShahawi <[email protected]>
1 parent 9ecbe30 commit 3bb7378

File tree

8 files changed

+280
-0
lines changed

8 files changed

+280
-0
lines changed

samples/subsys/usb/mtp/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
5+
project(mtp)
6+
7+
include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake)
8+
FILE(GLOB app_sources src/*.c)
9+
target_sources(app PRIVATE ${app_sources})

samples/subsys/usb/mtp/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright (c) 2023 Nordic Semiconductor ASA
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
# Source common USB sample options used to initialize new experimental USB
5+
# device stack. The scope of these options is limited to USB samples in project
6+
# tree, you cannot use them in your own application.
7+
source "samples/subsys/usb/common/Kconfig.sample_usbd"
8+
9+
source "Kconfig.zephyr"

samples/subsys/usb/mtp/README.rst

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
.. zephyr:code-sample:: usb-mtp
2+
:name: USB MTP
3+
:relevant-api: usbd_api _usb_device_core_api file_system_api
4+
5+
Expose the selected storage partition(s) as USB Media device using Media Transfer Protocol driver.
6+
7+
Overview
8+
********
9+
10+
This sample app demonstrates the use of USB Media Transfer Protocol (MTP)
11+
driver provided by the Zephyr project. It allows the device to be mounted
12+
as a media device on the host system, enabling file transfers between the
13+
host and device.
14+
This sample can be found under :zephyr_file:`samples/subsys/usb/mtp` in the
15+
Zephyr project tree.
16+
17+
Requirements
18+
************
19+
20+
- USB device driver support.
21+
- Storage media with Littlefs/FAT filesystem support.
22+
- Partitions must be mounted before connecting the board to Host.
23+
24+
Building and Running
25+
********************
26+
27+
This sample can be built for multiple boards which can support at least one storage parition,
28+
in this example we will build it for the stm32f769i_disco board:
29+
30+
.. zephyr-app-commands::
31+
:zephyr-app: samples/subsys/usb/mtp
32+
:board: stm32f769i_disco
33+
:goals: flash
34+
:compact:
35+
36+
Running
37+
=======
38+
39+
Plug the board into a host device, for example, a PC running Linux.
40+
The board will be detected as shown by the Linux dmesg command:
41+
42+
.. code-block:: console
43+
44+
usb 9-1: new full-speed USB device number 112 using uhci_hcd
45+
usb 9-1: New USB device found, idVendor=8086, idProduct=f8a1
46+
usb 9-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
47+
usb 9-1: Product: Zephyr MTP
48+
usb 9-1: Manufacturer: ZEPHYR
49+
usb 9-1: SerialNumber: 0123456789AB
50+
51+
Once connected, the device should appear as a media device on your host system.
52+
You can then:
53+
- Browse the device storage
54+
- Transfer files to/from the device
55+
- Create/delete directories
56+
57+
The storage contents will persist across device reboots as long as the
58+
filesystem is properly unmounted before disconnecting or resetting the device.
59+
60+
.. note::
61+
62+
Not All MTP Features are implemented, for example you can't move/copy
63+
files from within the device, it must be done via Host.
64+
65+
Troubleshooting
66+
===============
67+
68+
If the device is not recognized properly:
69+
70+
1. Ensure the storage medium is properly initialized
71+
2. Check that the filesystem is mounted correctly
72+
3. Verify USB configuration is correct for your board
73+
4. Enable DEBUG logs on USB MTP driver to get more information
74+
75+
For debugging purposes, you can enable USB debug logs by setting the following
76+
in your project's configuration:
77+
78+
.. code-block:: none
79+
80+
CONFIG_USBD_LOG_LEVEL_DBG=y
81+
CONFIG_USBD_MTP_LOG_LEVEL_DBG=y
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright (c) 2024 Kelly Lord
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
&flash0 {
8+
partitions {
9+
compatible = "fixed-partitions";
10+
#address-cells = <1>;
11+
#size-cells = <1>;
12+
13+
storage_partition: partition@100000 {
14+
label = "storage";
15+
reg = <0x100000 DT_SIZE_M(1)>;
16+
};
17+
};
18+
};
19+
20+
/ {
21+
fstab {
22+
compatible = "zephyr,fstab";
23+
lfs1: lfs1 {
24+
compatible = "zephyr,fstab,littlefs";
25+
read-size = <32>;
26+
prog-size = <32>;
27+
cache-size = <256>;
28+
lookahead-size = <64>;
29+
block-cycles = <512>;
30+
partition = <&storage_partition>;
31+
mount-point = "/lfs1";
32+
automount;
33+
mtp-enabled;
34+
};
35+
};
36+
};
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright (c) 2025 Mohamed ElShahawi ([email protected])
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/delete-node/ &storage_partition;
8+
9+
&mx25l51245g {
10+
partitions {
11+
compatible = "fixed-partitions";
12+
#address-cells = <1>;
13+
#size-cells = <1>;
14+
15+
storage_partition: partition@1a0000 {
16+
label = "storage";
17+
reg = <0x001a0000 DT_SIZE_M(40)>;
18+
};
19+
storage_partition2: partition@2ba0000 {
20+
label = "storage2";
21+
reg = <0x2ba0000 DT_SIZE_M(20)>;
22+
};
23+
};
24+
};
25+
26+
/ {
27+
fstab {
28+
compatible = "zephyr,fstab";
29+
lfs1: lfs1 {
30+
compatible = "zephyr,fstab,littlefs";
31+
read-size = <32>;
32+
prog-size = <32>;
33+
cache-size = <256>;
34+
lookahead-size = <64>;
35+
block-cycles = <512>;
36+
partition = <&storage_partition>;
37+
mount-point = "/lfs1";
38+
automount;
39+
mtp-enabled;
40+
};
41+
lfs2: lfs2 {
42+
compatible = "zephyr,fstab,littlefs";
43+
read-size = <32>;
44+
prog-size = <32>;
45+
cache-size = <256>;
46+
lookahead-size = <64>;
47+
block-cycles = <512>;
48+
partition = <&storage_partition2>;
49+
mount-point = "/lfs2";
50+
automount;
51+
mtp-enabled;
52+
};
53+
};
54+
};

samples/subsys/usb/mtp/prj.conf

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
CONFIG_USB_DEVICE_STACK_NEXT=y
2+
CONFIG_USBD_MTP_CLASS=y
3+
4+
CONFIG_SAMPLE_USBD_PRODUCT="USBD MTP sample"
5+
CONFIG_SAMPLE_USBD_PID=0x0009
6+
7+
CONFIG_LOG=y
8+
CONFIG_USBD_LOG_LEVEL_WRN=y
9+
CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y
10+
CONFIG_USBD_MTP_LOG_LEVEL_ERR=y
11+
12+
CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n
13+
14+
CONFIG_FLASH=y
15+
CONFIG_FLASH_MAP=y
16+
17+
CONFIG_FILE_SYSTEM=y
18+
CONFIG_FILE_SYSTEM_LITTLEFS=y
19+
20+
CONFIG_USBD_THREAD_STACK_SIZE=3192

samples/subsys/usb/mtp/sample.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
sample:
2+
name: USB MTP device class sample
3+
tests:
4+
sample.usb_device_next.mtp:
5+
depends_on: usbd
6+
tags: usb
7+
harness: console
8+
harness_config:
9+
type: one_line
10+
regex:
11+
- "USB device support enabled"

samples/subsys/usb/mtp/src/main.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright (c) 2019 Intel Corporation
3+
* Copyright (c) 2025 Mohamed ElShahawi ([email protected])
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
/**
9+
* @file
10+
* @brief Sample app for USB MTP class
11+
*
12+
* Sample app for USB MTP class driver. By default MTP class driver will expose
13+
* all storage partitions which has the flag `mtp-enabled`
14+
*/
15+
16+
#include <sample_usbd.h>
17+
18+
#include <zephyr/kernel.h>
19+
#include <zephyr/usb/usb_device.h>
20+
#include <zephyr/usb/usbd.h>
21+
#include <zephyr/logging/log.h>
22+
LOG_MODULE_REGISTER(usb_mtp_sample, LOG_LEVEL_INF);
23+
24+
static void sample_msg_cb(struct usbd_context *const ctx, const struct usbd_msg *msg)
25+
{
26+
LOG_INF("USBD message: %s", usbd_msg_type_string(msg->type));
27+
28+
if (usbd_can_detect_vbus(ctx)) {
29+
if (msg->type == USBD_MSG_VBUS_READY) {
30+
if (usbd_enable(ctx)) {
31+
LOG_ERR("Failed to enable device support");
32+
}
33+
}
34+
35+
if (msg->type == USBD_MSG_VBUS_REMOVED) {
36+
if (usbd_disable(ctx)) {
37+
LOG_ERR("Failed to disable device support");
38+
}
39+
}
40+
}
41+
}
42+
43+
int main(void)
44+
{
45+
struct usbd_context *sample_usbd;
46+
47+
sample_usbd = sample_usbd_init_device(sample_msg_cb);
48+
if (sample_usbd == NULL) {
49+
LOG_ERR("Failed to initialize USB device");
50+
return -1;
51+
}
52+
53+
if (usbd_enable(sample_usbd)) {
54+
LOG_ERR("Failed to enable device support");
55+
return -1;
56+
}
57+
58+
LOG_INF("USB device support enabled\n");
59+
return 0;
60+
}

0 commit comments

Comments
 (0)