Introduce xferMap, avoid passing Go pointer into the C code.
Weirdness with memory barriers.
This commit is contained in:
@@ -18,6 +18,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
@@ -138,9 +139,9 @@ type libusbIntf interface {
|
|||||||
setAlt(*libusbDevHandle, uint8, uint8) error
|
setAlt(*libusbDevHandle, uint8, uint8) error
|
||||||
|
|
||||||
// transfer
|
// transfer
|
||||||
alloc(*libusbDevHandle, *EndpointInfo, time.Duration, int, []byte) (*libusbTransfer, error)
|
alloc(*libusbDevHandle, *EndpointInfo, time.Duration, int, []byte, chan struct{}) (*libusbTransfer, error)
|
||||||
cancel(*libusbTransfer) error
|
cancel(*libusbTransfer) error
|
||||||
submit(*libusbTransfer, chan struct{}) error
|
submit(*libusbTransfer) error
|
||||||
data(*libusbTransfer) (int, TransferStatus)
|
data(*libusbTransfer) (int, TransferStatus)
|
||||||
free(*libusbTransfer)
|
free(*libusbTransfer)
|
||||||
setIsoPacketLengths(*libusbTransfer, uint32)
|
setIsoPacketLengths(*libusbTransfer, uint32)
|
||||||
@@ -371,7 +372,7 @@ func (libusbImpl) setAlt(d *libusbDevHandle, iface, setup uint8) error {
|
|||||||
return fromErrNo(C.libusb_set_interface_alt_setting((*C.libusb_device_handle)(d), C.int(iface), C.int(setup)))
|
return fromErrNo(C.libusb_set_interface_alt_setting((*C.libusb_device_handle)(d), C.int(iface), C.int(setup)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (libusbImpl) alloc(d *libusbDevHandle, ep *EndpointInfo, timeout time.Duration, isoPackets int, buf []byte) (*libusbTransfer, error) {
|
func (libusbImpl) alloc(d *libusbDevHandle, ep *EndpointInfo, timeout time.Duration, isoPackets int, buf []byte, done chan struct{}) (*libusbTransfer, error) {
|
||||||
xfer := C.libusb_alloc_transfer(C.int(isoPackets))
|
xfer := C.libusb_alloc_transfer(C.int(isoPackets))
|
||||||
if xfer == nil {
|
if xfer == nil {
|
||||||
return nil, fmt.Errorf("libusb_alloc_transfer(%d) failed", isoPackets)
|
return nil, fmt.Errorf("libusb_alloc_transfer(%d) failed", isoPackets)
|
||||||
@@ -381,17 +382,20 @@ func (libusbImpl) alloc(d *libusbDevHandle, ep *EndpointInfo, timeout time.Durat
|
|||||||
xfer.timeout = C.uint(timeout / time.Millisecond)
|
xfer.timeout = C.uint(timeout / time.Millisecond)
|
||||||
xfer._type = C.uchar(ep.TransferType)
|
xfer._type = C.uchar(ep.TransferType)
|
||||||
xfer.num_iso_packets = C.int(isoPackets)
|
xfer.num_iso_packets = C.int(isoPackets)
|
||||||
xfer.buffer = (*C.uchar)((unsafe.Pointer)(&buf[0]))
|
xfer.buffer = (*C.uchar)(unsafe.Pointer(&buf[0]))
|
||||||
xfer.length = C.int(len(buf))
|
xfer.length = C.int(len(buf))
|
||||||
return (*libusbTransfer)(xfer), nil
|
ret := (*libusbTransfer)(xfer)
|
||||||
|
xferDoneMap.Lock()
|
||||||
|
xferDoneMap.m[ret] = done
|
||||||
|
xferDoneMap.Unlock()
|
||||||
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (libusbImpl) cancel(t *libusbTransfer) error {
|
func (libusbImpl) cancel(t *libusbTransfer) error {
|
||||||
return fromErrNo(C.libusb_cancel_transfer((*C.struct_libusb_transfer)(t)))
|
return fromErrNo(C.libusb_cancel_transfer((*C.struct_libusb_transfer)(t)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (libusbImpl) submit(t *libusbTransfer, done chan struct{}) error {
|
func (libusbImpl) submit(t *libusbTransfer) error {
|
||||||
t.user_data = (unsafe.Pointer)(&done)
|
|
||||||
return fromErrNo(C.submit((*C.struct_libusb_transfer)(t)))
|
return fromErrNo(C.submit((*C.struct_libusb_transfer)(t)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,6 +410,9 @@ func (libusbImpl) data(t *libusbTransfer) (int, TransferStatus) {
|
|||||||
|
|
||||||
func (libusbImpl) free(t *libusbTransfer) {
|
func (libusbImpl) free(t *libusbTransfer) {
|
||||||
C.libusb_free_transfer((*C.struct_libusb_transfer)(t))
|
C.libusb_free_transfer((*C.struct_libusb_transfer)(t))
|
||||||
|
xferDoneMap.Lock()
|
||||||
|
delete(xferDoneMap.m, t)
|
||||||
|
xferDoneMap.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (libusbImpl) setIsoPacketLengths(t *libusbTransfer, length uint32) {
|
func (libusbImpl) setIsoPacketLengths(t *libusbTransfer, length uint32) {
|
||||||
@@ -420,10 +427,20 @@ var (
|
|||||||
libusbIsoOffset = unsafe.Offsetof(C.struct_libusb_transfer{}.iso_packet_desc)
|
libusbIsoOffset = unsafe.Offsetof(C.struct_libusb_transfer{}.iso_packet_desc)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// xferDoneMap keeps a map of done callback channels for all allocated transfers.
|
||||||
|
var xferDoneMap = struct {
|
||||||
|
m map[*libusbTransfer]chan struct{}
|
||||||
|
sync.RWMutex
|
||||||
|
}{
|
||||||
|
m: make(map[*libusbTransfer]chan struct{}),
|
||||||
|
}
|
||||||
|
|
||||||
//export xferCallback
|
//export xferCallback
|
||||||
func xferCallback(cptr unsafe.Pointer) {
|
func xferCallback(xfer *C.struct_libusb_transfer) {
|
||||||
ch := *(*chan struct{})(cptr)
|
xferDoneMap.RLock()
|
||||||
close(ch)
|
ch := xferDoneMap.m[(*libusbTransfer)(xfer)]
|
||||||
|
xferDoneMap.RUnlock()
|
||||||
|
ch <- struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// for benchmarking and testing
|
// for benchmarking and testing
|
||||||
|
Reference in New Issue
Block a user