Skip to content

Commit 9c28ea3

Browse files
committed
Review comments
- mtp: use `usbd_bus_speed` to get the correct descriptor which holds the Manufacturer/Product/SerialNumber strings - mtp_class: return OPERATION_NOT_SUPPORTED when not supported command is received. - tests: Add mtp to build_all - Updated Sample README file - Fix build error - Cleanup multiple files
1 parent d9e53c2 commit 9c28ea3

File tree

7 files changed

+84
-123
lines changed

7 files changed

+84
-123
lines changed

samples/subsys/usb/mtp/README.rst

Lines changed: 36 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,36 @@
1-
.. zephyr:code-sample:: usb-cdc-acm
2-
:name: USB CDC-ACM
3-
:relevant-api: usbd_api _usb_device_core_api uart_interface
1+
.. zephyr:code-sample:: usb-mtp
2+
:name: USB MTP
3+
:relevant-api: usbd_api _usb_device_core_api file_system_api
44

5-
Use USB CDC-ACM driver to implement a serial port echo.
5+
Use USB MTP driver which implement a Media Transfer Protocol device.
66

77
Overview
88
********
99

10-
This sample app demonstrates use of a USB Communication Device Class (CDC)
11-
Abstract Control Model (ACM) driver provided by the Zephyr project.
12-
Received data from the serial port is echoed back to the same port
13-
provided by this driver.
14-
This sample can be found under :zephyr_file:`samples/subsys/usb/cdc_acm` in the
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
1515
Zephyr project tree.
1616

1717
Requirements
1818
************
1919

20-
This project requires an USB device driver, which is available for multiple
21-
boards supported in Zephyr.
20+
This project requires:
21+
- USB device driver support
22+
- Storage media with Littlefs/FAT filesystem support
2223

2324
Building and Running
2425
********************
2526

2627
Reel Board
2728
===========
2829

29-
To see the console output of the app, open a serial port emulator and
30-
attach it to the USB to TTL Serial cable. Build and flash the project:
30+
Build and flash the project:
3131

3232
.. zephyr-app-commands::
33-
:zephyr-app: samples/subsys/usb/cdc_acm
33+
:zephyr-app: samples/subsys/usb/mtp
3434
:board: reel_board
3535
:goals: flash
3636
:compact:
@@ -46,53 +46,34 @@ The board will be detected as shown by the Linux dmesg command:
4646
usb 9-1: new full-speed USB device number 112 using uhci_hcd
4747
usb 9-1: New USB device found, idVendor=8086, idProduct=f8a1
4848
usb 9-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
49-
usb 9-1: Product: CDC-ACM
50-
usb 9-1: Manufacturer: Intel
51-
usb 9-1: SerialNumber: 00.01
52-
cdc_acm 9-1:1.0: ttyACM1: USB ACM device
49+
usb 9-1: Product: Zephyr MTP
50+
usb 9-1: Manufacturer: ZEPHYR
51+
usb 9-1: SerialNumber: 0123456789AB
5352
54-
The app prints on serial output (UART1), used for the console:
53+
Once connected, the device should appear as a media device on your host system.
54+
You can then:
55+
- Browse the device storage
56+
- Transfer files to/from the device
57+
- Create/delete directories
58+
- Manage files on the device
5559

56-
.. code-block:: console
57-
58-
Wait for DTR
59-
60-
Open a serial port emulator, for example minicom
61-
and attach it to detected CDC ACM device:
62-
63-
.. code-block:: console
64-
65-
minicom --device /dev/ttyACM1
66-
67-
The app should respond on serial output with:
68-
69-
.. code-block:: console
70-
71-
DTR set, start test
72-
Baudrate detected: 115200
73-
74-
And on ttyACM device, provided by zephyr USB device stack:
75-
76-
.. code-block:: console
60+
The storage contents will persist across device reboots as long as the
61+
filesystem is properly unmounted before disconnecting or resetting the device.
7762

