Compare commits
5 Commits
187735eee6
...
396d8a99b6
Author | SHA1 | Date | |
---|---|---|---|
396d8a99b6 | |||
a3558053c3 | |||
a4da40a414 | |||
c1ec63fcc1 | |||
0b8d2218c1 |
13
go.mod
13
go.mod
@ -3,20 +3,19 @@ module github.com/cyrilix/robocar-led
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/cyrilix/robocar-base v0.1.5
|
||||
github.com/cyrilix/robocar-protobuf/go v1.0.3
|
||||
github.com/cyrilix/robocar-base v0.1.6
|
||||
github.com/cyrilix/robocar-protobuf/go v1.0.4
|
||||
github.com/eclipse/paho.mqtt.golang v1.3.5
|
||||
github.com/golang/protobuf v1.5.2
|
||||
go.uber.org/zap v1.19.1
|
||||
periph.io/x/conn/v3 v3.6.8
|
||||
periph.io/x/host/v3 v3.7.0
|
||||
google.golang.org/protobuf v1.27.1
|
||||
periph.io/x/conn/v3 v3.6.10
|
||||
periph.io/x/host/v3 v3.7.2
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect
|
||||
google.golang.org/protobuf v1.26.0 // indirect
|
||||
periph.io/x/d2xx v0.0.3 // indirect
|
||||
)
|
||||
|
25
go.sum
25
go.sum
@ -8,10 +8,10 @@ github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/cyrilix/robocar-base v0.1.5 h1:EfbYHB69hgyQCVuzZ9/ifdSrQfXS7+04M8O9BDu1/5w=
|
||||
github.com/cyrilix/robocar-base v0.1.5/go.mod h1:tb7R5OFoBn9EWNLX3Kzx6R/3cQ9/7r8XsHvlLSESOAM=
|
||||
github.com/cyrilix/robocar-protobuf/go v1.0.3 h1:iPHw2+7FVXG2C4+Th1m11hQ+2RpAQzlxKhc5M7XOa6Q=
|
||||
github.com/cyrilix/robocar-protobuf/go v1.0.3/go.mod h1:xb95cK07lYXnKcHZKnGafmAgYRrqZWZgV9LMiJAp+gE=
|
||||
github.com/cyrilix/robocar-base v0.1.6 h1:VVcSZD8DPsha3XDLxRBMvtcd6uC8CcIjqbxG482dxvo=
|
||||
github.com/cyrilix/robocar-base v0.1.6/go.mod h1:m5ov/7hpRHi0yMp2prKafL6UEsM2O71Uea85WR0/jjI=
|
||||
github.com/cyrilix/robocar-protobuf/go v1.0.4 h1:XTolFYbiKw4gQ2l+z/LMZkLrmAUMzlHcQBzp/czlANo=
|
||||
github.com/cyrilix/robocar-protobuf/go v1.0.4/go.mod h1:1fyGMVm4ZodfYRrbWCEQgtvKyvrhyTBe5zA7/Qeh/H0=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@ -48,6 +48,8 @@ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
|
||||
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
@ -143,8 +145,9 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
@ -159,10 +162,8 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools v0.0.0-20181223230014-1083505acf35/go.mod h1:R//lfYlUuTOTfblYI3lGoAAAebUdzjvbmQsuB7Ykd90=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
periph.io/x/conn/v3 v3.6.8 h1:fnNSwSoKPzpoLOSxml70EInaP6YrrqcucP3KDfNxpmU=
|
||||
periph.io/x/conn/v3 v3.6.8/go.mod h1:3OD27w9YVa5DS97VsUxsPGzD9Qrm5Ny7cF5b6xMMIWg=
|
||||
periph.io/x/d2xx v0.0.1/go.mod h1:38Euaaj+s6l0faIRHh32a+PrjXvxFTFkPBEQI0TKg34=
|
||||
periph.io/x/d2xx v0.0.3 h1:BE8XcIdxabu9ZzAr1UXxSz88T9Txki6Xyo8aJ1qZvks=
|
||||
periph.io/x/d2xx v0.0.3/go.mod h1:38Euaaj+s6l0faIRHh32a+PrjXvxFTFkPBEQI0TKg34=
|
||||
periph.io/x/host/v3 v3.7.0 h1:9CP/j0FcJmR+PRHlNzAmhV6Mt3GXoWnPmRhknJlQhnE=
|
||||
periph.io/x/host/v3 v3.7.0/go.mod h1:okb5m0yUYLTM/dnMYWMBX47w4owTzyCPLpZUQb35nhs=
|
||||
periph.io/x/conn/v3 v3.6.10 h1:gwU4ssmZkq1D/uz8hU91i/COo2c9DrRaS4PJZBbCd+c=
|
||||
periph.io/x/conn/v3 v3.6.10/go.mod h1:UqWNaPMosWmNCwtufoTSTTYhB2wXWsMRAJyo1PlxO4Q=
|
||||
periph.io/x/d2xx v0.0.4/go.mod h1:38Euaaj+s6l0faIRHh32a+PrjXvxFTFkPBEQI0TKg34=
|
||||
periph.io/x/host/v3 v3.7.2 h1:rCAUxkzy2xrzh18HP2AoVwTL/fEKqmcJ1icsZQGM58Q=
|
||||
periph.io/x/host/v3 v3.7.2/go.mod h1:nHMlzkPwmnHyP9Tn0I8FV+e0N3K7TjFXLZkIWzAicog=
|
||||
|
@ -118,7 +118,7 @@ func (l *PiColorLed) blink(freq float64) {
|
||||
ticker := time.NewTicker(time.Duration(float64(time.Second) / freq))
|
||||
|
||||
// Restore values
|
||||
defer l.SetColor(l.Color())
|
||||
defer l.on()
|
||||
|
||||
for {
|
||||
select {
|
||||
|
@ -6,8 +6,8 @@ import (
|
||||
"github.com/cyrilix/robocar-led/pkg/led"
|
||||
"github.com/cyrilix/robocar-protobuf/go/events"
|
||||
mqtt "github.com/eclipse/paho.mqtt.golang"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
@ -2,16 +2,21 @@ package part
|
||||
|
||||
import (
|
||||
"github.com/cyrilix/robocar-base/testtools"
|
||||
"github.com/cyrilix/robocar-led/pkg/led"
|
||||
"github.com/cyrilix/robocar-protobuf/go/events"
|
||||
mqtt "github.com/eclipse/paho.mqtt.golang"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type fakeLed struct {
|
||||
red, green, blue int
|
||||
blink bool
|
||||
color led.Color
|
||||
blink bool
|
||||
}
|
||||
|
||||
func (f *fakeLed) SetColor(color led.Color) {
|
||||
f.color = color
|
||||
}
|
||||
|
||||
func (f *fakeLed) SetBlink(freq float64) {
|
||||
@ -22,29 +27,17 @@ func (f *fakeLed) SetBlink(freq float64) {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *fakeLed) SetRed(value int) {
|
||||
f.red = value
|
||||
}
|
||||
|
||||
func (f *fakeLed) SetGreen(value int) {
|
||||
f.green = value
|
||||
}
|
||||
|
||||
func (f *fakeLed) SetBlue(value int) {
|
||||
f.blue = value
|
||||
}
|
||||
|
||||
func TestLedPart_OnDriveMode(t *testing.T) {
|
||||
led := fakeLed{}
|
||||
p := LedPart{led: &led}
|
||||
l := fakeLed{}
|
||||
p := LedPart{led: &l}
|
||||
|
||||
cases := []struct {
|
||||
msg mqtt.Message
|
||||
red, green, blue int
|
||||
msg mqtt.Message
|
||||
color led.Color
|
||||
}{
|
||||
{testtools.NewFakeMessageFromProtobuf("drive", &events.DriveModeMessage{DriveMode: events.DriveMode_USER}), 0, 255, 0},
|
||||
{testtools.NewFakeMessageFromProtobuf("drive", &events.DriveModeMessage{DriveMode: events.DriveMode_PILOT}), 0, 0, 255},
|
||||
{testtools.NewFakeMessageFromProtobuf("drive", &events.DriveModeMessage{DriveMode: events.DriveMode_INVALID}), 0, 0, 255},
|
||||
{testtools.NewFakeMessageFromProtobuf("drive", &events.DriveModeMessage{DriveMode: events.DriveMode_USER}), led.ColorGreen},
|
||||
{testtools.NewFakeMessageFromProtobuf("drive", &events.DriveModeMessage{DriveMode: events.DriveMode_PILOT}), led.ColorBlue},
|
||||
{testtools.NewFakeMessageFromProtobuf("drive", &events.DriveModeMessage{DriveMode: events.DriveMode_INVALID}), led.ColorBlue},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
@ -56,20 +49,8 @@ func TestLedPart_OnDriveMode(t *testing.T) {
|
||||
t.Errorf("unable to unmarshal drive mode message: %v", err)
|
||||
}
|
||||
value := msg.DriveMode
|
||||
if led.red != c.red {
|
||||
t.Errorf("driveMode(%v)=invalid value for red channel: %v, wants %v", value, led.red, c.red)
|
||||
}
|
||||
if led.green != c.green {
|
||||
if err != nil {
|
||||
t.Errorf("payload isn't a led value: %v", err)
|
||||
}
|
||||
t.Errorf("driveMode(%v)=invalid value for green channel: %v, wants %v", value, led.green, c.green)
|
||||
}
|
||||
if led.blue != c.blue {
|
||||
if err != nil {
|
||||
t.Errorf("payload isn't a led value: %v", err)
|
||||
}
|
||||
t.Errorf("driveMode(%v)=invalid value for blue channel: %v, wants %v", value, led.blue, c.blue)
|
||||
if l.color != c.color {
|
||||
t.Errorf("driveMode(%v)=invalid value for color: %v, wants %v", value, l.color, c.color)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
2
vendor/github.com/cyrilix/robocar-base/testtools/testtools.go
generated
vendored
2
vendor/github.com/cyrilix/robocar-base/testtools/testtools.go
generated
vendored
@ -2,8 +2,8 @@ package testtools
|
||||
|
||||
import (
|
||||
mqtt "github.com/eclipse/paho.mqtt.golang"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type fakeMessage struct {
|
||||
|
2
vendor/github.com/cyrilix/robocar-protobuf/go/events/events.pb.go
generated
vendored
2
vendor/github.com/cyrilix/robocar-protobuf/go/events/events.pb.go
generated
vendored
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.12.4
|
||||
// source: events/events.proto
|
||||
|
||||
|
324
vendor/github.com/golang/protobuf/proto/buffer.go
generated
vendored
324
vendor/github.com/golang/protobuf/proto/buffer.go
generated
vendored
@ -1,324 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"google.golang.org/protobuf/encoding/prototext"
|
||||
"google.golang.org/protobuf/encoding/protowire"
|
||||
"google.golang.org/protobuf/runtime/protoimpl"
|
||||
)
|
||||
|
||||
const (
|
||||
WireVarint = 0
|
||||
WireFixed32 = 5
|
||||
WireFixed64 = 1
|
||||
WireBytes = 2
|
||||
WireStartGroup = 3
|
||||
WireEndGroup = 4
|
||||
)
|
||||
|
||||
// EncodeVarint returns the varint encoded bytes of v.
|
||||
func EncodeVarint(v uint64) []byte {
|
||||
return protowire.AppendVarint(nil, v)
|
||||
}
|
||||
|
||||
// SizeVarint returns the length of the varint encoded bytes of v.
|
||||
// This is equal to len(EncodeVarint(v)).
|
||||
func SizeVarint(v uint64) int {
|
||||
return protowire.SizeVarint(v)
|
||||
}
|
||||
|
||||
// DecodeVarint parses a varint encoded integer from b,
|
||||
// returning the integer value and the length of the varint.
|
||||
// It returns (0, 0) if there is a parse error.
|
||||
func DecodeVarint(b []byte) (uint64, int) {
|
||||
v, n := protowire.ConsumeVarint(b)
|
||||
if n < 0 {
|
||||
return 0, 0
|
||||
}
|
||||
return v, n
|
||||
}
|
||||
|
||||
// Buffer is a buffer for encoding and decoding the protobuf wire format.
|
||||
// It may be reused between invocations to reduce memory usage.
|
||||
type Buffer struct {
|
||||
buf []byte
|
||||
idx int
|
||||
deterministic bool
|
||||
}
|
||||
|
||||
// NewBuffer allocates a new Buffer initialized with buf,
|
||||
// where the contents of buf are considered the unread portion of the buffer.
|
||||
func NewBuffer(buf []byte) *Buffer {
|
||||
return &Buffer{buf: buf}
|
||||
}
|
||||
|
||||
// SetDeterministic specifies whether to use deterministic serialization.
|
||||
//
|
||||
// Deterministic serialization guarantees that for a given binary, equal
|
||||
// messages will always be serialized to the same bytes. This implies:
|
||||
//
|
||||
// - Repeated serialization of a message will return the same bytes.
|
||||
// - Different processes of the same binary (which may be executing on
|
||||
// different machines) will serialize equal messages to the same bytes.
|
||||
//
|
||||
// Note that the deterministic serialization is NOT canonical across
|
||||
// languages. It is not guaranteed to remain stable over time. It is unstable
|
||||
// across different builds with schema changes due to unknown fields.
|
||||
// Users who need canonical serialization (e.g., persistent storage in a
|
||||
// canonical form, fingerprinting, etc.) should define their own
|
||||
// canonicalization specification and implement their own serializer rather
|
||||
// than relying on this API.
|
||||
//
|
||||
// If deterministic serialization is requested, map entries will be sorted
|
||||
// by keys in lexographical order. This is an implementation detail and
|
||||
// subject to change.
|
||||
func (b *Buffer) SetDeterministic(deterministic bool) {
|
||||
b.deterministic = deterministic
|
||||
}
|
||||
|
||||
// SetBuf sets buf as the internal buffer,
|
||||
// where the contents of buf are considered the unread portion of the buffer.
|
||||
func (b *Buffer) SetBuf(buf []byte) {
|
||||
b.buf = buf
|
||||
b.idx = 0
|
||||
}
|
||||
|
||||
// Reset clears the internal buffer of all written and unread data.
|
||||
func (b *Buffer) Reset() {
|
||||
b.buf = b.buf[:0]
|
||||
b.idx = 0
|
||||
}
|
||||
|
||||
// Bytes returns the internal buffer.
|
||||
func (b *Buffer) Bytes() []byte {
|
||||
return b.buf
|
||||
}
|
||||
|
||||
// Unread returns the unread portion of the buffer.
|
||||
func (b *Buffer) Unread() []byte {
|
||||
return b.buf[b.idx:]
|
||||
}
|
||||
|
||||
// Marshal appends the wire-format encoding of m to the buffer.
|
||||
func (b *Buffer) Marshal(m Message) error {
|
||||
var err error
|
||||
b.buf, err = marshalAppend(b.buf, m, b.deterministic)
|
||||
return err
|
||||
}
|
||||
|
||||
// Unmarshal parses the wire-format message in the buffer and
|
||||
// places the decoded results in m.
|
||||
// It does not reset m before unmarshaling.
|
||||
func (b *Buffer) Unmarshal(m Message) error {
|
||||
err := UnmarshalMerge(b.Unread(), m)
|
||||
b.idx = len(b.buf)
|
||||
return err
|
||||
}
|
||||
|
||||
type unknownFields struct{ XXX_unrecognized protoimpl.UnknownFields }
|
||||
|
||||
func (m *unknownFields) String() string { panic("not implemented") }
|
||||
func (m *unknownFields) Reset() { panic("not implemented") }
|
||||
func (m *unknownFields) ProtoMessage() { panic("not implemented") }
|
||||
|
||||
// DebugPrint dumps the encoded bytes of b with a header and footer including s
|
||||
// to stdout. This is only intended for debugging.
|
||||
func (*Buffer) DebugPrint(s string, b []byte) {
|
||||
m := MessageReflect(new(unknownFields))
|
||||
m.SetUnknown(b)
|
||||
b, _ = prototext.MarshalOptions{AllowPartial: true, Indent: "\t"}.Marshal(m.Interface())
|
||||
fmt.Printf("==== %s ====\n%s==== %s ====\n", s, b, s)
|
||||
}
|
||||
|
||||
// EncodeVarint appends an unsigned varint encoding to the buffer.
|
||||
func (b *Buffer) EncodeVarint(v uint64) error {
|
||||
b.buf = protowire.AppendVarint(b.buf, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeZigzag32 appends a 32-bit zig-zag varint encoding to the buffer.
|
||||
func (b *Buffer) EncodeZigzag32(v uint64) error {
|
||||
return b.EncodeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31))))
|
||||
}
|
||||
|
||||
// EncodeZigzag64 appends a 64-bit zig-zag varint encoding to the buffer.
|
||||
func (b *Buffer) EncodeZigzag64(v uint64) error {
|
||||
return b.EncodeVarint(uint64((uint64(v) << 1) ^ uint64((int64(v) >> 63))))
|
||||
}
|
||||
|
||||
// EncodeFixed32 appends a 32-bit little-endian integer to the buffer.
|
||||
func (b *Buffer) EncodeFixed32(v uint64) error {
|
||||
b.buf = protowire.AppendFixed32(b.buf, uint32(v))
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeFixed64 appends a 64-bit little-endian integer to the buffer.
|
||||
func (b *Buffer) EncodeFixed64(v uint64) error {
|
||||
b.buf = protowire.AppendFixed64(b.buf, uint64(v))
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeRawBytes appends a length-prefixed raw bytes to the buffer.
|
||||
func (b *Buffer) EncodeRawBytes(v []byte) error {
|
||||
b.buf = protowire.AppendBytes(b.buf, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeStringBytes appends a length-prefixed raw bytes to the buffer.
|
||||
// It does not validate whether v contains valid UTF-8.
|
||||
func (b *Buffer) EncodeStringBytes(v string) error {
|
||||
b.buf = protowire.AppendString(b.buf, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeMessage appends a length-prefixed encoded message to the buffer.
|
||||
func (b *Buffer) EncodeMessage(m Message) error {
|
||||
var err error
|
||||
b.buf = protowire.AppendVarint(b.buf, uint64(Size(m)))
|
||||
b.buf, err = marshalAppend(b.buf, m, b.deterministic)
|
||||
return err
|
||||
}
|
||||
|
||||
// DecodeVarint consumes an encoded unsigned varint from the buffer.
|
||||
func (b *Buffer) DecodeVarint() (uint64, error) {
|
||||
v, n := protowire.ConsumeVarint(b.buf[b.idx:])
|
||||
if n < 0 {
|
||||
return 0, protowire.ParseError(n)
|
||||
}
|
||||
b.idx += n
|
||||
return uint64(v), nil
|
||||
}
|
||||
|
||||
// DecodeZigzag32 consumes an encoded 32-bit zig-zag varint from the buffer.
|
||||
func (b *Buffer) DecodeZigzag32() (uint64, error) {
|
||||
v, err := b.DecodeVarint()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64((uint32(v) >> 1) ^ uint32((int32(v&1)<<31)>>31)), nil
|
||||
}
|
||||
|
||||
// DecodeZigzag64 consumes an encoded 64-bit zig-zag varint from the buffer.
|
||||
func (b *Buffer) DecodeZigzag64() (uint64, error) {
|
||||
v, err := b.DecodeVarint()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64((uint64(v) >> 1) ^ uint64((int64(v&1)<<63)>>63)), nil
|
||||
}
|
||||
|
||||
// DecodeFixed32 consumes a 32-bit little-endian integer from the buffer.
|
||||
func (b *Buffer) DecodeFixed32() (uint64, error) {
|
||||
v, n := protowire.ConsumeFixed32(b.buf[b.idx:])
|
||||
if n < 0 {
|
||||
return 0, protowire.ParseError(n)
|
||||
}
|
||||
b.idx += n
|
||||
return uint64(v), nil
|
||||
}
|
||||
|
||||
// DecodeFixed64 consumes a 64-bit little-endian integer from the buffer.
|
||||
func (b *Buffer) DecodeFixed64() (uint64, error) {
|
||||
v, n := protowire.ConsumeFixed64(b.buf[b.idx:])
|
||||
if n < 0 {
|
||||
return 0, protowire.ParseError(n)
|
||||
}
|
||||
b.idx += n
|
||||
return uint64(v), nil
|
||||
}
|
||||
|
||||
// DecodeRawBytes consumes a length-prefixed raw bytes from the buffer.
|
||||
// If alloc is specified, it returns a copy the raw bytes
|
||||
// rather than a sub-slice of the buffer.
|
||||
func (b *Buffer) DecodeRawBytes(alloc bool) ([]byte, error) {
|
||||
v, n := protowire.ConsumeBytes(b.buf[b.idx:])
|
||||
if n < 0 {
|
||||
return nil, protowire.ParseError(n)
|
||||
}
|
||||
b.idx += n
|
||||
if alloc {
|
||||
v = append([]byte(nil), v...)
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// DecodeStringBytes consumes a length-prefixed raw bytes from the buffer.
|
||||
// It does not validate whether the raw bytes contain valid UTF-8.
|
||||
func (b *Buffer) DecodeStringBytes() (string, error) {
|
||||
v, n := protowire.ConsumeString(b.buf[b.idx:])
|
||||
if n < 0 {
|
||||
return "", protowire.ParseError(n)
|
||||
}
|
||||
b.idx += n
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// DecodeMessage consumes a length-prefixed message from the buffer.
|
||||
// It does not reset m before unmarshaling.
|
||||
func (b *Buffer) DecodeMessage(m Message) error {
|
||||
v, err := b.DecodeRawBytes(false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return UnmarshalMerge(v, m)
|
||||
}
|
||||
|
||||
// DecodeGroup consumes a message group from the buffer.
|
||||
// It assumes that the start group marker has already been consumed and
|
||||
// consumes all bytes until (and including the end group marker).
|
||||
// It does not reset m before unmarshaling.
|
||||
func (b *Buffer) DecodeGroup(m Message) error {
|
||||
v, n, err := consumeGroup(b.buf[b.idx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.idx += n
|
||||
return UnmarshalMerge(v, m)
|
||||
}
|
||||
|
||||
// consumeGroup parses b until it finds an end group marker, returning
|
||||
// the raw bytes of the message (excluding the end group marker) and the
|
||||
// the total length of the message (including the end group marker).
|
||||
func consumeGroup(b []byte) ([]byte, int, error) {
|
||||
b0 := b
|
||||
depth := 1 // assume this follows a start group marker
|
||||
for {
|
||||
_, wtyp, tagLen := protowire.ConsumeTag(b)
|
||||
if tagLen < 0 {
|
||||
return nil, 0, protowire.ParseError(tagLen)
|
||||
}
|
||||
b = b[tagLen:]
|
||||
|
||||
var valLen int
|
||||
switch wtyp {
|
||||
case protowire.VarintType:
|
||||
_, valLen = protowire.ConsumeVarint(b)
|
||||
case protowire.Fixed32Type:
|
||||
_, valLen = protowire.ConsumeFixed32(b)
|
||||
case protowire.Fixed64Type:
|
||||
_, valLen = protowire.ConsumeFixed64(b)
|
||||
case protowire.BytesType:
|
||||
_, valLen = protowire.ConsumeBytes(b)
|
||||
case protowire.StartGroupType:
|
||||
depth++
|
||||
case protowire.EndGroupType:
|
||||
depth--
|
||||
default:
|
||||
return nil, 0, errors.New("proto: cannot parse reserved wire type")
|
||||
}
|
||||
if valLen < 0 {
|
||||
return nil, 0, protowire.ParseError(valLen)
|
||||
}
|
||||
b = b[valLen:]
|
||||
|
||||
if depth == 0 {
|
||||
return b0[:len(b0)-len(b)-tagLen], len(b0) - len(b), nil
|
||||
}
|
||||
}
|
||||
}
|
63
vendor/github.com/golang/protobuf/proto/defaults.go
generated
vendored
63
vendor/github.com/golang/protobuf/proto/defaults.go
generated
vendored
@ -1,63 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
)
|
||||
|
||||
// SetDefaults sets unpopulated scalar fields to their default values.
|
||||
// Fields within a oneof are not set even if they have a default value.
|
||||
// SetDefaults is recursively called upon any populated message fields.
|
||||
func SetDefaults(m Message) {
|
||||
if m != nil {
|
||||
setDefaults(MessageReflect(m))
|
||||
}
|
||||
}
|
||||
|
||||
func setDefaults(m protoreflect.Message) {
|
||||
fds := m.Descriptor().Fields()
|
||||
for i := 0; i < fds.Len(); i++ {
|
||||
fd := fds.Get(i)
|
||||
if !m.Has(fd) {
|
||||
if fd.HasDefault() && fd.ContainingOneof() == nil {
|
||||
v := fd.Default()
|
||||
if fd.Kind() == protoreflect.BytesKind {
|
||||
v = protoreflect.ValueOf(append([]byte(nil), v.Bytes()...)) // copy the default bytes
|
||||
}
|
||||
m.Set(fd, v)
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
|
||||
switch {
|
||||
// Handle singular message.
|
||||
case fd.Cardinality() != protoreflect.Repeated:
|
||||
if fd.Message() != nil {
|
||||
setDefaults(m.Get(fd).Message())
|
||||
}
|
||||
// Handle list of messages.
|
||||
case fd.IsList():
|
||||
if fd.Message() != nil {
|
||||
ls := m.Get(fd).List()
|
||||
for i := 0; i < ls.Len(); i++ {
|
||||
setDefaults(ls.Get(i).Message())
|
||||
}
|
||||
}
|
||||
// Handle map of messages.
|
||||
case fd.IsMap():
|
||||
if fd.MapValue().Message() != nil {
|
||||
ms := m.Get(fd).Map()
|
||||
ms.Range(func(_ protoreflect.MapKey, v protoreflect.Value) bool {
|
||||
setDefaults(v.Message())
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
113
vendor/github.com/golang/protobuf/proto/deprecated.go
generated
vendored
113
vendor/github.com/golang/protobuf/proto/deprecated.go
generated
vendored
@ -1,113 +0,0 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
protoV2 "google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var (
|
||||
// Deprecated: No longer returned.
|
||||
ErrNil = errors.New("proto: Marshal called with nil")
|
||||
|
||||
// Deprecated: No longer returned.
|
||||
ErrTooLarge = errors.New("proto: message encodes to over 2 GB")
|
||||
|
||||
// Deprecated: No longer returned.
|
||||
ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
|
||||
)
|
||||
|
||||
// Deprecated: Do not use.
|
||||
type Stats struct{ Emalloc, Dmalloc, Encode, Decode, Chit, Cmiss, Size uint64 }
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func GetStats() Stats { return Stats{} }
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func MarshalMessageSet(interface{}) ([]byte, error) {
|
||||
return nil, errors.New("proto: not implemented")
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func UnmarshalMessageSet([]byte, interface{}) error {
|
||||
return errors.New("proto: not implemented")
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func MarshalMessageSetJSON(interface{}) ([]byte, error) {
|
||||
return nil, errors.New("proto: not implemented")
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func UnmarshalMessageSetJSON([]byte, interface{}) error {
|
||||
return errors.New("proto: not implemented")
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func RegisterMessageSetType(Message, int32, string) {}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func EnumName(m map[int32]string, v int32) string {
|
||||
s, ok := m[v]
|
||||
if ok {
|
||||
return s
|
||||
}
|
||||
return strconv.Itoa(int(v))
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32, error) {
|
||||
if data[0] == '"' {
|
||||
// New style: enums are strings.
|
||||
var repr string
|
||||
if err := json.Unmarshal(data, &repr); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
val, ok := m[repr]
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("unrecognized enum %s value %q", enumName, repr)
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
// Old style: enums are ints.
|
||||
var val int32
|
||||
if err := json.Unmarshal(data, &val); err != nil {
|
||||
return 0, fmt.Errorf("cannot unmarshal %#q into enum %s", data, enumName)
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
// Deprecated: Do not use; this type existed for intenal-use only.
|
||||
type InternalMessageInfo struct{}
|
||||
|
||||
// Deprecated: Do not use; this method existed for intenal-use only.
|
||||
func (*InternalMessageInfo) DiscardUnknown(m Message) {
|
||||
DiscardUnknown(m)
|
||||
}
|
||||
|
||||
// Deprecated: Do not use; this method existed for intenal-use only.
|
||||
func (*InternalMessageInfo) Marshal(b []byte, m Message, deterministic bool) ([]byte, error) {
|
||||
return protoV2.MarshalOptions{Deterministic: deterministic}.MarshalAppend(b, MessageV2(m))
|
||||
}
|
||||
|
||||
// Deprecated: Do not use; this method existed for intenal-use only.
|
||||
func (*InternalMessageInfo) Merge(dst, src Message) {
|
||||
protoV2.Merge(MessageV2(dst), MessageV2(src))
|
||||
}
|
||||
|
||||
// Deprecated: Do not use; this method existed for intenal-use only.
|
||||
func (*InternalMessageInfo) Size(m Message) int {
|
||||
return protoV2.Size(MessageV2(m))
|
||||
}
|
||||
|
||||
// Deprecated: Do not use; this method existed for intenal-use only.
|
||||
func (*InternalMessageInfo) Unmarshal(m Message, b []byte) error {
|
||||
return protoV2.UnmarshalOptions{Merge: true}.Unmarshal(b, MessageV2(m))
|
||||
}
|
58
vendor/github.com/golang/protobuf/proto/discard.go
generated
vendored
58
vendor/github.com/golang/protobuf/proto/discard.go
generated
vendored
@ -1,58 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
)
|
||||
|
||||
// DiscardUnknown recursively discards all unknown fields from this message
|
||||
// and all embedded messages.
|
||||
//
|
||||
// When unmarshaling a message with unrecognized fields, the tags and values
|
||||
// of such fields are preserved in the Message. This allows a later call to
|
||||
// marshal to be able to produce a message that continues to have those
|
||||
// unrecognized fields. To avoid this, DiscardUnknown is used to
|
||||
// explicitly clear the unknown fields after unmarshaling.
|
||||
func DiscardUnknown(m Message) {
|
||||
if m != nil {
|
||||
discardUnknown(MessageReflect(m))
|
||||
}
|
||||
}
|
||||
|
||||
func discardUnknown(m protoreflect.Message) {
|
||||
m.Range(func(fd protoreflect.FieldDescriptor, val protoreflect.Value) bool {
|
||||
switch {
|
||||
// Handle singular message.
|
||||
case fd.Cardinality() != protoreflect.Repeated:
|
||||
if fd.Message() != nil {
|
||||
discardUnknown(m.Get(fd).Message())
|
||||
}
|
||||
// Handle list of messages.
|
||||
case fd.IsList():
|
||||
if fd.Message() != nil {
|
||||
ls := m.Get(fd).List()
|
||||
for i := 0; i < ls.Len(); i++ {
|
||||
discardUnknown(ls.Get(i).Message())
|
||||
}
|
||||
}
|
||||
// Handle map of messages.
|
||||
case fd.IsMap():
|
||||
if fd.MapValue().Message() != nil {
|
||||
ms := m.Get(fd).Map()
|
||||
ms.Range(func(_ protoreflect.MapKey, v protoreflect.Value) bool {
|
||||
discardUnknown(v.Message())
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
// Discard unknown fields.
|
||||
if len(m.GetUnknown()) > 0 {
|
||||
m.SetUnknown(nil)
|
||||
}
|
||||
}
|
356
vendor/github.com/golang/protobuf/proto/extensions.go
generated
vendored
356
vendor/github.com/golang/protobuf/proto/extensions.go
generated
vendored
@ -1,356 +0,0 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"google.golang.org/protobuf/encoding/protowire"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/reflect/protoregistry"
|
||||
"google.golang.org/protobuf/runtime/protoiface"
|
||||
"google.golang.org/protobuf/runtime/protoimpl"
|
||||
)
|
||||
|
||||
type (
|
||||
// ExtensionDesc represents an extension descriptor and
|
||||
// is used to interact with an extension field in a message.
|
||||
//
|
||||
// Variables of this type are generated in code by protoc-gen-go.
|
||||
ExtensionDesc = protoimpl.ExtensionInfo
|
||||
|
||||
// ExtensionRange represents a range of message extensions.
|
||||
// Used in code generated by protoc-gen-go.
|
||||
ExtensionRange = protoiface.ExtensionRangeV1
|
||||
|
||||
// Deprecated: Do not use; this is an internal type.
|
||||
Extension = protoimpl.ExtensionFieldV1
|
||||
|
||||
// Deprecated: Do not use; this is an internal type.
|
||||
XXX_InternalExtensions = protoimpl.ExtensionFields
|
||||
)
|
||||
|
||||
// ErrMissingExtension reports whether the extension was not present.
|
||||
var ErrMissingExtension = errors.New("proto: missing extension")
|
||||
|
||||
var errNotExtendable = errors.New("proto: not an extendable proto.Message")
|
||||
|
||||
// HasExtension reports whether the extension field is present in m
|
||||
// either as an explicitly populated field or as an unknown field.
|
||||
func HasExtension(m Message, xt *ExtensionDesc) (has bool) {
|
||||
mr := MessageReflect(m)
|
||||
if mr == nil || !mr.IsValid() {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check whether any populated known field matches the field number.
|
||||
xtd := xt.TypeDescriptor()
|
||||
if isValidExtension(mr.Descriptor(), xtd) {
|
||||
has = mr.Has(xtd)
|
||||
} else {
|
||||
mr.Range(func(fd protoreflect.FieldDescriptor, _ protoreflect.Value) bool {
|
||||
has = int32(fd.Number()) == xt.Field
|
||||
return !has
|
||||
})
|
||||
}
|
||||
|
||||
// Check whether any unknown field matches the field number.
|
||||
for b := mr.GetUnknown(); !has && len(b) > 0; {
|
||||
num, _, n := protowire.ConsumeField(b)
|
||||
has = int32(num) == xt.Field
|
||||
b = b[n:]
|
||||
}
|
||||
return has
|
||||
}
|
||||
|
||||
// ClearExtension removes the extension field from m
|
||||
// either as an explicitly populated field or as an unknown field.
|
||||
func ClearExtension(m Message, xt *ExtensionDesc) {
|
||||
mr := MessageReflect(m)
|
||||
if mr == nil || !mr.IsValid() {
|
||||
return
|
||||
}
|
||||
|
||||
xtd := xt.TypeDescriptor()
|
||||
if isValidExtension(mr.Descriptor(), xtd) {
|
||||
mr.Clear(xtd)
|
||||
} else {
|
||||
mr.Range(func(fd protoreflect.FieldDescriptor, _ protoreflect.Value) bool {
|
||||
if int32(fd.Number()) == xt.Field {
|
||||
mr.Clear(fd)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
clearUnknown(mr, fieldNum(xt.Field))
|
||||
}
|
||||
|
||||
// ClearAllExtensions clears all extensions from m.
|
||||
// This includes populated fields and unknown fields in the extension range.
|
||||
func ClearAllExtensions(m Message) {
|
||||
mr := MessageReflect(m)
|
||||
if mr == nil || !mr.IsValid() {
|
||||
return
|
||||
}
|
||||
|
||||
mr.Range(func(fd protoreflect.FieldDescriptor, _ protoreflect.Value) bool {
|
||||
if fd.IsExtension() {
|
||||
mr.Clear(fd)
|
||||
}
|
||||
return true
|
||||
})
|
||||
clearUnknown(mr, mr.Descriptor().ExtensionRanges())
|
||||
}
|
||||
|
||||
// GetExtension retrieves a proto2 extended field from m.
|
||||
//
|
||||
// If the descriptor is type complete (i.e., ExtensionDesc.ExtensionType is non-nil),
|
||||
// then GetExtension parses the encoded field and returns a Go value of the specified type.
|
||||
// If the field is not present, then the default value is returned (if one is specified),
|
||||
// otherwise ErrMissingExtension is reported.
|
||||
//
|
||||
// If the descriptor is type incomplete (i.e., ExtensionDesc.ExtensionType is nil),
|
||||
// then GetExtension returns the raw encoded bytes for the extension field.
|
||||
func GetExtension(m Message, xt *ExtensionDesc) (interface{}, error) {
|
||||
mr := MessageReflect(m)
|
||||
if mr == nil || !mr.IsValid() || mr.Descriptor().ExtensionRanges().Len() == 0 {
|
||||
return nil, errNotExtendable
|
||||
}
|
||||
|
||||
// Retrieve the unknown fields for this extension field.
|
||||
var bo protoreflect.RawFields
|
||||
for bi := mr.GetUnknown(); len(bi) > 0; {
|
||||
num, _, n := protowire.ConsumeField(bi)
|
||||
if int32(num) == xt.Field {
|
||||
bo = append(bo, bi[:n]...)
|
||||
}
|
||||
bi = bi[n:]
|
||||
}
|
||||
|
||||
// For type incomplete descriptors, only retrieve the unknown fields.
|
||||
if xt.ExtensionType == nil {
|
||||
return []byte(bo), nil
|
||||
}
|
||||
|
||||
// If the extension field only exists as unknown fields, unmarshal it.
|
||||
// This is rarely done since proto.Unmarshal eagerly unmarshals extensions.
|
||||
xtd := xt.TypeDescriptor()
|
||||
if !isValidExtension(mr.Descriptor(), xtd) {
|
||||
return nil, fmt.Errorf("proto: bad extended type; %T does not extend %T", xt.ExtendedType, m)
|
||||
}
|
||||
if !mr.Has(xtd) && len(bo) > 0 {
|
||||
m2 := mr.New()
|
||||
if err := (proto.UnmarshalOptions{
|
||||
Resolver: extensionResolver{xt},
|
||||
}.Unmarshal(bo, m2.Interface())); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if m2.Has(xtd) {
|
||||
mr.Set(xtd, m2.Get(xtd))
|
||||
clearUnknown(mr, fieldNum(xt.Field))
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether the message has the extension field set or a default.
|
||||
var pv protoreflect.Value
|
||||
switch {
|
||||
case mr.Has(xtd):
|
||||
pv = mr.Get(xtd)
|
||||
case xtd.HasDefault():
|
||||
pv = xtd.Default()
|
||||
default:
|
||||
return nil, ErrMissingExtension
|
||||
}
|
||||
|
||||
v := xt.InterfaceOf(pv)
|
||||
rv := reflect.ValueOf(v)
|
||||
if isScalarKind(rv.Kind()) {
|
||||
rv2 := reflect.New(rv.Type())
|
||||
rv2.Elem().Set(rv)
|
||||
v = rv2.Interface()
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// extensionResolver is a custom extension resolver that stores a single
|
||||
// extension type that takes precedence over the global registry.
|
||||
type extensionResolver struct{ xt protoreflect.ExtensionType }
|
||||
|
||||
func (r extensionResolver) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) {
|
||||
if xtd := r.xt.TypeDescriptor(); xtd.FullName() == field {
|
||||
return r.xt, nil
|
||||
}
|
||||
return protoregistry.GlobalTypes.FindExtensionByName(field)
|
||||
}
|
||||
|
||||
func (r extensionResolver) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) {
|
||||
if xtd := r.xt.TypeDescriptor(); xtd.ContainingMessage().FullName() == message && xtd.Number() == field {
|
||||
return r.xt, nil
|
||||
}
|
||||
return protoregistry.GlobalTypes.FindExtensionByNumber(message, field)
|
||||
}
|
||||
|
||||
// GetExtensions returns a list of the extensions values present in m,
|
||||
// corresponding with the provided list of extension descriptors, xts.
|
||||
// If an extension is missing in m, the corresponding value is nil.
|
||||
func GetExtensions(m Message, xts []*ExtensionDesc) ([]interface{}, error) {
|
||||
mr := MessageReflect(m)
|
||||
if mr == nil || !mr.IsValid() {
|
||||
return nil, errNotExtendable
|
||||
}
|
||||
|
||||
vs := make([]interface{}, len(xts))
|
||||
for i, xt := range xts {
|
||||
v, err := GetExtension(m, xt)
|
||||
if err != nil {
|
||||
if err == ErrMissingExtension {
|
||||
continue
|
||||
}
|
||||
return vs, err
|
||||
}
|
||||
vs[i] = v
|
||||
}
|
||||
return vs, nil
|
||||
}
|
||||
|
||||
// SetExtension sets an extension field in m to the provided value.
|
||||
func SetExtension(m Message, xt *ExtensionDesc, v interface{}) error {
|
||||
mr := MessageReflect(m)
|
||||
if mr == nil || !mr.IsValid() || mr.Descriptor().ExtensionRanges().Len() == 0 {
|
||||
return errNotExtendable
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(v)
|
||||
if reflect.TypeOf(v) != reflect.TypeOf(xt.ExtensionType) {
|
||||
return fmt.Errorf("proto: bad extension value type. got: %T, want: %T", v, xt.ExtensionType)
|
||||
}
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
if rv.IsNil() {
|
||||
return fmt.Errorf("proto: SetExtension called with nil value of type %T", v)
|
||||
}
|
||||
if isScalarKind(rv.Elem().Kind()) {
|
||||
v = rv.Elem().Interface()
|
||||
}
|
||||
}
|
||||
|
||||
xtd := xt.TypeDescriptor()
|
||||
if !isValidExtension(mr.Descriptor(), xtd) {
|
||||
return fmt.Errorf("proto: bad extended type; %T does not extend %T", xt.ExtendedType, m)
|
||||
}
|
||||
mr.Set(xtd, xt.ValueOf(v))
|
||||
clearUnknown(mr, fieldNum(xt.Field))
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetRawExtension inserts b into the unknown fields of m.
|
||||
//
|
||||
// Deprecated: Use Message.ProtoReflect.SetUnknown instead.
|
||||
func SetRawExtension(m Message, fnum int32, b []byte) {
|
||||
mr := MessageReflect(m)
|
||||
if mr == nil || !mr.IsValid() {
|
||||
return
|
||||
}
|
||||
|
||||
// Verify that the raw field is valid.
|
||||
for b0 := b; len(b0) > 0; {
|
||||
num, _, n := protowire.ConsumeField(b0)
|
||||
if int32(num) != fnum {
|
||||
panic(fmt.Sprintf("mismatching field number: got %d, want %d", num, fnum))
|
||||
}
|
||||
b0 = b0[n:]
|
||||
}
|
||||
|
||||
ClearExtension(m, &ExtensionDesc{Field: fnum})
|
||||
mr.SetUnknown(append(mr.GetUnknown(), b...))
|
||||
}
|
||||
|
||||
// ExtensionDescs returns a list of extension descriptors found in m,
|
||||
// containing descriptors for both populated extension fields in m and
|
||||
// also unknown fields of m that are in the extension range.
|
||||
// For the later case, an type incomplete descriptor is provided where only
|
||||
// the ExtensionDesc.Field field is populated.
|
||||
// The order of the extension descriptors is undefined.
|
||||
func ExtensionDescs(m Message) ([]*ExtensionDesc, error) {
|
||||
mr := MessageReflect(m)
|
||||
if mr == nil || !mr.IsValid() || mr.Descriptor().ExtensionRanges().Len() == 0 {
|
||||
return nil, errNotExtendable
|
||||
}
|
||||
|
||||
// Collect a set of known extension descriptors.
|
||||
extDescs := make(map[protoreflect.FieldNumber]*ExtensionDesc)
|
||||
mr.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
|
||||
if fd.IsExtension() {
|
||||
xt := fd.(protoreflect.ExtensionTypeDescriptor)
|
||||
if xd, ok := xt.Type().(*ExtensionDesc); ok {
|
||||
extDescs[fd.Number()] = xd
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
// Collect a set of unknown extension descriptors.
|
||||
extRanges := mr.Descriptor().ExtensionRanges()
|
||||
for b := mr.GetUnknown(); len(b) > 0; {
|
||||
num, _, n := protowire.ConsumeField(b)
|
||||
if extRanges.Has(num) && extDescs[num] == nil {
|
||||
extDescs[num] = nil
|
||||
}
|
||||
b = b[n:]
|
||||
}
|
||||
|
||||
// Transpose the set of descriptors into a list.
|
||||
var xts []*ExtensionDesc
|
||||
for num, xt := range extDescs {
|
||||
if xt == nil {
|
||||
xt = &ExtensionDesc{Field: int32(num)}
|
||||
}
|
||||
xts = append(xts, xt)
|
||||
}
|
||||
return xts, nil
|
||||
}
|
||||
|
||||
// isValidExtension reports whether xtd is a valid extension descriptor for md.
|
||||
func isValidExtension(md protoreflect.MessageDescriptor, xtd protoreflect.ExtensionTypeDescriptor) bool {
|
||||
return xtd.ContainingMessage() == md && md.ExtensionRanges().Has(xtd.Number())
|
||||
}
|
||||
|
||||
// isScalarKind reports whether k is a protobuf scalar kind (except bytes).
|
||||
// This function exists for historical reasons since the representation of
|
||||
// scalars differs between v1 and v2, where v1 uses *T and v2 uses T.
|
||||
func isScalarKind(k reflect.Kind) bool {
|
||||
switch k {
|
||||
case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// clearUnknown removes unknown fields from m where remover.Has reports true.
|
||||
func clearUnknown(m protoreflect.Message, remover interface {
|
||||
Has(protoreflect.FieldNumber) bool
|
||||
}) {
|
||||
var bo protoreflect.RawFields
|
||||
for bi := m.GetUnknown(); len(bi) > 0; {
|
||||
num, _, n := protowire.ConsumeField(bi)
|
||||
if !remover.Has(num) {
|
||||
bo = append(bo, bi[:n]...)
|
||||
}
|
||||
bi = bi[n:]
|
||||
}
|
||||
if bi := m.GetUnknown(); len(bi) != len(bo) {
|
||||
m.SetUnknown(bo)
|
||||
}
|
||||
}
|
||||
|
||||
type fieldNum protoreflect.FieldNumber
|
||||
|
||||
func (n1 fieldNum) Has(n2 protoreflect.FieldNumber) bool {
|
||||
return protoreflect.FieldNumber(n1) == n2
|
||||
}
|
306
vendor/github.com/golang/protobuf/proto/properties.go
generated
vendored
306
vendor/github.com/golang/protobuf/proto/properties.go
generated
vendored
@ -1,306 +0,0 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/runtime/protoimpl"
|
||||
)
|
||||
|
||||
// StructProperties represents protocol buffer type information for a
|
||||
// generated protobuf message in the open-struct API.
|
||||
//
|
||||
// Deprecated: Do not use.
|
||||
type StructProperties struct {
|
||||
// Prop are the properties for each field.
|
||||
//
|
||||
// Fields belonging to a oneof are stored in OneofTypes instead, with a
|
||||
// single Properties representing the parent oneof held here.
|
||||
//
|
||||
// The order of Prop matches the order of fields in the Go struct.
|
||||
// Struct fields that are not related to protobufs have a "XXX_" prefix
|
||||
// in the Properties.Name and must be ignored by the user.
|
||||
Prop []*Properties
|
||||
|
||||
// OneofTypes contains information about the oneof fields in this message.
|
||||
// It is keyed by the protobuf field name.
|
||||
OneofTypes map[string]*OneofProperties
|
||||
}
|
||||
|
||||
// Properties represents the type information for a protobuf message field.
|
||||
//
|
||||
// Deprecated: Do not use.
|
||||
type Properties struct {
|
||||
// Name is a placeholder name with little meaningful semantic value.
|
||||
// If the name has an "XXX_" prefix, the entire Properties must be ignored.
|
||||
Name string
|
||||
// OrigName is the protobuf field name or oneof name.
|
||||
OrigName string
|
||||
// JSONName is the JSON name for the protobuf field.
|
||||
JSONName string
|
||||
// Enum is a placeholder name for enums.
|
||||
// For historical reasons, this is neither the Go name for the enum,
|
||||
// nor the protobuf name for the enum.
|
||||
Enum string // Deprecated: Do not use.
|
||||
// Weak contains the full name of the weakly referenced message.
|
||||
Weak string
|
||||
// Wire is a string representation of the wire type.
|
||||
Wire string
|
||||
// WireType is the protobuf wire type for the field.
|
||||
WireType int
|
||||
// Tag is the protobuf field number.
|
||||
Tag int
|
||||
// Required reports whether this is a required field.
|
||||
Required bool
|
||||
// Optional reports whether this is a optional field.
|
||||
Optional bool
|
||||
// Repeated reports whether this is a repeated field.
|
||||
Repeated bool
|
||||
// Packed reports whether this is a packed repeated field of scalars.
|
||||
Packed bool
|
||||
// Proto3 reports whether this field operates under the proto3 syntax.
|
||||
Proto3 bool
|
||||
// Oneof reports whether this field belongs within a oneof.
|
||||
Oneof bool
|
||||
|
||||
// Default is the default value in string form.
|
||||
Default string
|
||||
// HasDefault reports whether the field has a default value.
|
||||
HasDefault bool
|
||||
|
||||
// MapKeyProp is the properties for the key field for a map field.
|
||||
MapKeyProp *Properties
|
||||
// MapValProp is the properties for the value field for a map field.
|
||||
MapValProp *Properties
|
||||
}
|
||||
|
||||
// OneofProperties represents the type information for a protobuf oneof.
|
||||
//
|
||||
// Deprecated: Do not use.
|
||||
type OneofProperties struct {
|
||||
// Type is a pointer to the generated wrapper type for the field value.
|
||||
// This is nil for messages that are not in the open-struct API.
|
||||
Type reflect.Type
|
||||
// Field is the index into StructProperties.Prop for the containing oneof.
|
||||
Field int
|
||||
// Prop is the properties for the field.
|
||||
Prop *Properties
|
||||
}
|
||||
|
||||
// String formats the properties in the protobuf struct field tag style.
|
||||
func (p *Properties) String() string {
|
||||
s := p.Wire
|
||||
s += "," + strconv.Itoa(p.Tag)
|
||||
if p.Required {
|
||||
s += ",req"
|
||||
}
|
||||
if p.Optional {
|
||||
s += ",opt"
|
||||
}
|
||||
if p.Repeated {
|
||||
s += ",rep"
|
||||
}
|
||||
if p.Packed {
|
||||
s += ",packed"
|
||||
}
|
||||
s += ",name=" + p.OrigName
|
||||
if p.JSONName != "" {
|
||||
s += ",json=" + p.JSONName
|
||||
}
|
||||
if len(p.Enum) > 0 {
|
||||
s += ",enum=" + p.Enum
|
||||
}
|
||||
if len(p.Weak) > 0 {
|
||||
s += ",weak=" + p.Weak
|
||||
}
|
||||
if p.Proto3 {
|
||||
s += ",proto3"
|
||||
}
|
||||
if p.Oneof {
|
||||
s += ",oneof"
|
||||
}
|
||||
if p.HasDefault {
|
||||
s += ",def=" + p.Default
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Parse populates p by parsing a string in the protobuf struct field tag style.
|
||||
func (p *Properties) Parse(tag string) {
|
||||
// For example: "bytes,49,opt,name=foo,def=hello!"
|
||||
for len(tag) > 0 {
|
||||
i := strings.IndexByte(tag, ',')
|
||||
if i < 0 {
|
||||
i = len(tag)
|
||||
}
|
||||
switch s := tag[:i]; {
|
||||
case strings.HasPrefix(s, "name="):
|
||||
p.OrigName = s[len("name="):]
|
||||
case strings.HasPrefix(s, "json="):
|
||||
p.JSONName = s[len("json="):]
|
||||
case strings.HasPrefix(s, "enum="):
|
||||
p.Enum = s[len("enum="):]
|
||||
case strings.HasPrefix(s, "weak="):
|
||||
p.Weak = s[len("weak="):]
|
||||
case strings.Trim(s, "0123456789") == "":
|
||||
n, _ := strconv.ParseUint(s, 10, 32)
|
||||
p.Tag = int(n)
|
||||
case s == "opt":
|
||||
p.Optional = true
|
||||
case s == "req":
|
||||
p.Required = true
|
||||
case s == "rep":
|
||||
p.Repeated = true
|
||||
case s == "varint" || s == "zigzag32" || s == "zigzag64":
|
||||
p.Wire = s
|
||||
p.WireType = WireVarint
|
||||
case s == "fixed32":
|
||||
p.Wire = s
|
||||
p.WireType = WireFixed32
|
||||
case s == "fixed64":
|
||||
p.Wire = s
|
||||
p.WireType = WireFixed64
|
||||
case s == "bytes":
|
||||
p.Wire = s
|
||||
p.WireType = WireBytes
|
||||
case s == "group":
|
||||
p.Wire = s
|
||||
p.WireType = WireStartGroup
|
||||
case s == "packed":
|
||||
p.Packed = true
|
||||
case s == "proto3":
|
||||
p.Proto3 = true
|
||||
case s == "oneof":
|
||||
p.Oneof = true
|
||||
case strings.HasPrefix(s, "def="):
|
||||
// The default tag is special in that everything afterwards is the
|
||||
// default regardless of the presence of commas.
|
||||
p.HasDefault = true
|
||||
p.Default, i = tag[len("def="):], len(tag)
|
||||
}
|
||||
tag = strings.TrimPrefix(tag[i:], ",")
|
||||
}
|
||||
}
|
||||
|
||||
// Init populates the properties from a protocol buffer struct tag.
|
||||
//
|
||||
// Deprecated: Do not use.
|
||||
func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
|
||||
p.Name = name
|
||||
p.OrigName = name
|
||||
if tag == "" {
|
||||
return
|
||||
}
|
||||
p.Parse(tag)
|
||||
|
||||
if typ != nil && typ.Kind() == reflect.Map {
|
||||
p.MapKeyProp = new(Properties)
|
||||
p.MapKeyProp.Init(nil, "Key", f.Tag.Get("protobuf_key"), nil)
|
||||
p.MapValProp = new(Properties)
|
||||
p.MapValProp.Init(nil, "Value", f.Tag.Get("protobuf_val"), nil)
|
||||
}
|
||||
}
|
||||
|
||||
var propertiesCache sync.Map // map[reflect.Type]*StructProperties
|
||||
|
||||
// GetProperties returns the list of properties for the type represented by t,
|
||||
// which must be a generated protocol buffer message in the open-struct API,
|
||||
// where protobuf message fields are represented by exported Go struct fields.
|
||||
//
|
||||
// Deprecated: Use protobuf reflection instead.
|
||||
func GetProperties(t reflect.Type) *StructProperties {
|
||||
if p, ok := propertiesCache.Load(t); ok {
|
||||
return p.(*StructProperties)
|
||||
}
|
||||
p, _ := propertiesCache.LoadOrStore(t, newProperties(t))
|
||||
return p.(*StructProperties)
|
||||
}
|
||||
|
||||
func newProperties(t reflect.Type) *StructProperties {
|
||||
if t.Kind() != reflect.Struct {
|
||||
panic(fmt.Sprintf("%v is not a generated message in the open-struct API", t))
|
||||
}
|
||||
|
||||
var hasOneof bool
|
||||
prop := new(StructProperties)
|
||||
|
||||
// Construct a list of properties for each field in the struct.
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
p := new(Properties)
|
||||
f := t.Field(i)
|
||||
tagField := f.Tag.Get("protobuf")
|
||||
p.Init(f.Type, f.Name, tagField, &f)
|
||||
|
||||
tagOneof := f.Tag.Get("protobuf_oneof")
|
||||
if tagOneof != "" {
|
||||
hasOneof = true
|
||||
p.OrigName = tagOneof
|
||||
}
|
||||
|
||||
// Rename unrelated struct fields with the "XXX_" prefix since so much
|
||||
// user code simply checks for this to exclude special fields.
|
||||
if tagField == "" && tagOneof == "" && !strings.HasPrefix(p.Name, "XXX_") {
|
||||
p.Name = "XXX_" + p.Name
|
||||
p.OrigName = "XXX_" + p.OrigName
|
||||
} else if p.Weak != "" {
|
||||
p.Name = p.OrigName // avoid possible "XXX_" prefix on weak field
|
||||
}
|
||||
|
||||
prop.Prop = append(prop.Prop, p)
|
||||
}
|
||||
|
||||
// Construct a mapping of oneof field names to properties.
|
||||
if hasOneof {
|
||||
var oneofWrappers []interface{}
|
||||
if fn, ok := reflect.PtrTo(t).MethodByName("XXX_OneofFuncs"); ok {
|
||||
oneofWrappers = fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))})[3].Interface().([]interface{})
|
||||
}
|
||||
if fn, ok := reflect.PtrTo(t).MethodByName("XXX_OneofWrappers"); ok {
|
||||
oneofWrappers = fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))})[0].Interface().([]interface{})
|
||||
}
|
||||
if m, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(protoreflect.ProtoMessage); ok {
|
||||
if m, ok := m.ProtoReflect().(interface{ ProtoMessageInfo() *protoimpl.MessageInfo }); ok {
|
||||
oneofWrappers = m.ProtoMessageInfo().OneofWrappers
|
||||
}
|
||||
}
|
||||
|
||||
prop.OneofTypes = make(map[string]*OneofProperties)
|
||||
for _, wrapper := range oneofWrappers {
|
||||
p := &OneofProperties{
|
||||
Type: reflect.ValueOf(wrapper).Type(), // *T
|
||||
Prop: new(Properties),
|
||||
}
|
||||
f := p.Type.Elem().Field(0)
|
||||
p.Prop.Name = f.Name
|
||||
p.Prop.Parse(f.Tag.Get("protobuf"))
|
||||
|
||||
// Determine the struct field that contains this oneof.
|
||||
// Each wrapper is assignable to exactly one parent field.
|
||||
var foundOneof bool
|
||||
for i := 0; i < t.NumField() && !foundOneof; i++ {
|
||||
if p.Type.AssignableTo(t.Field(i).Type) {
|
||||
p.Field = i
|
||||
foundOneof = true
|
||||
}
|
||||
}
|
||||
if !foundOneof {
|
||||
panic(fmt.Sprintf("%v is not a generated message in the open-struct API", t))
|
||||
}
|
||||
prop.OneofTypes[p.Prop.OrigName] = p
|
||||
}
|
||||
}
|
||||
|
||||
return prop
|
||||
}
|
||||
|
||||
func (sp *StructProperties) Len() int { return len(sp.Prop) }
|
||||
func (sp *StructProperties) Less(i, j int) bool { return false }
|
||||
func (sp *StructProperties) Swap(i, j int) { return }
|
167
vendor/github.com/golang/protobuf/proto/proto.go
generated
vendored
167
vendor/github.com/golang/protobuf/proto/proto.go
generated
vendored
@ -1,167 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package proto provides functionality for handling protocol buffer messages.
|
||||
// In particular, it provides marshaling and unmarshaling between a protobuf
|
||||
// message and the binary wire format.
|
||||
//
|
||||
// See https://developers.google.com/protocol-buffers/docs/gotutorial for
|
||||
// more information.
|
||||
//
|
||||
// Deprecated: Use the "google.golang.org/protobuf/proto" package instead.
|
||||
package proto
|
||||
|
||||
import (
|
||||
protoV2 "google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/runtime/protoiface"
|
||||
"google.golang.org/protobuf/runtime/protoimpl"
|
||||
)
|
||||
|
||||
const (
|
||||
ProtoPackageIsVersion1 = true
|
||||
ProtoPackageIsVersion2 = true
|
||||
ProtoPackageIsVersion3 = true
|
||||
ProtoPackageIsVersion4 = true
|
||||
)
|
||||
|
||||
// GeneratedEnum is any enum type generated by protoc-gen-go
|
||||
// which is a named int32 kind.
|
||||
// This type exists for documentation purposes.
|
||||
type GeneratedEnum interface{}
|
||||
|
||||
// GeneratedMessage is any message type generated by protoc-gen-go
|
||||
// which is a pointer to a named struct kind.
|
||||
// This type exists for documentation purposes.
|
||||
type GeneratedMessage interface{}
|
||||
|
||||
// Message is a protocol buffer message.
|
||||
//
|
||||
// This is the v1 version of the message interface and is marginally better
|
||||
// than an empty interface as it lacks any method to programatically interact
|
||||
// with the contents of the message.
|
||||
//
|
||||
// A v2 message is declared in "google.golang.org/protobuf/proto".Message and
|
||||
// exposes protobuf reflection as a first-class feature of the interface.
|
||||
//
|
||||
// To convert a v1 message to a v2 message, use the MessageV2 function.
|
||||
// To convert a v2 message to a v1 message, use the MessageV1 function.
|
||||
type Message = protoiface.MessageV1
|
||||
|
||||
// MessageV1 converts either a v1 or v2 message to a v1 message.
|
||||
// It returns nil if m is nil.
|
||||
func MessageV1(m GeneratedMessage) protoiface.MessageV1 {
|
||||
return protoimpl.X.ProtoMessageV1Of(m)
|
||||
}
|
||||
|
||||
// MessageV2 converts either a v1 or v2 message to a v2 message.
|
||||
// It returns nil if m is nil.
|
||||
func MessageV2(m GeneratedMessage) protoV2.Message {
|
||||
return protoimpl.X.ProtoMessageV2Of(m)
|
||||
}
|
||||
|
||||
// MessageReflect returns a reflective view for a message.
|
||||
// It returns nil if m is nil.
|
||||
func MessageReflect(m Message) protoreflect.Message {
|
||||
return protoimpl.X.MessageOf(m)
|
||||
}
|
||||
|
||||
// Marshaler is implemented by messages that can marshal themselves.
|
||||
// This interface is used by the following functions: Size, Marshal,
|
||||
// Buffer.Marshal, and Buffer.EncodeMessage.
|
||||
//
|
||||
// Deprecated: Do not implement.
|
||||
type Marshaler interface {
|
||||
// Marshal formats the encoded bytes of the message.
|
||||
// It should be deterministic and emit valid protobuf wire data.
|
||||
// The caller takes ownership of the returned buffer.
|
||||
Marshal() ([]byte, error)
|
||||
}
|
||||
|
||||
// Unmarshaler is implemented by messages that can unmarshal themselves.
|
||||
// This interface is used by the following functions: Unmarshal, UnmarshalMerge,
|
||||
// Buffer.Unmarshal, Buffer.DecodeMessage, and Buffer.DecodeGroup.
|
||||
//
|
||||
// Deprecated: Do not implement.
|
||||
type Unmarshaler interface {
|
||||
// Unmarshal parses the encoded bytes of the protobuf wire input.
|
||||
// The provided buffer is only valid for during method call.
|
||||
// It should not reset the receiver message.
|
||||
Unmarshal([]byte) error
|
||||
}
|
||||
|
||||
// Merger is implemented by messages that can merge themselves.
|
||||
// This interface is used by the following functions: Clone and Merge.
|
||||
//
|
||||
// Deprecated: Do not implement.
|
||||
type Merger interface {
|
||||
// Merge merges the contents of src into the receiver message.
|
||||
// It clones all data structures in src such that it aliases no mutable
|
||||
// memory referenced by src.
|
||||
Merge(src Message)
|
||||
}
|
||||
|
||||
// RequiredNotSetError is an error type returned when
|
||||
// marshaling or unmarshaling a message with missing required fields.
|
||||
type RequiredNotSetError struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (e *RequiredNotSetError) Error() string {
|
||||
if e.err != nil {
|
||||
return e.err.Error()
|
||||
}
|
||||
return "proto: required field not set"
|
||||
}
|
||||
func (e *RequiredNotSetError) RequiredNotSet() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func checkRequiredNotSet(m protoV2.Message) error {
|
||||
if err := protoV2.CheckInitialized(m); err != nil {
|
||||
return &RequiredNotSetError{err: err}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Clone returns a deep copy of src.
|
||||
func Clone(src Message) Message {
|
||||
return MessageV1(protoV2.Clone(MessageV2(src)))
|
||||
}
|
||||
|
||||
// Merge merges src into dst, which must be messages of the same type.
|
||||
//
|
||||
// Populated scalar fields in src are copied to dst, while populated
|
||||
// singular messages in src are merged into dst by recursively calling Merge.
|
||||
// The elements of every list field in src is appended to the corresponded
|
||||
// list fields in dst. The entries of every map field in src is copied into
|
||||
// the corresponding map field in dst, possibly replacing existing entries.
|
||||
// The unknown fields of src are appended to the unknown fields of dst.
|
||||
func Merge(dst, src Message) {
|
||||
protoV2.Merge(MessageV2(dst), MessageV2(src))
|
||||
}
|
||||
|
||||
// Equal reports whether two messages are equal.
|
||||
// If two messages marshal to the same bytes under deterministic serialization,
|
||||
// then Equal is guaranteed to report true.
|
||||
//
|
||||
// Two messages are equal if they are the same protobuf message type,
|
||||
// have the same set of populated known and extension field values,
|
||||
// and the same set of unknown fields values.
|
||||
//
|
||||
// Scalar values are compared with the equivalent of the == operator in Go,
|
||||
// except bytes values which are compared using bytes.Equal and
|
||||
// floating point values which specially treat NaNs as equal.
|
||||
// Message values are compared by recursively calling Equal.
|
||||
// Lists are equal if each element value is also equal.
|
||||
// Maps are equal if they have the same set of keys, where the pair of values
|
||||
// for each key is also equal.
|
||||
func Equal(x, y Message) bool {
|
||||
return protoV2.Equal(MessageV2(x), MessageV2(y))
|
||||
}
|
||||
|
||||
func isMessageSet(md protoreflect.MessageDescriptor) bool {
|
||||
ms, ok := md.(interface{ IsMessageSet() bool })
|
||||
return ok && ms.IsMessageSet()
|
||||
}
|
317
vendor/github.com/golang/protobuf/proto/registry.go
generated
vendored
317
vendor/github.com/golang/protobuf/proto/registry.go
generated
vendored
@ -1,317 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/protobuf/reflect/protodesc"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/reflect/protoregistry"
|
||||
"google.golang.org/protobuf/runtime/protoimpl"
|
||||
)
|
||||
|
||||
// filePath is the path to the proto source file.
|
||||
type filePath = string // e.g., "google/protobuf/descriptor.proto"
|
||||
|
||||
// fileDescGZIP is the compressed contents of the encoded FileDescriptorProto.
|
||||
type fileDescGZIP = []byte
|
||||
|
||||
var fileCache sync.Map // map[filePath]fileDescGZIP
|
||||
|
||||
// RegisterFile is called from generated code to register the compressed
|
||||
// FileDescriptorProto with the file path for a proto source file.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalFiles.RegisterFile instead.
|
||||
func RegisterFile(s filePath, d fileDescGZIP) {
|
||||
// Decompress the descriptor.
|
||||
zr, err := gzip.NewReader(bytes.NewReader(d))
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("proto: invalid compressed file descriptor: %v", err))
|
||||
}
|
||||
b, err := ioutil.ReadAll(zr)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("proto: invalid compressed file descriptor: %v", err))
|
||||
}
|
||||
|
||||
// Construct a protoreflect.FileDescriptor from the raw descriptor.
|
||||
// Note that DescBuilder.Build automatically registers the constructed
|
||||
// file descriptor with the v2 registry.
|
||||
protoimpl.DescBuilder{RawDescriptor: b}.Build()
|
||||
|
||||
// Locally cache the raw descriptor form for the file.
|
||||
fileCache.Store(s, d)
|
||||
}
|
||||
|
||||
// FileDescriptor returns the compressed FileDescriptorProto given the file path
|
||||
// for a proto source file. It returns nil if not found.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalFiles.FindFileByPath instead.
|
||||
func FileDescriptor(s filePath) fileDescGZIP {
|
||||
if v, ok := fileCache.Load(s); ok {
|
||||
return v.(fileDescGZIP)
|
||||
}
|
||||
|
||||
// Find the descriptor in the v2 registry.
|
||||
var b []byte
|
||||
if fd, _ := protoregistry.GlobalFiles.FindFileByPath(s); fd != nil {
|
||||
b, _ = Marshal(protodesc.ToFileDescriptorProto(fd))
|
||||
}
|
||||
|
||||
// Locally cache the raw descriptor form for the file.
|
||||
if len(b) > 0 {
|
||||
v, _ := fileCache.LoadOrStore(s, protoimpl.X.CompressGZIP(b))
|
||||
return v.(fileDescGZIP)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// enumName is the name of an enum. For historical reasons, the enum name is
|
||||
// neither the full Go name nor the full protobuf name of the enum.
|
||||
// The name is the dot-separated combination of just the proto package that the
|
||||
// enum is declared within followed by the Go type name of the generated enum.
|
||||
type enumName = string // e.g., "my.proto.package.GoMessage_GoEnum"
|
||||
|
||||
// enumsByName maps enum values by name to their numeric counterpart.
|
||||
type enumsByName = map[string]int32
|
||||
|
||||
// enumsByNumber maps enum values by number to their name counterpart.
|
||||
type enumsByNumber = map[int32]string
|
||||
|
||||
var enumCache sync.Map // map[enumName]enumsByName
|
||||
var numFilesCache sync.Map // map[protoreflect.FullName]int
|
||||
|
||||
// RegisterEnum is called from the generated code to register the mapping of
|
||||
// enum value names to enum numbers for the enum identified by s.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalTypes.RegisterEnum instead.
|
||||
func RegisterEnum(s enumName, _ enumsByNumber, m enumsByName) {
|
||||
if _, ok := enumCache.Load(s); ok {
|
||||
panic("proto: duplicate enum registered: " + s)
|
||||
}
|
||||
enumCache.Store(s, m)
|
||||
|
||||
// This does not forward registration to the v2 registry since this API
|
||||
// lacks sufficient information to construct a complete v2 enum descriptor.
|
||||
}
|
||||
|
||||
// EnumValueMap returns the mapping from enum value names to enum numbers for
|
||||
// the enum of the given name. It returns nil if not found.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalTypes.FindEnumByName instead.
|
||||
func EnumValueMap(s enumName) enumsByName {
|
||||
if v, ok := enumCache.Load(s); ok {
|
||||
return v.(enumsByName)
|
||||
}
|
||||
|
||||
// Check whether the cache is stale. If the number of files in the current
|
||||
// package differs, then it means that some enums may have been recently
|
||||
// registered upstream that we do not know about.
|
||||
var protoPkg protoreflect.FullName
|
||||
if i := strings.LastIndexByte(s, '.'); i >= 0 {
|
||||
protoPkg = protoreflect.FullName(s[:i])
|
||||
}
|
||||
v, _ := numFilesCache.Load(protoPkg)
|
||||
numFiles, _ := v.(int)
|
||||
if protoregistry.GlobalFiles.NumFilesByPackage(protoPkg) == numFiles {
|
||||
return nil // cache is up-to-date; was not found earlier
|
||||
}
|
||||
|
||||
// Update the enum cache for all enums declared in the given proto package.
|
||||
numFiles = 0
|
||||
protoregistry.GlobalFiles.RangeFilesByPackage(protoPkg, func(fd protoreflect.FileDescriptor) bool {
|
||||
walkEnums(fd, func(ed protoreflect.EnumDescriptor) {
|
||||
name := protoimpl.X.LegacyEnumName(ed)
|
||||
if _, ok := enumCache.Load(name); !ok {
|
||||
m := make(enumsByName)
|
||||
evs := ed.Values()
|
||||
for i := evs.Len() - 1; i >= 0; i-- {
|
||||
ev := evs.Get(i)
|
||||
m[string(ev.Name())] = int32(ev.Number())
|
||||
}
|
||||
enumCache.LoadOrStore(name, m)
|
||||
}
|
||||
})
|
||||
numFiles++
|
||||
return true
|
||||
})
|
||||
numFilesCache.Store(protoPkg, numFiles)
|
||||
|
||||
// Check cache again for enum map.
|
||||
if v, ok := enumCache.Load(s); ok {
|
||||
return v.(enumsByName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// walkEnums recursively walks all enums declared in d.
|
||||
func walkEnums(d interface {
|
||||
Enums() protoreflect.EnumDescriptors
|
||||
Messages() protoreflect.MessageDescriptors
|
||||
}, f func(protoreflect.EnumDescriptor)) {
|
||||
eds := d.Enums()
|
||||
for i := eds.Len() - 1; i >= 0; i-- {
|
||||
f(eds.Get(i))
|
||||
}
|
||||
mds := d.Messages()
|
||||
for i := mds.Len() - 1; i >= 0; i-- {
|
||||
walkEnums(mds.Get(i), f)
|
||||
}
|
||||
}
|
||||
|
||||
// messageName is the full name of protobuf message.
|
||||
type messageName = string
|
||||
|
||||
var messageTypeCache sync.Map // map[messageName]reflect.Type
|
||||
|
||||
// RegisterType is called from generated code to register the message Go type
|
||||
// for a message of the given name.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalTypes.RegisterMessage instead.
|
||||
func RegisterType(m Message, s messageName) {
|
||||
mt := protoimpl.X.LegacyMessageTypeOf(m, protoreflect.FullName(s))
|
||||
if err := protoregistry.GlobalTypes.RegisterMessage(mt); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
messageTypeCache.Store(s, reflect.TypeOf(m))
|
||||
}
|
||||
|
||||
// RegisterMapType is called from generated code to register the Go map type
|
||||
// for a protobuf message representing a map entry.
|
||||
//
|
||||
// Deprecated: Do not use.
|
||||
func RegisterMapType(m interface{}, s messageName) {
|
||||
t := reflect.TypeOf(m)
|
||||
if t.Kind() != reflect.Map {
|
||||
panic(fmt.Sprintf("invalid map kind: %v", t))
|
||||
}
|
||||
if _, ok := messageTypeCache.Load(s); ok {
|
||||
panic(fmt.Errorf("proto: duplicate proto message registered: %s", s))
|
||||
}
|
||||
messageTypeCache.Store(s, t)
|
||||
}
|
||||
|
||||
// MessageType returns the message type for a named message.
|
||||
// It returns nil if not found.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalTypes.FindMessageByName instead.
|
||||
func MessageType(s messageName) reflect.Type {
|
||||
if v, ok := messageTypeCache.Load(s); ok {
|
||||
return v.(reflect.Type)
|
||||
}
|
||||
|
||||
// Derive the message type from the v2 registry.
|
||||
var t reflect.Type
|
||||
if mt, _ := protoregistry.GlobalTypes.FindMessageByName(protoreflect.FullName(s)); mt != nil {
|
||||
t = messageGoType(mt)
|
||||
}
|
||||
|
||||
// If we could not get a concrete type, it is possible that it is a
|
||||
// pseudo-message for a map entry.
|
||||
if t == nil {
|
||||
d, _ := protoregistry.GlobalFiles.FindDescriptorByName(protoreflect.FullName(s))
|
||||
if md, _ := d.(protoreflect.MessageDescriptor); md != nil && md.IsMapEntry() {
|
||||
kt := goTypeForField(md.Fields().ByNumber(1))
|
||||
vt := goTypeForField(md.Fields().ByNumber(2))
|
||||
t = reflect.MapOf(kt, vt)
|
||||
}
|
||||
}
|
||||
|
||||
// Locally cache the message type for the given name.
|
||||
if t != nil {
|
||||
v, _ := messageTypeCache.LoadOrStore(s, t)
|
||||
return v.(reflect.Type)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func goTypeForField(fd protoreflect.FieldDescriptor) reflect.Type {
|
||||
switch k := fd.Kind(); k {
|
||||
case protoreflect.EnumKind:
|
||||
if et, _ := protoregistry.GlobalTypes.FindEnumByName(fd.Enum().FullName()); et != nil {
|
||||
return enumGoType(et)
|
||||
}
|
||||
return reflect.TypeOf(protoreflect.EnumNumber(0))
|
||||
case protoreflect.MessageKind, protoreflect.GroupKind:
|
||||
if mt, _ := protoregistry.GlobalTypes.FindMessageByName(fd.Message().FullName()); mt != nil {
|
||||
return messageGoType(mt)
|
||||
}
|
||||
return reflect.TypeOf((*protoreflect.Message)(nil)).Elem()
|
||||
default:
|
||||
return reflect.TypeOf(fd.Default().Interface())
|
||||
}
|
||||
}
|
||||
|
||||
func enumGoType(et protoreflect.EnumType) reflect.Type {
|
||||
return reflect.TypeOf(et.New(0))
|
||||
}
|
||||
|
||||
func messageGoType(mt protoreflect.MessageType) reflect.Type {
|
||||
return reflect.TypeOf(MessageV1(mt.Zero().Interface()))
|
||||
}
|
||||
|
||||
// MessageName returns the full protobuf name for the given message type.
|
||||
//
|
||||
// Deprecated: Use protoreflect.MessageDescriptor.FullName instead.
|
||||
func MessageName(m Message) messageName {
|
||||
if m == nil {
|
||||
return ""
|
||||
}
|
||||
if m, ok := m.(interface{ XXX_MessageName() messageName }); ok {
|
||||
return m.XXX_MessageName()
|
||||
}
|
||||
return messageName(protoimpl.X.MessageDescriptorOf(m).FullName())
|
||||
}
|
||||
|
||||
// RegisterExtension is called from the generated code to register
|
||||
// the extension descriptor.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalTypes.RegisterExtension instead.
|
||||
func RegisterExtension(d *ExtensionDesc) {
|
||||
if err := protoregistry.GlobalTypes.RegisterExtension(d); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
type extensionsByNumber = map[int32]*ExtensionDesc
|
||||
|
||||
var extensionCache sync.Map // map[messageName]extensionsByNumber
|
||||
|
||||
// RegisteredExtensions returns a map of the registered extensions for the
|
||||
// provided protobuf message, indexed by the extension field number.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalTypes.RangeExtensionsByMessage instead.
|
||||
func RegisteredExtensions(m Message) extensionsByNumber {
|
||||
// Check whether the cache is stale. If the number of extensions for
|
||||
// the given message differs, then it means that some extensions were
|
||||
// recently registered upstream that we do not know about.
|
||||
s := MessageName(m)
|
||||
v, _ := extensionCache.Load(s)
|
||||
xs, _ := v.(extensionsByNumber)
|
||||
if protoregistry.GlobalTypes.NumExtensionsByMessage(protoreflect.FullName(s)) == len(xs) {
|
||||
return xs // cache is up-to-date
|
||||
}
|
||||
|
||||
// Cache is stale, re-compute the extensions map.
|
||||
xs = make(extensionsByNumber)
|
||||
protoregistry.GlobalTypes.RangeExtensionsByMessage(protoreflect.FullName(s), func(xt protoreflect.ExtensionType) bool {
|
||||
if xd, ok := xt.(*ExtensionDesc); ok {
|
||||
xs[int32(xt.TypeDescriptor().Number())] = xd
|
||||
} else {
|
||||
// TODO: This implies that the protoreflect.ExtensionType is a
|
||||
// custom type not generated by protoc-gen-go. We could try and
|
||||
// convert the type to an ExtensionDesc.
|
||||
}
|
||||
return true
|
||||
})
|
||||
extensionCache.Store(s, xs)
|
||||
return xs
|
||||
}
|
801
vendor/github.com/golang/protobuf/proto/text_decode.go
generated
vendored
801
vendor/github.com/golang/protobuf/proto/text_decode.go
generated
vendored
@ -1,801 +0,0 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"google.golang.org/protobuf/encoding/prototext"
|
||||
protoV2 "google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/reflect/protoregistry"
|
||||
)
|
||||
|
||||
const wrapTextUnmarshalV2 = false
|
||||
|
||||
// ParseError is returned by UnmarshalText.
|
||||
type ParseError struct {
|
||||
Message string
|
||||
|
||||
// Deprecated: Do not use.
|
||||
Line, Offset int
|
||||
}
|
||||
|
||||
func (e *ParseError) Error() string {
|
||||
if wrapTextUnmarshalV2 {
|
||||
return e.Message
|
||||
}
|
||||
if e.Line == 1 {
|
||||
return fmt.Sprintf("line 1.%d: %v", e.Offset, e.Message)
|
||||
}
|
||||
return fmt.Sprintf("line %d: %v", e.Line, e.Message)
|
||||
}
|
||||
|
||||
// UnmarshalText parses a proto text formatted string into m.
|
||||
func UnmarshalText(s string, m Message) error {
|
||||
if u, ok := m.(encoding.TextUnmarshaler); ok {
|
||||
return u.UnmarshalText([]byte(s))
|
||||
}
|
||||
|
||||
m.Reset()
|
||||
mi := MessageV2(m)
|
||||
|
||||
if wrapTextUnmarshalV2 {
|
||||
err := prototext.UnmarshalOptions{
|
||||
AllowPartial: true,
|
||||
}.Unmarshal([]byte(s), mi)
|
||||
if err != nil {
|
||||
return &ParseError{Message: err.Error()}
|
||||
}
|
||||
return checkRequiredNotSet(mi)
|
||||
} else {
|
||||
if err := newTextParser(s).unmarshalMessage(mi.ProtoReflect(), ""); err != nil {
|
||||
return err
|
||||
}
|
||||
return checkRequiredNotSet(mi)
|
||||
}
|
||||
}
|
||||
|
||||
type textParser struct {
|
||||
s string // remaining input
|
||||
done bool // whether the parsing is finished (success or error)
|
||||
backed bool // whether back() was called
|
||||
offset, line int
|
||||
cur token
|
||||
}
|
||||
|
||||
type token struct {
|
||||
value string
|
||||
err *ParseError
|
||||
line int // line number
|
||||
offset int // byte number from start of input, not start of line
|
||||
unquoted string // the unquoted version of value, if it was a quoted string
|
||||
}
|
||||
|
||||
func newTextParser(s string) *textParser {
|
||||
p := new(textParser)
|
||||
p.s = s
|
||||
p.line = 1
|
||||
p.cur.line = 1
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *textParser) unmarshalMessage(m protoreflect.Message, terminator string) (err error) {
|
||||
md := m.Descriptor()
|
||||
fds := md.Fields()
|
||||
|
||||
// A struct is a sequence of "name: value", terminated by one of
|
||||
// '>' or '}', or the end of the input. A name may also be
|
||||
// "[extension]" or "[type/url]".
|
||||
//
|
||||
// The whole struct can also be an expanded Any message, like:
|
||||
// [type/url] < ... struct contents ... >
|
||||
seen := make(map[protoreflect.FieldNumber]bool)
|
||||
for {
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return tok.err
|
||||
}
|
||||
if tok.value == terminator {
|
||||
break
|
||||
}
|
||||
if tok.value == "[" {
|
||||
if err := p.unmarshalExtensionOrAny(m, seen); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// This is a normal, non-extension field.
|
||||
name := protoreflect.Name(tok.value)
|
||||
fd := fds.ByName(name)
|
||||
switch {
|
||||
case fd == nil:
|
||||
gd := fds.ByName(protoreflect.Name(strings.ToLower(string(name))))
|
||||
if gd != nil && gd.Kind() == protoreflect.GroupKind && gd.Message().Name() == name {
|
||||
fd = gd
|
||||
}
|
||||
case fd.Kind() == protoreflect.GroupKind && fd.Message().Name() != name:
|
||||
fd = nil
|
||||
case fd.IsWeak() && fd.Message().IsPlaceholder():
|
||||
fd = nil
|
||||
}
|
||||
if fd == nil {
|
||||
typeName := string(md.FullName())
|
||||
if m, ok := m.Interface().(Message); ok {
|
||||
t := reflect.TypeOf(m)
|
||||
if t.Kind() == reflect.Ptr {
|
||||
typeName = t.Elem().String()
|
||||
}
|
||||
}
|
||||
return p.errorf("unknown field name %q in %v", name, typeName)
|
||||
}
|
||||
if od := fd.ContainingOneof(); od != nil && m.WhichOneof(od) != nil {
|
||||
return p.errorf("field '%s' would overwrite already parsed oneof '%s'", name, od.Name())
|
||||
}
|
||||
if fd.Cardinality() != protoreflect.Repeated && seen[fd.Number()] {
|
||||
return p.errorf("non-repeated field %q was repeated", fd.Name())
|
||||
}
|
||||
seen[fd.Number()] = true
|
||||
|
||||
// Consume any colon.
|
||||
if err := p.checkForColon(fd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Parse into the field.
|
||||
v := m.Get(fd)
|
||||
if !m.Has(fd) && (fd.IsList() || fd.IsMap() || fd.Message() != nil) {
|
||||
v = m.Mutable(fd)
|
||||
}
|
||||
if v, err = p.unmarshalValue(v, fd); err != nil {
|
||||
return err
|
||||
}
|
||||
m.Set(fd, v)
|
||||
|
||||
if err := p.consumeOptionalSeparator(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *textParser) unmarshalExtensionOrAny(m protoreflect.Message, seen map[protoreflect.FieldNumber]bool) error {
|
||||
name, err := p.consumeExtensionOrAnyName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If it contains a slash, it's an Any type URL.
|
||||
if slashIdx := strings.LastIndex(name, "/"); slashIdx >= 0 {
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return tok.err
|
||||
}
|
||||
// consume an optional colon
|
||||
if tok.value == ":" {
|
||||
tok = p.next()
|
||||
if tok.err != nil {
|
||||
return tok.err
|
||||
}
|
||||
}
|
||||
|
||||
var terminator string
|
||||
switch tok.value {
|
||||
case "<":
|
||||
terminator = ">"
|
||||
case "{":
|
||||
terminator = "}"
|
||||
default:
|
||||
return p.errorf("expected '{' or '<', found %q", tok.value)
|
||||
}
|
||||
|
||||
mt, err := protoregistry.GlobalTypes.FindMessageByURL(name)
|
||||
if err != nil {
|
||||
return p.errorf("unrecognized message %q in google.protobuf.Any", name[slashIdx+len("/"):])
|
||||
}
|
||||
m2 := mt.New()
|
||||
if err := p.unmarshalMessage(m2, terminator); err != nil {
|
||||
return err
|
||||
}
|
||||
b, err := protoV2.Marshal(m2.Interface())
|
||||
if err != nil {
|
||||
return p.errorf("failed to marshal message of type %q: %v", name[slashIdx+len("/"):], err)
|
||||
}
|
||||
|
||||
urlFD := m.Descriptor().Fields().ByName("type_url")
|
||||
valFD := m.Descriptor().Fields().ByName("value")
|
||||
if seen[urlFD.Number()] {
|
||||
return p.errorf("Any message unpacked multiple times, or %q already set", urlFD.Name())
|
||||
}
|
||||
if seen[valFD.Number()] {
|
||||
return p.errorf("Any message unpacked multiple times, or %q already set", valFD.Name())
|
||||
}
|
||||
m.Set(urlFD, protoreflect.ValueOfString(name))
|
||||
m.Set(valFD, protoreflect.ValueOfBytes(b))
|
||||
seen[urlFD.Number()] = true
|
||||
seen[valFD.Number()] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
xname := protoreflect.FullName(name)
|
||||
xt, _ := protoregistry.GlobalTypes.FindExtensionByName(xname)
|
||||
if xt == nil && isMessageSet(m.Descriptor()) {
|
||||
xt, _ = protoregistry.GlobalTypes.FindExtensionByName(xname.Append("message_set_extension"))
|
||||
}
|
||||
if xt == nil {
|
||||
return p.errorf("unrecognized extension %q", name)
|
||||
}
|
||||
fd := xt.TypeDescriptor()
|
||||
if fd.ContainingMessage().FullName() != m.Descriptor().FullName() {
|
||||
return p.errorf("extension field %q does not extend message %q", name, m.Descriptor().FullName())
|
||||
}
|
||||
|
||||
if err := p.checkForColon(fd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
v := m.Get(fd)
|
||||
if !m.Has(fd) && (fd.IsList() || fd.IsMap() || fd.Message() != nil) {
|
||||
v = m.Mutable(fd)
|
||||
}
|
||||
v, err = p.unmarshalValue(v, fd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.Set(fd, v)
|
||||
return p.consumeOptionalSeparator()
|
||||
}
|
||||
|
||||
func (p *textParser) unmarshalValue(v protoreflect.Value, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return v, tok.err
|
||||
}
|
||||
if tok.value == "" {
|
||||
return v, p.errorf("unexpected EOF")
|
||||
}
|
||||
|
||||
switch {
|
||||
case fd.IsList():
|
||||
lv := v.List()
|
||||
var err error
|
||||
if tok.value == "[" {
|
||||
// Repeated field with list notation, like [1,2,3].
|
||||
for {
|
||||
vv := lv.NewElement()
|
||||
vv, err = p.unmarshalSingularValue(vv, fd)
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
lv.Append(vv)
|
||||
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return v, tok.err
|
||||
}
|
||||
if tok.value == "]" {
|
||||
break
|
||||
}
|
||||
if tok.value != "," {
|
||||
return v, p.errorf("Expected ']' or ',' found %q", tok.value)
|
||||
}
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// One value of the repeated field.
|
||||
p.back()
|
||||
vv := lv.NewElement()
|
||||
vv, err = p.unmarshalSingularValue(vv, fd)
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
lv.Append(vv)
|
||||
return v, nil
|
||||
case fd.IsMap():
|
||||
// The map entry should be this sequence of tokens:
|
||||
// < key : KEY value : VALUE >
|
||||
// However, implementations may omit key or value, and technically
|
||||
// we should support them in any order.
|
||||
var terminator string
|
||||
switch tok.value {
|
||||
case "<":
|
||||
terminator = ">"
|
||||
case "{":
|
||||
terminator = "}"
|
||||
default:
|
||||
return v, p.errorf("expected '{' or '<', found %q", tok.value)
|
||||
}
|
||||
|
||||
keyFD := fd.MapKey()
|
||||
valFD := fd.MapValue()
|
||||
|
||||
mv := v.Map()
|
||||
kv := keyFD.Default()
|
||||
vv := mv.NewValue()
|
||||
for {
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return v, tok.err
|
||||
}
|
||||
if tok.value == terminator {
|
||||
break
|
||||
}
|
||||
var err error
|
||||
switch tok.value {
|
||||
case "key":
|
||||
if err := p.consumeToken(":"); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if kv, err = p.unmarshalSingularValue(kv, keyFD); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if err := p.consumeOptionalSeparator(); err != nil {
|
||||
return v, err
|
||||
}
|
||||
case "value":
|
||||
if err := p.checkForColon(valFD); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if vv, err = p.unmarshalSingularValue(vv, valFD); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if err := p.consumeOptionalSeparator(); err != nil {
|
||||
return v, err
|
||||
}
|
||||
default:
|
||||
p.back()
|
||||
return v, p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value)
|
||||
}
|
||||
}
|
||||
mv.Set(kv.MapKey(), vv)
|
||||
return v, nil
|
||||
default:
|
||||
p.back()
|
||||
return p.unmarshalSingularValue(v, fd)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *textParser) unmarshalSingularValue(v protoreflect.Value, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return v, tok.err
|
||||
}
|
||||
if tok.value == "" {
|
||||
return v, p.errorf("unexpected EOF")
|
||||
}
|
||||
|
||||
switch fd.Kind() {
|
||||
case protoreflect.BoolKind:
|
||||
switch tok.value {
|
||||
case "true", "1", "t", "True":
|
||||
return protoreflect.ValueOfBool(true), nil
|
||||
case "false", "0", "f", "False":
|
||||
return protoreflect.ValueOfBool(false), nil
|
||||
}
|
||||
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
|
||||
if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
|
||||
return protoreflect.ValueOfInt32(int32(x)), nil
|
||||
}
|
||||
|
||||
// The C++ parser accepts large positive hex numbers that uses
|
||||
// two's complement arithmetic to represent negative numbers.
|
||||
// This feature is here for backwards compatibility with C++.
|
||||
if strings.HasPrefix(tok.value, "0x") {
|
||||
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
|
||||
return protoreflect.ValueOfInt32(int32(-(int64(^x) + 1))), nil
|
||||
}
|
||||
}
|
||||
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
|
||||
if x, err := strconv.ParseInt(tok.value, 0, 64); err == nil {
|
||||
return protoreflect.ValueOfInt64(int64(x)), nil
|
||||
}
|
||||
|
||||
// The C++ parser accepts large positive hex numbers that uses
|
||||
// two's complement arithmetic to represent negative numbers.
|
||||
// This feature is here for backwards compatibility with C++.
|
||||
if strings.HasPrefix(tok.value, "0x") {
|
||||
if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil {
|
||||
return protoreflect.ValueOfInt64(int64(-(int64(^x) + 1))), nil
|
||||
}
|
||||
}
|
||||
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
|
||||
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
|
||||
return protoreflect.ValueOfUint32(uint32(x)), nil
|
||||
}
|
||||
case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
|
||||
if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil {
|
||||
return protoreflect.ValueOfUint64(uint64(x)), nil
|
||||
}
|
||||
case protoreflect.FloatKind:
|
||||
// Ignore 'f' for compatibility with output generated by C++,
|
||||
// but don't remove 'f' when the value is "-inf" or "inf".
|
||||
v := tok.value
|
||||
if strings.HasSuffix(v, "f") && v != "-inf" && v != "inf" {
|
||||
v = v[:len(v)-len("f")]
|
||||
}
|
||||
if x, err := strconv.ParseFloat(v, 32); err == nil {
|
||||
return protoreflect.ValueOfFloat32(float32(x)), nil
|
||||
}
|
||||
case protoreflect.DoubleKind:
|
||||
// Ignore 'f' for compatibility with output generated by C++,
|
||||
// but don't remove 'f' when the value is "-inf" or "inf".
|
||||
v := tok.value
|
||||
if strings.HasSuffix(v, "f") && v != "-inf" && v != "inf" {
|
||||
v = v[:len(v)-len("f")]
|
||||
}
|
||||
if x, err := strconv.ParseFloat(v, 64); err == nil {
|
||||
return protoreflect.ValueOfFloat64(float64(x)), nil
|
||||
}
|
||||
case protoreflect.StringKind:
|
||||
if isQuote(tok.value[0]) {
|
||||
return protoreflect.ValueOfString(tok.unquoted), nil
|
||||
}
|
||||
case protoreflect.BytesKind:
|
||||
if isQuote(tok.value[0]) {
|
||||
return protoreflect.ValueOfBytes([]byte(tok.unquoted)), nil
|
||||
}
|
||||
case protoreflect.EnumKind:
|
||||
if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
|
||||
return protoreflect.ValueOfEnum(protoreflect.EnumNumber(x)), nil
|
||||
}
|
||||
vd := fd.Enum().Values().ByName(protoreflect.Name(tok.value))
|
||||
if vd != nil {
|
||||
return protoreflect.ValueOfEnum(vd.Number()), nil
|
||||
}
|
||||
case protoreflect.MessageKind, protoreflect.GroupKind:
|
||||
var terminator string
|
||||
switch tok.value {
|
||||
case "{":
|
||||
terminator = "}"
|
||||
case "<":
|
||||
terminator = ">"
|
||||
default:
|
||||
return v, p.errorf("expected '{' or '<', found %q", tok.value)
|
||||
}
|
||||
err := p.unmarshalMessage(v.Message(), terminator)
|
||||
return v, err
|
||||
default:
|
||||
panic(fmt.Sprintf("invalid kind %v", fd.Kind()))
|
||||
}
|
||||
return v, p.errorf("invalid %v: %v", fd.Kind(), tok.value)
|
||||
}
|
||||
|
||||
// Consume a ':' from the input stream (if the next token is a colon),
|
||||
// returning an error if a colon is needed but not present.
|
||||
func (p *textParser) checkForColon(fd protoreflect.FieldDescriptor) *ParseError {
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return tok.err
|
||||
}
|
||||
if tok.value != ":" {
|
||||
if fd.Message() == nil {
|
||||
return p.errorf("expected ':', found %q", tok.value)
|
||||
}
|
||||
p.back()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// consumeExtensionOrAnyName consumes an extension name or an Any type URL and
|
||||
// the following ']'. It returns the name or URL consumed.
|
||||
func (p *textParser) consumeExtensionOrAnyName() (string, error) {
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return "", tok.err
|
||||
}
|
||||
|
||||
// If extension name or type url is quoted, it's a single token.
|
||||
if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] {
|
||||
name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0]))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return name, p.consumeToken("]")
|
||||
}
|
||||
|
||||
// Consume everything up to "]"
|
||||
var parts []string
|
||||
for tok.value != "]" {
|
||||
parts = append(parts, tok.value)
|
||||
tok = p.next()
|
||||
if tok.err != nil {
|
||||
return "", p.errorf("unrecognized type_url or extension name: %s", tok.err)
|
||||
}
|
||||
if p.done && tok.value != "]" {
|
||||
return "", p.errorf("unclosed type_url or extension name")
|
||||
}
|
||||
}
|
||||
return strings.Join(parts, ""), nil
|
||||
}
|
||||
|
||||
// consumeOptionalSeparator consumes an optional semicolon or comma.
|
||||
// It is used in unmarshalMessage to provide backward compatibility.
|
||||
func (p *textParser) consumeOptionalSeparator() error {
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return tok.err
|
||||
}
|
||||
if tok.value != ";" && tok.value != "," {
|
||||
p.back()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *textParser) errorf(format string, a ...interface{}) *ParseError {
|
||||
pe := &ParseError{fmt.Sprintf(format, a...), p.cur.line, p.cur.offset}
|
||||
p.cur.err = pe
|
||||
p.done = true
|
||||
return pe
|
||||
}
|
||||
|
||||
func (p *textParser) skipWhitespace() {
|
||||
i := 0
|
||||
for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') {
|
||||
if p.s[i] == '#' {
|
||||
// comment; skip to end of line or input
|
||||
for i < len(p.s) && p.s[i] != '\n' {
|
||||
i++
|
||||
}
|
||||
if i == len(p.s) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if p.s[i] == '\n' {
|
||||
p.line++
|
||||
}
|
||||
i++
|
||||
}
|
||||
p.offset += i
|
||||
p.s = p.s[i:len(p.s)]
|
||||
if len(p.s) == 0 {
|
||||
p.done = true
|
||||
}
|
||||
}
|
||||
|
||||
func (p *textParser) advance() {
|
||||
// Skip whitespace
|
||||
p.skipWhitespace()
|
||||
if p.done {
|
||||
return
|
||||
}
|
||||
|
||||
// Start of non-whitespace
|
||||
p.cur.err = nil
|
||||
p.cur.offset, p.cur.line = p.offset, p.line
|
||||
p.cur.unquoted = ""
|
||||
switch p.s[0] {
|
||||
case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/':
|
||||
// Single symbol
|
||||
p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)]
|
||||
case '"', '\'':
|
||||
// Quoted string
|
||||
i := 1
|
||||
for i < len(p.s) && p.s[i] != p.s[0] && p.s[i] != '\n' {
|
||||
if p.s[i] == '\\' && i+1 < len(p.s) {
|
||||
// skip escaped char
|
||||
i++
|
||||
}
|
||||
i++
|
||||
}
|
||||
if i >= len(p.s) || p.s[i] != p.s[0] {
|
||||
p.errorf("unmatched quote")
|
||||
return
|
||||
}
|
||||
unq, err := unquoteC(p.s[1:i], rune(p.s[0]))
|
||||
if err != nil {
|
||||
p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err)
|
||||
return
|
||||
}
|
||||
p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)]
|
||||
p.cur.unquoted = unq
|
||||
default:
|
||||
i := 0
|
||||
for i < len(p.s) && isIdentOrNumberChar(p.s[i]) {
|
||||
i++
|
||||
}
|
||||
if i == 0 {
|
||||
p.errorf("unexpected byte %#x", p.s[0])
|
||||
return
|
||||
}
|
||||
p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)]
|
||||
}
|
||||
p.offset += len(p.cur.value)
|
||||
}
|
||||
|
||||
// Back off the parser by one token. Can only be done between calls to next().
|
||||
// It makes the next advance() a no-op.
|
||||
func (p *textParser) back() { p.backed = true }
|
||||
|
||||
// Advances the parser and returns the new current token.
|
||||
func (p *textParser) next() *token {
|
||||
if p.backed || p.done {
|
||||
p.backed = false
|
||||
return &p.cur
|
||||
}
|
||||
p.advance()
|
||||
if p.done {
|
||||
p.cur.value = ""
|
||||
} else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) {
|
||||
// Look for multiple quoted strings separated by whitespace,
|
||||
// and concatenate them.
|
||||
cat := p.cur
|
||||
for {
|
||||
p.skipWhitespace()
|
||||
if p.done || !isQuote(p.s[0]) {
|
||||
break
|
||||
}
|
||||
p.advance()
|
||||
if p.cur.err != nil {
|
||||
return &p.cur
|
||||
}
|
||||
cat.value += " " + p.cur.value
|
||||
cat.unquoted += p.cur.unquoted
|
||||
}
|
||||
p.done = false // parser may have seen EOF, but we want to return cat
|
||||
p.cur = cat
|
||||
}
|
||||
return &p.cur
|
||||
}
|
||||
|
||||
func (p *textParser) consumeToken(s string) error {
|
||||
tok := p.next()
|
||||
if tok.err != nil {
|
||||
return tok.err
|
||||
}
|
||||
if tok.value != s {
|
||||
p.back()
|
||||
return p.errorf("expected %q, found %q", s, tok.value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var errBadUTF8 = errors.New("proto: bad UTF-8")
|
||||
|
||||
func unquoteC(s string, quote rune) (string, error) {
|
||||
// This is based on C++'s tokenizer.cc.
|
||||
// Despite its name, this is *not* parsing C syntax.
|
||||
// For instance, "\0" is an invalid quoted string.
|
||||
|
||||
// Avoid allocation in trivial cases.
|
||||
simple := true
|
||||
for _, r := range s {
|
||||
if r == '\\' || r == quote {
|
||||
simple = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if simple {
|
||||
return s, nil
|
||||
}
|
||||
|
||||
buf := make([]byte, 0, 3*len(s)/2)
|
||||
for len(s) > 0 {
|
||||
r, n := utf8.DecodeRuneInString(s)
|
||||
if r == utf8.RuneError && n == 1 {
|
||||
return "", errBadUTF8
|
||||
}
|
||||
s = s[n:]
|
||||
if r != '\\' {
|
||||
if r < utf8.RuneSelf {
|
||||
buf = append(buf, byte(r))
|
||||
} else {
|
||||
buf = append(buf, string(r)...)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
ch, tail, err := unescape(s)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
buf = append(buf, ch...)
|
||||
s = tail
|
||||
}
|
||||
return string(buf), nil
|
||||
}
|
||||
|
||||
func unescape(s string) (ch string, tail string, err error) {
|
||||
r, n := utf8.DecodeRuneInString(s)
|
||||
if r == utf8.RuneError && n == 1 {
|
||||
return "", "", errBadUTF8
|
||||
}
|
||||
s = s[n:]
|
||||
switch r {
|
||||
case 'a':
|
||||
return "\a", s, nil
|
||||
case 'b':
|
||||
return "\b", s, nil
|
||||
case 'f':
|
||||
return "\f", s, nil
|
||||
case 'n':
|
||||
return "\n", s, nil
|
||||
case 'r':
|
||||
return "\r", s, nil
|
||||
case 't':
|
||||
return "\t", s, nil
|
||||
case 'v':
|
||||
return "\v", s, nil
|
||||
case '?':
|
||||
return "?", s, nil // trigraph workaround
|
||||
case '\'', '"', '\\':
|
||||
return string(r), s, nil
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7':
|
||||
if len(s) < 2 {
|
||||
return "", "", fmt.Errorf(`\%c requires 2 following digits`, r)
|
||||
}
|
||||
ss := string(r) + s[:2]
|
||||
s = s[2:]
|
||||
i, err := strconv.ParseUint(ss, 8, 8)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf(`\%s contains non-octal digits`, ss)
|
||||
}
|
||||
return string([]byte{byte(i)}), s, nil
|
||||
case 'x', 'X', 'u', 'U':
|
||||
var n int
|
||||
switch r {
|
||||
case 'x', 'X':
|
||||
n = 2
|
||||
case 'u':
|
||||
n = 4
|
||||
case 'U':
|
||||
n = 8
|
||||
}
|
||||
if len(s) < n {
|
||||
return "", "", fmt.Errorf(`\%c requires %d following digits`, r, n)
|
||||
}
|
||||
ss := s[:n]
|
||||
s = s[n:]
|
||||
i, err := strconv.ParseUint(ss, 16, 64)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf(`\%c%s contains non-hexadecimal digits`, r, ss)
|
||||
}
|
||||
if r == 'x' || r == 'X' {
|
||||
return string([]byte{byte(i)}), s, nil
|
||||
}
|
||||
if i > utf8.MaxRune {
|
||||
return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss)
|
||||
}
|
||||
return string(rune(i)), s, nil
|
||||
}
|
||||
return "", "", fmt.Errorf(`unknown escape \%c`, r)
|
||||
}
|
||||
|
||||
func isIdentOrNumberChar(c byte) bool {
|
||||
switch {
|
||||
case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z':
|
||||
return true
|
||||
case '0' <= c && c <= '9':
|
||||
return true
|
||||
}
|
||||
switch c {
|
||||
case '-', '+', '.', '_':
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isWhitespace(c byte) bool {
|
||||
switch c {
|
||||
case ' ', '\t', '\n', '\r':
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isQuote(c byte) bool {
|
||||
switch c {
|
||||
case '"', '\'':
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
560
vendor/github.com/golang/protobuf/proto/text_encode.go
generated
vendored
560
vendor/github.com/golang/protobuf/proto/text_encode.go
generated
vendored
@ -1,560 +0,0 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/protobuf/encoding/prototext"
|
||||
"google.golang.org/protobuf/encoding/protowire"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/reflect/protoregistry"
|
||||
)
|
||||
|
||||
const wrapTextMarshalV2 = false
|
||||
|
||||
// TextMarshaler is a configurable text format marshaler.
|
||||
type TextMarshaler struct {
|
||||
Compact bool // use compact text format (one line)
|
||||
ExpandAny bool // expand google.protobuf.Any messages of known types
|
||||
}
|
||||
|
||||
// Marshal writes the proto text format of m to w.
|
||||
func (tm *TextMarshaler) Marshal(w io.Writer, m Message) error {
|
||||
b, err := tm.marshal(m)
|
||||
if len(b) > 0 {
|
||||
if _, err := w.Write(b); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Text returns a proto text formatted string of m.
|
||||
func (tm *TextMarshaler) Text(m Message) string {
|
||||
b, _ := tm.marshal(m)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (tm *TextMarshaler) marshal(m Message) ([]byte, error) {
|
||||
mr := MessageReflect(m)
|
||||
if mr == nil || !mr.IsValid() {
|
||||
return []byte("<nil>"), nil
|
||||
}
|
||||
|
||||
if wrapTextMarshalV2 {
|
||||
if m, ok := m.(encoding.TextMarshaler); ok {
|
||||
return m.MarshalText()
|
||||
}
|
||||
|
||||
opts := prototext.MarshalOptions{
|
||||
AllowPartial: true,
|
||||
EmitUnknown: true,
|
||||
}
|
||||
if !tm.Compact {
|
||||
opts.Indent = " "
|
||||
}
|
||||
if !tm.ExpandAny {
|
||||
opts.Resolver = (*protoregistry.Types)(nil)
|
||||
}
|
||||
return opts.Marshal(mr.Interface())
|
||||
} else {
|
||||
w := &textWriter{
|
||||
compact: tm.Compact,
|
||||
expandAny: tm.ExpandAny,
|
||||
complete: true,
|
||||
}
|
||||
|
||||
if m, ok := m.(encoding.TextMarshaler); ok {
|
||||
b, err := m.MarshalText()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
w.Write(b)
|
||||
return w.buf, nil
|
||||
}
|
||||
|
||||
err := w.writeMessage(mr)
|
||||
return w.buf, err
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
defaultTextMarshaler = TextMarshaler{}
|
||||
compactTextMarshaler = TextMarshaler{Compact: true}
|
||||
)
|
||||
|
||||
// MarshalText writes the proto text format of m to w.
|
||||
func MarshalText(w io.Writer, m Message) error { return defaultTextMarshaler.Marshal(w, m) }
|
||||
|
||||
// MarshalTextString returns a proto text formatted string of m.
|
||||
func MarshalTextString(m Message) string { return defaultTextMarshaler.Text(m) }
|
||||
|
||||
// CompactText writes the compact proto text format of m to w.
|
||||
func CompactText(w io.Writer, m Message) error { return compactTextMarshaler.Marshal(w, m) }
|
||||
|
||||
// CompactTextString returns a compact proto text formatted string of m.
|
||||
func CompactTextString(m Message) string { return compactTextMarshaler.Text(m) }
|
||||
|
||||
var (
|
||||
newline = []byte("\n")
|
||||
endBraceNewline = []byte("}\n")
|
||||
posInf = []byte("inf")
|
||||
negInf = []byte("-inf")
|
||||
nan = []byte("nan")
|
||||
)
|
||||
|
||||
// textWriter is an io.Writer that tracks its indentation level.
|
||||
type textWriter struct {
|
||||
compact bool // same as TextMarshaler.Compact
|
||||
expandAny bool // same as TextMarshaler.ExpandAny
|
||||
complete bool // whether the current position is a complete line
|
||||
indent int // indentation level; never negative
|
||||
buf []byte
|
||||
}
|
||||
|
||||
func (w *textWriter) Write(p []byte) (n int, _ error) {
|
||||
newlines := bytes.Count(p, newline)
|
||||
if newlines == 0 {
|
||||
if !w.compact && w.complete {
|
||||
w.writeIndent()
|
||||
}
|
||||
w.buf = append(w.buf, p...)
|
||||
w.complete = false
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
frags := bytes.SplitN(p, newline, newlines+1)
|
||||
if w.compact {
|
||||
for i, frag := range frags {
|
||||
if i > 0 {
|
||||
w.buf = append(w.buf, ' ')
|
||||
n++
|
||||
}
|
||||
w.buf = append(w.buf, frag...)
|
||||
n += len(frag)
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
for i, frag := range frags {
|
||||
if w.complete {
|
||||
w.writeIndent()
|
||||
}
|
||||
w.buf = append(w.buf, frag...)
|
||||
n += len(frag)
|
||||
if i+1 < len(frags) {
|
||||
w.buf = append(w.buf, '\n')
|
||||
n++
|
||||
}
|
||||
}
|
||||
w.complete = len(frags[len(frags)-1]) == 0
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (w *textWriter) WriteByte(c byte) error {
|
||||
if w.compact && c == '\n' {
|
||||
c = ' '
|
||||
}
|
||||
if !w.compact && w.complete {
|
||||
w.writeIndent()
|
||||
}
|
||||
w.buf = append(w.buf, c)
|
||||
w.complete = c == '\n'
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *textWriter) writeName(fd protoreflect.FieldDescriptor) {
|
||||
if !w.compact && w.complete {
|
||||
w.writeIndent()
|
||||
}
|
||||
w.complete = false
|
||||
|
||||
if fd.Kind() != protoreflect.GroupKind {
|
||||
w.buf = append(w.buf, fd.Name()...)
|
||||
w.WriteByte(':')
|
||||
} else {
|
||||
// Use message type name for group field name.
|
||||
w.buf = append(w.buf, fd.Message().Name()...)
|
||||
}
|
||||
|
||||
if !w.compact {
|
||||
w.WriteByte(' ')
|
||||
}
|
||||
}
|
||||
|
||||
func requiresQuotes(u string) bool {
|
||||
// When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
|
||||
for _, ch := range u {
|
||||
switch {
|
||||
case ch == '.' || ch == '/' || ch == '_':
|
||||
continue
|
||||
case '0' <= ch && ch <= '9':
|
||||
continue
|
||||
case 'A' <= ch && ch <= 'Z':
|
||||
continue
|
||||
case 'a' <= ch && ch <= 'z':
|
||||
continue
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// writeProto3Any writes an expanded google.protobuf.Any message.
|
||||
//
|
||||
// It returns (false, nil) if sv value can't be unmarshaled (e.g. because
|
||||
// required messages are not linked in).
|
||||
//
|
||||
// It returns (true, error) when sv was written in expanded format or an error
|
||||
// was encountered.
|
||||
func (w *textWriter) writeProto3Any(m protoreflect.Message) (bool, error) {
|
||||
md := m.Descriptor()
|
||||
fdURL := md.Fields().ByName("type_url")
|
||||
fdVal := md.Fields().ByName("value")
|
||||
|
||||
url := m.Get(fdURL).String()
|
||||
mt, err := protoregistry.GlobalTypes.FindMessageByURL(url)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
b := m.Get(fdVal).Bytes()
|
||||
m2 := mt.New()
|
||||
if err := proto.Unmarshal(b, m2.Interface()); err != nil {
|
||||
return false, nil
|
||||
}
|
||||
w.Write([]byte("["))
|
||||
if requiresQuotes(url) {
|
||||
w.writeQuotedString(url)
|
||||
} else {
|
||||
w.Write([]byte(url))
|
||||
}
|
||||
if w.compact {
|
||||
w.Write([]byte("]:<"))
|
||||
} else {
|
||||
w.Write([]byte("]: <\n"))
|
||||
w.indent++
|
||||
}
|
||||
if err := w.writeMessage(m2); err != nil {
|
||||
return true, err
|
||||
}
|
||||
if w.compact {
|
||||
w.Write([]byte("> "))
|
||||
} else {
|
||||
w.indent--
|
||||
w.Write([]byte(">\n"))
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (w *textWriter) writeMessage(m protoreflect.Message) error {
|
||||
md := m.Descriptor()
|
||||
if w.expandAny && md.FullName() == "google.protobuf.Any" {
|
||||
if canExpand, err := w.writeProto3Any(m); canExpand {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
fds := md.Fields()
|
||||
for i := 0; i < fds.Len(); {
|
||||
fd := fds.Get(i)
|
||||
if od := fd.ContainingOneof(); od != nil {
|
||||
fd = m.WhichOneof(od)
|
||||
i += od.Fields().Len()
|
||||
} else {
|
||||
i++
|
||||
}
|
||||
if fd == nil || !m.Has(fd) {
|
||||
continue
|
||||
}
|
||||
|
||||
switch {
|
||||
case fd.IsList():
|
||||
lv := m.Get(fd).List()
|
||||
for j := 0; j < lv.Len(); j++ {
|
||||
w.writeName(fd)
|
||||
v := lv.Get(j)
|
||||
if err := w.writeSingularValue(v, fd); err != nil {
|
||||
return err
|
||||
}
|
||||
w.WriteByte('\n')
|
||||
}
|
||||
case fd.IsMap():
|
||||
kfd := fd.MapKey()
|
||||
vfd := fd.MapValue()
|
||||
mv := m.Get(fd).Map()
|
||||
|
||||
type entry struct{ key, val protoreflect.Value }
|
||||
var entries []entry
|
||||
mv.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool {
|
||||
entries = append(entries, entry{k.Value(), v})
|
||||
return true
|
||||
})
|
||||
sort.Slice(entries, func(i, j int) bool {
|
||||
switch kfd.Kind() {
|
||||
case protoreflect.BoolKind:
|
||||
return !entries[i].key.Bool() && entries[j].key.Bool()
|
||||
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
|
||||
return entries[i].key.Int() < entries[j].key.Int()
|
||||
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
|
||||
return entries[i].key.Uint() < entries[j].key.Uint()
|
||||
case protoreflect.StringKind:
|
||||
return entries[i].key.String() < entries[j].key.String()
|
||||
default:
|
||||
panic("invalid kind")
|
||||
}
|
||||
})
|
||||
for _, entry := range entries {
|
||||
w.writeName(fd)
|
||||
w.WriteByte('<')
|
||||
if !w.compact {
|
||||
w.WriteByte('\n')
|
||||
}
|
||||
w.indent++
|
||||
w.writeName(kfd)
|
||||
if err := w.writeSingularValue(entry.key, kfd); err != nil {
|
||||
return err
|
||||
}
|
||||
w.WriteByte('\n')
|
||||
w.writeName(vfd)
|
||||
if err := w.writeSingularValue(entry.val, vfd); err != nil {
|
||||
return err
|
||||
}
|
||||
w.WriteByte('\n')
|
||||
w.indent--
|
||||
w.WriteByte('>')
|
||||
w.WriteByte('\n')
|
||||
}
|
||||
default:
|
||||
w.writeName(fd)
|
||||
if err := w.writeSingularValue(m.Get(fd), fd); err != nil {
|
||||
return err
|
||||
}
|
||||
w.WriteByte('\n')
|
||||
}
|
||||
}
|
||||
|
||||
if b := m.GetUnknown(); len(b) > 0 {
|
||||
w.writeUnknownFields(b)
|
||||
}
|
||||
return w.writeExtensions(m)
|
||||
}
|
||||
|
||||
func (w *textWriter) writeSingularValue(v protoreflect.Value, fd protoreflect.FieldDescriptor) error {
|
||||
switch fd.Kind() {
|
||||
case protoreflect.FloatKind, protoreflect.DoubleKind:
|
||||
switch vf := v.Float(); {
|
||||
case math.IsInf(vf, +1):
|
||||
w.Write(posInf)
|
||||
case math.IsInf(vf, -1):
|
||||
w.Write(negInf)
|
||||
case math.IsNaN(vf):
|
||||
w.Write(nan)
|
||||
default:
|
||||
fmt.Fprint(w, v.Interface())
|
||||
}
|
||||
case protoreflect.StringKind:
|
||||
// NOTE: This does not validate UTF-8 for historical reasons.
|
||||
w.writeQuotedString(string(v.String()))
|
||||
case protoreflect.BytesKind:
|
||||
w.writeQuotedString(string(v.Bytes()))
|
||||
case protoreflect.MessageKind, protoreflect.GroupKind:
|
||||
var bra, ket byte = '<', '>'
|
||||
if fd.Kind() == protoreflect.GroupKind {
|
||||
bra, ket = '{', '}'
|
||||
}
|
||||
w.WriteByte(bra)
|
||||
if !w.compact {
|
||||
w.WriteByte('\n')
|
||||
}
|
||||
w.indent++
|
||||
m := v.Message()
|
||||
if m2, ok := m.Interface().(encoding.TextMarshaler); ok {
|
||||
b, err := m2.MarshalText()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w.Write(b)
|
||||
} else {
|
||||
w.writeMessage(m)
|
||||
}
|
||||
w.indent--
|
||||
w.WriteByte(ket)
|
||||
case protoreflect.EnumKind:
|
||||
if ev := fd.Enum().Values().ByNumber(v.Enum()); ev != nil {
|
||||
fmt.Fprint(w, ev.Name())
|
||||
} else {
|
||||
fmt.Fprint(w, v.Enum())
|
||||
}
|
||||
default:
|
||||
fmt.Fprint(w, v.Interface())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// writeQuotedString writes a quoted string in the protocol buffer text format.
|
||||
func (w *textWriter) writeQuotedString(s string) {
|
||||
w.WriteByte('"')
|
||||
for i := 0; i < len(s); i++ {
|
||||
switch c := s[i]; c {
|
||||
case '\n':
|
||||
w.buf = append(w.buf, `\n`...)
|
||||
case '\r':
|
||||
w.buf = append(w.buf, `\r`...)
|
||||
case '\t':
|
||||
w.buf = append(w.buf, `\t`...)
|
||||
case '"':
|
||||
w.buf = append(w.buf, `\"`...)
|
||||
case '\\':
|
||||
w.buf = append(w.buf, `\\`...)
|
||||
default:
|
||||
if isPrint := c >= 0x20 && c < 0x7f; isPrint {
|
||||
w.buf = append(w.buf, c)
|
||||
} else {
|
||||
w.buf = append(w.buf, fmt.Sprintf(`\%03o`, c)...)
|
||||
}
|
||||
}
|
||||
}
|
||||
w.WriteByte('"')
|
||||
}
|
||||
|
||||
func (w *textWriter) writeUnknownFields(b []byte) {
|
||||
if !w.compact {
|
||||
fmt.Fprintf(w, "/* %d unknown bytes */\n", len(b))
|
||||
}
|
||||
|
||||
for len(b) > 0 {
|
||||
num, wtyp, n := protowire.ConsumeTag(b)
|
||||
if n < 0 {
|
||||
return
|
||||
}
|
||||
b = b[n:]
|
||||
|
||||
if wtyp == protowire.EndGroupType {
|
||||
w.indent--
|
||||
w.Write(endBraceNewline)
|
||||
continue
|
||||
}
|
||||
fmt.Fprint(w, num)
|
||||
if wtyp != protowire.StartGroupType {
|
||||
w.WriteByte(':')
|
||||
}
|
||||
if !w.compact || wtyp == protowire.StartGroupType {
|
||||
w.WriteByte(' ')
|
||||
}
|
||||
switch wtyp {
|
||||
case protowire.VarintType:
|
||||
v, n := protowire.ConsumeVarint(b)
|
||||
if n < 0 {
|
||||
return
|
||||
}
|
||||
b = b[n:]
|
||||
fmt.Fprint(w, v)
|
||||
case protowire.Fixed32Type:
|
||||
v, n := protowire.ConsumeFixed32(b)
|
||||
if n < 0 {
|
||||
return
|
||||
}
|
||||
b = b[n:]
|
||||
fmt.Fprint(w, v)
|
||||
case protowire.Fixed64Type:
|
||||
v, n := protowire.ConsumeFixed64(b)
|
||||
if n < 0 {
|
||||
return
|
||||
}
|
||||
b = b[n:]
|
||||
fmt.Fprint(w, v)
|
||||
case protowire.BytesType:
|
||||
v, n := protowire.ConsumeBytes(b)
|
||||
if n < 0 {
|
||||
return
|
||||
}
|
||||
b = b[n:]
|
||||
fmt.Fprintf(w, "%q", v)
|
||||
case protowire.StartGroupType:
|
||||
w.WriteByte('{')
|
||||
w.indent++
|
||||
default:
|
||||
fmt.Fprintf(w, "/* unknown wire type %d */", wtyp)
|
||||
}
|
||||
w.WriteByte('\n')
|
||||
}
|
||||
}
|
||||
|
||||
// writeExtensions writes all the extensions in m.
|
||||
func (w *textWriter) writeExtensions(m protoreflect.Message) error {
|
||||
md := m.Descriptor()
|
||||
if md.ExtensionRanges().Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
type ext struct {
|
||||
desc protoreflect.FieldDescriptor
|
||||
val protoreflect.Value
|
||||
}
|
||||
var exts []ext
|
||||
m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
|
||||
if fd.IsExtension() {
|
||||
exts = append(exts, ext{fd, v})
|
||||
}
|
||||
return true
|
||||
})
|
||||
sort.Slice(exts, func(i, j int) bool {
|
||||
return exts[i].desc.Number() < exts[j].desc.Number()
|
||||
})
|
||||
|
||||
for _, ext := range exts {
|
||||
// For message set, use the name of the message as the extension name.
|
||||
name := string(ext.desc.FullName())
|
||||
if isMessageSet(ext.desc.ContainingMessage()) {
|
||||
name = strings.TrimSuffix(name, ".message_set_extension")
|
||||
}
|
||||
|
||||
if !ext.desc.IsList() {
|
||||
if err := w.writeSingularExtension(name, ext.val, ext.desc); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
lv := ext.val.List()
|
||||
for i := 0; i < lv.Len(); i++ {
|
||||
if err := w.writeSingularExtension(name, lv.Get(i), ext.desc); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *textWriter) writeSingularExtension(name string, v protoreflect.Value, fd protoreflect.FieldDescriptor) error {
|
||||
fmt.Fprintf(w, "[%s]:", name)
|
||||
if !w.compact {
|
||||
w.WriteByte(' ')
|
||||
}
|
||||
if err := w.writeSingularValue(v, fd); err != nil {
|
||||
return err
|
||||
}
|
||||
w.WriteByte('\n')
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *textWriter) writeIndent() {
|
||||
if !w.complete {
|
||||
return
|
||||
}
|
||||
for i := 0; i < w.indent*2; i++ {
|
||||
w.buf = append(w.buf, ' ')
|
||||
}
|
||||
w.complete = false
|
||||
}
|
78
vendor/github.com/golang/protobuf/proto/wire.go
generated
vendored
78
vendor/github.com/golang/protobuf/proto/wire.go
generated
vendored
@ -1,78 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
import (
|
||||
protoV2 "google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/runtime/protoiface"
|
||||
)
|
||||
|
||||
// Size returns the size in bytes of the wire-format encoding of m.
|
||||
func Size(m Message) int {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
mi := MessageV2(m)
|
||||
return protoV2.Size(mi)
|
||||
}
|
||||
|
||||
// Marshal returns the wire-format encoding of m.
|
||||
func Marshal(m Message) ([]byte, error) {
|
||||
b, err := marshalAppend(nil, m, false)
|
||||
if b == nil {
|
||||
b = zeroBytes
|
||||
}
|
||||
return b, err
|
||||
}
|
||||
|
||||
var zeroBytes = make([]byte, 0, 0)
|
||||
|
||||
func marshalAppend(buf []byte, m Message, deterministic bool) ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, ErrNil
|
||||
}
|
||||
mi := MessageV2(m)
|
||||
nbuf, err := protoV2.MarshalOptions{
|
||||
Deterministic: deterministic,
|
||||
AllowPartial: true,
|
||||
}.MarshalAppend(buf, mi)
|
||||
if err != nil {
|
||||
return buf, err
|
||||
}
|
||||
if len(buf) == len(nbuf) {
|
||||
if !mi.ProtoReflect().IsValid() {
|
||||
return buf, ErrNil
|
||||
}
|
||||
}
|
||||
return nbuf, checkRequiredNotSet(mi)
|
||||
}
|
||||
|
||||
// Unmarshal parses a wire-format message in b and places the decoded results in m.
|
||||
//
|
||||
// Unmarshal resets m before starting to unmarshal, so any existing data in m is always
|
||||
// removed. Use UnmarshalMerge to preserve and append to existing data.
|
||||
func Unmarshal(b []byte, m Message) error {
|
||||
m.Reset()
|
||||
return UnmarshalMerge(b, m)
|
||||
}
|
||||
|
||||
// UnmarshalMerge parses a wire-format message in b and places the decoded results in m.
|
||||
func UnmarshalMerge(b []byte, m Message) error {
|
||||
mi := MessageV2(m)
|
||||
out, err := protoV2.UnmarshalOptions{
|
||||
AllowPartial: true,
|
||||
Merge: true,
|
||||
}.UnmarshalState(protoiface.UnmarshalInput{
|
||||
Buf: b,
|
||||
Message: mi.ProtoReflect(),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if out.Flags&protoiface.UnmarshalInitialized > 0 {
|
||||
return nil
|
||||
}
|
||||
return checkRequiredNotSet(mi)
|
||||
}
|
34
vendor/github.com/golang/protobuf/proto/wrappers.go
generated
vendored
34
vendor/github.com/golang/protobuf/proto/wrappers.go
generated
vendored
@ -1,34 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proto
|
||||
|
||||
// Bool stores v in a new bool value and returns a pointer to it.
|
||||
func Bool(v bool) *bool { return &v }
|
||||
|
||||
// Int stores v in a new int32 value and returns a pointer to it.
|
||||
//
|
||||
// Deprecated: Use Int32 instead.
|
||||
func Int(v int) *int32 { return Int32(int32(v)) }
|
||||
|
||||
// Int32 stores v in a new int32 value and returns a pointer to it.
|
||||
func Int32(v int32) *int32 { return &v }
|
||||
|
||||
// Int64 stores v in a new int64 value and returns a pointer to it.
|
||||
func Int64(v int64) *int64 { return &v }
|
||||
|
||||
// Uint32 stores v in a new uint32 value and returns a pointer to it.
|
||||
func Uint32(v uint32) *uint32 { return &v }
|
||||
|
||||
// Uint64 stores v in a new uint64 value and returns a pointer to it.
|
||||
func Uint64(v uint64) *uint64 { return &v }
|
||||
|
||||
// Float32 stores v in a new float32 value and returns a pointer to it.
|
||||
func Float32(v float32) *float32 { return &v }
|
||||
|
||||
// Float64 stores v in a new float64 value and returns a pointer to it.
|
||||
func Float64(v float64) *float64 { return &v }
|
||||
|
||||
// String stores v in a new string value and returns a pointer to it.
|
||||
func String(v string) *string { return &v }
|
3
vendor/google.golang.org/protobuf/encoding/prototext/decode.go
generated
vendored
3
vendor/google.golang.org/protobuf/encoding/prototext/decode.go
generated
vendored
@ -744,9 +744,6 @@ func (d decoder) skipValue() error {
|
||||
// Skip items. This will not validate whether skipped values are
|
||||
// of the same type or not, same behavior as C++
|
||||
// TextFormat::Parser::AllowUnknownField(true) version 3.8.0.
|
||||
if err := d.skipValue(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
5
vendor/google.golang.org/protobuf/internal/encoding/text/encode.go
generated
vendored
5
vendor/google.golang.org/protobuf/internal/encoding/text/encode.go
generated
vendored
@ -263,3 +263,8 @@ func (e *Encoder) Snapshot() encoderState {
|
||||
func (e *Encoder) Reset(es encoderState) {
|
||||
e.encoderState = es
|
||||
}
|
||||
|
||||
// AppendString appends the escaped form of the input string to b.
|
||||
func AppendString(b []byte, s string) []byte {
|
||||
return appendString(b, s, false)
|
||||
}
|
||||
|
7
vendor/google.golang.org/protobuf/internal/impl/legacy_message.go
generated
vendored
7
vendor/google.golang.org/protobuf/internal/impl/legacy_message.go
generated
vendored
@ -440,6 +440,13 @@ func legacyMerge(in piface.MergeInput) piface.MergeOutput {
|
||||
if !ok {
|
||||
return piface.MergeOutput{}
|
||||
}
|
||||
if !in.Source.IsValid() {
|
||||
// Legacy Marshal methods may not function on nil messages.
|
||||
// Check for a typed nil source only after we confirm that
|
||||
// legacy Marshal/Unmarshal methods are present, for
|
||||
// consistency.
|
||||
return piface.MergeOutput{Flags: piface.MergeComplete}
|
||||
}
|
||||
b, err := marshaler.Marshal()
|
||||
if err != nil {
|
||||
return piface.MergeOutput{}
|
||||
|
4
vendor/google.golang.org/protobuf/internal/version/version.go
generated
vendored
4
vendor/google.golang.org/protobuf/internal/version/version.go
generated
vendored
@ -52,8 +52,8 @@ import (
|
||||
// 10. Send out the CL for review and submit it.
|
||||
const (
|
||||
Major = 1
|
||||
Minor = 26
|
||||
Patch = 0
|
||||
Minor = 27
|
||||
Patch = 1
|
||||
PreRelease = ""
|
||||
)
|
||||
|
||||
|
276
vendor/google.golang.org/protobuf/reflect/protodesc/desc.go
generated
vendored
276
vendor/google.golang.org/protobuf/reflect/protodesc/desc.go
generated
vendored
@ -1,276 +0,0 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package protodesc provides functionality for converting
|
||||
// FileDescriptorProto messages to/from protoreflect.FileDescriptor values.
|
||||
//
|
||||
// The google.protobuf.FileDescriptorProto is a protobuf message that describes
|
||||
// the type information for a .proto file in a form that is easily serializable.
|
||||
// The protoreflect.FileDescriptor is a more structured representation of
|
||||
// the FileDescriptorProto message where references and remote dependencies
|
||||
// can be directly followed.
|
||||
package protodesc
|
||||
|
||||
import (
|
||||
"google.golang.org/protobuf/internal/errors"
|
||||
"google.golang.org/protobuf/internal/filedesc"
|
||||
"google.golang.org/protobuf/internal/pragma"
|
||||
"google.golang.org/protobuf/internal/strs"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/reflect/protoregistry"
|
||||
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
)
|
||||
|
||||
// Resolver is the resolver used by NewFile to resolve dependencies.
|
||||
// The enums and messages provided must belong to some parent file,
|
||||
// which is also registered.
|
||||
//
|
||||
// It is implemented by protoregistry.Files.
|
||||
type Resolver interface {
|
||||
FindFileByPath(string) (protoreflect.FileDescriptor, error)
|
||||
FindDescriptorByName(protoreflect.FullName) (protoreflect.Descriptor, error)
|
||||
}
|
||||
|
||||
// FileOptions configures the construction of file descriptors.
|
||||
type FileOptions struct {
|
||||
pragma.NoUnkeyedLiterals
|
||||
|
||||
// AllowUnresolvable configures New to permissively allow unresolvable
|
||||
// file, enum, or message dependencies. Unresolved dependencies are replaced
|
||||
// by placeholder equivalents.
|
||||
//
|
||||
// The following dependencies may be left unresolved:
|
||||
// • Resolving an imported file.
|
||||
// • Resolving the type for a message field or extension field.
|
||||
// If the kind of the field is unknown, then a placeholder is used for both
|
||||
// the Enum and Message accessors on the protoreflect.FieldDescriptor.
|
||||
// • Resolving an enum value set as the default for an optional enum field.
|
||||
// If unresolvable, the protoreflect.FieldDescriptor.Default is set to the
|
||||
// first value in the associated enum (or zero if the also enum dependency
|
||||
// is also unresolvable). The protoreflect.FieldDescriptor.DefaultEnumValue
|
||||
// is populated with a placeholder.
|
||||
// • Resolving the extended message type for an extension field.
|
||||
// • Resolving the input or output message type for a service method.
|
||||
//
|
||||
// If the unresolved dependency uses a relative name,
|
||||
// then the placeholder will contain an invalid FullName with a "*." prefix,
|
||||
// indicating that the starting prefix of the full name is unknown.
|
||||
AllowUnresolvable bool
|
||||
}
|
||||
|
||||
// NewFile creates a new protoreflect.FileDescriptor from the provided
|
||||
// file descriptor message. See FileOptions.New for more information.
|
||||
func NewFile(fd *descriptorpb.FileDescriptorProto, r Resolver) (protoreflect.FileDescriptor, error) {
|
||||
return FileOptions{}.New(fd, r)
|
||||
}
|
||||
|
||||
// NewFiles creates a new protoregistry.Files from the provided
|
||||
// FileDescriptorSet message. See FileOptions.NewFiles for more information.
|
||||
func NewFiles(fd *descriptorpb.FileDescriptorSet) (*protoregistry.Files, error) {
|
||||
return FileOptions{}.NewFiles(fd)
|
||||
}
|
||||
|
||||
// New creates a new protoreflect.FileDescriptor from the provided
|
||||
// file descriptor message. The file must represent a valid proto file according
|
||||
// to protobuf semantics. The returned descriptor is a deep copy of the input.
|
||||
//
|
||||
// Any imported files, enum types, or message types referenced in the file are
|
||||
// resolved using the provided registry. When looking up an import file path,
|
||||
// the path must be unique. The newly created file descriptor is not registered
|
||||
// back into the provided file registry.
|
||||
func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (protoreflect.FileDescriptor, error) {
|
||||
if r == nil {
|
||||
r = (*protoregistry.Files)(nil) // empty resolver
|
||||
}
|
||||
|
||||
// Handle the file descriptor content.
|
||||
f := &filedesc.File{L2: &filedesc.FileL2{}}
|
||||
switch fd.GetSyntax() {
|
||||
case "proto2", "":
|
||||
f.L1.Syntax = protoreflect.Proto2
|
||||
case "proto3":
|
||||
f.L1.Syntax = protoreflect.Proto3
|
||||
default:
|
||||
return nil, errors.New("invalid syntax: %q", fd.GetSyntax())
|
||||
}
|
||||
f.L1.Path = fd.GetName()
|
||||
if f.L1.Path == "" {
|
||||
return nil, errors.New("file path must be populated")
|
||||
}
|
||||
f.L1.Package = protoreflect.FullName(fd.GetPackage())
|
||||
if !f.L1.Package.IsValid() && f.L1.Package != "" {
|
||||
return nil, errors.New("invalid package: %q", f.L1.Package)
|
||||
}
|
||||
if opts := fd.GetOptions(); opts != nil {
|
||||
opts = proto.Clone(opts).(*descriptorpb.FileOptions)
|
||||
f.L2.Options = func() protoreflect.ProtoMessage { return opts }
|
||||
}
|
||||
|
||||
f.L2.Imports = make(filedesc.FileImports, len(fd.GetDependency()))
|
||||
for _, i := range fd.GetPublicDependency() {
|
||||
if !(0 <= i && int(i) < len(f.L2.Imports)) || f.L2.Imports[i].IsPublic {
|
||||
return nil, errors.New("invalid or duplicate public import index: %d", i)
|
||||
}
|
||||
f.L2.Imports[i].IsPublic = true
|
||||
}
|
||||
for _, i := range fd.GetWeakDependency() {
|
||||
if !(0 <= i && int(i) < len(f.L2.Imports)) || f.L2.Imports[i].IsWeak {
|
||||
return nil, errors.New("invalid or duplicate weak import index: %d", i)
|
||||
}
|
||||
f.L2.Imports[i].IsWeak = true
|
||||
}
|
||||
imps := importSet{f.Path(): true}
|
||||
for i, path := range fd.GetDependency() {
|
||||
imp := &f.L2.Imports[i]
|
||||
f, err := r.FindFileByPath(path)
|
||||
if err == protoregistry.NotFound && (o.AllowUnresolvable || imp.IsWeak) {
|
||||
f = filedesc.PlaceholderFile(path)
|
||||
} else if err != nil {
|
||||
return nil, errors.New("could not resolve import %q: %v", path, err)
|
||||
}
|
||||
imp.FileDescriptor = f
|
||||
|
||||
if imps[imp.Path()] {
|
||||
return nil, errors.New("already imported %q", path)
|
||||
}
|
||||
imps[imp.Path()] = true
|
||||
}
|
||||
for i := range fd.GetDependency() {
|
||||
imp := &f.L2.Imports[i]
|
||||
imps.importPublic(imp.Imports())
|
||||
}
|
||||
|
||||
// Handle source locations.
|
||||
f.L2.Locations.File = f
|
||||
for _, loc := range fd.GetSourceCodeInfo().GetLocation() {
|
||||
var l protoreflect.SourceLocation
|
||||
// TODO: Validate that the path points to an actual declaration?
|
||||
l.Path = protoreflect.SourcePath(loc.GetPath())
|
||||
s := loc.GetSpan()
|
||||
switch len(s) {
|
||||
case 3:
|
||||
l.StartLine, l.StartColumn, l.EndLine, l.EndColumn = int(s[0]), int(s[1]), int(s[0]), int(s[2])
|
||||
case 4:
|
||||
l.StartLine, l.StartColumn, l.EndLine, l.EndColumn = int(s[0]), int(s[1]), int(s[2]), int(s[3])
|
||||
default:
|
||||
return nil, errors.New("invalid span: %v", s)
|
||||
}
|
||||
// TODO: Validate that the span information is sensible?
|
||||
// See https://github.com/protocolbuffers/protobuf/issues/6378.
|
||||
if false && (l.EndLine < l.StartLine || l.StartLine < 0 || l.StartColumn < 0 || l.EndColumn < 0 ||
|
||||
(l.StartLine == l.EndLine && l.EndColumn <= l.StartColumn)) {
|
||||
return nil, errors.New("invalid span: %v", s)
|
||||
}
|
||||
l.LeadingDetachedComments = loc.GetLeadingDetachedComments()
|
||||
l.LeadingComments = loc.GetLeadingComments()
|
||||
l.TrailingComments = loc.GetTrailingComments()
|
||||
f.L2.Locations.List = append(f.L2.Locations.List, l)
|
||||
}
|
||||
|
||||
// Step 1: Allocate and derive the names for all declarations.
|
||||
// This copies all fields from the descriptor proto except:
|
||||
// google.protobuf.FieldDescriptorProto.type_name
|
||||
// google.protobuf.FieldDescriptorProto.default_value
|
||||
// google.protobuf.FieldDescriptorProto.oneof_index
|
||||
// google.protobuf.FieldDescriptorProto.extendee
|
||||
// google.protobuf.MethodDescriptorProto.input
|
||||
// google.protobuf.MethodDescriptorProto.output
|
||||
var err error
|
||||
sb := new(strs.Builder)
|
||||
r1 := make(descsByName)
|
||||
if f.L1.Enums.List, err = r1.initEnumDeclarations(fd.GetEnumType(), f, sb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if f.L1.Messages.List, err = r1.initMessagesDeclarations(fd.GetMessageType(), f, sb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if f.L1.Extensions.List, err = r1.initExtensionDeclarations(fd.GetExtension(), f, sb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if f.L1.Services.List, err = r1.initServiceDeclarations(fd.GetService(), f, sb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Step 2: Resolve every dependency reference not handled by step 1.
|
||||
r2 := &resolver{local: r1, remote: r, imports: imps, allowUnresolvable: o.AllowUnresolvable}
|
||||
if err := r2.resolveMessageDependencies(f.L1.Messages.List, fd.GetMessageType()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := r2.resolveExtensionDependencies(f.L1.Extensions.List, fd.GetExtension()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := r2.resolveServiceDependencies(f.L1.Services.List, fd.GetService()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Step 3: Validate every enum, message, and extension declaration.
|
||||
if err := validateEnumDeclarations(f.L1.Enums.List, fd.GetEnumType()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := validateMessageDeclarations(f.L1.Messages.List, fd.GetMessageType()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := validateExtensionDeclarations(f.L1.Extensions.List, fd.GetExtension()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return f, nil
|
||||
}
|
||||
|
||||
type importSet map[string]bool
|
||||
|
||||
func (is importSet) importPublic(imps protoreflect.FileImports) {
|
||||
for i := 0; i < imps.Len(); i++ {
|
||||
if imp := imps.Get(i); imp.IsPublic {
|
||||
is[imp.Path()] = true
|
||||
is.importPublic(imp.Imports())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NewFiles creates a new protoregistry.Files from the provided
|
||||
// FileDescriptorSet message. The descriptor set must include only
|
||||
// valid files according to protobuf semantics. The returned descriptors
|
||||
// are a deep copy of the input.
|
||||
func (o FileOptions) NewFiles(fds *descriptorpb.FileDescriptorSet) (*protoregistry.Files, error) {
|
||||
files := make(map[string]*descriptorpb.FileDescriptorProto)
|
||||
for _, fd := range fds.File {
|
||||
if _, ok := files[fd.GetName()]; ok {
|
||||
return nil, errors.New("file appears multiple times: %q", fd.GetName())
|
||||
}
|
||||
files[fd.GetName()] = fd
|
||||
}
|
||||
r := &protoregistry.Files{}
|
||||
for _, fd := range files {
|
||||
if err := o.addFileDeps(r, fd, files); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
func (o FileOptions) addFileDeps(r *protoregistry.Files, fd *descriptorpb.FileDescriptorProto, files map[string]*descriptorpb.FileDescriptorProto) error {
|
||||
// Set the entry to nil while descending into a file's dependencies to detect cycles.
|
||||
files[fd.GetName()] = nil
|
||||
for _, dep := range fd.Dependency {
|
||||
depfd, ok := files[dep]
|
||||
if depfd == nil {
|
||||
if ok {
|
||||
return errors.New("import cycle in file: %q", dep)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err := o.addFileDeps(r, depfd, files); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Delete the entry once dependencies are processed.
|
||||
delete(files, fd.GetName())
|
||||
f, err := o.New(fd, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return r.RegisterFile(f)
|
||||
}
|
248
vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go
generated
vendored
248
vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go
generated
vendored
@ -1,248 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package protodesc
|
||||
|
||||
import (
|
||||
"google.golang.org/protobuf/internal/errors"
|
||||
"google.golang.org/protobuf/internal/filedesc"
|
||||
"google.golang.org/protobuf/internal/strs"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
)
|
||||
|
||||
type descsByName map[protoreflect.FullName]protoreflect.Descriptor
|
||||
|
||||
func (r descsByName) initEnumDeclarations(eds []*descriptorpb.EnumDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (es []filedesc.Enum, err error) {
|
||||
es = make([]filedesc.Enum, len(eds)) // allocate up-front to ensure stable pointers
|
||||
for i, ed := range eds {
|
||||
e := &es[i]
|
||||
e.L2 = new(filedesc.EnumL2)
|
||||
if e.L0, err = r.makeBase(e, parent, ed.GetName(), i, sb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if opts := ed.GetOptions(); opts != nil {
|
||||
opts = proto.Clone(opts).(*descriptorpb.EnumOptions)
|
||||
e.L2.Options = func() protoreflect.ProtoMessage { return opts }
|
||||
}
|
||||
for _, s := range ed.GetReservedName() {
|
||||
e.L2.ReservedNames.List = append(e.L2.ReservedNames.List, protoreflect.Name(s))
|
||||
}
|
||||
for _, rr := range ed.GetReservedRange() {
|
||||
e.L2.ReservedRanges.List = append(e.L2.ReservedRanges.List, [2]protoreflect.EnumNumber{
|
||||
protoreflect.EnumNumber(rr.GetStart()),
|
||||
protoreflect.EnumNumber(rr.GetEnd()),
|
||||
})
|
||||
}
|
||||
if e.L2.Values.List, err = r.initEnumValuesFromDescriptorProto(ed.GetValue(), e, sb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return es, nil
|
||||
}
|
||||
|
||||
func (r descsByName) initEnumValuesFromDescriptorProto(vds []*descriptorpb.EnumValueDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (vs []filedesc.EnumValue, err error) {
|
||||
vs = make([]filedesc.EnumValue, len(vds)) // allocate up-front to ensure stable pointers
|
||||
for i, vd := range vds {
|
||||
v := &vs[i]
|
||||
if v.L0, err = r.makeBase(v, parent, vd.GetName(), i, sb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if opts := vd.GetOptions(); opts != nil {
|
||||
opts = proto.Clone(opts).(*descriptorpb.EnumValueOptions)
|
||||
v.L1.Options = func() protoreflect.ProtoMessage { return opts }
|
||||
}
|
||||
v.L1.Number = protoreflect.EnumNumber(vd.GetNumber())
|
||||
}
|
||||
return vs, nil
|
||||
}
|
||||
|
||||
func (r descsByName) initMessagesDeclarations(mds []*descriptorpb.DescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ms []filedesc.Message, err error) {
|
||||
ms = make([]filedesc.Message, len(mds)) // allocate up-front to ensure stable pointers
|
||||
for i, md := range mds {
|
||||
m := &ms[i]
|
||||
m.L2 = new(filedesc.MessageL2)
|
||||
if m.L0, err = r.makeBase(m, parent, md.GetName(), i, sb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if opts := md.GetOptions(); opts != nil {
|
||||
opts = proto.Clone(opts).(*descriptorpb.MessageOptions)
|
||||
m.L2.Options = func() protoreflect.ProtoMessage { return opts }
|
||||
m.L1.IsMapEntry = opts.GetMapEntry()
|
||||
m.L1.IsMessageSet = opts.GetMessageSetWireFormat()
|
||||
}
|
||||
for _, s := range md.GetReservedName() {
|
||||
m.L2.ReservedNames.List = append(m.L2.ReservedNames.List, protoreflect.Name(s))
|
||||
}
|
||||
for _, rr := range md.GetReservedRange() {
|
||||
m.L2.ReservedRanges.List = append(m.L2.ReservedRanges.List, [2]protoreflect.FieldNumber{
|
||||
protoreflect.FieldNumber(rr.GetStart()),
|
||||
protoreflect.FieldNumber(rr.GetEnd()),
|
||||
})
|
||||
}
|
||||
for _, xr := range md.GetExtensionRange() {
|
||||
m.L2.ExtensionRanges.List = append(m.L2.ExtensionRanges.List, [2]protoreflect.FieldNumber{
|
||||
protoreflect.FieldNumber(xr.GetStart()),
|
||||
protoreflect.FieldNumber(xr.GetEnd()),
|
||||
})
|
||||
var optsFunc func() protoreflect.ProtoMessage
|
||||
if opts := xr.GetOptions(); opts != nil {
|
||||
opts = proto.Clone(opts).(*descriptorpb.ExtensionRangeOptions)
|
||||
optsFunc = func() protoreflect.ProtoMessage { return opts }
|
||||
}
|
||||
m.L2.ExtensionRangeOptions = append(m.L2.ExtensionRangeOptions, optsFunc)
|
||||
}
|
||||
if m.L2.Fields.List, err = r.initFieldsFromDescriptorProto(md.GetField(), m, sb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if m.L2.Oneofs.List, err = r.initOneofsFromDescriptorProto(md.GetOneofDecl(), m, sb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if m.L1.Enums.List, err = r.initEnumDeclarations(md.GetEnumType(), m, sb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if m.L1.Messages.List, err = r.initMessagesDeclarations(md.GetNestedType(), m, sb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if m.L1.Extensions.List, err = r.initExtensionDeclarations(md.GetExtension(), m, sb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return ms, nil
|
||||
}
|
||||
|
||||
func (r descsByName) initFieldsFromDescriptorProto(fds []*descriptorpb.FieldDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (fs []filedesc.Field, err error) {
|
||||
fs = make([]filedesc.Field, len(fds)) // allocate up-front to ensure stable pointers
|
||||
for i, fd := range fds {
|
||||
f := &fs[i]
|
||||
if f.L0, err = r.makeBase(f, parent, fd.GetName(), i, sb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f.L1.IsProto3Optional = fd.GetProto3Optional()
|
||||
if opts := fd.GetOptions(); opts != nil {
|
||||
opts = proto.Clone(opts).(*descriptorpb.FieldOptions)
|
||||
f.L1.Options = func() protoreflect.ProtoMessage { return opts }
|
||||
f.L1.IsWeak = opts.GetWeak()
|
||||
f.L1.HasPacked = opts.Packed != nil
|
||||
f.L1.IsPacked = opts.GetPacked()
|
||||
}
|
||||
f.L1.Number = protoreflect.FieldNumber(fd.GetNumber())
|
||||
f.L1.Cardinality = protoreflect.Cardinality(fd.GetLabel())
|
||||
if fd.Type != nil {
|
||||
f.L1.Kind = protoreflect.Kind(fd.GetType())
|
||||
}
|
||||
if fd.JsonName != nil {
|
||||
f.L1.StringName.InitJSON(fd.GetJsonName())
|
||||
}
|
||||
}
|
||||
return fs, nil
|
||||
}
|
||||
|
||||
func (r descsByName) initOneofsFromDescriptorProto(ods []*descriptorpb.OneofDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (os []filedesc.Oneof, err error) {
|
||||
os = make([]filedesc.Oneof, len(ods)) // allocate up-front to ensure stable pointers
|
||||
for i, od := range ods {
|
||||
o := &os[i]
|
||||
if o.L0, err = r.makeBase(o, parent, od.GetName(), i, sb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if opts := od.GetOptions(); opts != nil {
|
||||
opts = proto.Clone(opts).(*descriptorpb.OneofOptions)
|
||||
o.L1.Options = func() protoreflect.ProtoMessage { return opts }
|
||||
}
|
||||
}
|
||||
return os, nil
|
||||
}
|
||||
|
||||
func (r descsByName) initExtensionDeclarations(xds []*descriptorpb.FieldDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (xs []filedesc.Extension, err error) {
|
||||
xs = make([]filedesc.Extension, len(xds)) // allocate up-front to ensure stable pointers
|
||||
for i, xd := range xds {
|
||||
x := &xs[i]
|
||||
x.L2 = new(filedesc.ExtensionL2)
|
||||
if x.L0, err = r.makeBase(x, parent, xd.GetName(), i, sb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if opts := xd.GetOptions(); opts != nil {
|
||||
opts = proto.Clone(opts).(*descriptorpb.FieldOptions)
|
||||
x.L2.Options = func() protoreflect.ProtoMessage { return opts }
|
||||
x.L2.IsPacked = opts.GetPacked()
|
||||
}
|
||||
x.L1.Number = protoreflect.FieldNumber(xd.GetNumber())
|
||||
x.L1.Cardinality = protoreflect.Cardinality(xd.GetLabel())
|
||||
if xd.Type != nil {
|
||||
x.L1.Kind = protoreflect.Kind(xd.GetType())
|
||||
}
|
||||
if xd.JsonName != nil {
|
||||
x.L2.StringName.InitJSON(xd.GetJsonName())
|
||||
}
|
||||
}
|
||||
return xs, nil
|
||||
}
|
||||
|
||||
func (r descsByName) initServiceDeclarations(sds []*descriptorpb.ServiceDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ss []filedesc.Service, err error) {
|
||||
ss = make([]filedesc.Service, len(sds)) // allocate up-front to ensure stable pointers
|
||||
for i, sd := range sds {
|
||||
s := &ss[i]
|
||||
s.L2 = new(filedesc.ServiceL2)
|
||||
if s.L0, err = r.makeBase(s, parent, sd.GetName(), i, sb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if opts := sd.GetOptions(); opts != nil {
|
||||
opts = proto.Clone(opts).(*descriptorpb.ServiceOptions)
|
||||
s.L2.Options = func() protoreflect.ProtoMessage { return opts }
|
||||
}
|
||||
if s.L2.Methods.List, err = r.initMethodsFromDescriptorProto(sd.GetMethod(), s, sb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return ss, nil
|
||||
}
|
||||
|
||||
func (r descsByName) initMethodsFromDescriptorProto(mds []*descriptorpb.MethodDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ms []filedesc.Method, err error) {
|
||||
ms = make([]filedesc.Method, len(mds)) // allocate up-front to ensure stable pointers
|
||||
for i, md := range mds {
|
||||
m := &ms[i]
|
||||
if m.L0, err = r.makeBase(m, parent, md.GetName(), i, sb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if opts := md.GetOptions(); opts != nil {
|
||||
opts = proto.Clone(opts).(*descriptorpb.MethodOptions)
|
||||
m.L1.Options = func() protoreflect.ProtoMessage { return opts }
|
||||
}
|
||||
m.L1.IsStreamingClient = md.GetClientStreaming()
|
||||
m.L1.IsStreamingServer = md.GetServerStreaming()
|
||||
}
|
||||
return ms, nil
|
||||
}
|
||||
|
||||
func (r descsByName) makeBase(child, parent protoreflect.Descriptor, name string, idx int, sb *strs.Builder) (filedesc.BaseL0, error) {
|
||||
if !protoreflect.Name(name).IsValid() {
|
||||
return filedesc.BaseL0{}, errors.New("descriptor %q has an invalid nested name: %q", parent.FullName(), name)
|
||||
}
|
||||
|
||||
// Derive the full name of the child.
|
||||
// Note that enum values are a sibling to the enum parent in the namespace.
|
||||
var fullName protoreflect.FullName
|
||||
if _, ok := parent.(protoreflect.EnumDescriptor); ok {
|
||||
fullName = sb.AppendFullName(parent.FullName().Parent(), protoreflect.Name(name))
|
||||
} else {
|
||||
fullName = sb.AppendFullName(parent.FullName(), protoreflect.Name(name))
|
||||
}
|
||||
if _, ok := r[fullName]; ok {
|
||||
return filedesc.BaseL0{}, errors.New("descriptor %q already declared", fullName)
|
||||
}
|
||||
r[fullName] = child
|
||||
|
||||
// TODO: Verify that the full name does not already exist in the resolver?
|
||||
// This is not as critical since most usages of NewFile will register
|
||||
// the created file back into the registry, which will perform this check.
|
||||
|
||||
return filedesc.BaseL0{
|
||||
FullName: fullName,
|
||||
ParentFile: parent.ParentFile().(*filedesc.File),
|
||||
Parent: parent,
|
||||
Index: idx,
|
||||
}, nil
|
||||
}
|
286
vendor/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go
generated
vendored
286
vendor/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go
generated
vendored
@ -1,286 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package protodesc
|
||||
|
||||
import (
|
||||
"google.golang.org/protobuf/internal/encoding/defval"
|
||||
"google.golang.org/protobuf/internal/errors"
|
||||
"google.golang.org/protobuf/internal/filedesc"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/reflect/protoregistry"
|
||||
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
)
|
||||
|
||||
// resolver is a wrapper around a local registry of declarations within the file
|
||||
// and the remote resolver. The remote resolver is restricted to only return
|
||||
// descriptors that have been imported.
|
||||
type resolver struct {
|
||||
local descsByName
|
||||
remote Resolver
|
||||
imports importSet
|
||||
|
||||
allowUnresolvable bool
|
||||
}
|
||||
|
||||
func (r *resolver) resolveMessageDependencies(ms []filedesc.Message, mds []*descriptorpb.DescriptorProto) (err error) {
|
||||
for i, md := range mds {
|
||||
m := &ms[i]
|
||||
for j, fd := range md.GetField() {
|
||||
f := &m.L2.Fields.List[j]
|
||||
if f.L1.Cardinality == protoreflect.Required {
|
||||
m.L2.RequiredNumbers.List = append(m.L2.RequiredNumbers.List, f.L1.Number)
|
||||
}
|
||||
if fd.OneofIndex != nil {
|
||||
k := int(fd.GetOneofIndex())
|
||||
if !(0 <= k && k < len(md.GetOneofDecl())) {
|
||||
return errors.New("message field %q has an invalid oneof index: %d", f.FullName(), k)
|
||||
}
|
||||
o := &m.L2.Oneofs.List[k]
|
||||
f.L1.ContainingOneof = o
|
||||
o.L1.Fields.List = append(o.L1.Fields.List, f)
|
||||
}
|
||||
|
||||
if f.L1.Kind, f.L1.Enum, f.L1.Message, err = r.findTarget(f.Kind(), f.Parent().FullName(), partialName(fd.GetTypeName()), f.IsWeak()); err != nil {
|
||||
return errors.New("message field %q cannot resolve type: %v", f.FullName(), err)
|
||||
}
|
||||
if fd.DefaultValue != nil {
|
||||
v, ev, err := unmarshalDefault(fd.GetDefaultValue(), f, r.allowUnresolvable)
|
||||
if err != nil {
|
||||
return errors.New("message field %q has invalid default: %v", f.FullName(), err)
|
||||
}
|
||||
f.L1.Default = filedesc.DefaultValue(v, ev)
|
||||
}
|
||||
}
|
||||
|
||||
if err := r.resolveMessageDependencies(m.L1.Messages.List, md.GetNestedType()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := r.resolveExtensionDependencies(m.L1.Extensions.List, md.GetExtension()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *resolver) resolveExtensionDependencies(xs []filedesc.Extension, xds []*descriptorpb.FieldDescriptorProto) (err error) {
|
||||
for i, xd := range xds {
|
||||
x := &xs[i]
|
||||
if x.L1.Extendee, err = r.findMessageDescriptor(x.Parent().FullName(), partialName(xd.GetExtendee()), false); err != nil {
|
||||
return errors.New("extension field %q cannot resolve extendee: %v", x.FullName(), err)
|
||||
}
|
||||
if x.L1.Kind, x.L2.Enum, x.L2.Message, err = r.findTarget(x.Kind(), x.Parent().FullName(), partialName(xd.GetTypeName()), false); err != nil {
|
||||
return errors.New("extension field %q cannot resolve type: %v", x.FullName(), err)
|
||||
}
|
||||
if xd.DefaultValue != nil {
|
||||
v, ev, err := unmarshalDefault(xd.GetDefaultValue(), x, r.allowUnresolvable)
|
||||
if err != nil {
|
||||
return errors.New("extension field %q has invalid default: %v", x.FullName(), err)
|
||||
}
|
||||
x.L2.Default = filedesc.DefaultValue(v, ev)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *resolver) resolveServiceDependencies(ss []filedesc.Service, sds []*descriptorpb.ServiceDescriptorProto) (err error) {
|
||||
for i, sd := range sds {
|
||||
s := &ss[i]
|
||||
for j, md := range sd.GetMethod() {
|
||||
m := &s.L2.Methods.List[j]
|
||||
m.L1.Input, err = r.findMessageDescriptor(m.Parent().FullName(), partialName(md.GetInputType()), false)
|
||||
if err != nil {
|
||||
return errors.New("service method %q cannot resolve input: %v", m.FullName(), err)
|
||||
}
|
||||
m.L1.Output, err = r.findMessageDescriptor(s.FullName(), partialName(md.GetOutputType()), false)
|
||||
if err != nil {
|
||||
return errors.New("service method %q cannot resolve output: %v", m.FullName(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// findTarget finds an enum or message descriptor if k is an enum, message,
|
||||
// group, or unknown. If unknown, and the name could be resolved, the kind
|
||||
// returned kind is set based on the type of the resolved descriptor.
|
||||
func (r *resolver) findTarget(k protoreflect.Kind, scope protoreflect.FullName, ref partialName, isWeak bool) (protoreflect.Kind, protoreflect.EnumDescriptor, protoreflect.MessageDescriptor, error) {
|
||||
switch k {
|
||||
case protoreflect.EnumKind:
|
||||
ed, err := r.findEnumDescriptor(scope, ref, isWeak)
|
||||
if err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
return k, ed, nil, nil
|
||||
case protoreflect.MessageKind, protoreflect.GroupKind:
|
||||
md, err := r.findMessageDescriptor(scope, ref, isWeak)
|
||||
if err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
return k, nil, md, nil
|
||||
case 0:
|
||||
// Handle unspecified kinds (possible with parsers that operate
|
||||
// on a per-file basis without knowledge of dependencies).
|
||||
d, err := r.findDescriptor(scope, ref)
|
||||
if err == protoregistry.NotFound && (r.allowUnresolvable || isWeak) {
|
||||
return k, filedesc.PlaceholderEnum(ref.FullName()), filedesc.PlaceholderMessage(ref.FullName()), nil
|
||||
} else if err == protoregistry.NotFound {
|
||||
return 0, nil, nil, errors.New("%q not found", ref.FullName())
|
||||
} else if err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
switch d := d.(type) {
|
||||
case protoreflect.EnumDescriptor:
|
||||
return protoreflect.EnumKind, d, nil, nil
|
||||
case protoreflect.MessageDescriptor:
|
||||
return protoreflect.MessageKind, nil, d, nil
|
||||
default:
|
||||
return 0, nil, nil, errors.New("unknown kind")
|
||||
}
|
||||
default:
|
||||
if ref != "" {
|
||||
return 0, nil, nil, errors.New("target name cannot be specified for %v", k)
|
||||
}
|
||||
if !k.IsValid() {
|
||||
return 0, nil, nil, errors.New("invalid kind: %d", k)
|
||||
}
|
||||
return k, nil, nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
// findDescriptor finds the descriptor by name,
|
||||
// which may be a relative name within some scope.
|
||||
//
|
||||
// Suppose the scope was "fizz.buzz" and the reference was "Foo.Bar",
|
||||
// then the following full names are searched:
|
||||
// * fizz.buzz.Foo.Bar
|
||||
// * fizz.Foo.Bar
|
||||
// * Foo.Bar
|
||||
func (r *resolver) findDescriptor(scope protoreflect.FullName, ref partialName) (protoreflect.Descriptor, error) {
|
||||
if !ref.IsValid() {
|
||||
return nil, errors.New("invalid name reference: %q", ref)
|
||||
}
|
||||
if ref.IsFull() {
|
||||
scope, ref = "", ref[1:]
|
||||
}
|
||||
var foundButNotImported protoreflect.Descriptor
|
||||
for {
|
||||
// Derive the full name to search.
|
||||
s := protoreflect.FullName(ref)
|
||||
if scope != "" {
|
||||
s = scope + "." + s
|
||||
}
|
||||
|
||||
// Check the current file for the descriptor.
|
||||
if d, ok := r.local[s]; ok {
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// Check the remote registry for the descriptor.
|
||||
d, err := r.remote.FindDescriptorByName(s)
|
||||
if err == nil {
|
||||
// Only allow descriptors covered by one of the imports.
|
||||
if r.imports[d.ParentFile().Path()] {
|
||||
return d, nil
|
||||
}
|
||||
foundButNotImported = d
|
||||
} else if err != protoregistry.NotFound {
|
||||
return nil, errors.Wrap(err, "%q", s)
|
||||
}
|
||||
|
||||
// Continue on at a higher level of scoping.
|
||||
if scope == "" {
|
||||
if d := foundButNotImported; d != nil {
|
||||
return nil, errors.New("resolved %q, but %q is not imported", d.FullName(), d.ParentFile().Path())
|
||||
}
|
||||
return nil, protoregistry.NotFound
|
||||
}
|
||||
scope = scope.Parent()
|
||||
}
|
||||
}
|
||||
|
||||
func (r *resolver) findEnumDescriptor(scope protoreflect.FullName, ref partialName, isWeak bool) (protoreflect.EnumDescriptor, error) {
|
||||
d, err := r.findDescriptor(scope, ref)
|
||||
if err == protoregistry.NotFound && (r.allowUnresolvable || isWeak) {
|
||||
return filedesc.PlaceholderEnum(ref.FullName()), nil
|
||||
} else if err == protoregistry.NotFound {
|
||||
return nil, errors.New("%q not found", ref.FullName())
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ed, ok := d.(protoreflect.EnumDescriptor)
|
||||
if !ok {
|
||||
return nil, errors.New("resolved %q, but it is not an enum", d.FullName())
|
||||
}
|
||||
return ed, nil
|
||||
}
|
||||
|
||||
func (r *resolver) findMessageDescriptor(scope protoreflect.FullName, ref partialName, isWeak bool) (protoreflect.MessageDescriptor, error) {
|
||||
d, err := r.findDescriptor(scope, ref)
|
||||
if err == protoregistry.NotFound && (r.allowUnresolvable || isWeak) {
|
||||
return filedesc.PlaceholderMessage(ref.FullName()), nil
|
||||
} else if err == protoregistry.NotFound {
|
||||
return nil, errors.New("%q not found", ref.FullName())
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
md, ok := d.(protoreflect.MessageDescriptor)
|
||||
if !ok {
|
||||
return nil, errors.New("resolved %q, but it is not an message", d.FullName())
|
||||
}
|
||||
return md, nil
|
||||
}
|
||||
|
||||
// partialName is the partial name. A leading dot means that the name is full,
|
||||
// otherwise the name is relative to some current scope.
|
||||
// See google.protobuf.FieldDescriptorProto.type_name.
|
||||
type partialName string
|
||||
|
||||
func (s partialName) IsFull() bool {
|
||||
return len(s) > 0 && s[0] == '.'
|
||||
}
|
||||
|
||||
func (s partialName) IsValid() bool {
|
||||
if s.IsFull() {
|
||||
return protoreflect.FullName(s[1:]).IsValid()
|
||||
}
|
||||
return protoreflect.FullName(s).IsValid()
|
||||
}
|
||||
|
||||
const unknownPrefix = "*."
|
||||
|
||||
// FullName converts the partial name to a full name on a best-effort basis.
|
||||
// If relative, it creates an invalid full name, using a "*." prefix
|
||||
// to indicate that the start of the full name is unknown.
|
||||
func (s partialName) FullName() protoreflect.FullName {
|
||||
if s.IsFull() {
|
||||
return protoreflect.FullName(s[1:])
|
||||
}
|
||||
return protoreflect.FullName(unknownPrefix + s)
|
||||
}
|
||||
|
||||
func unmarshalDefault(s string, fd protoreflect.FieldDescriptor, allowUnresolvable bool) (protoreflect.Value, protoreflect.EnumValueDescriptor, error) {
|
||||
var evs protoreflect.EnumValueDescriptors
|
||||
if fd.Enum() != nil {
|
||||
evs = fd.Enum().Values()
|
||||
}
|
||||
v, ev, err := defval.Unmarshal(s, fd.Kind(), evs, defval.Descriptor)
|
||||
if err != nil && allowUnresolvable && evs != nil && protoreflect.Name(s).IsValid() {
|
||||
v = protoreflect.ValueOfEnum(0)
|
||||
if evs.Len() > 0 {
|
||||
v = protoreflect.ValueOfEnum(evs.Get(0).Number())
|
||||
}
|
||||
ev = filedesc.PlaceholderEnumValue(fd.Enum().FullName().Parent().Append(protoreflect.Name(s)))
|
||||
} else if err != nil {
|
||||
return v, ev, err
|
||||
}
|
||||
if fd.Syntax() == protoreflect.Proto3 {
|
||||
return v, ev, errors.New("cannot be specified under proto3 semantics")
|
||||
}
|
||||
if fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind || fd.Cardinality() == protoreflect.Repeated {
|
||||
return v, ev, errors.New("cannot be specified on composite types")
|
||||
}
|
||||
return v, ev, nil
|
||||
}
|
374
vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go
generated
vendored
374
vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go
generated
vendored
@ -1,374 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package protodesc
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"google.golang.org/protobuf/encoding/protowire"
|
||||
"google.golang.org/protobuf/internal/errors"
|
||||
"google.golang.org/protobuf/internal/filedesc"
|
||||
"google.golang.org/protobuf/internal/flags"
|
||||
"google.golang.org/protobuf/internal/genid"
|
||||
"google.golang.org/protobuf/internal/strs"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
)
|
||||
|
||||
func validateEnumDeclarations(es []filedesc.Enum, eds []*descriptorpb.EnumDescriptorProto) error {
|
||||
for i, ed := range eds {
|
||||
e := &es[i]
|
||||
if err := e.L2.ReservedNames.CheckValid(); err != nil {
|
||||
return errors.New("enum %q reserved names has %v", e.FullName(), err)
|
||||
}
|
||||
if err := e.L2.ReservedRanges.CheckValid(); err != nil {
|
||||
return errors.New("enum %q reserved ranges has %v", e.FullName(), err)
|
||||
}
|
||||
if len(ed.GetValue()) == 0 {
|
||||
return errors.New("enum %q must contain at least one value declaration", e.FullName())
|
||||
}
|
||||
allowAlias := ed.GetOptions().GetAllowAlias()
|
||||
foundAlias := false
|
||||
for i := 0; i < e.Values().Len(); i++ {
|
||||
v1 := e.Values().Get(i)
|
||||
if v2 := e.Values().ByNumber(v1.Number()); v1 != v2 {
|
||||
foundAlias = true
|
||||
if !allowAlias {
|
||||
return errors.New("enum %q has conflicting non-aliased values on number %d: %q with %q", e.FullName(), v1.Number(), v1.Name(), v2.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
if allowAlias && !foundAlias {
|
||||
return errors.New("enum %q allows aliases, but none were found", e.FullName())
|
||||
}
|
||||
if e.Syntax() == protoreflect.Proto3 {
|
||||
if v := e.Values().Get(0); v.Number() != 0 {
|
||||
return errors.New("enum %q using proto3 semantics must have zero number for the first value", v.FullName())
|
||||
}
|
||||
// Verify that value names in proto3 do not conflict if the
|
||||
// case-insensitive prefix is removed.
|
||||
// See protoc v3.8.0: src/google/protobuf/descriptor.cc:4991-5055
|
||||
names := map[string]protoreflect.EnumValueDescriptor{}
|
||||
prefix := strings.Replace(strings.ToLower(string(e.Name())), "_", "", -1)
|
||||
for i := 0; i < e.Values().Len(); i++ {
|
||||
v1 := e.Values().Get(i)
|
||||
s := strs.EnumValueName(strs.TrimEnumPrefix(string(v1.Name()), prefix))
|
||||
if v2, ok := names[s]; ok && v1.Number() != v2.Number() {
|
||||
return errors.New("enum %q using proto3 semantics has conflict: %q with %q", e.FullName(), v1.Name(), v2.Name())
|
||||
}
|
||||
names[s] = v1
|
||||
}
|
||||
}
|
||||
|
||||
for j, vd := range ed.GetValue() {
|
||||
v := &e.L2.Values.List[j]
|
||||
if vd.Number == nil {
|
||||
return errors.New("enum value %q must have a specified number", v.FullName())
|
||||
}
|
||||
if e.L2.ReservedNames.Has(v.Name()) {
|
||||
return errors.New("enum value %q must not use reserved name", v.FullName())
|
||||
}
|
||||
if e.L2.ReservedRanges.Has(v.Number()) {
|
||||
return errors.New("enum value %q must not use reserved number %d", v.FullName(), v.Number())
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateMessageDeclarations(ms []filedesc.Message, mds []*descriptorpb.DescriptorProto) error {
|
||||
for i, md := range mds {
|
||||
m := &ms[i]
|
||||
|
||||
// Handle the message descriptor itself.
|
||||
isMessageSet := md.GetOptions().GetMessageSetWireFormat()
|
||||
if err := m.L2.ReservedNames.CheckValid(); err != nil {
|
||||
return errors.New("message %q reserved names has %v", m.FullName(), err)
|
||||
}
|
||||
if err := m.L2.ReservedRanges.CheckValid(isMessageSet); err != nil {
|
||||
return errors.New("message %q reserved ranges has %v", m.FullName(), err)
|
||||
}
|
||||
if err := m.L2.ExtensionRanges.CheckValid(isMessageSet); err != nil {
|
||||
return errors.New("message %q extension ranges has %v", m.FullName(), err)
|
||||
}
|
||||
if err := (*filedesc.FieldRanges).CheckOverlap(&m.L2.ReservedRanges, &m.L2.ExtensionRanges); err != nil {
|
||||
return errors.New("message %q reserved and extension ranges has %v", m.FullName(), err)
|
||||
}
|
||||
for i := 0; i < m.Fields().Len(); i++ {
|
||||
f1 := m.Fields().Get(i)
|
||||
if f2 := m.Fields().ByNumber(f1.Number()); f1 != f2 {
|
||||
return errors.New("message %q has conflicting fields: %q with %q", m.FullName(), f1.Name(), f2.Name())
|
||||
}
|
||||
}
|
||||
if isMessageSet && !flags.ProtoLegacy {
|
||||
return errors.New("message %q is a MessageSet, which is a legacy proto1 feature that is no longer supported", m.FullName())
|
||||
}
|
||||
if isMessageSet && (m.Syntax() != protoreflect.Proto2 || m.Fields().Len() > 0 || m.ExtensionRanges().Len() == 0) {
|
||||
return errors.New("message %q is an invalid proto1 MessageSet", m.FullName())
|
||||
}
|
||||
if m.Syntax() == protoreflect.Proto3 {
|
||||
if m.ExtensionRanges().Len() > 0 {
|
||||
return errors.New("message %q using proto3 semantics cannot have extension ranges", m.FullName())
|
||||
}
|
||||
// Verify that field names in proto3 do not conflict if lowercased
|
||||
// with all underscores removed.
|
||||
// See protoc v3.8.0: src/google/protobuf/descriptor.cc:5830-5847
|
||||
names := map[string]protoreflect.FieldDescriptor{}
|
||||
for i := 0; i < m.Fields().Len(); i++ {
|
||||
f1 := m.Fields().Get(i)
|
||||
s := strings.Replace(strings.ToLower(string(f1.Name())), "_", "", -1)
|
||||
if f2, ok := names[s]; ok {
|
||||
return errors.New("message %q using proto3 semantics has conflict: %q with %q", m.FullName(), f1.Name(), f2.Name())
|
||||
}
|
||||
names[s] = f1
|
||||
}
|
||||
}
|
||||
|
||||
for j, fd := range md.GetField() {
|
||||
f := &m.L2.Fields.List[j]
|
||||
if m.L2.ReservedNames.Has(f.Name()) {
|
||||
return errors.New("message field %q must not use reserved name", f.FullName())
|
||||
}
|
||||
if !f.Number().IsValid() {
|
||||
return errors.New("message field %q has an invalid number: %d", f.FullName(), f.Number())
|
||||
}
|
||||
if !f.Cardinality().IsValid() {
|
||||
return errors.New("message field %q has an invalid cardinality: %d", f.FullName(), f.Cardinality())
|
||||
}
|
||||
if m.L2.ReservedRanges.Has(f.Number()) {
|
||||
return errors.New("message field %q must not use reserved number %d", f.FullName(), f.Number())
|
||||
}
|
||||
if m.L2.ExtensionRanges.Has(f.Number()) {
|
||||
return errors.New("message field %q with number %d in extension range", f.FullName(), f.Number())
|
||||
}
|
||||
if fd.Extendee != nil {
|
||||
return errors.New("message field %q may not have extendee: %q", f.FullName(), fd.GetExtendee())
|
||||
}
|
||||
if f.L1.IsProto3Optional {
|
||||
if f.Syntax() != protoreflect.Proto3 {
|
||||
return errors.New("message field %q under proto3 optional semantics must be specified in the proto3 syntax", f.FullName())
|
||||
}
|
||||
if f.Cardinality() != protoreflect.Optional {
|
||||
return errors.New("message field %q under proto3 optional semantics must have optional cardinality", f.FullName())
|
||||
}
|
||||
if f.ContainingOneof() != nil && f.ContainingOneof().Fields().Len() != 1 {
|
||||
return errors.New("message field %q under proto3 optional semantics must be within a single element oneof", f.FullName())
|
||||
}
|
||||
}
|
||||
if f.IsWeak() && !flags.ProtoLegacy {
|
||||
return errors.New("message field %q is a weak field, which is a legacy proto1 feature that is no longer supported", f.FullName())
|
||||
}
|
||||
if f.IsWeak() && (f.Syntax() != protoreflect.Proto2 || !isOptionalMessage(f) || f.ContainingOneof() != nil) {
|
||||
return errors.New("message field %q may only be weak for an optional message", f.FullName())
|
||||
}
|
||||
if f.IsPacked() && !isPackable(f) {
|
||||
return errors.New("message field %q is not packable", f.FullName())
|
||||
}
|
||||
if err := checkValidGroup(f); err != nil {
|
||||
return errors.New("message field %q is an invalid group: %v", f.FullName(), err)
|
||||
}
|
||||
if err := checkValidMap(f); err != nil {
|
||||
return errors.New("message field %q is an invalid map: %v", f.FullName(), err)
|
||||
}
|
||||
if f.Syntax() == protoreflect.Proto3 {
|
||||
if f.Cardinality() == protoreflect.Required {
|
||||
return errors.New("message field %q using proto3 semantics cannot be required", f.FullName())
|
||||
}
|
||||
if f.Enum() != nil && !f.Enum().IsPlaceholder() && f.Enum().Syntax() != protoreflect.Proto3 {
|
||||
return errors.New("message field %q using proto3 semantics may only depend on a proto3 enum", f.FullName())
|
||||
}
|
||||
}
|
||||
}
|
||||
seenSynthetic := false // synthetic oneofs for proto3 optional must come after real oneofs
|
||||
for j := range md.GetOneofDecl() {
|
||||
o := &m.L2.Oneofs.List[j]
|
||||
if o.Fields().Len() == 0 {
|
||||
return errors.New("message oneof %q must contain at least one field declaration", o.FullName())
|
||||
}
|
||||
if n := o.Fields().Len(); n-1 != (o.Fields().Get(n-1).Index() - o.Fields().Get(0).Index()) {
|
||||
return errors.New("message oneof %q must have consecutively declared fields", o.FullName())
|
||||
}
|
||||
|
||||
if o.IsSynthetic() {
|
||||
seenSynthetic = true
|
||||
continue
|
||||
}
|
||||
if !o.IsSynthetic() && seenSynthetic {
|
||||
return errors.New("message oneof %q must be declared before synthetic oneofs", o.FullName())
|
||||
}
|
||||
|
||||
for i := 0; i < o.Fields().Len(); i++ {
|
||||
f := o.Fields().Get(i)
|
||||
if f.Cardinality() != protoreflect.Optional {
|
||||
return errors.New("message field %q belongs in a oneof and must be optional", f.FullName())
|
||||
}
|
||||
if f.IsWeak() {
|
||||
return errors.New("message field %q belongs in a oneof and must not be a weak reference", f.FullName())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := validateEnumDeclarations(m.L1.Enums.List, md.GetEnumType()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validateMessageDeclarations(m.L1.Messages.List, md.GetNestedType()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validateExtensionDeclarations(m.L1.Extensions.List, md.GetExtension()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateExtensionDeclarations(xs []filedesc.Extension, xds []*descriptorpb.FieldDescriptorProto) error {
|
||||
for i, xd := range xds {
|
||||
x := &xs[i]
|
||||
// NOTE: Avoid using the IsValid method since extensions to MessageSet
|
||||
// may have a field number higher than normal. This check only verifies
|
||||
// that the number is not negative or reserved. We check again later
|
||||
// if we know that the extendee is definitely not a MessageSet.
|
||||
if n := x.Number(); n < 0 || (protowire.FirstReservedNumber <= n && n <= protowire.LastReservedNumber) {
|
||||
return errors.New("extension field %q has an invalid number: %d", x.FullName(), x.Number())
|
||||
}
|
||||
if !x.Cardinality().IsValid() || x.Cardinality() == protoreflect.Required {
|
||||
return errors.New("extension field %q has an invalid cardinality: %d", x.FullName(), x.Cardinality())
|
||||
}
|
||||
if xd.JsonName != nil {
|
||||
// A bug in older versions of protoc would always populate the
|
||||
// "json_name" option for extensions when it is meaningless.
|
||||
// When it did so, it would always use the camel-cased field name.
|
||||
if xd.GetJsonName() != strs.JSONCamelCase(string(x.Name())) {
|
||||
return errors.New("extension field %q may not have an explicitly set JSON name: %q", x.FullName(), xd.GetJsonName())
|
||||
}
|
||||
}
|
||||
if xd.OneofIndex != nil {
|
||||
return errors.New("extension field %q may not be part of a oneof", x.FullName())
|
||||
}
|
||||
if md := x.ContainingMessage(); !md.IsPlaceholder() {
|
||||
if !md.ExtensionRanges().Has(x.Number()) {
|
||||
return errors.New("extension field %q extends %q with non-extension field number: %d", x.FullName(), md.FullName(), x.Number())
|
||||
}
|
||||
isMessageSet := md.Options().(*descriptorpb.MessageOptions).GetMessageSetWireFormat()
|
||||
if isMessageSet && !isOptionalMessage(x) {
|
||||
return errors.New("extension field %q extends MessageSet and must be an optional message", x.FullName())
|
||||
}
|
||||
if !isMessageSet && !x.Number().IsValid() {
|
||||
return errors.New("extension field %q has an invalid number: %d", x.FullName(), x.Number())
|
||||
}
|
||||
}
|
||||
if xd.GetOptions().GetWeak() {
|
||||
return errors.New("extension field %q cannot be a weak reference", x.FullName())
|
||||
}
|
||||
if x.IsPacked() && !isPackable(x) {
|
||||
return errors.New("extension field %q is not packable", x.FullName())
|
||||
}
|
||||
if err := checkValidGroup(x); err != nil {
|
||||
return errors.New("extension field %q is an invalid group: %v", x.FullName(), err)
|
||||
}
|
||||
if md := x.Message(); md != nil && md.IsMapEntry() {
|
||||
return errors.New("extension field %q cannot be a map entry", x.FullName())
|
||||
}
|
||||
if x.Syntax() == protoreflect.Proto3 {
|
||||
switch x.ContainingMessage().FullName() {
|
||||
case (*descriptorpb.FileOptions)(nil).ProtoReflect().Descriptor().FullName():
|
||||
case (*descriptorpb.EnumOptions)(nil).ProtoReflect().Descriptor().FullName():
|
||||
case (*descriptorpb.EnumValueOptions)(nil).ProtoReflect().Descriptor().FullName():
|
||||
case (*descriptorpb.MessageOptions)(nil).ProtoReflect().Descriptor().FullName():
|
||||
case (*descriptorpb.FieldOptions)(nil).ProtoReflect().Descriptor().FullName():
|
||||
case (*descriptorpb.OneofOptions)(nil).ProtoReflect().Descriptor().FullName():
|
||||
case (*descriptorpb.ExtensionRangeOptions)(nil).ProtoReflect().Descriptor().FullName():
|
||||
case (*descriptorpb.ServiceOptions)(nil).ProtoReflect().Descriptor().FullName():
|
||||
case (*descriptorpb.MethodOptions)(nil).ProtoReflect().Descriptor().FullName():
|
||||
default:
|
||||
return errors.New("extension field %q cannot be declared in proto3 unless extended descriptor options", x.FullName())
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// isOptionalMessage reports whether this is an optional message.
|
||||
// If the kind is unknown, it is assumed to be a message.
|
||||
func isOptionalMessage(fd protoreflect.FieldDescriptor) bool {
|
||||
return (fd.Kind() == 0 || fd.Kind() == protoreflect.MessageKind) && fd.Cardinality() == protoreflect.Optional
|
||||
}
|
||||
|
||||
// isPackable checks whether the pack option can be specified.
|
||||
func isPackable(fd protoreflect.FieldDescriptor) bool {
|
||||
switch fd.Kind() {
|
||||
case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind, protoreflect.GroupKind:
|
||||
return false
|
||||
}
|
||||
return fd.IsList()
|
||||
}
|
||||
|
||||
// checkValidGroup reports whether fd is a valid group according to the same
|
||||
// rules that protoc imposes.
|
||||
func checkValidGroup(fd protoreflect.FieldDescriptor) error {
|
||||
md := fd.Message()
|
||||
switch {
|
||||
case fd.Kind() != protoreflect.GroupKind:
|
||||
return nil
|
||||
case fd.Syntax() != protoreflect.Proto2:
|
||||
return errors.New("invalid under proto2 semantics")
|
||||
case md == nil || md.IsPlaceholder():
|
||||
return errors.New("message must be resolvable")
|
||||
case fd.FullName().Parent() != md.FullName().Parent():
|
||||
return errors.New("message and field must be declared in the same scope")
|
||||
case !unicode.IsUpper(rune(md.Name()[0])):
|
||||
return errors.New("message name must start with an uppercase")
|
||||
case fd.Name() != protoreflect.Name(strings.ToLower(string(md.Name()))):
|
||||
return errors.New("field name must be lowercased form of the message name")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkValidMap checks whether the field is a valid map according to the same
|
||||
// rules that protoc imposes.
|
||||
// See protoc v3.8.0: src/google/protobuf/descriptor.cc:6045-6115
|
||||
func checkValidMap(fd protoreflect.FieldDescriptor) error {
|
||||
md := fd.Message()
|
||||
switch {
|
||||
case md == nil || !md.IsMapEntry():
|
||||
return nil
|
||||
case fd.FullName().Parent() != md.FullName().Parent():
|
||||
return errors.New("message and field must be declared in the same scope")
|
||||
case md.Name() != protoreflect.Name(strs.MapEntryName(string(fd.Name()))):
|
||||
return errors.New("incorrect implicit map entry name")
|
||||
case fd.Cardinality() != protoreflect.Repeated:
|
||||
return errors.New("field must be repeated")
|
||||
case md.Fields().Len() != 2:
|
||||
return errors.New("message must have exactly two fields")
|
||||
case md.ExtensionRanges().Len() > 0:
|
||||
return errors.New("message must not have any extension ranges")
|
||||
case md.Enums().Len()+md.Messages().Len()+md.Extensions().Len() > 0:
|
||||
return errors.New("message must not have any nested declarations")
|
||||
}
|
||||
kf := md.Fields().Get(0)
|
||||
vf := md.Fields().Get(1)
|
||||
switch {
|
||||
case kf.Name() != genid.MapEntry_Key_field_name || kf.Number() != genid.MapEntry_Key_field_number || kf.Cardinality() != protoreflect.Optional || kf.ContainingOneof() != nil || kf.HasDefault():
|
||||
return errors.New("invalid key field")
|
||||
case vf.Name() != genid.MapEntry_Value_field_name || vf.Number() != genid.MapEntry_Value_field_number || vf.Cardinality() != protoreflect.Optional || vf.ContainingOneof() != nil || vf.HasDefault():
|
||||
return errors.New("invalid value field")
|
||||
}
|
||||
switch kf.Kind() {
|
||||
case protoreflect.BoolKind: // bool
|
||||
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: // int32
|
||||
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: // int64
|
||||
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: // uint32
|
||||
case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: // uint64
|
||||
case protoreflect.StringKind: // string
|
||||
default:
|
||||
return errors.New("invalid key kind: %v", kf.Kind())
|
||||
}
|
||||
if e := vf.Enum(); e != nil && e.Values().Len() > 0 && e.Values().Get(0).Number() != 0 {
|
||||
return errors.New("map enum value must have zero number for the first value")
|
||||
}
|
||||
return nil
|
||||
}
|
252
vendor/google.golang.org/protobuf/reflect/protodesc/proto.go
generated
vendored
252
vendor/google.golang.org/protobuf/reflect/protodesc/proto.go
generated
vendored
@ -1,252 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package protodesc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/protobuf/internal/encoding/defval"
|
||||
"google.golang.org/protobuf/internal/strs"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
)
|
||||
|
||||
// ToFileDescriptorProto copies a protoreflect.FileDescriptor into a
|
||||
// google.protobuf.FileDescriptorProto message.
|
||||
func ToFileDescriptorProto(file protoreflect.FileDescriptor) *descriptorpb.FileDescriptorProto {
|
||||
p := &descriptorpb.FileDescriptorProto{
|
||||
Name: proto.String(file.Path()),
|
||||
Options: proto.Clone(file.Options()).(*descriptorpb.FileOptions),
|
||||
}
|
||||
if file.Package() != "" {
|
||||
p.Package = proto.String(string(file.Package()))
|
||||
}
|
||||
for i, imports := 0, file.Imports(); i < imports.Len(); i++ {
|
||||
imp := imports.Get(i)
|
||||
p.Dependency = append(p.Dependency, imp.Path())
|
||||
if imp.IsPublic {
|
||||
p.PublicDependency = append(p.PublicDependency, int32(i))
|
||||
}
|
||||
if imp.IsWeak {
|
||||
p.WeakDependency = append(p.WeakDependency, int32(i))
|
||||
}
|
||||
}
|
||||
for i, locs := 0, file.SourceLocations(); i < locs.Len(); i++ {
|
||||
loc := locs.Get(i)
|
||||
l := &descriptorpb.SourceCodeInfo_Location{}
|
||||
l.Path = append(l.Path, loc.Path...)
|
||||
if loc.StartLine == loc.EndLine {
|
||||
l.Span = []int32{int32(loc.StartLine), int32(loc.StartColumn), int32(loc.EndColumn)}
|
||||
} else {
|
||||
l.Span = []int32{int32(loc.StartLine), int32(loc.StartColumn), int32(loc.EndLine), int32(loc.EndColumn)}
|
||||
}
|
||||
l.LeadingDetachedComments = append([]string(nil), loc.LeadingDetachedComments...)
|
||||
if loc.LeadingComments != "" {
|
||||
l.LeadingComments = proto.String(loc.LeadingComments)
|
||||
}
|
||||
if loc.TrailingComments != "" {
|
||||
l.TrailingComments = proto.String(loc.TrailingComments)
|
||||
}
|
||||
if p.SourceCodeInfo == nil {
|
||||
p.SourceCodeInfo = &descriptorpb.SourceCodeInfo{}
|
||||
}
|
||||
p.SourceCodeInfo.Location = append(p.SourceCodeInfo.Location, l)
|
||||
|
||||
}
|
||||
for i, messages := 0, file.Messages(); i < messages.Len(); i++ {
|
||||
p.MessageType = append(p.MessageType, ToDescriptorProto(messages.Get(i)))
|
||||
}
|
||||
for i, enums := 0, file.Enums(); i < enums.Len(); i++ {
|
||||
p.EnumType = append(p.EnumType, ToEnumDescriptorProto(enums.Get(i)))
|
||||
}
|
||||
for i, services := 0, file.Services(); i < services.Len(); i++ {
|
||||
p.Service = append(p.Service, ToServiceDescriptorProto(services.Get(i)))
|
||||
}
|
||||
for i, exts := 0, file.Extensions(); i < exts.Len(); i++ {
|
||||
p.Extension = append(p.Extension, ToFieldDescriptorProto(exts.Get(i)))
|
||||
}
|
||||
if syntax := file.Syntax(); syntax != protoreflect.Proto2 {
|
||||
p.Syntax = proto.String(file.Syntax().String())
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// ToDescriptorProto copies a protoreflect.MessageDescriptor into a
|
||||
// google.protobuf.DescriptorProto message.
|
||||
func ToDescriptorProto(message protoreflect.MessageDescriptor) *descriptorpb.DescriptorProto {
|
||||
p := &descriptorpb.DescriptorProto{
|
||||
Name: proto.String(string(message.Name())),
|
||||
Options: proto.Clone(message.Options()).(*descriptorpb.MessageOptions),
|
||||
}
|
||||
for i, fields := 0, message.Fields(); i < fields.Len(); i++ {
|
||||
p.Field = append(p.Field, ToFieldDescriptorProto(fields.Get(i)))
|
||||
}
|
||||
for i, exts := 0, message.Extensions(); i < exts.Len(); i++ {
|
||||
p.Extension = append(p.Extension, ToFieldDescriptorProto(exts.Get(i)))
|
||||
}
|
||||
for i, messages := 0, message.Messages(); i < messages.Len(); i++ {
|
||||
p.NestedType = append(p.NestedType, ToDescriptorProto(messages.Get(i)))
|
||||
}
|
||||
for i, enums := 0, message.Enums(); i < enums.Len(); i++ {
|
||||
p.EnumType = append(p.EnumType, ToEnumDescriptorProto(enums.Get(i)))
|
||||
}
|
||||
for i, xranges := 0, message.ExtensionRanges(); i < xranges.Len(); i++ {
|
||||
xrange := xranges.Get(i)
|
||||
p.ExtensionRange = append(p.ExtensionRange, &descriptorpb.DescriptorProto_ExtensionRange{
|
||||
Start: proto.Int32(int32(xrange[0])),
|
||||
End: proto.Int32(int32(xrange[1])),
|
||||
Options: proto.Clone(message.ExtensionRangeOptions(i)).(*descriptorpb.ExtensionRangeOptions),
|
||||
})
|
||||
}
|
||||
for i, oneofs := 0, message.Oneofs(); i < oneofs.Len(); i++ {
|
||||
p.OneofDecl = append(p.OneofDecl, ToOneofDescriptorProto(oneofs.Get(i)))
|
||||
}
|
||||
for i, ranges := 0, message.ReservedRanges(); i < ranges.Len(); i++ {
|
||||
rrange := ranges.Get(i)
|
||||
p.ReservedRange = append(p.ReservedRange, &descriptorpb.DescriptorProto_ReservedRange{
|
||||
Start: proto.Int32(int32(rrange[0])),
|
||||
End: proto.Int32(int32(rrange[1])),
|
||||
})
|
||||
}
|
||||
for i, names := 0, message.ReservedNames(); i < names.Len(); i++ {
|
||||
p.ReservedName = append(p.ReservedName, string(names.Get(i)))
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// ToFieldDescriptorProto copies a protoreflect.FieldDescriptor into a
|
||||
// google.protobuf.FieldDescriptorProto message.
|
||||
func ToFieldDescriptorProto(field protoreflect.FieldDescriptor) *descriptorpb.FieldDescriptorProto {
|
||||
p := &descriptorpb.FieldDescriptorProto{
|
||||
Name: proto.String(string(field.Name())),
|
||||
Number: proto.Int32(int32(field.Number())),
|
||||
Label: descriptorpb.FieldDescriptorProto_Label(field.Cardinality()).Enum(),
|
||||
Options: proto.Clone(field.Options()).(*descriptorpb.FieldOptions),
|
||||
}
|
||||
if field.IsExtension() {
|
||||
p.Extendee = fullNameOf(field.ContainingMessage())
|
||||
}
|
||||
if field.Kind().IsValid() {
|
||||
p.Type = descriptorpb.FieldDescriptorProto_Type(field.Kind()).Enum()
|
||||
}
|
||||
if field.Enum() != nil {
|
||||
p.TypeName = fullNameOf(field.Enum())
|
||||
}
|
||||
if field.Message() != nil {
|
||||
p.TypeName = fullNameOf(field.Message())
|
||||
}
|
||||
if field.HasJSONName() {
|
||||
// A bug in older versions of protoc would always populate the
|
||||
// "json_name" option for extensions when it is meaningless.
|
||||
// When it did so, it would always use the camel-cased field name.
|
||||
if field.IsExtension() {
|
||||
p.JsonName = proto.String(strs.JSONCamelCase(string(field.Name())))
|
||||
} else {
|
||||
p.JsonName = proto.String(field.JSONName())
|
||||
}
|
||||
}
|
||||
if field.Syntax() == protoreflect.Proto3 && field.HasOptionalKeyword() {
|
||||
p.Proto3Optional = proto.Bool(true)
|
||||
}
|
||||
if field.HasDefault() {
|
||||
def, err := defval.Marshal(field.Default(), field.DefaultEnumValue(), field.Kind(), defval.Descriptor)
|
||||
if err != nil && field.DefaultEnumValue() != nil {
|
||||
def = string(field.DefaultEnumValue().Name()) // occurs for unresolved enum values
|
||||
} else if err != nil {
|
||||
panic(fmt.Sprintf("%v: %v", field.FullName(), err))
|
||||
}
|
||||
p.DefaultValue = proto.String(def)
|
||||
}
|
||||
if oneof := field.ContainingOneof(); oneof != nil {
|
||||
p.OneofIndex = proto.Int32(int32(oneof.Index()))
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// ToOneofDescriptorProto copies a protoreflect.OneofDescriptor into a
|
||||
// google.protobuf.OneofDescriptorProto message.
|
||||
func ToOneofDescriptorProto(oneof protoreflect.OneofDescriptor) *descriptorpb.OneofDescriptorProto {
|
||||
return &descriptorpb.OneofDescriptorProto{
|
||||
Name: proto.String(string(oneof.Name())),
|
||||
Options: proto.Clone(oneof.Options()).(*descriptorpb.OneofOptions),
|
||||
}
|
||||
}
|
||||
|
||||
// ToEnumDescriptorProto copies a protoreflect.EnumDescriptor into a
|
||||
// google.protobuf.EnumDescriptorProto message.
|
||||
func ToEnumDescriptorProto(enum protoreflect.EnumDescriptor) *descriptorpb.EnumDescriptorProto {
|
||||
p := &descriptorpb.EnumDescriptorProto{
|
||||
Name: proto.String(string(enum.Name())),
|
||||
Options: proto.Clone(enum.Options()).(*descriptorpb.EnumOptions),
|
||||
}
|
||||
for i, values := 0, enum.Values(); i < values.Len(); i++ {
|
||||
p.Value = append(p.Value, ToEnumValueDescriptorProto(values.Get(i)))
|
||||
}
|
||||
for i, ranges := 0, enum.ReservedRanges(); i < ranges.Len(); i++ {
|
||||
rrange := ranges.Get(i)
|
||||
p.ReservedRange = append(p.ReservedRange, &descriptorpb.EnumDescriptorProto_EnumReservedRange{
|
||||
Start: proto.Int32(int32(rrange[0])),
|
||||
End: proto.Int32(int32(rrange[1])),
|
||||
})
|
||||
}
|
||||
for i, names := 0, enum.ReservedNames(); i < names.Len(); i++ {
|
||||
p.ReservedName = append(p.ReservedName, string(names.Get(i)))
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// ToEnumValueDescriptorProto copies a protoreflect.EnumValueDescriptor into a
|
||||
// google.protobuf.EnumValueDescriptorProto message.
|
||||
func ToEnumValueDescriptorProto(value protoreflect.EnumValueDescriptor) *descriptorpb.EnumValueDescriptorProto {
|
||||
return &descriptorpb.EnumValueDescriptorProto{
|
||||
Name: proto.String(string(value.Name())),
|
||||
Number: proto.Int32(int32(value.Number())),
|
||||
Options: proto.Clone(value.Options()).(*descriptorpb.EnumValueOptions),
|
||||
}
|
||||
}
|
||||
|
||||
// ToServiceDescriptorProto copies a protoreflect.ServiceDescriptor into a
|
||||
// google.protobuf.ServiceDescriptorProto message.
|
||||
func ToServiceDescriptorProto(service protoreflect.ServiceDescriptor) *descriptorpb.ServiceDescriptorProto {
|
||||
p := &descriptorpb.ServiceDescriptorProto{
|
||||
Name: proto.String(string(service.Name())),
|
||||
Options: proto.Clone(service.Options()).(*descriptorpb.ServiceOptions),
|
||||
}
|
||||
for i, methods := 0, service.Methods(); i < methods.Len(); i++ {
|
||||
p.Method = append(p.Method, ToMethodDescriptorProto(methods.Get(i)))
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// ToMethodDescriptorProto copies a protoreflect.MethodDescriptor into a
|
||||
// google.protobuf.MethodDescriptorProto message.
|
||||
func ToMethodDescriptorProto(method protoreflect.MethodDescriptor) *descriptorpb.MethodDescriptorProto {
|
||||
p := &descriptorpb.MethodDescriptorProto{
|
||||
Name: proto.String(string(method.Name())),
|
||||
InputType: fullNameOf(method.Input()),
|
||||
OutputType: fullNameOf(method.Output()),
|
||||
Options: proto.Clone(method.Options()).(*descriptorpb.MethodOptions),
|
||||
}
|
||||
if method.IsStreamingClient() {
|
||||
p.ClientStreaming = proto.Bool(true)
|
||||
}
|
||||
if method.IsStreamingServer() {
|
||||
p.ServerStreaming = proto.Bool(true)
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func fullNameOf(d protoreflect.Descriptor) *string {
|
||||
if d == nil {
|
||||
return nil
|
||||
}
|
||||
if strings.HasPrefix(string(d.FullName()), unknownPrefix) {
|
||||
return proto.String(string(d.FullName()[len(unknownPrefix):]))
|
||||
}
|
||||
return proto.String("." + string(d.FullName()))
|
||||
}
|
43
vendor/google.golang.org/protobuf/reflect/protoregistry/registry.go
generated
vendored
43
vendor/google.golang.org/protobuf/reflect/protoregistry/registry.go
generated
vendored
@ -94,7 +94,8 @@ type Files struct {
|
||||
// Note that enum values are in the top-level since that are in the same
|
||||
// scope as the parent enum.
|
||||
descsByName map[protoreflect.FullName]interface{}
|
||||
filesByPath map[string]protoreflect.FileDescriptor
|
||||
filesByPath map[string][]protoreflect.FileDescriptor
|
||||
numFiles int
|
||||
}
|
||||
|
||||
type packageDescriptor struct {
|
||||
@ -117,17 +118,16 @@ func (r *Files) RegisterFile(file protoreflect.FileDescriptor) error {
|
||||
r.descsByName = map[protoreflect.FullName]interface{}{
|
||||
"": &packageDescriptor{},
|
||||
}
|
||||
r.filesByPath = make(map[string]protoreflect.FileDescriptor)
|
||||
r.filesByPath = make(map[string][]protoreflect.FileDescriptor)
|
||||
}
|
||||
path := file.Path()
|
||||
if prev := r.filesByPath[path]; prev != nil {
|
||||
if prev := r.filesByPath[path]; len(prev) > 0 {
|
||||
r.checkGenProtoConflict(path)
|
||||
err := errors.New("file %q is already registered", file.Path())
|
||||
err = amendErrorWithCaller(err, prev, file)
|
||||
if r == GlobalFiles && ignoreConflict(file, err) {
|
||||
err = nil
|
||||
err = amendErrorWithCaller(err, prev[0], file)
|
||||
if !(r == GlobalFiles && ignoreConflict(file, err)) {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
for name := file.Package(); name != ""; name = name.Parent() {
|
||||
@ -168,7 +168,8 @@ func (r *Files) RegisterFile(file protoreflect.FileDescriptor) error {
|
||||
rangeTopLevelDescriptors(file, func(d protoreflect.Descriptor) {
|
||||
r.descsByName[d.FullName()] = d
|
||||
})
|
||||
r.filesByPath[path] = file
|
||||
r.filesByPath[path] = append(r.filesByPath[path], file)
|
||||
r.numFiles++
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -308,6 +309,7 @@ func (s *nameSuffix) Pop() (name protoreflect.Name) {
|
||||
// FindFileByPath looks up a file by the path.
|
||||
//
|
||||
// This returns (nil, NotFound) if not found.
|
||||
// This returns an error if multiple files have the same path.
|
||||
func (r *Files) FindFileByPath(path string) (protoreflect.FileDescriptor, error) {
|
||||
if r == nil {
|
||||
return nil, NotFound
|
||||
@ -316,13 +318,19 @@ func (r *Files) FindFileByPath(path string) (protoreflect.FileDescriptor, error)
|
||||
globalMutex.RLock()
|
||||
defer globalMutex.RUnlock()
|
||||
}
|
||||
if fd, ok := r.filesByPath[path]; ok {
|
||||
return fd, nil
|
||||
fds := r.filesByPath[path]
|
||||
switch len(fds) {
|
||||
case 0:
|
||||
return nil, NotFound
|
||||
case 1:
|
||||
return fds[0], nil
|
||||
default:
|
||||
return nil, errors.New("multiple files named %q", path)
|
||||
}
|
||||
return nil, NotFound
|
||||
}
|
||||
|
||||
// NumFiles reports the number of registered files.
|
||||
// NumFiles reports the number of registered files,
|
||||
// including duplicate files with the same name.
|
||||
func (r *Files) NumFiles() int {
|
||||
if r == nil {
|
||||
return 0
|
||||
@ -331,10 +339,11 @@ func (r *Files) NumFiles() int {
|
||||
globalMutex.RLock()
|
||||
defer globalMutex.RUnlock()
|
||||
}
|
||||
return len(r.filesByPath)
|
||||
return r.numFiles
|
||||
}
|
||||
|
||||
// RangeFiles iterates over all registered files while f returns true.
|
||||
// If multiple files have the same name, RangeFiles iterates over all of them.
|
||||
// The iteration order is undefined.
|
||||
func (r *Files) RangeFiles(f func(protoreflect.FileDescriptor) bool) {
|
||||
if r == nil {
|
||||
@ -344,9 +353,11 @@ func (r *Files) RangeFiles(f func(protoreflect.FileDescriptor) bool) {
|
||||
globalMutex.RLock()
|
||||
defer globalMutex.RUnlock()
|
||||
}
|
||||
for _, file := range r.filesByPath {
|
||||
if !f(file) {
|
||||
return
|
||||
for _, files := range r.filesByPath {
|
||||
for _, file := range files {
|
||||
if !f(file) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
4039
vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go
generated
vendored
4039
vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
17
vendor/modules.txt
vendored
17
vendor/modules.txt
vendored
@ -1,9 +1,9 @@
|
||||
# github.com/cyrilix/robocar-base v0.1.5
|
||||
# github.com/cyrilix/robocar-base v0.1.6
|
||||
## explicit; go 1.17
|
||||
github.com/cyrilix/robocar-base/cli
|
||||
github.com/cyrilix/robocar-base/service
|
||||
github.com/cyrilix/robocar-base/testtools
|
||||
# github.com/cyrilix/robocar-protobuf/go v1.0.3
|
||||
# github.com/cyrilix/robocar-protobuf/go v1.0.4
|
||||
## explicit; go 1.17
|
||||
github.com/cyrilix/robocar-protobuf/go/events
|
||||
# github.com/eclipse/paho.mqtt.golang v1.3.5
|
||||
@ -12,7 +12,6 @@ github.com/eclipse/paho.mqtt.golang
|
||||
github.com/eclipse/paho.mqtt.golang/packets
|
||||
# github.com/golang/protobuf v1.5.2
|
||||
## explicit; go 1.9
|
||||
github.com/golang/protobuf/proto
|
||||
github.com/golang/protobuf/ptypes/timestamp
|
||||
# github.com/gorilla/websocket v1.4.2
|
||||
## explicit; go 1.12
|
||||
@ -35,7 +34,7 @@ go.uber.org/zap/zapcore
|
||||
## explicit; go 1.11
|
||||
golang.org/x/net/internal/socks
|
||||
golang.org/x/net/proxy
|
||||
# google.golang.org/protobuf v1.26.0
|
||||
# google.golang.org/protobuf v1.27.1
|
||||
## explicit; go 1.9
|
||||
google.golang.org/protobuf/encoding/prototext
|
||||
google.golang.org/protobuf/encoding/protowire
|
||||
@ -58,14 +57,12 @@ google.golang.org/protobuf/internal/set
|
||||
google.golang.org/protobuf/internal/strs
|
||||
google.golang.org/protobuf/internal/version
|
||||
google.golang.org/protobuf/proto
|
||||
google.golang.org/protobuf/reflect/protodesc
|
||||
google.golang.org/protobuf/reflect/protoreflect
|
||||
google.golang.org/protobuf/reflect/protoregistry
|
||||
google.golang.org/protobuf/runtime/protoiface
|
||||
google.golang.org/protobuf/runtime/protoimpl
|
||||
google.golang.org/protobuf/types/descriptorpb
|
||||
google.golang.org/protobuf/types/known/timestamppb
|
||||
# periph.io/x/conn/v3 v3.6.8
|
||||
# periph.io/x/conn/v3 v3.6.10
|
||||
## explicit; go 1.13
|
||||
periph.io/x/conn/v3
|
||||
periph.io/x/conn/v3/driver
|
||||
@ -80,10 +77,7 @@ periph.io/x/conn/v3/pin
|
||||
periph.io/x/conn/v3/pin/pinreg
|
||||
periph.io/x/conn/v3/spi
|
||||
periph.io/x/conn/v3/spi/spireg
|
||||
# periph.io/x/d2xx v0.0.3
|
||||
## explicit; go 1.13
|
||||
periph.io/x/d2xx
|
||||
# periph.io/x/host/v3 v3.7.0
|
||||
# periph.io/x/host/v3 v3.7.2
|
||||
## explicit; go 1.13
|
||||
periph.io/x/host/v3
|
||||
periph.io/x/host/v3/allwinner
|
||||
@ -96,7 +90,6 @@ periph.io/x/host/v3/chip
|
||||
periph.io/x/host/v3/cpu
|
||||
periph.io/x/host/v3/distro
|
||||
periph.io/x/host/v3/fs
|
||||
periph.io/x/host/v3/ftdi
|
||||
periph.io/x/host/v3/odroidc1
|
||||
periph.io/x/host/v3/pine64
|
||||
periph.io/x/host/v3/pmem
|
||||
|
380
vendor/periph.io/x/conn/v3/.gohci.yml
generated
vendored
380
vendor/periph.io/x/conn/v3/.gohci.yml
generated
vendored
@ -17,62 +17,87 @@ workers:
|
||||
- -benchtime=1000ms
|
||||
- -benchmem
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: host
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/host
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../host
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../host
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: devices
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/devices
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../devices
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../devices
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: cmd
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../cmd
|
||||
# Test commands.
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- install
|
||||
- -v
|
||||
@ -81,7 +106,6 @@ workers:
|
||||
- ./periph-info
|
||||
- ./periph-smoketest
|
||||
- ./spi-list
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- periph-info
|
||||
- cmd:
|
||||
@ -111,62 +135,87 @@ workers:
|
||||
- -benchtime=1000ms
|
||||
- -benchmem
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: host
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/host
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../host
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../host
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: devices
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/devices
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../devices
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../devices
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: cmd
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../cmd
|
||||
# Test commands.
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- install
|
||||
- -v
|
||||
@ -176,7 +225,6 @@ workers:
|
||||
- ./periph-info
|
||||
- ./periph-smoketest
|
||||
- ./spi-list
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- periph-info
|
||||
- cmd:
|
||||
@ -219,62 +267,87 @@ workers:
|
||||
- -benchtime=1000ms
|
||||
- -benchmem
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: host
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/host
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../host
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../host
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: devices
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/devices
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../devices
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../devices
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: cmd
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../cmd
|
||||
# Test commands.
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- install
|
||||
- -v
|
||||
@ -284,7 +357,6 @@ workers:
|
||||
- ./periph-info
|
||||
- ./periph-smoketest
|
||||
- ./spi-list
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- periph-info
|
||||
- cmd:
|
||||
@ -343,62 +415,87 @@ workers:
|
||||
- -benchtime=1000ms
|
||||
- -benchmem
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: host
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/host
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../host
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../host
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: devices
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/devices
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../devices
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../devices
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: cmd
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../cmd
|
||||
# Test commands.
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- install
|
||||
- -v
|
||||
@ -408,7 +505,6 @@ workers:
|
||||
- ./periph-info
|
||||
- ./periph-smoketest
|
||||
- ./spi-list
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- periph-info
|
||||
- cmd:
|
||||
@ -433,62 +529,87 @@ workers:
|
||||
- -benchtime=1000ms
|
||||
- -benchmem
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: host
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/host
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../host
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../host
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: devices
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/devices
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../devices
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../devices
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: cmd
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../cmd
|
||||
# Test commands.
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- install
|
||||
- -v
|
||||
@ -498,7 +619,6 @@ workers:
|
||||
- ./periph-info
|
||||
- ./periph-smoketest
|
||||
- ./spi-list
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- periph-info
|
||||
- cmd:
|
||||
|
3
vendor/periph.io/x/conn/v3/README.md
generated
vendored
3
vendor/periph.io/x/conn/v3/README.md
generated
vendored
@ -9,8 +9,7 @@ get an [invite here](https://invite.slack.golangbridge.org/).
|
||||
[](https://periph.io/)
|
||||
|
||||
[](https://pkg.go.dev/periph.io/x/conn/v3)
|
||||
[](https://codecov.io/gh/periph/conn)
|
||||
[](https://codecov.io/gh/periph/conn)
|
||||
|
||||
|
||||
## Example
|
||||
|
18
vendor/periph.io/x/conn/v3/driver/driverreg/driverreg_parallel.go
generated
vendored
18
vendor/periph.io/x/conn/v3/driver/driverreg/driverreg_parallel.go
generated
vendored
@ -5,6 +5,7 @@
|
||||
// This file contains the parallelized driver loading logic. It is meant to be
|
||||
// load the drivers as fast as possible by parallelising work.
|
||||
|
||||
//go:build !tinygo
|
||||
// +build !tinygo
|
||||
|
||||
package driverreg
|
||||
@ -50,9 +51,11 @@ func initImpl() (*State, error) {
|
||||
if err != nil {
|
||||
return state, err
|
||||
}
|
||||
loaded := make(map[string]struct{}, len(byName))
|
||||
loaded := sync.Map{}
|
||||
for _, s := range stages {
|
||||
s.loadParallel(loaded, cD, cS, cE)
|
||||
// It's very important that each of the stage is fully completed before the
|
||||
// next one is attempted.
|
||||
s.loadParallel(&loaded, cD, cS, cE)
|
||||
}
|
||||
close(cD)
|
||||
close(cS)
|
||||
@ -61,10 +64,9 @@ func initImpl() (*State, error) {
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// loadParallel loads all the drivers for this stage in parallel.
|
||||
//
|
||||
// Updates loaded in a safe way.
|
||||
func (s *stage) loadParallel(loaded map[string]struct{}, cD chan<- driver.Impl, cS, cE chan<- DriverFailure) {
|
||||
// loadParallel loads all the drivers for this stage in parallel and returns
|
||||
// once they are all loaded.
|
||||
func (s *stage) loadParallel(loaded *sync.Map, cD chan<- driver.Impl, cS, cE chan<- DriverFailure) {
|
||||
success := make(chan string)
|
||||
go func() {
|
||||
defer close(success)
|
||||
@ -73,7 +75,7 @@ func (s *stage) loadParallel(loaded map[string]struct{}, cD chan<- driver.Impl,
|
||||
for name, drv := range s.drvs {
|
||||
// Intentionally do not look at After(), only Prerequisites().
|
||||
for _, dep := range drv.Prerequisites() {
|
||||
if _, ok := loaded[dep]; !ok {
|
||||
if _, ok := loaded.Load(dep); !ok {
|
||||
cS <- DriverFailure{drv, errors.New("dependency not loaded: " + strconv.Quote(dep))}
|
||||
continue loop
|
||||
}
|
||||
@ -98,6 +100,6 @@ func (s *stage) loadParallel(loaded map[string]struct{}, cD chan<- driver.Impl,
|
||||
wg.Wait()
|
||||
}()
|
||||
for s := range success {
|
||||
loaded[s] = struct{}{}
|
||||
loaded.Store(s, nil)
|
||||
}
|
||||
}
|
||||
|
1
vendor/periph.io/x/conn/v3/driver/driverreg/driverreg_serial.go
generated
vendored
1
vendor/periph.io/x/conn/v3/driver/driverreg/driverreg_serial.go
generated
vendored
@ -5,6 +5,7 @@
|
||||
// This file contains the single threaded driver loading code, to be used on
|
||||
// low performance cores.
|
||||
|
||||
//go:build tinygo
|
||||
// +build tinygo
|
||||
|
||||
package driverreg
|
||||
|
48
vendor/periph.io/x/d2xx/.gohci.yml
generated
vendored
48
vendor/periph.io/x/d2xx/.gohci.yml
generated
vendored
@ -1,48 +0,0 @@
|
||||
# Copyright 2021 The Periph Authors. All rights reserved.
|
||||
# Use of this source code is governed under the Apache License, Version 2.0
|
||||
# that can be found in the LICENSE file.
|
||||
|
||||
# See https://github.com/periph/gohci
|
||||
version: 1
|
||||
workers:
|
||||
- checks:
|
||||
- cmd:
|
||||
- go
|
||||
- test
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/host
|
||||
dir: ..
|
||||
- cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/d2xx@${GIT_SHA}
|
||||
dir: ../host
|
||||
- cmd:
|
||||
- go
|
||||
- test
|
||||
- ./...
|
||||
dir: ../host
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/d2xx@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- go
|
||||
- test
|
||||
- ./...
|
||||
dir: ../cmd
|
202
vendor/periph.io/x/d2xx/LICENSE
generated
vendored
202
vendor/periph.io/x/d2xx/LICENSE
generated
vendored
@ -1,202 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
44
vendor/periph.io/x/d2xx/README.md
generated
vendored
44
vendor/periph.io/x/d2xx/README.md
generated
vendored
@ -1,44 +0,0 @@
|
||||
# d2xx
|
||||
|
||||
Package d2xx is a thin Go wrapper for the Future Technology "D2XX" driver at
|
||||
https://ftdichip.com/drivers/d2xx-drivers/.
|
||||
|
||||
This package is not Go idiomatic. You will want to use
|
||||
https://periph.io/x/host/v3/ftdi (or later) instead.
|
||||
|
||||
But if you really want, here it goes:
|
||||
[](https://pkg.go.dev/periph.io/x/d2xx)
|
||||
|
||||
This Go package includes third party software. See
|
||||
[third_party/README.md](third_party/README.md).
|
||||
|
||||
## Configuration
|
||||
|
||||
See https://periph.io/device/ftdi/ to configure the host to be able to use this
|
||||
driver.
|
||||
|
||||
## Availability
|
||||
|
||||
On darwin_amd64, linux_amd64 linux_arm (v6, v7 compatible) and linux_arm64 (v8),
|
||||
cgo is required. If cgo is disabled (via `CGO_ENABLED=0`), all functions in this
|
||||
driver return error [NoCGO](https://periph.io/x/d2xx#NoCGO).
|
||||
|
||||
On Windows, cgo is not required. If the dynamic library is not found at runtime,
|
||||
[Missing](https://periph.io/x/d2xx#Missing) is returned.
|
||||
|
||||
## bcm2385
|
||||
|
||||
On linux_arm (v6), hard-float is required. For cross compilation, this
|
||||
means arm-linux-gnueabihf-gcc is preferred to arm-linux-gnueabi-gcc. Using
|
||||
hardfloat causes a segfault on Raspberry Pi 1, Zero and Zero Wireless. It is
|
||||
recommended to disable this driver if targeting these hosts, see below.
|
||||
|
||||
## Disabling
|
||||
|
||||
To disable this driver, build with tag `no_d2xx`, e.g.
|
||||
|
||||
```
|
||||
go install -tags no_d2xx periph.io/x/cmd/gpio-list@latest
|
||||
```
|
||||
|
||||
This will behave has if cgo was disabled, even on Windows.
|
145
vendor/periph.io/x/d2xx/d2xx.go
generated
vendored
145
vendor/periph.io/x/d2xx/d2xx.go
generated
vendored
@ -1,145 +0,0 @@
|
||||
// Copyright 2021 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
package d2xx
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Err is the error type returned by d2xx functions.
|
||||
type Err int
|
||||
|
||||
// These are additional synthetic error codes.
|
||||
const (
|
||||
// NoCGO is returned when the package was compiled without cgo, thus the d2xx
|
||||
// library is unavailable or the library was disabled via the `no_d2xx` build
|
||||
// tag.
|
||||
NoCGO Err = -2
|
||||
// Missing is returned when the dynamic library is not available.
|
||||
Missing Err = -1
|
||||
)
|
||||
|
||||
// String converts a error integer to a string representation of the error.
|
||||
func (e Err) String() string {
|
||||
switch e {
|
||||
case Missing:
|
||||
// when the library d2xx couldn't be loaded at runtime.
|
||||
return "couldn't load driver; visit https://periph.io/device/ftdi/ for help"
|
||||
case NoCGO:
|
||||
return "can't be used without cgo"
|
||||
case 0: // FT_OK
|
||||
return ""
|
||||
case 1: // FT_INVALID_HANDLE
|
||||
return "invalid handle"
|
||||
case 2: // FT_DEVICE_NOT_FOUND
|
||||
return "device not found; see https://periph.io/device/ftdi/ for help"
|
||||
case 3: // FT_DEVICE_NOT_OPENED
|
||||
return "device busy; see https://periph.io/device/ftdi/ for help"
|
||||
case 4: // FT_IO_ERROR
|
||||
return "I/O error"
|
||||
case 5: // FT_INSUFFICIENT_RESOURCES
|
||||
return "insufficient resources"
|
||||
case 6: // FT_INVALID_PARAMETER
|
||||
return "invalid parameter"
|
||||
case 7: // FT_INVALID_BAUD_RATE
|
||||
return "invalid baud rate"
|
||||
case 8: // FT_DEVICE_NOT_OPENED_FOR_ERASE
|
||||
return "device not opened for erase"
|
||||
case 9: // FT_DEVICE_NOT_OPENED_FOR_WRITE
|
||||
return "device not opened for write"
|
||||
case 10: // FT_FAILED_TO_WRITE_DEVICE
|
||||
return "failed to write device"
|
||||
case 11: // FT_EEPROM_READ_FAILED
|
||||
return "eeprom read failed"
|
||||
case 12: // FT_EEPROM_WRITE_FAILED
|
||||
return "eeprom write failed"
|
||||
case 13: // FT_EEPROM_ERASE_FAILED
|
||||
return "eeprom erase failed"
|
||||
case 14: // FT_EEPROM_NOT_PRESENT
|
||||
return "eeprom not present"
|
||||
case 15: // FT_EEPROM_NOT_PROGRAMMED
|
||||
return "eeprom not programmed"
|
||||
case 16: // FT_INVALID_ARGS
|
||||
return "invalid argument"
|
||||
case 17: // FT_NOT_SUPPORTED
|
||||
return "not supported"
|
||||
case 18: // FT_OTHER_ERROR
|
||||
return "other error"
|
||||
case 19: // FT_DEVICE_LIST_NOT_READY
|
||||
return "device list not ready"
|
||||
default:
|
||||
return "unknown status " + strconv.Itoa(int(e))
|
||||
}
|
||||
}
|
||||
|
||||
// unknown is a forward declaration of ftdi.DevType.
|
||||
const unknown = 3
|
||||
|
||||
// handle is a d2xx handle.
|
||||
//
|
||||
// This is the base type which each OS specific implementation adds methods to.
|
||||
type handle uintptr
|
||||
|
||||
// Handle is d2xx device handle.
|
||||
type Handle interface {
|
||||
Close() Err
|
||||
// ResetDevice takes >1.2ms
|
||||
ResetDevice() Err
|
||||
GetDeviceInfo() (uint32, uint16, uint16, Err)
|
||||
EEPROMRead(devType uint32, e *EEPROM) Err
|
||||
EEPROMProgram(e *EEPROM) Err
|
||||
EraseEE() Err
|
||||
WriteEE(offset uint8, value uint16) Err
|
||||
EEUASize() (int, Err)
|
||||
EEUARead(ua []byte) Err
|
||||
EEUAWrite(ua []byte) Err
|
||||
SetChars(eventChar byte, eventEn bool, errorChar byte, errorEn bool) Err
|
||||
SetUSBParameters(in, out int) Err
|
||||
SetFlowControl() Err
|
||||
SetTimeouts(readMS, writeMS int) Err
|
||||
SetLatencyTimer(delayMS uint8) Err
|
||||
SetBaudRate(hz uint32) Err
|
||||
// GetQueueStatus takes >60µs
|
||||
GetQueueStatus() (uint32, Err)
|
||||
// Read takes <5µs if GetQueueStatus was called just before,
|
||||
// 300µs~800µs otherwise (!)
|
||||
Read(b []byte) (int, Err)
|
||||
// Write takes >0.1ms
|
||||
Write(b []byte) (int, Err)
|
||||
GetBitMode() (byte, Err)
|
||||
// SetBitMode takes >0.1ms
|
||||
SetBitMode(mask, mode byte) Err
|
||||
}
|
||||
|
||||
var _ Handle = handle(0)
|
||||
|
||||
// Version returns the library's version.
|
||||
//
|
||||
// 0, 0, 0 is returned if the library is unavailable.
|
||||
func Version() (uint8, uint8, uint8) {
|
||||
return version()
|
||||
}
|
||||
|
||||
// CreateDeviceInfoList discovers the currently found devices.
|
||||
//
|
||||
// If the driver is disabled via build tag `no_d2xx`, or on posix
|
||||
// `CGO_ENABLED=0` environment variable, NoCGO is returned.
|
||||
//
|
||||
// On Windows, Missing is returned if the dynamic library is not found at
|
||||
// runtime.
|
||||
func CreateDeviceInfoList() (int, Err) {
|
||||
return createDeviceInfoList()
|
||||
}
|
||||
|
||||
// Open opens the ith device discovered.
|
||||
//
|
||||
// If the driver is disabled via build tag `no_d2xx`, or on posix
|
||||
// `CGO_ENABLED=0` environment variable, NoCGO is returned.
|
||||
//
|
||||
// On Windows, Missing is returned if the dynamic library is not found at
|
||||
// runtime.
|
||||
func Open(i int) (Handle, Err) {
|
||||
return open(i)
|
||||
}
|
13
vendor/periph.io/x/d2xx/d2xx_darwin_amd64.go
generated
vendored
13
vendor/periph.io/x/d2xx/d2xx_darwin_amd64.go
generated
vendored
@ -1,13 +0,0 @@
|
||||
// Copyright 2017 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build cgo
|
||||
// +build !no_d2xx
|
||||
|
||||
package d2xx
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -framework CoreFoundation -framework IOKit ${SRCDIR}/third_party/libftd2xx_darwin_amd64_v1.4.4.a
|
||||
*/
|
||||
import "C"
|
13
vendor/periph.io/x/d2xx/d2xx_linux_amd64.go
generated
vendored
13
vendor/periph.io/x/d2xx/d2xx_linux_amd64.go
generated
vendored
@ -1,13 +0,0 @@
|
||||
// Copyright 2017 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build cgo
|
||||
// +build !no_d2xx
|
||||
|
||||
package d2xx
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: ${SRCDIR}/third_party/libftd2xx_linux_amd64_v1.4.24.a
|
||||
*/
|
||||
import "C"
|
16
vendor/periph.io/x/d2xx/d2xx_linux_arm.go
generated
vendored
16
vendor/periph.io/x/d2xx/d2xx_linux_arm.go
generated
vendored
@ -1,16 +0,0 @@
|
||||
// Copyright 2017 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build cgo
|
||||
// +build !no_d2xx
|
||||
|
||||
package d2xx
|
||||
|
||||
// TODO(maruel): https://github.com/golang/go/issues/7211 would help target the
|
||||
// optimal ARM architecture.
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: ${SRCDIR}/third_party/libftd2xx_linux_arm6hf_v1.4.24.a
|
||||
*/
|
||||
import "C"
|
13
vendor/periph.io/x/d2xx/d2xx_linux_arm64.go
generated
vendored
13
vendor/periph.io/x/d2xx/d2xx_linux_arm64.go
generated
vendored
@ -1,13 +0,0 @@
|
||||
// Copyright 2021 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build cgo
|
||||
// +build !no_d2xx
|
||||
|
||||
package d2xx
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: ${SRCDIR}/third_party/libftd2xx_linux_arm64_v1.4.24.a
|
||||
*/
|
||||
import "C"
|
219
vendor/periph.io/x/d2xx/d2xx_posix.go
generated
vendored
219
vendor/periph.io/x/d2xx/d2xx_posix.go
generated
vendored
@ -1,219 +0,0 @@
|
||||
// Copyright 2017 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build cgo
|
||||
// +build !windows
|
||||
// +build !no_d2xx
|
||||
|
||||
package d2xx
|
||||
|
||||
/*
|
||||
#include "third_party/ftd2xx.h"
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Available is true if the library is available on this system.
|
||||
const Available = true
|
||||
|
||||
// Library functions.
|
||||
|
||||
func version() (uint8, uint8, uint8) {
|
||||
var v C.DWORD
|
||||
C.FT_GetLibraryVersion(&v)
|
||||
return uint8(v >> 16), uint8(v >> 8), uint8(v)
|
||||
}
|
||||
|
||||
func createDeviceInfoList() (int, Err) {
|
||||
var num C.DWORD
|
||||
e := C.FT_CreateDeviceInfoList(&num)
|
||||
return int(num), Err(e)
|
||||
}
|
||||
|
||||
func open(i int) (Handle, Err) {
|
||||
var h C.FT_HANDLE
|
||||
e := C.FT_Open(C.int(i), &h)
|
||||
if uintptr(h) == 0 && e == 0 {
|
||||
// 18 means FT_OTHER_ERROR. Kind of a hack but better than panic.
|
||||
e = 18
|
||||
}
|
||||
return handle(h), Err(e)
|
||||
}
|
||||
|
||||
func (h handle) Close() Err {
|
||||
return Err(C.FT_Close(h.toH()))
|
||||
}
|
||||
|
||||
func (h handle) ResetDevice() Err {
|
||||
return Err(C.FT_ResetDevice(h.toH()))
|
||||
}
|
||||
|
||||
func (h handle) GetDeviceInfo() (uint32, uint16, uint16, Err) {
|
||||
var dev C.FT_DEVICE
|
||||
var id C.DWORD
|
||||
if e := C.FT_GetDeviceInfo(h.toH(), &dev, &id, nil, nil, nil); e != 0 {
|
||||
return unknown, 0, 0, Err(e)
|
||||
}
|
||||
return uint32(dev), uint16(id >> 16), uint16(id), 0
|
||||
}
|
||||
|
||||
func (h handle) EEPROMRead(devType uint32, ee *EEPROM) Err {
|
||||
var manufacturer [64]C.char
|
||||
var manufacturerID [64]C.char
|
||||
var desc [64]C.char
|
||||
var serial [64]C.char
|
||||
eepromVoid := unsafe.Pointer(&ee.Raw[0])
|
||||
hdr := ee.asHeader()
|
||||
|
||||
// There something odd going on here.
|
||||
//
|
||||
// On a ft232h, we observed that hdr.DeviceType MUST NOT be set, but on a
|
||||
// ft232r, it MUST be set. Since we can't know in advance what we must use,
|
||||
// just try both. ¯\_(ツ)_/¯
|
||||
hdr.DeviceType = devType
|
||||
if e := C.FT_EEPROM_Read(h.toH(), eepromVoid, C.DWORD(len(ee.Raw)), &manufacturer[0], &manufacturerID[0], &desc[0], &serial[0]); e != 0 {
|
||||
// FT_INVALID_PARAMETER
|
||||
if e == 6 {
|
||||
hdr.DeviceType = 0
|
||||
e = C.FT_EEPROM_Read(h.toH(), eepromVoid, C.DWORD(len(ee.Raw)), &manufacturer[0], &manufacturerID[0], &desc[0], &serial[0])
|
||||
}
|
||||
if e != 0 {
|
||||
return Err(e)
|
||||
}
|
||||
}
|
||||
|
||||
ee.Manufacturer = C.GoString(&manufacturer[0])
|
||||
ee.ManufacturerID = C.GoString(&manufacturerID[0])
|
||||
ee.Desc = C.GoString(&desc[0])
|
||||
ee.Serial = C.GoString(&serial[0])
|
||||
return 0
|
||||
}
|
||||
|
||||
func (h handle) EEPROMProgram(ee *EEPROM) Err {
|
||||
// len(manufacturer) + len(desc) <= 40.
|
||||
/*
|
||||
var cmanu [64]byte
|
||||
copy(cmanu[:], ee.manufacturer)
|
||||
var cmanuID [64]byte
|
||||
copy(cmanuID[:], ee.manufacturerID)
|
||||
var cdesc [64]byte
|
||||
copy(cdesc[:], ee.desc)
|
||||
var cserial [64]byte
|
||||
copy(cserial[:], ee.serial)
|
||||
*/
|
||||
cmanu := C.CString(ee.Manufacturer)
|
||||
defer C.free(unsafe.Pointer(cmanu))
|
||||
cmanuID := C.CString(ee.ManufacturerID)
|
||||
defer C.free(unsafe.Pointer(cmanuID))
|
||||
cdesc := C.CString(ee.Desc)
|
||||
defer C.free(unsafe.Pointer(cdesc))
|
||||
cserial := C.CString(ee.Serial)
|
||||
defer C.free(unsafe.Pointer(cserial))
|
||||
|
||||
if len(ee.Raw) == 0 {
|
||||
return Err(C.FT_EEPROM_Program(h.toH(), unsafe.Pointer(uintptr(0)), 0, cmanu, cmanuID, cdesc, cserial))
|
||||
}
|
||||
return Err(C.FT_EEPROM_Program(h.toH(), unsafe.Pointer(&ee.Raw[0]), C.DWORD(len(ee.Raw)), cmanu, cmanuID, cdesc, cserial))
|
||||
}
|
||||
|
||||
func (h handle) EraseEE() Err {
|
||||
return Err(C.FT_EraseEE(h.toH()))
|
||||
}
|
||||
|
||||
func (h handle) WriteEE(offset uint8, value uint16) Err {
|
||||
return Err(C.FT_WriteEE(h.toH(), C.DWORD(offset), C.WORD(value)))
|
||||
}
|
||||
|
||||
func (h handle) EEUASize() (int, Err) {
|
||||
var size C.DWORD
|
||||
if e := C.FT_EE_UASize(h.toH(), &size); e != 0 {
|
||||
return 0, Err(e)
|
||||
}
|
||||
return int(size), 0
|
||||
}
|
||||
|
||||
func (h handle) EEUARead(ua []byte) Err {
|
||||
var size C.DWORD
|
||||
if e := C.FT_EE_UARead(h.toH(), (*C.UCHAR)(unsafe.Pointer(&ua[0])), C.DWORD(len(ua)), &size); e != 0 {
|
||||
return Err(e)
|
||||
}
|
||||
if int(size) != len(ua) {
|
||||
return 6 // FT_INVALID_PARAMETER
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (h handle) EEUAWrite(ua []byte) Err {
|
||||
if e := C.FT_EE_UAWrite(h.toH(), (*C.UCHAR)(&ua[0]), C.DWORD(len(ua))); e != 0 {
|
||||
return Err(e)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (h handle) SetChars(eventChar byte, eventEn bool, errorChar byte, errorEn bool) Err {
|
||||
v := C.UCHAR(0)
|
||||
if eventEn {
|
||||
v = 1
|
||||
}
|
||||
w := C.UCHAR(0)
|
||||
if errorEn {
|
||||
w = 1
|
||||
}
|
||||
return Err(C.FT_SetChars(h.toH(), C.UCHAR(eventChar), v, C.UCHAR(errorChar), w))
|
||||
}
|
||||
|
||||
func (h handle) SetUSBParameters(in, out int) Err {
|
||||
return Err(C.FT_SetUSBParameters(h.toH(), C.DWORD(in), C.DWORD(out)))
|
||||
}
|
||||
|
||||
func (h handle) SetFlowControl() Err {
|
||||
return Err(C.FT_SetFlowControl(h.toH(), C.FT_FLOW_RTS_CTS, 0, 0))
|
||||
}
|
||||
|
||||
func (h handle) SetTimeouts(readMS, writeMS int) Err {
|
||||
return Err(C.FT_SetTimeouts(h.toH(), C.DWORD(readMS), C.DWORD(writeMS)))
|
||||
}
|
||||
|
||||
func (h handle) SetLatencyTimer(delayMS uint8) Err {
|
||||
return Err(C.FT_SetLatencyTimer(h.toH(), C.UCHAR(delayMS)))
|
||||
}
|
||||
|
||||
func (h handle) SetBaudRate(hz uint32) Err {
|
||||
return Err(C.FT_SetBaudRate(h.toH(), C.DWORD(hz)))
|
||||
}
|
||||
|
||||
func (h handle) GetQueueStatus() (uint32, Err) {
|
||||
var v C.DWORD
|
||||
e := C.FT_GetQueueStatus(h.toH(), &v)
|
||||
return uint32(v), Err(e)
|
||||
}
|
||||
|
||||
func (h handle) Read(b []byte) (int, Err) {
|
||||
var bytesRead C.DWORD
|
||||
e := C.FT_Read(h.toH(), C.LPVOID(unsafe.Pointer(&b[0])), C.DWORD(len(b)), &bytesRead)
|
||||
return int(bytesRead), Err(e)
|
||||
}
|
||||
|
||||
func (h handle) Write(b []byte) (int, Err) {
|
||||
var bytesSent C.DWORD
|
||||
e := C.FT_Write(h.toH(), C.LPVOID(unsafe.Pointer(&b[0])), C.DWORD(len(b)), &bytesSent)
|
||||
return int(bytesSent), Err(e)
|
||||
}
|
||||
|
||||
func (h handle) GetBitMode() (byte, Err) {
|
||||
var s C.UCHAR
|
||||
e := C.FT_GetBitMode(h.toH(), &s)
|
||||
return uint8(s), Err(e)
|
||||
}
|
||||
|
||||
func (h handle) SetBitMode(mask, mode byte) Err {
|
||||
return Err(C.FT_SetBitMode(h.toH(), C.UCHAR(mask), C.UCHAR(mode)))
|
||||
}
|
||||
|
||||
func (h handle) toH() C.FT_HANDLE {
|
||||
return C.FT_HANDLE(h)
|
||||
}
|
109
vendor/periph.io/x/d2xx/d2xx_posix_no_cgo.go
generated
vendored
109
vendor/periph.io/x/d2xx/d2xx_posix_no_cgo.go
generated
vendored
@ -1,109 +0,0 @@
|
||||
// Copyright 2017 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !cgo no_d2xx
|
||||
// +build !windows no_d2xx
|
||||
|
||||
package d2xx
|
||||
|
||||
// Available is true if the library is available on this system.
|
||||
const Available = false
|
||||
|
||||
// Library functions.
|
||||
|
||||
func version() (uint8, uint8, uint8) {
|
||||
return 0, 0, 0
|
||||
}
|
||||
|
||||
func createDeviceInfoList() (int, Err) {
|
||||
return 0, NoCGO
|
||||
}
|
||||
|
||||
func open(i int) (Handle, Err) {
|
||||
return handle(0), NoCGO
|
||||
}
|
||||
|
||||
func (h handle) Close() Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) ResetDevice() Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) GetDeviceInfo() (uint32, uint16, uint16, Err) {
|
||||
return unknown, 0, 0, NoCGO
|
||||
}
|
||||
|
||||
func (h handle) EEPROMRead(devType uint32, ee *EEPROM) Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) EEPROMProgram(e *EEPROM) Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) EraseEE() Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) WriteEE(offset uint8, value uint16) Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) EEUASize() (int, Err) {
|
||||
return 0, NoCGO
|
||||
}
|
||||
|
||||
func (h handle) EEUARead(ua []byte) Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) EEUAWrite(ua []byte) Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) SetChars(eventChar byte, eventEn bool, errorChar byte, errorEn bool) Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) SetUSBParameters(in, out int) Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) SetFlowControl() Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) SetTimeouts(readMS, writeMS int) Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) SetLatencyTimer(delayMS uint8) Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) SetBaudRate(hz uint32) Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) GetQueueStatus() (uint32, Err) {
|
||||
return 0, NoCGO
|
||||
}
|
||||
|
||||
func (h handle) Read(b []byte) (int, Err) {
|
||||
return 0, NoCGO
|
||||
}
|
||||
|
||||
func (h handle) Write(b []byte) (int, Err) {
|
||||
return 0, NoCGO
|
||||
}
|
||||
|
||||
func (h handle) GetBitMode() (byte, Err) {
|
||||
return 0, NoCGO
|
||||
}
|
||||
|
||||
func (h handle) SetBitMode(mask, mode byte) Err {
|
||||
return NoCGO
|
||||
}
|
19
vendor/periph.io/x/d2xx/d2xx_posix_other.go
generated
vendored
19
vendor/periph.io/x/d2xx/d2xx_posix_other.go
generated
vendored
@ -1,19 +0,0 @@
|
||||
// Copyright 2017 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build cgo
|
||||
// +build !darwin,!amd64
|
||||
// +build !linux,!amd64
|
||||
// +build !linux,!arm
|
||||
// +build !windows
|
||||
// +build !no_d2xx
|
||||
|
||||
package d2xx
|
||||
|
||||
// This assumes the library is installed and available for linking.
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lftd2xx
|
||||
*/
|
||||
import "C"
|
281
vendor/periph.io/x/d2xx/d2xx_windows.go
generated
vendored
281
vendor/periph.io/x/d2xx/d2xx_windows.go
generated
vendored
@ -1,281 +0,0 @@
|
||||
// Copyright 2017 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !no_d2xx
|
||||
|
||||
package d2xx
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Available is true if the library is available on this system.
|
||||
var Available = false
|
||||
|
||||
func version() (uint8, uint8, uint8) {
|
||||
var v uint32
|
||||
if pGetLibraryVersion != nil {
|
||||
_, _, _ = pGetLibraryVersion.Call(uintptr(unsafe.Pointer(&v)))
|
||||
}
|
||||
return uint8(v >> 16), uint8(v >> 8), uint8(v)
|
||||
}
|
||||
|
||||
func createDeviceInfoList() (int, Err) {
|
||||
if pCreateDeviceInfoList != nil {
|
||||
var num uint32
|
||||
r1, _, _ := pCreateDeviceInfoList.Call(uintptr(unsafe.Pointer(&num)))
|
||||
return int(num), Err(r1)
|
||||
}
|
||||
return 0, Missing
|
||||
}
|
||||
|
||||
func open(i int) (Handle, Err) {
|
||||
var h handle
|
||||
if pOpen != nil {
|
||||
r1, _, _ := pOpen.Call(uintptr(i), uintptr(unsafe.Pointer(&h)))
|
||||
return h, Err(r1)
|
||||
}
|
||||
return h, Missing
|
||||
}
|
||||
|
||||
func (h handle) Close() Err {
|
||||
r1, _, _ := pClose.Call(h.toH())
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) ResetDevice() Err {
|
||||
r1, _, _ := pResetDevice.Call(h.toH())
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) GetDeviceInfo() (uint32, uint16, uint16, Err) {
|
||||
var d uint32
|
||||
var id uint32
|
||||
if r1, _, _ := pGetDeviceInfo.Call(h.toH(), uintptr(unsafe.Pointer(&d)), uintptr(unsafe.Pointer(&id)), 0, 0, 0); r1 != 0 {
|
||||
return unknown, 0, 0, Err(r1)
|
||||
}
|
||||
return d, uint16(id >> 16), uint16(id), 0
|
||||
}
|
||||
|
||||
func (h handle) EEPROMRead(devType uint32, ee *EEPROM) Err {
|
||||
var manufacturer [64]byte
|
||||
var manufacturerID [64]byte
|
||||
var desc [64]byte
|
||||
var serial [64]byte
|
||||
// Shortcuts.
|
||||
m := uintptr(unsafe.Pointer(&manufacturer[0]))
|
||||
mi := uintptr(unsafe.Pointer(&manufacturerID[0]))
|
||||
de := uintptr(unsafe.Pointer(&desc[0]))
|
||||
s := uintptr(unsafe.Pointer(&serial[0]))
|
||||
|
||||
eepromVoid := unsafe.Pointer(&ee.Raw[0])
|
||||
hdr := ee.asHeader()
|
||||
// It MUST be set here. This is not always the case on posix.
|
||||
hdr.DeviceType = devType
|
||||
if r1, _, _ := pEEPROMRead.Call(h.toH(), uintptr(eepromVoid), uintptr(len(ee.Raw)), m, mi, de, s); r1 != 0 {
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
ee.Manufacturer = toStr(manufacturer[:])
|
||||
ee.ManufacturerID = toStr(manufacturerID[:])
|
||||
ee.Desc = toStr(desc[:])
|
||||
ee.Serial = toStr(serial[:])
|
||||
return 0
|
||||
}
|
||||
|
||||
func (h handle) EEPROMProgram(ee *EEPROM) Err {
|
||||
var cmanu [64]byte
|
||||
copy(cmanu[:], ee.Manufacturer)
|
||||
var cmanuID [64]byte
|
||||
copy(cmanuID[:], ee.ManufacturerID)
|
||||
var cdesc [64]byte
|
||||
copy(cdesc[:], ee.Desc)
|
||||
var cserial [64]byte
|
||||
copy(cserial[:], ee.Serial)
|
||||
r1, _, _ := pEEPROMProgram.Call(h.toH(), uintptr(unsafe.Pointer(&ee.Raw[0])), uintptr(len(ee.Raw)), uintptr(unsafe.Pointer(&cmanu[0])), uintptr(unsafe.Pointer(&cmanuID[0])), uintptr(unsafe.Pointer(&cdesc[0])), uintptr(unsafe.Pointer(&cserial[0])))
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) EraseEE() Err {
|
||||
r1, _, _ := pEraseEE.Call(h.toH())
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) WriteEE(offset uint8, value uint16) Err {
|
||||
r1, _, _ := pWriteEE.Call(h.toH(), uintptr(offset), uintptr(value))
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) EEUASize() (int, Err) {
|
||||
var size uint32
|
||||
if r1, _, _ := pEEUASize.Call(h.toH(), uintptr(unsafe.Pointer(&size))); r1 != 0 {
|
||||
return 0, Err(r1)
|
||||
}
|
||||
return int(size), 0
|
||||
}
|
||||
|
||||
func (h handle) EEUARead(ua []byte) Err {
|
||||
var size uint32
|
||||
if r1, _, _ := pEEUARead.Call(h.toH(), uintptr(unsafe.Pointer(&ua[0])), uintptr(len(ua)), uintptr(unsafe.Pointer(&size))); r1 != 0 {
|
||||
return Err(r1)
|
||||
}
|
||||
if int(size) != len(ua) {
|
||||
return 6 // FT_INVALID_PARAMETER
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (h handle) EEUAWrite(ua []byte) Err {
|
||||
r1, _, _ := pEEUAWrite.Call(h.toH(), uintptr(unsafe.Pointer(&ua[0])), uintptr(len(ua)))
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) SetChars(eventChar byte, eventEn bool, errorChar byte, errorEn bool) Err {
|
||||
v := uintptr(0)
|
||||
if eventEn {
|
||||
v = 1
|
||||
}
|
||||
w := uintptr(0)
|
||||
if errorEn {
|
||||
w = 1
|
||||
}
|
||||
r1, _, _ := pSetChars.Call(h.toH(), uintptr(eventChar), v, uintptr(errorChar), w)
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) SetUSBParameters(in, out int) Err {
|
||||
r1, _, _ := pSetUSBParameters.Call(h.toH(), uintptr(in), uintptr(out))
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) SetFlowControl() Err {
|
||||
// FT_FLOW_RTS_CTS
|
||||
r1, _, _ := pSetFlowControl.Call(h.toH(), 0x0100, 0, 0)
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) SetTimeouts(readMS, writeMS int) Err {
|
||||
r1, _, _ := pSetTimeouts.Call(h.toH(), uintptr(readMS), uintptr(writeMS))
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) SetLatencyTimer(delayMS uint8) Err {
|
||||
r1, _, _ := pSetLatencyTimer.Call(h.toH(), uintptr(delayMS))
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) SetBaudRate(hz uint32) Err {
|
||||
r1, _, _ := pSetBaudRate.Call(h.toH(), uintptr(hz))
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) GetQueueStatus() (uint32, Err) {
|
||||
var v uint32
|
||||
r1, _, _ := pGetQueueStatus.Call(h.toH(), uintptr(unsafe.Pointer(&v)))
|
||||
return v, Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) Read(b []byte) (int, Err) {
|
||||
var bytesRead uint32
|
||||
r1, _, _ := pRead.Call(h.toH(), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), uintptr(unsafe.Pointer(&bytesRead)))
|
||||
return int(bytesRead), Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) Write(b []byte) (int, Err) {
|
||||
var bytesSent uint32
|
||||
r1, _, _ := pWrite.Call(h.toH(), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), uintptr(unsafe.Pointer(&bytesSent)))
|
||||
return int(bytesSent), Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) GetBitMode() (byte, Err) {
|
||||
var s uint8
|
||||
r1, _, _ := pGetBitMode.Call(h.toH(), uintptr(unsafe.Pointer(&s)))
|
||||
return s, Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) SetBitMode(mask, mode byte) Err {
|
||||
r1, _, _ := pSetBitMode.Call(h.toH(), uintptr(mask), uintptr(mode))
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) toH() uintptr {
|
||||
return uintptr(h)
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
var (
|
||||
pClose *syscall.Proc
|
||||
pCreateDeviceInfoList *syscall.Proc
|
||||
pEEPROMRead *syscall.Proc
|
||||
pEEPROMProgram *syscall.Proc
|
||||
pEraseEE *syscall.Proc
|
||||
pWriteEE *syscall.Proc
|
||||
pEEUASize *syscall.Proc
|
||||
pEEUARead *syscall.Proc
|
||||
pEEUAWrite *syscall.Proc
|
||||
pGetBitMode *syscall.Proc
|
||||
pGetDeviceInfo *syscall.Proc
|
||||
pGetLibraryVersion *syscall.Proc
|
||||
pGetQueueStatus *syscall.Proc
|
||||
pOpen *syscall.Proc
|
||||
pRead *syscall.Proc
|
||||
pResetDevice *syscall.Proc
|
||||
pSetBaudRate *syscall.Proc
|
||||
pSetBitMode *syscall.Proc
|
||||
pSetChars *syscall.Proc
|
||||
pSetFlowControl *syscall.Proc
|
||||
pSetLatencyTimer *syscall.Proc
|
||||
pSetTimeouts *syscall.Proc
|
||||
pSetUSBParameters *syscall.Proc
|
||||
pWrite *syscall.Proc
|
||||
)
|
||||
|
||||
func init() {
|
||||
if dll, _ := syscall.LoadDLL("ftd2xx.dll"); dll != nil {
|
||||
// If any function is not found, disable the support.
|
||||
Available = true
|
||||
find := func(n string) *syscall.Proc {
|
||||
s, _ := dll.FindProc(n)
|
||||
if s == nil {
|
||||
Available = false
|
||||
}
|
||||
return s
|
||||
}
|
||||
pClose = find("FT_Close")
|
||||
pCreateDeviceInfoList = find("FT_CreateDeviceInfoList")
|
||||
pEEPROMRead = find("FT_EEPROM_Read")
|
||||
pEEPROMProgram = find("FT_EEPROM_Program")
|
||||
pEraseEE = find("FT_EraseEE")
|
||||
pWriteEE = find("FT_WriteEE")
|
||||
pEEUASize = find("FT_EE_UASize")
|
||||
pEEUARead = find("FT_EE_UARead")
|
||||
pEEUAWrite = find("FT_EE_UAWrite")
|
||||
pGetBitMode = find("FT_GetBitMode")
|
||||
pGetDeviceInfo = find("FT_GetDeviceInfo")
|
||||
pGetLibraryVersion = find("FT_GetLibraryVersion")
|
||||
pGetQueueStatus = find("FT_GetQueueStatus")
|
||||
pOpen = find("FT_Open")
|
||||
pRead = find("FT_Read")
|
||||
pResetDevice = find("FT_ResetDevice")
|
||||
pSetBaudRate = find("FT_SetBaudRate")
|
||||
pSetBitMode = find("FT_SetBitMode")
|
||||
pSetChars = find("FT_SetChars")
|
||||
pSetFlowControl = find("FT_SetFlowControl")
|
||||
pSetLatencyTimer = find("FT_SetLatencyTimer")
|
||||
pSetTimeouts = find("FT_SetTimeouts")
|
||||
pSetUSBParameters = find("FT_SetUSBParameters")
|
||||
pWrite = find("FT_Write")
|
||||
}
|
||||
}
|
||||
|
||||
func toStr(c []byte) string {
|
||||
i := bytes.IndexByte(c, 0)
|
||||
if i != -1 {
|
||||
return string(c[:i])
|
||||
}
|
||||
return string(c)
|
||||
}
|
18
vendor/periph.io/x/d2xx/doc.go
generated
vendored
18
vendor/periph.io/x/d2xx/doc.go
generated
vendored
@ -1,18 +0,0 @@
|
||||
// Copyright 2017 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// Package d2xx is a thin Go wrapper for the Future Technology "D2XX" driver.
|
||||
//
|
||||
// This package is not Go idiomatic. You want to use
|
||||
// https://periph.io/x/host/v3/ftdi (or later) instead.
|
||||
//
|
||||
// A static library of the d2xx driver is included for linux and macOS. They are
|
||||
// from https://ftdichip.com/drivers/d2xx-drivers/. See third_party/README.md
|
||||
// for more details.
|
||||
//
|
||||
// Configuration
|
||||
//
|
||||
// See https://periph.io/device/ftdi/ for more details, and how to configure
|
||||
// the host to be able to use this driver.
|
||||
package d2xx
|
39
vendor/periph.io/x/d2xx/eeprom.go
generated
vendored
39
vendor/periph.io/x/d2xx/eeprom.go
generated
vendored
@ -1,39 +0,0 @@
|
||||
// Copyright 2018 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
package d2xx
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// EEPROM is the unprocessed EEPROM content.
|
||||
//
|
||||
// The EEPROM is in 3 parts: the defined struct, the 4 strings and the rest
|
||||
// which is used as an 'user area'. The size of the user area depends on the
|
||||
// length of the strings. The user area content is not included in this struct.
|
||||
type EEPROM struct {
|
||||
// Raw is the raw EEPROM content. It excludes the strings.
|
||||
Raw []byte
|
||||
|
||||
// The following condition must be true: len(Manufacturer) + len(Desc) <= 40.
|
||||
Manufacturer string
|
||||
ManufacturerID string
|
||||
Desc string
|
||||
Serial string
|
||||
}
|
||||
|
||||
func (e *EEPROM) asHeader() *eepromHeader {
|
||||
// sizeof(EEPROMHeader)
|
||||
if len(e.Raw) < 16 {
|
||||
return nil
|
||||
}
|
||||
return (*eepromHeader)(unsafe.Pointer(&e.Raw[0]))
|
||||
}
|
||||
|
||||
// eepromHeader is the common 16 bytes header.
|
||||
type eepromHeader struct {
|
||||
DeviceType uint32
|
||||
// The rest is not necessary here so it is skipped.
|
||||
}
|
43
vendor/periph.io/x/d2xx/test.sh
generated
vendored
43
vendor/periph.io/x/d2xx/test.sh
generated
vendored
@ -1,43 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Copyright 2017 The Periph Authors. All rights reserved.
|
||||
# Use of this source code is governed under the Apache License, Version 2.0
|
||||
# that can be found in the LICENSE file.
|
||||
|
||||
# Builds the package on multiple OSes to confirm it builds fine.
|
||||
|
||||
set -eu
|
||||
|
||||
cd `dirname $0`
|
||||
|
||||
OPT=$*
|
||||
|
||||
# Do not set CGO_ENABLED, as we want the default behavior when cross compiling,
|
||||
# which is different from when CGO_ENABLED=1.
|
||||
export -n CGO_ENABLED
|
||||
|
||||
# Cleanup.
|
||||
export -n GOOS
|
||||
export -n GOARCH
|
||||
|
||||
function build {
|
||||
export GOOS=$1
|
||||
export GOARCH=$2
|
||||
echo "Building on $GOOS/$GOARCH"
|
||||
go build $OPT
|
||||
echo "Building on $GOOS/$GOARCH - no_d2xx"
|
||||
go build -tags no_d2xx $OPT
|
||||
echo "Building on $GOOS/$GOARCH - no cgo"
|
||||
CGO_ENABLED=0 go build $OPT
|
||||
echo "Building on $GOOS/$GOARCH - no cgo, no_d2xx"
|
||||
CGO_ENABLED=0 go build -tags no_d2xx $OPT
|
||||
}
|
||||
|
||||
CGO_ENABLED=1 CC=x86_64-linux-gnu-gcc build linux amd64
|
||||
# Requires: sudo apt install gcc-arm-linux-gnueabihf
|
||||
CGO_ENABLED=1 CC=arm-linux-gnueabihf-gcc build linux arm
|
||||
# Requires: sudo apt install gcc-aarch64-linux-gnu
|
||||
CGO_ENABLED=1 CC=aarch64-linux-gnu-gcc build linux arm64
|
||||
|
||||
build linux 386
|
||||
build windows amd64
|
||||
build darwin amd64
|
285
vendor/periph.io/x/host/v3/.gohci.yml
generated
vendored
285
vendor/periph.io/x/host/v3/.gohci.yml
generated
vendored
@ -17,44 +17,61 @@ workers:
|
||||
- -benchtime=1000ms
|
||||
- -benchmem
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: devices
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/devices
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/host/v3=../host
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/host/v3@${GIT_SHA}
|
||||
dir: ../devices
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../devices
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: cmd
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/host/v3=../host
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/host/v3@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../cmd
|
||||
# Test commands.
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- install
|
||||
- -v
|
||||
@ -63,7 +80,6 @@ workers:
|
||||
- ./periph-info
|
||||
- ./periph-smoketest
|
||||
- ./spi-list
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- periph-info
|
||||
- cmd:
|
||||
@ -93,44 +109,61 @@ workers:
|
||||
- -benchtime=1000ms
|
||||
- -benchmem
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: devices
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/devices
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/host/v3=../host
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/host/v3@${GIT_SHA}
|
||||
dir: ../devices
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../devices
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: cmd
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/host/v3=../host
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/host/v3@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../cmd
|
||||
# Test commands.
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- install
|
||||
- -v
|
||||
@ -140,7 +173,6 @@ workers:
|
||||
- ./periph-info
|
||||
- ./periph-smoketest
|
||||
- ./spi-list
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- periph-info
|
||||
- cmd:
|
||||
@ -183,44 +215,61 @@ workers:
|
||||
- -benchtime=1000ms
|
||||
- -benchmem
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: devices
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/devices
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/host/v3=../host
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/host/v3@${GIT_SHA}
|
||||
dir: ../devices
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../devices
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: cmd
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/host/v3=../host
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/host/v3@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../cmd
|
||||
# Test commands.
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- install
|
||||
- -v
|
||||
@ -230,7 +279,6 @@ workers:
|
||||
- ./periph-info
|
||||
- ./periph-smoketest
|
||||
- ./spi-list
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- periph-info
|
||||
- cmd:
|
||||
@ -277,6 +325,11 @@ workers:
|
||||
- periph-smoketest
|
||||
- bcm283x
|
||||
- -quick
|
||||
- cmd:
|
||||
- periph-smoketest
|
||||
- ftdi
|
||||
- -type
|
||||
- ft232h
|
||||
|
||||
# Old MacBook Pro on 10.9.
|
||||
- name: mbp
|
||||
@ -289,44 +342,61 @@ workers:
|
||||
- -benchtime=1000ms
|
||||
- -benchmem
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: devices
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/devices
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/host/v3=../host
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/host/v3@${GIT_SHA}
|
||||
dir: ../devices
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../devices
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: cmd
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/host/v3=../host
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/host/v3@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../cmd
|
||||
# Test commands.
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- install
|
||||
- -v
|
||||
@ -336,7 +406,6 @@ workers:
|
||||
- ./periph-info
|
||||
- ./periph-smoketest
|
||||
- ./spi-list
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- periph-info
|
||||
- cmd:
|
||||
@ -349,11 +418,11 @@ workers:
|
||||
- i2c-list
|
||||
- cmd:
|
||||
- spi-list
|
||||
# - cmd:
|
||||
# - periph-smoketest
|
||||
# - ftdi
|
||||
# - -type
|
||||
# - ft232r
|
||||
- cmd:
|
||||
- periph-smoketest
|
||||
- ftdi
|
||||
- -type
|
||||
- ft232r
|
||||
|
||||
# Laptop on Windows 10.
|
||||
- name: win10
|
||||
@ -366,44 +435,61 @@ workers:
|
||||
- -benchtime=1000ms
|
||||
- -benchmem
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: devices
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/devices
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/host/v3=../host
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/host/v3@${GIT_SHA}
|
||||
dir: ../devices
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../devices
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: cmd
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/host/v3=../host
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/host/v3@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../cmd
|
||||
# Test commands.
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- install
|
||||
- -v
|
||||
@ -413,7 +499,6 @@ workers:
|
||||
- ./periph-info
|
||||
- ./periph-smoketest
|
||||
- ./spi-list
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- periph-info
|
||||
- cmd:
|
||||
@ -426,8 +511,8 @@ workers:
|
||||
- i2c-list
|
||||
- cmd:
|
||||
- spi-list
|
||||
# - cmd:
|
||||
# - periph-smoketest
|
||||
# - ftdi
|
||||
# - -type
|
||||
# - ft232h
|
||||
- cmd:
|
||||
- periph-smoketest
|
||||
- ftdi
|
||||
- -type
|
||||
- ft232h
|
||||
|
3
vendor/periph.io/x/host/v3/README.md
generated
vendored
3
vendor/periph.io/x/host/v3/README.md
generated
vendored
@ -9,8 +9,7 @@ get an [invite here](https://invite.slack.golangbridge.org/).
|
||||
[](https://periph.io/)
|
||||
|
||||
[](https://pkg.go.dev/periph.io/x/host/v3)
|
||||
[](https://codecov.io/gh/periph/host)
|
||||
[](https://codecov.io/gh/periph/host)
|
||||
|
||||
|
||||
## Example
|
||||
|
1
vendor/periph.io/x/host/v3/allwinner/allwinner_arm64.go
generated
vendored
1
vendor/periph.io/x/host/v3/allwinner/allwinner_arm64.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build arm64
|
||||
// +build arm64
|
||||
|
||||
package allwinner
|
||||
|
1
vendor/periph.io/x/host/v3/allwinner/allwinner_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/allwinner/allwinner_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm && !arm64
|
||||
// +build !arm,!arm64
|
||||
|
||||
package allwinner
|
||||
|
1
vendor/periph.io/x/host/v3/am335x/am335x_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/am335x/am335x_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm
|
||||
// +build !arm
|
||||
|
||||
package am335x
|
||||
|
1
vendor/periph.io/x/host/v3/bcm283x/bcm283x_arm64.go
generated
vendored
1
vendor/periph.io/x/host/v3/bcm283x/bcm283x_arm64.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build arm64
|
||||
// +build arm64
|
||||
|
||||
package bcm283x
|
||||
|
1
vendor/periph.io/x/host/v3/bcm283x/bcm283x_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/bcm283x/bcm283x_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm && !arm64
|
||||
// +build !arm,!arm64
|
||||
|
||||
package bcm283x
|
||||
|
14
vendor/periph.io/x/host/v3/bcm283x/gpio.go
generated
vendored
14
vendor/periph.io/x/host/v3/bcm283x/gpio.go
generated
vendored
@ -406,8 +406,8 @@ func (p *Pin) In(pull gpio.Pull, edge gpio.Edge) error {
|
||||
// https://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
|
||||
// page 101.
|
||||
// However, BCM2711 uses a simpler way of setting pull resistors, reference at
|
||||
// https://github.com/raspberrypi/documentation/blob/master/hardware/raspberrypi/bcm2711/rpi_DATA_2711_1p0.pdf
|
||||
// page 84 and 95 ~ 98.
|
||||
// https://datasheets.raspberrypi.org/bcm2711/bcm2711-peripherals.pdf
|
||||
// page 65 and 73 ~ 76.
|
||||
|
||||
// If we are running on a newer chip such as BCM2711, set Pull directly.
|
||||
if !drvGPIO.useLegacyPull {
|
||||
@ -431,7 +431,10 @@ func (p *Pin) In(pull gpio.Pull, edge gpio.Edge) error {
|
||||
case gpio.Float:
|
||||
pullState = 0
|
||||
}
|
||||
drvGPIO.gpioMemory.pullRegister[offset] = pullState << uint((p.number%16)<<1)
|
||||
|
||||
bitOffset := 2 * uint(p.number%16)
|
||||
previous := drvGPIO.gpioMemory.pullRegister[offset] & ^(3 << bitOffset)
|
||||
drvGPIO.gpioMemory.pullRegister[offset] = previous | (pullState << bitOffset)
|
||||
} else {
|
||||
// Set Pull
|
||||
switch pull {
|
||||
@ -1024,9 +1027,8 @@ type function uint8
|
||||
// Mapping as
|
||||
// https://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
|
||||
// pages 90-91.
|
||||
// And
|
||||
// https://github.com/raspberrypi/documentation/blob/master/hardware/raspberrypi/bcm2711/rpi_DATA_2711_1p0.pdf
|
||||
// pages 83-84.
|
||||
// And https://datasheets.raspberrypi.org/bcm2711/bcm2711-peripherals.pdf pages
|
||||
// 65 and 73 ~ 76.
|
||||
type gpioMap struct {
|
||||
// 0x00 RW GPIO Function Select 0 (GPIO0-9)
|
||||
// 0x04 RW GPIO Function Select 1 (GPIO10-19)
|
||||
|
1
vendor/periph.io/x/host/v3/beagle/black/black_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/beagle/black/black_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm
|
||||
// +build !arm
|
||||
|
||||
package black
|
||||
|
1
vendor/periph.io/x/host/v3/beagle/bone/bone_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/beagle/bone/bone_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm
|
||||
// +build !arm
|
||||
|
||||
package bone
|
||||
|
1
vendor/periph.io/x/host/v3/beagle/green/green_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/beagle/green/green_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm
|
||||
// +build !arm
|
||||
|
||||
package green
|
||||
|
1
vendor/periph.io/x/host/v3/chip/chip_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/chip/chip_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm
|
||||
// +build !arm
|
||||
|
||||
package chip
|
||||
|
1
vendor/periph.io/x/host/v3/cpu/cpu_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/cpu/cpu_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package cpu
|
||||
|
1
vendor/periph.io/x/host/v3/distro/distro_arm64.go
generated
vendored
1
vendor/periph.io/x/host/v3/distro/distro_arm64.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build arm64
|
||||
// +build arm64
|
||||
|
||||
package distro
|
||||
|
1
vendor/periph.io/x/host/v3/distro/distro_nonarm.go
generated
vendored
1
vendor/periph.io/x/host/v3/distro/distro_nonarm.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm && !arm64
|
||||
// +build !arm,!arm64
|
||||
|
||||
package distro
|
||||
|
1
vendor/periph.io/x/host/v3/distro/distro_nonlinux.go
generated
vendored
1
vendor/periph.io/x/host/v3/distro/distro_nonlinux.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package distro
|
||||
|
1
vendor/periph.io/x/host/v3/fs/fs_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/fs/fs_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package fs
|
||||
|
1
vendor/periph.io/x/host/v3/fs/ioctl_mips_like.go
generated
vendored
1
vendor/periph.io/x/host/v3/fs/ioctl_mips_like.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build mips || mipsle
|
||||
// +build mips mipsle
|
||||
|
||||
package fs
|
||||
|
1
vendor/periph.io/x/host/v3/fs/ioctl_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/fs/ioctl_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !mips && !mipsle
|
||||
// +build !mips,!mipsle
|
||||
|
||||
package fs
|
||||
|
878
vendor/periph.io/x/host/v3/ftdi/dev.go
generated
vendored
878
vendor/periph.io/x/host/v3/ftdi/dev.go
generated
vendored
@ -1,878 +0,0 @@
|
||||
// Copyright 2017 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
package ftdi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"periph.io/x/conn/v3"
|
||||
"periph.io/x/conn/v3/gpio"
|
||||
"periph.io/x/conn/v3/i2c"
|
||||
"periph.io/x/conn/v3/physic"
|
||||
"periph.io/x/conn/v3/spi"
|
||||
)
|
||||
|
||||
// Info is the information gathered about the connected FTDI device.
|
||||
//
|
||||
// The data is gathered from the USB descriptor.
|
||||
type Info struct {
|
||||
// Opened is true if the device was successfully opened.
|
||||
Opened bool
|
||||
// Type is the FTDI device type.
|
||||
//
|
||||
// The value can be "FT232H", "FT232R", etc.
|
||||
//
|
||||
// An empty string means the type is unknown.
|
||||
Type string
|
||||
// VenID is the vendor ID from the USB descriptor information. It is expected
|
||||
// to be 0x0403 (FTDI).
|
||||
VenID uint16
|
||||
// DevID is the product ID from the USB descriptor information. It is
|
||||
// expected to be one of 0x6001, 0x6006, 0x6010, 0x6014.
|
||||
DevID uint16
|
||||
}
|
||||
|
||||
// Dev represents one FTDI device.
|
||||
//
|
||||
// There can be multiple FTDI devices connected to a host.
|
||||
//
|
||||
// The device may also export one or multiple of I²C, SPI buses. You need to
|
||||
// either cast into the right hardware, but more simply use the i2creg / spireg
|
||||
// bus/port registries.
|
||||
type Dev interface {
|
||||
// conn.Resource
|
||||
String() string
|
||||
Halt() error
|
||||
|
||||
// Info returns information about an opened device.
|
||||
Info(i *Info)
|
||||
|
||||
// Header returns the GPIO pins exposed on the chip.
|
||||
Header() []gpio.PinIO
|
||||
|
||||
// SetSpeed sets the base clock for all I/O transactions.
|
||||
//
|
||||
// The device defaults to its fastest speed.
|
||||
SetSpeed(f physic.Frequency) error
|
||||
|
||||
// EEPROM returns the EEPROM content.
|
||||
EEPROM(ee *EEPROM) error
|
||||
// WriteEEPROM updates the EEPROM. Must be used carefully.
|
||||
WriteEEPROM(ee *EEPROM) error
|
||||
// EraseEEPROM erases the EEPROM. Must be used carefully.
|
||||
EraseEEPROM() error
|
||||
// UserArea reads and return the EEPROM part that can be used to stored user
|
||||
// defined values.
|
||||
UserArea() ([]byte, error)
|
||||
// WriteUserArea updates the user area in the EEPROM.
|
||||
//
|
||||
// If the length of ua is less than the available space, is it zero extended.
|
||||
WriteUserArea(ua []byte) error
|
||||
}
|
||||
|
||||
// broken represents a device that couldn't be opened correctly.
|
||||
//
|
||||
// It returns an error message to help the user diagnose issues.
|
||||
type broken struct {
|
||||
index int
|
||||
err error
|
||||
name string
|
||||
}
|
||||
|
||||
func (b *broken) String() string {
|
||||
return b.name
|
||||
}
|
||||
|
||||
func (b *broken) Halt() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *broken) Info(i *Info) {
|
||||
i.Opened = false
|
||||
}
|
||||
|
||||
func (b *broken) Header() []gpio.PinIO {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *broken) SetSpeed(f physic.Frequency) error {
|
||||
return b.err
|
||||
}
|
||||
|
||||
func (b *broken) EEPROM(ee *EEPROM) error {
|
||||
return b.err
|
||||
}
|
||||
|
||||
func (b *broken) WriteEEPROM(ee *EEPROM) error {
|
||||
return b.err
|
||||
}
|
||||
|
||||
func (b *broken) EraseEEPROM() error {
|
||||
return b.err
|
||||
}
|
||||
|
||||
func (b *broken) UserArea() ([]byte, error) {
|
||||
return nil, b.err
|
||||
}
|
||||
|
||||
func (b *broken) WriteUserArea(ua []byte) error {
|
||||
return b.err
|
||||
}
|
||||
|
||||
// generic represents a generic FTDI device.
|
||||
//
|
||||
// It is used for the models that this package doesn't fully support yet.
|
||||
type generic struct {
|
||||
// Immutable after initialization.
|
||||
index int
|
||||
h *handle
|
||||
name string
|
||||
}
|
||||
|
||||
func (f *generic) String() string {
|
||||
return f.name
|
||||
}
|
||||
|
||||
// Halt implements conn.Resource.
|
||||
//
|
||||
// This halts all operations going through this device.
|
||||
func (f *generic) Halt() error {
|
||||
return f.h.Reset()
|
||||
}
|
||||
|
||||
// Info returns information about an opened device.
|
||||
func (f *generic) Info(i *Info) {
|
||||
i.Opened = true
|
||||
i.Type = f.h.t.String()
|
||||
i.VenID = f.h.venID
|
||||
i.DevID = f.h.devID
|
||||
}
|
||||
|
||||
// Header returns the GPIO pins exposed on the chip.
|
||||
func (f *generic) Header() []gpio.PinIO {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *generic) SetSpeed(freq physic.Frequency) error {
|
||||
// TODO(maruel): Doc says the actual speed is 16x, confirm.
|
||||
return f.h.SetBaudRate(freq)
|
||||
}
|
||||
|
||||
func (f *generic) EEPROM(ee *EEPROM) error {
|
||||
return f.h.ReadEEPROM(ee)
|
||||
/*
|
||||
if f.ee.Raw == nil {
|
||||
if err := f.h.readEEPROM(&f.ee); err != nil {
|
||||
return nil
|
||||
}
|
||||
if f.ee.Raw == nil {
|
||||
// It's a fresh new device. Devices bought via Adafruit already have
|
||||
// their EEPROM programmed with Adafruit branding but devices sold by
|
||||
// CJMCU are not. Since d2xxGetDeviceInfo() above succeeded, we know the
|
||||
// device type via the USB descriptor, which is sufficient to load the
|
||||
// driver, which permits to program the EEPROM to "bootstrap" it.
|
||||
f.ee.Raw = []byte{}
|
||||
}
|
||||
}
|
||||
*ee = f.ee
|
||||
return nil
|
||||
*/
|
||||
}
|
||||
|
||||
func (f *generic) WriteEEPROM(ee *EEPROM) error {
|
||||
// TODO(maruel): Compare with the cached EEPROM, and only update the
|
||||
// different values if needed so reduce the EEPROM wear.
|
||||
// f.h.h.d2xxWriteEE()
|
||||
return f.h.WriteEEPROM(ee)
|
||||
}
|
||||
|
||||
func (f *generic) EraseEEPROM() error {
|
||||
return f.h.EraseEEPROM()
|
||||
}
|
||||
|
||||
func (f *generic) UserArea() ([]byte, error) {
|
||||
return f.h.ReadUA()
|
||||
}
|
||||
|
||||
func (f *generic) WriteUserArea(ua []byte) error {
|
||||
return f.h.WriteUA(ua)
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
func newFT232H(g generic) (*FT232H, error) {
|
||||
f := &FT232H{
|
||||
generic: g,
|
||||
cbus: gpiosMPSSE{h: g.h, cbus: true},
|
||||
dbus: gpiosMPSSE{h: g.h},
|
||||
c8: invalidPin{num: 16, n: g.name + ".C8"}, // , dp: gpio.PullUp
|
||||
c9: invalidPin{num: 17, n: g.name + ".C9"}, // , dp: gpio.PullUp
|
||||
}
|
||||
f.cbus.init(f.name)
|
||||
f.dbus.init(f.name)
|
||||
|
||||
for i := range f.dbus.pins {
|
||||
f.hdr[i] = &f.dbus.pins[i]
|
||||
}
|
||||
for i := range f.cbus.pins {
|
||||
f.hdr[i+8] = &f.cbus.pins[i]
|
||||
}
|
||||
// TODO(maruel): C8 and C9 can be used when their mux in the EEPROM is set to
|
||||
// ft232hCBusIOMode.
|
||||
f.hdr[16] = &f.c8
|
||||
f.hdr[17] = &f.c9
|
||||
f.D0 = f.hdr[0]
|
||||
f.D1 = f.hdr[1]
|
||||
f.D2 = f.hdr[2]
|
||||
f.D3 = f.hdr[3]
|
||||
f.D4 = f.hdr[4]
|
||||
f.D5 = f.hdr[5]
|
||||
f.D6 = f.hdr[6]
|
||||
f.D7 = f.hdr[7]
|
||||
f.C0 = f.hdr[8]
|
||||
f.C1 = f.hdr[9]
|
||||
f.C2 = f.hdr[10]
|
||||
f.C3 = f.hdr[11]
|
||||
f.C4 = f.hdr[12]
|
||||
f.C5 = f.hdr[13]
|
||||
f.C6 = f.hdr[14]
|
||||
f.C7 = f.hdr[15]
|
||||
f.C8 = f.hdr[16]
|
||||
f.C9 = f.hdr[17]
|
||||
|
||||
// This function forces all pins as inputs.
|
||||
if err := f.h.InitMPSSE(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f.s.c.f = f
|
||||
f.i.f = f
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// FT232H represents a FT232H device.
|
||||
//
|
||||
// It implements Dev.
|
||||
//
|
||||
// The FT232H has 1024 bytes output buffer and 1024 bytes input buffer. It
|
||||
// supports 512 bytes USB packets.
|
||||
//
|
||||
// The device can be used in a few different modes, two modes are supported:
|
||||
//
|
||||
// - D0~D3 as a serial protocol (MPSEE), supporting I²C and SPI (and eventually
|
||||
// UART), In this mode, D4~D7 and C0~C7 can be used as synchronized GPIO.
|
||||
//
|
||||
// - D0~D7 as a synchronous 8 bits bit-bang port. In this mode, only a few pins
|
||||
// on CBus are usable in slow mode.
|
||||
//
|
||||
// Each group of pins D0~D7 and C0~C7 can be changed at once in one pass via
|
||||
// DBus() or CBus().
|
||||
//
|
||||
// This enables usage as an 8 bit parallel port.
|
||||
//
|
||||
// Pins C8 and C9 can only be used in 'slow' mode via EEPROM and are currently
|
||||
// not implemented.
|
||||
//
|
||||
// Datasheet
|
||||
//
|
||||
// http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT232H.pdf
|
||||
type FT232H struct {
|
||||
generic
|
||||
|
||||
D0 gpio.PinIO // Clock output
|
||||
D1 gpio.PinIO // Data out
|
||||
D2 gpio.PinIO // Data in
|
||||
D3 gpio.PinIO // Chip select
|
||||
D4 gpio.PinIO
|
||||
D5 gpio.PinIO
|
||||
D6 gpio.PinIO
|
||||
D7 gpio.PinIO
|
||||
C0 gpio.PinIO
|
||||
C1 gpio.PinIO
|
||||
C2 gpio.PinIO
|
||||
C3 gpio.PinIO
|
||||
C4 gpio.PinIO
|
||||
C5 gpio.PinIO
|
||||
C6 gpio.PinIO
|
||||
C7 gpio.PinIO
|
||||
C8 gpio.PinIO // Not implemented
|
||||
C9 gpio.PinIO // Not implemented
|
||||
|
||||
hdr [18]gpio.PinIO
|
||||
cbus gpiosMPSSE
|
||||
dbus gpiosMPSSE
|
||||
c8 invalidPin // gpio.PullUp
|
||||
c9 invalidPin // gpio.PullUp
|
||||
|
||||
mu sync.Mutex
|
||||
usingI2C bool
|
||||
usingSPI bool
|
||||
i i2cBus
|
||||
s spiMPSEEPort
|
||||
// TODO(maruel): Technically speaking, a SPI port could be hacked up too in
|
||||
// sync bit-bang but there's less point when MPSEE is available.
|
||||
}
|
||||
|
||||
// Header returns the GPIO pins exposed on the chip.
|
||||
func (f *FT232H) Header() []gpio.PinIO {
|
||||
out := make([]gpio.PinIO, len(f.hdr))
|
||||
copy(out, f.hdr[:])
|
||||
return out
|
||||
}
|
||||
|
||||
func (f *FT232H) SetSpeed(freq physic.Frequency) error {
|
||||
// TODO(maruel): When using MPSEE, use the MPSEE command. If using sync
|
||||
// bit-bang, use SetBaudRate().
|
||||
|
||||
// TODO(maruel): Doc says the actual speed is 16x, confirm.
|
||||
return f.h.SetBaudRate(freq)
|
||||
}
|
||||
|
||||
// CBus sets the values of C0 to C7 in the specified direction and value.
|
||||
//
|
||||
// 0 direction means input, 1 means output.
|
||||
func (f *FT232H) CBus(direction, value byte) error {
|
||||
return f.h.MPSSECBus(direction, value)
|
||||
}
|
||||
|
||||
// DBus sets the values of D0 to d7 in the specified direction and value.
|
||||
//
|
||||
// 0 direction means input, 1 means output.
|
||||
//
|
||||
// This function must be used to set Clock idle level.
|
||||
func (f *FT232H) DBus(direction, value byte) error {
|
||||
return f.h.MPSSEDBus(direction, value)
|
||||
}
|
||||
|
||||
// CBusRead reads the values of C0 to C7.
|
||||
func (f *FT232H) CBusRead() (byte, error) {
|
||||
return f.h.MPSSECBusRead()
|
||||
}
|
||||
|
||||
// DBusRead reads the values of D0 to D7.
|
||||
func (f *FT232H) DBusRead() (byte, error) {
|
||||
return f.h.MPSSEDBusRead()
|
||||
}
|
||||
|
||||
// I2C returns an I²C bus over the AD bus.
|
||||
//
|
||||
// pull can be either gpio.PullUp or gpio.Float. The recommended pull up
|
||||
// resistors are 10kΩ for 100kHz and 2kΩ for 400kHz when using Float. The
|
||||
// GPIO's pull up is 75kΩ, which may require using a lower speed for signal
|
||||
// reliability. Optimal pull up resistor calculation depends on the capacitance.
|
||||
//
|
||||
// It uses D0, D1 and D2.
|
||||
//
|
||||
// D0 is SCL. It must to be pulled up externally.
|
||||
//
|
||||
// D1 and D2 are used for SDA. D1 is the output using open drain, D2 is the
|
||||
// input. D1 and D2 must be wired together and must be pulled up externally.
|
||||
//
|
||||
// It is recommended to set the mode to ‘245 FIFO’ in the EEPROM of the FT232H.
|
||||
//
|
||||
// The FIFO mode is recommended because it allows the ADbus lines to start as
|
||||
// tristate. If the chip starts in the default UART mode, then the ADbus lines
|
||||
// will be in the default UART idle states until the application opens the port
|
||||
// and configures it as MPSSE. Care should also be taken that the RD# input on
|
||||
// ACBUS is not asserted in this initial state as this can cause the FIFO lines
|
||||
// to drive out.
|
||||
func (f *FT232H) I2C(pull gpio.Pull) (i2c.BusCloser, error) {
|
||||
if pull != gpio.PullUp && pull != gpio.Float {
|
||||
return nil, errors.New("d2xx: I²C pull can only be PullUp or Float")
|
||||
}
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
if f.usingI2C {
|
||||
return nil, errors.New("d2xx: already using I²C")
|
||||
}
|
||||
if f.usingSPI {
|
||||
return nil, errors.New("d2xx: already using SPI")
|
||||
}
|
||||
if err := f.i.setupI2C(pull == gpio.PullUp); err != nil {
|
||||
_ = f.i.stopI2C()
|
||||
return nil, err
|
||||
}
|
||||
return &f.i, nil
|
||||
}
|
||||
|
||||
// SPI returns a SPI port over the AD bus.
|
||||
//
|
||||
// It uses D0, D1, D2 and D3. D0 is the clock, D1 the output (MOSI), D2 is the
|
||||
// input (MISO) and D3 is CS line.
|
||||
func (f *FT232H) SPI() (spi.PortCloser, error) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
if f.usingI2C {
|
||||
return nil, errors.New("d2xx: already using I²C")
|
||||
}
|
||||
if f.usingSPI {
|
||||
return nil, errors.New("d2xx: already using SPI")
|
||||
}
|
||||
// Don't mark it as being used yet. It only become used once Connect() is
|
||||
// called.
|
||||
return &f.s, nil
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
func newFT232R(g generic) (*FT232R, error) {
|
||||
f := &FT232R{
|
||||
generic: g,
|
||||
dbus: [...]dbusPinSync{{num: 0}, {num: 1}, {num: 2}, {num: 3}, {num: 4}, {num: 5}, {num: 6}, {num: 7}},
|
||||
cbus: [...]cbusPin{{num: 8, p: gpio.PullUp}, {num: 9, p: gpio.PullUp}, {num: 10, p: gpio.PullUp}, {num: 11, p: gpio.Float}},
|
||||
}
|
||||
// Use the UART names, as this is how all FT232R boards are marked.
|
||||
dnames := [...]string{"TX", "RX", "RTS", "CTS", "DTR", "DSR", "DCD", "RI"}
|
||||
for i := range f.dbus {
|
||||
f.dbus[i].n = f.name + "." + dnames[i]
|
||||
f.dbus[i].bus = f
|
||||
f.hdr[i] = &f.dbus[i]
|
||||
}
|
||||
for i := range f.cbus {
|
||||
f.cbus[i].n = f.name + ".C" + strconv.Itoa(i)
|
||||
f.cbus[i].bus = f
|
||||
f.hdr[i+8] = &f.cbus[i]
|
||||
}
|
||||
f.D0 = f.hdr[0]
|
||||
f.D1 = f.hdr[1]
|
||||
f.D2 = f.hdr[2]
|
||||
f.D3 = f.hdr[3]
|
||||
f.D4 = f.hdr[4]
|
||||
f.D5 = f.hdr[5]
|
||||
f.D6 = f.hdr[6]
|
||||
f.D7 = f.hdr[7]
|
||||
f.TX = f.hdr[0]
|
||||
f.RX = f.hdr[1]
|
||||
f.RTS = f.hdr[2]
|
||||
f.CTS = f.hdr[3]
|
||||
f.DTR = f.hdr[4]
|
||||
f.DSR = f.hdr[5]
|
||||
f.DCD = f.hdr[6]
|
||||
f.RI = f.hdr[7]
|
||||
f.C0 = f.hdr[8]
|
||||
f.C1 = f.hdr[9]
|
||||
f.C2 = f.hdr[10]
|
||||
f.C3 = f.hdr[11]
|
||||
|
||||
// Default to 3MHz.
|
||||
if err := f.h.SetBaudRate(3 * physic.MegaHertz); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set all CBus pins as input.
|
||||
if err := f.h.SetBitMode(0, bitModeCbusBitbang); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// And read their value.
|
||||
// TODO(maruel): Sadly this is impossible to know which pin is input or
|
||||
// output, but we could try to guess, as the call above may generate noise on
|
||||
// the line which could interfere with the device connected.
|
||||
var err error
|
||||
if f.cbusnibble, err = f.h.GetBitMode(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Set all DBus as asynchronous bitbang, everything as input.
|
||||
if err := f.h.SetBitMode(0, bitModeAsyncBitbang); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// And read their value.
|
||||
var b [1]byte
|
||||
if _, err := f.h.ReadAll(context.Background(), b[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f.dvalue = b[0]
|
||||
f.s.c.f = f
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// FT232R represents a FT232RL/FT232RQ device.
|
||||
//
|
||||
// It implements Dev.
|
||||
//
|
||||
// Not all pins may be physically connected on the header!
|
||||
//
|
||||
// Adafruit's version only has the following pins connected: RX, TX, RTS and
|
||||
// CTS.
|
||||
//
|
||||
// SparkFun's version exports all pins *except* (inexplicably) the CBus ones.
|
||||
//
|
||||
// The FT232R has 128 bytes output buffer and 256 bytes input buffer.
|
||||
//
|
||||
// Pin C4 can only be used in 'slow' mode via EEPROM and is currently not
|
||||
// implemented.
|
||||
//
|
||||
// Datasheet
|
||||
//
|
||||
// http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT232R.pdf
|
||||
type FT232R struct {
|
||||
generic
|
||||
|
||||
// Pin and their alias to the Dn pins for user convenience. Each pair points
|
||||
// to the exact same pin.
|
||||
D0, TX gpio.PinIO // Transmit; SPI_MOSI
|
||||
D1, RX gpio.PinIO // Receive; SPI_MISO
|
||||
D2, RTS gpio.PinIO // Request To Send Control Output / Handshake signal; SPI_CLK
|
||||
D3, CTS gpio.PinIO // Clear to Send Control input / Handshake signal; SPI_CS
|
||||
D4, DTR gpio.PinIO // Data Terminal Ready Control Output / Handshake signal
|
||||
D5, DSR gpio.PinIO // Data Set Ready Control Input / Handshake signal
|
||||
D6, DCD gpio.PinIO // Data Carrier Detect Control input
|
||||
D7, RI gpio.PinIO // Ring Indicator Control Input. When remote wake up is enabled in the internal EEPROM taking RI# low can be used to resume the PC USB host controller from suspend.
|
||||
|
||||
// The CBus pins are slower to use, but can drive an high load, like a LED.
|
||||
C0 gpio.PinIO
|
||||
C1 gpio.PinIO
|
||||
C2 gpio.PinIO
|
||||
C3 gpio.PinIO
|
||||
|
||||
dbus [8]dbusPinSync
|
||||
cbus [4]cbusPin
|
||||
hdr [12]gpio.PinIO
|
||||
|
||||
// Mutable.
|
||||
mu sync.Mutex
|
||||
usingSPI bool
|
||||
usingCBus bool
|
||||
s spiSyncPort
|
||||
dmask uint8 // 0 input, 1 output
|
||||
dvalue uint8
|
||||
cbusnibble uint8 // upper nibble is I/O control, lower nibble is values.
|
||||
}
|
||||
|
||||
// Header returns the GPIO pins exposed on the chip.
|
||||
func (f *FT232R) Header() []gpio.PinIO {
|
||||
out := make([]gpio.PinIO, len(f.hdr))
|
||||
copy(out, f.hdr[:])
|
||||
return out
|
||||
}
|
||||
|
||||
// SetDBusMask sets all D0~D7 input or output mode at once.
|
||||
//
|
||||
// mask is the input/output pins to use. A bit value of 0 sets the
|
||||
// corresponding pin to an input, a bit value of 1 sets the corresponding pin
|
||||
// to an output.
|
||||
//
|
||||
// It should be called before calling Tx().
|
||||
func (f *FT232R) SetDBusMask(mask uint8) error {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
if f.usingSPI {
|
||||
return errors.New("d2xx: already using SPI")
|
||||
}
|
||||
return f.setDBusMaskLocked(mask)
|
||||
}
|
||||
|
||||
// Tx does synchronized read-then-write on all the D0~D7 GPIOs.
|
||||
//
|
||||
// SetSpeed() determines the pace at which the I/O is done.
|
||||
//
|
||||
// SetDBusMask() determines which bits are interpreted in the w and r byte
|
||||
// slice. w has its significant value masked by 'mask' and r has its
|
||||
// significant value masked by '^mask'.
|
||||
//
|
||||
// Input sample is done *before* updating outputs. So r[0] is sampled before
|
||||
// w[0] is used. The last w byte should be duplicated if an addition read is
|
||||
// desired.
|
||||
//
|
||||
// On the Adafruit cable, only the first 4 bits D0(TX), D1(RX), D2(RTS) and
|
||||
// D3(CTS) are connected. This is just enough to create a full duplex SPI bus!
|
||||
func (f *FT232R) Tx(w, r []byte) error {
|
||||
if len(w) != 0 {
|
||||
if len(r) != 0 && len(w) != len(r) {
|
||||
return errors.New("d2xx: length of buffer w and r must match")
|
||||
}
|
||||
} else if len(r) == 0 {
|
||||
return errors.New("d2xx: at least one of w or r must be passed")
|
||||
}
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
if f.usingSPI {
|
||||
return errors.New("d2xx: already using SPI")
|
||||
}
|
||||
return f.txLocked(w, r)
|
||||
}
|
||||
|
||||
// SPI returns a SPI port over the first 4 pins.
|
||||
//
|
||||
// It uses D0(TX), D1(RX), D2(RTS) and D3(CTS). D2(RTS) is the clock, D0(TX)
|
||||
// the output (MOSI), D1(RX) is the input (MISO) and D3(CTS) is CS line.
|
||||
func (f *FT232R) SPI() (spi.PortCloser, error) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
if f.usingSPI {
|
||||
return nil, errors.New("d2xx: already using SPI")
|
||||
}
|
||||
// Don't mark it as being used yet. It only become used once Connect() is
|
||||
// called.
|
||||
return &f.s, nil
|
||||
}
|
||||
|
||||
// setDBusMaskLocked is the locked version of SetDBusMask.
|
||||
func (f *FT232R) setDBusMaskLocked(mask uint8) error {
|
||||
if mask != f.dmask {
|
||||
if err := f.h.SetBitMode(mask, bitModeAsyncBitbang); err != nil {
|
||||
return err
|
||||
}
|
||||
f.dmask = mask
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FT232R) txLocked(w, r []byte) error {
|
||||
// Investigate FT232R clock issue:
|
||||
// http://developer.intra2net.com/mailarchive/html/libftdi/2010/msg00240.html
|
||||
|
||||
// The FT232R has 128 bytes TX buffer and 256 bytes RX buffer. Chunk into 64
|
||||
// bytes chunks. That's half the buffer size of the TX buffer and permits
|
||||
// pipelining and removes the risk of buffer overrun. This is important
|
||||
// otherwise there's huge gaps due to the USB transmit overhead.
|
||||
// TODO(maruel): Determine what's optimal via experimentation.
|
||||
chunk := 64
|
||||
var scratch [128]byte
|
||||
if len(w) == 0 {
|
||||
// Read only.
|
||||
for i := range scratch {
|
||||
scratch[i] = f.dvalue
|
||||
}
|
||||
for len(r) != 0 {
|
||||
// TODO(maruel): Optimize.
|
||||
c := len(r)
|
||||
if c > chunk {
|
||||
c = chunk
|
||||
}
|
||||
if _, err := f.h.Write(scratch[:c]); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := f.h.ReadAll(context.Background(), r[:c]); err != nil {
|
||||
return err
|
||||
}
|
||||
r = r[c:]
|
||||
}
|
||||
} else if len(r) == 0 {
|
||||
// Write only.
|
||||
// The first write is 128 bytes to fill the buffer.
|
||||
chunk = 128
|
||||
for len(w) != 0 {
|
||||
c := len(w)
|
||||
if c > chunk {
|
||||
c = chunk
|
||||
}
|
||||
if _, err := f.h.Write(w[:c]); err != nil {
|
||||
return err
|
||||
}
|
||||
w = w[c:]
|
||||
chunk = 64
|
||||
}
|
||||
/*
|
||||
// Let the USB drive pace it.
|
||||
if _, err := f.h.Write(w); err != nil {
|
||||
return err
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
// R/W.
|
||||
// Always write one 'w' ahead.
|
||||
// The first write is 128 bytes to fill the buffer.
|
||||
chunk = 128
|
||||
cw := len(w)
|
||||
if cw > chunk {
|
||||
cw = chunk
|
||||
}
|
||||
if _, err := f.h.Write(w[:cw]); err != nil {
|
||||
return err
|
||||
}
|
||||
w = w[cw:]
|
||||
chunk = 64
|
||||
for len(r) != 0 {
|
||||
// Read then write.
|
||||
cr := len(r)
|
||||
if cr > chunk {
|
||||
cr = chunk
|
||||
}
|
||||
if _, err := f.h.ReadAll(context.Background(), r[:cr]); err != nil {
|
||||
return err
|
||||
}
|
||||
r = r[cr:]
|
||||
|
||||
cw = len(w)
|
||||
if cw > chunk {
|
||||
cw = chunk
|
||||
}
|
||||
if cw != 0 {
|
||||
if _, err := f.h.Write(w[:cw]); err != nil {
|
||||
return err
|
||||
}
|
||||
w = w[cw:]
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// dbusSyncGPIOFunc implements dbusSync. It returns the function of a GPIO
|
||||
// pin.
|
||||
func (f *FT232R) dbusSyncGPIOFunc(n int) string {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
if f.usingSPI {
|
||||
switch n {
|
||||
case 0:
|
||||
return "SPI_MOSI" // TX
|
||||
case 1:
|
||||
return "SPI_MISO" // RX
|
||||
case 2:
|
||||
return "SPI_CLK" // RTS
|
||||
case 3:
|
||||
return "SPI_CS" // CTS
|
||||
}
|
||||
}
|
||||
mask := uint8(1 << uint(n))
|
||||
if f.dmask&mask != 0 {
|
||||
return "Out/" + gpio.Level(f.dvalue&mask != 0).String()
|
||||
}
|
||||
return "In/" + f.dbusSyncReadLocked(n).String()
|
||||
}
|
||||
|
||||
// dbusSyncGPIOIn implements dbusSync.
|
||||
func (f *FT232R) dbusSyncGPIOIn(n int) error {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
// TODO(maruel): if f.usingSPI && n < 4.
|
||||
mask := uint8(1 << uint(n))
|
||||
if f.dmask&mask == 0 {
|
||||
// Already input.
|
||||
return nil
|
||||
}
|
||||
v := f.dmask &^ mask
|
||||
if err := f.h.SetBitMode(v, bitModeAsyncBitbang); err != nil {
|
||||
return err
|
||||
}
|
||||
f.dmask = v
|
||||
return nil
|
||||
}
|
||||
|
||||
// dbusSyncGPIORead implements dbusSync.
|
||||
func (f *FT232R) dbusSyncGPIORead(n int) gpio.Level {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
return f.dbusSyncReadLocked(n)
|
||||
}
|
||||
|
||||
func (f *FT232R) dbusSyncReadLocked(n int) gpio.Level {
|
||||
// In synchronous mode, to read we must write first to for a sample.
|
||||
b := [1]byte{f.dvalue}
|
||||
if _, err := f.h.Write(b[:]); err != nil {
|
||||
return gpio.Low
|
||||
}
|
||||
mask := uint8(1 << uint(n))
|
||||
if _, err := f.h.ReadAll(context.Background(), b[:]); err != nil {
|
||||
return gpio.Low
|
||||
}
|
||||
f.dvalue = b[0]
|
||||
return f.dvalue&mask != 0
|
||||
}
|
||||
|
||||
// dbusSyncGPIOOut implements dbusSync.
|
||||
func (f *FT232R) dbusSyncGPIOOut(n int, l gpio.Level) error {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
mask := uint8(1 << uint(n))
|
||||
if f.dmask&mask != 1 {
|
||||
// Was input.
|
||||
v := f.dmask | mask
|
||||
if err := f.h.SetBitMode(v, bitModeAsyncBitbang); err != nil {
|
||||
return err
|
||||
}
|
||||
f.dmask = v
|
||||
}
|
||||
return f.dbusSyncGPIOOutLocked(n, l)
|
||||
}
|
||||
|
||||
func (f *FT232R) dbusSyncGPIOOutLocked(n int, l gpio.Level) error {
|
||||
b := [1]byte{f.dvalue}
|
||||
if _, err := f.h.Write(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
f.dvalue = b[0]
|
||||
// In synchronous mode, we must read after writing to flush the buffer.
|
||||
if _, err := f.h.Write(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// cBusGPIOFunc implements cBusGPIO.
|
||||
func (f *FT232R) cBusGPIOFunc(n int) string {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
fmask := uint8(0x10 << uint(n))
|
||||
vmask := uint8(1 << uint(n))
|
||||
if f.cbusnibble&fmask != 0 {
|
||||
return "Out/" + gpio.Level(f.cbusnibble&vmask != 0).String()
|
||||
}
|
||||
return "In/" + f.cBusReadLocked(n).String()
|
||||
}
|
||||
|
||||
// cBusGPIOIn implements cBusGPIO.
|
||||
func (f *FT232R) cBusGPIOIn(n int) error {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
fmask := uint8(0x10 << uint(n))
|
||||
if f.cbusnibble&fmask == 0 {
|
||||
// Already input.
|
||||
return nil
|
||||
}
|
||||
v := f.cbusnibble &^ fmask
|
||||
if err := f.h.SetBitMode(v, bitModeCbusBitbang); err != nil {
|
||||
return err
|
||||
}
|
||||
f.cbusnibble = v
|
||||
return nil
|
||||
}
|
||||
|
||||
// cBusGPIORead implements cBusGPIO.
|
||||
func (f *FT232R) cBusGPIORead(n int) gpio.Level {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
return f.cBusReadLocked(n)
|
||||
}
|
||||
|
||||
func (f *FT232R) cBusReadLocked(n int) gpio.Level {
|
||||
v, err := f.h.GetBitMode()
|
||||
if err != nil {
|
||||
return gpio.Low
|
||||
}
|
||||
f.cbusnibble = v
|
||||
vmask := uint8(1 << uint(n))
|
||||
return f.cbusnibble&vmask != 0
|
||||
}
|
||||
|
||||
// cBusGPIOOut implements cBusGPIO.
|
||||
func (f *FT232R) cBusGPIOOut(n int, l gpio.Level) error {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
fmask := uint8(0x10 << uint(n))
|
||||
vmask := uint8(1 << uint(n))
|
||||
v := f.cbusnibble | fmask
|
||||
if l {
|
||||
v |= vmask
|
||||
} else {
|
||||
v &^= vmask
|
||||
}
|
||||
if f.cbusnibble == v {
|
||||
// Was already in the right mode.
|
||||
return nil
|
||||
}
|
||||
if err := f.h.SetBitMode(v, bitModeCbusBitbang); err != nil {
|
||||
return err
|
||||
}
|
||||
f.cbusnibble = v
|
||||
return nil
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
var _ conn.Resource = Dev(nil)
|
20
vendor/periph.io/x/host/v3/ftdi/doc.go
generated
vendored
20
vendor/periph.io/x/host/v3/ftdi/doc.go
generated
vendored
@ -1,20 +0,0 @@
|
||||
// Copyright 2017 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// Package ftdi implements support for popular FTDI devices.
|
||||
//
|
||||
// The supported devices (FT232h/FT232r) implement support for various
|
||||
// protocols like the GPIO, I²C, SPI, UART, JTAG.
|
||||
//
|
||||
// More details
|
||||
//
|
||||
// See https://periph.io/device/ftdi/ for more details, and how to configure
|
||||
// the host to be able to use this driver.
|
||||
//
|
||||
// Datasheets
|
||||
//
|
||||
// http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT232R.pdf
|
||||
//
|
||||
// http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT232H.pdf
|
||||
package ftdi
|
213
vendor/periph.io/x/host/v3/ftdi/driver.go
generated
vendored
213
vendor/periph.io/x/host/v3/ftdi/driver.go
generated
vendored
@ -1,213 +0,0 @@
|
||||
// Copyright 2018 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
package ftdi
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"periph.io/x/conn/v3/driver/driverreg"
|
||||
"periph.io/x/conn/v3/gpio"
|
||||
"periph.io/x/conn/v3/gpio/gpioreg"
|
||||
"periph.io/x/conn/v3/i2c"
|
||||
"periph.io/x/conn/v3/i2c/i2creg"
|
||||
"periph.io/x/conn/v3/pin"
|
||||
"periph.io/x/conn/v3/pin/pinreg"
|
||||
"periph.io/x/conn/v3/spi/spireg"
|
||||
"periph.io/x/d2xx"
|
||||
)
|
||||
|
||||
// All enumerates all the connected FTDI devices.
|
||||
func All() []Dev {
|
||||
drv.mu.Lock()
|
||||
defer drv.mu.Unlock()
|
||||
out := make([]Dev, len(drv.all))
|
||||
copy(out, drv.all)
|
||||
return out
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// open opens a FTDI device.
|
||||
//
|
||||
// Must be called with mu held.
|
||||
func open(opener func(i int) (d2xx.Handle, d2xx.Err), i int) (Dev, error) {
|
||||
h, err := openHandle(opener, i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := h.Init(); err != nil {
|
||||
// setupCommon() takes the device in its previous state. It could be in an
|
||||
// unexpected state, so try resetting it first.
|
||||
if err := h.Reset(); err != nil {
|
||||
_ = h.Close()
|
||||
return nil, err
|
||||
}
|
||||
if err := h.Init(); err != nil {
|
||||
_ = h.Close()
|
||||
return nil, err
|
||||
}
|
||||
// The second attempt worked.
|
||||
}
|
||||
// Makes a copy of the handle.
|
||||
g := generic{index: i, h: h, name: h.t.String()}
|
||||
if i > 0 {
|
||||
// When more than one device is present, add "(index)" suffix.
|
||||
// TODO(maruel): Using the serial number would be nicer than a number.
|
||||
g.name += "(" + strconv.Itoa(i) + ")"
|
||||
}
|
||||
// Makes a copy of the generic instance.
|
||||
switch g.h.t {
|
||||
case DevTypeFT232H:
|
||||
f, err := newFT232H(g)
|
||||
if err != nil {
|
||||
_ = h.Close()
|
||||
return nil, err
|
||||
}
|
||||
return f, nil
|
||||
case DevTypeFT2232H:
|
||||
f, err := newFT232H(g)
|
||||
if err != nil {
|
||||
_ = h.Close()
|
||||
return nil, err
|
||||
}
|
||||
return f, nil
|
||||
case DevTypeFT232R:
|
||||
f, err := newFT232R(g)
|
||||
if err != nil {
|
||||
_ = h.Close()
|
||||
return nil, err
|
||||
}
|
||||
return f, nil
|
||||
default:
|
||||
return &g, nil
|
||||
}
|
||||
}
|
||||
|
||||
// registerDev registers the header and supported buses and ports in the
|
||||
// relevant registries.
|
||||
func registerDev(d Dev, multi bool) error {
|
||||
name := d.String()
|
||||
hdr := d.Header()
|
||||
|
||||
// Register the GPIOs.
|
||||
for _, p := range hdr {
|
||||
if err := gpioreg.Register(p); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if !multi {
|
||||
// Register shorthands.
|
||||
// The "." used here vs the "_" used in pinreg is unfortunate. Investigate
|
||||
// a better way.
|
||||
prefix := len(name) + 1
|
||||
for _, p := range hdr {
|
||||
n := p.Name()
|
||||
if err := gpioreg.RegisterAlias(n[prefix:], n); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Register the header.
|
||||
raw := make([][]pin.Pin, len(hdr))
|
||||
for i := range hdr {
|
||||
raw[i] = []pin.Pin{hdr[i]}
|
||||
}
|
||||
if err := pinreg.Register(name, raw); err != nil {
|
||||
return err
|
||||
}
|
||||
switch t := d.(type) {
|
||||
case *FT232H:
|
||||
// Register I²C without pull up.
|
||||
if err := i2creg.Register(name, nil, -1, func() (i2c.BusCloser, error) { return t.I2C(gpio.Float) }); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := spireg.Register(name, nil, -1, t.SPI); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO(maruel): UART
|
||||
case *FT232R:
|
||||
// TODO(maruel): SPI, UART
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// driver implements driver.Impl.
|
||||
type driver struct {
|
||||
mu sync.Mutex
|
||||
all []Dev
|
||||
d2xxOpen func(i int) (d2xx.Handle, d2xx.Err)
|
||||
numDevices func() (int, error)
|
||||
}
|
||||
|
||||
func (d *driver) String() string {
|
||||
return "ftdi"
|
||||
}
|
||||
|
||||
func (d *driver) Prerequisites() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) After() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) Init() (bool, error) {
|
||||
num, err := d.numDevices()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
multi := num > 1
|
||||
for i := 0; i < num; i++ {
|
||||
// TODO(maruel): Close the device one day. :)
|
||||
if dev, err1 := open(d.d2xxOpen, i); err1 == nil {
|
||||
d.all = append(d.all, dev)
|
||||
if err = registerDev(dev, multi); err != nil {
|
||||
return true, err
|
||||
}
|
||||
} else {
|
||||
// Create a shallow broken handle, so the user can learn how to fix the
|
||||
// problem.
|
||||
//
|
||||
// TODO(maruel): On macOS with a FT232R, calling two processes in a row
|
||||
// often results in a broken device on the second process. Figure out why
|
||||
// and make it more resilient.
|
||||
err = err1
|
||||
// The serial number is not available so what can be listed is limited.
|
||||
// TODO(maruel): Add VID/PID?
|
||||
name := "broken#" + strconv.Itoa(i) + ": " + err.Error()
|
||||
d.all = append(d.all, &broken{index: i, err: err, name: name})
|
||||
}
|
||||
}
|
||||
return true, err
|
||||
}
|
||||
|
||||
func (d *driver) reset() {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
d.all = nil
|
||||
// open is mocked in tests.
|
||||
d.d2xxOpen = d2xx.Open
|
||||
// numDevices is mocked in tests.
|
||||
d.numDevices = numDevices
|
||||
|
||||
// The d2xx can hang for up to the timeout under certain circumstances and the
|
||||
// Go profiler is not very useful to find the source, so use manual logging
|
||||
// to see where time it spent.
|
||||
//d.d2xxOpen = func(i int) (d2xx.Handle, int) {
|
||||
// h, e := d2xxOpen(i)
|
||||
// return &d2xxLoggingHandle{h}, e
|
||||
//}
|
||||
}
|
||||
|
||||
func init() {
|
||||
if d2xx.Available {
|
||||
drv.reset()
|
||||
driverreg.MustRegister(&drv)
|
||||
}
|
||||
}
|
||||
|
||||
var drv driver
|
368
vendor/periph.io/x/host/v3/ftdi/eeprom.go
generated
vendored
368
vendor/periph.io/x/host/v3/ftdi/eeprom.go
generated
vendored
@ -1,368 +0,0 @@
|
||||
// Copyright 2018 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
package ftdi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// EEPROM is the unprocessed EEPROM content.
|
||||
//
|
||||
// The EEPROM is in 3 parts: the defined struct, the 4 strings and the rest
|
||||
// which is used as an 'user area'. The size of the user area depends on the
|
||||
// length of the strings. The user area content is not included in this struct.
|
||||
type EEPROM struct {
|
||||
// Raw is the raw EEPROM content. It excludes the strings.
|
||||
Raw []byte
|
||||
|
||||
// The following condition must be true: len(Manufacturer) + len(Desc) <= 40.
|
||||
Manufacturer string
|
||||
ManufacturerID string
|
||||
Desc string
|
||||
Serial string
|
||||
}
|
||||
|
||||
// Validate checks that the data is good.
|
||||
func (e *EEPROM) Validate() error {
|
||||
// Verify that the values are set correctly.
|
||||
if len(e.Manufacturer) > 40 {
|
||||
return errors.New("ftdi: Manufacturer is too long")
|
||||
}
|
||||
if len(e.ManufacturerID) > 40 {
|
||||
return errors.New("ftdi: ManufacturerID is too long")
|
||||
}
|
||||
if len(e.Desc) > 40 {
|
||||
return errors.New("ftdi: Desc is too long")
|
||||
}
|
||||
if len(e.Serial) > 40 {
|
||||
return errors.New("ftdi: Serial is too long")
|
||||
}
|
||||
if len(e.Manufacturer)+len(e.Desc) > 40 {
|
||||
return errors.New("ftdi: length of Manufacturer plus Desc is too long")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *EEPROM) AsHeader() *EEPROMHeader {
|
||||
// sizeof(EEPROMHeader)
|
||||
if len(e.Raw) < 16 {
|
||||
return nil
|
||||
}
|
||||
return (*EEPROMHeader)(unsafe.Pointer(&e.Raw[0]))
|
||||
}
|
||||
|
||||
// AsFT232H returns the Raw data aliased as EEPROMFT232H.
|
||||
func (e *EEPROM) AsFT232H() *EEPROMFT232H {
|
||||
// sizeof(EEPROMFT232H)
|
||||
if len(e.Raw) < 44 {
|
||||
return nil
|
||||
}
|
||||
return (*EEPROMFT232H)(unsafe.Pointer(&e.Raw[0]))
|
||||
}
|
||||
|
||||
// AsFT2232H returns the Raw data aliased as EEPROMFT2232H.
|
||||
func (e *EEPROM) AsFT2232H() *EEPROMFT2232H {
|
||||
// sizeof(EEPROMFT2232H)
|
||||
if len(e.Raw) < 40 {
|
||||
return nil
|
||||
}
|
||||
return (*EEPROMFT2232H)(unsafe.Pointer(&e.Raw[0]))
|
||||
}
|
||||
|
||||
// AsFT232R returns the Raw data aliased as EEPROMFT232R.
|
||||
func (e *EEPROM) AsFT232R() *EEPROMFT232R {
|
||||
// sizeof(EEPROMFT232R)
|
||||
if len(e.Raw) < 32 {
|
||||
return nil
|
||||
}
|
||||
return (*EEPROMFT232R)(unsafe.Pointer(&e.Raw[0]))
|
||||
}
|
||||
|
||||
// FT232hCBusMux is stored in the FT232H EEPROM to control each CBus pin.
|
||||
type FT232hCBusMux uint8
|
||||
|
||||
const (
|
||||
// TriSt-PU; Sets in Tristate (pull up) (C0~C6, C8, C9) on 75kΩ.
|
||||
FT232hCBusTristatePullUp FT232hCBusMux = 0x00
|
||||
// TXLED#; Pulses low when transmitting data (C0~C6, C8, C9).
|
||||
FT232hCBusTxLED FT232hCBusMux = 0x01
|
||||
// RXLED#; Pulses low when receiving data (C0~C6, C8, C9).
|
||||
FT232hCBusRxLED FT232hCBusMux = 0x02
|
||||
// TX&RXLED#; Pulses low when either receiving or transmitting data (C0~C6,
|
||||
// C8, C9).
|
||||
FT232hCBusTxRxLED FT232hCBusMux = 0x03
|
||||
// PWREN#; Output is low after the device has been configured by USB, then
|
||||
// high during USB suspend mode (C0~C6, C8, C9).
|
||||
//
|
||||
// Must be used with an external 10kΩ pull up.
|
||||
FT232hCBusPwrEnable FT232hCBusMux = 0x04
|
||||
// SLEEP#; Goes low during USB suspend mode (C0~C6, C8, C9).
|
||||
FT232hCBusSleep FT232hCBusMux = 0x05
|
||||
// DRIVE1; Drives pin to logic 0 (C0~C6, C8, C9).
|
||||
FT232hCBusDrive0 FT232hCBusMux = 0x06
|
||||
// DRIVE1; Drives pin to logic 1 (C0, C5, C6, C8, C9).
|
||||
FT232hCBusDrive1 FT232hCBusMux = 0x07
|
||||
// I/O Mode; CBus bit-bang mode option (C5, C6, C8, C9).
|
||||
FT232hCBusIOMode FT232hCBusMux = 0x08
|
||||
// TXDEN; Tx Data Enable. Used with RS485 level converters to enable the line
|
||||
// driver during data transmit. It is active one bit time before the start
|
||||
// bit up to until the end of the stop bit (C0~C6, C8, C9).
|
||||
FT232hCBusTxdEnable FT232hCBusMux = 0x09
|
||||
// CLK30 30MHz clock output (C0, C5, C6, C8, C9).
|
||||
FT232hCBusClk30 FT232hCBusMux = 0x0A
|
||||
// CLK15 15MHz clock output (C0, C5, C6, C8, C9).
|
||||
FT232hCBusClk15 FT232hCBusMux = 0x0B
|
||||
// CLK7.5 7.5MHz clock output (C0, C5, C6, C8, C9).
|
||||
FT232hCBusClk7_5 FT232hCBusMux = 0x0C
|
||||
)
|
||||
|
||||
const ft232hCBusMuxName = "FT232hCBusTristatePullUpFT232hCBusTxLEDFT232hCBusRxLEDFT232hCBusTxRxLEDFT232hCBusPwrEnableFT232hCBusSleepFT232hCBusDrive0FT232hCBusDrive1FT232hCBusIOModeFT232hCBusTxdEnableFT232hCBusClk30FT232hCBusClk15FT232hCBusClk7_5"
|
||||
|
||||
var fr232hCBusMuxIndex = [...]uint8{0, 24, 39, 54, 71, 90, 105, 121, 137, 153, 172, 187, 202, 218}
|
||||
|
||||
func (f FT232hCBusMux) String() string {
|
||||
if f >= FT232hCBusMux(len(fr232hCBusMuxIndex)-1) {
|
||||
return fmt.Sprintf("FT232hCBusMux(%d)", f)
|
||||
}
|
||||
return ft232hCBusMuxName[fr232hCBusMuxIndex[f]:fr232hCBusMuxIndex[f+1]]
|
||||
}
|
||||
|
||||
// FT232rCBusMux is stored in the FT232R EEPROM to control each CBus pin.
|
||||
type FT232rCBusMux uint8
|
||||
|
||||
const (
|
||||
// TXDEN; Tx Data Enable. Used with RS485 level converters to enable the line
|
||||
// driver during data transmit. It is active one bit time before the start
|
||||
// bit up to until the end of the stop bit (C0~C4).
|
||||
FT232rCBusTxdEnable FT232rCBusMux = 0x00
|
||||
// PWREN#; Output is low after the device has been configured by USB, then
|
||||
// high during USB suspend mode (C0~C4).
|
||||
//
|
||||
// Must be used with an external 10kΩ pull up.
|
||||
FT232rCBusPwrEnable FT232rCBusMux = 0x01
|
||||
// RXLED#; Pulses low when receiving data (C0~C4).
|
||||
FT232rCBusRxLED FT232rCBusMux = 0x02
|
||||
// TXLED#; Pulses low when transmitting data (C0~C4).
|
||||
FT232rCBusTxLED FT232rCBusMux = 0x03
|
||||
// TX&RXLED#; Pulses low when either receiving or transmitting data (C0~C4).
|
||||
FT232rCBusTxRxLED FT232rCBusMux = 0x04
|
||||
// SLEEP# Goes low during USB suspend mode (C0~C4).
|
||||
FT232rCBusSleep FT232rCBusMux = 0x05
|
||||
// CLK48 48Mhz +/-0.7% clock output (C0~C4).
|
||||
FT232rCBusClk48 FT232rCBusMux = 0x06
|
||||
// CLK24 24Mhz clock output (C0~C4).
|
||||
FT232rCBusClk24 FT232rCBusMux = 0x07
|
||||
// CLK12 12Mhz clock output (C0~C4).
|
||||
FT232rCBusClk12 FT232rCBusMux = 0x08
|
||||
// CLK6 6Mhz +/-0.7% clock output (C0~C4).
|
||||
FT232rCBusClk6 FT232rCBusMux = 0x09
|
||||
// CBitBangI/O; CBus bit-bang mode option (C0~C3).
|
||||
FT232rCBusIOMode FT232rCBusMux = 0x0A
|
||||
// BitBangWRn; CBus WR# strobe output (C0~C3).
|
||||
FT232rCBusBitBangWR FT232rCBusMux = 0x0B
|
||||
// BitBangRDn; CBus RD# strobe output (C0~C3).
|
||||
FT232rCBusBitBangRD FT232rCBusMux = 0x0C
|
||||
)
|
||||
|
||||
const ft232rCBusMuxName = "FT232rCBusTxdEnableFT232rCBusPwrEnableFT232rCBusRxLEDFT232rCBusTxLEDFT232rCBusTxRxLEDFT232rCBusSleepFT232rCBusClk48FT232rCBusClk24FT232rCBusClk12FT232rCBusClk6FT232rCBusIOModeFT232rCBusBitBangWRFT232rCBusBitBangRD"
|
||||
|
||||
var ft232rCBusMuxIndex = [...]uint8{0, 19, 38, 53, 68, 85, 100, 115, 130, 145, 159, 175, 194, 213}
|
||||
|
||||
func (f FT232rCBusMux) String() string {
|
||||
if f >= FT232rCBusMux(len(ft232rCBusMuxIndex)-1) {
|
||||
return fmt.Sprintf("FT232rCBusMux(%d)", f)
|
||||
}
|
||||
return ft232rCBusMuxName[ft232rCBusMuxIndex[f]:ft232rCBusMuxIndex[f+1]]
|
||||
}
|
||||
|
||||
// EEPROMHeader is the common header found on FTDI devices.
|
||||
//
|
||||
// It is 16 bytes long.
|
||||
type EEPROMHeader struct {
|
||||
DeviceType DevType // 0x00 FTxxxx device type to be programmed
|
||||
VendorID uint16 // 0x04 Defaults to 0x0403; can be changed
|
||||
ProductID uint16 // 0x06 Defaults to 0x6001 for FT232R, 0x6014 for FT232H, relevant value
|
||||
SerNumEnable uint8 // 0x07 bool Non-zero if serial number to be used
|
||||
Unused0 uint8 // 0x08 For alignment.
|
||||
MaxPower uint16 // 0x0A 0mA < MaxPower <= 500mA
|
||||
SelfPowered uint8 // 0x0C bool 0 = bus powered, 1 = self powered
|
||||
RemoteWakeup uint8 // 0x0D bool 0 = not capable, 1 = capable; RI# low will wake host in 20ms.
|
||||
PullDownEnable uint8 // 0x0E bool Non zero if pull down in suspend enabled
|
||||
Unused1 uint8 // 0x0F For alignment.
|
||||
}
|
||||
|
||||
// EEPROMFT232H is the EEPROM layout of a FT232H device.
|
||||
//
|
||||
// It is 44 bytes long.
|
||||
type EEPROMFT232H struct {
|
||||
EEPROMHeader
|
||||
|
||||
// FT232H specific.
|
||||
ACSlowSlew uint8 // 0x10 bool Non-zero if AC bus pins have slow slew
|
||||
ACSchmittInput uint8 // 0x11 bool Non-zero if AC bus pins are Schmitt input
|
||||
ACDriveCurrent uint8 // 0x12 Valid values are 4mA, 8mA, 12mA, 16mA in 2mA units
|
||||
ADSlowSlew uint8 // 0x13 bool Non-zero if AD bus pins have slow slew
|
||||
ADSchmittInput uint8 // 0x14 bool Non-zero if AD bus pins are Schmitt input
|
||||
ADDriveCurrent uint8 // 0x15 Valid values are 4mA, 8mA, 12mA, 16mA in 2mA units
|
||||
Cbus0 FT232hCBusMux // 0x16
|
||||
Cbus1 FT232hCBusMux // 0x17
|
||||
Cbus2 FT232hCBusMux // 0x18
|
||||
Cbus3 FT232hCBusMux // 0x19
|
||||
Cbus4 FT232hCBusMux // 0x1A
|
||||
Cbus5 FT232hCBusMux // 0x1B
|
||||
Cbus6 FT232hCBusMux // 0x1C
|
||||
Cbus7 FT232hCBusMux // 0x1D C7 is limited a sit can only do 'suspend on C7 low'. Defaults pull down.
|
||||
Cbus8 FT232hCBusMux // 0x1E
|
||||
Cbus9 FT232hCBusMux // 0x1F
|
||||
FT1248Cpol uint8 // 0x20 bool FT1248 clock polarity - clock idle high (true) or clock idle low (false)
|
||||
FT1248Lsb uint8 // 0x21 bool FT1248 data is LSB (true), or MSB (false)
|
||||
FT1248FlowControl uint8 // 0x22 bool FT1248 flow control enable
|
||||
IsFifo uint8 // 0x23 bool Non-zero if Interface is 245 FIFO
|
||||
IsFifoTar uint8 // 0x24 bool Non-zero if Interface is 245 FIFO CPU target
|
||||
IsFastSer uint8 // 0x25 bool Non-zero if Interface is Fast serial
|
||||
IsFT1248 uint8 // 0x26 bool Non-zero if Interface is FT1248
|
||||
PowerSaveEnable uint8 // 0x27 bool Suspect on ACBus7 low.
|
||||
DriverType uint8 // 0x28 bool 0 is D2XX, 1 is VCP
|
||||
Unused2 uint8 // 0x29
|
||||
Unused3 uint16 // 0x30
|
||||
}
|
||||
|
||||
func (e *EEPROMFT232H) Defaults() {
|
||||
// As found on Adafruit device.
|
||||
e.ACDriveCurrent = 4
|
||||
e.ADDriveCurrent = 4
|
||||
e.Cbus0 = FT232hCBusTristatePullUp
|
||||
e.Cbus1 = FT232hCBusTristatePullUp
|
||||
e.Cbus2 = FT232hCBusTristatePullUp
|
||||
e.Cbus3 = FT232hCBusTristatePullUp
|
||||
e.Cbus4 = FT232hCBusTristatePullUp
|
||||
e.Cbus5 = FT232hCBusTristatePullUp
|
||||
e.Cbus6 = FT232hCBusTristatePullUp
|
||||
e.Cbus7 = FT232hCBusTristatePullUp
|
||||
e.Cbus8 = FT232hCBusDrive1
|
||||
e.Cbus9 = FT232hCBusDrive0
|
||||
}
|
||||
|
||||
// EEPROMFT2232H is the EEPROM layout of a FT2232H device.
|
||||
//
|
||||
// It is 40 bytes long.
|
||||
type EEPROMFT2232H struct {
|
||||
EEPROMHeader
|
||||
|
||||
// FT232H specific.
|
||||
ALSlowSlew uint8 // 0x10 bool non-zero if AL pins have slow slew
|
||||
ALSchmittInput uint8 // 0x11 bool non-zero if AL pins are Schmitt input
|
||||
ALDriveCurrent uint8 // 0x12 Valid values are 4mA, 8mA, 12mA, 16mA in 2mA units
|
||||
AHSlowSlew uint8 // 0x13 bool non-zero if AH pins have slow slew
|
||||
AHSchmittInput uint8 // 0x14 bool non-zero if AH pins are Schmitt input
|
||||
AHDriveCurrent uint8 // 0x15 Valid values are 4mA, 8mA, 12mA, 16mA in 2mA units
|
||||
BLSlowSlew uint8 // 0x16 bool non-zero if BL pins have slow slew
|
||||
BLSchmittInput uint8 // 0x17 bool non-zero if BL pins are Schmitt input
|
||||
BLDriveCurrent uint8 // 0x18 Valid values are 4mA, 8mA, 12mA, 16mA in 2mA units
|
||||
BHSlowSlew uint8 // 0x19 bool non-zero if BH pins have slow slew
|
||||
BHSchmittInput uint8 // 0x1A bool non-zero if BH pins are Schmitt input
|
||||
BHDriveCurrent uint8 // 0x1B Valid values are 4mA, 8mA, 12mA, 16mA in 2mA units
|
||||
AIsFifo uint8 // 0x1C bool non-zero if interface is 245 FIFO
|
||||
AIsFifoTar uint8 // 0x1D bool non-zero if interface is 245 FIFO CPU target
|
||||
AIsFastSer uint8 // 0x1E bool non-zero if interface is Fast serial
|
||||
BIsFifo uint8 // 0x1F bool non-zero if interface is 245 FIFO
|
||||
BIsFifoTar uint8 // 0x20 bool non-zero if interface is 245 FIFO CPU target
|
||||
BIsFastSer uint8 // 0x21 bool non-zero if interface is Fast serial
|
||||
PowerSaveEnable uint8 // 0x22 bool non-zero if using BCBUS7 to save power for self-powered designs
|
||||
ADriverType uint8 // 0x23 bool
|
||||
BDriverType uint8 // 0x24 bool
|
||||
Unused2 uint8 // 0x25
|
||||
Unused3 uint16 // 0x26
|
||||
}
|
||||
|
||||
// EEPROMFT232R is the EEPROM layout of a FT232R device.
|
||||
//
|
||||
// It is 32 bytes long.
|
||||
type EEPROMFT232R struct {
|
||||
EEPROMHeader
|
||||
|
||||
// FT232R specific.
|
||||
IsHighCurrent uint8 // 0x10 bool High Drive I/Os; 3mA instead of 1mA (@3.3V)
|
||||
UseExtOsc uint8 // 0x11 bool Use external oscillator
|
||||
InvertTXD uint8 // 0x12 bool
|
||||
InvertRXD uint8 // 0x13 bool
|
||||
InvertRTS uint8 // 0x14 bool
|
||||
InvertCTS uint8 // 0x15 bool
|
||||
InvertDTR uint8 // 0x16 bool
|
||||
InvertDSR uint8 // 0x17 bool
|
||||
InvertDCD uint8 // 0x18 bool
|
||||
InvertRI uint8 // 0x19 bool
|
||||
Cbus0 FT232rCBusMux // 0x1A Default ft232rCBusTxLED
|
||||
Cbus1 FT232rCBusMux // 0x1B Default ft232rCBusRxLED
|
||||
Cbus2 FT232rCBusMux // 0x1C Default ft232rCBusTxdEnable
|
||||
Cbus3 FT232rCBusMux // 0x1D Default ft232rCBusPwrEnable
|
||||
Cbus4 FT232rCBusMux // 0x1E Default ft232rCBusSleep
|
||||
DriverType uint8 // 0x1F bool 0 is D2XX, 1 is VCP
|
||||
}
|
||||
|
||||
func (e *EEPROMFT232R) Defaults() {
|
||||
// As found on Adafruit device.
|
||||
e.Cbus0 = FT232rCBusTxLED
|
||||
e.Cbus1 = FT232rCBusRxLED
|
||||
e.Cbus2 = FT232rCBusTxdEnable
|
||||
e.Cbus3 = FT232rCBusPwrEnable
|
||||
e.Cbus4 = FT232rCBusSleep
|
||||
e.DriverType = 1
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// DevType is the FTDI device type.
|
||||
type DevType uint32
|
||||
|
||||
const (
|
||||
DevTypeFTBM DevType = iota // 0
|
||||
DevTypeFTAM
|
||||
DevTypeFT100AX
|
||||
DevTypeUnknown // 3
|
||||
DevTypeFT2232C
|
||||
DevTypeFT232R // 5
|
||||
DevTypeFT2232H
|
||||
DevTypeFT4232H
|
||||
DevTypeFT232H // 8
|
||||
DevTypeFTXSeries
|
||||
DevTypeFT4222H0
|
||||
DevTypeFT4222H1_2
|
||||
DevTypeFT4222H3
|
||||
DevTypeFT4222Prog
|
||||
DevTypeFT900
|
||||
DevTypeFT930
|
||||
DevTypeFTUMFTPD3A
|
||||
)
|
||||
|
||||
// EEPROMSize returns the size of the EEPROM for this device.
|
||||
func (d DevType) EEPROMSize() int {
|
||||
switch d {
|
||||
case DevTypeFT232H:
|
||||
// sizeof(EEPROMFT232H)
|
||||
return 44
|
||||
case DevTypeFT2232H:
|
||||
// sizeof(EEPROMFT2232H)
|
||||
return 40
|
||||
case DevTypeFT232R:
|
||||
// sizeof(EEPROMFT232R)
|
||||
return 32
|
||||
default:
|
||||
return 256
|
||||
}
|
||||
}
|
||||
|
||||
const devTypeName = "FTBMFTAMFT100AXUnknownFT2232CFT232RFT2232HFT4232HFT232HFTXSeriesFT4222H0FT4222H1/2FT4222H3FT4222ProgFT900FT930FTUMFTPD3A"
|
||||
|
||||
var devTypeIndex = [...]uint8{0, 4, 8, 15, 22, 29, 35, 42, 49, 55, 64, 72, 82, 90, 100, 105, 110, 120}
|
||||
|
||||
func (d DevType) String() string {
|
||||
if d >= DevType(len(devTypeIndex)-1) {
|
||||
d = DevTypeUnknown
|
||||
}
|
||||
return devTypeName[devTypeIndex[d]:devTypeIndex[d+1]]
|
||||
}
|
5
vendor/periph.io/x/host/v3/ftdi/ftdi.go
generated
vendored
5
vendor/periph.io/x/host/v3/ftdi/ftdi.go
generated
vendored
@ -1,5 +0,0 @@
|
||||
// Copyright 2021 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
package ftdi
|
241
vendor/periph.io/x/host/v3/ftdi/gpio.go
generated
vendored
241
vendor/periph.io/x/host/v3/ftdi/gpio.go
generated
vendored
@ -1,241 +0,0 @@
|
||||
// Copyright 2017 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// Emulate independent GPIOs.
|
||||
|
||||
package ftdi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"periph.io/x/conn/v3/gpio"
|
||||
"periph.io/x/conn/v3/physic"
|
||||
)
|
||||
|
||||
// dbusSync is the handler of a synchronous bitbang on DBus.
|
||||
//
|
||||
// More details at:
|
||||
// http://www.ftdichip.com/Support/Documents/AppNotes/AN_232R-01_Bit_Bang_Mode_Available_For_FT232R_and_Ft245R.pdf
|
||||
type dbusSync interface {
|
||||
dbusSyncGPIOFunc(n int) string
|
||||
dbusSyncGPIOIn(n int) error
|
||||
dbusSyncGPIORead(n int) gpio.Level
|
||||
dbusSyncGPIOOut(n int, l gpio.Level) error
|
||||
}
|
||||
|
||||
// dbusPinSync represents a GPIO on a synchronous bitbang DBus.
|
||||
//
|
||||
// It is immutable and stateless.
|
||||
type dbusPinSync struct {
|
||||
n string
|
||||
num int
|
||||
bus dbusSync
|
||||
}
|
||||
|
||||
// String implements conn.Resource.
|
||||
func (s *dbusPinSync) String() string {
|
||||
return s.n
|
||||
}
|
||||
|
||||
// Halt implements conn.Resource.
|
||||
func (s *dbusPinSync) Halt() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Name implements pin.Pin.
|
||||
func (s *dbusPinSync) Name() string {
|
||||
return s.n
|
||||
}
|
||||
|
||||
// Number implements pin.Pin.
|
||||
func (s *dbusPinSync) Number() int {
|
||||
return s.num
|
||||
}
|
||||
|
||||
// Function implements pin.Pin.
|
||||
func (s *dbusPinSync) Function() string {
|
||||
return s.bus.dbusSyncGPIOFunc(s.num)
|
||||
}
|
||||
|
||||
// In implements gpio.PinIn.
|
||||
func (s *dbusPinSync) In(pull gpio.Pull, e gpio.Edge) error {
|
||||
if e != gpio.NoEdge {
|
||||
// We could support it on D5.
|
||||
return errors.New("d2xx: edge triggering is not supported")
|
||||
}
|
||||
if pull != gpio.PullUp && pull != gpio.PullNoChange {
|
||||
// EEPROM has a PullDownEnable flag.
|
||||
return errors.New("d2xx: pull is not supported")
|
||||
}
|
||||
return s.bus.dbusSyncGPIOIn(s.num)
|
||||
}
|
||||
|
||||
// Read implements gpio.PinIn.
|
||||
func (s *dbusPinSync) Read() gpio.Level {
|
||||
return s.bus.dbusSyncGPIORead(s.num)
|
||||
}
|
||||
|
||||
// WaitForEdge implements gpio.PinIn.
|
||||
func (s *dbusPinSync) WaitForEdge(t time.Duration) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// DefaultPull implements gpio.PinIn.
|
||||
func (s *dbusPinSync) DefaultPull() gpio.Pull {
|
||||
// 200kΩ
|
||||
// http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT232R.pdf
|
||||
// p. 24
|
||||
return gpio.PullUp
|
||||
}
|
||||
|
||||
// Pull implements gpio.PinIn.
|
||||
func (s *dbusPinSync) Pull() gpio.Pull {
|
||||
return gpio.PullUp
|
||||
}
|
||||
|
||||
// Out implements gpio.PinOut.
|
||||
func (s *dbusPinSync) Out(l gpio.Level) error {
|
||||
return s.bus.dbusSyncGPIOOut(s.num, l)
|
||||
}
|
||||
|
||||
// PWM implements gpio.PinOut.
|
||||
func (s *dbusPinSync) PWM(d gpio.Duty, f physic.Frequency) error {
|
||||
return errors.New("d2xx: not implemented")
|
||||
}
|
||||
|
||||
/*
|
||||
func (s *dbusPinSync) Drive() physic.ElectricCurrent {
|
||||
// optionally 3
|
||||
//return s.bus.ee.DDriveCurrent * physic.MilliAmpere
|
||||
return physic.MilliAmpere
|
||||
}
|
||||
|
||||
func (s *dbusPinSync) SlewLimit() bool {
|
||||
//return s.bus.ee.DSlowSlew
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *dbusPinSync) Hysteresis() bool {
|
||||
//return s.bus.ee.DSchmittInput
|
||||
return true
|
||||
}
|
||||
*/
|
||||
|
||||
//
|
||||
|
||||
// cBusGPIO is the handler of a CBus bitbang bus.
|
||||
//
|
||||
// This is an asynchronous mode.
|
||||
//
|
||||
// More details at:
|
||||
// http://www.ftdichip.com/Support/Knowledgebase/index.html?cbusbitbangmode.htm
|
||||
type cBusGPIO interface {
|
||||
cBusGPIOFunc(n int) string
|
||||
cBusGPIOIn(n int) error
|
||||
cBusGPIORead(n int) gpio.Level
|
||||
cBusGPIOOut(n int, l gpio.Level) error
|
||||
}
|
||||
|
||||
// cbusPin represents a GPIO on a CBus bitbang bus.
|
||||
//
|
||||
// It is immutable and stateless.
|
||||
type cbusPin struct {
|
||||
n string
|
||||
num int
|
||||
p gpio.Pull
|
||||
bus cBusGPIO
|
||||
}
|
||||
|
||||
// String implements conn.Resource.
|
||||
func (c *cbusPin) String() string {
|
||||
return c.n
|
||||
}
|
||||
|
||||
// Halt implements conn.Resource.
|
||||
func (c *cbusPin) Halt() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Name implements pin.Pin.
|
||||
func (c *cbusPin) Name() string {
|
||||
return c.n
|
||||
}
|
||||
|
||||
// Number implements pin.Pin.
|
||||
func (c *cbusPin) Number() int {
|
||||
return c.num
|
||||
}
|
||||
|
||||
// Function implements pin.Pin.
|
||||
func (c *cbusPin) Function() string {
|
||||
return c.bus.cBusGPIOFunc(c.num)
|
||||
}
|
||||
|
||||
// In implements gpio.PinIn.
|
||||
func (c *cbusPin) In(pull gpio.Pull, e gpio.Edge) error {
|
||||
if e != gpio.NoEdge {
|
||||
// We could support it on D5.
|
||||
return errors.New("d2xx: edge triggering is not supported")
|
||||
}
|
||||
if pull != c.p && pull != gpio.PullNoChange {
|
||||
// EEPROM has a PullDownEnable flag.
|
||||
return errors.New("d2xx: pull is not supported")
|
||||
}
|
||||
return c.bus.cBusGPIOIn(c.num)
|
||||
}
|
||||
|
||||
// Read implements gpio.PinIn.
|
||||
func (c *cbusPin) Read() gpio.Level {
|
||||
return c.bus.cBusGPIORead(c.num)
|
||||
}
|
||||
|
||||
// WaitForEdge implements gpio.PinIn.
|
||||
func (c *cbusPin) WaitForEdge(t time.Duration) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// DefaultPull implements gpio.PinIn.
|
||||
func (c *cbusPin) DefaultPull() gpio.Pull {
|
||||
// 200kΩ
|
||||
// http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT232R.pdf
|
||||
// p. 24
|
||||
return c.p
|
||||
}
|
||||
|
||||
// Pull implements gpio.PinIn.
|
||||
func (c *cbusPin) Pull() gpio.Pull {
|
||||
return c.p
|
||||
}
|
||||
|
||||
// Out implements gpio.PinOut.
|
||||
func (c *cbusPin) Out(l gpio.Level) error {
|
||||
return c.bus.cBusGPIOOut(c.num, l)
|
||||
}
|
||||
|
||||
// PWM implements gpio.PinOut.
|
||||
func (c *cbusPin) PWM(d gpio.Duty, f physic.Frequency) error {
|
||||
return errors.New("d2xx: not implemented")
|
||||
}
|
||||
|
||||
/*
|
||||
func (c *cbusPin) Drive() physic.ElectricCurrent {
|
||||
// optionally 3
|
||||
//return c.bus.ee.CDriveCurrent * physic.MilliAmpere
|
||||
return physic.MilliAmpere
|
||||
}
|
||||
|
||||
func (c *cbusPin) SlewLimit() bool {
|
||||
//return c.bus.ee.CSlowSlew
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *cbusPin) Hysteresis() bool {
|
||||
//return c.bus.ee.CSchmittInput
|
||||
return true
|
||||
}
|
||||
*/
|
||||
|
||||
var _ gpio.PinIO = &dbusPinSync{}
|
||||
var _ gpio.PinIO = &cbusPin{}
|
382
vendor/periph.io/x/host/v3/ftdi/handle.go
generated
vendored
382
vendor/periph.io/x/host/v3/ftdi/handle.go
generated
vendored
@ -1,382 +0,0 @@
|
||||
// Copyright 2021 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
package ftdi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"periph.io/x/conn/v3/physic"
|
||||
"periph.io/x/d2xx"
|
||||
)
|
||||
|
||||
//
|
||||
|
||||
// bitMode is used by SetBitMode to change the chip behavior.
|
||||
type bitMode uint8
|
||||
|
||||
const (
|
||||
// Resets all Pins to their default value
|
||||
bitModeReset bitMode = 0x00
|
||||
// Sets the DBus to asynchronous bit-bang.
|
||||
bitModeAsyncBitbang bitMode = 0x01
|
||||
// Switch to MPSSE mode (FT2232, FT2232H, FT4232H and FT232H).
|
||||
bitModeMpsse bitMode = 0x02
|
||||
// Sets the DBus to synchronous bit-bang (FT232R, FT245R, FT2232, FT2232H,
|
||||
// FT4232H and FT232H).
|
||||
bitModeSyncBitbang bitMode = 0x04
|
||||
// Switch to MCU host bus emulation (FT2232, FT2232H, FT4232H and FT232H).
|
||||
bitModeMcuHost bitMode = 0x08
|
||||
// Switch to fast opto-isolated serial mode (FT2232, FT2232H, FT4232H and
|
||||
// FT232H).
|
||||
bitModeFastSerial bitMode = 0x10
|
||||
// Sets the CBus in 4 bits bit-bang mode (FT232R and FT232H)
|
||||
// In this case, upper nibble controls which pin is output/input, lower
|
||||
// controls which of outputs are high and low.
|
||||
bitModeCbusBitbang bitMode = 0x20
|
||||
// Single Channel Synchronous 245 FIFO mode (FT2232H and FT232H).
|
||||
bitModeSyncFifo bitMode = 0x40
|
||||
)
|
||||
|
||||
// numDevices returns the number of detected devices.
|
||||
func numDevices() (int, error) {
|
||||
num, e := d2xx.CreateDeviceInfoList()
|
||||
if e != 0 {
|
||||
return 0, toErr("GetNumDevices initialization failed", e)
|
||||
}
|
||||
return num, nil
|
||||
}
|
||||
|
||||
func openHandle(opener func(i int) (d2xx.Handle, d2xx.Err), i int) (*handle, error) {
|
||||
h, e := opener(i)
|
||||
if e != 0 {
|
||||
return nil, toErr("Open", e)
|
||||
}
|
||||
d := &handle{h: h}
|
||||
t, vid, did, e := h.GetDeviceInfo()
|
||||
if e != 0 {
|
||||
_ = d.Close()
|
||||
return nil, toErr("GetDeviceInfo", e)
|
||||
}
|
||||
d.t = DevType(t)
|
||||
d.venID = vid
|
||||
d.devID = did
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// handle is a thin wrapper around the low level d2xx device handle to make it
|
||||
// more go-idiomatic.
|
||||
//
|
||||
// It also implements many utility functions to help with initialization and
|
||||
// device management.
|
||||
type handle struct {
|
||||
// It is just above 'handle' which directly maps to D2XX function calls.
|
||||
//
|
||||
// Dev converts the int error type into Go native error and handles higher
|
||||
// level functionality like reading and writing to the USB connection.
|
||||
//
|
||||
// The content of the struct is immutable after initialization.
|
||||
h d2xx.Handle
|
||||
t DevType
|
||||
venID uint16
|
||||
devID uint16
|
||||
}
|
||||
|
||||
func (h *handle) Close() error {
|
||||
// Not yet called.
|
||||
return toErr("Close", h.h.Close())
|
||||
}
|
||||
|
||||
// Init is the general setup for common devices.
|
||||
//
|
||||
// It tries first the 'happy path' which doesn't reset the device. By doing so,
|
||||
// the goal is to reduce the amount of glitches on the GPIO pins, on a best
|
||||
// effort basis. On all devices, the GPIOs are still reset as inputs, since
|
||||
// there is no way to determine if each GPIO is an input or output.
|
||||
func (h *handle) Init() error {
|
||||
// Driver: maximum packet size. Note that this clears any data in the buffer,
|
||||
// so it is good to do it immediately after a reset. The 'out' parameter is
|
||||
// ignored.
|
||||
// TODO(maruel): The FT232H doc claims a 512 byte packets support in hi-speed
|
||||
// mode, which means that this would likely be better to use this value.
|
||||
if e := h.h.SetUSBParameters(65536, 0); e != 0 {
|
||||
return toErr("SetUSBParameters", e)
|
||||
}
|
||||
// Driver: Set I/O timeouts to 15 sec. The reason is that we want the
|
||||
// timeouts to be very visible, at least as the driver is being developed.
|
||||
if e := h.h.SetTimeouts(15000, 15000); e != 0 {
|
||||
return toErr("SetTimeouts", e)
|
||||
}
|
||||
// Not sure: Disable event/error characters.
|
||||
if e := h.h.SetChars(0, false, 0, false); e != 0 {
|
||||
return toErr("SetChars", e)
|
||||
}
|
||||
// Not sure: Latency timer at 1ms.
|
||||
if e := h.h.SetLatencyTimer(1); e != 0 {
|
||||
return toErr("SetLatencyTimer", e)
|
||||
}
|
||||
// Not sure: Turn on flow control to synchronize IN requests.
|
||||
if e := h.h.SetFlowControl(); e != 0 {
|
||||
return toErr("SetFlowControl", e)
|
||||
}
|
||||
// Just in case. It's a very small cost.
|
||||
return h.Flush()
|
||||
}
|
||||
|
||||
// Reset resets the device.
|
||||
func (h *handle) Reset() error {
|
||||
if e := h.h.ResetDevice(); e != 0 {
|
||||
return toErr("Reset", e)
|
||||
}
|
||||
if err := h.SetBitMode(0, bitModeReset); err != nil {
|
||||
return err
|
||||
}
|
||||
// USB/driver: Flush any pending read buffer that had been sent by the device
|
||||
// before it reset. Do not return any error there, as the device may spew a
|
||||
// read error right after being initialized.
|
||||
_ = h.Flush()
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetBitMode returns the current bit mode.
|
||||
//
|
||||
// This is device-dependent.
|
||||
func (h *handle) GetBitMode() (byte, error) {
|
||||
l, e := h.h.GetBitMode()
|
||||
if e != 0 {
|
||||
return 0, toErr("GetBitMode", e)
|
||||
}
|
||||
return l, nil
|
||||
}
|
||||
|
||||
// SetBitMode change the mode of operation of the device.
|
||||
//
|
||||
// mask sets which pins are inputs and outputs for bitModeCbusBitbang.
|
||||
func (h *handle) SetBitMode(mask byte, mode bitMode) error {
|
||||
return toErr("SetBitMode", h.h.SetBitMode(mask, byte(mode)))
|
||||
}
|
||||
|
||||
// Flush flushes any data left in the read buffer.
|
||||
func (h *handle) Flush() error {
|
||||
var buf [128]byte
|
||||
for {
|
||||
p, err := h.Read(buf[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if p == 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read returns as much as available in the read buffer without blocking.
|
||||
func (h *handle) Read(b []byte) (int, error) {
|
||||
// GetQueueStatus() 60µs is relatively slow compared to Read() 4µs,
|
||||
// but surprisingly if GetQueueStatus() is *not* called, Read()
|
||||
// becomes largely slower (800µs).
|
||||
//
|
||||
// TODO(maruel): This asks for more perf testing before settling on the best
|
||||
// solution.
|
||||
// TODO(maruel): Investigate FT_GetStatus().
|
||||
p, e := h.h.GetQueueStatus()
|
||||
if p == 0 || e != 0 {
|
||||
return int(p), toErr("Read/GetQueueStatus", e)
|
||||
}
|
||||
v := int(p)
|
||||
if v > len(b) {
|
||||
v = len(b)
|
||||
}
|
||||
n, e := h.h.Read(b[:v])
|
||||
return n, toErr("Read", e)
|
||||
}
|
||||
|
||||
// ReadAll blocks to return all the data.
|
||||
//
|
||||
// Similar to ioutil.ReadAll() except that it will stop if the context is
|
||||
// canceled.
|
||||
func (h *handle) ReadAll(ctx context.Context, b []byte) (int, error) {
|
||||
// TODO(maruel): Use FT_SetEventNotification() instead of looping when
|
||||
// waiting for bytes.
|
||||
for offset := 0; offset != len(b); {
|
||||
if ctx.Err() != nil {
|
||||
return offset, io.EOF
|
||||
}
|
||||
chunk := len(b) - offset
|
||||
if chunk > 4096 {
|
||||
chunk = 4096
|
||||
}
|
||||
n, err := h.Read(b[offset : offset+chunk])
|
||||
if offset += n; err != nil {
|
||||
return offset, err
|
||||
}
|
||||
}
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
// WriteFast writes to the USB device.
|
||||
//
|
||||
// In practice this takes at least 0.1ms, which limits the effective rate.
|
||||
//
|
||||
// There's no guarantee that the data is all written, so it is important to
|
||||
// check the return value.
|
||||
func (h *handle) WriteFast(b []byte) (int, error) {
|
||||
n, e := h.h.Write(b)
|
||||
return n, toErr("Write", e)
|
||||
}
|
||||
|
||||
// Write blocks until all data is written.
|
||||
func (h *handle) Write(b []byte) (int, error) {
|
||||
for offset := 0; offset != len(b); {
|
||||
chunk := len(b) - offset
|
||||
if chunk > 4096 {
|
||||
chunk = 4096
|
||||
}
|
||||
p, err := h.WriteFast(b[offset : offset+chunk])
|
||||
if err != nil {
|
||||
return offset + p, err
|
||||
}
|
||||
if p != 0 {
|
||||
offset += p
|
||||
}
|
||||
}
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
// ReadEEPROM reads the EEPROM.
|
||||
func (h *handle) ReadEEPROM(ee *EEPROM) error {
|
||||
// The raw data size must be exactly what the device contains.
|
||||
eepromSize := h.t.EEPROMSize()
|
||||
if len(ee.Raw) < eepromSize {
|
||||
ee.Raw = make([]byte, eepromSize)
|
||||
} else if len(ee.Raw) > eepromSize {
|
||||
ee.Raw = ee.Raw[:eepromSize]
|
||||
}
|
||||
ee2 := d2xx.EEPROM{Raw: ee.Raw}
|
||||
e := h.h.EEPROMRead(uint32(h.t), &ee2)
|
||||
ee.Manufacturer = ee2.Manufacturer
|
||||
ee.ManufacturerID = ee2.ManufacturerID
|
||||
ee.Desc = ee2.Desc
|
||||
ee.Serial = ee2.Serial
|
||||
if e != 0 {
|
||||
// 15 == FT_EEPROM_NOT_PROGRAMMED
|
||||
if e != 15 {
|
||||
return toErr("EEPROMRead", e)
|
||||
}
|
||||
// It's a fresh new device. Devices bought via Adafruit already have
|
||||
// their EEPROM programmed with Adafruit branding but fake devices sold by
|
||||
// CJMCU are not. Since GetDeviceInfo() above succeeded, we know the
|
||||
// device type via the USB descriptor, which is sufficient to load the
|
||||
// driver, which permits to program the EEPROM to "bootstrap" it.
|
||||
//
|
||||
// Fill it with an empty yet valid EEPROM content. We don't want to set
|
||||
// VenID or DevID to 0! Nobody would do that, right?
|
||||
ee.Raw = make([]byte, h.t.EEPROMSize())
|
||||
hdr := ee.AsHeader()
|
||||
hdr.DeviceType = h.t
|
||||
hdr.VendorID = h.venID
|
||||
hdr.ProductID = h.devID
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteEEPROM programs the EEPROM.
|
||||
func (h *handle) WriteEEPROM(ee *EEPROM) error {
|
||||
if err := ee.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(ee.Raw) != 0 {
|
||||
hdr := ee.AsHeader()
|
||||
if hdr == nil {
|
||||
return errors.New("ftdi: unexpected EEPROM header size")
|
||||
}
|
||||
if hdr.DeviceType != h.t {
|
||||
return errors.New("ftdi: unexpected device type set while programming EEPROM")
|
||||
}
|
||||
if hdr.VendorID != h.venID {
|
||||
return errors.New("ftdi: unexpected VenID set while programming EEPROM")
|
||||
}
|
||||
if hdr.ProductID != h.devID {
|
||||
return errors.New("ftdi: unexpected DevID set while programming EEPROM")
|
||||
}
|
||||
}
|
||||
ee2 := d2xx.EEPROM{
|
||||
Raw: ee.Raw,
|
||||
Manufacturer: ee.Manufacturer,
|
||||
ManufacturerID: ee.ManufacturerID,
|
||||
Desc: ee.Desc,
|
||||
Serial: ee.Serial,
|
||||
}
|
||||
return toErr("EEPROMWrite", h.h.EEPROMProgram(&ee2))
|
||||
}
|
||||
|
||||
// EraseEEPROM erases all the EEPROM.
|
||||
//
|
||||
// Will fail on FT232R and FT245R.
|
||||
func (h *handle) EraseEEPROM() error {
|
||||
return toErr("EraseEE", h.h.EraseEE())
|
||||
}
|
||||
|
||||
// ReadUA reads the EEPROM user area.
|
||||
//
|
||||
// May return nil when there's nothing programmed yet.
|
||||
func (h *handle) ReadUA() ([]byte, error) {
|
||||
size, e := h.h.EEUASize()
|
||||
if e != 0 {
|
||||
return nil, toErr("EEUASize", e)
|
||||
}
|
||||
if size == 0 {
|
||||
// Happens on uninitialized EEPROM.
|
||||
return nil, nil
|
||||
}
|
||||
b := make([]byte, size)
|
||||
if e := h.h.EEUARead(b); e != 0 {
|
||||
return nil, toErr("EEUARead", e)
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// WriteUA writes to the EEPROM user area.
|
||||
func (h *handle) WriteUA(ua []byte) error {
|
||||
size, e := h.h.EEUASize()
|
||||
if e != 0 {
|
||||
return toErr("EEUASize", e)
|
||||
}
|
||||
if size == 0 {
|
||||
return errors.New("ftdi: please program EEPROM first")
|
||||
}
|
||||
if size < len(ua) {
|
||||
return fmt.Errorf("ftdi: maximum user area size is %d bytes", size)
|
||||
}
|
||||
if size != len(ua) {
|
||||
b := make([]byte, size)
|
||||
copy(b, ua)
|
||||
ua = b
|
||||
}
|
||||
if e := h.h.EEUAWrite(ua); e != 0 {
|
||||
return toErr("EEUAWrite", e)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetBaudRate sets the baud rate.
|
||||
func (h *handle) SetBaudRate(f physic.Frequency) error {
|
||||
if f >= physic.GigaHertz {
|
||||
return errors.New("ftdi: baud rate too high")
|
||||
}
|
||||
v := uint32(f / physic.Hertz)
|
||||
return toErr("SetBaudRate", h.h.SetBaudRate(v))
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
func toErr(s string, e d2xx.Err) error {
|
||||
if e == 0 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("ftdi: " + s + ": " + e.String())
|
||||
}
|
295
vendor/periph.io/x/host/v3/ftdi/i2c.go
generated
vendored
295
vendor/periph.io/x/host/v3/ftdi/i2c.go
generated
vendored
@ -1,295 +0,0 @@
|
||||
// Copyright 2017 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// This functionality requires MPSSE.
|
||||
//
|
||||
// Interfacing I²C:
|
||||
// http://www.ftdichip.com/Support/Documents/AppNotes/AN_113_FTDI_Hi_Speed_USB_To_I2C_Example.pdf
|
||||
//
|
||||
// Implementation based on
|
||||
// http://www.ftdichip.com/Support/Documents/AppNotes/AN_255_USB%20to%20I2C%20Example%20using%20the%20FT232H%20and%20FT201X%20devices.pdf
|
||||
//
|
||||
// Page 18: MPSSE does not automatically support clock stretching for I²C.
|
||||
|
||||
package ftdi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"periph.io/x/conn/v3"
|
||||
"periph.io/x/conn/v3/gpio"
|
||||
"periph.io/x/conn/v3/i2c"
|
||||
"periph.io/x/conn/v3/physic"
|
||||
)
|
||||
|
||||
const i2cSCL = 1 // D0
|
||||
const i2cSDAOut = 2 // D1
|
||||
const i2cSDAIn = 4 // D2
|
||||
|
||||
type i2cBus struct {
|
||||
f *FT232H
|
||||
pullUp bool
|
||||
}
|
||||
|
||||
// Close stops I²C mode, returns to high speed mode, disable tri-state.
|
||||
func (d *i2cBus) Close() error {
|
||||
d.f.mu.Lock()
|
||||
err := d.stopI2C()
|
||||
d.f.mu.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
// Duplex implements conn.Conn.
|
||||
func (d *i2cBus) Duplex() conn.Duplex {
|
||||
return conn.Half
|
||||
}
|
||||
|
||||
func (d *i2cBus) String() string {
|
||||
return d.f.String()
|
||||
}
|
||||
|
||||
// SetSpeed implements i2c.Bus.
|
||||
func (d *i2cBus) SetSpeed(f physic.Frequency) error {
|
||||
if f > 10*physic.MegaHertz {
|
||||
return fmt.Errorf("d2xx: invalid speed %s; maximum supported clock is 10MHz", f)
|
||||
}
|
||||
if f < 100*physic.Hertz {
|
||||
return fmt.Errorf("d2xx: invalid speed %s; minimum supported clock is 100Hz; did you forget to multiply by physic.KiloHertz?", f)
|
||||
}
|
||||
d.f.mu.Lock()
|
||||
defer d.f.mu.Unlock()
|
||||
_, err := d.f.h.MPSSEClock(f * 2 / 3)
|
||||
return err
|
||||
}
|
||||
|
||||
// Tx implements i2c.Bus.
|
||||
func (d *i2cBus) Tx(addr uint16, w, r []byte) error {
|
||||
d.f.mu.Lock()
|
||||
defer d.f.mu.Unlock()
|
||||
if err := d.setI2CStart(); err != nil {
|
||||
return err
|
||||
}
|
||||
a := [1]byte{byte(addr)}
|
||||
if err := d.writeBytes(a[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(w) != 0 {
|
||||
if err := d.writeBytes(w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(r) != 0 {
|
||||
if err := d.readBytes(r); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := d.setI2CStop(); err != nil {
|
||||
return err
|
||||
}
|
||||
return d.setI2CLinesIdle()
|
||||
}
|
||||
|
||||
// SCL implements i2c.Pins.
|
||||
func (d *i2cBus) SCL() gpio.PinIO {
|
||||
return d.f.D0
|
||||
}
|
||||
|
||||
// SDA implements i2c.Pins.
|
||||
func (d *i2cBus) SDA() gpio.PinIO {
|
||||
return d.f.D1
|
||||
}
|
||||
|
||||
// setupI2C initializes the MPSSE to the state to run an I²C transaction.
|
||||
//
|
||||
// Defaults to 400kHz.
|
||||
//
|
||||
// When pullUp is true; output alternates between Out(Low) and In(PullUp).
|
||||
//
|
||||
// when pullUp is false; pins are set in Tristate so Out(High) becomes float
|
||||
// instead of drive High. Low still drives low. That's called open collector.
|
||||
func (d *i2cBus) setupI2C(pullUp bool) error {
|
||||
if pullUp {
|
||||
return errors.New("d2xx: PullUp will soon be implemented")
|
||||
}
|
||||
// TODO(maruel): We could set these only *during* the I²C operation, which
|
||||
// would make more sense.
|
||||
f := 400 * physic.KiloHertz
|
||||
clk := ((30 * physic.MegaHertz / f) - 1) * 2 / 3
|
||||
|
||||
buf := [4 + 3]byte{
|
||||
clock3Phase,
|
||||
clock30MHz, byte(clk), byte(clk >> 8),
|
||||
}
|
||||
cmd := buf[:4]
|
||||
if !d.pullUp {
|
||||
// TODO(maruel): Do not mess with other GPIOs tristate.
|
||||
cmd = append(cmd, dataTristate, 7, 0)
|
||||
}
|
||||
if _, err := d.f.h.Write(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
d.f.usingI2C = true
|
||||
d.pullUp = pullUp
|
||||
return d.setI2CLinesIdle()
|
||||
}
|
||||
|
||||
// stopI2C resets the MPSSE to a more "normal" state.
|
||||
func (d *i2cBus) stopI2C() error {
|
||||
// Resets to 30MHz.
|
||||
buf := [4 + 3]byte{
|
||||
clock2Phase,
|
||||
clock30MHz, 0, 0,
|
||||
}
|
||||
cmd := buf[:4]
|
||||
if !d.pullUp {
|
||||
// TODO(maruel): Do not mess with other GPIOs tristate.
|
||||
cmd = append(cmd, dataTristate, 0, 0)
|
||||
}
|
||||
_, err := d.f.h.Write(cmd)
|
||||
d.f.usingI2C = false
|
||||
return err
|
||||
}
|
||||
|
||||
// setI2CLinesIdle sets all D0 and D1 lines high.
|
||||
//
|
||||
// Does not touch D3~D7.
|
||||
func (d *i2cBus) setI2CLinesIdle() error {
|
||||
const mask = 0xFF &^ (i2cSCL | i2cSDAOut | i2cSDAIn)
|
||||
// TODO(maruel): d.pullUp
|
||||
d.f.dbus.direction = d.f.dbus.direction&mask | i2cSCL | i2cSDAOut
|
||||
d.f.dbus.value = d.f.dbus.value & mask
|
||||
cmd := [...]byte{gpioSetD, d.f.dbus.value | i2cSCL | i2cSDAOut, d.f.dbus.direction}
|
||||
_, err := d.f.h.Write(cmd[:])
|
||||
return err
|
||||
}
|
||||
|
||||
// setI2CStart starts an I²C transaction.
|
||||
//
|
||||
// Does not touch D3~D7.
|
||||
func (d *i2cBus) setI2CStart() error {
|
||||
// TODO(maruel): d.pullUp
|
||||
dir := d.f.dbus.direction
|
||||
v := d.f.dbus.value
|
||||
// Assumes last setup was d.setI2CLinesIdle(), e.g. D0 and D1 are high, so
|
||||
// skip this.
|
||||
//
|
||||
// Runs the command 4 times as a way to delay execution.
|
||||
cmd := [...]byte{
|
||||
// SCL high, SDA low for 600ns
|
||||
gpioSetD, v | i2cSCL, dir,
|
||||
gpioSetD, v | i2cSCL, dir,
|
||||
gpioSetD, v | i2cSCL, dir,
|
||||
gpioSetD, v | i2cSCL, dir,
|
||||
// SCL low, SDA low
|
||||
gpioSetD, v, dir,
|
||||
gpioSetD, v, dir,
|
||||
gpioSetD, v, dir,
|
||||
}
|
||||
_, err := d.f.h.Write(cmd[:])
|
||||
return err
|
||||
}
|
||||
|
||||
// setI2CStop completes an I²C transaction.
|
||||
//
|
||||
// Does not touch D3~D7.
|
||||
func (d *i2cBus) setI2CStop() error {
|
||||
// TODO(maruel): d.pullUp
|
||||
dir := d.f.dbus.direction
|
||||
v := d.f.dbus.value
|
||||
// Runs the command 4 times as a way to delay execution.
|
||||
cmd := [...]byte{
|
||||
// SCL low, SDA low
|
||||
gpioSetD, v, dir,
|
||||
gpioSetD, v, dir,
|
||||
gpioSetD, v, dir,
|
||||
gpioSetD, v, dir,
|
||||
// SCL high, SDA low
|
||||
gpioSetD, v | i2cSCL, dir,
|
||||
gpioSetD, v | i2cSCL, dir,
|
||||
gpioSetD, v | i2cSCL, dir,
|
||||
gpioSetD, v | i2cSCL, dir,
|
||||
// SCL high, SDA high
|
||||
gpioSetD, v | i2cSCL | i2cSDAOut, dir,
|
||||
gpioSetD, v | i2cSCL | i2cSDAOut, dir,
|
||||
gpioSetD, v | i2cSCL | i2cSDAOut, dir,
|
||||
gpioSetD, v | i2cSCL | i2cSDAOut, dir,
|
||||
}
|
||||
_, err := d.f.h.Write(cmd[:])
|
||||
return err
|
||||
}
|
||||
|
||||
// writeBytes writes multiple bytes within an I²C transaction.
|
||||
//
|
||||
// Does not touch D3~D7.
|
||||
func (d *i2cBus) writeBytes(w []byte) error {
|
||||
// TODO(maruel): d.pullUp
|
||||
dir := d.f.dbus.direction
|
||||
v := d.f.dbus.value
|
||||
// TODO(maruel): WAT?
|
||||
if err := d.f.h.Flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO(maruel): Implement both with and without NAK check.
|
||||
var r [1]byte
|
||||
cmd := [...]byte{
|
||||
// Data out, the 0 will be replaced with the byte.
|
||||
dataOut | dataOutFall, 0, 0, 0,
|
||||
// Set back to idle.
|
||||
gpioSetD, v | i2cSCL | i2cSDAOut, dir,
|
||||
// Read ACK/NAK.
|
||||
dataIn | dataBit, 0,
|
||||
flush,
|
||||
}
|
||||
for _, c := range w {
|
||||
cmd[3] = c
|
||||
if _, err := d.f.h.Write(cmd[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := d.f.h.ReadAll(context.Background(), r[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if r[0]&1 == 0 {
|
||||
return errors.New("got NAK")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// readBytes reads multiple bytes within an I²C transaction.
|
||||
//
|
||||
// Does not touch D3~D7.
|
||||
func (d *i2cBus) readBytes(r []byte) error {
|
||||
// TODO(maruel): d.pullUp
|
||||
dir := d.f.dbus.direction
|
||||
v := d.f.dbus.value
|
||||
|
||||
cmd := [...]byte{
|
||||
// Read 8 bits.
|
||||
dataIn | dataBit, 7,
|
||||
// Send ACK/NAK.
|
||||
dataOut | dataOutFall | dataBit, 0, 0,
|
||||
// Set back to idle.
|
||||
gpioSetD, v | i2cSCL | i2cSDAOut, dir,
|
||||
// Force read buffer flush. This is only necessary if NAK are not ignored.
|
||||
flush,
|
||||
}
|
||||
for i := range r {
|
||||
if i == len(r)-1 {
|
||||
// NAK.
|
||||
cmd[4] = 0x80
|
||||
}
|
||||
if _, err := d.f.h.Write(cmd[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := d.f.h.ReadAll(context.Background(), r[i:1]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ i2c.BusCloser = &i2cBus{}
|
||||
var _ i2c.Pins = &i2cBus{}
|
452
vendor/periph.io/x/host/v3/ftdi/mpsse.go
generated
vendored
452
vendor/periph.io/x/host/v3/ftdi/mpsse.go
generated
vendored
@ -1,452 +0,0 @@
|
||||
// Copyright 2017 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// MPSSE is Multi-Protocol Synchronous Serial Engine
|
||||
//
|
||||
// MPSSE basics:
|
||||
// http://www.ftdichip.com/Support/Documents/AppNotes/AN_135_MPSSE_Basics.pdf
|
||||
//
|
||||
// MPSSE and MCU emulation modes:
|
||||
// http://www.ftdichip.com/Support/Documents/AppNotes/AN_108_Command_Processor_for_MPSSE_and_MCU_Host_Bus_Emulation_Modes.pdf
|
||||
|
||||
package ftdi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"periph.io/x/conn/v3/gpio"
|
||||
"periph.io/x/conn/v3/physic"
|
||||
)
|
||||
|
||||
const (
|
||||
// TDI/TDO serial operation synchronised on clock edges.
|
||||
//
|
||||
// Long streams (default):
|
||||
// - [1, 65536] bytes (length is sent minus one, requires 8 bits multiple)
|
||||
// <op>, <LengthLow-1>, <LengthHigh-1>, <byte0>, ..., <byteN>
|
||||
//
|
||||
// Short streams (dataBit is specified):
|
||||
// - [1, 8] bits
|
||||
// <op>, <Length-1>, <byte>
|
||||
//
|
||||
// When both dataOut and dataIn are specified, one of dataOutFall or
|
||||
// dataInFall should be specified, at least for most sane protocols.
|
||||
//
|
||||
// Flags:
|
||||
dataOut byte = 0x10 // Enable output, default on +VE (Rise)
|
||||
dataIn byte = 0x20 // Enable input, default on +VE (Rise)
|
||||
dataOutFall byte = 0x01 // instead of Rise
|
||||
dataInFall byte = 0x04 // instead of Rise
|
||||
dataLSBF byte = 0x08 // instead of MSBF
|
||||
dataBit byte = 0x02 // instead of Byte
|
||||
|
||||
// Data line drives low when the data is 0 and tristates on data 1. This is
|
||||
// used with I²C.
|
||||
// <op>, <ADBus pins>, <ACBus pins>
|
||||
dataTristate byte = 0x9E
|
||||
|
||||
// TSM operation (for JTAG).
|
||||
//
|
||||
// - Send bits 6 to 0 to the TMS pin using LSB or MSB.
|
||||
// - Bit 7 is passed to TDI/DO before the first clock of TMS and is held
|
||||
// static for the duration of TMS clocking.
|
||||
//
|
||||
// <op>, <Length>, <byte>
|
||||
tmsOutLSBFRise byte = 0x4A
|
||||
tmsOutLSBFFall byte = 0x4B
|
||||
tmsIOLSBInRise byte = 0x6A
|
||||
tmsIOLSBInFall byte = 0x6B
|
||||
// Unclear: 0x6E and 0x6F
|
||||
|
||||
// GPIO operation.
|
||||
//
|
||||
// - Operates on 8 GPIOs at a time, e.g. C0~C7 or D0~D7.
|
||||
// - Direction 1 means output, 0 means input.
|
||||
//
|
||||
// <op>, <value>, <direction>
|
||||
gpioSetD byte = 0x80
|
||||
gpioSetC byte = 0x82
|
||||
// <op>, returns <value>
|
||||
gpioReadD byte = 0x81
|
||||
gpioReadC byte = 0x83
|
||||
|
||||
// Internal loopback.
|
||||
//
|
||||
// Connects TDI and TDO together.
|
||||
internalLoopbackEnable byte = 0x84
|
||||
internalLoopbackDisable byte = 0x85
|
||||
|
||||
// Clock.
|
||||
//
|
||||
// The TCK/SK has a 50% duty cycle.
|
||||
//
|
||||
// The inactive clock state can be set via the gpioSetD command and control
|
||||
// bit 0.
|
||||
//
|
||||
// By default, the base clock is 6MHz via a 5x divisor. On
|
||||
// FT232H/FT2232H/FT4232H, the 5x divisor can be disabled.
|
||||
clock30MHz byte = 0x8A
|
||||
clock6MHz byte = 0x8B
|
||||
// Sets clock divisor.
|
||||
//
|
||||
// The effective value depends if clock30MHz was sent or not.
|
||||
//
|
||||
// - 0(1) 6MHz / 30MHz
|
||||
// - 1(2) 3MHz / 15MHz
|
||||
// - 2(3) 2MHz / 10MHz
|
||||
// - 3(4) 1.5MHz / 7.5MHz
|
||||
// - 4(5) 1.25MHz / 6MHz
|
||||
// - ...
|
||||
// - 0xFFFF(65536) 91.553Hz / 457.763Hz
|
||||
//
|
||||
// <op>, <valueL-1>, <valueH-1>
|
||||
clockSetDivisor byte = 0x86
|
||||
// Uses 3 phases data clocking: data is valid on both clock edges. Needed
|
||||
// for I²C.
|
||||
clock3Phase byte = 0x8C
|
||||
// Uses normal 2 phases data clocking.
|
||||
clock2Phase byte = 0x8D
|
||||
// Enables clock even while not doing any operation. Used with JTAG.
|
||||
// Enables the clock between [1, 8] pulses.
|
||||
// <op>, <length-1>
|
||||
clockOnShort byte = 0x8E
|
||||
// Enables the clock between [8, 524288] pulses in 8 multiples.
|
||||
// <op>, <lengthL-1>, <lengthH-1>
|
||||
clockOnLong byte = 0x8F
|
||||
// Enables clock until D5 is high or low. Used with JTAG.
|
||||
clockUntilHigh byte = 0x94
|
||||
clockUntilLow byte = 0x95
|
||||
// <op>, <lengthL-1>, <lengthH-1> in 8 multiples.
|
||||
clockUntilHighLong byte = 0x9C
|
||||
clockUntilLowLong byte = 0x9D
|
||||
// Enables adaptive clocking. Used with JTAG.
|
||||
//
|
||||
// This causes the controller to wait for D7 signal state as an ACK.
|
||||
clockAdaptive byte = 0x96
|
||||
// Disables adaptive clocking.
|
||||
clockNormal byte = 0x97
|
||||
|
||||
// CPU mode.
|
||||
//
|
||||
// Access the device registers like a memory mapped device.
|
||||
//
|
||||
// <op>, <addrLow>
|
||||
cpuReadShort byte = 0x90
|
||||
// <op>, <addrHi>, <addrLow>
|
||||
cpuReadFar byte = 0x91
|
||||
// <op>, <addrLow>, <data>
|
||||
cpuWriteShort byte = 0x92
|
||||
// <op>, <addrHi>, <addrLow>, <data>
|
||||
cpuWriteFar byte = 0x91
|
||||
|
||||
// Buffer operations.
|
||||
//
|
||||
// Flush the buffer back to the host.
|
||||
flush byte = 0x87
|
||||
// Wait until D5 (JTAG) or I/O1 (CPU) is high. Once it is detected as
|
||||
// high, the MPSSE engine moves on to process the next instruction.
|
||||
waitHigh byte = 0x88
|
||||
waitLow byte = 0x89
|
||||
)
|
||||
|
||||
// InitMPSSE sets the device into MPSSE mode.
|
||||
//
|
||||
// This requires a f232h, ft2232, ft2232h or a ft4232h.
|
||||
//
|
||||
// Use only one of Init or InitMPSSE.
|
||||
func (h *handle) InitMPSSE() error {
|
||||
// http://www.ftdichip.com/Support/Documents/AppNotes/AN_255_USB%20to%20I2C%20Example%20using%20the%20FT232H%20and%20FT201X%20devices.pdf
|
||||
// Pre-state:
|
||||
// - Write EEPROM i.IsFifo = true so the device DBus is started in tristate.
|
||||
|
||||
// Try to verify the MPSSE controller without initializing it first. This is
|
||||
// the 'happy path', which enables reusing the device is its current state
|
||||
// without affecting current GPIO state.
|
||||
if h.mpsseVerify() != nil {
|
||||
// Do a full reset. Just trying to set the MPSSE controller will
|
||||
// likely not work. That's a layering violation (since the retry with reset
|
||||
// is done in driver.go) but we've survived worse things...
|
||||
//
|
||||
// TODO(maruel): This is not helping in practice, this need to be fine
|
||||
// tuned.
|
||||
if err := h.Reset(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := h.Init(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := h.SetBitMode(0, bitModeMpsse); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := h.mpsseVerify(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize MPSSE to a known state.
|
||||
// Reset the clock since it is impossible to read back the current clock rate.
|
||||
// Reset all the GPIOs are inputs since it is impossible to read back the
|
||||
// state of each GPIO (if they are input or output).
|
||||
cmd := []byte{
|
||||
clock30MHz, clockNormal, clock2Phase, internalLoopbackDisable,
|
||||
gpioSetC, 0x00, 0x00,
|
||||
gpioSetD, 0x00, 0x00,
|
||||
}
|
||||
if _, err := h.Write(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
// Success!!
|
||||
return nil
|
||||
}
|
||||
|
||||
// mpsseVerify sends an invalid MPSSE command and verifies the returned value
|
||||
// is incorrect.
|
||||
//
|
||||
// In practice this takes around 2ms.
|
||||
func (h *handle) mpsseVerify() error {
|
||||
var b [16]byte
|
||||
for _, v := range []byte{0xAA, 0xAB} {
|
||||
// Write a bad command and ensure it returned correctly.
|
||||
// Unlike what the application note proposes, include a flush op right
|
||||
// after. Without the flush, the device will only flush after the delay
|
||||
// specified to SetLatencyTimer. The flush removes this unneeded wait,
|
||||
// which enables increasing the delay specified to SetLatencyTimer.
|
||||
b[0] = v
|
||||
b[1] = flush
|
||||
if _, err := h.Write(b[:2]); err != nil {
|
||||
return fmt.Errorf("d2xx: mpsseVerify: %v", err)
|
||||
}
|
||||
// Sometimes, especially right after a reset, the device spews a few bytes.
|
||||
// Discard them. This significantly increases the odds of a successful
|
||||
// initialization.
|
||||
p, e := h.h.GetQueueStatus()
|
||||
if e != 0 {
|
||||
return toErr("Read/GetQueueStatus", e)
|
||||
}
|
||||
for p > 2 {
|
||||
l := int(p) - 2
|
||||
if l > len(b) {
|
||||
l = len(b)
|
||||
}
|
||||
// Discard the overflow bytes.
|
||||
ctx, cancel := context200ms()
|
||||
defer cancel()
|
||||
if _, err := h.ReadAll(ctx, b[:l]); err != nil {
|
||||
return fmt.Errorf("d2xx: mpsseVerify: %v", err)
|
||||
}
|
||||
p -= uint32(l)
|
||||
}
|
||||
// Custom implementation, as we want to flush any stray byte.
|
||||
ctx, cancel := context200ms()
|
||||
defer cancel()
|
||||
if _, err := h.ReadAll(ctx, b[:2]); err != nil {
|
||||
return fmt.Errorf("d2xx: mpsseVerify: %v", err)
|
||||
}
|
||||
// 0xFA means invalid command, 0xAA is the command echoed back.
|
||||
if b[0] != 0xFA || b[1] != v {
|
||||
return fmt.Errorf("d2xx: mpsseVerify: failed test for byte %#x: %#x", v, b)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// MPSSERegRead reads the memory mapped registers from the device.
|
||||
func (h *handle) MPSSERegRead(addr uint16) (byte, error) {
|
||||
// Unlike most other operations, the uint16 byte order is <hi>, <lo>.
|
||||
b := [...]byte{cpuReadFar, byte(addr >> 8), byte(addr), flush}
|
||||
if _, err := h.Write(b[:]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ctx, cancel := context200ms()
|
||||
defer cancel()
|
||||
_, err := h.ReadAll(ctx, b[:1])
|
||||
return b[0], err
|
||||
}
|
||||
|
||||
// MPSSEClock sets the clock at the closest value and returns it.
|
||||
func (h *handle) MPSSEClock(f physic.Frequency) (physic.Frequency, error) {
|
||||
// TODO(maruel): Memory clock and skip if the same value.
|
||||
clk := clock30MHz
|
||||
base := 30 * physic.MegaHertz
|
||||
div := base / f
|
||||
if div >= 65536 {
|
||||
clk = clock6MHz
|
||||
base /= 5
|
||||
div = base / f
|
||||
if div >= 65536 {
|
||||
return 0, errors.New("d2xx: clock frequency is too low")
|
||||
}
|
||||
}
|
||||
b := [...]byte{clk, clockSetDivisor, byte(div - 1), byte((div - 1) >> 8)}
|
||||
_, err := h.Write(b[:])
|
||||
return base / div, err
|
||||
}
|
||||
|
||||
// mpsseTxOp returns the right MPSSE command byte for the stream.
|
||||
func mpsseTxOp(w, r bool, ew, er gpio.Edge, lsbf bool) byte {
|
||||
op := byte(0)
|
||||
if lsbf {
|
||||
op |= dataLSBF
|
||||
}
|
||||
if w {
|
||||
op |= dataOut
|
||||
if ew == gpio.FallingEdge {
|
||||
op |= dataOutFall
|
||||
}
|
||||
}
|
||||
if r {
|
||||
op |= dataIn
|
||||
if er == gpio.FallingEdge {
|
||||
op |= dataInFall
|
||||
}
|
||||
}
|
||||
return op
|
||||
}
|
||||
|
||||
// MPSSETx runs a transaction on the clock on pins D0, D1 and D2.
|
||||
//
|
||||
// It can only do it on a multiple of 8 bits.
|
||||
func (h *handle) MPSSETx(w, r []byte, ew, er gpio.Edge, lsbf bool) error {
|
||||
l := len(w)
|
||||
if len(w) != 0 {
|
||||
// TODO(maruel): This is easy to fix by daisy chaining operations.
|
||||
if len(w) > 65536 {
|
||||
return errors.New("d2xx: write buffer too long; max 65536")
|
||||
}
|
||||
}
|
||||
if len(r) != 0 {
|
||||
if len(r) > 65536 {
|
||||
return errors.New("d2xx: read buffer too long; max 65536")
|
||||
}
|
||||
if l != 0 && len(r) != l {
|
||||
return errors.New("d2xx: mismatched buffer lengths")
|
||||
}
|
||||
l = len(r)
|
||||
}
|
||||
// The FT232H has 1Kb Tx and Rx buffers. So partial writes should be done.
|
||||
// TODO(maruel): Test.
|
||||
|
||||
// Flush can be useful if rbits != 0.
|
||||
op := mpsseTxOp(len(w) != 0, len(r) != 0, ew, er, lsbf)
|
||||
cmd := []byte{op, byte(l - 1), byte((l - 1) >> 8)}
|
||||
cmd = append(cmd, w...)
|
||||
if len(r) != 0 {
|
||||
cmd = append(cmd, flush)
|
||||
}
|
||||
if _, err := h.Write(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(r) != 0 {
|
||||
ctx, cancel := context200ms()
|
||||
defer cancel()
|
||||
_, err := h.ReadAll(ctx, r)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MPSSETxShort runs a transaction on the clock pins D0, D1 and D2 for a byte
|
||||
// or less: between 1 and 8 bits.
|
||||
func (h *handle) MPSSETxShort(w byte, wbits, rbits int, ew, er gpio.Edge, lsbf bool) (byte, error) {
|
||||
op := byte(dataBit)
|
||||
if lsbf {
|
||||
op |= dataLSBF
|
||||
}
|
||||
l := wbits
|
||||
if wbits != 0 {
|
||||
if wbits > 8 {
|
||||
return 0, errors.New("d2xx: write buffer too long; max 8")
|
||||
}
|
||||
op |= dataOut
|
||||
if ew == gpio.FallingEdge {
|
||||
op |= dataOutFall
|
||||
}
|
||||
}
|
||||
if rbits != 0 {
|
||||
if rbits > 8 {
|
||||
return 0, errors.New("d2xx: read buffer too long; max 8")
|
||||
}
|
||||
op |= dataIn
|
||||
if er == gpio.FallingEdge {
|
||||
op |= dataInFall
|
||||
}
|
||||
if l != 0 && rbits != l {
|
||||
return 0, errors.New("d2xx: mismatched buffer lengths")
|
||||
}
|
||||
l = rbits
|
||||
}
|
||||
b := [3]byte{op, byte(l - 1)}
|
||||
cmd := b[:2]
|
||||
if wbits != 0 {
|
||||
cmd = append(cmd, w)
|
||||
}
|
||||
if rbits != 0 {
|
||||
cmd = append(cmd, flush)
|
||||
}
|
||||
if _, err := h.Write(cmd); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if rbits != 0 {
|
||||
ctx, cancel := context200ms()
|
||||
defer cancel()
|
||||
_, err := h.ReadAll(ctx, b[:1])
|
||||
return b[0], err
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// MPSSECBus operates on 8 GPIOs at a time C0~C7.
|
||||
//
|
||||
// Direction 1 means output, 0 means input.
|
||||
func (h *handle) MPSSECBus(mask, value byte) error {
|
||||
b := [...]byte{gpioSetC, value, mask}
|
||||
_, err := h.Write(b[:])
|
||||
return err
|
||||
}
|
||||
|
||||
// MPSSEDBus operates on 8 GPIOs at a time D0~D7.
|
||||
//
|
||||
// Direction 1 means output, 0 means input.
|
||||
func (h *handle) MPSSEDBus(mask, value byte) error {
|
||||
b := [...]byte{gpioSetD, value, mask}
|
||||
_, err := h.Write(b[:])
|
||||
return err
|
||||
}
|
||||
|
||||
// MPSSECBusRead reads all the CBus pins C0~C7.
|
||||
func (h *handle) MPSSECBusRead() (byte, error) {
|
||||
b := [...]byte{gpioReadC, flush}
|
||||
if _, err := h.Write(b[:]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ctx, cancel := context200ms()
|
||||
defer cancel()
|
||||
if _, err := h.ReadAll(ctx, b[:1]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return b[0], nil
|
||||
}
|
||||
|
||||
// MPSSEDBusRead reads all the DBus pins D0~D7.
|
||||
func (h *handle) MPSSEDBusRead() (byte, error) {
|
||||
b := [...]byte{gpioReadD, flush}
|
||||
if _, err := h.Write(b[:]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ctx, cancel := context200ms()
|
||||
defer cancel()
|
||||
if _, err := h.ReadAll(ctx, b[:1]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return b[0], nil
|
||||
}
|
||||
|
||||
func context200ms() (context.Context, func()) {
|
||||
return context.WithTimeout(context.Background(), 200*time.Millisecond)
|
||||
}
|
205
vendor/periph.io/x/host/v3/ftdi/mpsse_gpio.go
generated
vendored
205
vendor/periph.io/x/host/v3/ftdi/mpsse_gpio.go
generated
vendored
@ -1,205 +0,0 @@
|
||||
// Copyright 2017 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
package ftdi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"periph.io/x/conn/v3/gpio"
|
||||
"periph.io/x/conn/v3/physic"
|
||||
)
|
||||
|
||||
// gpiosMPSSE is a slice of 8 GPIO pins driven via MPSSE.
|
||||
//
|
||||
// This permits keeping a cache.
|
||||
type gpiosMPSSE struct {
|
||||
// Immutable.
|
||||
h *handle
|
||||
cbus bool // false if D bus
|
||||
pins [8]gpioMPSSE
|
||||
|
||||
// Cache of values
|
||||
direction byte
|
||||
value byte
|
||||
}
|
||||
|
||||
func (g *gpiosMPSSE) init(name string) {
|
||||
s := "D"
|
||||
if g.cbus {
|
||||
s = "C"
|
||||
}
|
||||
// Configure pulls; pull ups are 75kΩ.
|
||||
// http://www.ftdichip.com/Support/Documents/AppNotes/AN_184%20FTDI%20Device%20Input%20Output%20Pin%20States.pdf
|
||||
// has a good table.
|
||||
// D0, D2 and D4 go in high impedance before going into pull up.
|
||||
// TODO(maruel): The pull on CBus depends on EEPROM!
|
||||
for i := range g.pins {
|
||||
g.pins[i].a = g
|
||||
g.pins[i].n = name + "." + s + strconv.Itoa(i)
|
||||
g.pins[i].num = i
|
||||
g.pins[i].dp = gpio.PullUp
|
||||
}
|
||||
if g.cbus {
|
||||
// That's just the default EEPROM value.
|
||||
g.pins[7].dp = gpio.PullDown
|
||||
}
|
||||
}
|
||||
|
||||
func (g *gpiosMPSSE) in(n int) error {
|
||||
if g.h == nil {
|
||||
return errors.New("d2xx: device not open")
|
||||
}
|
||||
g.direction = g.direction & ^(1 << uint(n))
|
||||
if g.cbus {
|
||||
return g.h.MPSSECBus(g.direction, g.value)
|
||||
}
|
||||
return g.h.MPSSEDBus(g.direction, g.value)
|
||||
}
|
||||
|
||||
func (g *gpiosMPSSE) read() (byte, error) {
|
||||
if g.h == nil {
|
||||
return 0, errors.New("d2xx: device not open")
|
||||
}
|
||||
var err error
|
||||
if g.cbus {
|
||||
g.value, err = g.h.MPSSECBusRead()
|
||||
} else {
|
||||
g.value, err = g.h.MPSSEDBusRead()
|
||||
}
|
||||
return g.value, err
|
||||
}
|
||||
|
||||
func (g *gpiosMPSSE) out(n int, l gpio.Level) error {
|
||||
if g.h == nil {
|
||||
return errors.New("d2xx: device not open")
|
||||
}
|
||||
g.direction = g.direction | (1 << uint(n))
|
||||
if l {
|
||||
g.value |= 1 << uint(n)
|
||||
} else {
|
||||
g.value &^= 1 << uint(n)
|
||||
}
|
||||
if g.cbus {
|
||||
return g.h.MPSSECBus(g.direction, g.value)
|
||||
}
|
||||
return g.h.MPSSEDBus(g.direction, g.value)
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// gpioMPSSE is a GPIO pin on a FTDI device driven via MPSSE.
|
||||
//
|
||||
// gpioMPSSE implements gpio.PinIO.
|
||||
//
|
||||
// It is immutable and stateless.
|
||||
type gpioMPSSE struct {
|
||||
a *gpiosMPSSE
|
||||
n string
|
||||
num int
|
||||
dp gpio.Pull
|
||||
}
|
||||
|
||||
// String implements pin.Pin.
|
||||
func (g *gpioMPSSE) String() string {
|
||||
return g.n
|
||||
}
|
||||
|
||||
// Name implements pin.Pin.
|
||||
func (g *gpioMPSSE) Name() string {
|
||||
return g.n
|
||||
}
|
||||
|
||||
// Number implements pin.Pin.
|
||||
func (g *gpioMPSSE) Number() int {
|
||||
return g.num
|
||||
}
|
||||
|
||||
// Function implements pin.Pin.
|
||||
func (g *gpioMPSSE) Function() string {
|
||||
s := "Out/"
|
||||
m := byte(1 << uint(g.num))
|
||||
if g.a.direction&m == 0 {
|
||||
s = "In/"
|
||||
_, _ = g.a.read()
|
||||
}
|
||||
return s + gpio.Level(g.a.value&m != 0).String()
|
||||
}
|
||||
|
||||
// Halt implements gpio.PinIO.
|
||||
func (g *gpioMPSSE) Halt() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// In implements gpio.PinIn.
|
||||
func (g *gpioMPSSE) In(pull gpio.Pull, e gpio.Edge) error {
|
||||
if e != gpio.NoEdge {
|
||||
// We could support it on D5.
|
||||
return errors.New("d2xx: edge triggering is not supported")
|
||||
}
|
||||
if pull != g.dp && pull != gpio.PullNoChange {
|
||||
// TODO(maruel): This needs to be redone:
|
||||
// - EEPROM values FT232hCBusTristatePullUp and FT232hCBusPwrEnable can be
|
||||
// used to control individual CBus pins.
|
||||
// - dataTristate enables gpio.Float when set to output High, but I don't
|
||||
// know if it will enable reading the value (?). This needs to be
|
||||
// confirmed.
|
||||
return fmt.Errorf("d2xx: pull %s is not supported; try %s", pull, g.dp)
|
||||
}
|
||||
return g.a.in(g.num)
|
||||
}
|
||||
|
||||
// Read implements gpio.PinIn.
|
||||
func (g *gpioMPSSE) Read() gpio.Level {
|
||||
v, _ := g.a.read()
|
||||
return gpio.Level(v&(1<<uint(g.num)) != 0)
|
||||
}
|
||||
|
||||
// WaitForEdge implements gpio.PinIn.
|
||||
func (g *gpioMPSSE) WaitForEdge(t time.Duration) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// DefaultPull implements gpio.PinIn.
|
||||
func (g *gpioMPSSE) DefaultPull() gpio.Pull {
|
||||
return g.dp
|
||||
}
|
||||
|
||||
// Pull implements gpio.PinIn. The resistor is 75kΩ.
|
||||
func (g *gpioMPSSE) Pull() gpio.Pull {
|
||||
// See In() for the challenges.
|
||||
return g.dp
|
||||
}
|
||||
|
||||
// Out implements gpio.PinOut.
|
||||
func (g *gpioMPSSE) Out(l gpio.Level) error {
|
||||
return g.a.out(g.num, l)
|
||||
}
|
||||
|
||||
// PWM implements gpio.PinOut.
|
||||
func (g *gpioMPSSE) PWM(d gpio.Duty, f physic.Frequency) error {
|
||||
return errors.New("d2xx: not implemented")
|
||||
}
|
||||
|
||||
/*
|
||||
func (g *gpioMPSSE) Drive() physic.ElectricCurrent {
|
||||
//return g.a.ee.CDriveCurrent * physic.MilliAmpere
|
||||
return 2 * physic.MilliAmpere
|
||||
}
|
||||
|
||||
func (g *gpioMPSSE) SlewLimit() bool {
|
||||
//return g.a.ee.CSlowSlew
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *gpioMPSSE) Hysteresis() bool {
|
||||
//return g.a.ee.DSchmittInput
|
||||
return true
|
||||
}
|
||||
*/
|
||||
|
||||
var _ gpio.PinIO = &gpioMPSSE{}
|
85
vendor/periph.io/x/host/v3/ftdi/pin.go
generated
vendored
85
vendor/periph.io/x/host/v3/ftdi/pin.go
generated
vendored
@ -1,85 +0,0 @@
|
||||
// Copyright 2017 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// Emulate independent GPIOs.
|
||||
|
||||
package ftdi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"periph.io/x/conn/v3/gpio"
|
||||
"periph.io/x/conn/v3/physic"
|
||||
)
|
||||
|
||||
// invalidPin is a non-working (not implemented) pin on a FTDI device.
|
||||
//
|
||||
// invalidPin implements gpio.PinIO.
|
||||
type invalidPin struct {
|
||||
n string
|
||||
num int
|
||||
}
|
||||
|
||||
// String implements pin.Pin.
|
||||
func (p *invalidPin) String() string {
|
||||
return p.n
|
||||
}
|
||||
|
||||
// Name implements pin.Pin.
|
||||
func (p *invalidPin) Name() string {
|
||||
return p.n
|
||||
}
|
||||
|
||||
// Number implements pin.Pin.
|
||||
func (p *invalidPin) Number() int {
|
||||
return p.num
|
||||
}
|
||||
|
||||
// Function implements pin.Pin.
|
||||
func (p *invalidPin) Function() string {
|
||||
return "N/A"
|
||||
}
|
||||
|
||||
// Halt implements gpio.PinIO.
|
||||
func (p *invalidPin) Halt() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// In implements gpio.PinIn.
|
||||
func (p *invalidPin) In(pull gpio.Pull, e gpio.Edge) error {
|
||||
return errors.New("d2xx: to be implemented")
|
||||
}
|
||||
|
||||
// Read implements gpio.PinIn.
|
||||
func (p *invalidPin) Read() gpio.Level {
|
||||
return gpio.Low
|
||||
}
|
||||
|
||||
// WaitForEdge implements gpio.PinIn.
|
||||
func (p *invalidPin) WaitForEdge(t time.Duration) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Pull implements gpio.PinIn.
|
||||
func (p *invalidPin) Pull() gpio.Pull {
|
||||
return gpio.PullNoChange
|
||||
}
|
||||
|
||||
// DefaultPull implements gpio.PinIn.
|
||||
func (p *invalidPin) DefaultPull() gpio.Pull {
|
||||
return gpio.PullNoChange
|
||||
}
|
||||
|
||||
// Out implements gpio.PinOut.
|
||||
func (p *invalidPin) Out(l gpio.Level) error {
|
||||
return errors.New("d2xx: to be implemented")
|
||||
}
|
||||
|
||||
// PWM implements gpio.PinOut.
|
||||
func (p *invalidPin) PWM(d gpio.Duty, f physic.Frequency) error {
|
||||
return errors.New("d2xx: to be implemented")
|
||||
}
|
||||
|
||||
var _ gpio.PinIO = &invalidPin{}
|
697
vendor/periph.io/x/host/v3/ftdi/spi.go
generated
vendored
697
vendor/periph.io/x/host/v3/ftdi/spi.go
generated
vendored
@ -1,697 +0,0 @@
|
||||
// Copyright 2017 The Periph Authors. All rights reserved.
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// This functionality requires MPSSE.
|
||||
//
|
||||
// Interfacing SPI:
|
||||
// http://www.ftdichip.com/Support/Documents/AppNotes/AN_114_FTDI_Hi_Speed_USB_To_SPI_Example.pdf
|
||||
//
|
||||
// Implementation based on
|
||||
// http://www.ftdichip.com/Support/Documents/AppNotes/AN_180_FT232H%20MPSSE%20Example%20-%20USB%20Current%20Meter%20using%20the%20SPI%20interface.pdf
|
||||
|
||||
package ftdi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"periph.io/x/conn/v3"
|
||||
"periph.io/x/conn/v3/gpio"
|
||||
"periph.io/x/conn/v3/physic"
|
||||
"periph.io/x/conn/v3/spi"
|
||||
)
|
||||
|
||||
// spiMPSEEPort is an SPI port over a FTDI device in MPSSE mode using the data
|
||||
// command on the AD bus.
|
||||
type spiMPSEEPort struct {
|
||||
c spiMPSEEConn
|
||||
|
||||
// Mutable.
|
||||
maxFreq physic.Frequency
|
||||
}
|
||||
|
||||
func (s *spiMPSEEPort) Close() error {
|
||||
s.c.f.mu.Lock()
|
||||
s.c.f.usingSPI = false
|
||||
s.maxFreq = 0
|
||||
s.c.edgeInvert = false
|
||||
s.c.clkActiveLow = false
|
||||
s.c.noCS = false
|
||||
s.c.lsbFirst = false
|
||||
s.c.halfDuplex = false
|
||||
s.c.f.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *spiMPSEEPort) String() string {
|
||||
return s.c.f.String()
|
||||
}
|
||||
|
||||
// Connect implements spi.Port.
|
||||
func (s *spiMPSEEPort) Connect(f physic.Frequency, m spi.Mode, bits int) (spi.Conn, error) {
|
||||
if f > physic.GigaHertz {
|
||||
return nil, fmt.Errorf("d2xx: invalid speed %s; maximum supported clock is 30MHz", f)
|
||||
}
|
||||
if f > 30*physic.MegaHertz {
|
||||
// TODO(maruel): Figure out a way to communicate that the speed was lowered.
|
||||
// https://github.com/google/periph/issues/255
|
||||
f = 30 * physic.MegaHertz
|
||||
}
|
||||
if f < 100*physic.Hertz {
|
||||
return nil, fmt.Errorf("d2xx: invalid speed %s; minimum supported clock is 100Hz; did you forget to multiply by physic.MegaHertz?", f)
|
||||
}
|
||||
if bits&7 != 0 {
|
||||
return nil, errors.New("d2xx: bits must be multiple of 8")
|
||||
}
|
||||
if bits != 8 {
|
||||
return nil, errors.New("d2xx: implement bits per word above 8")
|
||||
}
|
||||
|
||||
s.c.f.mu.Lock()
|
||||
defer s.c.f.mu.Unlock()
|
||||
s.c.noCS = m&spi.NoCS != 0
|
||||
s.c.halfDuplex = m&spi.HalfDuplex != 0
|
||||
s.c.lsbFirst = m&spi.LSBFirst != 0
|
||||
m &^= spi.NoCS | spi.HalfDuplex | spi.LSBFirst
|
||||
if s.c.halfDuplex {
|
||||
return nil, errors.New("d2xx: spi.HalfDuplex is not yet supported (implementing wouldn't be too hard, please submit a PR")
|
||||
}
|
||||
if m < 0 || m > 3 {
|
||||
return nil, errors.New("d2xx: unknown spi mode")
|
||||
}
|
||||
s.c.edgeInvert = m&1 != 0
|
||||
s.c.clkActiveLow = m&2 != 0
|
||||
if s.maxFreq == 0 || f < s.maxFreq {
|
||||
// TODO(maruel): We could set these only *during* the SPI operation, which
|
||||
// would make more sense.
|
||||
if _, err := s.c.f.h.MPSSEClock(f); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.maxFreq = f
|
||||
}
|
||||
s.c.resetIdle()
|
||||
if err := s.c.f.h.MPSSEDBus(s.c.f.dbus.direction, s.c.f.dbus.value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.c.f.usingSPI = true
|
||||
return &s.c, nil
|
||||
}
|
||||
|
||||
// LimitSpeed implements spi.Port.
|
||||
func (s *spiMPSEEPort) LimitSpeed(f physic.Frequency) error {
|
||||
if f > physic.GigaHertz {
|
||||
return fmt.Errorf("d2xx: invalid speed %s; maximum supported clock is 30MHz", f)
|
||||
}
|
||||
if f > 30*physic.MegaHertz {
|
||||
f = 30 * physic.MegaHertz
|
||||
}
|
||||
if f < 100*physic.Hertz {
|
||||
return errors.New("d2xx: minimum supported clock is 100Hz; did you forget to multiply by physic.MegaHertz?")
|
||||
}
|
||||
s.c.f.mu.Lock()
|
||||
defer s.c.f.mu.Unlock()
|
||||
if s.maxFreq != 0 && s.maxFreq <= f {
|
||||
return nil
|
||||
}
|
||||
s.maxFreq = f
|
||||
// TODO(maruel): We could set these only *during* the SPI operation, which
|
||||
// would make more sense.
|
||||
_, err := s.c.f.h.MPSSEClock(s.maxFreq)
|
||||
return err
|
||||
}
|
||||
|
||||
// CLK returns the SCK (clock) pin.
|
||||
func (s *spiMPSEEPort) CLK() gpio.PinOut {
|
||||
return s.c.CLK()
|
||||
}
|
||||
|
||||
// MOSI returns the SDO (master out, slave in) pin.
|
||||
func (s *spiMPSEEPort) MOSI() gpio.PinOut {
|
||||
return s.c.MOSI()
|
||||
}
|
||||
|
||||
// MISO returns the SDI (master in, slave out) pin.
|
||||
func (s *spiMPSEEPort) MISO() gpio.PinIn {
|
||||
return s.c.MISO()
|
||||
}
|
||||
|
||||
// CS returns the CSN (chip select) pin.
|
||||
func (s *spiMPSEEPort) CS() gpio.PinOut {
|
||||
return s.c.CS()
|
||||
}
|
||||
|
||||
type spiMPSEEConn struct {
|
||||
// Immutable.
|
||||
f *FT232H
|
||||
|
||||
// Initialized at Connect().
|
||||
edgeInvert bool // CPHA=1
|
||||
clkActiveLow bool // CPOL=1
|
||||
noCS bool // CS line is not changed
|
||||
lsbFirst bool // Default is MSB first
|
||||
halfDuplex bool // 3 wire mode
|
||||
}
|
||||
|
||||
func (s *spiMPSEEConn) String() string {
|
||||
return s.f.String()
|
||||
}
|
||||
|
||||
func (s *spiMPSEEConn) Tx(w, r []byte) error {
|
||||
var p = [1]spi.Packet{{W: w, R: r}}
|
||||
return s.TxPackets(p[:])
|
||||
}
|
||||
|
||||
func (s *spiMPSEEConn) Duplex() conn.Duplex {
|
||||
// TODO(maruel): Support half if there's a need.
|
||||
return conn.Full
|
||||
}
|
||||
|
||||
func (s *spiMPSEEConn) TxPackets(pkts []spi.Packet) error {
|
||||
// Verification.
|
||||
for _, p := range pkts {
|
||||
if p.KeepCS {
|
||||
return errors.New("d2xx: implement spi.Packet.KeepCS")
|
||||
}
|
||||
if p.BitsPerWord&7 != 0 {
|
||||
return errors.New("d2xx: bits must be a multiple of 8")
|
||||
}
|
||||
if p.BitsPerWord != 0 && p.BitsPerWord != 8 {
|
||||
return errors.New("d2xx: implement spi.Packet.BitsPerWord")
|
||||
}
|
||||
if err := verifyBuffers(p.W, p.R); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
s.f.mu.Lock()
|
||||
defer s.f.mu.Unlock()
|
||||
const clk = byte(1) << 0
|
||||
const mosi = byte(1) << 1
|
||||
const miso = byte(1) << 2
|
||||
const cs = byte(1) << 3
|
||||
s.resetIdle()
|
||||
idle := s.f.dbus.value
|
||||
start1 := idle
|
||||
if !s.noCS {
|
||||
start1 &^= cs
|
||||
}
|
||||
// In mode 0 and 2, start2 is not needed.
|
||||
start2 := start1
|
||||
stop := idle
|
||||
if s.edgeInvert {
|
||||
// This is needed to 'prime' the clock.
|
||||
start2 ^= clk
|
||||
// With mode 1 and 3, keep the clock steady while CS is being deasserted to
|
||||
// not create a spurious clock.
|
||||
stop ^= clk
|
||||
}
|
||||
ew := gpio.FallingEdge
|
||||
er := gpio.RisingEdge
|
||||
if s.edgeInvert {
|
||||
ew, er = er, ew
|
||||
}
|
||||
if s.clkActiveLow {
|
||||
// TODO(maruel): Not sure.
|
||||
ew, er = er, ew
|
||||
}
|
||||
|
||||
// FT232H claims 512 USB packet support, so to reduce the chatter over USB,
|
||||
// try to make all I/O be aligned on this amount. This also removes the need
|
||||
// for heap usage. The idea is to always trail reads by one buffer. This is
|
||||
// fine as the device has 1024 byte read buffer. Operations look like this:
|
||||
// W, W, R, W, R, W, R, R
|
||||
// This enables reducing the I/O gaps between USB packets as the device is
|
||||
// always busy with operations.
|
||||
var buf [512]byte
|
||||
cmd := buf[:0]
|
||||
keptCS := false
|
||||
|
||||
// Loop, without increasing the index.
|
||||
for _, p := range pkts {
|
||||
if len(p.W) == 0 && len(p.R) == 0 {
|
||||
continue
|
||||
}
|
||||
// TODO(maruel): s.halfDuplex.
|
||||
|
||||
if !keptCS {
|
||||
for i := 0; i < 5; i++ {
|
||||
cmd = append(cmd, gpioSetD, idle, s.f.dbus.direction)
|
||||
}
|
||||
for i := 0; i < 5; i++ {
|
||||
cmd = append(cmd, gpioSetD, start1, s.f.dbus.direction)
|
||||
}
|
||||
}
|
||||
if s.edgeInvert {
|
||||
// This is needed to 'prime' the clock.
|
||||
for i := 0; i < 5; i++ {
|
||||
cmd = append(cmd, gpioSetD, start2, s.f.dbus.direction)
|
||||
}
|
||||
}
|
||||
op := mpsseTxOp(len(p.W) != 0, len(p.R) != 0, ew, er, s.lsbFirst)
|
||||
|
||||
// Do an I/O loop. We can mutate p here because it is a copy.
|
||||
// TODO(maruel): Have the pipeline cross the packet boundary.
|
||||
if len(p.W) == 0 {
|
||||
// Have the write buffer point to the read one. This saves from
|
||||
// allocating memory. The side effect is that it will write whatever
|
||||
// happened to be in the read buffer.
|
||||
p.W = p.R[:]
|
||||
}
|
||||
pendingRead := 0
|
||||
for len(p.W) != 0 {
|
||||
// op, sizelo, sizehi.
|
||||
chunk := len(buf) - 3 - len(cmd)
|
||||
if l := len(p.W); chunk > l {
|
||||
chunk = l
|
||||
}
|
||||
cmd = append(cmd, op, byte(chunk-1), byte((chunk-1)>>8))
|
||||
cmd = append(cmd, p.W[:chunk]...)
|
||||
p.W = p.W[chunk:]
|
||||
if _, err := s.f.h.WriteFast(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
cmd = buf[:0]
|
||||
|
||||
// TODO(maruel): Read 62 bytes at a time?
|
||||
// Delay reading by 512 bytes.
|
||||
if pendingRead >= 512 {
|
||||
if len(p.R) != 0 {
|
||||
// Align reads on 512 bytes exactly, aligned on USB packet size.
|
||||
if _, err := s.f.h.ReadAll(context.Background(), p.R[:512]); err != nil {
|
||||
return err
|
||||
}
|
||||
p.R = p.R[512:]
|
||||
pendingRead -= 512
|
||||
}
|
||||
}
|
||||
pendingRead += chunk
|
||||
}
|
||||
// Do not forget to read whatever is pending.
|
||||
// TODO(maruel): Investigate if a flush helps.
|
||||
if len(p.R) != 0 {
|
||||
// Send a flush to not wait for data.
|
||||
cmd = append(cmd, flush)
|
||||
if _, err := s.f.h.WriteFast(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
cmd = buf[:0]
|
||||
if _, err := s.f.h.ReadAll(context.Background(), p.R); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// TODO(maruel): Inject this in the write if it fits (it will generally
|
||||
// do). That will save one USB I/O, which is not insignificant.
|
||||
keptCS = p.KeepCS
|
||||
if !keptCS {
|
||||
cmd = append(cmd, flush)
|
||||
for i := 0; i < 5; i++ {
|
||||
cmd = append(cmd, gpioSetD, stop, s.f.dbus.direction)
|
||||
}
|
||||
for i := 0; i < 5; i++ {
|
||||
cmd = append(cmd, gpioSetD, idle, s.f.dbus.direction)
|
||||
}
|
||||
if _, err := s.f.h.WriteFast(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
cmd = buf[:0]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CLK returns the SCK (clock) pin.
|
||||
func (s *spiMPSEEConn) CLK() gpio.PinOut {
|
||||
return s.f.D0
|
||||
}
|
||||
|
||||
// MOSI returns the SDO (master out, slave in) pin.
|
||||
func (s *spiMPSEEConn) MOSI() gpio.PinOut {
|
||||
return s.f.D1
|
||||
}
|
||||
|
||||
// MISO returns the SDI (master in, slave out) pin.
|
||||
func (s *spiMPSEEConn) MISO() gpio.PinIn {
|
||||
return s.f.D2
|
||||
}
|
||||
|
||||
// CS returns the CSN (chip select) pin.
|
||||
func (s *spiMPSEEConn) CS() gpio.PinOut {
|
||||
return s.f.D3
|
||||
}
|
||||
|
||||
// resetIdle sets D0~D3. D0, D1 and D3 are output but only touch D3 is CS is
|
||||
// used.
|
||||
func (s *spiMPSEEConn) resetIdle() {
|
||||
const clk = byte(1) << 0
|
||||
const mosi = byte(1) << 1
|
||||
const miso = byte(1) << 2
|
||||
const cs = byte(1) << 3
|
||||
if !s.noCS {
|
||||
s.f.dbus.direction &= 0xF0
|
||||
s.f.dbus.direction |= cs
|
||||
s.f.dbus.value &= 0xF0
|
||||
s.f.dbus.value |= cs
|
||||
} else {
|
||||
s.f.dbus.value &= 0xF8
|
||||
s.f.dbus.direction &= 0xF8
|
||||
}
|
||||
s.f.dbus.direction |= mosi | clk
|
||||
if s.clkActiveLow {
|
||||
// Clock idles high.
|
||||
s.f.dbus.value |= clk
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// spiSyncPort is an SPI port over a FTDI device in synchronous bit-bang mode.
|
||||
type spiSyncPort struct {
|
||||
c spiSyncConn
|
||||
|
||||
// Mutable.
|
||||
maxFreq physic.Frequency
|
||||
}
|
||||
|
||||
func (s *spiSyncPort) Close() error {
|
||||
s.c.f.mu.Lock()
|
||||
s.c.f.usingSPI = false
|
||||
s.maxFreq = 0
|
||||
s.c.edgeInvert = false
|
||||
s.c.clkActiveLow = false
|
||||
s.c.noCS = false
|
||||
s.c.lsbFirst = false
|
||||
s.c.halfDuplex = false
|
||||
s.c.f.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *spiSyncPort) String() string {
|
||||
return s.c.f.String()
|
||||
}
|
||||
|
||||
const ft232rMaxSpeed = 3 * physic.MegaHertz
|
||||
|
||||
// Connect implements spi.Port.
|
||||
func (s *spiSyncPort) Connect(f physic.Frequency, m spi.Mode, bits int) (spi.Conn, error) {
|
||||
if f > physic.GigaHertz {
|
||||
return nil, fmt.Errorf("d2xx: invalid speed %s; maximum supported clock is 1.5MHz", f)
|
||||
}
|
||||
if f > ft232rMaxSpeed/2 {
|
||||
// TODO(maruel): Figure out a way to communicate that the speed was lowered.
|
||||
// https://github.com/google/periph/issues/255
|
||||
f = ft232rMaxSpeed / 2
|
||||
}
|
||||
if f < 100*physic.Hertz {
|
||||
return nil, fmt.Errorf("d2xx: invalid speed %s; minimum supported clock is 100Hz; did you forget to multiply by physic.MegaHertz?", f)
|
||||
}
|
||||
if bits&7 != 0 {
|
||||
return nil, errors.New("d2xx: bits must be multiple of 8")
|
||||
}
|
||||
if bits != 8 {
|
||||
return nil, errors.New("d2xx: implement bits per word above 8")
|
||||
}
|
||||
|
||||
s.c.f.mu.Lock()
|
||||
defer s.c.f.mu.Unlock()
|
||||
s.c.noCS = m&spi.NoCS != 0
|
||||
s.c.halfDuplex = m&spi.HalfDuplex != 0
|
||||
s.c.lsbFirst = m&spi.LSBFirst != 0
|
||||
m &^= spi.NoCS | spi.HalfDuplex | spi.LSBFirst
|
||||
if s.c.halfDuplex {
|
||||
return nil, errors.New("d2xx: spi.HalfDuplex is not yet supported (implementing wouldn't be too hard, please submit a PR")
|
||||
}
|
||||
if m < 0 || m > 3 {
|
||||
return nil, errors.New("d2xx: unknown spi mode")
|
||||
}
|
||||
s.c.edgeInvert = m&1 != 0
|
||||
s.c.clkActiveLow = m&2 != 0
|
||||
if s.maxFreq == 0 || f < s.maxFreq {
|
||||
if err := s.c.f.SetSpeed(f * 2); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.maxFreq = f
|
||||
}
|
||||
// D0, D2 and D3 are output. D4~D7 are kept as-is.
|
||||
const mosi = byte(1) << 0 // TX
|
||||
const miso = byte(1) << 1 // RX
|
||||
const clk = byte(1) << 2 // RTS
|
||||
const cs = byte(1) << 3 // CTS
|
||||
mask := mosi | clk | cs | (s.c.f.dmask & 0xF0)
|
||||
if err := s.c.f.setDBusMaskLocked(mask); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO(maruel): Combine both following calls if possible. We'd shave off a
|
||||
// few ms.
|
||||
if !s.c.noCS {
|
||||
// CTS/SPI_CS is active low.
|
||||
if err := s.c.f.dbusSyncGPIOOutLocked(3, gpio.High); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if s.c.clkActiveLow {
|
||||
// RTS/SPI_CLK is active low.
|
||||
if err := s.c.f.dbusSyncGPIOOutLocked(2, gpio.High); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
s.c.f.usingSPI = true
|
||||
return &s.c, nil
|
||||
}
|
||||
|
||||
// LimitSpeed implements spi.Port.
|
||||
func (s *spiSyncPort) LimitSpeed(f physic.Frequency) error {
|
||||
if f > physic.GigaHertz {
|
||||
return fmt.Errorf("d2xx: invalid speed %s; maximum supported clock is 1.5MHz", f)
|
||||
}
|
||||
if f < 100*physic.Hertz {
|
||||
return fmt.Errorf("d2xx: invalid speed %s; minimum supported clock is 100Hz; did you forget to multiply by physic.MegaHertz?", f)
|
||||
}
|
||||
s.c.f.mu.Lock()
|
||||
defer s.c.f.mu.Unlock()
|
||||
if s.maxFreq != 0 && s.maxFreq <= f {
|
||||
return nil
|
||||
}
|
||||
if err := s.c.f.SetSpeed(f * 2); err == nil {
|
||||
s.maxFreq = f
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CLK returns the SCK (clock) pin.
|
||||
func (s *spiSyncPort) CLK() gpio.PinOut {
|
||||
return s.c.CLK()
|
||||
}
|
||||
|
||||
// MOSI returns the SDO (master out, slave in) pin.
|
||||
func (s *spiSyncPort) MOSI() gpio.PinOut {
|
||||
return s.c.MOSI()
|
||||
}
|
||||
|
||||
// MISO returns the SDI (master in, slave out) pin.
|
||||
func (s *spiSyncPort) MISO() gpio.PinIn {
|
||||
return s.c.MISO()
|
||||
}
|
||||
|
||||
// CS returns the CSN (chip select) pin.
|
||||
func (s *spiSyncPort) CS() gpio.PinOut {
|
||||
return s.c.CS()
|
||||
}
|
||||
|
||||
type spiSyncConn struct {
|
||||
// Immutable.
|
||||
f *FT232R
|
||||
|
||||
// Initialized at Connect().
|
||||
edgeInvert bool // CPHA=1
|
||||
clkActiveLow bool // CPOL=1
|
||||
noCS bool // CS line is not changed
|
||||
lsbFirst bool // Default is MSB first
|
||||
halfDuplex bool // 3 wire mode
|
||||
}
|
||||
|
||||
func (s *spiSyncConn) String() string {
|
||||
return s.f.String()
|
||||
}
|
||||
|
||||
func (s *spiSyncConn) Tx(w, r []byte) error {
|
||||
var p = [1]spi.Packet{{W: w, R: r}}
|
||||
return s.TxPackets(p[:])
|
||||
}
|
||||
|
||||
func (s *spiSyncConn) Duplex() conn.Duplex {
|
||||
// TODO(maruel): Support half if there's a need.
|
||||
return conn.Full
|
||||
}
|
||||
|
||||
func (s *spiSyncConn) TxPackets(pkts []spi.Packet) error {
|
||||
// We need to 'expand' each bit 2 times * 8 bits, which leads
|
||||
// to a 16x memory usage increase. Adds 5 samples before and after.
|
||||
totalW := 0
|
||||
totalR := 0
|
||||
for _, p := range pkts {
|
||||
if p.KeepCS {
|
||||
return errors.New("d2xx: implement spi.Packet.KeepCS")
|
||||
}
|
||||
if p.BitsPerWord&7 != 0 {
|
||||
return errors.New("d2xx: bits must be a multiple of 8")
|
||||
}
|
||||
if p.BitsPerWord != 0 && p.BitsPerWord != 8 {
|
||||
return errors.New("d2xx: implement spi.Packet.BitsPerWord")
|
||||
}
|
||||
if err := verifyBuffers(p.W, p.R); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO(maruel): Correctly calculate offsets.
|
||||
if len(p.W) != 0 {
|
||||
totalW += 2 * 8 * len(p.W)
|
||||
}
|
||||
if len(p.R) != 0 {
|
||||
totalR += 2 * 8 * len(p.R)
|
||||
}
|
||||
}
|
||||
|
||||
// Create a large, single chunk.
|
||||
var we, re []byte
|
||||
if totalW != 0 {
|
||||
totalW += 10
|
||||
we = make([]byte, 0, totalW)
|
||||
}
|
||||
if totalR != 0 {
|
||||
totalR += 10
|
||||
re = make([]byte, totalR)
|
||||
}
|
||||
const mosi = byte(1) << 0 // TX
|
||||
const miso = byte(1) << 1 // RX
|
||||
const clk = byte(1) << 2 // RTS
|
||||
const cs = byte(1) << 3 // CTS
|
||||
|
||||
s.f.mu.Lock()
|
||||
defer s.f.mu.Unlock()
|
||||
|
||||
// https://en.wikipedia.org/wiki/Serial_Peripheral_Interface#Data_transmission
|
||||
|
||||
csActive := s.f.dvalue & s.f.dmask & 0xF0
|
||||
csIdle := csActive
|
||||
if !s.noCS {
|
||||
csIdle = csActive | cs
|
||||
}
|
||||
clkIdle := csActive
|
||||
clkActive := clkIdle | clk
|
||||
if s.clkActiveLow {
|
||||
clkActive, clkIdle = clkIdle, clkActive
|
||||
csIdle |= clk
|
||||
}
|
||||
// Start of tx; assert CS if needed.
|
||||
we = append(we, csIdle, clkIdle, clkIdle, clkIdle, clkIdle)
|
||||
for _, p := range pkts {
|
||||
if len(p.W) == 0 && len(p.R) == 0 {
|
||||
continue
|
||||
}
|
||||
// TODO(maruel): s.halfDuplex.
|
||||
for _, b := range p.W {
|
||||
for j := uint(0); j < 8; j++ {
|
||||
// For each bit, handle clock phase and data phase.
|
||||
bit := byte(0)
|
||||
if !s.lsbFirst {
|
||||
// MSBF
|
||||
if b&(0x80>>j) != 0 {
|
||||
bit = mosi
|
||||
}
|
||||
} else {
|
||||
// LSBF
|
||||
if b&(1<<j) != 0 {
|
||||
bit = mosi
|
||||
}
|
||||
}
|
||||
if !s.edgeInvert {
|
||||
// Mode0/2; CPHA=0
|
||||
we = append(we, clkIdle|bit, clkActive|bit)
|
||||
} else {
|
||||
// Mode1/3; CPHA=1
|
||||
we = append(we, clkActive|bit, clkIdle|bit)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// End of tx; deassert CS.
|
||||
we = append(we, clkIdle, clkIdle, clkIdle, clkIdle, csIdle)
|
||||
|
||||
if err := s.f.txLocked(we, re); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Extract data from re into r.
|
||||
for _, p := range pkts {
|
||||
// TODO(maruel): Correctly calculate offsets.
|
||||
if len(p.W) == 0 && len(p.R) == 0 {
|
||||
continue
|
||||
}
|
||||
// TODO(maruel): halfDuplex.
|
||||
for i := range p.R {
|
||||
// For each bit, read at the right data phase.
|
||||
b := byte(0)
|
||||
for j := 0; j < 8; j++ {
|
||||
if re[5+i*8*2+j*2+1]&byte(1)<<1 != 0 {
|
||||
if !s.lsbFirst {
|
||||
// MSBF
|
||||
b |= 0x80 >> uint(j)
|
||||
} else {
|
||||
// LSBF
|
||||
b |= 1 << uint(j)
|
||||
}
|
||||
}
|
||||
}
|
||||
p.R[i] = b
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CLK returns the SCK (clock) pin.
|
||||
func (s *spiSyncConn) CLK() gpio.PinOut {
|
||||
return s.f.D2 // RTS
|
||||
}
|
||||
|
||||
// MOSI returns the SDO (master out, slave in) pin.
|
||||
func (s *spiSyncConn) MOSI() gpio.PinOut {
|
||||
return s.f.D0 // TX
|
||||
}
|
||||
|
||||
// MISO returns the SDI (master in, slave out) pin.
|
||||
func (s *spiSyncConn) MISO() gpio.PinIn {
|
||||
return s.f.D1 // RX
|
||||
}
|
||||
|
||||
// CS returns the CSN (chip select) pin.
|
||||
func (s *spiSyncConn) CS() gpio.PinOut {
|
||||
return s.f.D3 // CTS
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
func verifyBuffers(w, r []byte) error {
|
||||
if len(w) != 0 {
|
||||
if len(r) != 0 {
|
||||
if len(w) != len(r) {
|
||||
return errors.New("d2xx: both buffers must have the same size")
|
||||
}
|
||||
}
|
||||
// TODO(maruel): When the buffer is >64Kb, cut it in parts and do not
|
||||
// request a flush. Still try to read though.
|
||||
if len(w) > 65536 {
|
||||
return errors.New("d2xx: maximum buffer size is 64Kb")
|
||||
}
|
||||
} else if len(r) != 0 {
|
||||
// TODO(maruel): Remove, this is not a problem.
|
||||
if len(r) > 65536 {
|
||||
return errors.New("d2xx: maximum buffer size is 64Kb")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ spi.PortCloser = &spiMPSEEPort{}
|
||||
var _ spi.Conn = &spiMPSEEConn{}
|
||||
var _ spi.PortCloser = &spiSyncPort{}
|
||||
var _ spi.Conn = &spiSyncConn{}
|
4
vendor/periph.io/x/host/v3/host.go
generated
vendored
4
vendor/periph.io/x/host/v3/host.go
generated
vendored
@ -6,7 +6,9 @@ package host
|
||||
|
||||
import (
|
||||
"periph.io/x/conn/v3/driver/driverreg"
|
||||
_ "periph.io/x/host/v3/ftdi"
|
||||
// TODO(maruel): For now do not include ftdi by default. It's not stable
|
||||
// enough to warrant being included.
|
||||
// _ "periph.io/x/host/v3/ftdi"
|
||||
)
|
||||
|
||||
// Init calls driverreg.Init() and returns it as-is.
|
||||
|
1
vendor/periph.io/x/host/v3/odroidc1/odroidc1_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/odroidc1/odroidc1_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm
|
||||
// +build !arm
|
||||
|
||||
package odroidc1
|
||||
|
1
vendor/periph.io/x/host/v3/pine64/pine64_arm64.go
generated
vendored
1
vendor/periph.io/x/host/v3/pine64/pine64_arm64.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build arm64
|
||||
// +build arm64
|
||||
|
||||
package pine64
|
||||
|
1
vendor/periph.io/x/host/v3/pine64/pine64_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/pine64/pine64_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm && !arm64
|
||||
// +build !arm,!arm64
|
||||
|
||||
package pine64
|
||||
|
1
vendor/periph.io/x/host/v3/pmem/mem_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/pmem/mem_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package pmem
|
||||
|
12
vendor/periph.io/x/host/v3/rpi/rpi.go
generated
vendored
12
vendor/periph.io/x/host/v3/rpi/rpi.go
generated
vendored
@ -384,6 +384,7 @@ const (
|
||||
memory1GB revisionCode = 2 << memoryShift
|
||||
memory2GB revisionCode = 3 << memoryShift
|
||||
memory4GB revisionCode = 4 << memoryShift
|
||||
memory8GB revisionCode = 5 << memoryShift
|
||||
|
||||
sonyUK revisionCode = 0 << manufacturerShift
|
||||
egoman revisionCode = 1 << manufacturerShift
|
||||
@ -413,6 +414,9 @@ const (
|
||||
boardReserved revisionCode = 0xf << boardShift
|
||||
boardCM3Plus revisionCode = 0x10 << boardShift
|
||||
board4B revisionCode = 0x11 << boardShift
|
||||
boardZero2W revisionCode = 0x12 << boardShift
|
||||
board400 revisionCode = 0x13 << boardShift
|
||||
boardCM4 revisionCode = 0x14 << boardShift
|
||||
)
|
||||
|
||||
// features represents the different features on various Raspberry Pi boards.
|
||||
@ -502,6 +506,14 @@ func (f *features) init(v uint32) error {
|
||||
f.hdrAudio = true
|
||||
f.audioLeft41 = true
|
||||
f.hdrHDMI = true
|
||||
case boardZero2W:
|
||||
f.hdrP1P40 = true
|
||||
f.hdrHDMI = true
|
||||
case board400:
|
||||
f.hdrP1P40 = true
|
||||
f.hdrHDMI = true
|
||||
case boardCM4:
|
||||
// Compute Module does not have a SODIMM header.
|
||||
default:
|
||||
return fmt.Errorf("rpi: unknown hardware version: 0x%x", r)
|
||||
}
|
||||
|
1
vendor/periph.io/x/host/v3/rpi/rpi_arm64.go
generated
vendored
1
vendor/periph.io/x/host/v3/rpi/rpi_arm64.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build arm64
|
||||
// +build arm64
|
||||
|
||||
package rpi
|
||||
|
1
vendor/periph.io/x/host/v3/rpi/rpi_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/rpi/rpi_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm && !arm64
|
||||
// +build !arm,!arm64
|
||||
|
||||
package rpi
|
||||
|
1
vendor/periph.io/x/host/v3/sysfs/fs_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/sysfs/fs_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package sysfs
|
||||
|
1
vendor/periph.io/x/host/v3/sysfs/sysfs_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/sysfs/sysfs_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package sysfs
|
||||
|
Loading…
x
Reference in New Issue
Block a user