-
Notifications
You must be signed in to change notification settings - Fork 2
/
device_info.go
171 lines (146 loc) · 3.62 KB
/
device_info.go
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package adb
import (
"bufio"
"bytes"
"fmt"
"strconv"
"strings"
"github.com/prife/goadb/wire"
)
type DeviceInfo struct {
// Always set.
Serial string
State string
// Product, device, and model are not set in the short form.
Product string
Model string
DeviceInfo string
TransportID int
// Only set for devices connected via USB.
Usb string
}
// IsUsb returns true if the device is connected via USB.
func (d *DeviceInfo) IsUsb() bool {
return d.Usb != ""
}
func newDevice(serial, state string, attrs map[string]string) (*DeviceInfo, error) {
if serial == "" {
return nil, fmt.Errorf("%w: device serial cannot be blank", wire.ErrAssertion)
}
var tid int
tidstr, ok := attrs["transport_id"]
if ok {
value, err := strconv.Atoi(tidstr)
if err == nil {
tid = value
}
}
return &DeviceInfo{
Serial: serial,
State: state,
Product: attrs["product"],
Model: attrs["model"],
DeviceInfo: attrs["device"],
Usb: attrs["usb"],
TransportID: tid,
}, nil
}
func parseDeviceList(list string, lineParseFunc func(string) (*DeviceInfo, error)) ([]*DeviceInfo, error) {
devices := []*DeviceInfo{}
scanner := bufio.NewScanner(strings.NewReader(list))
for scanner.Scan() {
device, err := lineParseFunc(scanner.Text())
if err != nil {
return nil, err
}
devices = append(devices, device)
}
return devices, nil
}
func parseDeviceShort(line string) (*DeviceInfo, error) {
fields := strings.Fields(line)
if len(fields) != 2 {
return nil, fmt.Errorf("%w: malformed device line, expected 2 fields but found %d", wire.ErrParse, len(fields))
}
return newDevice(fields[0], fields[1], map[string]string{})
}
func readBuff(buf *bytes.Buffer, toSpace bool) ([]byte, error) {
cbuf := buf.Bytes()
for i, c := range cbuf {
if toSpace {
if c == '\t' || c == ' ' {
return buf.Next(i), nil
}
} else {
if !(c == '\t' || c == ' ') {
return buf.Next(i), nil
}
}
}
return nil, fmt.Errorf("not found")
}
func parseDeviceLongE(line string) (*DeviceInfo, error) {
invalidErr := fmt.Errorf("%w: invalid line:%s", wire.ErrParse, line)
buf := bytes.NewBufferString(strings.TrimSpace(line))
// Read serial
serial, err := readBuff(buf, true)
if err != nil {
return nil, invalidErr
}
// skip spaces
if _, err = readBuff(buf, false); err != nil {
return nil, invalidErr
}
// Read state
state, err := readBuff(buf, true)
if err != nil {
return nil, invalidErr
}
if _, err = readBuff(buf, false); err != nil {
return nil, invalidErr
}
// Read attributes
attrs := map[string]string{}
// get the first 'key'
rbuf, err := buf.ReadBytes(':')
if err != nil {
return nil, invalidErr
}
key := string(rbuf[:len(rbuf)-1])
for {
// get the value
rbuf, err = buf.ReadBytes(':')
if err != nil {
value := string(rbuf)
attrs[key] = value
break
}
bi := bytes.LastIndexByte(rbuf, ' ')
if bi < 0 {
return nil, invalidErr
}
value := string(bytes.TrimSpace(rbuf[:bi]))
attrs[key] = value
// get the next key
key = string(rbuf[bi+1 : len(rbuf)-1])
}
return newDevice(string(serial), string(state), attrs)
}
func parseDeviceLong(line string) (*DeviceInfo, error) {
fields := strings.Fields(line)
attrs := parseDeviceAttributes(fields[2:])
return newDevice(fields[0], fields[1], attrs)
}
func parseDeviceAttributes(fields []string) map[string]string {
attrs := map[string]string{}
for _, field := range fields {
key, val := parseKeyVal(field)
attrs[key] = val
}
return attrs
}
// Parses a key:val pair and returns key, val.
func parseKeyVal(pair string) (string, string) {
split := strings.Split(pair, ":")
return split[0], split[1]
}