Skip to content

Commit 06840af

Browse files
jfischer-noMaureenHelm
authored andcommitted
drivers: usb: kinetis: fixup endpoint config, stall and read
This patch fixes some bugs found during testing with testusb from linux kernel. An unresolved issue is that the stack is not fast enough to stall (if necessary) the control endpoint during Setup Stage. This might require a API change so that the usb device stack can explicit allow the driver to resume token processing. Signed-off-by: Johann Fischer <j.fischer@phytec.de>
1 parent 36eb4dd commit 06840af

File tree

1 file changed

+87
-11
lines changed

1 file changed

+87
-11
lines changed

drivers/usb/device/usb_dc_kinetis.c

Lines changed: 87 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ struct usb_ep_ctrl_data {
9292
u16_t out_data1 : 1;
9393
u16_t in_odd : 1;
9494
u16_t out_odd : 1;
95+
u16_t in_stalled : 1;
96+
u16_t out_stalled : 1;
9597
} status;
9698
u16_t mps_in;
9799
u16_t mps_out;
@@ -279,6 +281,13 @@ int usb_dc_ep_configure(const struct usb_dc_ep_cfg_data * const cfg)
279281
return -EINVAL;
280282
}
281283

284+
if (ep_idx && (dev_data.ep_ctrl[ep_idx].status.in_enabled ||
285+
dev_data.ep_ctrl[ep_idx].status.out_enabled)) {
286+
SYS_LOG_WRN("endpoint already configured");
287+
return -EBUSY;
288+
}
289+
290+
282291
SYS_LOG_DBG("ep %x, mps %d, type %d",
283292
cfg->ep_addr,
284293
cfg->ep_mps,
@@ -355,30 +364,63 @@ int usb_dc_ep_configure(const struct usb_dc_ep_cfg_data * const cfg)
355364
int usb_dc_ep_set_stall(const u8_t ep)
356365
{
357366
u8_t ep_idx = EP_ADDR2IDX(ep);
367+
u8_t bd_idx;
358368

359369
if (ep_idx > NUM_OF_EP_MAX) {
360370
SYS_LOG_ERR("Wrong endpoint index/address");
361371
return -EINVAL;
362372
}
363373

364-
SYS_LOG_DBG("ep %x, idx %d", ep_idx, ep);
365-
USB0->ENDPOINT[ep_idx].ENDPT |= USB_ENDPT_EPSTALL_MASK;
374+
SYS_LOG_DBG("ep %x, idx %d", ep, ep_idx);
375+
376+
if (EP_ADDR2DIR(ep) == USB_EP_DIR_OUT) {
377+
dev_data.ep_ctrl[ep_idx].status.out_stalled = 1;
378+
bd_idx = get_bdt_idx(ep,
379+
~dev_data.ep_ctrl[ep_idx].status.out_odd);
380+
} else {
381+
dev_data.ep_ctrl[ep_idx].status.in_stalled = 1;
382+
bd_idx = get_bdt_idx(ep,
383+
dev_data.ep_ctrl[ep_idx].status.in_odd);
384+
}
385+
386+
bdt[bd_idx].set.bd_ctrl = BD_STALL_MASK | BD_DTS_MASK | BD_OWN_MASK;
366387

367388
return 0;
368389
}
369390

370391
int usb_dc_ep_clear_stall(const u8_t ep)
371392
{
372393
u8_t ep_idx = EP_ADDR2IDX(ep);
394+
u8_t bd_idx;
373395

374396
if (ep_idx > NUM_OF_EP_MAX) {
375397
SYS_LOG_ERR("Wrong endpoint index/address");
376398
return -EINVAL;
377399
}
378400

379-
SYS_LOG_DBG("ep %x, idx %d", ep_idx, ep);
401+
SYS_LOG_DBG("ep %x, idx %d", ep, ep_idx);
380402
USB0->ENDPOINT[ep_idx].ENDPT &= ~USB_ENDPT_EPSTALL_MASK;
381403

404+
if (EP_ADDR2DIR(ep) == USB_EP_DIR_OUT) {
405+
dev_data.ep_ctrl[ep_idx].status.out_stalled = 0;
406+
dev_data.ep_ctrl[ep_idx].status.out_data1 = false;
407+
bd_idx = get_bdt_idx(ep,
408+
~dev_data.ep_ctrl[ep_idx].status.out_odd);
409+
bdt[bd_idx].set.bd_ctrl = 0;
410+
bdt[bd_idx].set.bd_ctrl = BD_DTS_MASK | BD_OWN_MASK;
411+
} else {
412+
dev_data.ep_ctrl[ep_idx].status.in_stalled = 0;
413+
dev_data.ep_ctrl[ep_idx].status.in_data1 = false;
414+
bd_idx = get_bdt_idx(ep,
415+
dev_data.ep_ctrl[ep_idx].status.in_odd);
416+
bdt[bd_idx].set.bd_ctrl = 0;
417+
}
418+
419+
/* Resume TX token processing, see USBx_CTL field descriptions */
420+
if (ep == 0) {
421+
USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
422+
}
423+
382424
return 0;
383425
}
384426

@@ -397,8 +439,20 @@ int usb_dc_ep_is_stalled(const u8_t ep, u8_t *const stalled)
397439
}
398440

