Reading from a USB Device in Go using karalabe package

Issue

I am using karalabe USB package (since it does not depend on libusb installation on Win 10) and I can successfully find a micro:bit, but no output is read into the buffer, i.e. count is always 0:

func show_read(device usb.Device) {
    var buffer []byte
    for {
        count, err := device.Read(buffer)
        if err != nil {
            fmt.Println("Error reading:", err)
        } else if count != 0 {
            fmt.Print(string(buffer))
        }
    }
}

func ShowDevices() {
    hids, err := usb.Enumerate(0x0D28, 0x0204)
    if err != nil {
        panic(err)
    }
    for i, hid := range hids {
        fmt.Printf("HID #%d\n", i)
        fmt.Printf("  OS Path:      %s\n", hid.Path)
        fmt.Printf("  Vendor ID:    %#04x\n", hid.VendorID)
        fmt.Printf("  Product ID:   %#04x\n", hid.ProductID)
        var device, err = hid.Open()
        if err != nil {
            fmt.Println("Error opening", err)
        } else {
            go show_read(device)
        }
    }
}

e.g. this outputs:

HID #0
  OS Path:      \\?\hid#vid_0d28&pid_0204&mi_03#8&30686a44&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
  Vendor ID:    0x0d28
  Product ID:   0x0204

I have an existing program on the micro:bit that does connect and output successfully to a python version (which I am porting to Go) – and this works and shows that output is being sent from the micro:bit.

Note: If I open the micro:bit REPL through the Mu Editor, the Python code fails to open/connect (which is technically correct) but the Go program still runs without throwing an error, which implies that the device isn’t actually being opened.

Solution

I’m not sure how much of this was necessary, but I solved this by:

  1. Using go.bug.st/serial – see also https://godoc.org/go.bug.st/serial
  2. and adding uart.init(115200,8,None,1) to my micro:bit python code

It’s possible that karalabe would also work now that the uart is initialized correctly…

Here is some working serial code – which fine for my purposes (only tested on windows) – though there is obviously some tidying to do – the program exits when the micro:bit is disconnected.

package usb

import (
    "fmt"
    "log"

    "go.bug.st/serial"
    "go.bug.st/serial/enumerator"
)

const VID = "0D28"
const PID = "0204"

func show_read(device serial.Port) {
    buffer := make([]byte, 100)
    for {
        count, err := device.Read(buffer)
        if err != nil {
            fmt.Println("Error reading:", err)
        } else if count != 0 {
            fmt.Print(string(buffer[:count]))
        }
    }
}

func ShowDevices() {
    ports, err := enumerator.GetDetailedPortsList()
    if err != nil {
        log.Fatal(err)
    }
    for _, port := range ports {
        if port.IsUSB && (port.VID == VID) && (port.PID == PID) {
            UBIT_MODE := &serial.Mode{
                BaudRate: 115200,
                DataBits: 8,
                Parity:   serial.NoParity,
                StopBits: serial.OneStopBit,
            }
            fmt.Printf("Found port: %s\n", port.Name)
            fmt.Printf("   USB ID     %s:%s\n", port.VID, port.PID)
            fmt.Printf("   USB serial %s\n", port.SerialNumber)
            device, err := serial.Open(port.Name, UBIT_MODE)
            if err != nil {
                log.Fatal(err)
            }
            go show_read(device)
        }
    }
}

Answered By – AndyS

Answer Checked By – Marilyn (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.