fix set interface

This commit is contained in:
duffyduck 2026-02-18 23:20:38 +01:00
parent 9d10beec9b
commit e327bad9c6
3 changed files with 56 additions and 15 deletions

Binary file not shown.

Binary file not shown.

View File

@ -360,21 +360,59 @@ func (s *Server) handleCmdSubmit(r io.Reader, hdr *URBHeader, retChan chan<- []b
}
if endpoint == 0 && hdr.Direction == DirOut {
buf := transferBuf
if buf == nil {
buf = make([]byte, 0)
}
_, err := s.handle.ControlTransfer(
body.Setup[0], body.Setup[1],
binary.LittleEndian.Uint16(body.Setup[2:4]),
binary.LittleEndian.Uint16(body.Setup[4:6]),
binary.LittleEndian.Uint16(body.Setup[6:8]),
5000, buf,
)
bmRequestType := body.Setup[0]
bRequest := body.Setup[1]
wValue := binary.LittleEndian.Uint16(body.Setup[2:4])
wIndex := binary.LittleEndian.Uint16(body.Setup[4:6])
var status int32
if err != nil {
status = -32 // -EPIPE
// Intercept standard USB requests that require special usbdevfs ioctls.
// Raw control transfers via USBDEVFS_CONTROL don't update kernel state.
switch {
case bmRequestType == 0x01 && bRequest == 0x0B:
// SET_INTERFACE (Standard, Interface recipient)
// MUST use USBDEVFS_SETINTERFACE so the kernel updates endpoint state
// and allocates bandwidth for ISO endpoints (critical for webcams).
if err := s.handle.SetInterface(uint32(wIndex), uint32(wValue)); err != nil {
log.Printf("[usbip-server] SET_INTERFACE(iface=%d, alt=%d) failed: %v", wIndex, wValue, err)
status = -32 // -EPIPE
} else {
log.Printf("[usbip-server] SET_INTERFACE(iface=%d, alt=%d) OK", wIndex, wValue)
}
case bmRequestType == 0x00 && bRequest == 0x09:
// SET_CONFIGURATION (Standard, Device recipient)
if err := s.handle.SetConfiguration(uint32(wValue)); err != nil {
log.Printf("[usbip-server] SET_CONFIGURATION(%d) failed: %v", wValue, err)
status = -32
} else {
log.Printf("[usbip-server] SET_CONFIGURATION(%d) OK", wValue)
}
case bmRequestType == 0x02 && bRequest == 0x01 && wValue == 0x0000:
// CLEAR_FEATURE(ENDPOINT_HALT) (Standard, Endpoint recipient)
if err := s.handle.ClearHalt(uint32(wIndex)); err != nil {
log.Printf("[usbip-server] CLEAR_HALT(ep=0x%02x) failed: %v", wIndex, err)
status = -32
}
default:
// Generic OUT control transfer
buf := transferBuf
if buf == nil {
buf = make([]byte, 0)
}
_, err := s.handle.ControlTransfer(
bmRequestType, bRequest, wValue, wIndex,
binary.LittleEndian.Uint16(body.Setup[6:8]),
5000, buf,
)
if err != nil {
status = -32 // -EPIPE
}
}
resp, err := BuildRetSubmit(hdr.SeqNum, hdr.DevID, hdr.Direction, hdr.Endpoint, status, nil)
if err != nil {
return err
@ -388,8 +426,11 @@ func (s *Server) handleCmdSubmit(r io.Reader, hdr *URBHeader, retChan chan<- []b
ep |= 0x80
}
// Handle isochronous transfers
if urbType == 0 && numPackets > 0 {
// Handle isochronous transfers.
// Trust the USB/IP NumberOfPackets field rather than our endpoint type map,
// because the map is built at enumeration time (alternate setting 0) and
// webcams only activate ISO endpoints after SET_INTERFACE to alt > 0.
if numPackets > 0 {
return s.handleISOSubmit(hdr, body, transferBuf, isoDescs, numPackets, ep, retChan)
}