Update readme with instructions for darwin
This commit is contained in:
@@ -17,6 +17,8 @@ Dependencies
|
|||||||
------------
|
------------
|
||||||
You must first install [libusb-1.0](http://libusb.org/wiki/libusb-1.0). This is pretty straightforward on linux and darwin. The cgo package should be able to find it if you install it in the default manner or use your distribution's package manager. How to tell cgo how to find one installed in a non-default place is beyond the scope of this README.
|
You must first install [libusb-1.0](http://libusb.org/wiki/libusb-1.0). This is pretty straightforward on linux and darwin. The cgo package should be able to find it if you install it in the default manner or use your distribution's package manager. How to tell cgo how to find one installed in a non-default place is beyond the scope of this README.
|
||||||
|
|
||||||
|
*Note*: If you are installing this on darwin, you will probably need to run `fixlibusb_darwin.sh /usr/local/lib/libusb-1.0/libusb.h` because of an LLVM incompatibility. It shouldn't break C programs, though I haven't tried it in anger.
|
||||||
|
|
||||||
Example: lsusb
|
Example: lsusb
|
||||||
--------------
|
--------------
|
||||||
The gousb project provides a simple but useful example: lsusb. This binary will list the USB devices connected to your system and various interesting tidbits about them, their configurations, endpoints, etc. To install it, run the following command:
|
The gousb project provides a simple but useful example: lsusb. This binary will list the USB devices connected to your system and various interesting tidbits about them, their configurations, endpoints, etc. To install it, run the following command:
|
||||||
|
@@ -5,7 +5,7 @@ import "C"
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
//"log" // TODO(kevlar): make a logger
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -55,7 +55,7 @@ func (d *Device) Reset() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Device) Control(rType, request uint8, val, idx uint16, data []byte) (int, error) {
|
func (d *Device) Control(rType, request uint8, val, idx uint16, data []byte) (int, error) {
|
||||||
log.Printf("control xfer: %d:%d/%d:%d %x", idx, rType, request, val, string(data))
|
//log.Printf("control xfer: %d:%d/%d:%d %x", idx, rType, request, val, string(data))
|
||||||
dataSlice := (*reflect.SliceHeader)(unsafe.Pointer(&data))
|
dataSlice := (*reflect.SliceHeader)(unsafe.Pointer(&data))
|
||||||
n := C.libusb_control_transfer(
|
n := C.libusb_control_transfer(
|
||||||
d.handle,
|
d.handle,
|
||||||
|
30
usb/error.go
30
usb/error.go
@@ -42,3 +42,33 @@ var usbErrorString = map[usbError]string{
|
|||||||
C.LIBUSB_ERROR_NOT_SUPPORTED: "not supported",
|
C.LIBUSB_ERROR_NOT_SUPPORTED: "not supported",
|
||||||
C.LIBUSB_ERROR_OTHER: "unknown error",
|
C.LIBUSB_ERROR_OTHER: "unknown error",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TransferStatus uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
LIBUSB_TRANSFER_COMPLETED TransferStatus = C.LIBUSB_TRANSFER_COMPLETED
|
||||||
|
LIBUSB_TRANSFER_ERROR TransferStatus = C.LIBUSB_TRANSFER_ERROR
|
||||||
|
LIBUSB_TRANSFER_TIMED_OUT TransferStatus = C.LIBUSB_TRANSFER_TIMED_OUT
|
||||||
|
LIBUSB_TRANSFER_CANCELLED TransferStatus = C.LIBUSB_TRANSFER_CANCELLED
|
||||||
|
LIBUSB_TRANSFER_STALL TransferStatus = C.LIBUSB_TRANSFER_STALL
|
||||||
|
LIBUSB_TRANSFER_NO_DEVICE TransferStatus = C.LIBUSB_TRANSFER_NO_DEVICE
|
||||||
|
LIBUSB_TRANSFER_OVERFLOW TransferStatus = C.LIBUSB_TRANSFER_OVERFLOW
|
||||||
|
)
|
||||||
|
|
||||||
|
var transferStatusDescription = map[TransferStatus]string{
|
||||||
|
LIBUSB_TRANSFER_COMPLETED: "transfer completed without error",
|
||||||
|
LIBUSB_TRANSFER_ERROR: "transfer failed",
|
||||||
|
LIBUSB_TRANSFER_TIMED_OUT: "transfer timed out",
|
||||||
|
LIBUSB_TRANSFER_CANCELLED: "transfer was cancelled",
|
||||||
|
LIBUSB_TRANSFER_STALL: "halt condition detected (endpoint stalled) or control request not supported",
|
||||||
|
LIBUSB_TRANSFER_NO_DEVICE: "device was disconnected",
|
||||||
|
LIBUSB_TRANSFER_OVERFLOW: "device sent more data than requested",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ts TransferStatus) String() string {
|
||||||
|
return transferStatusDescription[ts]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ts TransferStatus) Error() string {
|
||||||
|
return "libusb: " + ts.String()
|
||||||
|
}
|
||||||
|
35
usb/iso.c
35
usb/iso.c
@@ -5,8 +5,8 @@
|
|||||||
void print_xfer(struct libusb_transfer *xfer);
|
void print_xfer(struct libusb_transfer *xfer);
|
||||||
|
|
||||||
void callback(struct libusb_transfer *xfer) {
|
void callback(struct libusb_transfer *xfer) {
|
||||||
printf("Callback!\n");
|
//printf("Callback!\n");
|
||||||
print_xfer(xfer);
|
//print_xfer(xfer);
|
||||||
iso_callback(xfer->user_data);
|
iso_callback(xfer->user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ int submit(struct libusb_transfer *xfer) {
|
|||||||
xfer->callback = &callback;
|
xfer->callback = &callback;
|
||||||
xfer->status = -1;
|
xfer->status = -1;
|
||||||
//print_xfer(xfer);
|
//print_xfer(xfer);
|
||||||
printf("Transfer submitted\n");
|
//printf("Transfer submitted\n");
|
||||||
|
|
||||||
/* fake
|
/* fake
|
||||||
strcpy(xfer->buffer, "hello");
|
strcpy(xfer->buffer, "hello");
|
||||||
@@ -47,3 +47,32 @@ void print_xfer(struct libusb_transfer *xfer) {
|
|||||||
xfer->iso_packet_desc[i].status);
|
xfer->iso_packet_desc[i].status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int extract_data(struct libusb_transfer *xfer, void *raw, int max, unsigned char *status) {
|
||||||
|
int i;
|
||||||
|
int copied = 0;
|
||||||
|
unsigned char *in = xfer->buffer;
|
||||||
|
unsigned char *out = raw;
|
||||||
|
for (i = 0; i < xfer->num_iso_packets; i++) {
|
||||||
|
struct libusb_iso_packet_descriptor pkt = xfer->iso_packet_desc[i];
|
||||||
|
|
||||||
|
// Copy the data
|
||||||
|
int len = pkt.actual_length;
|
||||||
|
if (len > max) {
|
||||||
|
len = max;
|
||||||
|
}
|
||||||
|
memcpy(out, in, len);
|
||||||
|
copied += len;
|
||||||
|
|
||||||
|
// Increment offsets
|
||||||
|
in += pkt.length;
|
||||||
|
out += len;
|
||||||
|
|
||||||
|
// Extract first error
|
||||||
|
if (pkt.status == 0 || *status != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*status = pkt.status;
|
||||||
|
}
|
||||||
|
return copied;
|
||||||
|
}
|
||||||
|
35
usb/iso.go
35
usb/iso.go
@@ -4,13 +4,14 @@ package usb
|
|||||||
#include <libusb-1.0/libusb.h>
|
#include <libusb-1.0/libusb.h>
|
||||||
|
|
||||||
int submit(struct libusb_transfer *xfer);
|
int submit(struct libusb_transfer *xfer);
|
||||||
|
void print_xfer(struct libusb_transfer *xfer);
|
||||||
|
int extract_data(struct libusb_transfer *xfer, void *data, int max, unsigned char *status);
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"reflect"
|
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
@@ -46,15 +47,16 @@ func (end *endpoint) allocTransfer() *Transfer {
|
|||||||
xfer.num_iso_packets = iso_packets
|
xfer.num_iso_packets = iso_packets
|
||||||
|
|
||||||
C.libusb_set_iso_packet_lengths(xfer, packet_size)
|
C.libusb_set_iso_packet_lengths(xfer, packet_size)
|
||||||
|
/*
|
||||||
pkts := *(*[]C.struct_libusb_packet_descriptor)(unsafe.Pointer(&reflect.SliceHeader{
|
pkts := *(*[]C.struct_libusb_packet_descriptor)(unsafe.Pointer(&reflect.SliceHeader{
|
||||||
Data: uintptr(unsafe.Pointer(&xfer.iso_packet_desc)),
|
Data: uintptr(unsafe.Pointer(&xfer.iso_packet_desc)),
|
||||||
Len: iso_packets,
|
Len: iso_packets,
|
||||||
Cap: iso_packets,
|
Cap: iso_packets,
|
||||||
}))
|
}))
|
||||||
|
*/
|
||||||
|
|
||||||
t := &Transfer{
|
t := &Transfer{
|
||||||
xfer: xfer,
|
xfer: xfer,
|
||||||
pkts: pkts,
|
|
||||||
done: done,
|
done: done,
|
||||||
buf: buf,
|
buf: buf,
|
||||||
}
|
}
|
||||||
@@ -65,13 +67,13 @@ func (end *endpoint) allocTransfer() *Transfer {
|
|||||||
|
|
||||||
type Transfer struct {
|
type Transfer struct {
|
||||||
xfer *C.struct_libusb_transfer
|
xfer *C.struct_libusb_transfer
|
||||||
pkts []C.struct_libusb_packet_descriptor
|
pkts []*C.struct_libusb_packet_descriptor
|
||||||
done chan struct{}
|
done chan struct{}
|
||||||
buf []byte
|
buf []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transfer) Submit(timeout time.Duration) error {
|
func (t *Transfer) Submit(timeout time.Duration) error {
|
||||||
log.Printf("iso: submitting %#v", t.xfer)
|
//log.Printf("iso: submitting %#v", t.xfer)
|
||||||
t.xfer.timeout = C.uint(timeout / time.Millisecond)
|
t.xfer.timeout = C.uint(timeout / time.Millisecond)
|
||||||
if errno := C.submit(t.xfer); errno < 0 {
|
if errno := C.submit(t.xfer); errno < 0 {
|
||||||
return usbError(errno)
|
return usbError(errno)
|
||||||
@@ -85,12 +87,27 @@ func (t *Transfer) Wait(b []byte) (n int, err error) {
|
|||||||
return 0, fmt.Errorf("wait timed out after 10s")
|
return 0, fmt.Errorf("wait timed out after 10s")
|
||||||
case <-t.done:
|
case <-t.done:
|
||||||
}
|
}
|
||||||
n = int(t.xfer.actual_length)
|
// Non-iso transfers:
|
||||||
copy(b, ((*[1 << 16]byte)(unsafe.Pointer(t.xfer.buffer)))[:n])
|
//n = int(t.xfer.actual_length)
|
||||||
|
//copy(b, ((*[1 << 16]byte)(unsafe.Pointer(t.xfer.buffer)))[:n])
|
||||||
|
|
||||||
|
//C.print_xfer(t.xfer)
|
||||||
/*
|
/*
|
||||||
for i, pkt := range t.pkts {
|
buf, offset := ((*[1 << 16]byte)(unsafe.Pointer(t.xfer.buffer))), 0
|
||||||
log.Printf("PACKET[%4d] - %#v", i, pkt)
|
for i, pkt := range *t.pkts {
|
||||||
}*/
|
log.Printf("Type is %T", t.pkts)
|
||||||
|
n += copy(b[n:], buf[offset:][:pkt.actual_length])
|
||||||
|
offset += pkt.Length
|
||||||
|
if pkt.status != 0 && err == nil {
|
||||||
|
err = error(TransferStatus(pkt.status))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
var status uint8
|
||||||
|
n = int(C.extract_data(t.xfer, unsafe.Pointer(&b[0]), C.int(len(b)), (*C.uchar)(unsafe.Pointer(&status))))
|
||||||
|
if status != 0 {
|
||||||
|
err = TransferStatus(status)
|
||||||
|
}
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -39,7 +39,7 @@ func NewContext() *Context {
|
|||||||
log.Printf("handle_events: error: %s", usbError(errno))
|
log.Printf("handle_events: error: %s", usbError(errno))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
log.Printf("handle_events returned")
|
//log.Printf("handle_events returned")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user