Skip to content

Commit cc76c06

Browse files
P33MPhil Elwell
authored and
Phil Elwell
committed
dwc_otg: use align_buf for small IN control transfers (#3150)
The hardware will do a 4-byte write to memory on any IN packet received that is between 1 and 3 bytes long. This tramples memory in the uvcvideo driver, as it uses a sequence of 1- and 2-byte control transfers to query the min/max/range/step of each individual camera control and gives us buffers that are offsets into a struct. Catch small control transfers in the data phase and use the align_buf to bounce the correct number of bytes into the URB's buffer. In general, short packets on non-control endpoints should be OK as URBs should have enough buffer space for a wMaxPacket size transfer. See: #3148 Signed-off-by: Jonathan Bell <[email protected]>
1 parent ff0589a commit cc76c06

File tree

1 file changed

+18
-0
lines changed

1 file changed

+18
-0
lines changed

drivers/usb/host/dwc_otg/dwc_otg_hcd.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,6 +1182,7 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
11821182
dwc_otg_qtd_t *qtd;
11831183
dwc_otg_hcd_urb_t *urb;
11841184
void* ptr = NULL;
1185+
uint16_t wLength;
11851186
uint32_t intr_enable;
11861187
unsigned long flags;
11871188
gintmsk_data_t gintmsk = { .d32 = 0, };
@@ -1293,6 +1294,23 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
12931294
break;
12941295
case DWC_OTG_CONTROL_DATA:
12951296
DWC_DEBUGPL(DBG_HCDV, " Control data transaction\n");
1297+
/*
1298+
* Hardware bug: small IN packets with length < 4
1299+
* cause a 4-byte write to memory. We can only catch
1300+
* the case where we know a short packet is going to be
1301+
* returned in a control transfer, as the length is
1302+
* specified in the setup packet. This is only an issue
1303+
* for drivers that insist on packing a device's various
1304+
* properties into a struct and querying them one at a
1305+
* time (uvcvideo).
1306+
* Force the use of align_buf so that the subsequent
1307+
* memcpy puts the right number of bytes in the URB's
1308+
* buffer.
1309+
*/
1310+
wLength = ((uint16_t *)urb->setup_packet)[3];
1311+
if (hc->ep_is_in && wLength < 4)
1312+
ptr = hc->xfer_buff;
1313+
12961314
hc->data_pid_start = qtd->data_toggle;
12971315
break;
12981316
case DWC_OTG_CONTROL_STATUS:

0 commit comments

Comments
 (0)