78-
Send characters to the UART device
79-
Characters read:
63+
Troubleshooting
64+
==============
8065

81-
The characters entered in serial port emulator will be echoed back.
66+
If the device is not recognized properly:
8267

83-
Troubleshooting
84-
===============
68+
1. Ensure the storage medium is properly initialized
69+
2. Check that the filesystem is mounted correctly
70+
3. Verify USB configuration is correct for your board
71+
4. Some systems may require additional MTP device support to be installed
8572

86-
If the ModemManager runs on your operating system, it will try
87-
to access the CDC ACM device and maybe you can see several characters
88-
including "AT" on the terminal attached to the CDC ACM device.
89-
You can add or extend the udev rule for your board to inform
90-
ModemManager to skip the CDC ACM device.
91-
For this example, it would look like this:
73+
For debugging purposes, you can enable USB debug logs by setting the following
74+
in your project's configuration:
9275

9376
.. code-block:: none
9477
95-
ATTRS{idVendor}=="8086" ATTRS{idProduct}=="f8a1", ENV{ID_MM_DEVICE_IGNORE}="1"
96-
97-
You can use
98-
``/lib/udev/rules.d/77-mm-usb-device-blacklist.rules`` as reference.
78+
CONFIG_USB_DEVICE_LOG_LEVEL_DBG=y
79+
CONFIG_USB_MTP_LOG_LEVEL_DBG=y
Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
1+
/*
2+
* Copyright (c) 2025 Mohamed ElShahawi (extremegtx@hotmail.com)
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
16

27
/delete-node/ &storage_partition;
38

9+
&mx25l51245g {
10+
partitions {
11+
compatible = "fixed-partitions";
12+
#address-cells = <1>;
13+
#size-cells = <1>;
414

5-
&mx25l51245g {
6-
partitions {
7-
compatible = "fixed-partitions";
8-
#address-cells = <1>;
9-
#size-cells = <1>;
10-
11-
storage_partition: partition@1a0000 {
12-
label = "storage";
13-
reg = <0x001a0000 DT_SIZE_M(40)>;
14-
};
15-
storage_partition2: partition@2ba0000 {
16-
label = "storage2";
17-
reg = <0x2ba0000 DT_SIZE_M(20)>;
18-
};
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)>;
1922
};
2023
};
21-
22-
24+
};
2325

2426
/ {
2527
fstab {
@@ -48,12 +50,5 @@
4850
automount;
4951
mtp-enabled;
5052
};
51-
// Not Working
52-
// sd0: sd0 {
53-
// compatible = "zephyr,fstab-common";
54-
// partition = <&sdmmc2>;
55-
// mount-point = "/SD:";
56-
// automount;
57-
// };
5853
};
5954
};

samples/subsys/usb/mtp/prj.conf

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@ CONFIG_LOG=y
88
CONFIG_SAMPLE_USBD_PRODUCT="USBD MTP sample"
99
CONFIG_SAMPLE_USBD_PID=0x0009
1010

11-
12-
13-
14-
15-
1611
CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n
1712

1813
CONFIG_FLASH=y
@@ -22,40 +17,22 @@ CONFIG_MAIN_STACK_SIZE=2048
2217
CONFIG_FILE_SYSTEM=y
2318
CONFIG_FILE_SYSTEM_MKFS=y
2419
CONFIG_FILE_SYSTEM_LITTLEFS=y
25-
#CONFIG_FS_LITTLEFS_FMP_DEV=y
2620

2721
CONFIG_SHELL=y
2822
CONFIG_FILE_SYSTEM_SHELL=y
2923
CONFIG_HEAP_MEM_POOL_SIZE=16384
3024

31-
#CONFIG_DISK_DRIVERS=y
32-
#CONFIG_DISK_ACCESS=y
33-
#CONFIG_DISK_DRIVER_FLASH=y
34-
3525
#CONFIG_USB_DEVICE_LOG_LEVEL_DBG=y
3626
CONFIG_LOG_PROCESS_TRIGGER_THRESHOLD=5
3727
CONFIG_LOG_BUFFER_SIZE=65536
3828

3929
CONFIG_USBD_LOG_LEVEL_WRN=y
4030
#CONFIG_USBD_LOG_LEVEL_DBG=y
4131

42-
#CONFIG_SAMPLE_USBD_PID=0x6860
43-
#CONFIG_SAMPLE_USBD_PRODUCT="SAMSUNG_Android"
44-
#CONFIG_SAMPLE_USBD_MANUFACTURER="SAMSUNG"
45-
46-
47-
#SDCARD
48-
CONFIG_DISK_ACCESS=y
49-
CONFIG_DISK_DRIVER_SDMMC=y
50-
CONFIG_SDMMC_STM32=y
51-
CONFIG_SDMMC_SUBSYS=y
52-
53-
5432
CONFIG_FAT_FILESYSTEM_ELM=y
5533

5634
CONFIG_USBD_THREAD_STACK_SIZE=2048
5735

58-
5936
CONFIG_OUTPUT_DISASSEMBLY=y
6037
CONFIG_OUTPUT_DISASSEMBLY_WITH_SOURCE=y
6138
CONFIG_FLASH_SHELL=y

subsys/usb/device_next/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ zephyr_linker_sources_ifdef(
102102
zephyr_library_sources_ifdef(
103103
CONFIG_USBD_MTP_CLASS
104104
class/usbd_mtp.c
105-
class/usbd_mtp_impl.c
105+
class/usbd_mtp_class.c
106106
)
107107

108108
zephyr_linker_sources(DATA_SECTIONS usbd_data.ld)

subsys/usb/device_next/class/usbd_mtp.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@
1212
#include <zephyr/logging/log.h>
1313
LOG_MODULE_REGISTER(usb_mtp, CONFIG_USBD_MTP_LOG_LEVEL);
1414

15-
#define MTP_RESPONSE_OK 0x2001
16-
#define MTP_RESPONSE_DEVICE_BUSY 0x2019
17-
18-
1915
/* Endpoint addresses */
2016
#define MTP_IN_EP_ADDR 0x81 /* Bulk IN */
2117
#define MTP_OUT_EP_ADDR 0x01 /* Bulk OUT */
@@ -290,26 +286,31 @@ static int usbd_mtp_init(struct usbd_class_data *c_data)
290286
LOG_INF("Init class instance %p", c_data);
291287

