aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/kylelemons/gousb/usbid/parse.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/kylelemons/gousb/usbid/parse.go')
-rw-r--r--vendor/github.com/kylelemons/gousb/usbid/parse.go246
1 files changed, 246 insertions, 0 deletions
diff --git a/vendor/github.com/kylelemons/gousb/usbid/parse.go b/vendor/github.com/kylelemons/gousb/usbid/parse.go
new file mode 100644
index 0000000..57571b8
--- /dev/null
+++ b/vendor/github.com/kylelemons/gousb/usbid/parse.go
@@ -0,0 +1,246 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Copyright 2016 the gousb Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package usbid
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "strconv"
+ "strings"
+
+ "github.com/kylelemons/gousb/usb"
+)
+
+// A Vendor contains the name of the vendor and mappings corresponding to all
+// known products by their ID.
+type Vendor struct {
+ Name string
+ Product map[usb.ID]*Product
+}
+
+// String returns the name of the vendor.
+func (v Vendor) String() string {
+ return v.Name
+}
+
+// A Product contains the name of the product (from a particular vendor) and
+// the names of any interfaces that were specified.
+type Product struct {
+ Name string
+ Interface map[usb.ID]string
+}
+
+// String returns the name of the product.
+func (p Product) String() string {
+ return p.Name
+}
+
+// A Class contains the name of the class and mappings for each subclass.
+type Class struct {
+ Name string
+ SubClass map[uint8]*SubClass
+}
+
+// String returns the name of the class.
+func (c Class) String() string {
+ return c.Name
+}
+
+// A SubClass contains the name of the subclass and any associated protocols.
+type SubClass struct {
+ Name string
+ Protocol map[uint8]string
+}
+
+// String returns the name of the SubClass.
+func (s SubClass) String() string {
+ return s.Name
+}
+
+// ParseIDs parses and returns mappings from the given reader. In general, this
+// should not be necessary, as a set of mappings is already embedded in the library.
+// If a new or specialized file is obtained, this can be used to retrieve the mappings,
+// which can be stored in the global Vendors and Classes map.
+func ParseIDs(r io.Reader) (map[usb.ID]*Vendor, map[uint8]*Class, error) {
+ vendors := make(map[usb.ID]*Vendor, 2800)
+ classes := make(map[uint8]*Class) // TODO(kevlar): count
+
+ split := func(s string) (kind string, level int, id uint64, name string, err error) {
+ pieces := strings.SplitN(s, " ", 2)
+ if len(pieces) != 2 {
+ err = fmt.Errorf("malformatted line %q", s)
+ return
+ }
+
+ // Save the name
+ name = pieces[1]
+
+ // Parse out the level
+ for len(pieces[0]) > 0 && pieces[0][0] == '\t' {
+ level, pieces[0] = level+1, pieces[0][1:]
+ }
+
+ // Parse the first piece to see if it has a kind
+ first := strings.SplitN(pieces[0], " ", 2)
+ if len(first) == 2 {
+ kind, pieces[0] = first[0], first[1]
+ }
+
+ // Parse the ID
+ i, err := strconv.ParseUint(pieces[0], 16, 16)
+ if err != nil {
+ err = fmt.Errorf("malformatted id %q: %s", pieces[0], err)
+ return
+ }
+ id = i
+
+ return
+ }
+
+ // Hold the interim values
+ var vendor *Vendor
+ var device *Product
+
+ parseVendor := func(level int, raw uint64, name string) error {
+ id := usb.ID(raw)
+
+ switch level {
+ case 0:
+ vendor = &Vendor{
+ Name: name,
+ }
+ vendors[id] = vendor
+
+ case 1:
+ if vendor == nil {
+ return fmt.Errorf("product line without vendor line")
+ }
+
+ device = &Product{
+ Name: name,
+ }
+ if vendor.Product == nil {
+ vendor.Product = make(map[usb.ID]*Product)
+ }
+ vendor.Product[id] = device
+
+ case 2:
+ if device == nil {
+ return fmt.Errorf("interface line without device line")
+ }
+
+ if device.Interface == nil {
+ device.Interface = make(map[usb.ID]string)
+ }
+ device.Interface[id] = name
+
+ default:
+ return fmt.Errorf("too many levels of nesting for vendor block")
+ }
+
+ return nil
+ }
+
+ // Hold the interim values
+ var class *Class
+ var subclass *SubClass
+
+ parseClass := func(level int, raw uint64, name string) error {
+ id := uint8(raw)
+
+ switch level {
+ case 0:
+ class = &Class{
+ Name: name,
+ }
+ classes[id] = class
+
+ case 1:
+ if class == nil {
+ return fmt.Errorf("subclass line without class line")
+ }
+
+ subclass = &SubClass{
+ Name: name,
+ }
+ if class.SubClass == nil {
+ class.SubClass = make(map[uint8]*SubClass)
+ }
+ class.SubClass[id] = subclass
+
+ case 2:
+ if subclass == nil {
+ return fmt.Errorf("protocol line without subclass line")
+ }
+
+ if subclass.Protocol == nil {
+ subclass.Protocol = make(map[uint8]string)
+ }
+ subclass.Protocol[id] = name
+
+ default:
+ return fmt.Errorf("too many levels of nesting for class")
+ }
+
+ return nil
+ }
+
+ // TODO(kevlar): Parse class information, etc
+ //var class *Class
+ //var subclass *SubClass
+
+ var kind string
+
+ lines := bufio.NewReaderSize(r, 512)
+parseLines:
+ for lineno := 0; ; lineno++ {
+ b, isPrefix, err := lines.ReadLine()
+ switch {
+ case err == io.EOF:
+ break parseLines
+ case err != nil:
+ return nil, nil, err
+ case isPrefix:
+ return nil, nil, fmt.Errorf("line %d: line too long", lineno)
+ }
+ line := string(b)
+
+ if len(line) == 0 || line[0] == '#' {
+ continue
+ }
+
+ k, level, id, name, err := split(line)
+ if err != nil {
+ return nil, nil, fmt.Errorf("line %d: %s", lineno, err)
+ }
+ if k != "" {
+ kind = k
+ }
+
+ switch kind {
+ case "":
+ err = parseVendor(level, id, name)
+ case "C":
+ err = parseClass(level, id, name)
+ }
+ if err != nil {
+ return nil, nil, fmt.Errorf("line %d: %s", lineno, err)
+ }
+ }
+
+ return vendors, classes, nil
+}