USB Bulk Transfer Timeout: High-Speed, Full-Speed, STALL, NAK, Device Firmware 지연 디버깅

USB bulk transfer는 고정 timing보다 정확성이 더 중요할 때 사용됩니다. storage device, serial adapter, debug probe, firmware updater, scanner, vendor-specific device, 그리고 많은 data-acquisition 제품이 bulk endpoint를 사용합니다.

usb bulk transfer timeout, usb bulk endpoint, usb high speed, usb full speed, endpoint stall, usb diagnostics

USB bulk transfer는 고정 timing보다 정확성이 더 중요할 때 사용됩니다. storage device, serial adapter, debug probe, firmware updater, scanner, vendor-specific device, 그리고 많은 data-acquisition 제품이 bulk endpoint를 사용합니다. 실패하면 사용자는 "USB bulk transfer timeout", "bulk endpoint stalled", "USB read timeout", "USB write timeout", "libusb bulk transfer failed", "bulk transfer 중 USB device 응답 없음" 같은 표현을 검색합니다.

application은 보통 timeout이나 I/O error만 봅니다. 하지만 bus는 더 많은 이야기를 들려줄 수 있습니다. device가 너무 오래 NAK했거나, endpoint가 stalled 되었거나, host가 retry했거나, device가 reset되었거나, transfer size가 틀렸거나, device speed가 예상보다 낮았거나, firmware가 data 준비 중 block되었을 수 있습니다.

Bus Scope가 유용한 이유는 bulk transfer 실패에는 application stack trace가 아니라 endpoint-level 증거가 필요하기 때문입니다.

Bulk transfer가 잘하는 일

Bulk transfer는 USB protocol 수준에서 reliable합니다. 사용 가능한 bandwidth를 쓰고 retry할 수 있습니다. latency보다 correctness가 중요한 대용량 data movement에 적합합니다.

대표적인 bulk device는 다음과 같습니다.

  • USB mass storage
  • CDC serial adapter
  • Vendor-specific firmware tool
  • Debug probe
  • Measurement device
  • Printer와 scanner
  • 일부 capture device
  • FPGA 또는 microcontroller data pipe

bulk transfer는 남는 bus bandwidth를 사용하므로 다른 USB 트래픽과 host scheduling에 따라 성능이 달라질 수 있습니다.

Timeout이 항상 packet loss를 뜻하지는 않습니다

bulk transfer timeout은 보통 host-side request가 application timeout 안에 완료되지 않았다는 뜻입니다. USB bus가 합법적으로 동작하고 있어도 발생할 수 있습니다.

원인은 다음과 같습니다.

  • device에 준비된 data가 없어 계속 NAK함.
  • firmware가 바빠 응답을 지연함.
  • STALL 이후 endpoint가 halt 상태임.
  • host가 잘못된 endpoint로 request를 보냄.
  • transfer size가 protocol expectation과 맞지 않음.
  • device가 reset되었거나 disconnect됨.
  • driver가 transfer를 올바르게 submit하지 않음.
  • full-speed 경로가 기대 throughput에 비해 너무 느림.
  • 다른 device가 bus bandwidth를 소비함.
  • application timeout이 지나치게 공격적으로 설정됨.

trace는 이 중 무엇이 그럴듯한지 보여줘야 합니다.

NAK 동작

USB device는 일시적으로 준비되지 않았음을 알리기 위해 NAK로 응답할 수 있습니다. NAK는 반드시 error가 아닙니다. flow-control signal입니다.

bulk IN endpoint에서 반복 NAK는 device에 아직 data가 없다는 뜻일 수 있습니다. bulk OUT endpoint에서 NAK는 device가 더 많은 data를 받을 수 없다는 뜻일 수 있습니다.

문제는 지속 시간과 context입니다. NAK 몇 번은 정상입니다. application timeout까지 계속되는 NAK는 device가 끝내 준비되지 않았거나 host가 잘못된 시점에 data를 기대했다는 뜻입니다.

STALL과 endpoint halt

STALL은 NAK와 다릅니다. 보통 endpoint가 halt되었거나 해당 context에서 request가 지원되지 않는다는 뜻입니다. recovery에는 다음이 필요한 경우가 많습니다.

CLEAR_FEATURE(ENDPOINT_HALT)

