aboutsummaryrefslogtreecommitdiffstats
path: root/sw/usbcom/main.go
blob: 70661d96934523f36795819c472450d4034ed017 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package main

import (
	"context"
	"fmt"
	"io"
	"os"

	"golang.org/x/sync/errgroup"

	"git.samanthony.xyz/can_gauge_interface/sw/usbcom/usb"
)

const bufSize = 512

func main() {
	exitCode := make(chan int)
	go exit(exitCode)
	defer close(exitCode)

	dev, err := usb.Connect()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error connecting to device: %v\n", err)
		exitCode <- 1
		return
	}
	defer func() {
		if err := dev.Close(); err != nil {
			fmt.Fprintf(os.Stderr, "Error :%v\n", err)
			exitCode <- 1
		}
	}()

	var group errgroup.Group
	ctx, cancel := context.WithCancel(context.Background())

	// Host->Device
	group.Go(func() error {
		err := hostToDevice(dev)
		cancel() // device->host routine
		return err
	})

	// Device->Host
	group.Go(func() error {
		return deviceToHost(ctx, dev)
	})

	if err = group.Wait(); err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		exitCode <- 1
	}
}

func exit(code <-chan int) {
	worst := 0
	for c := range code {
		if c > worst {
			worst = c
		}
	}
	os.Exit(worst)
}

func hostToDevice(dev *usb.Device) error {
	_, err := io.Copy(dev, os.Stdin)
	return err
}

func deviceToHost(ctx context.Context, dev *usb.Device) error {
	buf := make([]byte, bufSize)
	for {
		select {
		case <-ctx.Done():
			return nil
		default:
		}

		n, err := dev.Read(buf)
		if err != nil {
			return err
		}
		fmt.Print(string(buf[:n]))
	}
}