From 67ecea57068d91d3ca3dc46793d69b621270751b Mon Sep 17 00:00:00 2001 From: Kyle Lemons Date: Sun, 7 Apr 2013 12:32:53 -0700 Subject: [PATCH] Update readme with instructions for darwin --- README.md | 2 ++ usb/device.go | 4 ++-- usb/error.go | 30 ++++++++++++++++++++++++++++++ usb/iso.c | 35 ++++++++++++++++++++++++++++++++--- usb/iso.go | 35 ++++++++++++++++++++++++++--------- usb/usb.go | 2 +- 6 files changed, 93 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 9a7963c..e1b548a 100644 --- a/README.md +++ b/README.md @@ -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. +*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 -------------- 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: diff --git a/usb/device.go b/usb/device.go index 10eba24..1264e65 100644 --- a/usb/device.go +++ b/usb/device.go @@ -5,7 +5,7 @@ import "C" import ( "fmt" - "log" + //"log" // TODO(kevlar): make a logger "reflect" "sync" "time" @@ -55,7 +55,7 @@ func (d *Device) Reset() 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)) n := C.libusb_control_transfer( d.handle, diff --git a/usb/error.go b/usb/error.go index 6418dd0..d97b685 100644 --- a/usb/error.go +++ b/usb/error.go @@ -42,3 +42,33 @@ var usbErrorString = map[usbError]string{ C.LIBUSB_ERROR_NOT_SUPPORTED: "not supported", 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() +} diff --git a/usb/iso.c b/usb/iso.c index 57b09a1..b83f6b2 100644 --- a/usb/iso.c +++ b/usb/iso.c @@ -5,8 +5,8 @@ void print_xfer(struct libusb_transfer *xfer); void callback(struct libusb_transfer *xfer) { - printf("Callback!\n"); - print_xfer(xfer); + //printf("Callback!\n"); + //print_xfer(xfer); iso_callback(xfer->user_data); } @@ -14,7 +14,7 @@ int submit(struct libusb_transfer *xfer) { xfer->callback = &callback; xfer->status = -1; //print_xfer(xfer); - printf("Transfer submitted\n"); + //printf("Transfer submitted\n"); /* fake strcpy(xfer->buffer, "hello"); @@ -47,3 +47,32 @@ void print_xfer(struct libusb_transfer *xfer) { 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; +} diff --git a/usb/iso.go b/usb/iso.go index 46add83..bff996c 100644 --- a/usb/iso.go +++ b/usb/iso.go @@ -4,13 +4,14 @@ package usb #include 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 ( "fmt" "log" - "reflect" "time" "unsafe" ) @@ -46,15 +47,16 @@ func (end *endpoint) allocTransfer() *Transfer { xfer.num_iso_packets = iso_packets C.libusb_set_iso_packet_lengths(xfer, packet_size) + /* pkts := *(*[]C.struct_libusb_packet_descriptor)(unsafe.Pointer(&reflect.SliceHeader{ Data: uintptr(unsafe.Pointer(&xfer.iso_packet_desc)), Len: iso_packets, Cap: iso_packets, })) + */ t := &Transfer{ xfer: xfer, - pkts: pkts, done: done, buf: buf, } @@ -65,13 +67,13 @@ func (end *endpoint) allocTransfer() *Transfer { type Transfer struct { xfer *C.struct_libusb_transfer - pkts []C.struct_libusb_packet_descriptor + pkts []*C.struct_libusb_packet_descriptor done chan struct{} buf []byte } 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) if errno := C.submit(t.xfer); errno < 0 { 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") case <-t.done: } - n = int(t.xfer.actual_length) - copy(b, ((*[1 << 16]byte)(unsafe.Pointer(t.xfer.buffer)))[:n]) + // Non-iso transfers: + //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 { - log.Printf("PACKET[%4d] - %#v", i, pkt) - }*/ + buf, offset := ((*[1 << 16]byte)(unsafe.Pointer(t.xfer.buffer))), 0 + 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 } diff --git a/usb/usb.go b/usb/usb.go index 56d13b8..0681d06 100644 --- a/usb/usb.go +++ b/usb/usb.go @@ -39,7 +39,7 @@ func NewContext() *Context { log.Printf("handle_events: error: %s", usbError(errno)) continue } - log.Printf("handle_events returned") + //log.Printf("handle_events returned") } }()