host가 halt를 clear하지 않으면 이후 transfer가 계속 실패할 수 있습니다. endpoint가 clear 직후 다시 stall된다면 device firmware가 command sequence를 거부하는 것일 수 있습니다.

확인할 것:

  • timeout 전에 처음 나타난 STALL.
  • CLEAR_FEATURE(ENDPOINT_HALT).
  • clear 이후 transfer가 재개되는지 여부.
  • 같은 command가 매번 STALL을 유발하는지 여부.
  • 반복 STALL 이후 reset.

High-speed vs full-speed 기대치

USB speed는 현실적인 throughput을 바꿉니다. full-speed로 동작하는 device는 high-speed throughput을 낼 수 없습니다. high-speed capable device라도 cable, hub, port, signal integrity, device negotiation 때문에 fallback될 수 있습니다.

application이 high-speed 성능을 가정했는데 device가 full-speed로 enumeration되었다면, 큰 transfer에서 timeout이 나타날 수 있습니다.

descriptor, negotiated speed, endpoint max packet size, 실제 transfer pacing을 확인하세요. connector 모양이나 marketing label만 보고 speed를 추정하지 마세요.

firmware command protocol 확인

많은 bulk device는 USB 위에 command/response protocol을 구현합니다. host는 bulk OUT으로 command를 쓰고 bulk IN에서 data를 기다립니다.

timeout은 다음 경우에 발생합니다.

  • command format이 틀림.
  • device가 bulk transfer 전에 control request를 기대함.
  • device가 다른 endpoint로 status를 보냄.
  • host가 너무 빨리 read함.
  • host가 너무 많이 read함.
  • firmware가 command 처리 중 block됨.
  • device가 zero-length packet boundary를 요구함.
  • 이전 error state가 clear되지 않음.

packet 증거는 device가 command를 무시했는지, stall했는지, 받아들였지만 응답하지 않았는지, 아니면 다른 endpoint로 응답했는지 보여줄 수 있습니다.

Bulk transfer size와 short packet

USB bulk protocol은 transfer 종료를 알리기 위해 short packet을 자주 사용합니다. host가 fixed length를 기대하는데 device가 short packet을 보내면 application이 결과를 잘못 해석할 수 있습니다. device가 이미 transfer를 끝냈는데 host가 더 많은 data를 기다리면 application layer에서 timeout이 발생할 수 있습니다.

확인할 것:

  • 요청된 transfer length.
  • 실제 반환된 length.
  • Short packet.
  • Zero-length packet.
  • USB 위의 protocol framing.

custom firmware와 libusb 기반 tool에서는 특히 중요합니다.

디버그 체크리스트

다음 process를 사용하세요.

  1. enumeration과 endpoint descriptor를 capture합니다.
  2. device speed와 endpoint max packet size를 확인합니다.
  3. bulk IN 및 bulk OUT endpoint를 식별합니다.
  4. timeout되는 command 또는 transfer를 capture합니다.
  5. endpoint가 NAK, STALL, data, disconnect 중 무엇을 반환하는지 확인합니다.
  6. STALL이 발생하면 CLEAR_FEATURE(ENDPOINT_HALT) recovery를 inspect합니다.
  7. requested length와 actual length를 비교합니다.
  8. device가 short packet 또는 zero-length packet을 보내는지 확인합니다.
  9. direct port vs hub, high-speed vs full-speed 경로를 비교합니다.
  10. 가능하면 firmware log와 연관 지어 봅니다.

최종 진단

USB bulk transfer timeout은 하나의 버그가 아닙니다. 정상적인 NAK 동작이 application timeout을 넘었거나, endpoint STALL이 recovery되지 않았거나, firmware가 응답하지 않았거나, speed가 예상보다 낮았거나, protocol framing이 틀렸거나, device가 reset되었다는 뜻일 수 있습니다.

Bus Scope는 endpoint-level sequence를 노출해 timeout을 generic I/O failure가 아니라 진단 가능한 USB 증거로 바꿉니다.

<!-- bus-scope-localized-transaction-foundation-v1:start -->

“USB Bulk Transfer Timeout: High-Speed, Full-Speed, STALL, NAK, Device Firmware 지연 디버깅”의 USB 계약 시험

