From 66db4a686ba47e71cf1ecba3e9c5ce0f22adeb9a Mon Sep 17 00:00:00 2001 From: Sebastian Zagrodzki Date: Fri, 10 Feb 2017 12:48:44 +0100 Subject: [PATCH 1/2] Merge flags vid/pid and bus/addr into single flags, vidpid and busaddr. --- rawread/main.go | 68 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 13 deletions(-) diff --git a/rawread/main.go b/rawread/main.go index 4e56e1e..b885294 100644 --- a/rawread/main.go +++ b/rawread/main.go @@ -21,6 +21,8 @@ import ( "fmt" "log" "os" + "strconv" + "strings" "sync/atomic" "time" @@ -29,10 +31,8 @@ import ( ) var ( - vid = flag.Uint("vid", 0, "VID of the device to which to connect. Exclusive with bus/addr flags.") - pid = flag.Uint("pid", 0, "PID of the device to which to connect. Exclusive with bus/addr flags.") - bus = flag.Uint("bus", 0, "Bus number for the device to which to connect. Exclusive with vid/pid flags.") - addr = flag.Uint("addr", 0, "Address of the device to which to connect. Exclusive with vid/pid flags.") + vidPID = flag.String("vidpid", "", "VID:PID of the device to which to connect. Exclusive with busaddr flag.") + busAddr = flag.String("busaddr", "", "Bus:address of the device to which to connect. Exclusive with vidpid flag.") config = flag.Uint("config", 1, "Endpoint to which to connect") iface = flag.Uint("interface", 0, "Endpoint to which to connect") setup = flag.Uint("setup", 0, "Endpoint to which to connect") @@ -42,6 +42,38 @@ var ( bench = flag.Bool("benchmark", false, "When true, keep reading from the endpoint and periodically report the measured throughput. If false, only one read operation is performed and obtained data is printed to STDOUT.") ) +func parseVIDPID(vidPid string) (usb.ID, usb.ID, error) { + s := strings.Split(vidPid, ":") + if len(s) != 2 { + return 0, 0, fmt.Errorf("want VID:PID, two 32-bit hex numbers separated by colon, e.g. 1d6b:0002") + } + vid, err := strconv.ParseUint(s[0], 16, 32) + if err != nil { + return 0, 0, fmt.Errorf("VID must be a hexadecimal 32-bit number, e.g. 1d6b") + } + pid, err := strconv.ParseUint(s[1], 16, 32) + if err != nil { + return 0, 0, fmt.Errorf("PID must be a hexadecimal 32-bit number, e.g. 1d6b") + } + return usb.ID(vid), usb.ID(pid), nil +} + +func parseBusAddr(busAddr string) (uint8, uint8, error) { + s := strings.Split(busAddr, ":") + if len(s) != 2 { + return 0, 0, fmt.Errorf("want bus:addr, two 8-bit decimal unsigned integers separated by colon, e.g. 1:1") + } + bus, err := strconv.ParseUint(s[0], 10, 8) + if err != nil { + return 0, 0, fmt.Errorf("bus number must be an 8-bit decimal unsigned integer") + } + addr, err := strconv.ParseUint(s[1], 10, 8) + if err != nil { + return 0, 0, fmt.Errorf("device address must be an 8-bit decimal unsigned integer") + } + return uint8(bus), uint8(addr), nil +} + func main() { flag.Parse() @@ -52,24 +84,34 @@ func main() { ctx.Debug(*debug) var devName string + var vid, pid usb.ID + var bus, addr uint8 switch { - case *vid == 0 && *pid == 0 && *bus == 0 && *addr == 0: - log.Fatal("You need to specify the device, either through --vid/--pid flags or through --bus/--addr flags.") - case (*vid > 0 || *pid > 0) && (*bus > 0 || *addr > 0): - log.Fatal("You can't use --vid/--pid flags at the same time as --bus/--addr.") - case *vid > 0 || *pid > 0: - devName = fmt.Sprintf("VID:PID %04x:%04x", *vid, *pid) + case *vidPID == "" && *busAddr == "": + log.Fatal("You need to specify the device through a --vidpid flag or through a --busaddr flag.") + case *vidPID != "" && *busAddr != "": + log.Fatal("You can't use --vidpid flag together with --busaddr. Pick one.") + case *vidPID != "": + vid, pid, err := parseVIDPID(*vidPID) + if err != nil { + log.Fatalf("Invalid value for --vidpid (%q): %v", *vidPID, err) + } + devName = fmt.Sprintf("VID:PID %s:%s", vid, pid) default: - devName = fmt.Sprintf("bus:addr %d:%d", *bus, *addr) + bus, addr, err := parseBusAddr(*busAddr) + if err != nil { + log.Fatalf("Invalid value for --busaddr (%q): %v", *busAddr, err) + } + devName = fmt.Sprintf("bus:addr %d:%d", bus, addr) } log.Printf("Scanning for device %q...", devName) // ListDevices is used to find the devices to open. devs, err := ctx.ListDevices(func(desc *usb.Descriptor) bool { switch { - case usb.ID(*vid) == desc.Vendor && usb.ID(*pid) == desc.Product: + case vid == desc.Vendor && pid == desc.Product: return true - case uint8(*bus) == desc.Bus && uint8(*addr) == desc.Address: + case bus == desc.Bus && addr == desc.Address: return true } return false From 0588c4e512141ffa7fc46976e4781928db4cdcbd Mon Sep 17 00:00:00 2001 From: Sebastian Zagrodzki Date: Fri, 10 Feb 2017 13:02:48 +0100 Subject: [PATCH 2/2] Remove the bench option, add num_reads instead for controlling how many reads to send. Default is read forever. --- rawread/main.go | 40 +++++++++------------------------------- 1 file changed, 9 insertions(+), 31 deletions(-) diff --git a/rawread/main.go b/rawread/main.go index b885294..c389c4f 100644 --- a/rawread/main.go +++ b/rawread/main.go @@ -23,8 +23,6 @@ import ( "os" "strconv" "strings" - "sync/atomic" - "time" "github.com/kylelemons/gousb/usb" "github.com/kylelemons/gousb/usbid" @@ -39,7 +37,7 @@ var ( endpoint = flag.Uint("endpoint", 1, "Endpoint to which to connect") debug = flag.Int("debug", 3, "Debug level for libusb") size = flag.Uint("read_size", 1024, "Number of bytes of data to read in a single transaction.") - bench = flag.Bool("benchmark", false, "When true, keep reading from the endpoint and periodically report the measured throughput. If false, only one read operation is performed and obtained data is printed to STDOUT.") + num = flag.Uint("read_num", 0, "Number of read transactions to perform. 0 means infinite.") ) func parseVIDPID(vidPid string) (usb.ID, usb.ID, error) { @@ -92,13 +90,15 @@ func main() { case *vidPID != "" && *busAddr != "": log.Fatal("You can't use --vidpid flag together with --busaddr. Pick one.") case *vidPID != "": - vid, pid, err := parseVIDPID(*vidPID) + var err error + vid, pid, err = parseVIDPID(*vidPID) if err != nil { log.Fatalf("Invalid value for --vidpid (%q): %v", *vidPID, err) } devName = fmt.Sprintf("VID:PID %s:%s", vid, pid) default: - bus, addr, err := parseBusAddr(*busAddr) + var err error + bus, addr, err = parseBusAddr(*busAddr) if err != nil { log.Fatalf("Invalid value for --busaddr (%q): %v", *busAddr, err) } @@ -162,41 +162,19 @@ func main() { log.Printf(" --------------\n") } - log.Print("Connecting to endpoint...") + log.Printf("Connecting to endpoint %d...", *endpoint) ep, err := dev.OpenEndpoint(uint8(*config), uint8(*iface), uint8(*setup), uint8(*endpoint)|uint8(usb.ENDPOINT_DIR_IN)) if err != nil { log.Fatalf("open: %s", err) } log.Print("Reading...") - var total uint64 - if *bench { - go func() { - var last uint64 - var before = time.Now() - for { - time.Sleep(4 * time.Second) - cur := atomic.LoadUint64(&total) - now := time.Now() - dur := now.Sub(before) - log.Printf("%.2f B/s\n", float64(cur-last)/(float64(dur)/float64(time.Second))) - before = now - last = cur - } - }() - } - - for { - buf := make([]byte, *size) + buf := make([]byte, *size) + for i := uint(0); *num == 0 || i < *num; i++ { num, err := ep.Read(buf) if err != nil { log.Fatalf("Reading from device failed: %v", err) } - if !*bench { - log.Printf("Read %d bytes of data", num) - os.Stdout.Write(buf[:num]) - return - } - atomic.AddUint64(&total, uint64(num)) + os.Stdout.Write(buf[:num]) } }