Skip to content

Commit 981dc98

Browse files
committed
mtp example work with highspeed device
1 parent 4a0613c commit 981dc98

File tree

2 files changed

+68
-6
lines changed

2 files changed

+68
-6
lines changed

examples/device/mtp/src/usb_descriptors.c

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,18 +109,79 @@ enum
109109

110110
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_MTP_DESC_LEN)
111111

112-
uint8_t const desc_fs_configuration[] = {
112+
// full speed configuration
113+
const uint8_t desc_fs_configuration[] = {
113114
// Config number, interface count, string index, total length, attribute, power in mA
114115
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
116+
// Interface number, string index, EP event, EP event size, EP event polling, EP Out & EP In address, EP size
115117
TUD_MTP_DESCRIPTOR(ITF_NUM_MTP, 4, EPNUM_MTP_EVT, 64, 1, EPNUM_MTP_OUT, EPNUM_MTP_IN, 64),
116118
};
117119

120+
#if TUD_OPT_HIGH_SPEED
121+
// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
122+
123+
// high speed configuration
124+
uint8_t const desc_hs_configuration[] = {
125+
// Config number, interface count, string index, total length, attribute, power in mA
126+
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
127+
// Interface number, string index, EP event, EP event size, EP event polling, EP Out & EP In address, EP size
128+
TUD_MTP_DESCRIPTOR(ITF_NUM_MTP, 4, EPNUM_MTP_EVT, 64, 1, EPNUM_MTP_OUT, EPNUM_MTP_IN, 512),
129+
};
130+
131+
// other speed configuration
132+
uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
133+
134+
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
135+
tusb_desc_device_qualifier_t const desc_device_qualifier = {
136+
.bLength = sizeof(tusb_desc_device_qualifier_t),
137+
.bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
138+
.bcdUSB = USB_BCD,
139+
140+
.bDeviceClass = TUSB_CLASS_MISC,
141+
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
142+
.bDeviceProtocol = MISC_PROTOCOL_IAD,
143+
144+
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
145+
.bNumConfigurations = 0x01,
146+
.bReserved = 0x00
147+
};
148+
149+
// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
150+
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
151+
// device_qualifier descriptor describes information about a high-speed capable device that would
152+
// change if the device were operating at the other speed. If not highspeed capable stall this request.
153+
uint8_t const *tud_descriptor_device_qualifier_cb(void) {
154+
return (uint8_t const *) &desc_device_qualifier;
155+
}
156+
157+
// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
158+
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
159+
// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
160+
uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) {
161+
(void) index; // for multiple configurations
162+
163+
// if link speed is high return fullspeed config, and vice versa
164+
// Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG
165+
memcpy(desc_other_speed_config,
166+
(tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration,
167+
CONFIG_TOTAL_LEN);
168+
desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG;
169+
return desc_other_speed_config;
170+
}
171+
172+
#endif // highspeed
173+
118174
// Invoked when received GET CONFIGURATION DESCRIPTOR
119175
// Application return pointer to descriptor
120176
// Descriptor contents must exist long enough for transfer to complete
121-
uint8_t const *tud_descriptor_configuration_cb(uint8_t index) {
177+
const uint8_t*tud_descriptor_configuration_cb(uint8_t index) {
122178
(void) index; // for multiple configurations
179+
#if TUD_OPT_HIGH_SPEED
180+
// Although we are highspeed, host may be fullspeed.
181+
return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration;
182+
#else
123183
return desc_fs_configuration;
184+
#endif
124185
}
125186

126187
//--------------------------------------------------------------------+
@@ -173,11 +234,12 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
173234
}
174235

175236
const char *str = string_desc_arr[index];
176-
177237
// Cap at max char
178238
chr_count = strlen(str);
179-
size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type
180-
if ( chr_count > max_count ) chr_count = max_count;
239+
const size_t max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type
240+
if ( chr_count > max_count ) {
241+
chr_count = max_count;
242+
}
181243

182244
// Convert ASCII string into UTF-16
183245
for ( size_t i = 0; i < chr_count; i++ ) {

src/device/usbd.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ
276276
// Length of template descriptor: 30 bytes
277277
#define TUD_MTP_DESC_LEN (9 + 7 + 7 + 7)
278278

279-
// Interface number, string index, EP Out & EP In address, EP size
279+
// Interface number, string index, EP event, EP event size, EP event polling, EP Out & EP In address, EP size
280280
#define TUD_MTP_DESCRIPTOR(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_polling_interval, _epout, _epin, _epsize) \
281281
/* Interface */\
282282
9, TUSB_DESC_INTERFACE, _itfnum, 0, 3, TUSB_CLASS_IMAGE, MTP_SUBCLASS_STILL_IMAGE, MTP_PROTOCOL_PIMA_15470, _stridx,\

0 commit comments

Comments
 (0)