직접적인 답은 STALL, timeout, reset 하나만으로 원인을 설명할 수 없다는 것입니다. 먼저 capture provider가 올바른 device를 보는지 증명하고 transfer 계약을 읽습니다. 종류, 방향, recipient, wValue, wIndex, 선언 길이, 실제 길이, status, 전후 상태를 확인하고 known-good과 처음 달라지는 transaction에 결론을 연결합니다.

경계 비교 근거 판단
platform provider, 권한, Root Hub, usbmon/XHC20 올바른 연결의 record인가
setup bmRequestType, bRequest, wValue, wIndex, wLength host가 의도한 요청을 보냈는가
data 방향, 길이, 보존 bytes payload가 계약과 맞는가
status ACK, STALL, timeout, cancellation transaction이 어디서 끝났는가
state configuration, interface, alternate setting, halt device가 요청을 받을 상태인가

reset과 enumeration 전부터 capture하여 descriptor, SET_CONFIGURATION, SET_INTERFACE, 실패 직전 command를 남깁니다. 좁은 endpoint filter는 결정적인 control transfer를 숨길 수 있습니다. 시험 한 번에는 문서화한 USB 동작 하나만 수행하고 firmware, driver, port, cable, host command, timing 중 하나만 바꿉니다.

인용 가능한 답

관찰한 request, setup field, 응답, 직전 상태를 쓰고 한 변수만 바꾸는 다음 시험을 제시합니다. retention 때문에 보존되지 않은 bytes는 packet loss 증명이 아닙니다. command와 reset의 시간적 근접은 상관관계이며 상태 전환이나 반복 없이 원인으로 단정할 수 없습니다.

VID/PID, firmware, speed, topology, provider, filter, trigger를 고정하고 usbmon과 USBPcap의 frame number 대신 USB 의미 단계로 비교합니다. 시작·종료, 버전, OS, 연결 위치, checksum을 기록하고 Bus Scope 문제 해결에서 검토합니다.

Semrush owner는 분리합니다. free USB analyzer제품 페이지, best USB protocol analyzer비교 페이지, USB descriptor viewerdescriptor 안내가 담당합니다. 이 지원 글에 확인되지 않은 검색량이나 KD를 만들지 않습니다.

<!-- bus-scope-localized-transaction-foundation-v1:end --><!-- bus-scope-localized-evidence-verdicts-v1:start -->

USB 캡처에서 검증 가능한 판정까지

“USB Bulk Transfer Timeout: High-Speed, Full-Speed, STALL, NAK, Device Firmware 지연 디버깅”에서는 오류 이름이 아니라 증명 가능한 경계부터 확인합니다. 첫 경계는 올바른 connection, bus, port, VID/PID, speed, topology입니다. 둘째는 의도한 control, bulk, interrupt transfer이고, 셋째는 그 이후 device state이며, 넷째는 재현성입니다. 첫 경계의 증거가 없으면 뒤의 records는 대상 device를 설명하지 못합니다.

1. 캡처 지점을 증명하기

OS, provider, 권한, controller 또는 Root Hub, 물리 port를 기록합니다. Linux에서는 재연결 뒤 device가 나타난 bus와 usbmon instance가 같아야 합니다. Windows에서는 USBPcap Root Hub를 Device Manager 연결과 대조합니다. 파일에 records가 있어도 keyboard, hub, 오래된 device instance의 트래픽일 수 있습니다.

reconnect나 reset 전에 capture를 시작합니다. 기준 구간에는 descriptor requests, 선택된 configuration, 필요한 SET_INTERFACE, 첫 application transfer가 들어가야 합니다. 증상 뒤에 시작하면 endpoint가 한 번도 활성화되지 않았는지 나중에 멈췄는지 구분할 수 없습니다. 시작과 종료, 파일 이름, checksum, firmware, driver, cable, port를 남깁니다.

2. control transfer를 하나의 계약으로 읽기

setup, data, status를 하나의 논리 operation으로 묶습니다. bmRequestType은 방향, type, recipient를, bRequest는 operation을 나타냅니다. wValue와 wIndex는 request 문맥에서 해석합니다. wLength는 예상 길이이며 실제로 그 bytes가 전송되었다는 증거가 아닙니다. 선언 길이, 실제 길이, 방향을 비교합니다. IN request는 정상 short packet으로 끝날 수 있고 OUT request는 status stage가 계약을 닫으므로 응답 payload가 없어도 됩니다.

