From 500caaeda74dd9c660279036293f4b2997cf0b03 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Sat, 9 Sep 2017 09:42:37 +0200 Subject: Add vendor --- vendor/github.com/kylelemons/gousb/usbid/parse.go | 246 ++++++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 vendor/github.com/kylelemons/gousb/usbid/parse.go (limited to 'vendor/github.com/kylelemons/gousb/usbid/parse.go') 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 +} -- cgit v1.2.3