added isochronous modus
This commit is contained in:
@@ -348,6 +348,109 @@ func (h *DeviceHandle) DiscardURB(urb *usbdevfsURB) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SubmitISOURBParams holds parameters for async ISO URB submission
|
||||
type SubmitISOURBParams struct {
|
||||
Endpoint uint8
|
||||
Flags uint32
|
||||
Buffer []byte
|
||||
NumberOfPackets int32
|
||||
PacketLengths []uint32 // length of each ISO packet
|
||||
UserContext uintptr
|
||||
}
|
||||
|
||||
// SubmitISOURB submits an asynchronous isochronous URB.
|
||||
// Returns the URB pointer and the backing memory slice (must be kept alive until reap).
|
||||
func (h *DeviceHandle) SubmitISOURB(params *SubmitISOURBParams) (urb *usbdevfsURB, mem []byte, err error) {
|
||||
urbSize := unsafe.Sizeof(usbdevfsURB{})
|
||||
isoDescSize := unsafe.Sizeof(usbdevfsISOPacketDesc{})
|
||||
totalSize := urbSize + uintptr(params.NumberOfPackets)*isoDescSize
|
||||
|
||||
mem = make([]byte, totalSize)
|
||||
urb = (*usbdevfsURB)(unsafe.Pointer(&mem[0]))
|
||||
|
||||
var bufPtr uintptr
|
||||
if len(params.Buffer) > 0 {
|
||||
bufPtr = uintptr(unsafe.Pointer(¶ms.Buffer[0]))
|
||||
}
|
||||
|
||||
urb.Type = urbTypeISO
|
||||
urb.Endpoint = params.Endpoint
|
||||
urb.Flags = params.Flags
|
||||
urb.Buffer = bufPtr
|
||||
urb.BufferLength = int32(len(params.Buffer))
|
||||
urb.NumberOfPackets = params.NumberOfPackets
|
||||
urb.UserContext = params.UserContext
|
||||
|
||||
// Fill ISO packet descriptors (immediately following the URB in memory)
|
||||
for i := int32(0); i < params.NumberOfPackets; i++ {
|
||||
descOffset := urbSize + uintptr(i)*isoDescSize
|
||||
desc := (*usbdevfsISOPacketDesc)(unsafe.Pointer(&mem[descOffset]))
|
||||
if i < int32(len(params.PacketLengths)) {
|
||||
desc.Length = params.PacketLengths[i]
|
||||
}
|
||||
}
|
||||
|
||||
_, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(h.fd), usbdevfsSubmitURB, uintptr(unsafe.Pointer(urb)))
|
||||
if errno != 0 {
|
||||
return nil, nil, fmt.Errorf("USBDEVFS_SUBMITURB (ISO): %w", errno)
|
||||
}
|
||||
return urb, mem, nil
|
||||
}
|
||||
|
||||
// ISOPacketResult holds the result of one ISO packet after reaping
|
||||
type ISOPacketResult struct {
|
||||
Length uint32
|
||||
ActualLength uint32
|
||||
Status uint32
|
||||
}
|
||||
|
||||
// ReadISOResults reads the ISO packet results from a reaped ISO URB's backing memory.
|
||||
func ReadISOResults(mem []byte, numPackets int32) []ISOPacketResult {
|
||||
urbSize := unsafe.Sizeof(usbdevfsURB{})
|
||||
isoDescSize := unsafe.Sizeof(usbdevfsISOPacketDesc{})
|
||||
|
||||
results := make([]ISOPacketResult, numPackets)
|
||||
for i := int32(0); i < numPackets; i++ {
|
||||
offset := urbSize + uintptr(i)*isoDescSize
|
||||
if int(offset+isoDescSize) > len(mem) {
|
||||
break
|
||||
}
|
||||
desc := (*usbdevfsISOPacketDesc)(unsafe.Pointer(&mem[offset]))
|
||||
results[i] = ISOPacketResult{
|
||||
Length: desc.Length,
|
||||
ActualLength: desc.ActualLength,
|
||||
Status: desc.Status,
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// ReapedURBInfo holds exported fields from a reaped URB needed for response building
|
||||
type ReapedURBInfo struct {
|
||||
UserContext uintptr
|
||||
Status int32
|
||||
ActualLength int32
|
||||
StartFrame int32
|
||||
ErrorCount int32
|
||||
}
|
||||
|
||||
// ReapURBInfo blocks until a URB completes and returns exported info
|
||||
func (h *DeviceHandle) ReapURBInfo() (*ReapedURBInfo, error) {
|
||||
var urbPtr uintptr
|
||||
_, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(h.fd), usbdevfsReapURB, uintptr(unsafe.Pointer(&urbPtr)))
|
||||
if errno != 0 {
|
||||
return nil, fmt.Errorf("USBDEVFS_REAPURB: %w", errno)
|
||||
}
|
||||
urb := (*usbdevfsURB)(unsafe.Pointer(urbPtr))
|
||||
return &ReapedURBInfo{
|
||||
UserContext: urb.UserContext,
|
||||
Status: urb.Status,
|
||||
ActualLength: urb.ActualLength,
|
||||
StartFrame: urb.StartFrame,
|
||||
ErrorCount: urb.ErrorCount,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetFile returns an os.File wrapping the device fd (useful for epoll/select)
|
||||
func (h *DeviceHandle) GetFile() *os.File {
|
||||
return os.NewFile(uintptr(h.fd), h.devPath)
|
||||
|
||||
Reference in New Issue
Block a user