292288
char *manufacturer, *model, *device_version, *serial_number;
293-
struct usb_device_descriptor *hs_desc =
294-
(struct usb_device_descriptor *)c_data->uds_ctx->hs_desc;
289+
struct usb_device_descriptor *usbd_desc;
295290
struct usbd_desc_node *d_nd;
296291

297-
d_nd = usbd_get_descriptor(c_data->uds_ctx, USB_DESC_STRING, hs_desc->iManufacturer);
292+
if (usbd_bus_speed(c_data->uds_ctx) == USBD_SPEED_HS) {
293+
usbd_desc = (struct usb_device_descriptor *)c_data->uds_ctx->hs_desc;
294+
} else {
295+
usbd_desc = (struct usb_device_descriptor *)c_data->uds_ctx->fs_desc;
296+
}
297+
298+
d_nd = usbd_get_descriptor(c_data->uds_ctx, USB_DESC_STRING, usbd_desc->iManufacturer);
298299
manufacturer = (char *)d_nd->ptr;
299300

300-
d_nd = usbd_get_descriptor(c_data->uds_ctx, USB_DESC_STRING, hs_desc->iProduct);
301+
d_nd = usbd_get_descriptor(c_data->uds_ctx, USB_DESC_STRING, usbd_desc->iProduct);
301302
model = (char *)d_nd->ptr;
302303

