fix keyboard and mass storgae stream

This commit is contained in:
2026-02-19 12:41:30 +01:00
parent 67ab5418ee
commit 3a94bf35a7
5 changed files with 51 additions and 9 deletions
+29 -9
View File
@@ -15,7 +15,6 @@ import (
"unsafe"
"github.com/duffy/usb-server/internal/usb"
"golang.org/x/sys/unix"
)
// Server handles USB/IP protocol on the share side.
@@ -112,9 +111,7 @@ func (s *Server) Detach() {
s.mu.Lock()
for seqNum, pending := range s.pendingURBs {
if pending.urbPtr != nil {
unix.Syscall(unix.SYS_IOCTL, uintptr(s.handle.Fd()),
0x8000550B, // USBDEVFS_DISCARDURB
uintptr(pending.urbPtr))
s.handle.DiscardURBByPtr(pending.urbPtr)
}
delete(s.pendingURBs, seqNum)
}
@@ -410,6 +407,33 @@ func (s *Server) handleCmdSubmit(r io.Reader, hdr *URBHeader, retChan chan<- []b
status = -32
}
case bmRequestType == 0x00 && bRequest == 0x09:
// SET_CONFIGURATION — the device resets all endpoint data toggles
// to DATA0 on SET_CONFIGURATION, but USBDEVFS_CONTROL doesn't update
// the host controller's toggle state. We must manually reset host-side
// toggles via USBDEVFS_RESETEP, otherwise data toggle mismatch causes
// all non-control transfers (bulk, interrupt) to fail silently.
buf := transferBuf
if buf == nil {
buf = make([]byte, 0)
}
_, err := s.handle.ControlTransfer(bmRequestType, bRequest, wValue, wIndex, 0, 5000, buf)
if err != nil {
log.Printf("[usbip-server] SET_CONFIGURATION(%d) failed: %v", wValue, err)
status = -32
} else {
log.Printf("[usbip-server] SET_CONFIGURATION(%d) OK, resetting endpoint toggles", wValue)
for epNum := range s.epTypes {
if epNum == 0 {
continue
}
// Reset both OUT and IN directions; ignore errors for
// non-existent directions (e.g. endpoint only has IN)
s.handle.ResetEndpoint(uint32(epNum))
s.handle.ResetEndpoint(uint32(epNum) | 0x80)
}
}
default:
// Generic OUT control transfer
buf := transferBuf
@@ -577,11 +601,7 @@ func (s *Server) handleCmdUnlink(r io.Reader, hdr *URBHeader, retChan chan<- []b
var status int32
if exists && pending.urbPtr != nil {
// Try to discard the URB via proper ioctl
_, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(s.handle.Fd()),
uintptr(0x8000550B), // USBDEVFS_DISCARDURB
uintptr(pending.urbPtr))
if errno == 0 {
if err := s.handle.DiscardURBByPtr(pending.urbPtr); err == nil {
status = -104 // -ECONNRESET
}
}