399441
*stalled = 0;
400-
if (USB0->ENDPOINT[ep_idx].ENDPT & USB_ENDPT_EPSTALL_MASK) {
401-
*stalled = 1;
442+
if (EP_ADDR2DIR(ep) == USB_EP_DIR_OUT) {
443+
*stalled = dev_data.ep_ctrl[ep_idx].status.out_stalled;
444+
} else {
445+
*stalled = dev_data.ep_ctrl[ep_idx].status.in_stalled;
446+
}
447+
448+
if (SYS_LOG_LEVEL == SYS_LOG_LEVEL_INFO) {
449+
u8_t bd_idx = get_bdt_idx(ep,
450+
dev_data.ep_ctrl[ep_idx].status.in_odd);
451+
bd_idx = bd_idx;
452+
SYS_LOG_WRN("active bd ctrl: %x", bdt[bd_idx].set.bd_ctrl);
453+
bd_idx = get_bdt_idx(ep,
454+
~dev_data.ep_ctrl[ep_idx].status.in_odd);
455+
SYS_LOG_WRN("next bd ctrl: %x", bdt[bd_idx].set.bd_ctrl);
402456
}
403457

404458
return 0;
@@ -420,16 +474,24 @@ int usb_dc_ep_enable(const u8_t ep)
420474
return -EINVAL;
421475
}
422476

477+
if (ep_idx && (dev_data.ep_ctrl[ep_idx].status.in_enabled ||
478+
dev_data.ep_ctrl[ep_idx].status.out_enabled)) {
479+
SYS_LOG_WRN("endpoint 0x%x already enabled", ep);
480+
return -EBUSY;
481+
}
482+
423483
if (EP_ADDR2DIR(ep) == USB_EP_DIR_OUT) {
424484
bdt[idx_even].set.bd_ctrl = BD_DTS_MASK | BD_OWN_MASK;
425485
bdt[idx_odd].set.bd_ctrl = 0;
426486
dev_data.ep_ctrl[ep_idx].status.out_odd = 0;
487+
dev_data.ep_ctrl[ep_idx].status.out_stalled = 0;
427488
dev_data.ep_ctrl[ep_idx].status.out_data1 = false;
428489
dev_data.ep_ctrl[ep_idx].status.out_enabled = true;
429490
} else {
430491
bdt[idx_even].bd_fields = 0;
431492
bdt[idx_odd].bd_fields = 0;
432493
dev_data.ep_ctrl[ep_idx].status.in_odd = 0;
494+
dev_data.ep_ctrl[ep_idx].status.in_stalled = 0;
433495
dev_data.ep_ctrl[ep_idx].status.in_data1 = false;
434496
dev_data.ep_ctrl[ep_idx].status.in_enabled = true;
435497
}
@@ -496,6 +558,11 @@ int usb_dc_ep_write(const u8_t ep, const u8_t *const data,
496558
return -EINVAL;
497559
}
498560

561+
if (dev_data.ep_ctrl[ep_idx].status.in_stalled) {
562+
SYS_LOG_WRN("endpoint is stalled");
563+
return -EBUSY;
564+
}
565+
499566
while (bdt[bd_idx].get.own) {
500567
SYS_LOG_DBG("ep 0x%x is busy", ep);
501568
k_yield();
@@ -554,6 +621,11 @@ int usb_dc_ep_read_wait(u8_t ep, u8_t *data, u32_t max_data_len,
554621
return -EINVAL;
555622
}
556623

624+
if (dev_data.ep_ctrl[ep_idx].status.out_stalled) {
625+
SYS_LOG_WRN("endpoint is stalled");
626+
return -EBUSY;
627+
}
628+
557629
/* Allow to read 0 bytes */
558630
if (!data && max_data_len) {
559631
SYS_LOG_ERR("Wrong arguments");
@@ -629,7 +701,7 @@ int usb_dc_ep_read_continue(u8_t ep)
629701
bdt[bd_idx].set.bd_ctrl = BD_DTS_MASK | BD_OWN_MASK;
630702
}
631703

632-
/* Resume TX toke processing, see USBx_CTL field descriptions */
704+
/* Resume TX token processing, see USBx_CTL field descriptions */
633705
if (ep_idx == 0) {
634706
USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
635707
}
@@ -642,8 +714,10 @@ int usb_dc_ep_read_continue(u8_t ep)
642714
int usb_dc_ep_read(const u8_t ep, u8_t *const data,
643715
const u32_t max_data_len, u32_t *const read_bytes)
644716
{
645-
if (usb_dc_ep_read_wait(ep, data, max_data_len, read_bytes) != 0) {
646-
return -EINVAL;
717+
int retval = usb_dc_ep_read_wait(ep, data, max_data_len, read_bytes);
718+
719+
if (retval) {
720+
return retval;
647721
}
648722

649723
if (!data && !max_data_len) {
@@ -745,9 +819,11 @@ static void usb_kinetis_isr_handler(void)
745819
}
746820

747821
if (istatus & USB_ISTAT_STALL_MASK) {
748-
if (istatus & USB_ISTAT_STALL_MASK) {
749-
/* STALL handshake was sent, unset STALL for EP0. */
750-
USB0->ENDPOINT[0].ENDPT &= ~USB_ENDPT_EPSTALL_MASK;
822+
if (dev_data.ep_ctrl[0].status.out_stalled) {
823+
usb_dc_ep_clear_stall(0);
824+
}
825+
if (dev_data.ep_ctrl[0].status.in_stalled) {
826+
usb_dc_ep_clear_stall(0x80);
751827
}
752828
}
753829

0 commit comments

Comments
 (0)