303-
d_nd = usbd_get_descriptor(c_data->uds_ctx, USB_DESC_STRING, hs_desc->iSerialNumber);
304+
d_nd = usbd_get_descriptor(c_data->uds_ctx, USB_DESC_STRING, usbd_desc->iSerialNumber);
304305
serial_number = (char *)d_nd->ptr;
305306

306307
device_version = "1.0";
307308

308-
LOG_DBG("Manufacturer: %s", manufacturer);
309-
LOG_DBG("Product: %s", model);
310-
if (d_nd->bLength > 0) {
311-
LOG_DBG("Serial Number: %s", serial_number);
312-
}
309+
LOG_DBG("Desc data: Manufacturer: %s, Product: %s, SN: %s",
310+
manufacturer,
311+
model,
312+
d_nd->bLength > 0 ? serial_number : "NULL");
313+
313314
mtp_init(manufacturer, model, device_version, serial_number);
314315

315316
return 0;

subsys/usb/device_next/class/usbd_mtp_class.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -910,7 +910,7 @@ static int continue_get_object(struct net_buf *buf)
910910
set_pending_packet(continue_get_object);
911911
}
912912
} else {
913-
LOG_ERR("shouldn't happen !!!!!!!!!");
913+
LOG_ERR("shouldn't happen !");
914914
}
915915
return 0;
916916
}
@@ -1296,7 +1296,15 @@ int mtp_commands_handler(struct net_buf *buf_in, struct net_buf *buf)
12961296
MTP_CMD(MTP_OP_GET_OBJECT_REFERENCES);
12971297
break;
12981298
default:
1299-
LOG_ERR("Unknown cmd 0x%x!", mtp_command->hdr.code);
1299+
LOG_ERR("Not supported cmd 0x%x!", mtp_command->hdr.code);
1300+
1301+
struct mtp_header mtp_response = {
1302+
.length = sizeof(struct mtp_header),
1303+
.type = MTP_CONTAINER_RESPONSE,
1304+
.code = MTP_RESP_OPERATION_NOT_SUPPORTED,
1305+
.transaction_id = mtp_command->hdr.transaction_id };
1306+
1307+
net_buf_add_mem(buf, &mtp_response, sizeof(struct mtp_header));
13001308
break;
13011309
}
13021310

@@ -1389,15 +1397,12 @@ int mtp_init(const char *manufacturer, const char *model, const char *device_ver
13891397
/* Zephyr set Serial Number descriptor after MTP init, so for now use this one */
13901398
dev_info.serial_number = "0123456789ABCDEF";
13911399

1392-
for (int i = 1; i < ARRAY_SIZE(storage); i++) {
1393-
memset(storage[i].filelist, 0x00, sizeof(storage[i].filelist));
1394-
storage[i].files_count = 0;
1395-
}
1396-
mtp_ctx.session_opened = false;
1400+
mtp_reset();
13971401

13981402
return 0;
13991403
}
14001404

1405+
#if CONFIG_SHELL
14011406
static int cmd_mtp_list(const struct shell *sh, size_t argc, char **argv)
14021407
{
14031408
for (int storageIdx = 1; storageIdx < ARRAY_SIZE(storage); storageIdx++) {
@@ -1422,3 +1427,4 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_mtp,
14221427
SHELL_SUBCMD_SET_END);
14231428

14241429
SHELL_CMD_REGISTER(mtp, &sub_mtp, "USB MTP commands", NULL);
1430+
#endif

tests/subsys/usb/device_next/build_all.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ CONFIG_UART_LINE_CTRL=y
2222
CONFIG_USBD_CDC_ACM_CLASS=y
2323

2424
CONFIG_USBD_MSC_CLASS=y
25+
CONFIG_USBD_MTP_CLASS=y
2526

2627
CONFIG_USBD_AUDIO2_CLASS=y
2728

0 commit comments

Comments
 (0)