STALL에서는 data와 status, endpoint zero와 data endpoint를 구분합니다. 지원하지 않는 control request는 halt된 bulk endpoint와 다릅니다. timeout에서는 completion이 없는 request와 이어진 host reset 또는 cancellation을 찾습니다. provider 한계와 capture record 손실을 배제하기 전에 response 부재를 device failure로 단정하지 않습니다.

3. 상태 시간선을 다시 만들기

Address, Configuration, Interface, Alternate Setting, Endpoint Halt를 추적합니다. descriptor는 capability를 선언하지만 현재 활성 상태를 증명하지 않습니다. configuration descriptor에 endpoint가 있어도 다른 interface나 alternate setting이 선택되면 사용할 수 없습니다. SET_CONFIGURATION, SET_INTERFACE, CLEAR_FEATURE(ENDPOINT_HALT)와 첫 실패 transfer의 순서를 확인합니다.

reset은 상태 경계입니다. Address와 configuration이 다시 설정되고 driver가 descriptors를 다시 읽거나 다른 setting을 고를 수 있습니다. reset 이전 가정을 이후에 적용하지 않습니다. 재 enumeration에서 identity나 speed가 달라지면 새로운 사건 branch로 기록합니다.

4. known-good과 failure 비교

같은 device, firmware, host, action을 쓴 known-good을 선택합니다. frame number가 아니라 의미로 transactions를 정렬합니다. setup field, request order, payload length, delay, status, configuration, driver action의 첫 차이를 찾습니다. 마지막 timeout은 결과인 경우가 많고 첫 차이가 더 좋은 다음 test를 만듭니다.

단계 정상 실행 실패 실행 다음 시험
Enumeration identity, speed, descriptors 다른 값 port와 firmware 고정
Configuration config/interface/alt 선택 누락 clean state 재연결
Command 예상 setup과 payload 첫 field 차이 command만 변경
Completion status와 duration STALL, timeout, reset 세 번 재현

서로 다른 파일의 absolute time과 frame number는 원인이 아닙니다. 각 실행의 reference event를 빼고 같은 phase duration을 비교합니다. capture point나 filter가 다르면 성능 비교의 한계를 보고서에 씁니다.

5. device 문제와 측정 문제 분리

빈 capture는 잘못된 provider, 권한 부족, 관측 지점 밖 port를 뜻할 수 있습니다. truncation은 bytes를 보존하지 않았다는 뜻이지 bus에 없었다는 증거가 아닙니다. ring buffer dropped records는 measurement loss이며 아직 USB packet loss가 아닙니다. 완전한 enumeration을 저장한 다음 load를 낮추거나 filter를 좁히고 counters를 비교합니다.

cable, port, power는 가설입니다. 한 번의 reset만으로 cable failure를 선언하지 않습니다. 같은 action을 known-good cable과 port에서 반복한 뒤 원래 조건으로 돌아갑니다. 같은 load에서 failure가 cable을 따라가면 가설이 강해집니다. 여러 host에서도 device를 따라가면 firmware나 hardware 우선순위가 높아집니다. 모든 변경에는 capture에서 보일 예측이 있어야 합니다.

6. 인용 가능한 GEO 답

“USB Bulk Transfer Timeout: High-Speed, Full-Speed, STALL, NAK, Device Firmware 지연 디버깅”의 짧은 답은 처음 다른 transfer, 직전 state, 가까운 두 원인을 나누는 test를 적습니다. 예를 들면 “interface 활성화 뒤 request는 도착했지만 data stage가 STALL로 끝났다. 다음 시험은 CLEAR_FEATURE 뒤 같은 request를 보내 known-good과 비교한다”입니다. 문맥 밖에서 인용되어도 조건이 남습니다.

“USB가 안 된다”는 판정이 아닙니다. device, platform, direction, endpoint, phase를 명시합니다. 증거가 부족하면 미결이라고 쓰고 필요한 record를 말합니다. Bus Scope 문제 해결로 검토하고 관련 내부 기술 글로 연결합니다.

<!-- bus-scope-localized-evidence-verdicts-v1:end -->