You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
During development of a USB serial port for Stabilizer, I noted that the same code I had used on another project was not enumerating properly on Windows.
Debugging indicated that the issue was timing related, so I added tracing information to usb-device to track the internal state machine. I discovered the following trace:
INFO - Suspend
INFO - Reset
INFO - Data { ep_out: 0, ep_in_complete: 0, ep_setup: 1 }
INFO - Initial ControlPipe State: Idle
INFO - Setup Req: Request { direction: In, request_type: Standard, recipient: Device, request: 6, value: 256, index: 0, length: 64 }
INFO - Writing 8 bytes: [18, 1, 16, 2, 2, 0, 0, 8]
INFO - Final ControlPipe State: DataIn
INFO - Data { ep_out: 0, ep_in_complete: 1, ep_setup: 0 }
INFO - HandleIn ControlState: DataIn
INFO - Writing 8 bytes: [18, 1, 16, 2, 2, 0, 0, 8]
INFO - Initial ControlPipe State: DataIn
INFO - Final ControlPipe State: DataIn
INFO - Data { ep_out: 1, ep_in_complete: 1, ep_setup: 0 }
INFO - HandleIn ControlState: DataIn
INFO - Writing 2 bytes: [18, 1]
INFO - Initial ControlPipe State: DataInLast
INFO - HandleOut ControlState: DataInLast
INFO - Final ControlPipe State: Idle
INFO - Data { ep_out: 0, ep_in_complete: 1, ep_setup: 0 }
INFO - HandleIn ControlState: Idle
INFO - Initial ControlPipe State: Error
INFO - Final ControlPipe State: Error
INFO - Initial ControlPipe State: Error
INFO - Reset
INFO - Data { ep_out: 0, ep_in_complete: 0, ep_setup: 1 }
INFO - Initial ControlPipe State: Idle
INFO - Setup Req: Request { direction: In, request_type: Standard, recipient: Device, request: 6, value: 256, index: 0, length: 64 }
INFO - Writing 8 bytes: [18, 1, 16, 2, 2, 0, 0, 8]
INFO - Final ControlPipe State: DataIn
INFO - Data { ep_out: 1, ep_in_complete: 1, ep_setup: 0 }
INFO - HandleIn ControlState: DataIn
INFO - Writing 8 bytes: [18, 1, 16, 2, 2, 0, 0, 8]
INFO - Initial ControlPipe State: DataIn
INFO - HandleOut ControlState: DataIn
INFO - Final ControlPipe State: Idle
INFO - Data { ep_out: 0, ep_in_complete: 1, ep_setup: 0 }
INFO - HandleIn ControlState: Idle
INFO - Initial ControlPipe State: Error
INFO - Final ControlPipe State: Error
INFO - Data { ep_out: 0, ep_in_complete: 0, ep_setup: 1 }
INFO - Initial ControlPipe State: Error
INFO - Setup Req: Request { direction: Out, request_type: Standard, recipient: Device, request: 5, value: 53, index: 0, length: 0 }
INFO - Final ControlPipe State: StatusIn
INFO - Reset
INFO - Data { ep_out: 0, ep_in_complete: 0, ep_setup: 1 }
INFO - Initial ControlPipe State: Idle
INFO - Setup Req: Request { direction: In, request_type: Standard, recipient: Device, request: 6, value: 256, index: 0, length: 64 }
INFO - Writing 8 bytes: [18, 1, 16, 2, 2, 0, 0, 8]
INFO - Final ControlPipe State: DataIn
INFO - Data { ep_out: 1, ep_in_complete: 1, ep_setup: 0 }
INFO - HandleIn ControlState: DataIn
INFO - Writing 8 bytes: [18, 1, 16, 2, 2, 0, 0, 8]
INFO - Initial ControlPipe State: DataIn
INFO - HandleOut ControlState: DataIn
INFO - Final ControlPipe State: Idle
INFO - Data { ep_out: 0, ep_in_complete: 1, ep_setup: 0 }
INFO - HandleIn ControlState: Idle
INFO - Initial ControlPipe State: Error
INFO - Final ControlPipe State: Error
INFO - Data { ep_out: 0, ep_in_complete: 0, ep_setup: 1 }
INFO - Initial ControlPipe State: Error
INFO - Setup Req: Request { direction: Out, request_type: Standard, recipient: Device, request: 5, value: 54, index: 0, length: 0 }
INFO - Reset
INFO - Data { ep_out: 0, ep_in_complete: 0, ep_setup: 1 }
INFO - Setup Req: Request { direction: In, request_type: Standard, recipient: Device, request: 6, value: 256, index: 0, length: 64 }
INFO - Writing 8 bytes: [18, 1, 16, 2, 2, 0, 0, 8]
INFO - Final ControlPipe State: DataIn
INFO - Data { ep_out: 1, ep_in_complete: 1, ep_setup: 0 }
INFO - HandleIn ControlState: DataIn
INFO - Writing 8 bytes: [18, 1, 16, 2, 2, 0, 0, 8]
INFO - Initial ControlPipe State: DataIn
INFO - HandleOut ControlState: DataIn
INFO - Final ControlPipe State: Idle
INFO - Data { ep_out: 0, ep_in_complete: 1, ep_setup: 0 }
INFO - HandleIn ControlState: Idle
INFO - Initial ControlPipe State: Error
INFO - Final ControlPipe State: Error
INFO - Data { ep_out: 0, ep_in_complete: 0, ep_setup: 1 }
INFO - Initial ControlPipe State: Error
INFO - Setup Req: Request { direction: Out, request_type: Standard, recipient: Device, request: 5, value: 55, index: 0, length: 0 }
INFO - Final ControlPipe State: StatusIn
INFO - Suspend
The most important portion appears to be:
INFO - Data { ep_out: 0, ep_in_complete: 0, ep_setup: 1 }
INFO - Initial ControlPipe State: Idle
INFO - Setup Req: Request { direction: In, request_type: Standard, recipient: Device, request: 6, value: 256, index: 0, length: 64 }
INFO - Writing 8 bytes: [18, 1, 16, 2, 2, 0, 0, 8]
INFO - Final ControlPipe State: DataIn
INFO - Data { ep_out: 0, ep_in_complete: 1, ep_setup: 0 }
INFO - HandleIn ControlState: DataIn
INFO - Writing 8 bytes: [18, 1, 16, 2, 2, 0, 0, 8]
INFO - Initial ControlPipe State: DataIn
INFO - Final ControlPipe State: DataIn
INFO - Data { ep_out: 1, ep_in_complete: 1, ep_setup: 0 }
INFO - HandleIn ControlState: DataIn
INFO - Writing 2 bytes: [18, 1]
INFO - Initial ControlPipe State: DataInLast
INFO - HandleOut ControlState: DataInLast
INFO - Final ControlPipe State: Idle
INFO - Data { ep_out: 0, ep_in_complete: 1, ep_setup: 0 }
INFO - HandleIn ControlState: Idle
INFO - Initial ControlPipe State: Error
INFO - Final ControlPipe State: Error
INFO - Initial ControlPipe State: Error
INFO - Reset
Specifically, it looks like, as the EP0-IN is sending the last portion of data in the descriptor response, it simultaneously has received an EP0-OUT packet (zero length in this case). This causes the state machine to internall transition to Idle while the control pipe has just enqueued an EP0-IN buffer.
Then, later once the EP0-IN transfer completes, an ep_in_complete bit is set and processed. However, the internal state machine has already transitioned to Idle, so this is interpretted as a spurious IN token when it actually represents acknowledgement of the completed IN transfer.
I believe we should just update the library to ignore ep_in_complete if we're already in the IDLE state, as we may have aborted out of a previous transfer.
The text was updated successfully, but these errors were encountered:
During development of a USB serial port for Stabilizer, I noted that the same code I had used on another project was not enumerating properly on Windows.
Debugging indicated that the issue was timing related, so I added tracing information to
usb-device
to track the internal state machine. I discovered the following trace:The most important portion appears to be:
Specifically, it looks like, as the EP0-IN is sending the last portion of data in the descriptor response, it simultaneously has received an EP0-OUT packet (zero length in this case). This causes the state machine to internall transition to
Idle
while the control pipe has just enqueued an EP0-IN buffer.Then, later once the EP0-IN transfer completes, an
ep_in_complete
bit is set and processed. However, the internal state machine has already transitioned toIdle
, so this is interpretted as a spuriousIN
token when it actually represents acknowledgement of the completed IN transfer.I believe we should just update the library to ignore
ep_in_complete
if we're already in the IDLE state, as we may have aborted out of a previous transfer.The text was updated successfully, but these errors were encountered: