Skip to content

Commit e4a408c

Browse files
committed
Allow multiple instances of MTP
1 parent 9c28ea3 commit e4a408c

File tree

3 files changed

+270
-254
lines changed

3 files changed

+270
-254
lines changed

subsys/usb/device_next/class/usbd_mtp.c

Lines changed: 122 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ LOG_MODULE_REGISTER(usb_mtp, CONFIG_USBD_MTP_LOG_LEVEL);
1717
#define MTP_OUT_EP_ADDR 0x01 /* Bulk OUT */
1818
#define MTP_INTR_EP_ADDR 0x82 /* Interrupt IN */
1919

20+
/* Single instance is likely enough because it can support multiple LUNs */
21+
#define MTP_NUM_INSTANCES CONFIG_USBD_MTP_INSTANCES_COUNT
22+
2023
#define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */
2124
#define BOLDWHITE "\033[1m\033[35m" /* Bold White */
2225
#define RESET "\033[0m"
@@ -42,15 +45,16 @@ UDC_BUF_POOL_DEFINE(mtp_ep_pool, 3, 512, sizeof(struct udc_buf_info), NULL);
4245

4346
struct mtp_desc {
4447

45-
/* Full Speed Descriptors */
4648
struct usb_if_descriptor if0;
49+
/* Full Speed Descriptors */
4750
struct usb_ep_descriptor if0_out_ep;
4851
struct usb_ep_descriptor if0_in_ep;
4952
struct usb_ep_descriptor if0_int_in_ep;
5053

5154
/* High Speed Descriptors */
5255
struct usb_ep_descriptor if0_hs_out_ep;
5356
struct usb_ep_descriptor if0_hs_in_ep;
57+
struct usb_ep_descriptor if0_hs_int_in_ep;
5458

5559
/* Termination descriptor */
5660
struct usb_desc_header nil_desc;
@@ -60,13 +64,9 @@ struct mtp_data {
6064
struct mtp_desc *const desc;
6165
const struct usb_desc_header **const fs_desc;
6266
const struct usb_desc_header **const hs_desc;
63-
atomic_t state;
67+
struct mtp_context mtp_ctx;
6468
};
6569

66-
struct mtp_device_status {
67-
uint16_t wLength;
68-
uint16_t wCode;
69-
};
7070

7171
static void usbd_mtp_update(struct usbd_class_data *c_data, uint8_t iface, uint8_t alternate)
7272
{
@@ -131,31 +131,33 @@ static int usbd_mtp_control_to_host(struct usbd_class_data *c_data,
131131
const struct usb_setup_packet *const setup,
132132
struct net_buf *const buf)
133133
{
134+
struct mtp_data *data = usbd_class_get_private(c_data);
135+
struct mtp_context *mtp_ctx = &data->mtp_ctx;
136+
134137
LOG_DBG("%s: Class request 0x%x (Recipient: %x)", __func__,
135138
setup->bRequest, setup->RequestType.recipient);
136139

137140
//FIXME: Handle Cancel transaction properly
138-
int ret = mtp_control_handler(setup->bRequest, buf);
139-
if (ret){
140-
usbd_ep_set_halt(usbd_class_get_ctx(c_data), 0x81);
141-
usbd_ep_set_halt(usbd_class_get_ctx(c_data), 0x01);
142-
}
141+
// Reply to host with the status
142+
mtp_control_handler(mtp_ctx, setup->bRequest, buf);
143+
143144
return 0;
144145
}
145146

146147
static int usbd_mtp_control_to_dev(struct usbd_class_data *c_data,
147148
const struct usb_setup_packet *const setup,
148149
const struct net_buf *const buf)
149150
{
151+
struct mtp_data *data = usbd_class_get_private(c_data);
152+
struct mtp_context *mtp_ctx = &data->mtp_ctx;
153+
150154
LOG_WRN("%s: Class request 0x%x (Recipient: %x)", __func__,
151155
setup->bRequest, setup->RequestType.recipient);
152156

153157
//FIXME: Handle Cancel transaction properly
154-
int ret = mtp_control_handler(setup->bRequest, buf);
155-
if (ret){
156-
usbd_ep_set_halt(usbd_class_get_ctx(c_data), 0x81);
157-
usbd_ep_set_halt(usbd_class_get_ctx(c_data), 0x01);
158-
}
158+
// here transaction is canceled without any reply back
159+
mtp_control_handler(mtp_ctx, setup->bRequest, buf);
160+
159161
return 0;
160162
}
161163

@@ -166,6 +168,9 @@ static int usbd_mtp_request_handler(struct usbd_class_data *c_data, struct net_b
166168
LOG_INF("\n\n");
167169
LOG_INF(BOLDWHITE "==[mtp_request_handler]=============Entry============" RESET);
168170

171+
struct mtp_data *data = usbd_class_get_private(c_data);
172+
struct mtp_context *ctx = &data->mtp_ctx;
173+
169174
struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
170175
struct udc_buf_info *bi = (struct udc_buf_info *)net_buf_user_data(buf);
171176
int ret = 0;
@@ -184,7 +189,7 @@ static int usbd_mtp_request_handler(struct usbd_class_data *c_data, struct net_b
184189
return -1;
185190
}
186191

187-
ret = mtp_commands_handler(buf, buf_resp);
192+
ret = mtp_commands_handler(ctx, buf, buf_resp);
188193
if (ret) {
189194
ret = usbd_ep_enqueue(c_data, buf_resp);
190195
if (ret) {
@@ -202,15 +207,12 @@ static int usbd_mtp_request_handler(struct usbd_class_data *c_data, struct net_b
202207
usbd_mtp_enable(c_data);
203208
}
204209

205-
if (mtp_needs_more_data(buf)) {
206-
LOG_INF("Alloc EXTRA Buffer");
207-
}
208210

209211
} else if (bi->ep == mtp_get_bulk_in(c_data)) {
210212
LOG_WRN("Host event EP: %x[%s] (buf %p, len: %u)", bi->ep,
211213
bi->ep == 0x01 ? "MTP_OUT_EP_ADDR" : "MTP_IN_EP_ADDR", buf, buf->len);
212214

213-
if (mtp_packet_pending()) {
215+
if (mtp_packet_pending(ctx)) {
214216
LOG_INF("Sending Pending packet");
215217
buf_resp = mtp_buf_alloc(mtp_get_bulk_in(c_data));
216218
if (buf_resp == NULL) {
@@ -219,7 +221,7 @@ static int usbd_mtp_request_handler(struct usbd_class_data *c_data, struct net_b
219221
return -1;
220222
}
221223

222-
send_pending_packet(buf_resp);
224+
send_pending_packet(ctx, buf_resp);
223225
ret = usbd_ep_enqueue(c_data, buf_resp);
224226
if (ret) {
225227
LOG_ERR("Failed to enqueue net_buf %d", ret);
@@ -283,6 +285,9 @@ static void *usbd_mtp_get_desc(struct usbd_class_data *const c_data, const enum
283285

284286
static int usbd_mtp_init(struct usbd_class_data *c_data)
285287
{
288+
struct mtp_data *data = usbd_class_get_private(c_data);
289+
struct mtp_context *mtp_ctx = &data->mtp_ctx;
290+
286291
LOG_INF("Init class instance %p", c_data);
287292

288293
char *manufacturer, *model, *device_version, *serial_number;
@@ -311,11 +316,94 @@ static int usbd_mtp_init(struct usbd_class_data *c_data)
311316
model,
312317
d_nd->bLength > 0 ? serial_number : "NULL");
313318

314-
mtp_init(manufacturer, model, device_version, serial_number);
319+
mtp_init(mtp_ctx, manufacturer, model, device_version, serial_number);
315320

316321
return 0;
317322
}
318323

324+
#define DEFINE_MTP_DESCRIPTOR(n, _) \
325+
static struct mtp_desc mtp_desc_0 = { \
326+
.if0 = { \
327+
.bLength = sizeof(struct usb_if_descriptor), \
328+
.bDescriptorType = USB_DESC_INTERFACE, \
329+
.bInterfaceNumber = 0x00, \
330+
.bAlternateSetting = 0x00, \
331+
.bNumEndpoints = 0x03, \
332+
.bInterfaceClass = USB_BCC_IMAGE, \
333+
.bInterfaceSubClass = 0x01, /* Still Image Capture */ \
334+
.bInterfaceProtocol = 0x01, /* PTP Protocol */ \
335+
.iInterface = 0x00, \
336+
}, \
337+
.if0_int_in_ep = { \
338+
.bLength = sizeof(struct usb_ep_descriptor), \
339+
.bDescriptorType = USB_DESC_ENDPOINT, \
340+
.bEndpointAddress = MTP_INTR_EP_ADDR, \
341+
.bmAttributes = USB_EP_TYPE_INTERRUPT, \
342+
.wMaxPacketSize = sys_cpu_to_le16(16U), \
343+
.bInterval = 0x06, \
344+
}, \
345+
.if0_in_ep = { \
346+
.bLength = sizeof(struct usb_ep_descriptor), \
347+
.bDescriptorType = USB_DESC_ENDPOINT, \
348+
.bEndpointAddress = MTP_IN_EP_ADDR, \
349+
.bmAttributes = USB_EP_TYPE_BULK, \
350+
.wMaxPacketSize = sys_cpu_to_le16(64U), \
351+
.bInterval = 0x00, \
352+
}, \
353+
.if0_out_ep = { \
354+
.bLength = sizeof(struct usb_ep_descriptor), \
355+
.bDescriptorType = USB_DESC_ENDPOINT, \
356+
.bEndpointAddress = MTP_OUT_EP_ADDR, \
357+
.bmAttributes = USB_EP_TYPE_BULK, \
358+
.wMaxPacketSize = sys_cpu_to_le16(64U), \
359+
.bInterval = 0x00, \
360+
}, \
361+
.if0_hs_in_ep = { \
362+
.bLength = sizeof(struct usb_ep_descriptor), \
363+
.bDescriptorType = USB_DESC_ENDPOINT, \
364+
.bEndpointAddress = MTP_IN_EP_ADDR, \
365+
.bmAttributes = USB_EP_TYPE_BULK, \
366+
.wMaxPacketSize = sys_cpu_to_le16(512U), \
367+
.bInterval = 0x00, \
368+
}, \
369+
.if0_hs_out_ep = { \
370+
.bLength = sizeof(struct usb_ep_descriptor), \
371+
.bDescriptorType = USB_DESC_ENDPOINT, \
372+
.bEndpointAddress = MTP_OUT_EP_ADDR, \
373+
.bmAttributes = USB_EP_TYPE_BULK, \
374+
.wMaxPacketSize = sys_cpu_to_le16(512U), \
375+
.bInterval = 0x00, \
376+
}, \
377+
.if0_hs_int_in_ep = { \
378+
.bLength = sizeof(struct usb_ep_descriptor), \
379+
.bDescriptorType = USB_DESC_ENDPOINT, \
380+
.bEndpointAddress = MTP_INTR_EP_ADDR, \
381+
.bmAttributes = USB_EP_TYPE_INTERRUPT, \
382+
.wMaxPacketSize = sys_cpu_to_le16(16U), \
383+
.bInterval = 0x06, \
384+
}, \
385+
.nil_desc = { \
386+
.bLength = 0, \
387+
.bDescriptorType = 0, \
388+
}, \
389+
}; \
390+
\
391+
const static struct usb_desc_header *mtp_fs_desc_##n[] = { \
392+
(struct usb_desc_header *)&mtp_desc_##n.if0, \
393+
(struct usb_desc_header *)&mtp_desc_##n.if0_in_ep, \
394+
(struct usb_desc_header *)&mtp_desc_##n.if0_out_ep, \
395+
(struct usb_desc_header *)&mtp_desc_##n.if0_int_in_ep, \
396+
(struct usb_desc_header *)&mtp_desc_##n.nil_desc, \
397+
}; \
398+
\
399+
const static struct usb_desc_header *mtp_hs_desc_##n[] = { \
400+
(struct usb_desc_header *)&mtp_desc_##n.if0, \
401+
(struct usb_desc_header *)&mtp_desc_##n.if0_hs_in_ep, \
402+
(struct usb_desc_header *)&mtp_desc_##n.if0_hs_out_ep, \
403+
(struct usb_desc_header *)&mtp_desc_##n.if0_int_in_ep, \
404+
(struct usb_desc_header *)&mtp_desc_##n.nil_desc, \
405+
};
406+
319407
struct usbd_class_api mtp_api = {
320408
.update = usbd_mtp_update,
321409
.control_to_dev = usbd_mtp_control_to_dev,
@@ -327,98 +415,16 @@ struct usbd_class_api mtp_api = {
327415
.init = usbd_mtp_init,
328416
};
329417

330-
static struct mtp_desc mtp_desc_0 = {
331-
.if0 = {
332-
333-
.bLength = sizeof(struct usb_if_descriptor),
334-
.bDescriptorType = USB_DESC_INTERFACE,
335-
.bInterfaceNumber = 0x00,
336-
.bAlternateSetting = 0x00,
337-
.bNumEndpoints = 0x03,
338-
.bInterfaceClass = USB_BCC_IMAGE,
339-
.bInterfaceSubClass = 0x01, /* Still Image Capture */
340-
.bInterfaceProtocol = 0x01, /* Picture Transfer Protocol */
341-
.iInterface = 0x00,
342-
},
343-
344-
.if0_int_in_ep = {
345-
346-
.bLength = sizeof(struct usb_ep_descriptor),
347-
.bDescriptorType = USB_DESC_ENDPOINT,
348-
.bEndpointAddress = MTP_INTR_EP_ADDR,
349-
.bmAttributes = USB_EP_TYPE_INTERRUPT,
350-
.wMaxPacketSize = sys_cpu_to_le16(16U),
351-
.bInterval = 0x06,
352-
},
353-
354-
/* Full Speed*/
355-
.if0_in_ep = {
356-
357-
.bLength = sizeof(struct usb_ep_descriptor),
358-
.bDescriptorType = USB_DESC_ENDPOINT,
359-
.bEndpointAddress = MTP_IN_EP_ADDR,
360-
.bmAttributes = USB_EP_TYPE_BULK,
361-
.wMaxPacketSize = sys_cpu_to_le16(64U),
362-
.bInterval = 0x00,
363-
},
364-
365-
.if0_out_ep = {
366-
367-
.bLength = sizeof(struct usb_ep_descriptor),
368-
.bDescriptorType = USB_DESC_ENDPOINT,
369-
.bEndpointAddress = MTP_OUT_EP_ADDR,
370-
.bmAttributes = USB_EP_TYPE_BULK,
371-
.wMaxPacketSize = sys_cpu_to_le16(64U),
372-
.bInterval = 0x00,
373-
},
374-
375-
/* High Speed */
376-
.if0_hs_in_ep = {
377-
378-
.bLength = sizeof(struct usb_ep_descriptor),
379-
.bDescriptorType = USB_DESC_ENDPOINT,
380-
.bEndpointAddress = MTP_IN_EP_ADDR,
381-
.bmAttributes = USB_EP_TYPE_BULK,
382-
.wMaxPacketSize = sys_cpu_to_le16(512U),
383-
.bInterval = 0x00,
384-
},
385-
386-
.if0_hs_out_ep = {
387-
388-
.bLength = sizeof(struct usb_ep_descriptor),
389-
.bDescriptorType = USB_DESC_ENDPOINT,
390-
.bEndpointAddress = MTP_OUT_EP_ADDR,
391-
.bmAttributes = USB_EP_TYPE_BULK,
392-
.wMaxPacketSize = sys_cpu_to_le16(512U),
393-
.bInterval = 0x00,
394-
},
395-
396-
.nil_desc = {
397-
398-
.bLength = 0,
399-
.bDescriptorType = 0,
400-
},
401-
};
402-
403-
const static struct usb_desc_header *mtp_fs_desc_0[] = {
404-
(struct usb_desc_header *)&mtp_desc_0.if0,
405-
(struct usb_desc_header *)&mtp_desc_0.if0_in_ep,
406-
(struct usb_desc_header *)&mtp_desc_0.if0_out_ep,
407-
(struct usb_desc_header *)&mtp_desc_0.if0_int_in_ep,
408-
(struct usb_desc_header *)&mtp_desc_0.nil_desc,
409-
};
410-
const static struct usb_desc_header *mtp_hs_desc_0[] = {
411-
(struct usb_desc_header *)&mtp_desc_0.if0,
412-
(struct usb_desc_header *)&mtp_desc_0.if0_hs_in_ep,
413-
(struct usb_desc_header *)&mtp_desc_0.if0_hs_out_ep,
414-
(struct usb_desc_header *)&mtp_desc_0.if0_int_in_ep,
415-
(struct usb_desc_header *)&mtp_desc_0.nil_desc,
416-
};
417418

418-
static struct mtp_data mtp_data0 = {
419-
.desc = &mtp_desc_0,
420-
.fs_desc = mtp_fs_desc_0,
421-
.hs_desc = mtp_hs_desc_0,
422-
};
419+
#define DEFINE_MTP_CLASS_DATA(x, _) \
420+
static struct mtp_data mtp_data_##x = { \
421+
.desc = &mtp_desc_##x, \
422+
.fs_desc = mtp_fs_desc_##x, \
423+
.hs_desc = mtp_hs_desc_##x, \
424+
}; \
425+
\
426+
USBD_DEFINE_CLASS(mtp_##x, &mtp_api, &mtp_data_##x, \
427+
NULL);
423428

424-
USBD_DEFINE_CLASS(mtp, &mtp_api, &mtp_data0, NULL);
429+
LISTIFY(MTP_NUM_INSTANCES, DEFINE_MTP_DESCRIPTOR, ())
430+
LISTIFY(MTP_NUM_INSTANCES, DEFINE_MTP_CLASS_DATA, ())

0 commit comments

Comments
 (0)