fix keyboard and mass storgae stream
This commit is contained in:
parent
67ab5418ee
commit
3a94bf35a7
BIN
bin/usb-client
BIN
bin/usb-client
Binary file not shown.
Binary file not shown.
BIN
bin/usb-relay
BIN
bin/usb-relay
Binary file not shown.
|
|
@ -37,6 +37,7 @@ var (
|
||||||
usbdevfsSetInterface = ior('U', 4, unsafe.Sizeof(usbdevfsSetIntf{}))
|
usbdevfsSetInterface = ior('U', 4, unsafe.Sizeof(usbdevfsSetIntf{}))
|
||||||
usbdevfsSetConfig = ior('U', 5, 4)
|
usbdevfsSetConfig = ior('U', 5, 4)
|
||||||
usbdevfsSubmitURB = ior('U', 10, unsafe.Sizeof(usbdevfsURB{}))
|
usbdevfsSubmitURB = ior('U', 10, unsafe.Sizeof(usbdevfsURB{}))
|
||||||
|
usbdevfsResetEP = ior('U', 3, 4)
|
||||||
usbdevfsDiscardURB = io_('U', 11)
|
usbdevfsDiscardURB = io_('U', 11)
|
||||||
usbdevfsReapURB = iow('U', 12, unsafe.Sizeof(uintptr(0)))
|
usbdevfsReapURB = iow('U', 12, unsafe.Sizeof(uintptr(0)))
|
||||||
usbdevfsReapURBNDelay = iow('U', 13, unsafe.Sizeof(uintptr(0)))
|
usbdevfsReapURBNDelay = iow('U', 13, unsafe.Sizeof(uintptr(0)))
|
||||||
|
|
@ -348,6 +349,27 @@ func (h *DeviceHandle) DiscardURB(urb *usbdevfsURB) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DiscardURBByPtr cancels a submitted URB given its raw pointer.
|
||||||
|
// Use this when the URB type is not accessible (e.g. from another package).
|
||||||
|
func (h *DeviceHandle) DiscardURBByPtr(ptr unsafe.Pointer) error {
|
||||||
|
_, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(h.fd), usbdevfsDiscardURB, uintptr(ptr))
|
||||||
|
if errno != 0 {
|
||||||
|
return fmt.Errorf("USBDEVFS_DISCARDURB: %w", errno)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResetEndpoint resets the host-side data toggle for an endpoint without
|
||||||
|
// sending any USB traffic to the device. Use after SET_CONFIGURATION to
|
||||||
|
// sync host controller toggle state with the device.
|
||||||
|
func (h *DeviceHandle) ResetEndpoint(endpoint uint32) error {
|
||||||
|
_, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(h.fd), usbdevfsResetEP, uintptr(unsafe.Pointer(&endpoint)))
|
||||||
|
if errno != 0 {
|
||||||
|
return fmt.Errorf("USBDEVFS_RESETEP(%d): %w", endpoint, errno)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// SubmitISOURBParams holds parameters for async ISO URB submission
|
// SubmitISOURBParams holds parameters for async ISO URB submission
|
||||||
type SubmitISOURBParams struct {
|
type SubmitISOURBParams struct {
|
||||||
Endpoint uint8
|
Endpoint uint8
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/duffy/usb-server/internal/usb"
|
"github.com/duffy/usb-server/internal/usb"
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Server handles USB/IP protocol on the share side.
|
// Server handles USB/IP protocol on the share side.
|
||||||
|
|
@ -112,9 +111,7 @@ func (s *Server) Detach() {
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
for seqNum, pending := range s.pendingURBs {
|
for seqNum, pending := range s.pendingURBs {
|
||||||
if pending.urbPtr != nil {
|
if pending.urbPtr != nil {
|
||||||
unix.Syscall(unix.SYS_IOCTL, uintptr(s.handle.Fd()),
|
s.handle.DiscardURBByPtr(pending.urbPtr)
|
||||||
0x8000550B, // USBDEVFS_DISCARDURB
|
|
||||||
uintptr(pending.urbPtr))
|
|
||||||
}
|
}
|
||||||
delete(s.pendingURBs, seqNum)
|
delete(s.pendingURBs, seqNum)
|
||||||
}
|
}
|
||||||
|
|
@ -410,6 +407,33 @@ func (s *Server) handleCmdSubmit(r io.Reader, hdr *URBHeader, retChan chan<- []b
|
||||||
status = -32
|
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:
|
default:
|
||||||
// Generic OUT control transfer
|
// Generic OUT control transfer
|
||||||
buf := transferBuf
|
buf := transferBuf
|
||||||
|
|
@ -577,11 +601,7 @@ func (s *Server) handleCmdUnlink(r io.Reader, hdr *URBHeader, retChan chan<- []b
|
||||||
|
|
||||||
var status int32
|
var status int32
|
||||||
if exists && pending.urbPtr != nil {
|
if exists && pending.urbPtr != nil {
|
||||||
// Try to discard the URB via proper ioctl
|
if err := s.handle.DiscardURBByPtr(pending.urbPtr); err == nil {
|
||||||
_, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(s.handle.Fd()),
|
|
||||||
uintptr(0x8000550B), // USBDEVFS_DISCARDURB
|
|
||||||
uintptr(pending.urbPtr))
|
|
||||||
if errno == 0 {
|
|
||||||
status = -104 // -ECONNRESET
|
status = -104 // -ECONNRESET
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue