소스 검색

Merge pull request #19588 from gballet/trezor-fix-ownlib

accounts/usbwallet: add webusb trezor support
Péter Szilágyi 6 년 전
부모
커밋
de38a1dbd4
100개의 변경된 파일15672개의 추가작업 그리고 15187개의 파일을 삭제
  1. 23 7
      accounts/usbwallet/hub.go
  2. 11 2
      accounts/usbwallet/trezor.go
  3. 811 0
      accounts/usbwallet/trezor/messages-common.pb.go
  4. 147 0
      accounts/usbwallet/trezor/messages-common.proto
  5. 698 0
      accounts/usbwallet/trezor/messages-ethereum.pb.go
  6. 131 0
      accounts/usbwallet/trezor/messages-ethereum.proto
  7. 1621 0
      accounts/usbwallet/trezor/messages-management.pb.go
  8. 289 0
      accounts/usbwallet/trezor/messages-management.proto
  9. 784 2976
      accounts/usbwallet/trezor/messages.pb.go
  10. 242 883
      accounts/usbwallet/trezor/messages.proto
  11. 28 4
      accounts/usbwallet/trezor/trezor.go
  12. 0 1333
      accounts/usbwallet/trezor/types.pb.go
  13. 0 278
      accounts/usbwallet/trezor/types.proto
  14. 3 3
      accounts/usbwallet/wallet.go
  15. 9 3
      node/config.go
  16. 11 4
      signer/core/api.go
  17. 0 3
      vendor/github.com/golang/protobuf/LICENSE
  18. 0 43
      vendor/github.com/golang/protobuf/proto/Makefile
  19. 35 11
      vendor/github.com/golang/protobuf/proto/clone.go
  20. 63 606
      vendor/github.com/golang/protobuf/proto/decode.go
  21. 63 0
      vendor/github.com/golang/protobuf/proto/deprecated.go
  22. 350 0
      vendor/github.com/golang/protobuf/proto/discard.go
  23. 25 1184
      vendor/github.com/golang/protobuf/proto/encode.go
  24. 17 16
      vendor/github.com/golang/protobuf/proto/equal.go
  25. 151 131
      vendor/github.com/golang/protobuf/proto/extensions.go
  26. 117 49
      vendor/github.com/golang/protobuf/proto/lib.go
  27. 4 134
      vendor/github.com/golang/protobuf/proto/message_set.go
  28. 237 361
      vendor/github.com/golang/protobuf/proto/pointer_reflect.go
  29. 210 167
      vendor/github.com/golang/protobuf/proto/pointer_unsafe.go
  30. 74 402
      vendor/github.com/golang/protobuf/proto/properties.go
  31. 2776 0
      vendor/github.com/golang/protobuf/proto/table_marshal.go
  32. 654 0
      vendor/github.com/golang/protobuf/proto/table_merge.go
  33. 2053 0
      vendor/github.com/golang/protobuf/proto/table_unmarshal.go
  34. 27 38
      vendor/github.com/golang/protobuf/proto/text.go
  35. 34 49
      vendor/github.com/golang/protobuf/proto/text_parser.go
  36. 0 36
      vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/Makefile
  37. 556 115
      vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go
  38. 883 0
      vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto
  39. 0 8
      vendor/github.com/karalabe/hid/LICENSE.md
  40. 0 53
      vendor/github.com/karalabe/hid/README.md
  41. 0 37
      vendor/github.com/karalabe/hid/hid.go
  42. 0 51
      vendor/github.com/karalabe/hid/hid_disabled.go
  43. 0 728
      vendor/github.com/karalabe/hid/libusb/libusb/os/poll_windows.c
  44. 0 55
      vendor/github.com/karalabe/hid/libusb/libusb/os/threads_posix.h
  45. 0 259
      vendor/github.com/karalabe/hid/libusb/libusb/os/threads_windows.c
  46. 0 63
      vendor/github.com/karalabe/hid/libusb/libusb/os/windows_nt_common.h
  47. 0 4290
      vendor/github.com/karalabe/hid/libusb/libusb/os/windows_winusb.c
  48. 0 1
      vendor/github.com/karalabe/hid/libusb/libusb/version_nano.h
  49. 6 0
      vendor/github.com/karalabe/usb/AUTHORS
  50. 165 0
      vendor/github.com/karalabe/usb/LICENSE
  51. 47 0
      vendor/github.com/karalabe/usb/README.md
  52. 3 3
      vendor/github.com/karalabe/usb/appveyor.yml
  53. 76 0
      vendor/github.com/karalabe/usb/demo.go
  54. 3 0
      vendor/github.com/karalabe/usb/go.mod
  55. 42 0
      vendor/github.com/karalabe/usb/hid_disabled.go
  56. 29 70
      vendor/github.com/karalabe/usb/hid_enabled.go
  57. 0 0
      vendor/github.com/karalabe/usb/hidapi/AUTHORS.txt
  58. 0 0
      vendor/github.com/karalabe/usb/hidapi/LICENSE-bsd.txt
  59. 0 0
      vendor/github.com/karalabe/usb/hidapi/LICENSE-gpl3.txt
  60. 0 0
      vendor/github.com/karalabe/usb/hidapi/LICENSE-orig.txt
  61. 0 0
      vendor/github.com/karalabe/usb/hidapi/LICENSE.txt
  62. 0 0
      vendor/github.com/karalabe/usb/hidapi/README.txt
  63. 0 0
      vendor/github.com/karalabe/usb/hidapi/hidapi/hidapi.h
  64. 0 0
      vendor/github.com/karalabe/usb/hidapi/libusb/hid.c
  65. 0 0
      vendor/github.com/karalabe/usb/hidapi/mac/hid.c
  66. 0 0
      vendor/github.com/karalabe/usb/hidapi/windows/hid.c
  67. 74 0
      vendor/github.com/karalabe/usb/libs.go
  68. 32 2
      vendor/github.com/karalabe/usb/libusb/AUTHORS
  69. 0 0
      vendor/github.com/karalabe/usb/libusb/COPYING
  70. 0 0
      vendor/github.com/karalabe/usb/libusb/libusb/config.h
  71. 201 145
      vendor/github.com/karalabe/usb/libusb/libusb/core.c
  72. 11 10
      vendor/github.com/karalabe/usb/libusb/libusb/descriptor.c
  73. 73 50
      vendor/github.com/karalabe/usb/libusb/libusb/hotplug.c
  74. 34 25
      vendor/github.com/karalabe/usb/libusb/libusb/hotplug.h
  75. 38 35
      vendor/github.com/karalabe/usb/libusb/libusb/io.c
  76. 63 32
      vendor/github.com/karalabe/usb/libusb/libusb/libusb.h
  77. 89 73
      vendor/github.com/karalabe/usb/libusb/libusb/libusbi.h
  78. 75 27
      vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.c
  79. 48 13
      vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.h
  80. 0 0
      vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_pollfs.cpp
  81. 0 0
      vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb.h
  82. 0 0
      vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_backend.cpp
  83. 5 2
      vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.cpp
  84. 0 0
      vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.h
  85. 37 28
      vendor/github.com/karalabe/usb/libusb/libusb/os/linux_netlink.c
  86. 26 8
      vendor/github.com/karalabe/usb/libusb/libusb/os/linux_udev.c
  87. 162 100
      vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.c
  88. 2 1
      vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.h
  89. 3 3
      vendor/github.com/karalabe/usb/libusb/libusb/os/netbsd_usb.c
  90. 3 3
      vendor/github.com/karalabe/usb/libusb/libusb/os/openbsd_usb.c
  91. 36 5
      vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.c
  92. 0 0
      vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.h
  93. 364 0
      vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.c
  94. 9 43
      vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.h
  95. 475 92
      vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.c
  96. 6 0
      vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.h
  97. 6 5
      vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.c
  98. 102 0
      vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.h
  99. 126 0
      vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.c
  100. 64 29
      vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.h

+ 23 - 7
accounts/usbwallet/hub.go

@@ -25,7 +25,7 @@ import (
 	"github.com/ethereum/go-ethereum/accounts"
 	"github.com/ethereum/go-ethereum/event"
 	"github.com/ethereum/go-ethereum/log"
-	"github.com/karalabe/hid"
+	"github.com/karalabe/usb"
 )
 
 // LedgerScheme is the protocol scheme prefixing account and wallet URLs.
@@ -84,14 +84,20 @@ func NewLedgerHub() (*Hub, error) {
 	}, 0xffa0, 0, newLedgerDriver)
 }
 
-// NewTrezorHub creates a new hardware wallet manager for Trezor devices.
-func NewTrezorHub() (*Hub, error) {
-	return newHub(TrezorScheme, 0x534c, []uint16{0x0001 /* Trezor 1 */}, 0xff00, 0, newTrezorDriver)
+// NewTrezorHubWithHID creates a new hardware wallet manager for Trezor devices.
+func NewTrezorHubWithHID() (*Hub, error) {
+	return newHub(TrezorScheme, 0x534c, []uint16{0x0001 /* Trezor HID */}, 0xff00, 0, newTrezorDriver)
+}
+
+// NewTrezorHubWithWebUSB creates a new hardware wallet manager for Trezor devices with
+// firmware version > 1.8.0
+func NewTrezorHubWithWebUSB() (*Hub, error) {
+	return newHub(TrezorScheme, 0x1209, []uint16{0x53c1 /* Trezor WebUSB */}, 0xffff /* No usage id on webusb, don't match unset (0) */, 0, newTrezorDriver)
 }
 
 // newHub creates a new hardware wallet manager for generic USB devices.
 func newHub(scheme string, vendorID uint16, productIDs []uint16, usageID uint16, endpointID int, makeDriver func(log.Logger) driver) (*Hub, error) {
-	if !hid.Supported() {
+	if !usb.Supported() {
 		return nil, errors.New("unsupported platform")
 	}
 	hub := &Hub{
@@ -133,7 +139,7 @@ func (hub *Hub) refreshWallets() {
 		return
 	}
 	// Retrieve the current list of USB wallet devices
-	var devices []hid.DeviceInfo
+	var devices []usb.DeviceInfo
 
 	if runtime.GOOS == "linux" {
 		// hidapi on Linux opens the device during enumeration to retrieve some infos,
@@ -148,8 +154,18 @@ func (hub *Hub) refreshWallets() {
 			return
 		}
 	}
-	for _, info := range hid.Enumerate(hub.vendorID, 0) {
+	infos, err := usb.Enumerate(hub.vendorID, 0)
+	if err != nil {
+		if runtime.GOOS == "linux" {
+			// See rationale before the enumeration why this is needed and only on Linux.
+			hub.commsLock.Unlock()
+		}
+		log.Error("error enumerating USB enumeration: ", "code", err)
+		return
+	}
+	for _, info := range infos {
 		for _, id := range hub.productIDs {
+			// Windows and Macos use UsageID matching, Linux uses Interface matching
 			if info.ProductID == id && (info.UsagePage == hub.usageID || info.Interface == hub.endpointID) {
 				devices = append(devices, info)
 				break

+ 11 - 2
accounts/usbwallet/trezor.go

@@ -192,7 +192,13 @@ func (w *trezorDriver) trezorDerive(derivationPath []uint32) (common.Address, er
 	if _, err := w.trezorExchange(&trezor.EthereumGetAddress{AddressN: derivationPath}, address); err != nil {
 		return common.Address{}, err
 	}
-	return common.BytesToAddress(address.GetAddress()), nil
+	if addr := address.GetAddressBin(); len(addr) > 0 { // Older firmwares use binary fomats
+		return common.BytesToAddress(addr), nil
+	}
+	if addr := address.GetAddressHex(); len(addr) > 0 { // Newer firmwares use hexadecimal fomats
+		return common.HexToAddress(addr), nil
+	}
+	return common.Address{}, errors.New("missing derived address")
 }
 
 // trezorSign sends the transaction to the Trezor wallet, and waits for the user
@@ -211,7 +217,10 @@ func (w *trezorDriver) trezorSign(derivationPath []uint32, tx *types.Transaction
 		DataLength: &length,
 	}
 	if to := tx.To(); to != nil {
-		request.To = (*to)[:] // Non contract deploy, set recipient explicitly
+		// Non contract deploy, set recipient explicitly
+		hex := to.Hex()
+		request.ToHex = &hex     // Newer firmwares (old will ignore)
+		request.ToBin = (*to)[:] // Older firmwares (new will ignore)
 	}
 	if length > 1024 { // Send the data chunked if that was requested
 		request.DataInitialChunk, data = data[:1024], data[1024:]

+ 811 - 0
accounts/usbwallet/trezor/messages-common.pb.go

@@ -0,0 +1,811 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: messages-common.proto
+
+package trezor
+
+import (
+	fmt "fmt"
+	math "math"
+
+	proto "github.com/golang/protobuf/proto"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type Failure_FailureType int32
+
+const (
+	Failure_Failure_UnexpectedMessage Failure_FailureType = 1
+	Failure_Failure_ButtonExpected    Failure_FailureType = 2
+	Failure_Failure_DataError         Failure_FailureType = 3
+	Failure_Failure_ActionCancelled   Failure_FailureType = 4
+	Failure_Failure_PinExpected       Failure_FailureType = 5
+	Failure_Failure_PinCancelled      Failure_FailureType = 6
+	Failure_Failure_PinInvalid        Failure_FailureType = 7
+	Failure_Failure_InvalidSignature  Failure_FailureType = 8
+	Failure_Failure_ProcessError      Failure_FailureType = 9
+	Failure_Failure_NotEnoughFunds    Failure_FailureType = 10
+	Failure_Failure_NotInitialized    Failure_FailureType = 11
+	Failure_Failure_PinMismatch       Failure_FailureType = 12
+	Failure_Failure_FirmwareError     Failure_FailureType = 99
+)
+
+var Failure_FailureType_name = map[int32]string{
+	1:  "Failure_UnexpectedMessage",
+	2:  "Failure_ButtonExpected",
+	3:  "Failure_DataError",
+	4:  "Failure_ActionCancelled",
+	5:  "Failure_PinExpected",
+	6:  "Failure_PinCancelled",
+	7:  "Failure_PinInvalid",
+	8:  "Failure_InvalidSignature",
+	9:  "Failure_ProcessError",
+	10: "Failure_NotEnoughFunds",
+	11: "Failure_NotInitialized",
+	12: "Failure_PinMismatch",
+	99: "Failure_FirmwareError",
+}
+
+var Failure_FailureType_value = map[string]int32{
+	"Failure_UnexpectedMessage": 1,
+	"Failure_ButtonExpected":    2,
+	"Failure_DataError":         3,
+	"Failure_ActionCancelled":   4,
+	"Failure_PinExpected":       5,
+	"Failure_PinCancelled":      6,
+	"Failure_PinInvalid":        7,
+	"Failure_InvalidSignature":  8,
+	"Failure_ProcessError":      9,
+	"Failure_NotEnoughFunds":    10,
+	"Failure_NotInitialized":    11,
+	"Failure_PinMismatch":       12,
+	"Failure_FirmwareError":     99,
+}
+
+func (x Failure_FailureType) Enum() *Failure_FailureType {
+	p := new(Failure_FailureType)
+	*p = x
+	return p
+}
+
+func (x Failure_FailureType) String() string {
+	return proto.EnumName(Failure_FailureType_name, int32(x))
+}
+
+func (x *Failure_FailureType) UnmarshalJSON(data []byte) error {
+	value, err := proto.UnmarshalJSONEnum(Failure_FailureType_value, data, "Failure_FailureType")
+	if err != nil {
+		return err
+	}
+	*x = Failure_FailureType(value)
+	return nil
+}
+
+func (Failure_FailureType) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_aaf30d059fdbc38d, []int{1, 0}
+}
+
+//*
+// Type of button request
+type ButtonRequest_ButtonRequestType int32
+
+const (
+	ButtonRequest_ButtonRequest_Other                 ButtonRequest_ButtonRequestType = 1
+	ButtonRequest_ButtonRequest_FeeOverThreshold      ButtonRequest_ButtonRequestType = 2
+	ButtonRequest_ButtonRequest_ConfirmOutput         ButtonRequest_ButtonRequestType = 3
+	ButtonRequest_ButtonRequest_ResetDevice           ButtonRequest_ButtonRequestType = 4
+	ButtonRequest_ButtonRequest_ConfirmWord           ButtonRequest_ButtonRequestType = 5
+	ButtonRequest_ButtonRequest_WipeDevice            ButtonRequest_ButtonRequestType = 6
+	ButtonRequest_ButtonRequest_ProtectCall           ButtonRequest_ButtonRequestType = 7
+	ButtonRequest_ButtonRequest_SignTx                ButtonRequest_ButtonRequestType = 8
+	ButtonRequest_ButtonRequest_FirmwareCheck         ButtonRequest_ButtonRequestType = 9
+	ButtonRequest_ButtonRequest_Address               ButtonRequest_ButtonRequestType = 10
+	ButtonRequest_ButtonRequest_PublicKey             ButtonRequest_ButtonRequestType = 11
+	ButtonRequest_ButtonRequest_MnemonicWordCount     ButtonRequest_ButtonRequestType = 12
+	ButtonRequest_ButtonRequest_MnemonicInput         ButtonRequest_ButtonRequestType = 13
+	ButtonRequest_ButtonRequest_PassphraseType        ButtonRequest_ButtonRequestType = 14
+	ButtonRequest_ButtonRequest_UnknownDerivationPath ButtonRequest_ButtonRequestType = 15
+)
+
+var ButtonRequest_ButtonRequestType_name = map[int32]string{
+	1:  "ButtonRequest_Other",
+	2:  "ButtonRequest_FeeOverThreshold",
+	3:  "ButtonRequest_ConfirmOutput",
+	4:  "ButtonRequest_ResetDevice",
+	5:  "ButtonRequest_ConfirmWord",
+	6:  "ButtonRequest_WipeDevice",
+	7:  "ButtonRequest_ProtectCall",
+	8:  "ButtonRequest_SignTx",
+	9:  "ButtonRequest_FirmwareCheck",
+	10: "ButtonRequest_Address",
+	11: "ButtonRequest_PublicKey",
+	12: "ButtonRequest_MnemonicWordCount",
+	13: "ButtonRequest_MnemonicInput",
+	14: "ButtonRequest_PassphraseType",
+	15: "ButtonRequest_UnknownDerivationPath",
+}
+
+var ButtonRequest_ButtonRequestType_value = map[string]int32{
+	"ButtonRequest_Other":                 1,
+	"ButtonRequest_FeeOverThreshold":      2,
+	"ButtonRequest_ConfirmOutput":         3,
+	"ButtonRequest_ResetDevice":           4,
+	"ButtonRequest_ConfirmWord":           5,
+	"ButtonRequest_WipeDevice":            6,
+	"ButtonRequest_ProtectCall":           7,
+	"ButtonRequest_SignTx":                8,
+	"ButtonRequest_FirmwareCheck":         9,
+	"ButtonRequest_Address":               10,
+	"ButtonRequest_PublicKey":             11,
+	"ButtonRequest_MnemonicWordCount":     12,
+	"ButtonRequest_MnemonicInput":         13,
+	"ButtonRequest_PassphraseType":        14,
+	"ButtonRequest_UnknownDerivationPath": 15,
+}
+
+func (x ButtonRequest_ButtonRequestType) Enum() *ButtonRequest_ButtonRequestType {
+	p := new(ButtonRequest_ButtonRequestType)
+	*p = x
+	return p
+}
+
+func (x ButtonRequest_ButtonRequestType) String() string {
+	return proto.EnumName(ButtonRequest_ButtonRequestType_name, int32(x))
+}
+
+func (x *ButtonRequest_ButtonRequestType) UnmarshalJSON(data []byte) error {
+	value, err := proto.UnmarshalJSONEnum(ButtonRequest_ButtonRequestType_value, data, "ButtonRequest_ButtonRequestType")
+	if err != nil {
+		return err
+	}
+	*x = ButtonRequest_ButtonRequestType(value)
+	return nil
+}
+
+func (ButtonRequest_ButtonRequestType) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_aaf30d059fdbc38d, []int{2, 0}
+}
+
+//*
+// Type of PIN request
+type PinMatrixRequest_PinMatrixRequestType int32
+
+const (
+	PinMatrixRequest_PinMatrixRequestType_Current   PinMatrixRequest_PinMatrixRequestType = 1
+	PinMatrixRequest_PinMatrixRequestType_NewFirst  PinMatrixRequest_PinMatrixRequestType = 2
+	PinMatrixRequest_PinMatrixRequestType_NewSecond PinMatrixRequest_PinMatrixRequestType = 3
+)
+
+var PinMatrixRequest_PinMatrixRequestType_name = map[int32]string{
+	1: "PinMatrixRequestType_Current",
+	2: "PinMatrixRequestType_NewFirst",
+	3: "PinMatrixRequestType_NewSecond",
+}
+
+var PinMatrixRequest_PinMatrixRequestType_value = map[string]int32{
+	"PinMatrixRequestType_Current":   1,
+	"PinMatrixRequestType_NewFirst":  2,
+	"PinMatrixRequestType_NewSecond": 3,
+}
+
+func (x PinMatrixRequest_PinMatrixRequestType) Enum() *PinMatrixRequest_PinMatrixRequestType {
+	p := new(PinMatrixRequest_PinMatrixRequestType)
+	*p = x
+	return p
+}
+
+func (x PinMatrixRequest_PinMatrixRequestType) String() string {
+	return proto.EnumName(PinMatrixRequest_PinMatrixRequestType_name, int32(x))
+}
+
+func (x *PinMatrixRequest_PinMatrixRequestType) UnmarshalJSON(data []byte) error {
+	value, err := proto.UnmarshalJSONEnum(PinMatrixRequest_PinMatrixRequestType_value, data, "PinMatrixRequest_PinMatrixRequestType")
+	if err != nil {
+		return err
+	}
+	*x = PinMatrixRequest_PinMatrixRequestType(value)
+	return nil
+}
+
+func (PinMatrixRequest_PinMatrixRequestType) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_aaf30d059fdbc38d, []int{4, 0}
+}
+
+//*
+// Response: Success of the previous request
+// @end
+type Success struct {
+	Message              *string  `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Success) Reset()         { *m = Success{} }
+func (m *Success) String() string { return proto.CompactTextString(m) }
+func (*Success) ProtoMessage()    {}
+func (*Success) Descriptor() ([]byte, []int) {
+	return fileDescriptor_aaf30d059fdbc38d, []int{0}
+}
+
+func (m *Success) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Success.Unmarshal(m, b)
+}
+func (m *Success) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Success.Marshal(b, m, deterministic)
+}
+func (m *Success) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Success.Merge(m, src)
+}
+func (m *Success) XXX_Size() int {
+	return xxx_messageInfo_Success.Size(m)
+}
+func (m *Success) XXX_DiscardUnknown() {
+	xxx_messageInfo_Success.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Success proto.InternalMessageInfo
+
+func (m *Success) GetMessage() string {
+	if m != nil && m.Message != nil {
+		return *m.Message
+	}
+	return ""
+}
+
+//*
+// Response: Failure of the previous request
+// @end
+type Failure struct {
+	Code                 *Failure_FailureType `protobuf:"varint,1,opt,name=code,enum=hw.trezor.messages.common.Failure_FailureType" json:"code,omitempty"`
+	Message              *string              `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}             `json:"-"`
+	XXX_unrecognized     []byte               `json:"-"`
+	XXX_sizecache        int32                `json:"-"`
+}
+
+func (m *Failure) Reset()         { *m = Failure{} }
+func (m *Failure) String() string { return proto.CompactTextString(m) }
+func (*Failure) ProtoMessage()    {}
+func (*Failure) Descriptor() ([]byte, []int) {
+	return fileDescriptor_aaf30d059fdbc38d, []int{1}
+}
+
+func (m *Failure) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Failure.Unmarshal(m, b)
+}
+func (m *Failure) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Failure.Marshal(b, m, deterministic)
+}
+func (m *Failure) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Failure.Merge(m, src)
+}
+func (m *Failure) XXX_Size() int {
+	return xxx_messageInfo_Failure.Size(m)
+}
+func (m *Failure) XXX_DiscardUnknown() {
+	xxx_messageInfo_Failure.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Failure proto.InternalMessageInfo
+
+func (m *Failure) GetCode() Failure_FailureType {
+	if m != nil && m.Code != nil {
+		return *m.Code
+	}
+	return Failure_Failure_UnexpectedMessage
+}
+
+func (m *Failure) GetMessage() string {
+	if m != nil && m.Message != nil {
+		return *m.Message
+	}
+	return ""
+}
+
+//*
+// Response: Device is waiting for HW button press.
+// @auxstart
+// @next ButtonAck
+type ButtonRequest struct {
+	Code                 *ButtonRequest_ButtonRequestType `protobuf:"varint,1,opt,name=code,enum=hw.trezor.messages.common.ButtonRequest_ButtonRequestType" json:"code,omitempty"`
+	Data                 *string                          `protobuf:"bytes,2,opt,name=data" json:"data,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}                         `json:"-"`
+	XXX_unrecognized     []byte                           `json:"-"`
+	XXX_sizecache        int32                            `json:"-"`
+}
+
+func (m *ButtonRequest) Reset()         { *m = ButtonRequest{} }
+func (m *ButtonRequest) String() string { return proto.CompactTextString(m) }
+func (*ButtonRequest) ProtoMessage()    {}
+func (*ButtonRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_aaf30d059fdbc38d, []int{2}
+}
+
+func (m *ButtonRequest) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ButtonRequest.Unmarshal(m, b)
+}
+func (m *ButtonRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ButtonRequest.Marshal(b, m, deterministic)
+}
+func (m *ButtonRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ButtonRequest.Merge(m, src)
+}
+func (m *ButtonRequest) XXX_Size() int {
+	return xxx_messageInfo_ButtonRequest.Size(m)
+}
+func (m *ButtonRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_ButtonRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ButtonRequest proto.InternalMessageInfo
+
+func (m *ButtonRequest) GetCode() ButtonRequest_ButtonRequestType {
+	if m != nil && m.Code != nil {
+		return *m.Code
+	}
+	return ButtonRequest_ButtonRequest_Other
+}
+
+func (m *ButtonRequest) GetData() string {
+	if m != nil && m.Data != nil {
+		return *m.Data
+	}
+	return ""
+}
+
+//*
+// Request: Computer agrees to wait for HW button press
+// @auxend
+type ButtonAck struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ButtonAck) Reset()         { *m = ButtonAck{} }
+func (m *ButtonAck) String() string { return proto.CompactTextString(m) }
+func (*ButtonAck) ProtoMessage()    {}
+func (*ButtonAck) Descriptor() ([]byte, []int) {
+	return fileDescriptor_aaf30d059fdbc38d, []int{3}
+}
+
+func (m *ButtonAck) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ButtonAck.Unmarshal(m, b)
+}
+func (m *ButtonAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ButtonAck.Marshal(b, m, deterministic)
+}
+func (m *ButtonAck) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ButtonAck.Merge(m, src)
+}
+func (m *ButtonAck) XXX_Size() int {
+	return xxx_messageInfo_ButtonAck.Size(m)
+}
+func (m *ButtonAck) XXX_DiscardUnknown() {
+	xxx_messageInfo_ButtonAck.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ButtonAck proto.InternalMessageInfo
+
+//*
+// Response: Device is asking computer to show PIN matrix and awaits PIN encoded using this matrix scheme
+// @auxstart
+// @next PinMatrixAck
+type PinMatrixRequest struct {
+	Type                 *PinMatrixRequest_PinMatrixRequestType `protobuf:"varint,1,opt,name=type,enum=hw.trezor.messages.common.PinMatrixRequest_PinMatrixRequestType" json:"type,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}                               `json:"-"`
+	XXX_unrecognized     []byte                                 `json:"-"`
+	XXX_sizecache        int32                                  `json:"-"`
+}
+
+func (m *PinMatrixRequest) Reset()         { *m = PinMatrixRequest{} }
+func (m *PinMatrixRequest) String() string { return proto.CompactTextString(m) }
+func (*PinMatrixRequest) ProtoMessage()    {}
+func (*PinMatrixRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_aaf30d059fdbc38d, []int{4}
+}
+
+func (m *PinMatrixRequest) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_PinMatrixRequest.Unmarshal(m, b)
+}
+func (m *PinMatrixRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_PinMatrixRequest.Marshal(b, m, deterministic)
+}
+func (m *PinMatrixRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PinMatrixRequest.Merge(m, src)
+}
+func (m *PinMatrixRequest) XXX_Size() int {
+	return xxx_messageInfo_PinMatrixRequest.Size(m)
+}
+func (m *PinMatrixRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_PinMatrixRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PinMatrixRequest proto.InternalMessageInfo
+
+func (m *PinMatrixRequest) GetType() PinMatrixRequest_PinMatrixRequestType {
+	if m != nil && m.Type != nil {
+		return *m.Type
+	}
+	return PinMatrixRequest_PinMatrixRequestType_Current
+}
+
+//*
+// Request: Computer responds with encoded PIN
+// @auxend
+type PinMatrixAck struct {
+	Pin                  *string  `protobuf:"bytes,1,req,name=pin" json:"pin,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *PinMatrixAck) Reset()         { *m = PinMatrixAck{} }
+func (m *PinMatrixAck) String() string { return proto.CompactTextString(m) }
+func (*PinMatrixAck) ProtoMessage()    {}
+func (*PinMatrixAck) Descriptor() ([]byte, []int) {
+	return fileDescriptor_aaf30d059fdbc38d, []int{5}
+}
+
+func (m *PinMatrixAck) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_PinMatrixAck.Unmarshal(m, b)
+}
+func (m *PinMatrixAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_PinMatrixAck.Marshal(b, m, deterministic)
+}
+func (m *PinMatrixAck) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PinMatrixAck.Merge(m, src)
+}
+func (m *PinMatrixAck) XXX_Size() int {
+	return xxx_messageInfo_PinMatrixAck.Size(m)
+}
+func (m *PinMatrixAck) XXX_DiscardUnknown() {
+	xxx_messageInfo_PinMatrixAck.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PinMatrixAck proto.InternalMessageInfo
+
+func (m *PinMatrixAck) GetPin() string {
+	if m != nil && m.Pin != nil {
+		return *m.Pin
+	}
+	return ""
+}
+
+//*
+// Response: Device awaits encryption passphrase
+// @auxstart
+// @next PassphraseAck
+type PassphraseRequest struct {
+	OnDevice             *bool    `protobuf:"varint,1,opt,name=on_device,json=onDevice" json:"on_device,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *PassphraseRequest) Reset()         { *m = PassphraseRequest{} }
+func (m *PassphraseRequest) String() string { return proto.CompactTextString(m) }
+func (*PassphraseRequest) ProtoMessage()    {}
+func (*PassphraseRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_aaf30d059fdbc38d, []int{6}
+}
+
+func (m *PassphraseRequest) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_PassphraseRequest.Unmarshal(m, b)
+}
+func (m *PassphraseRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_PassphraseRequest.Marshal(b, m, deterministic)
+}
+func (m *PassphraseRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PassphraseRequest.Merge(m, src)
+}
+func (m *PassphraseRequest) XXX_Size() int {
+	return xxx_messageInfo_PassphraseRequest.Size(m)
+}
+func (m *PassphraseRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_PassphraseRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PassphraseRequest proto.InternalMessageInfo
+
+func (m *PassphraseRequest) GetOnDevice() bool {
+	if m != nil && m.OnDevice != nil {
+		return *m.OnDevice
+	}
+	return false
+}
+
+//*
+// Request: Send passphrase back
+// @next PassphraseStateRequest
+type PassphraseAck struct {
+	Passphrase           *string  `protobuf:"bytes,1,opt,name=passphrase" json:"passphrase,omitempty"`
+	State                []byte   `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *PassphraseAck) Reset()         { *m = PassphraseAck{} }
+func (m *PassphraseAck) String() string { return proto.CompactTextString(m) }
+func (*PassphraseAck) ProtoMessage()    {}
+func (*PassphraseAck) Descriptor() ([]byte, []int) {
+	return fileDescriptor_aaf30d059fdbc38d, []int{7}
+}
+
+func (m *PassphraseAck) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_PassphraseAck.Unmarshal(m, b)
+}
+func (m *PassphraseAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_PassphraseAck.Marshal(b, m, deterministic)
+}
+func (m *PassphraseAck) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PassphraseAck.Merge(m, src)
+}
+func (m *PassphraseAck) XXX_Size() int {
+	return xxx_messageInfo_PassphraseAck.Size(m)
+}
+func (m *PassphraseAck) XXX_DiscardUnknown() {
+	xxx_messageInfo_PassphraseAck.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PassphraseAck proto.InternalMessageInfo
+
+func (m *PassphraseAck) GetPassphrase() string {
+	if m != nil && m.Passphrase != nil {
+		return *m.Passphrase
+	}
+	return ""
+}
+
+func (m *PassphraseAck) GetState() []byte {
+	if m != nil {
+		return m.State
+	}
+	return nil
+}
+
+//*
+// Response: Device awaits passphrase state
+// @next PassphraseStateAck
+type PassphraseStateRequest struct {
+	State                []byte   `protobuf:"bytes,1,opt,name=state" json:"state,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *PassphraseStateRequest) Reset()         { *m = PassphraseStateRequest{} }
+func (m *PassphraseStateRequest) String() string { return proto.CompactTextString(m) }
+func (*PassphraseStateRequest) ProtoMessage()    {}
+func (*PassphraseStateRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_aaf30d059fdbc38d, []int{8}
+}
+
+func (m *PassphraseStateRequest) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_PassphraseStateRequest.Unmarshal(m, b)
+}
+func (m *PassphraseStateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_PassphraseStateRequest.Marshal(b, m, deterministic)
+}
+func (m *PassphraseStateRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PassphraseStateRequest.Merge(m, src)
+}
+func (m *PassphraseStateRequest) XXX_Size() int {
+	return xxx_messageInfo_PassphraseStateRequest.Size(m)
+}
+func (m *PassphraseStateRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_PassphraseStateRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PassphraseStateRequest proto.InternalMessageInfo
+
+func (m *PassphraseStateRequest) GetState() []byte {
+	if m != nil {
+		return m.State
+	}
+	return nil
+}
+
+//*
+// Request: Send passphrase state back
+// @auxend
+type PassphraseStateAck struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *PassphraseStateAck) Reset()         { *m = PassphraseStateAck{} }
+func (m *PassphraseStateAck) String() string { return proto.CompactTextString(m) }
+func (*PassphraseStateAck) ProtoMessage()    {}
+func (*PassphraseStateAck) Descriptor() ([]byte, []int) {
+	return fileDescriptor_aaf30d059fdbc38d, []int{9}
+}
+
+func (m *PassphraseStateAck) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_PassphraseStateAck.Unmarshal(m, b)
+}
+func (m *PassphraseStateAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_PassphraseStateAck.Marshal(b, m, deterministic)
+}
+func (m *PassphraseStateAck) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_PassphraseStateAck.Merge(m, src)
+}
+func (m *PassphraseStateAck) XXX_Size() int {
+	return xxx_messageInfo_PassphraseStateAck.Size(m)
+}
+func (m *PassphraseStateAck) XXX_DiscardUnknown() {
+	xxx_messageInfo_PassphraseStateAck.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PassphraseStateAck proto.InternalMessageInfo
+
+//*
+// Structure representing BIP32 (hierarchical deterministic) node
+// Used for imports of private key into the device and exporting public key out of device
+// @embed
+type HDNodeType struct {
+	Depth                *uint32  `protobuf:"varint,1,req,name=depth" json:"depth,omitempty"`
+	Fingerprint          *uint32  `protobuf:"varint,2,req,name=fingerprint" json:"fingerprint,omitempty"`
+	ChildNum             *uint32  `protobuf:"varint,3,req,name=child_num,json=childNum" json:"child_num,omitempty"`
+	ChainCode            []byte   `protobuf:"bytes,4,req,name=chain_code,json=chainCode" json:"chain_code,omitempty"`
+	PrivateKey           []byte   `protobuf:"bytes,5,opt,name=private_key,json=privateKey" json:"private_key,omitempty"`
+	PublicKey            []byte   `protobuf:"bytes,6,opt,name=public_key,json=publicKey" json:"public_key,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *HDNodeType) Reset()         { *m = HDNodeType{} }
+func (m *HDNodeType) String() string { return proto.CompactTextString(m) }
+func (*HDNodeType) ProtoMessage()    {}
+func (*HDNodeType) Descriptor() ([]byte, []int) {
+	return fileDescriptor_aaf30d059fdbc38d, []int{10}
+}
+
+func (m *HDNodeType) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_HDNodeType.Unmarshal(m, b)
+}
+func (m *HDNodeType) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_HDNodeType.Marshal(b, m, deterministic)
+}
+func (m *HDNodeType) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_HDNodeType.Merge(m, src)
+}
+func (m *HDNodeType) XXX_Size() int {
+	return xxx_messageInfo_HDNodeType.Size(m)
+}
+func (m *HDNodeType) XXX_DiscardUnknown() {
+	xxx_messageInfo_HDNodeType.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_HDNodeType proto.InternalMessageInfo
+
+func (m *HDNodeType) GetDepth() uint32 {
+	if m != nil && m.Depth != nil {
+		return *m.Depth
+	}
+	return 0
+}
+
+func (m *HDNodeType) GetFingerprint() uint32 {
+	if m != nil && m.Fingerprint != nil {
+		return *m.Fingerprint
+	}
+	return 0
+}
+
+func (m *HDNodeType) GetChildNum() uint32 {
+	if m != nil && m.ChildNum != nil {
+		return *m.ChildNum
+	}
+	return 0
+}
+
+func (m *HDNodeType) GetChainCode() []byte {
+	if m != nil {
+		return m.ChainCode
+	}
+	return nil
+}
+
+func (m *HDNodeType) GetPrivateKey() []byte {
+	if m != nil {
+		return m.PrivateKey
+	}
+	return nil
+}
+
+func (m *HDNodeType) GetPublicKey() []byte {
+	if m != nil {
+		return m.PublicKey
+	}
+	return nil
+}
+
+func init() {
+	proto.RegisterEnum("hw.trezor.messages.common.Failure_FailureType", Failure_FailureType_name, Failure_FailureType_value)
+	proto.RegisterEnum("hw.trezor.messages.common.ButtonRequest_ButtonRequestType", ButtonRequest_ButtonRequestType_name, ButtonRequest_ButtonRequestType_value)
+	proto.RegisterEnum("hw.trezor.messages.common.PinMatrixRequest_PinMatrixRequestType", PinMatrixRequest_PinMatrixRequestType_name, PinMatrixRequest_PinMatrixRequestType_value)
+	proto.RegisterType((*Success)(nil), "hw.trezor.messages.common.Success")
+	proto.RegisterType((*Failure)(nil), "hw.trezor.messages.common.Failure")
+	proto.RegisterType((*ButtonRequest)(nil), "hw.trezor.messages.common.ButtonRequest")
+	proto.RegisterType((*ButtonAck)(nil), "hw.trezor.messages.common.ButtonAck")
+	proto.RegisterType((*PinMatrixRequest)(nil), "hw.trezor.messages.common.PinMatrixRequest")
+	proto.RegisterType((*PinMatrixAck)(nil), "hw.trezor.messages.common.PinMatrixAck")
+	proto.RegisterType((*PassphraseRequest)(nil), "hw.trezor.messages.common.PassphraseRequest")
+	proto.RegisterType((*PassphraseAck)(nil), "hw.trezor.messages.common.PassphraseAck")
+	proto.RegisterType((*PassphraseStateRequest)(nil), "hw.trezor.messages.common.PassphraseStateRequest")
+	proto.RegisterType((*PassphraseStateAck)(nil), "hw.trezor.messages.common.PassphraseStateAck")
+	proto.RegisterType((*HDNodeType)(nil), "hw.trezor.messages.common.HDNodeType")
+}
+
+func init() { proto.RegisterFile("messages-common.proto", fileDescriptor_aaf30d059fdbc38d) }
+
+var fileDescriptor_aaf30d059fdbc38d = []byte{
+	// 846 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x54, 0xcd, 0x52, 0x23, 0x37,
+	0x10, 0x2e, 0xff, 0x80, 0xed, 0xb6, 0xd9, 0x08, 0xc5, 0x80, 0x09, 0xb0, 0x38, 0xc3, 0x21, 0x5c,
+	0xe2, 0x4a, 0xe5, 0x98, 0x53, 0x58, 0x83, 0x2b, 0xd4, 0x16, 0x86, 0x1a, 0xd8, 0xda, 0xa3, 0x4b,
+	0xd1, 0xf4, 0x32, 0x2a, 0xcf, 0x48, 0x13, 0x8d, 0x06, 0xf0, 0x5e, 0xf2, 0x6a, 0x79, 0x89, 0xbc,
+	0x42, 0xaa, 0x52, 0xb9, 0xe4, 0x11, 0xb6, 0x34, 0x3f, 0x78, 0xc6, 0x66, 0x39, 0xcd, 0xe8, 0xfb,
+	0xbe, 0xee, 0x96, 0xba, 0x3f, 0x09, 0x76, 0x42, 0x8c, 0x63, 0x76, 0x8f, 0xf1, 0x8f, 0x5c, 0x85,
+	0xa1, 0x92, 0xa3, 0x48, 0x2b, 0xa3, 0xe8, 0xbe, 0xff, 0x38, 0x32, 0x1a, 0x3f, 0x2b, 0x3d, 0x2a,
+	0x04, 0xa3, 0x4c, 0xe0, 0x9c, 0x40, 0xeb, 0x36, 0xe1, 0x1c, 0xe3, 0x98, 0x0e, 0xa0, 0x95, 0xb3,
+	0x83, 0xda, 0xb0, 0x76, 0xda, 0x71, 0x8b, 0xa5, 0xf3, 0x77, 0x03, 0x5a, 0x13, 0x26, 0x82, 0x44,
+	0x23, 0x7d, 0x07, 0x4d, 0xae, 0xbc, 0x4c, 0xf2, 0xe6, 0xe7, 0xd1, 0xe8, 0xab, 0xa9, 0x47, 0x79,
+	0x44, 0xf1, 0xbd, 0x5b, 0x44, 0xe8, 0xa6, 0xb1, 0xe5, 0x4a, 0xf5, 0x6a, 0xa5, 0xff, 0xea, 0xd0,
+	0x2d, 0xe9, 0xe9, 0x11, 0xec, 0xe7, 0xcb, 0xd9, 0x07, 0x89, 0x4f, 0x11, 0x72, 0x83, 0xde, 0x55,
+	0x26, 0x26, 0x35, 0xfa, 0x1d, 0xec, 0x16, 0xf4, 0xbb, 0xc4, 0x18, 0x25, 0x2f, 0x72, 0x09, 0xa9,
+	0xd3, 0x1d, 0xd8, 0x2e, 0xb8, 0x73, 0x66, 0xd8, 0x85, 0xd6, 0x4a, 0x93, 0x06, 0x3d, 0x80, 0xbd,
+	0x02, 0x3e, 0xe3, 0x46, 0x28, 0x39, 0x66, 0x92, 0x63, 0x10, 0xa0, 0x47, 0x9a, 0x74, 0x0f, 0xbe,
+	0x2d, 0xc8, 0x1b, 0xb1, 0x4c, 0xb6, 0x41, 0x07, 0xd0, 0x2f, 0x11, 0xcb, 0x90, 0x4d, 0xba, 0x0b,
+	0xb4, 0xc4, 0x5c, 0xca, 0x07, 0x16, 0x08, 0x8f, 0xb4, 0xe8, 0x21, 0x0c, 0x0a, 0x3c, 0x07, 0x6f,
+	0xc5, 0xbd, 0x64, 0x26, 0xd1, 0x48, 0xda, 0x95, 0x7c, 0x5a, 0xd9, 0xf6, 0x67, 0xfb, 0xeb, 0x94,
+	0x8f, 0x34, 0x55, 0xe6, 0x42, 0xaa, 0xe4, 0xde, 0x9f, 0x24, 0xd2, 0x8b, 0x09, 0xac, 0x70, 0x97,
+	0x52, 0x18, 0xc1, 0x02, 0xf1, 0x19, 0x3d, 0xd2, 0x5d, 0xd9, 0xfa, 0x95, 0x88, 0x43, 0x66, 0xb8,
+	0x4f, 0x7a, 0x74, 0x1f, 0x76, 0x0a, 0x62, 0x22, 0x74, 0xf8, 0xc8, 0x34, 0x66, 0xb5, 0xb8, 0xf3,
+	0x4f, 0x13, 0xb6, 0xb2, 0xbe, 0xb9, 0xf8, 0x47, 0x82, 0xb1, 0xa1, 0xd3, 0xca, 0x74, 0x7f, 0x79,
+	0x65, 0xba, 0x95, 0xb8, 0xea, 0xaa, 0x34, 0x69, 0x0a, 0x4d, 0x8f, 0x19, 0x96, 0x8f, 0x39, 0xfd,
+	0x77, 0xfe, 0x6f, 0xc0, 0xf6, 0x9a, 0xde, 0xee, 0xbf, 0x02, 0xce, 0xae, 0x8d, 0x8f, 0x9a, 0xd4,
+	0xa8, 0x03, 0x6f, 0xab, 0xc4, 0x04, 0xf1, 0xfa, 0x01, 0xf5, 0x9d, 0xaf, 0x31, 0xf6, 0x55, 0x60,
+	0x67, 0x7d, 0x0c, 0x07, 0x55, 0xcd, 0x58, 0xc9, 0x4f, 0x42, 0x87, 0xd7, 0x89, 0x89, 0x12, 0x43,
+	0x1a, 0xd6, 0x47, 0x55, 0x81, 0x8b, 0x31, 0x9a, 0x73, 0x7c, 0x10, 0x1c, 0x49, 0x73, 0x9d, 0xce,
+	0xe3, 0x3f, 0x2a, 0x6d, 0xa7, 0x7f, 0x08, 0x83, 0x2a, 0xfd, 0x51, 0x44, 0x98, 0x07, 0x6f, 0xae,
+	0x07, 0xdf, 0x68, 0x65, 0x90, 0x9b, 0x31, 0x0b, 0x02, 0xd2, 0xb2, 0xa3, 0xae, 0xd2, 0xd6, 0x07,
+	0x77, 0x4f, 0xa4, 0xbd, 0xbe, 0xeb, 0x62, 0x3e, 0x63, 0x1f, 0xf9, 0x9c, 0x74, 0xec, 0xe8, 0xaa,
+	0x82, 0x33, 0xcf, 0xd3, 0x18, 0x5b, 0x2b, 0x1c, 0xc0, 0xde, 0x4a, 0xd1, 0xe4, 0xf7, 0x40, 0xf0,
+	0xf7, 0xb8, 0x20, 0x5d, 0x7a, 0x02, 0xc7, 0x55, 0xf2, 0x4a, 0x62, 0xa8, 0xa4, 0xe0, 0xf6, 0x3c,
+	0x63, 0x95, 0x48, 0x43, 0x7a, 0xeb, 0xd5, 0x0b, 0xd1, 0xa5, 0xb4, 0x3d, 0xdb, 0xa2, 0x43, 0x38,
+	0x5c, 0x29, 0xc1, 0xe2, 0x38, 0xf2, 0x35, 0x8b, 0xd3, 0xbb, 0x49, 0xde, 0xd0, 0x1f, 0xe0, 0xa4,
+	0xaa, 0xf8, 0x20, 0xe7, 0x52, 0x3d, 0xca, 0x73, 0xd4, 0xe2, 0x81, 0xd9, 0xcb, 0x75, 0xc3, 0x8c,
+	0x4f, 0xbe, 0x71, 0xba, 0xd0, 0xc9, 0x84, 0x67, 0x7c, 0xee, 0xfc, 0x5b, 0x03, 0x62, 0x2d, 0xca,
+	0x8c, 0x16, 0x4f, 0x85, 0xf1, 0xee, 0xa0, 0x69, 0x16, 0x51, 0x61, 0xbc, 0x5f, 0x5f, 0x31, 0xde,
+	0x6a, 0xe8, 0x1a, 0x90, 0xd9, 0xcf, 0x66, 0x73, 0xfe, 0x84, 0xfe, 0x4b, 0xac, 0x3d, 0xda, 0x4b,
+	0xf8, 0x6c, 0x9c, 0x68, 0x8d, 0xd2, 0x90, 0x1a, 0xfd, 0x1e, 0x8e, 0x5e, 0x54, 0x4c, 0xf1, 0x71,
+	0x22, 0x74, 0x6c, 0x48, 0xdd, 0x1a, 0xf3, 0x6b, 0x92, 0x5b, 0xe4, 0x4a, 0x7a, 0xa4, 0xe1, 0x0c,
+	0xa1, 0xf7, 0xac, 0x39, 0xe3, 0x73, 0x4a, 0xa0, 0x11, 0x09, 0x39, 0xa8, 0x0d, 0xeb, 0xa7, 0x1d,
+	0xd7, 0xfe, 0x3a, 0x3f, 0xc1, 0xf6, 0xb2, 0xaf, 0x45, 0x37, 0x0e, 0xa0, 0xa3, 0xe4, 0xcc, 0x4b,
+	0x1d, 0x96, 0xb6, 0xa4, 0xed, 0xb6, 0x95, 0xcc, 0x1c, 0xe7, 0x5c, 0xc0, 0xd6, 0x32, 0xc2, 0x26,
+	0x7d, 0x0b, 0x10, 0x3d, 0x03, 0xf9, 0xdb, 0x5d, 0x42, 0x68, 0x1f, 0x36, 0x62, 0xc3, 0x4c, 0xf6,
+	0xd8, 0xf6, 0xdc, 0x6c, 0xe1, 0x8c, 0x60, 0x77, 0x99, 0xe6, 0xd6, 0x42, 0x45, 0xf5, 0x67, 0x7d,
+	0xad, 0xac, 0xef, 0x03, 0x5d, 0xd1, 0xdb, 0x61, 0xfe, 0x55, 0x03, 0xf8, 0xed, 0x7c, 0xaa, 0xbc,
+	0xec, 0xbd, 0xee, 0xc3, 0x86, 0x87, 0x91, 0xf1, 0xd3, 0x13, 0x6e, 0xb9, 0xd9, 0x82, 0x0e, 0xa1,
+	0xfb, 0x49, 0xc8, 0x7b, 0xd4, 0x91, 0x16, 0xd2, 0x0c, 0xea, 0x29, 0x57, 0x86, 0xec, 0x81, 0xb9,
+	0x2f, 0x02, 0x6f, 0x26, 0x93, 0x70, 0xd0, 0x48, 0xf9, 0x76, 0x0a, 0x4c, 0x93, 0x90, 0x1e, 0x01,
+	0x70, 0x9f, 0x09, 0x39, 0x4b, 0x9f, 0xa6, 0xe6, 0xb0, 0x7e, 0xda, 0x73, 0x3b, 0x29, 0x32, 0xb6,
+	0x6f, 0xcc, 0x31, 0x74, 0xa3, 0xd4, 0x6f, 0x38, 0x9b, 0xe3, 0x62, 0xb0, 0x91, 0x6e, 0x1a, 0x72,
+	0xe8, 0x3d, 0x2e, 0x6c, 0x7c, 0x94, 0xde, 0x8e, 0x94, 0xdf, 0x4c, 0xf9, 0x4e, 0x54, 0xdc, 0x97,
+	0x2f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xb2, 0x7d, 0x20, 0xa6, 0x35, 0x07, 0x00, 0x00,
+}

+ 147 - 0
accounts/usbwallet/trezor/messages-common.proto

@@ -0,0 +1,147 @@
+// This file originates from the SatoshiLabs Trezor `common` repository at:
+//   https://github.com/trezor/trezor-common/blob/master/protob/messages-common.proto
+// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9.
+
+syntax = "proto2";
+package hw.trezor.messages.common;
+
+/**
+ * Response: Success of the previous request
+ * @end
+ */
+message Success {
+    optional string message = 1;    // human readable description of action or request-specific payload
+}
+
+/**
+ * Response: Failure of the previous request
+ * @end
+ */
+message Failure {
+    optional FailureType code = 1;  // computer-readable definition of the error state
+    optional string message = 2;    // human-readable message of the error state
+    enum FailureType {
+        Failure_UnexpectedMessage = 1;
+        Failure_ButtonExpected = 2;
+        Failure_DataError = 3;
+        Failure_ActionCancelled = 4;
+        Failure_PinExpected = 5;
+        Failure_PinCancelled = 6;
+        Failure_PinInvalid = 7;
+        Failure_InvalidSignature = 8;
+        Failure_ProcessError = 9;
+        Failure_NotEnoughFunds = 10;
+        Failure_NotInitialized = 11;
+        Failure_PinMismatch = 12;
+        Failure_FirmwareError = 99;
+    }
+}
+
+/**
+ * Response: Device is waiting for HW button press.
+ * @auxstart
+ * @next ButtonAck
+ */
+message ButtonRequest {
+    optional ButtonRequestType code = 1;
+    optional string data = 2;
+    /**
+    * Type of button request
+    */
+    enum ButtonRequestType {
+        ButtonRequest_Other = 1;
+        ButtonRequest_FeeOverThreshold = 2;
+        ButtonRequest_ConfirmOutput = 3;
+        ButtonRequest_ResetDevice = 4;
+        ButtonRequest_ConfirmWord = 5;
+        ButtonRequest_WipeDevice = 6;
+        ButtonRequest_ProtectCall = 7;
+        ButtonRequest_SignTx = 8;
+        ButtonRequest_FirmwareCheck = 9;
+        ButtonRequest_Address = 10;
+        ButtonRequest_PublicKey = 11;
+        ButtonRequest_MnemonicWordCount = 12;
+        ButtonRequest_MnemonicInput = 13;
+        ButtonRequest_PassphraseType = 14;
+        ButtonRequest_UnknownDerivationPath = 15;
+    }
+}
+
+/**
+ * Request: Computer agrees to wait for HW button press
+ * @auxend
+ */
+message ButtonAck {
+}
+
+/**
+ * Response: Device is asking computer to show PIN matrix and awaits PIN encoded using this matrix scheme
+ * @auxstart
+ * @next PinMatrixAck
+ */
+message PinMatrixRequest {
+    optional PinMatrixRequestType type = 1;
+    /**
+    * Type of PIN request
+    */
+    enum PinMatrixRequestType {
+        PinMatrixRequestType_Current = 1;
+        PinMatrixRequestType_NewFirst = 2;
+        PinMatrixRequestType_NewSecond = 3;
+    }
+}
+
+/**
+ * Request: Computer responds with encoded PIN
+ * @auxend
+ */
+message PinMatrixAck {
+    required string pin = 1;    // matrix encoded PIN entered by user
+}
+
+/**
+ * Response: Device awaits encryption passphrase
+ * @auxstart
+ * @next PassphraseAck
+ */
+message PassphraseRequest {
+    optional bool on_device = 1;    // passphrase is being entered on the device
+}
+
+/**
+ * Request: Send passphrase back
+ * @next PassphraseStateRequest
+ */
+message PassphraseAck {
+    optional string passphrase = 1;
+    optional bytes state = 2;       // expected device state
+}
+
+/**
+ * Response: Device awaits passphrase state
+ * @next PassphraseStateAck
+ */
+message PassphraseStateRequest {
+    optional bytes state = 1;       // actual device state
+}
+
+/**
+ * Request: Send passphrase state back
+ * @auxend
+ */
+message PassphraseStateAck {
+}
+
+/**
+ * Structure representing BIP32 (hierarchical deterministic) node
+ * Used for imports of private key into the device and exporting public key out of device
+ * @embed
+ */
+message HDNodeType {
+    required uint32 depth = 1;
+    required uint32 fingerprint = 2;
+    required uint32 child_num = 3;
+    required bytes chain_code = 4;
+    optional bytes private_key = 5;
+    optional bytes public_key = 6;
+}

+ 698 - 0
accounts/usbwallet/trezor/messages-ethereum.pb.go

@@ -0,0 +1,698 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: messages-ethereum.proto
+
+package trezor
+
+import (
+	fmt "fmt"
+	math "math"
+
+	proto "github.com/golang/protobuf/proto"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+//*
+// Request: Ask device for public key corresponding to address_n path
+// @start
+// @next EthereumPublicKey
+// @next Failure
+type EthereumGetPublicKey struct {
+	AddressN             []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
+	ShowDisplay          *bool    `protobuf:"varint,2,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *EthereumGetPublicKey) Reset()         { *m = EthereumGetPublicKey{} }
+func (m *EthereumGetPublicKey) String() string { return proto.CompactTextString(m) }
+func (*EthereumGetPublicKey) ProtoMessage()    {}
+func (*EthereumGetPublicKey) Descriptor() ([]byte, []int) {
+	return fileDescriptor_cb33f46ba915f15c, []int{0}
+}
+
+func (m *EthereumGetPublicKey) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_EthereumGetPublicKey.Unmarshal(m, b)
+}
+func (m *EthereumGetPublicKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_EthereumGetPublicKey.Marshal(b, m, deterministic)
+}
+func (m *EthereumGetPublicKey) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_EthereumGetPublicKey.Merge(m, src)
+}
+func (m *EthereumGetPublicKey) XXX_Size() int {
+	return xxx_messageInfo_EthereumGetPublicKey.Size(m)
+}
+func (m *EthereumGetPublicKey) XXX_DiscardUnknown() {
+	xxx_messageInfo_EthereumGetPublicKey.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EthereumGetPublicKey proto.InternalMessageInfo
+
+func (m *EthereumGetPublicKey) GetAddressN() []uint32 {
+	if m != nil {
+		return m.AddressN
+	}
+	return nil
+}
+
+func (m *EthereumGetPublicKey) GetShowDisplay() bool {
+	if m != nil && m.ShowDisplay != nil {
+		return *m.ShowDisplay
+	}
+	return false
+}
+
+//*
+// Response: Contains public key derived from device private seed
+// @end
+type EthereumPublicKey struct {
+	Node                 *HDNodeType `protobuf:"bytes,1,opt,name=node" json:"node,omitempty"`
+	Xpub                 *string     `protobuf:"bytes,2,opt,name=xpub" json:"xpub,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}    `json:"-"`
+	XXX_unrecognized     []byte      `json:"-"`
+	XXX_sizecache        int32       `json:"-"`
+}
+
+func (m *EthereumPublicKey) Reset()         { *m = EthereumPublicKey{} }
+func (m *EthereumPublicKey) String() string { return proto.CompactTextString(m) }
+func (*EthereumPublicKey) ProtoMessage()    {}
+func (*EthereumPublicKey) Descriptor() ([]byte, []int) {
+	return fileDescriptor_cb33f46ba915f15c, []int{1}
+}
+
+func (m *EthereumPublicKey) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_EthereumPublicKey.Unmarshal(m, b)
+}
+func (m *EthereumPublicKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_EthereumPublicKey.Marshal(b, m, deterministic)
+}
+func (m *EthereumPublicKey) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_EthereumPublicKey.Merge(m, src)
+}
+func (m *EthereumPublicKey) XXX_Size() int {
+	return xxx_messageInfo_EthereumPublicKey.Size(m)
+}
+func (m *EthereumPublicKey) XXX_DiscardUnknown() {
+	xxx_messageInfo_EthereumPublicKey.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EthereumPublicKey proto.InternalMessageInfo
+
+func (m *EthereumPublicKey) GetNode() *HDNodeType {
+	if m != nil {
+		return m.Node
+	}
+	return nil
+}
+
+func (m *EthereumPublicKey) GetXpub() string {
+	if m != nil && m.Xpub != nil {
+		return *m.Xpub
+	}
+	return ""
+}
+
+//*
+// Request: Ask device for Ethereum address corresponding to address_n path
+// @start
+// @next EthereumAddress
+// @next Failure
+type EthereumGetAddress struct {
+	AddressN             []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
+	ShowDisplay          *bool    `protobuf:"varint,2,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *EthereumGetAddress) Reset()         { *m = EthereumGetAddress{} }
+func (m *EthereumGetAddress) String() string { return proto.CompactTextString(m) }
+func (*EthereumGetAddress) ProtoMessage()    {}
+func (*EthereumGetAddress) Descriptor() ([]byte, []int) {
+	return fileDescriptor_cb33f46ba915f15c, []int{2}
+}
+
+func (m *EthereumGetAddress) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_EthereumGetAddress.Unmarshal(m, b)
+}
+func (m *EthereumGetAddress) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_EthereumGetAddress.Marshal(b, m, deterministic)
+}
+func (m *EthereumGetAddress) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_EthereumGetAddress.Merge(m, src)
+}
+func (m *EthereumGetAddress) XXX_Size() int {
+	return xxx_messageInfo_EthereumGetAddress.Size(m)
+}
+func (m *EthereumGetAddress) XXX_DiscardUnknown() {
+	xxx_messageInfo_EthereumGetAddress.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EthereumGetAddress proto.InternalMessageInfo
+
+func (m *EthereumGetAddress) GetAddressN() []uint32 {
+	if m != nil {
+		return m.AddressN
+	}
+	return nil
+}
+
+func (m *EthereumGetAddress) GetShowDisplay() bool {
+	if m != nil && m.ShowDisplay != nil {
+		return *m.ShowDisplay
+	}
+	return false
+}
+
+//*
+// Response: Contains an Ethereum address derived from device private seed
+// @end
+type EthereumAddress struct {
+	AddressBin           []byte   `protobuf:"bytes,1,opt,name=addressBin" json:"addressBin,omitempty"`
+	AddressHex           *string  `protobuf:"bytes,2,opt,name=addressHex" json:"addressHex,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *EthereumAddress) Reset()         { *m = EthereumAddress{} }
+func (m *EthereumAddress) String() string { return proto.CompactTextString(m) }
+func (*EthereumAddress) ProtoMessage()    {}
+func (*EthereumAddress) Descriptor() ([]byte, []int) {
+	return fileDescriptor_cb33f46ba915f15c, []int{3}
+}
+
+func (m *EthereumAddress) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_EthereumAddress.Unmarshal(m, b)
+}
+func (m *EthereumAddress) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_EthereumAddress.Marshal(b, m, deterministic)
+}
+func (m *EthereumAddress) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_EthereumAddress.Merge(m, src)
+}
+func (m *EthereumAddress) XXX_Size() int {
+	return xxx_messageInfo_EthereumAddress.Size(m)
+}
+func (m *EthereumAddress) XXX_DiscardUnknown() {
+	xxx_messageInfo_EthereumAddress.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EthereumAddress proto.InternalMessageInfo
+
+func (m *EthereumAddress) GetAddressBin() []byte {
+	if m != nil {
+		return m.AddressBin
+	}
+	return nil
+}
+
+func (m *EthereumAddress) GetAddressHex() string {
+	if m != nil && m.AddressHex != nil {
+		return *m.AddressHex
+	}
+	return ""
+}
+
+//*
+// Request: Ask device to sign transaction
+// All fields are optional from the protocol's point of view. Each field defaults to value `0` if missing.
+// Note: the first at most 1024 bytes of data MUST be transmitted as part of this message.
+// @start
+// @next EthereumTxRequest
+// @next Failure
+type EthereumSignTx struct {
+	AddressN             []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
+	Nonce                []byte   `protobuf:"bytes,2,opt,name=nonce" json:"nonce,omitempty"`
+	GasPrice             []byte   `protobuf:"bytes,3,opt,name=gas_price,json=gasPrice" json:"gas_price,omitempty"`
+	GasLimit             []byte   `protobuf:"bytes,4,opt,name=gas_limit,json=gasLimit" json:"gas_limit,omitempty"`
+	ToBin                []byte   `protobuf:"bytes,5,opt,name=toBin" json:"toBin,omitempty"`
+	ToHex                *string  `protobuf:"bytes,11,opt,name=toHex" json:"toHex,omitempty"`
+	Value                []byte   `protobuf:"bytes,6,opt,name=value" json:"value,omitempty"`
+	DataInitialChunk     []byte   `protobuf:"bytes,7,opt,name=data_initial_chunk,json=dataInitialChunk" json:"data_initial_chunk,omitempty"`
+	DataLength           *uint32  `protobuf:"varint,8,opt,name=data_length,json=dataLength" json:"data_length,omitempty"`
+	ChainId              *uint32  `protobuf:"varint,9,opt,name=chain_id,json=chainId" json:"chain_id,omitempty"`
+	TxType               *uint32  `protobuf:"varint,10,opt,name=tx_type,json=txType" json:"tx_type,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *EthereumSignTx) Reset()         { *m = EthereumSignTx{} }
+func (m *EthereumSignTx) String() string { return proto.CompactTextString(m) }
+func (*EthereumSignTx) ProtoMessage()    {}
+func (*EthereumSignTx) Descriptor() ([]byte, []int) {
+	return fileDescriptor_cb33f46ba915f15c, []int{4}
+}
+
+func (m *EthereumSignTx) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_EthereumSignTx.Unmarshal(m, b)
+}
+func (m *EthereumSignTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_EthereumSignTx.Marshal(b, m, deterministic)
+}
+func (m *EthereumSignTx) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_EthereumSignTx.Merge(m, src)
+}
+func (m *EthereumSignTx) XXX_Size() int {
+	return xxx_messageInfo_EthereumSignTx.Size(m)
+}
+func (m *EthereumSignTx) XXX_DiscardUnknown() {
+	xxx_messageInfo_EthereumSignTx.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EthereumSignTx proto.InternalMessageInfo
+
+func (m *EthereumSignTx) GetAddressN() []uint32 {
+	if m != nil {
+		return m.AddressN
+	}
+	return nil
+}
+
+func (m *EthereumSignTx) GetNonce() []byte {
+	if m != nil {
+		return m.Nonce
+	}
+	return nil
+}
+
+func (m *EthereumSignTx) GetGasPrice() []byte {
+	if m != nil {
+		return m.GasPrice
+	}
+	return nil
+}
+
+func (m *EthereumSignTx) GetGasLimit() []byte {
+	if m != nil {
+		return m.GasLimit
+	}
+	return nil
+}
+
+func (m *EthereumSignTx) GetToBin() []byte {
+	if m != nil {
+		return m.ToBin
+	}
+	return nil
+}
+
+func (m *EthereumSignTx) GetToHex() string {
+	if m != nil && m.ToHex != nil {
+		return *m.ToHex
+	}
+	return ""
+}
+
+func (m *EthereumSignTx) GetValue() []byte {
+	if m != nil {
+		return m.Value
+	}
+	return nil
+}
+
+func (m *EthereumSignTx) GetDataInitialChunk() []byte {
+	if m != nil {
+		return m.DataInitialChunk
+	}
+	return nil
+}
+
+func (m *EthereumSignTx) GetDataLength() uint32 {
+	if m != nil && m.DataLength != nil {
+		return *m.DataLength
+	}
+	return 0
+}
+
+func (m *EthereumSignTx) GetChainId() uint32 {
+	if m != nil && m.ChainId != nil {
+		return *m.ChainId
+	}
+	return 0
+}
+
+func (m *EthereumSignTx) GetTxType() uint32 {
+	if m != nil && m.TxType != nil {
+		return *m.TxType
+	}
+	return 0
+}
+
+//*
+// Response: Device asks for more data from transaction payload, or returns the signature.
+// If data_length is set, device awaits that many more bytes of payload.
+// Otherwise, the signature_* fields contain the computed transaction signature. All three fields will be present.
+// @end
+// @next EthereumTxAck
+type EthereumTxRequest struct {
+	DataLength           *uint32  `protobuf:"varint,1,opt,name=data_length,json=dataLength" json:"data_length,omitempty"`
+	SignatureV           *uint32  `protobuf:"varint,2,opt,name=signature_v,json=signatureV" json:"signature_v,omitempty"`
+	SignatureR           []byte   `protobuf:"bytes,3,opt,name=signature_r,json=signatureR" json:"signature_r,omitempty"`
+	SignatureS           []byte   `protobuf:"bytes,4,opt,name=signature_s,json=signatureS" json:"signature_s,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *EthereumTxRequest) Reset()         { *m = EthereumTxRequest{} }
+func (m *EthereumTxRequest) String() string { return proto.CompactTextString(m) }
+func (*EthereumTxRequest) ProtoMessage()    {}
+func (*EthereumTxRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_cb33f46ba915f15c, []int{5}
+}
+
+func (m *EthereumTxRequest) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_EthereumTxRequest.Unmarshal(m, b)
+}
+func (m *EthereumTxRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_EthereumTxRequest.Marshal(b, m, deterministic)
+}
+func (m *EthereumTxRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_EthereumTxRequest.Merge(m, src)
+}
+func (m *EthereumTxRequest) XXX_Size() int {
+	return xxx_messageInfo_EthereumTxRequest.Size(m)
+}
+func (m *EthereumTxRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_EthereumTxRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EthereumTxRequest proto.InternalMessageInfo
+
+func (m *EthereumTxRequest) GetDataLength() uint32 {
+	if m != nil && m.DataLength != nil {
+		return *m.DataLength
+	}
+	return 0
+}
+
+func (m *EthereumTxRequest) GetSignatureV() uint32 {
+	if m != nil && m.SignatureV != nil {
+		return *m.SignatureV
+	}
+	return 0
+}
+
+func (m *EthereumTxRequest) GetSignatureR() []byte {
+	if m != nil {
+		return m.SignatureR
+	}
+	return nil
+}
+
+func (m *EthereumTxRequest) GetSignatureS() []byte {
+	if m != nil {
+		return m.SignatureS
+	}
+	return nil
+}
+
+//*
+// Request: Transaction payload data.
+// @next EthereumTxRequest
+type EthereumTxAck struct {
+	DataChunk            []byte   `protobuf:"bytes,1,opt,name=data_chunk,json=dataChunk" json:"data_chunk,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *EthereumTxAck) Reset()         { *m = EthereumTxAck{} }
+func (m *EthereumTxAck) String() string { return proto.CompactTextString(m) }
+func (*EthereumTxAck) ProtoMessage()    {}
+func (*EthereumTxAck) Descriptor() ([]byte, []int) {
+	return fileDescriptor_cb33f46ba915f15c, []int{6}
+}
+
+func (m *EthereumTxAck) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_EthereumTxAck.Unmarshal(m, b)
+}
+func (m *EthereumTxAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_EthereumTxAck.Marshal(b, m, deterministic)
+}
+func (m *EthereumTxAck) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_EthereumTxAck.Merge(m, src)
+}
+func (m *EthereumTxAck) XXX_Size() int {
+	return xxx_messageInfo_EthereumTxAck.Size(m)
+}
+func (m *EthereumTxAck) XXX_DiscardUnknown() {
+	xxx_messageInfo_EthereumTxAck.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EthereumTxAck proto.InternalMessageInfo
+
+func (m *EthereumTxAck) GetDataChunk() []byte {
+	if m != nil {
+		return m.DataChunk
+	}
+	return nil
+}
+
+//*
+// Request: Ask device to sign message
+// @start
+// @next EthereumMessageSignature
+// @next Failure
+type EthereumSignMessage struct {
+	AddressN             []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
+	Message              []byte   `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *EthereumSignMessage) Reset()         { *m = EthereumSignMessage{} }
+func (m *EthereumSignMessage) String() string { return proto.CompactTextString(m) }
+func (*EthereumSignMessage) ProtoMessage()    {}
+func (*EthereumSignMessage) Descriptor() ([]byte, []int) {
+	return fileDescriptor_cb33f46ba915f15c, []int{7}
+}
+
+func (m *EthereumSignMessage) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_EthereumSignMessage.Unmarshal(m, b)
+}
+func (m *EthereumSignMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_EthereumSignMessage.Marshal(b, m, deterministic)
+}
+func (m *EthereumSignMessage) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_EthereumSignMessage.Merge(m, src)
+}
+func (m *EthereumSignMessage) XXX_Size() int {
+	return xxx_messageInfo_EthereumSignMessage.Size(m)
+}
+func (m *EthereumSignMessage) XXX_DiscardUnknown() {
+	xxx_messageInfo_EthereumSignMessage.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EthereumSignMessage proto.InternalMessageInfo
+
+func (m *EthereumSignMessage) GetAddressN() []uint32 {
+	if m != nil {
+		return m.AddressN
+	}
+	return nil
+}
+
+func (m *EthereumSignMessage) GetMessage() []byte {
+	if m != nil {
+		return m.Message
+	}
+	return nil
+}
+
+//*
+// Response: Signed message
+// @end
+type EthereumMessageSignature struct {
+	AddressBin           []byte   `protobuf:"bytes,1,opt,name=addressBin" json:"addressBin,omitempty"`
+	Signature            []byte   `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"`
+	AddressHex           *string  `protobuf:"bytes,3,opt,name=addressHex" json:"addressHex,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *EthereumMessageSignature) Reset()         { *m = EthereumMessageSignature{} }
+func (m *EthereumMessageSignature) String() string { return proto.CompactTextString(m) }
+func (*EthereumMessageSignature) ProtoMessage()    {}
+func (*EthereumMessageSignature) Descriptor() ([]byte, []int) {
+	return fileDescriptor_cb33f46ba915f15c, []int{8}
+}
+
+func (m *EthereumMessageSignature) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_EthereumMessageSignature.Unmarshal(m, b)
+}
+func (m *EthereumMessageSignature) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_EthereumMessageSignature.Marshal(b, m, deterministic)
+}
+func (m *EthereumMessageSignature) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_EthereumMessageSignature.Merge(m, src)
+}
+func (m *EthereumMessageSignature) XXX_Size() int {
+	return xxx_messageInfo_EthereumMessageSignature.Size(m)
+}
+func (m *EthereumMessageSignature) XXX_DiscardUnknown() {
+	xxx_messageInfo_EthereumMessageSignature.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EthereumMessageSignature proto.InternalMessageInfo
+
+func (m *EthereumMessageSignature) GetAddressBin() []byte {
+	if m != nil {
+		return m.AddressBin
+	}
+	return nil
+}
+
+func (m *EthereumMessageSignature) GetSignature() []byte {
+	if m != nil {
+		return m.Signature
+	}
+	return nil
+}
+
+func (m *EthereumMessageSignature) GetAddressHex() string {
+	if m != nil && m.AddressHex != nil {
+		return *m.AddressHex
+	}
+	return ""
+}
+
+//*
+// Request: Ask device to verify message
+// @start
+// @next Success
+// @next Failure
+type EthereumVerifyMessage struct {
+	AddressBin           []byte   `protobuf:"bytes,1,opt,name=addressBin" json:"addressBin,omitempty"`
+	Signature            []byte   `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"`
+	Message              []byte   `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"`
+	AddressHex           *string  `protobuf:"bytes,4,opt,name=addressHex" json:"addressHex,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *EthereumVerifyMessage) Reset()         { *m = EthereumVerifyMessage{} }
+func (m *EthereumVerifyMessage) String() string { return proto.CompactTextString(m) }
+func (*EthereumVerifyMessage) ProtoMessage()    {}
+func (*EthereumVerifyMessage) Descriptor() ([]byte, []int) {
+	return fileDescriptor_cb33f46ba915f15c, []int{9}
+}
+
+func (m *EthereumVerifyMessage) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_EthereumVerifyMessage.Unmarshal(m, b)
+}
+func (m *EthereumVerifyMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_EthereumVerifyMessage.Marshal(b, m, deterministic)
+}
+func (m *EthereumVerifyMessage) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_EthereumVerifyMessage.Merge(m, src)
+}
+func (m *EthereumVerifyMessage) XXX_Size() int {
+	return xxx_messageInfo_EthereumVerifyMessage.Size(m)
+}
+func (m *EthereumVerifyMessage) XXX_DiscardUnknown() {
+	xxx_messageInfo_EthereumVerifyMessage.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EthereumVerifyMessage proto.InternalMessageInfo
+
+func (m *EthereumVerifyMessage) GetAddressBin() []byte {
+	if m != nil {
+		return m.AddressBin
+	}
+	return nil
+}
+
+func (m *EthereumVerifyMessage) GetSignature() []byte {
+	if m != nil {
+		return m.Signature
+	}
+	return nil
+}
+
+func (m *EthereumVerifyMessage) GetMessage() []byte {
+	if m != nil {
+		return m.Message
+	}
+	return nil
+}
+
+func (m *EthereumVerifyMessage) GetAddressHex() string {
+	if m != nil && m.AddressHex != nil {
+		return *m.AddressHex
+	}
+	return ""
+}
+
+func init() {
+	proto.RegisterType((*EthereumGetPublicKey)(nil), "hw.trezor.messages.ethereum.EthereumGetPublicKey")
+	proto.RegisterType((*EthereumPublicKey)(nil), "hw.trezor.messages.ethereum.EthereumPublicKey")
+	proto.RegisterType((*EthereumGetAddress)(nil), "hw.trezor.messages.ethereum.EthereumGetAddress")
+	proto.RegisterType((*EthereumAddress)(nil), "hw.trezor.messages.ethereum.EthereumAddress")
+	proto.RegisterType((*EthereumSignTx)(nil), "hw.trezor.messages.ethereum.EthereumSignTx")
+	proto.RegisterType((*EthereumTxRequest)(nil), "hw.trezor.messages.ethereum.EthereumTxRequest")
+	proto.RegisterType((*EthereumTxAck)(nil), "hw.trezor.messages.ethereum.EthereumTxAck")
+	proto.RegisterType((*EthereumSignMessage)(nil), "hw.trezor.messages.ethereum.EthereumSignMessage")
+	proto.RegisterType((*EthereumMessageSignature)(nil), "hw.trezor.messages.ethereum.EthereumMessageSignature")
+	proto.RegisterType((*EthereumVerifyMessage)(nil), "hw.trezor.messages.ethereum.EthereumVerifyMessage")
+}
+
+func init() { proto.RegisterFile("messages-ethereum.proto", fileDescriptor_cb33f46ba915f15c) }
+
+var fileDescriptor_cb33f46ba915f15c = []byte{
+	// 593 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0x4d, 0x6f, 0xd3, 0x40,
+	0x10, 0x95, 0x9b, 0xb4, 0x49, 0x26, 0x0d, 0x1f, 0xa6, 0x55, 0x17, 0x0a, 0x34, 0x18, 0x21, 0xe5,
+	0x00, 0x3e, 0x70, 0x43, 0xe2, 0xd2, 0x52, 0x44, 0x2b, 0x4a, 0x55, 0xdc, 0xa8, 0x57, 0x6b, 0x63,
+	0x6f, 0xe3, 0x55, 0x9d, 0xdd, 0xe0, 0x5d, 0xb7, 0x0e, 0x7f, 0x82, 0x23, 0xff, 0x87, 0x5f, 0x86,
+	0xf6, 0x2b, 0x71, 0x52, 0x54, 0x0e, 0xbd, 0x65, 0xde, 0xbc, 0x7d, 0xf3, 0x66, 0xf4, 0x62, 0xd8,
+	0x99, 0x10, 0x21, 0xf0, 0x98, 0x88, 0x77, 0x44, 0x66, 0xa4, 0x20, 0xe5, 0x24, 0x9c, 0x16, 0x5c,
+	0x72, 0x7f, 0x37, 0xbb, 0x09, 0x65, 0x41, 0x7e, 0xf2, 0x22, 0x74, 0x94, 0xd0, 0x51, 0x9e, 0x6d,
+	0xcf, 0x5f, 0x25, 0x7c, 0x32, 0xe1, 0xcc, 0xbc, 0x09, 0x2e, 0x60, 0xeb, 0xb3, 0xa5, 0x7c, 0x21,
+	0xf2, 0xac, 0x1c, 0xe5, 0x34, 0xf9, 0x4a, 0x66, 0xfe, 0x2e, 0x74, 0x70, 0x9a, 0x16, 0x44, 0x88,
+	0x98, 0x21, 0xaf, 0xdf, 0x18, 0xf4, 0xa2, 0xb6, 0x05, 0x4e, 0xfd, 0x57, 0xb0, 0x29, 0x32, 0x7e,
+	0x13, 0xa7, 0x54, 0x4c, 0x73, 0x3c, 0x43, 0x6b, 0x7d, 0x6f, 0xd0, 0x8e, 0xba, 0x0a, 0x3b, 0x34,
+	0x50, 0x30, 0x82, 0xc7, 0x4e, 0x77, 0x21, 0xfa, 0x01, 0x9a, 0x8c, 0xa7, 0x04, 0x79, 0x7d, 0x6f,
+	0xd0, 0x7d, 0xff, 0x26, 0xfc, 0x87, 0x5f, 0x6b, 0xee, 0xe8, 0xf0, 0x94, 0xa7, 0x64, 0x38, 0x9b,
+	0x92, 0x48, 0x3f, 0xf1, 0x7d, 0x68, 0x56, 0xd3, 0x72, 0xa4, 0x47, 0x75, 0x22, 0xfd, 0x3b, 0x18,
+	0x82, 0x5f, 0xf3, 0xbe, 0x6f, 0xdc, 0xdd, 0xdb, 0xf9, 0x77, 0x78, 0xe8, 0x54, 0x9d, 0xe4, 0x4b,
+	0x00, 0xab, 0x70, 0x40, 0x99, 0x76, 0xbf, 0x19, 0xd5, 0x90, 0x5a, 0xff, 0x88, 0x54, 0xd6, 0x62,
+	0x0d, 0x09, 0xfe, 0xac, 0xc1, 0x03, 0xa7, 0x79, 0x4e, 0xc7, 0x6c, 0x58, 0xdd, 0xed, 0x72, 0x0b,
+	0xd6, 0x19, 0x67, 0x09, 0xd1, 0x52, 0x9b, 0x91, 0x29, 0xd4, 0x93, 0x31, 0x16, 0xf1, 0xb4, 0xa0,
+	0x09, 0x41, 0x0d, 0xdd, 0x69, 0x8f, 0xb1, 0x38, 0x53, 0xb5, 0x6b, 0xe6, 0x74, 0x42, 0x25, 0x6a,
+	0xce, 0x9b, 0x27, 0xaa, 0x56, 0x7a, 0x92, 0x2b, 0xeb, 0xeb, 0x46, 0x4f, 0x17, 0x06, 0x55, 0x86,
+	0xbb, 0xda, 0xb0, 0x29, 0x14, 0x7a, 0x8d, 0xf3, 0x92, 0xa0, 0x0d, 0xc3, 0xd5, 0x85, 0xff, 0x16,
+	0xfc, 0x14, 0x4b, 0x1c, 0x53, 0x46, 0x25, 0xc5, 0x79, 0x9c, 0x64, 0x25, 0xbb, 0x42, 0x2d, 0x4d,
+	0x79, 0xa4, 0x3a, 0xc7, 0xa6, 0xf1, 0x49, 0xe1, 0xfe, 0x1e, 0x74, 0x35, 0x3b, 0x27, 0x6c, 0x2c,
+	0x33, 0xd4, 0xee, 0x7b, 0x83, 0x5e, 0x04, 0x0a, 0x3a, 0xd1, 0x88, 0xff, 0x14, 0xda, 0x49, 0x86,
+	0x29, 0x8b, 0x69, 0x8a, 0x3a, 0xba, 0xdb, 0xd2, 0xf5, 0x71, 0xea, 0xef, 0x40, 0x4b, 0x56, 0xb1,
+	0x9c, 0x4d, 0x09, 0x02, 0xdd, 0xd9, 0x90, 0x95, 0xca, 0x41, 0xf0, 0xdb, 0x5b, 0x44, 0x6a, 0x58,
+	0x45, 0xe4, 0x47, 0x49, 0x84, 0x5c, 0x1d, 0xe5, 0xdd, 0x1a, 0xb5, 0x07, 0x5d, 0x41, 0xc7, 0x0c,
+	0xcb, 0xb2, 0x20, 0xf1, 0xb5, 0xbe, 0x68, 0x2f, 0x82, 0x39, 0x74, 0xb1, 0x4c, 0x28, 0xec, 0x61,
+	0x17, 0x84, 0x68, 0x99, 0x20, 0xec, 0x71, 0x17, 0x84, 0xf3, 0x20, 0x84, 0xde, 0xc2, 0xd8, 0x7e,
+	0x72, 0xe5, 0xbf, 0x00, 0xed, 0xc0, 0x5e, 0xc9, 0xe4, 0xa5, 0xa3, 0x10, 0x7d, 0x9e, 0xe0, 0x04,
+	0x9e, 0xd4, 0xd3, 0xf0, 0xcd, 0x64, 0xff, 0xee, 0x48, 0x20, 0x68, 0xd9, 0xff, 0x88, 0x0d, 0x85,
+	0x2b, 0x83, 0x0a, 0x90, 0x53, 0xb3, 0x4a, 0xe7, 0xce, 0xda, 0x7f, 0x83, 0xfb, 0x1c, 0x3a, 0xf3,
+	0x3d, 0xac, 0xee, 0x02, 0x58, 0x89, 0x75, 0xe3, 0x56, 0xac, 0x7f, 0x79, 0xb0, 0xed, 0x46, 0x5f,
+	0x90, 0x82, 0x5e, 0xce, 0xdc, 0x2a, 0xf7, 0x9b, 0x5b, 0xdb, 0xb5, 0xb1, 0xb4, 0xeb, 0x8a, 0xa3,
+	0xe6, 0xaa, 0xa3, 0x83, 0x8f, 0xf0, 0x3a, 0xe1, 0x93, 0x50, 0x60, 0xc9, 0x45, 0x46, 0x73, 0x3c,
+	0x12, 0xee, 0x03, 0x93, 0xd3, 0x91, 0xf9, 0xe2, 0x8d, 0xca, 0xcb, 0x83, 0xed, 0xa1, 0x06, 0xad,
+	0x5b, 0xb7, 0xc2, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8a, 0xce, 0x81, 0xc8, 0x59, 0x05, 0x00,
+	0x00,
+}

+ 131 - 0
accounts/usbwallet/trezor/messages-ethereum.proto

@@ -0,0 +1,131 @@
+// This file originates from the SatoshiLabs Trezor `common` repository at:
+//   https://github.com/trezor/trezor-common/blob/master/protob/messages-ethereum.proto
+// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9.
+
+syntax = "proto2";
+package hw.trezor.messages.ethereum;
+
+// Sugar for easier handling in Java
+option java_package = "com.satoshilabs.trezor.lib.protobuf";
+option java_outer_classname = "TrezorMessageEthereum";
+
+import "messages-common.proto";
+
+
+/**
+ * Request: Ask device for public key corresponding to address_n path
+ * @start
+ * @next EthereumPublicKey
+ * @next Failure
+ */
+message EthereumGetPublicKey {
+    repeated uint32 address_n = 1;                                      // BIP-32 path to derive the key from master node
+    optional bool show_display = 2;                                     // optionally show on display before sending the result
+}
+
+/**
+ * Response: Contains public key derived from device private seed
+ * @end
+ */
+message EthereumPublicKey {
+    optional hw.trezor.messages.common.HDNodeType node = 1;        // BIP32 public node
+    optional string xpub = 2;        // serialized form of public node
+}
+
+/**
+ * Request: Ask device for Ethereum address corresponding to address_n path
+ * @start
+ * @next EthereumAddress
+ * @next Failure
+ */
+message EthereumGetAddress {
+    repeated uint32 address_n = 1;  // BIP-32 path to derive the key from master node
+    optional bool show_display = 2; // optionally show on display before sending the result
+}
+
+/**
+ * Response: Contains an Ethereum address derived from device private seed
+ * @end
+ */
+message EthereumAddress {
+    optional bytes  addressBin = 1;    // Ethereum address as 20 bytes (legacy firmwares)
+    optional string addressHex = 2;    // Ethereum address as hex string (newer firmwares)
+}
+
+/**
+ * Request: Ask device to sign transaction
+ * All fields are optional from the protocol's point of view. Each field defaults to value `0` if missing.
+ * Note: the first at most 1024 bytes of data MUST be transmitted as part of this message.
+ * @start
+ * @next EthereumTxRequest
+ * @next Failure
+ */
+message EthereumSignTx {
+    repeated uint32 address_n = 1;          // BIP-32 path to derive the key from master node
+    optional bytes nonce = 2;               // <=256 bit unsigned big endian
+    optional bytes gas_price = 3;           // <=256 bit unsigned big endian (in wei)
+    optional bytes gas_limit = 4;           // <=256 bit unsigned big endian
+    optional bytes toBin = 5;               // recipient address (20 bytes, legacy firmware)
+    optional string toHex = 11;             // recipient address (hex string, newer firmware)
+    optional bytes value = 6;               // <=256 bit unsigned big endian (in wei)
+    optional bytes data_initial_chunk = 7;  // The initial data chunk (<= 1024 bytes)
+    optional uint32 data_length = 8;        // Length of transaction payload
+    optional uint32 chain_id = 9;           // Chain Id for EIP 155
+    optional uint32 tx_type = 10;           // (only for Wanchain)
+}
+
+/**
+ * Response: Device asks for more data from transaction payload, or returns the signature.
+ * If data_length is set, device awaits that many more bytes of payload.
+ * Otherwise, the signature_* fields contain the computed transaction signature. All three fields will be present.
+ * @end
+ * @next EthereumTxAck
+ */
+message EthereumTxRequest {
+    optional uint32 data_length = 1;    // Number of bytes being requested (<= 1024)
+    optional uint32 signature_v = 2;    // Computed signature (recovery parameter, limited to 27 or 28)
+    optional bytes signature_r = 3;     // Computed signature R component (256 bit)
+    optional bytes signature_s = 4;     // Computed signature S component (256 bit)
+}
+
+/**
+ * Request: Transaction payload data.
+ * @next EthereumTxRequest
+ */
+message EthereumTxAck {
+    optional bytes data_chunk = 1;  // Bytes from transaction payload (<= 1024 bytes)
+}
+
+/**
+ * Request: Ask device to sign message
+ * @start
+ * @next EthereumMessageSignature
+ * @next Failure
+ */
+message EthereumSignMessage {
+    repeated uint32 address_n = 1;  // BIP-32 path to derive the key from master node
+    optional bytes message = 2;     // message to be signed
+}
+
+/**
+ * Response: Signed message
+ * @end
+ */
+message EthereumMessageSignature {
+    optional bytes addressBin = 1;     // address used to sign the message (20 bytes, legacy firmware)
+    optional bytes signature = 2;      // signature of the message
+    optional string addressHex = 3;    // address used to sign the message (hex string, newer firmware)
+}
+
+/**
+ * Request: Ask device to verify message
+ * @start
+ * @next Success
+ * @next Failure
+ */
+message EthereumVerifyMessage {
+    optional bytes addressBin = 1;  // address to verify (20 bytes, legacy firmware)
+    optional bytes signature = 2;   // signature to verify
+    optional bytes message = 3;     // message to verify
+    optional string addressHex = 4; // address to verify (hex string, newer firmware)
+}

+ 1621 - 0
accounts/usbwallet/trezor/messages-management.pb.go

@@ -0,0 +1,1621 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: messages-management.proto
+
+package trezor
+
+import (
+	fmt "fmt"
+	math "math"
+
+	proto "github.com/golang/protobuf/proto"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+//*
+// Structure representing passphrase source
+type ApplySettings_PassphraseSourceType int32
+
+const (
+	ApplySettings_ASK    ApplySettings_PassphraseSourceType = 0
+	ApplySettings_DEVICE ApplySettings_PassphraseSourceType = 1
+	ApplySettings_HOST   ApplySettings_PassphraseSourceType = 2
+)
+
+var ApplySettings_PassphraseSourceType_name = map[int32]string{
+	0: "ASK",
+	1: "DEVICE",
+	2: "HOST",
+}
+
+var ApplySettings_PassphraseSourceType_value = map[string]int32{
+	"ASK":    0,
+	"DEVICE": 1,
+	"HOST":   2,
+}
+
+func (x ApplySettings_PassphraseSourceType) Enum() *ApplySettings_PassphraseSourceType {
+	p := new(ApplySettings_PassphraseSourceType)
+	*p = x
+	return p
+}
+
+func (x ApplySettings_PassphraseSourceType) String() string {
+	return proto.EnumName(ApplySettings_PassphraseSourceType_name, int32(x))
+}
+
+func (x *ApplySettings_PassphraseSourceType) UnmarshalJSON(data []byte) error {
+	value, err := proto.UnmarshalJSONEnum(ApplySettings_PassphraseSourceType_value, data, "ApplySettings_PassphraseSourceType")
+	if err != nil {
+		return err
+	}
+	*x = ApplySettings_PassphraseSourceType(value)
+	return nil
+}
+
+func (ApplySettings_PassphraseSourceType) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{4, 0}
+}
+
+//*
+// Type of recovery procedure. These should be used as bitmask, e.g.,
+// `RecoveryDeviceType_ScrambledWords | RecoveryDeviceType_Matrix`
+// listing every method supported by the host computer.
+//
+// Note that ScrambledWords must be supported by every implementation
+// for backward compatibility; there is no way to not support it.
+type RecoveryDevice_RecoveryDeviceType int32
+
+const (
+	// use powers of two when extending this field
+	RecoveryDevice_RecoveryDeviceType_ScrambledWords RecoveryDevice_RecoveryDeviceType = 0
+	RecoveryDevice_RecoveryDeviceType_Matrix         RecoveryDevice_RecoveryDeviceType = 1
+)
+
+var RecoveryDevice_RecoveryDeviceType_name = map[int32]string{
+	0: "RecoveryDeviceType_ScrambledWords",
+	1: "RecoveryDeviceType_Matrix",
+}
+
+var RecoveryDevice_RecoveryDeviceType_value = map[string]int32{
+	"RecoveryDeviceType_ScrambledWords": 0,
+	"RecoveryDeviceType_Matrix":         1,
+}
+
+func (x RecoveryDevice_RecoveryDeviceType) Enum() *RecoveryDevice_RecoveryDeviceType {
+	p := new(RecoveryDevice_RecoveryDeviceType)
+	*p = x
+	return p
+}
+
+func (x RecoveryDevice_RecoveryDeviceType) String() string {
+	return proto.EnumName(RecoveryDevice_RecoveryDeviceType_name, int32(x))
+}
+
+func (x *RecoveryDevice_RecoveryDeviceType) UnmarshalJSON(data []byte) error {
+	value, err := proto.UnmarshalJSONEnum(RecoveryDevice_RecoveryDeviceType_value, data, "RecoveryDevice_RecoveryDeviceType")
+	if err != nil {
+		return err
+	}
+	*x = RecoveryDevice_RecoveryDeviceType(value)
+	return nil
+}
+
+func (RecoveryDevice_RecoveryDeviceType) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{17, 0}
+}
+
+//*
+// Type of Recovery Word request
+type WordRequest_WordRequestType int32
+
+const (
+	WordRequest_WordRequestType_Plain   WordRequest_WordRequestType = 0
+	WordRequest_WordRequestType_Matrix9 WordRequest_WordRequestType = 1
+	WordRequest_WordRequestType_Matrix6 WordRequest_WordRequestType = 2
+)
+
+var WordRequest_WordRequestType_name = map[int32]string{
+	0: "WordRequestType_Plain",
+	1: "WordRequestType_Matrix9",
+	2: "WordRequestType_Matrix6",
+}
+
+var WordRequest_WordRequestType_value = map[string]int32{
+	"WordRequestType_Plain":   0,
+	"WordRequestType_Matrix9": 1,
+	"WordRequestType_Matrix6": 2,
+}
+
+func (x WordRequest_WordRequestType) Enum() *WordRequest_WordRequestType {
+	p := new(WordRequest_WordRequestType)
+	*p = x
+	return p
+}
+
+func (x WordRequest_WordRequestType) String() string {
+	return proto.EnumName(WordRequest_WordRequestType_name, int32(x))
+}
+
+func (x *WordRequest_WordRequestType) UnmarshalJSON(data []byte) error {
+	value, err := proto.UnmarshalJSONEnum(WordRequest_WordRequestType_value, data, "WordRequest_WordRequestType")
+	if err != nil {
+		return err
+	}
+	*x = WordRequest_WordRequestType(value)
+	return nil
+}
+
+func (WordRequest_WordRequestType) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{18, 0}
+}
+
+//*
+// Request: Reset device to default state and ask for device details
+// @start
+// @next Features
+type Initialize struct {
+	State                []byte   `protobuf:"bytes,1,opt,name=state" json:"state,omitempty"`
+	SkipPassphrase       *bool    `protobuf:"varint,2,opt,name=skip_passphrase,json=skipPassphrase" json:"skip_passphrase,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Initialize) Reset()         { *m = Initialize{} }
+func (m *Initialize) String() string { return proto.CompactTextString(m) }
+func (*Initialize) ProtoMessage()    {}
+func (*Initialize) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{0}
+}
+
+func (m *Initialize) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Initialize.Unmarshal(m, b)
+}
+func (m *Initialize) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Initialize.Marshal(b, m, deterministic)
+}
+func (m *Initialize) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Initialize.Merge(m, src)
+}
+func (m *Initialize) XXX_Size() int {
+	return xxx_messageInfo_Initialize.Size(m)
+}
+func (m *Initialize) XXX_DiscardUnknown() {
+	xxx_messageInfo_Initialize.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Initialize proto.InternalMessageInfo
+
+func (m *Initialize) GetState() []byte {
+	if m != nil {
+		return m.State
+	}
+	return nil
+}
+
+func (m *Initialize) GetSkipPassphrase() bool {
+	if m != nil && m.SkipPassphrase != nil {
+		return *m.SkipPassphrase
+	}
+	return false
+}
+
+//*
+// Request: Ask for device details (no device reset)
+// @start
+// @next Features
+type GetFeatures struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *GetFeatures) Reset()         { *m = GetFeatures{} }
+func (m *GetFeatures) String() string { return proto.CompactTextString(m) }
+func (*GetFeatures) ProtoMessage()    {}
+func (*GetFeatures) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{1}
+}
+
+func (m *GetFeatures) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_GetFeatures.Unmarshal(m, b)
+}
+func (m *GetFeatures) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_GetFeatures.Marshal(b, m, deterministic)
+}
+func (m *GetFeatures) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_GetFeatures.Merge(m, src)
+}
+func (m *GetFeatures) XXX_Size() int {
+	return xxx_messageInfo_GetFeatures.Size(m)
+}
+func (m *GetFeatures) XXX_DiscardUnknown() {
+	xxx_messageInfo_GetFeatures.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetFeatures proto.InternalMessageInfo
+
+//*
+// Response: Reports various information about the device
+// @end
+type Features struct {
+	Vendor               *string  `protobuf:"bytes,1,opt,name=vendor" json:"vendor,omitempty"`
+	MajorVersion         *uint32  `protobuf:"varint,2,opt,name=major_version,json=majorVersion" json:"major_version,omitempty"`
+	MinorVersion         *uint32  `protobuf:"varint,3,opt,name=minor_version,json=minorVersion" json:"minor_version,omitempty"`
+	PatchVersion         *uint32  `protobuf:"varint,4,opt,name=patch_version,json=patchVersion" json:"patch_version,omitempty"`
+	BootloaderMode       *bool    `protobuf:"varint,5,opt,name=bootloader_mode,json=bootloaderMode" json:"bootloader_mode,omitempty"`
+	DeviceId             *string  `protobuf:"bytes,6,opt,name=device_id,json=deviceId" json:"device_id,omitempty"`
+	PinProtection        *bool    `protobuf:"varint,7,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"`
+	PassphraseProtection *bool    `protobuf:"varint,8,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"`
+	Language             *string  `protobuf:"bytes,9,opt,name=language" json:"language,omitempty"`
+	Label                *string  `protobuf:"bytes,10,opt,name=label" json:"label,omitempty"`
+	Initialized          *bool    `protobuf:"varint,12,opt,name=initialized" json:"initialized,omitempty"`
+	Revision             []byte   `protobuf:"bytes,13,opt,name=revision" json:"revision,omitempty"`
+	BootloaderHash       []byte   `protobuf:"bytes,14,opt,name=bootloader_hash,json=bootloaderHash" json:"bootloader_hash,omitempty"`
+	Imported             *bool    `protobuf:"varint,15,opt,name=imported" json:"imported,omitempty"`
+	PinCached            *bool    `protobuf:"varint,16,opt,name=pin_cached,json=pinCached" json:"pin_cached,omitempty"`
+	PassphraseCached     *bool    `protobuf:"varint,17,opt,name=passphrase_cached,json=passphraseCached" json:"passphrase_cached,omitempty"`
+	FirmwarePresent      *bool    `protobuf:"varint,18,opt,name=firmware_present,json=firmwarePresent" json:"firmware_present,omitempty"`
+	NeedsBackup          *bool    `protobuf:"varint,19,opt,name=needs_backup,json=needsBackup" json:"needs_backup,omitempty"`
+	Flags                *uint32  `protobuf:"varint,20,opt,name=flags" json:"flags,omitempty"`
+	Model                *string  `protobuf:"bytes,21,opt,name=model" json:"model,omitempty"`
+	FwMajor              *uint32  `protobuf:"varint,22,opt,name=fw_major,json=fwMajor" json:"fw_major,omitempty"`
+	FwMinor              *uint32  `protobuf:"varint,23,opt,name=fw_minor,json=fwMinor" json:"fw_minor,omitempty"`
+	FwPatch              *uint32  `protobuf:"varint,24,opt,name=fw_patch,json=fwPatch" json:"fw_patch,omitempty"`
+	FwVendor             *string  `protobuf:"bytes,25,opt,name=fw_vendor,json=fwVendor" json:"fw_vendor,omitempty"`
+	FwVendorKeys         []byte   `protobuf:"bytes,26,opt,name=fw_vendor_keys,json=fwVendorKeys" json:"fw_vendor_keys,omitempty"`
+	UnfinishedBackup     *bool    `protobuf:"varint,27,opt,name=unfinished_backup,json=unfinishedBackup" json:"unfinished_backup,omitempty"`
+	NoBackup             *bool    `protobuf:"varint,28,opt,name=no_backup,json=noBackup" json:"no_backup,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Features) Reset()         { *m = Features{} }
+func (m *Features) String() string { return proto.CompactTextString(m) }
+func (*Features) ProtoMessage()    {}
+func (*Features) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{2}
+}
+
+func (m *Features) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Features.Unmarshal(m, b)
+}
+func (m *Features) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Features.Marshal(b, m, deterministic)
+}
+func (m *Features) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Features.Merge(m, src)
+}
+func (m *Features) XXX_Size() int {
+	return xxx_messageInfo_Features.Size(m)
+}
+func (m *Features) XXX_DiscardUnknown() {
+	xxx_messageInfo_Features.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Features proto.InternalMessageInfo
+
+func (m *Features) GetVendor() string {
+	if m != nil && m.Vendor != nil {
+		return *m.Vendor
+	}
+	return ""
+}
+
+func (m *Features) GetMajorVersion() uint32 {
+	if m != nil && m.MajorVersion != nil {
+		return *m.MajorVersion
+	}
+	return 0
+}
+
+func (m *Features) GetMinorVersion() uint32 {
+	if m != nil && m.MinorVersion != nil {
+		return *m.MinorVersion
+	}
+	return 0
+}
+
+func (m *Features) GetPatchVersion() uint32 {
+	if m != nil && m.PatchVersion != nil {
+		return *m.PatchVersion
+	}
+	return 0
+}
+
+func (m *Features) GetBootloaderMode() bool {
+	if m != nil && m.BootloaderMode != nil {
+		return *m.BootloaderMode
+	}
+	return false
+}
+
+func (m *Features) GetDeviceId() string {
+	if m != nil && m.DeviceId != nil {
+		return *m.DeviceId
+	}
+	return ""
+}
+
+func (m *Features) GetPinProtection() bool {
+	if m != nil && m.PinProtection != nil {
+		return *m.PinProtection
+	}
+	return false
+}
+
+func (m *Features) GetPassphraseProtection() bool {
+	if m != nil && m.PassphraseProtection != nil {
+		return *m.PassphraseProtection
+	}
+	return false
+}
+
+func (m *Features) GetLanguage() string {
+	if m != nil && m.Language != nil {
+		return *m.Language
+	}
+	return ""
+}
+
+func (m *Features) GetLabel() string {
+	if m != nil && m.Label != nil {
+		return *m.Label
+	}
+	return ""
+}
+
+func (m *Features) GetInitialized() bool {
+	if m != nil && m.Initialized != nil {
+		return *m.Initialized
+	}
+	return false
+}
+
+func (m *Features) GetRevision() []byte {
+	if m != nil {
+		return m.Revision
+	}
+	return nil
+}
+
+func (m *Features) GetBootloaderHash() []byte {
+	if m != nil {
+		return m.BootloaderHash
+	}
+	return nil
+}
+
+func (m *Features) GetImported() bool {
+	if m != nil && m.Imported != nil {
+		return *m.Imported
+	}
+	return false
+}
+
+func (m *Features) GetPinCached() bool {
+	if m != nil && m.PinCached != nil {
+		return *m.PinCached
+	}
+	return false
+}
+
+func (m *Features) GetPassphraseCached() bool {
+	if m != nil && m.PassphraseCached != nil {
+		return *m.PassphraseCached
+	}
+	return false
+}
+
+func (m *Features) GetFirmwarePresent() bool {
+	if m != nil && m.FirmwarePresent != nil {
+		return *m.FirmwarePresent
+	}
+	return false
+}
+
+func (m *Features) GetNeedsBackup() bool {
+	if m != nil && m.NeedsBackup != nil {
+		return *m.NeedsBackup
+	}
+	return false
+}
+
+func (m *Features) GetFlags() uint32 {
+	if m != nil && m.Flags != nil {
+		return *m.Flags
+	}
+	return 0
+}
+
+func (m *Features) GetModel() string {
+	if m != nil && m.Model != nil {
+		return *m.Model
+	}
+	return ""
+}
+
+func (m *Features) GetFwMajor() uint32 {
+	if m != nil && m.FwMajor != nil {
+		return *m.FwMajor
+	}
+	return 0
+}
+
+func (m *Features) GetFwMinor() uint32 {
+	if m != nil && m.FwMinor != nil {
+		return *m.FwMinor
+	}
+	return 0
+}
+
+func (m *Features) GetFwPatch() uint32 {
+	if m != nil && m.FwPatch != nil {
+		return *m.FwPatch
+	}
+	return 0
+}
+
+func (m *Features) GetFwVendor() string {
+	if m != nil && m.FwVendor != nil {
+		return *m.FwVendor
+	}
+	return ""
+}
+
+func (m *Features) GetFwVendorKeys() []byte {
+	if m != nil {
+		return m.FwVendorKeys
+	}
+	return nil
+}
+
+func (m *Features) GetUnfinishedBackup() bool {
+	if m != nil && m.UnfinishedBackup != nil {
+		return *m.UnfinishedBackup
+	}
+	return false
+}
+
+func (m *Features) GetNoBackup() bool {
+	if m != nil && m.NoBackup != nil {
+		return *m.NoBackup
+	}
+	return false
+}
+
+//*
+// Request: clear session (removes cached PIN, passphrase, etc).
+// @start
+// @next Success
+type ClearSession struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ClearSession) Reset()         { *m = ClearSession{} }
+func (m *ClearSession) String() string { return proto.CompactTextString(m) }
+func (*ClearSession) ProtoMessage()    {}
+func (*ClearSession) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{3}
+}
+
+func (m *ClearSession) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ClearSession.Unmarshal(m, b)
+}
+func (m *ClearSession) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ClearSession.Marshal(b, m, deterministic)
+}
+func (m *ClearSession) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ClearSession.Merge(m, src)
+}
+func (m *ClearSession) XXX_Size() int {
+	return xxx_messageInfo_ClearSession.Size(m)
+}
+func (m *ClearSession) XXX_DiscardUnknown() {
+	xxx_messageInfo_ClearSession.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ClearSession proto.InternalMessageInfo
+
+//*
+// Request: change language and/or label of the device
+// @start
+// @next Success
+// @next Failure
+type ApplySettings struct {
+	Language             *string                             `protobuf:"bytes,1,opt,name=language" json:"language,omitempty"`
+	Label                *string                             `protobuf:"bytes,2,opt,name=label" json:"label,omitempty"`
+	UsePassphrase        *bool                               `protobuf:"varint,3,opt,name=use_passphrase,json=usePassphrase" json:"use_passphrase,omitempty"`
+	Homescreen           []byte                              `protobuf:"bytes,4,opt,name=homescreen" json:"homescreen,omitempty"`
+	PassphraseSource     *ApplySettings_PassphraseSourceType `protobuf:"varint,5,opt,name=passphrase_source,json=passphraseSource,enum=hw.trezor.messages.management.ApplySettings_PassphraseSourceType" json:"passphrase_source,omitempty"`
+	AutoLockDelayMs      *uint32                             `protobuf:"varint,6,opt,name=auto_lock_delay_ms,json=autoLockDelayMs" json:"auto_lock_delay_ms,omitempty"`
+	DisplayRotation      *uint32                             `protobuf:"varint,7,opt,name=display_rotation,json=displayRotation" json:"display_rotation,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}                            `json:"-"`
+	XXX_unrecognized     []byte                              `json:"-"`
+	XXX_sizecache        int32                               `json:"-"`
+}
+
+func (m *ApplySettings) Reset()         { *m = ApplySettings{} }
+func (m *ApplySettings) String() string { return proto.CompactTextString(m) }
+func (*ApplySettings) ProtoMessage()    {}
+func (*ApplySettings) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{4}
+}
+
+func (m *ApplySettings) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ApplySettings.Unmarshal(m, b)
+}
+func (m *ApplySettings) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ApplySettings.Marshal(b, m, deterministic)
+}
+func (m *ApplySettings) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ApplySettings.Merge(m, src)
+}
+func (m *ApplySettings) XXX_Size() int {
+	return xxx_messageInfo_ApplySettings.Size(m)
+}
+func (m *ApplySettings) XXX_DiscardUnknown() {
+	xxx_messageInfo_ApplySettings.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ApplySettings proto.InternalMessageInfo
+
+func (m *ApplySettings) GetLanguage() string {
+	if m != nil && m.Language != nil {
+		return *m.Language
+	}
+	return ""
+}
+
+func (m *ApplySettings) GetLabel() string {
+	if m != nil && m.Label != nil {
+		return *m.Label
+	}
+	return ""
+}
+
+func (m *ApplySettings) GetUsePassphrase() bool {
+	if m != nil && m.UsePassphrase != nil {
+		return *m.UsePassphrase
+	}
+	return false
+}
+
+func (m *ApplySettings) GetHomescreen() []byte {
+	if m != nil {
+		return m.Homescreen
+	}
+	return nil
+}
+
+func (m *ApplySettings) GetPassphraseSource() ApplySettings_PassphraseSourceType {
+	if m != nil && m.PassphraseSource != nil {
+		return *m.PassphraseSource
+	}
+	return ApplySettings_ASK
+}
+
+func (m *ApplySettings) GetAutoLockDelayMs() uint32 {
+	if m != nil && m.AutoLockDelayMs != nil {
+		return *m.AutoLockDelayMs
+	}
+	return 0
+}
+
+func (m *ApplySettings) GetDisplayRotation() uint32 {
+	if m != nil && m.DisplayRotation != nil {
+		return *m.DisplayRotation
+	}
+	return 0
+}
+
+//*
+// Request: set flags of the device
+// @start
+// @next Success
+// @next Failure
+type ApplyFlags struct {
+	Flags                *uint32  `protobuf:"varint,1,opt,name=flags" json:"flags,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ApplyFlags) Reset()         { *m = ApplyFlags{} }
+func (m *ApplyFlags) String() string { return proto.CompactTextString(m) }
+func (*ApplyFlags) ProtoMessage()    {}
+func (*ApplyFlags) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{5}
+}
+
+func (m *ApplyFlags) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ApplyFlags.Unmarshal(m, b)
+}
+func (m *ApplyFlags) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ApplyFlags.Marshal(b, m, deterministic)
+}
+func (m *ApplyFlags) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ApplyFlags.Merge(m, src)
+}
+func (m *ApplyFlags) XXX_Size() int {
+	return xxx_messageInfo_ApplyFlags.Size(m)
+}
+func (m *ApplyFlags) XXX_DiscardUnknown() {
+	xxx_messageInfo_ApplyFlags.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ApplyFlags proto.InternalMessageInfo
+
+func (m *ApplyFlags) GetFlags() uint32 {
+	if m != nil && m.Flags != nil {
+		return *m.Flags
+	}
+	return 0
+}
+
+//*
+// Request: Starts workflow for setting/changing/removing the PIN
+// @start
+// @next Success
+// @next Failure
+type ChangePin struct {
+	Remove               *bool    `protobuf:"varint,1,opt,name=remove" json:"remove,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ChangePin) Reset()         { *m = ChangePin{} }
+func (m *ChangePin) String() string { return proto.CompactTextString(m) }
+func (*ChangePin) ProtoMessage()    {}
+func (*ChangePin) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{6}
+}
+
+func (m *ChangePin) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ChangePin.Unmarshal(m, b)
+}
+func (m *ChangePin) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ChangePin.Marshal(b, m, deterministic)
+}
+func (m *ChangePin) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ChangePin.Merge(m, src)
+}
+func (m *ChangePin) XXX_Size() int {
+	return xxx_messageInfo_ChangePin.Size(m)
+}
+func (m *ChangePin) XXX_DiscardUnknown() {
+	xxx_messageInfo_ChangePin.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ChangePin proto.InternalMessageInfo
+
+func (m *ChangePin) GetRemove() bool {
+	if m != nil && m.Remove != nil {
+		return *m.Remove
+	}
+	return false
+}
+
+//*
+// Request: Test if the device is alive, device sends back the message in Success response
+// @start
+// @next Success
+type Ping struct {
+	Message              *string  `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"`
+	ButtonProtection     *bool    `protobuf:"varint,2,opt,name=button_protection,json=buttonProtection" json:"button_protection,omitempty"`
+	PinProtection        *bool    `protobuf:"varint,3,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"`
+	PassphraseProtection *bool    `protobuf:"varint,4,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Ping) Reset()         { *m = Ping{} }
+func (m *Ping) String() string { return proto.CompactTextString(m) }
+func (*Ping) ProtoMessage()    {}
+func (*Ping) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{7}
+}
+
+func (m *Ping) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Ping.Unmarshal(m, b)
+}
+func (m *Ping) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Ping.Marshal(b, m, deterministic)
+}
+func (m *Ping) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Ping.Merge(m, src)
+}
+func (m *Ping) XXX_Size() int {
+	return xxx_messageInfo_Ping.Size(m)
+}
+func (m *Ping) XXX_DiscardUnknown() {
+	xxx_messageInfo_Ping.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Ping proto.InternalMessageInfo
+
+func (m *Ping) GetMessage() string {
+	if m != nil && m.Message != nil {
+		return *m.Message
+	}
+	return ""
+}
+
+func (m *Ping) GetButtonProtection() bool {
+	if m != nil && m.ButtonProtection != nil {
+		return *m.ButtonProtection
+	}
+	return false
+}
+
+func (m *Ping) GetPinProtection() bool {
+	if m != nil && m.PinProtection != nil {
+		return *m.PinProtection
+	}
+	return false
+}
+
+func (m *Ping) GetPassphraseProtection() bool {
+	if m != nil && m.PassphraseProtection != nil {
+		return *m.PassphraseProtection
+	}
+	return false
+}
+
+//*
+// Request: Abort last operation that required user interaction
+// @start
+// @next Failure
+type Cancel struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Cancel) Reset()         { *m = Cancel{} }
+func (m *Cancel) String() string { return proto.CompactTextString(m) }
+func (*Cancel) ProtoMessage()    {}
+func (*Cancel) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{8}
+}
+
+func (m *Cancel) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Cancel.Unmarshal(m, b)
+}
+func (m *Cancel) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Cancel.Marshal(b, m, deterministic)
+}
+func (m *Cancel) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Cancel.Merge(m, src)
+}
+func (m *Cancel) XXX_Size() int {
+	return xxx_messageInfo_Cancel.Size(m)
+}
+func (m *Cancel) XXX_DiscardUnknown() {
+	xxx_messageInfo_Cancel.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Cancel proto.InternalMessageInfo
+
+//*
+// Request: Request a sample of random data generated by hardware RNG. May be used for testing.
+// @start
+// @next Entropy
+// @next Failure
+type GetEntropy struct {
+	Size                 *uint32  `protobuf:"varint,1,req,name=size" json:"size,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *GetEntropy) Reset()         { *m = GetEntropy{} }
+func (m *GetEntropy) String() string { return proto.CompactTextString(m) }
+func (*GetEntropy) ProtoMessage()    {}
+func (*GetEntropy) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{9}
+}
+
+func (m *GetEntropy) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_GetEntropy.Unmarshal(m, b)
+}
+func (m *GetEntropy) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_GetEntropy.Marshal(b, m, deterministic)
+}
+func (m *GetEntropy) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_GetEntropy.Merge(m, src)
+}
+func (m *GetEntropy) XXX_Size() int {
+	return xxx_messageInfo_GetEntropy.Size(m)
+}
+func (m *GetEntropy) XXX_DiscardUnknown() {
+	xxx_messageInfo_GetEntropy.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetEntropy proto.InternalMessageInfo
+
+func (m *GetEntropy) GetSize() uint32 {
+	if m != nil && m.Size != nil {
+		return *m.Size
+	}
+	return 0
+}
+
+//*
+// Response: Reply with random data generated by internal RNG
+// @end
+type Entropy struct {
+	Entropy              []byte   `protobuf:"bytes,1,req,name=entropy" json:"entropy,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Entropy) Reset()         { *m = Entropy{} }
+func (m *Entropy) String() string { return proto.CompactTextString(m) }
+func (*Entropy) ProtoMessage()    {}
+func (*Entropy) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{10}
+}
+
+func (m *Entropy) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Entropy.Unmarshal(m, b)
+}
+func (m *Entropy) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Entropy.Marshal(b, m, deterministic)
+}
+func (m *Entropy) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Entropy.Merge(m, src)
+}
+func (m *Entropy) XXX_Size() int {
+	return xxx_messageInfo_Entropy.Size(m)
+}
+func (m *Entropy) XXX_DiscardUnknown() {
+	xxx_messageInfo_Entropy.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Entropy proto.InternalMessageInfo
+
+func (m *Entropy) GetEntropy() []byte {
+	if m != nil {
+		return m.Entropy
+	}
+	return nil
+}
+
+//*
+// Request: Request device to wipe all sensitive data and settings
+// @start
+// @next Success
+// @next Failure
+type WipeDevice struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *WipeDevice) Reset()         { *m = WipeDevice{} }
+func (m *WipeDevice) String() string { return proto.CompactTextString(m) }
+func (*WipeDevice) ProtoMessage()    {}
+func (*WipeDevice) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{11}
+}
+
+func (m *WipeDevice) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_WipeDevice.Unmarshal(m, b)
+}
+func (m *WipeDevice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_WipeDevice.Marshal(b, m, deterministic)
+}
+func (m *WipeDevice) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_WipeDevice.Merge(m, src)
+}
+func (m *WipeDevice) XXX_Size() int {
+	return xxx_messageInfo_WipeDevice.Size(m)
+}
+func (m *WipeDevice) XXX_DiscardUnknown() {
+	xxx_messageInfo_WipeDevice.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WipeDevice proto.InternalMessageInfo
+
+//*
+// Request: Load seed and related internal settings from the computer
+// @start
+// @next Success
+// @next Failure
+type LoadDevice struct {
+	Mnemonic             *string     `protobuf:"bytes,1,opt,name=mnemonic" json:"mnemonic,omitempty"`
+	Node                 *HDNodeType `protobuf:"bytes,2,opt,name=node" json:"node,omitempty"`
+	Pin                  *string     `protobuf:"bytes,3,opt,name=pin" json:"pin,omitempty"`
+	PassphraseProtection *bool       `protobuf:"varint,4,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"`
+	Language             *string     `protobuf:"bytes,5,opt,name=language,def=english" json:"language,omitempty"`
+	Label                *string     `protobuf:"bytes,6,opt,name=label" json:"label,omitempty"`
+	SkipChecksum         *bool       `protobuf:"varint,7,opt,name=skip_checksum,json=skipChecksum" json:"skip_checksum,omitempty"`
+	U2FCounter           *uint32     `protobuf:"varint,8,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}    `json:"-"`
+	XXX_unrecognized     []byte      `json:"-"`
+	XXX_sizecache        int32       `json:"-"`
+}
+
+func (m *LoadDevice) Reset()         { *m = LoadDevice{} }
+func (m *LoadDevice) String() string { return proto.CompactTextString(m) }
+func (*LoadDevice) ProtoMessage()    {}
+func (*LoadDevice) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{12}
+}
+
+func (m *LoadDevice) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_LoadDevice.Unmarshal(m, b)
+}
+func (m *LoadDevice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_LoadDevice.Marshal(b, m, deterministic)
+}
+func (m *LoadDevice) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_LoadDevice.Merge(m, src)
+}
+func (m *LoadDevice) XXX_Size() int {
+	return xxx_messageInfo_LoadDevice.Size(m)
+}
+func (m *LoadDevice) XXX_DiscardUnknown() {
+	xxx_messageInfo_LoadDevice.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_LoadDevice proto.InternalMessageInfo
+
+const Default_LoadDevice_Language string = "english"
+
+func (m *LoadDevice) GetMnemonic() string {
+	if m != nil && m.Mnemonic != nil {
+		return *m.Mnemonic
+	}
+	return ""
+}
+
+func (m *LoadDevice) GetNode() *HDNodeType {
+	if m != nil {
+		return m.Node
+	}
+	return nil
+}
+
+func (m *LoadDevice) GetPin() string {
+	if m != nil && m.Pin != nil {
+		return *m.Pin
+	}
+	return ""
+}
+
+func (m *LoadDevice) GetPassphraseProtection() bool {
+	if m != nil && m.PassphraseProtection != nil {
+		return *m.PassphraseProtection
+	}
+	return false
+}
+
+func (m *LoadDevice) GetLanguage() string {
+	if m != nil && m.Language != nil {
+		return *m.Language
+	}
+	return Default_LoadDevice_Language
+}
+
+func (m *LoadDevice) GetLabel() string {
+	if m != nil && m.Label != nil {
+		return *m.Label
+	}
+	return ""
+}
+
+func (m *LoadDevice) GetSkipChecksum() bool {
+	if m != nil && m.SkipChecksum != nil {
+		return *m.SkipChecksum
+	}
+	return false
+}
+
+func (m *LoadDevice) GetU2FCounter() uint32 {
+	if m != nil && m.U2FCounter != nil {
+		return *m.U2FCounter
+	}
+	return 0
+}
+
+//*
+// Request: Ask device to do initialization involving user interaction
+// @start
+// @next EntropyRequest
+// @next Failure
+type ResetDevice struct {
+	DisplayRandom        *bool    `protobuf:"varint,1,opt,name=display_random,json=displayRandom" json:"display_random,omitempty"`
+	Strength             *uint32  `protobuf:"varint,2,opt,name=strength,def=256" json:"strength,omitempty"`
+	PassphraseProtection *bool    `protobuf:"varint,3,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"`
+	PinProtection        *bool    `protobuf:"varint,4,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"`
+	Language             *string  `protobuf:"bytes,5,opt,name=language,def=english" json:"language,omitempty"`
+	Label                *string  `protobuf:"bytes,6,opt,name=label" json:"label,omitempty"`
+	U2FCounter           *uint32  `protobuf:"varint,7,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"`
+	SkipBackup           *bool    `protobuf:"varint,8,opt,name=skip_backup,json=skipBackup" json:"skip_backup,omitempty"`
+	NoBackup             *bool    `protobuf:"varint,9,opt,name=no_backup,json=noBackup" json:"no_backup,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ResetDevice) Reset()         { *m = ResetDevice{} }
+func (m *ResetDevice) String() string { return proto.CompactTextString(m) }
+func (*ResetDevice) ProtoMessage()    {}
+func (*ResetDevice) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{13}
+}
+
+func (m *ResetDevice) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ResetDevice.Unmarshal(m, b)
+}
+func (m *ResetDevice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ResetDevice.Marshal(b, m, deterministic)
+}
+func (m *ResetDevice) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ResetDevice.Merge(m, src)
+}
+func (m *ResetDevice) XXX_Size() int {
+	return xxx_messageInfo_ResetDevice.Size(m)
+}
+func (m *ResetDevice) XXX_DiscardUnknown() {
+	xxx_messageInfo_ResetDevice.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ResetDevice proto.InternalMessageInfo
+
+const Default_ResetDevice_Strength uint32 = 256
+const Default_ResetDevice_Language string = "english"
+
+func (m *ResetDevice) GetDisplayRandom() bool {
+	if m != nil && m.DisplayRandom != nil {
+		return *m.DisplayRandom
+	}
+	return false
+}
+
+func (m *ResetDevice) GetStrength() uint32 {
+	if m != nil && m.Strength != nil {
+		return *m.Strength
+	}
+	return Default_ResetDevice_Strength
+}
+
+func (m *ResetDevice) GetPassphraseProtection() bool {
+	if m != nil && m.PassphraseProtection != nil {
+		return *m.PassphraseProtection
+	}
+	return false
+}
+
+func (m *ResetDevice) GetPinProtection() bool {
+	if m != nil && m.PinProtection != nil {
+		return *m.PinProtection
+	}
+	return false
+}
+
+func (m *ResetDevice) GetLanguage() string {
+	if m != nil && m.Language != nil {
+		return *m.Language
+	}
+	return Default_ResetDevice_Language
+}
+
+func (m *ResetDevice) GetLabel() string {
+	if m != nil && m.Label != nil {
+		return *m.Label
+	}
+	return ""
+}
+
+func (m *ResetDevice) GetU2FCounter() uint32 {
+	if m != nil && m.U2FCounter != nil {
+		return *m.U2FCounter
+	}
+	return 0
+}
+
+func (m *ResetDevice) GetSkipBackup() bool {
+	if m != nil && m.SkipBackup != nil {
+		return *m.SkipBackup
+	}
+	return false
+}
+
+func (m *ResetDevice) GetNoBackup() bool {
+	if m != nil && m.NoBackup != nil {
+		return *m.NoBackup
+	}
+	return false
+}
+
+//*
+// Request: Perform backup of the device seed if not backed up using ResetDevice
+// @start
+// @next Success
+type BackupDevice struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *BackupDevice) Reset()         { *m = BackupDevice{} }
+func (m *BackupDevice) String() string { return proto.CompactTextString(m) }
+func (*BackupDevice) ProtoMessage()    {}
+func (*BackupDevice) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{14}
+}
+
+func (m *BackupDevice) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_BackupDevice.Unmarshal(m, b)
+}
+func (m *BackupDevice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_BackupDevice.Marshal(b, m, deterministic)
+}
+func (m *BackupDevice) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_BackupDevice.Merge(m, src)
+}
+func (m *BackupDevice) XXX_Size() int {
+	return xxx_messageInfo_BackupDevice.Size(m)
+}
+func (m *BackupDevice) XXX_DiscardUnknown() {
+	xxx_messageInfo_BackupDevice.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_BackupDevice proto.InternalMessageInfo
+
+//*
+// Response: Ask for additional entropy from host computer
+// @next EntropyAck
+type EntropyRequest struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *EntropyRequest) Reset()         { *m = EntropyRequest{} }
+func (m *EntropyRequest) String() string { return proto.CompactTextString(m) }
+func (*EntropyRequest) ProtoMessage()    {}
+func (*EntropyRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{15}
+}
+
+func (m *EntropyRequest) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_EntropyRequest.Unmarshal(m, b)
+}
+func (m *EntropyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_EntropyRequest.Marshal(b, m, deterministic)
+}
+func (m *EntropyRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_EntropyRequest.Merge(m, src)
+}
+func (m *EntropyRequest) XXX_Size() int {
+	return xxx_messageInfo_EntropyRequest.Size(m)
+}
+func (m *EntropyRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_EntropyRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EntropyRequest proto.InternalMessageInfo
+
+//*
+// Request: Provide additional entropy for seed generation function
+// @next Success
+type EntropyAck struct {
+	Entropy              []byte   `protobuf:"bytes,1,opt,name=entropy" json:"entropy,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *EntropyAck) Reset()         { *m = EntropyAck{} }
+func (m *EntropyAck) String() string { return proto.CompactTextString(m) }
+func (*EntropyAck) ProtoMessage()    {}
+func (*EntropyAck) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{16}
+}
+
+func (m *EntropyAck) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_EntropyAck.Unmarshal(m, b)
+}
+func (m *EntropyAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_EntropyAck.Marshal(b, m, deterministic)
+}
+func (m *EntropyAck) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_EntropyAck.Merge(m, src)
+}
+func (m *EntropyAck) XXX_Size() int {
+	return xxx_messageInfo_EntropyAck.Size(m)
+}
+func (m *EntropyAck) XXX_DiscardUnknown() {
+	xxx_messageInfo_EntropyAck.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_EntropyAck proto.InternalMessageInfo
+
+func (m *EntropyAck) GetEntropy() []byte {
+	if m != nil {
+		return m.Entropy
+	}
+	return nil
+}
+
+//*
+// Request: Start recovery workflow asking user for specific words of mnemonic
+// Used to recovery device safely even on untrusted computer.
+// @start
+// @next WordRequest
+type RecoveryDevice struct {
+	WordCount            *uint32 `protobuf:"varint,1,opt,name=word_count,json=wordCount" json:"word_count,omitempty"`
+	PassphraseProtection *bool   `protobuf:"varint,2,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"`
+	PinProtection        *bool   `protobuf:"varint,3,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"`
+	Language             *string `protobuf:"bytes,4,opt,name=language,def=english" json:"language,omitempty"`
+	Label                *string `protobuf:"bytes,5,opt,name=label" json:"label,omitempty"`
+	EnforceWordlist      *bool   `protobuf:"varint,6,opt,name=enforce_wordlist,json=enforceWordlist" json:"enforce_wordlist,omitempty"`
+	// 7 reserved for unused recovery method
+	Type                 *RecoveryDevice_RecoveryDeviceType `protobuf:"varint,8,opt,name=type,enum=hw.trezor.messages.management.RecoveryDevice_RecoveryDeviceType" json:"type,omitempty"`
+	U2FCounter           *uint32                            `protobuf:"varint,9,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"`
+	DryRun               *bool                              `protobuf:"varint,10,opt,name=dry_run,json=dryRun" json:"dry_run,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}                           `json:"-"`
+	XXX_unrecognized     []byte                             `json:"-"`
+	XXX_sizecache        int32                              `json:"-"`
+}
+
+func (m *RecoveryDevice) Reset()         { *m = RecoveryDevice{} }
+func (m *RecoveryDevice) String() string { return proto.CompactTextString(m) }
+func (*RecoveryDevice) ProtoMessage()    {}
+func (*RecoveryDevice) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{17}
+}
+
+func (m *RecoveryDevice) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_RecoveryDevice.Unmarshal(m, b)
+}
+func (m *RecoveryDevice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_RecoveryDevice.Marshal(b, m, deterministic)
+}
+func (m *RecoveryDevice) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_RecoveryDevice.Merge(m, src)
+}
+func (m *RecoveryDevice) XXX_Size() int {
+	return xxx_messageInfo_RecoveryDevice.Size(m)
+}
+func (m *RecoveryDevice) XXX_DiscardUnknown() {
+	xxx_messageInfo_RecoveryDevice.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_RecoveryDevice proto.InternalMessageInfo
+
+const Default_RecoveryDevice_Language string = "english"
+
+func (m *RecoveryDevice) GetWordCount() uint32 {
+	if m != nil && m.WordCount != nil {
+		return *m.WordCount
+	}
+	return 0
+}
+
+func (m *RecoveryDevice) GetPassphraseProtection() bool {
+	if m != nil && m.PassphraseProtection != nil {
+		return *m.PassphraseProtection
+	}
+	return false
+}
+
+func (m *RecoveryDevice) GetPinProtection() bool {
+	if m != nil && m.PinProtection != nil {
+		return *m.PinProtection
+	}
+	return false
+}
+
+func (m *RecoveryDevice) GetLanguage() string {
+	if m != nil && m.Language != nil {
+		return *m.Language
+	}
+	return Default_RecoveryDevice_Language
+}
+
+func (m *RecoveryDevice) GetLabel() string {
+	if m != nil && m.Label != nil {
+		return *m.Label
+	}
+	return ""
+}
+
+func (m *RecoveryDevice) GetEnforceWordlist() bool {
+	if m != nil && m.EnforceWordlist != nil {
+		return *m.EnforceWordlist
+	}
+	return false
+}
+
+func (m *RecoveryDevice) GetType() RecoveryDevice_RecoveryDeviceType {
+	if m != nil && m.Type != nil {
+		return *m.Type
+	}
+	return RecoveryDevice_RecoveryDeviceType_ScrambledWords
+}
+
+func (m *RecoveryDevice) GetU2FCounter() uint32 {
+	if m != nil && m.U2FCounter != nil {
+		return *m.U2FCounter
+	}
+	return 0
+}
+
+func (m *RecoveryDevice) GetDryRun() bool {
+	if m != nil && m.DryRun != nil {
+		return *m.DryRun
+	}
+	return false
+}
+
+//*
+// Response: Device is waiting for user to enter word of the mnemonic
+// Its position is shown only on device's internal display.
+// @next WordAck
+type WordRequest struct {
+	Type                 *WordRequest_WordRequestType `protobuf:"varint,1,opt,name=type,enum=hw.trezor.messages.management.WordRequest_WordRequestType" json:"type,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}                     `json:"-"`
+	XXX_unrecognized     []byte                       `json:"-"`
+	XXX_sizecache        int32                        `json:"-"`
+}
+
+func (m *WordRequest) Reset()         { *m = WordRequest{} }
+func (m *WordRequest) String() string { return proto.CompactTextString(m) }
+func (*WordRequest) ProtoMessage()    {}
+func (*WordRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{18}
+}
+
+func (m *WordRequest) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_WordRequest.Unmarshal(m, b)
+}
+func (m *WordRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_WordRequest.Marshal(b, m, deterministic)
+}
+func (m *WordRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_WordRequest.Merge(m, src)
+}
+func (m *WordRequest) XXX_Size() int {
+	return xxx_messageInfo_WordRequest.Size(m)
+}
+func (m *WordRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_WordRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WordRequest proto.InternalMessageInfo
+
+func (m *WordRequest) GetType() WordRequest_WordRequestType {
+	if m != nil && m.Type != nil {
+		return *m.Type
+	}
+	return WordRequest_WordRequestType_Plain
+}
+
+//*
+// Request: Computer replies with word from the mnemonic
+// @next WordRequest
+// @next Success
+// @next Failure
+type WordAck struct {
+	Word                 *string  `protobuf:"bytes,1,req,name=word" json:"word,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *WordAck) Reset()         { *m = WordAck{} }
+func (m *WordAck) String() string { return proto.CompactTextString(m) }
+func (*WordAck) ProtoMessage()    {}
+func (*WordAck) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{19}
+}
+
+func (m *WordAck) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_WordAck.Unmarshal(m, b)
+}
+func (m *WordAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_WordAck.Marshal(b, m, deterministic)
+}
+func (m *WordAck) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_WordAck.Merge(m, src)
+}
+func (m *WordAck) XXX_Size() int {
+	return xxx_messageInfo_WordAck.Size(m)
+}
+func (m *WordAck) XXX_DiscardUnknown() {
+	xxx_messageInfo_WordAck.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WordAck proto.InternalMessageInfo
+
+func (m *WordAck) GetWord() string {
+	if m != nil && m.Word != nil {
+		return *m.Word
+	}
+	return ""
+}
+
+//*
+// Request: Set U2F counter
+// @start
+// @next Success
+type SetU2FCounter struct {
+	U2FCounter           *uint32  `protobuf:"varint,1,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *SetU2FCounter) Reset()         { *m = SetU2FCounter{} }
+func (m *SetU2FCounter) String() string { return proto.CompactTextString(m) }
+func (*SetU2FCounter) ProtoMessage()    {}
+func (*SetU2FCounter) Descriptor() ([]byte, []int) {
+	return fileDescriptor_0c720c20d27aa029, []int{20}
+}
+
+func (m *SetU2FCounter) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_SetU2FCounter.Unmarshal(m, b)
+}
+func (m *SetU2FCounter) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_SetU2FCounter.Marshal(b, m, deterministic)
+}
+func (m *SetU2FCounter) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_SetU2FCounter.Merge(m, src)
+}
+func (m *SetU2FCounter) XXX_Size() int {
+	return xxx_messageInfo_SetU2FCounter.Size(m)
+}
+func (m *SetU2FCounter) XXX_DiscardUnknown() {
+	xxx_messageInfo_SetU2FCounter.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SetU2FCounter proto.InternalMessageInfo
+
+func (m *SetU2FCounter) GetU2FCounter() uint32 {
+	if m != nil && m.U2FCounter != nil {
+		return *m.U2FCounter
+	}
+	return 0
+}
+
+func init() {
+	proto.RegisterEnum("hw.trezor.messages.management.ApplySettings_PassphraseSourceType", ApplySettings_PassphraseSourceType_name, ApplySettings_PassphraseSourceType_value)
+	proto.RegisterEnum("hw.trezor.messages.management.RecoveryDevice_RecoveryDeviceType", RecoveryDevice_RecoveryDeviceType_name, RecoveryDevice_RecoveryDeviceType_value)
+	proto.RegisterEnum("hw.trezor.messages.management.WordRequest_WordRequestType", WordRequest_WordRequestType_name, WordRequest_WordRequestType_value)
+	proto.RegisterType((*Initialize)(nil), "hw.trezor.messages.management.Initialize")
+	proto.RegisterType((*GetFeatures)(nil), "hw.trezor.messages.management.GetFeatures")
+	proto.RegisterType((*Features)(nil), "hw.trezor.messages.management.Features")
+	proto.RegisterType((*ClearSession)(nil), "hw.trezor.messages.management.ClearSession")
+	proto.RegisterType((*ApplySettings)(nil), "hw.trezor.messages.management.ApplySettings")
+	proto.RegisterType((*ApplyFlags)(nil), "hw.trezor.messages.management.ApplyFlags")
+	proto.RegisterType((*ChangePin)(nil), "hw.trezor.messages.management.ChangePin")
+	proto.RegisterType((*Ping)(nil), "hw.trezor.messages.management.Ping")
+	proto.RegisterType((*Cancel)(nil), "hw.trezor.messages.management.Cancel")
+	proto.RegisterType((*GetEntropy)(nil), "hw.trezor.messages.management.GetEntropy")
+	proto.RegisterType((*Entropy)(nil), "hw.trezor.messages.management.Entropy")
+	proto.RegisterType((*WipeDevice)(nil), "hw.trezor.messages.management.WipeDevice")
+	proto.RegisterType((*LoadDevice)(nil), "hw.trezor.messages.management.LoadDevice")
+	proto.RegisterType((*ResetDevice)(nil), "hw.trezor.messages.management.ResetDevice")
+	proto.RegisterType((*BackupDevice)(nil), "hw.trezor.messages.management.BackupDevice")
+	proto.RegisterType((*EntropyRequest)(nil), "hw.trezor.messages.management.EntropyRequest")
+	proto.RegisterType((*EntropyAck)(nil), "hw.trezor.messages.management.EntropyAck")
+	proto.RegisterType((*RecoveryDevice)(nil), "hw.trezor.messages.management.RecoveryDevice")
+	proto.RegisterType((*WordRequest)(nil), "hw.trezor.messages.management.WordRequest")
+	proto.RegisterType((*WordAck)(nil), "hw.trezor.messages.management.WordAck")
+	proto.RegisterType((*SetU2FCounter)(nil), "hw.trezor.messages.management.SetU2FCounter")
+}
+
+func init() { proto.RegisterFile("messages-management.proto", fileDescriptor_0c720c20d27aa029) }
+
+var fileDescriptor_0c720c20d27aa029 = []byte{
+	// 1393 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x57, 0xdd, 0x6e, 0xdb, 0xc8,
+	0x15, 0x8e, 0x7e, 0x62, 0x49, 0xc7, 0xfa, 0xcb, 0xd4, 0x8e, 0xe9, 0xb8, 0x6e, 0x1c, 0xba, 0x6e,
+	0x12, 0x04, 0x15, 0x0a, 0x17, 0x09, 0x90, 0x5c, 0x14, 0x75, 0xec, 0xfc, 0x21, 0x71, 0x6a, 0xd0,
+	0x6e, 0x02, 0xf4, 0x86, 0x18, 0x91, 0x47, 0xd2, 0xd4, 0xe4, 0x0c, 0xcb, 0x19, 0xda, 0x55, 0x5e,
+	0x60, 0x6f, 0xf6, 0x45, 0x16, 0xfb, 0x1c, 0x7b, 0xb5, 0xcf, 0xb0, 0xef, 0xb2, 0x98, 0x19, 0x52,
+	0xa2, 0x65, 0x3b, 0x46, 0x76, 0xef, 0xe6, 0x7c, 0xe7, 0xe3, 0x68, 0xce, 0x77, 0xbe, 0x39, 0x63,
+	0xc3, 0x7a, 0x8c, 0x52, 0xd2, 0x31, 0xca, 0xbf, 0xc6, 0x94, 0xd3, 0x31, 0xc6, 0xc8, 0xd5, 0x20,
+	0x49, 0x85, 0x12, 0x64, 0x73, 0x72, 0x3e, 0x50, 0x29, 0x7e, 0x11, 0xe9, 0xa0, 0x20, 0x0d, 0xe6,
+	0xa4, 0x7b, 0xab, 0xb3, 0x2f, 0x03, 0x11, 0xc7, 0x82, 0xdb, 0xaf, 0xdc, 0xf7, 0x00, 0xef, 0x38,
+	0x53, 0x8c, 0x46, 0xec, 0x0b, 0x92, 0x15, 0xb8, 0x2d, 0x15, 0x55, 0xe8, 0x54, 0xb6, 0x2a, 0x8f,
+	0xda, 0x9e, 0x0d, 0xc8, 0x43, 0xe8, 0xc9, 0x53, 0x96, 0xf8, 0x09, 0x95, 0x32, 0x99, 0xa4, 0x54,
+	0xa2, 0x53, 0xdd, 0xaa, 0x3c, 0x6a, 0x7a, 0x5d, 0x0d, 0x1f, 0xcd, 0x50, 0xb7, 0x03, 0xcb, 0x6f,
+	0x50, 0xbd, 0x46, 0xaa, 0xb2, 0x14, 0xa5, 0xfb, 0x7d, 0x03, 0x9a, 0x45, 0x40, 0xee, 0xc2, 0xd2,
+	0x19, 0xf2, 0x50, 0xa4, 0x66, 0xef, 0x96, 0x97, 0x47, 0x64, 0x1b, 0x3a, 0x31, 0xfd, 0xaf, 0x48,
+	0xfd, 0x33, 0x4c, 0x25, 0x13, 0xdc, 0x6c, 0xdd, 0xf1, 0xda, 0x06, 0xfc, 0x64, 0x31, 0x43, 0x62,
+	0xbc, 0x44, 0xaa, 0xe5, 0x24, 0x0d, 0x96, 0x48, 0x09, 0x55, 0xc1, 0x64, 0x46, 0xaa, 0x5b, 0x92,
+	0x01, 0x0b, 0xd2, 0x43, 0xe8, 0x0d, 0x85, 0x50, 0x91, 0xa0, 0x21, 0xa6, 0x7e, 0x2c, 0x42, 0x74,
+	0x6e, 0xdb, 0x5a, 0xe6, 0xf0, 0xa1, 0x08, 0x91, 0x6c, 0x40, 0x2b, 0xc4, 0x33, 0x16, 0xa0, 0xcf,
+	0x42, 0x67, 0xc9, 0x1c, 0xb9, 0x69, 0x81, 0x77, 0x21, 0xd9, 0x81, 0x6e, 0xc2, 0xb8, 0xaf, 0x25,
+	0xc4, 0x40, 0xe9, 0xdf, 0x6a, 0x98, 0x4d, 0x3a, 0x09, 0xe3, 0x47, 0x33, 0x90, 0xfc, 0x1d, 0x56,
+	0xe7, 0x9a, 0x95, 0xd9, 0x4d, 0xc3, 0x5e, 0x99, 0x27, 0x4b, 0x1f, 0xdd, 0x83, 0x66, 0x44, 0xf9,
+	0x38, 0xa3, 0x63, 0x74, 0x5a, 0xf6, 0x77, 0x8b, 0x58, 0xf7, 0x27, 0xa2, 0x43, 0x8c, 0x1c, 0x30,
+	0x09, 0x1b, 0x90, 0x2d, 0x58, 0x66, 0xb3, 0x1e, 0x86, 0x4e, 0xdb, 0x6c, 0x5e, 0x86, 0xf4, 0x9e,
+	0x29, 0x9e, 0x31, 0xa3, 0x4a, 0xc7, 0xb4, 0x76, 0x16, 0x2f, 0x28, 0x32, 0xa1, 0x72, 0xe2, 0x74,
+	0x0d, 0xa5, 0xa4, 0xc8, 0x5b, 0x2a, 0x27, 0x7a, 0x13, 0x16, 0x27, 0x22, 0x55, 0x18, 0x3a, 0x3d,
+	0xf3, 0x1b, 0xb3, 0x98, 0x6c, 0x02, 0x68, 0x41, 0x02, 0x1a, 0x4c, 0x30, 0x74, 0xfa, 0x26, 0xdb,
+	0x4a, 0x18, 0xdf, 0x37, 0x00, 0x79, 0x02, 0x77, 0x4a, 0x42, 0xe4, 0xac, 0x3b, 0x86, 0xd5, 0x9f,
+	0x27, 0x72, 0xf2, 0x63, 0xe8, 0x8f, 0x58, 0x1a, 0x9f, 0xd3, 0x54, 0x6b, 0x86, 0x12, 0xb9, 0x72,
+	0x88, 0xe1, 0xf6, 0x0a, 0xfc, 0xc8, 0xc2, 0xe4, 0x01, 0xb4, 0x39, 0x62, 0x28, 0xfd, 0x21, 0x0d,
+	0x4e, 0xb3, 0xc4, 0xf9, 0x83, 0x2d, 0xdd, 0x60, 0x2f, 0x0d, 0xa4, 0x25, 0x1b, 0x45, 0x74, 0x2c,
+	0x9d, 0x15, 0xe3, 0x06, 0x1b, 0x68, 0x54, 0xf7, 0x3e, 0x72, 0x56, 0xad, 0x90, 0x26, 0x20, 0xeb,
+	0xd0, 0x1c, 0x9d, 0xfb, 0xc6, 0x79, 0xce, 0x5d, 0x43, 0x6f, 0x8c, 0xce, 0x0f, 0x75, 0x58, 0xa4,
+	0xb4, 0xdf, 0x9c, 0xb5, 0x59, 0x4a, 0x87, 0x79, 0xca, 0xb8, 0xcc, 0x71, 0x8a, 0xd4, 0x91, 0x0e,
+	0xb5, 0x89, 0x46, 0xe7, 0x7e, 0xee, 0xfb, 0x75, 0xdb, 0xcc, 0xd1, 0xf9, 0x27, 0xeb, 0xfc, 0x3f,
+	0x43, 0x77, 0x96, 0xf4, 0x4f, 0x71, 0x2a, 0x9d, 0x7b, 0x46, 0xf7, 0x76, 0xc1, 0x78, 0x8f, 0x53,
+	0xa9, 0xa5, 0xcb, 0xf8, 0x88, 0x71, 0x26, 0x27, 0x18, 0x16, 0x75, 0x6e, 0x58, 0xe9, 0xe6, 0x89,
+	0xbc, 0xd8, 0x0d, 0x68, 0x71, 0x51, 0x90, 0xfe, 0x68, 0x7b, 0xc4, 0x85, 0x4d, 0xba, 0x5d, 0x68,
+	0xef, 0x47, 0x48, 0xd3, 0x63, 0x94, 0xba, 0xf1, 0xee, 0x77, 0x35, 0xe8, 0xec, 0x25, 0x49, 0x34,
+	0x3d, 0x46, 0xa5, 0x18, 0x1f, 0xcb, 0x0b, 0xd6, 0xab, 0x5c, 0x67, 0xbd, 0x6a, 0xd9, 0x7a, 0x3b,
+	0xd0, 0xcd, 0xb4, 0xb5, 0xe7, 0x93, 0xa1, 0x66, 0x2f, 0x42, 0x26, 0x71, 0x3e, 0x18, 0xc8, 0x9f,
+	0x00, 0x26, 0x22, 0x46, 0x19, 0xa4, 0x88, 0xf6, 0x5e, 0xb6, 0xbd, 0x12, 0x42, 0xf8, 0x05, 0x7f,
+	0x48, 0x91, 0xa5, 0x81, 0xbd, 0x97, 0xdd, 0xdd, 0xbd, 0xc1, 0x57, 0xe7, 0xda, 0xe0, 0x42, 0x05,
+	0x83, 0xf9, 0x6f, 0x1e, 0x9b, 0x4d, 0x4e, 0xa6, 0x09, 0x96, 0x2d, 0x66, 0x51, 0xf2, 0x04, 0x08,
+	0xcd, 0x94, 0xf0, 0x23, 0x11, 0x9c, 0xfa, 0x21, 0x46, 0x74, 0xea, 0xc7, 0xd2, 0xdc, 0xf2, 0x8e,
+	0xd7, 0xd3, 0x99, 0x0f, 0x22, 0x38, 0x3d, 0xd0, 0xf8, 0xa1, 0xd4, 0x7e, 0x0c, 0x99, 0x4c, 0x34,
+	0x29, 0x15, 0x8a, 0xce, 0xae, 0x7b, 0xc7, 0xeb, 0xe5, 0xb8, 0x97, 0xc3, 0xee, 0x53, 0x58, 0xb9,
+	0xea, 0x04, 0xa4, 0x01, 0xb5, 0xbd, 0xe3, 0xf7, 0xfd, 0x5b, 0x04, 0x60, 0xe9, 0xe0, 0xd5, 0xa7,
+	0x77, 0xfb, 0xaf, 0xfa, 0x15, 0xd2, 0x84, 0xfa, 0xdb, 0x7f, 0x1d, 0x9f, 0xf4, 0xab, 0xae, 0x0b,
+	0x60, 0xca, 0x78, 0x5d, 0x78, 0xd3, 0x3a, 0xb6, 0x52, 0x72, 0xac, 0xbb, 0x0d, 0xad, 0xfd, 0x09,
+	0xe5, 0x63, 0x3c, 0x62, 0x5c, 0x0f, 0xd3, 0x14, 0x63, 0x71, 0x66, 0xdb, 0xd4, 0xf4, 0xf2, 0xc8,
+	0xfd, 0xa1, 0x02, 0xf5, 0x23, 0xc6, 0xc7, 0xc4, 0x81, 0x46, 0x2e, 0x56, 0xde, 0xc8, 0x22, 0xd4,
+	0x7e, 0x1a, 0x66, 0x4a, 0x89, 0x0b, 0xd3, 0xcb, 0x8e, 0xf3, 0xbe, 0x4d, 0x94, 0x66, 0xd1, 0xe5,
+	0x39, 0x57, 0xfb, 0xa6, 0x39, 0x57, 0xbf, 0x7e, 0xce, 0xb9, 0x4d, 0x58, 0xda, 0xa7, 0x3c, 0xc0,
+	0xc8, 0xdd, 0x02, 0x78, 0x83, 0xea, 0x15, 0x57, 0xa9, 0x48, 0xa6, 0x84, 0x40, 0x5d, 0xb2, 0x2f,
+	0xfa, 0xdc, 0xd5, 0x47, 0x1d, 0xcf, 0xac, 0xdd, 0x6d, 0x68, 0x14, 0x69, 0x07, 0x1a, 0x68, 0x97,
+	0x86, 0xd1, 0xf6, 0x8a, 0xd0, 0x6d, 0x03, 0x7c, 0x66, 0x09, 0x1e, 0x98, 0x21, 0xed, 0xfe, 0x58,
+	0x05, 0xf8, 0x20, 0x68, 0x68, 0x43, 0x6d, 0xed, 0x98, 0x63, 0x2c, 0x38, 0x0b, 0x0a, 0x6b, 0x17,
+	0x31, 0x79, 0x0e, 0x75, 0xae, 0x1f, 0x02, 0xad, 0xc2, 0xf2, 0xee, 0xce, 0x55, 0x86, 0xcb, 0xdf,
+	0xcc, 0xb7, 0x07, 0x1f, 0x45, 0x68, 0x4d, 0x65, 0x3e, 0x21, 0x7d, 0xa8, 0x25, 0xcc, 0xaa, 0xd2,
+	0xf2, 0xf4, 0xf2, 0x37, 0x69, 0x41, 0xb6, 0x4b, 0x17, 0x4f, 0xdb, 0xbe, 0xf5, 0xa2, 0x81, 0x7c,
+	0x1c, 0x31, 0x39, 0xb9, 0xea, 0x06, 0x2e, 0x95, 0x6f, 0xe0, 0x36, 0x74, 0xcc, 0xe3, 0x1c, 0x4c,
+	0x30, 0x38, 0x95, 0x59, 0x9c, 0xbf, 0x44, 0x6d, 0x0d, 0xee, 0xe7, 0x18, 0xb9, 0x0f, 0xcb, 0xd9,
+	0xee, 0xc8, 0x0f, 0x44, 0xc6, 0x15, 0xa6, 0xe6, 0xf9, 0xe9, 0x78, 0x90, 0xed, 0x8e, 0xf6, 0x2d,
+	0xe2, 0xfe, 0x5c, 0x85, 0x65, 0x0f, 0x25, 0xaa, 0x5c, 0xae, 0x1d, 0xe8, 0xce, 0x3c, 0x4f, 0x79,
+	0x28, 0xe2, 0xdc, 0x68, 0x9d, 0xc2, 0xf1, 0x06, 0x24, 0xf7, 0xa1, 0x29, 0x55, 0x8a, 0x7c, 0xac,
+	0x26, 0xf6, 0xdd, 0x7e, 0x51, 0xdb, 0x7d, 0xfa, 0xcc, 0x9b, 0x81, 0xd7, 0xab, 0x51, 0xfb, 0x8a,
+	0x1a, 0x97, 0x5d, 0x57, 0xbf, 0xca, 0x75, 0xbf, 0x43, 0xb4, 0x05, 0x3d, 0x1a, 0x8b, 0x7a, 0x68,
+	0x82, 0x51, 0x35, 0x1f, 0xa5, 0xf6, 0xbd, 0x06, 0x0d, 0x5d, 0x35, 0x69, 0x5b, 0x97, 0x27, 0xad,
+	0x5d, 0xe5, 0x5e, 0xec, 0x43, 0x37, 0xb7, 0xaf, 0x87, 0xff, 0xcb, 0x50, 0x2a, 0xf7, 0x2f, 0x00,
+	0x39, 0xb2, 0x17, 0x9c, 0x5e, 0xf4, 0x74, 0xa5, 0xec, 0xe9, 0x5f, 0x6a, 0xd0, 0xf5, 0x30, 0x10,
+	0x67, 0x98, 0x4e, 0xf3, 0xd6, 0x6c, 0x02, 0x9c, 0x8b, 0x34, 0xb4, 0x87, 0xcf, 0x67, 0x44, 0x4b,
+	0x23, 0xe6, 0xec, 0xd7, 0x2b, 0x5e, 0xfd, 0x26, 0xc5, 0x6b, 0x37, 0x29, 0x5e, 0xbf, 0x51, 0xf1,
+	0xdb, 0x65, 0xc5, 0x1f, 0x43, 0x1f, 0xf9, 0x48, 0xa4, 0x01, 0xfa, 0xfa, 0xac, 0x11, 0x93, 0xca,
+	0xb4, 0xa4, 0xe9, 0xf5, 0x72, 0xfc, 0x73, 0x0e, 0x93, 0x13, 0xa8, 0xab, 0x69, 0x82, 0x46, 0xf4,
+	0xee, 0xee, 0x3f, 0x6f, 0x98, 0xff, 0x17, 0xd5, 0x59, 0x08, 0xed, 0x4d, 0xd5, 0xbb, 0x2d, 0xb6,
+	0xbc, 0x75, 0xa9, 0xe5, 0x6b, 0xd0, 0x08, 0xd3, 0xa9, 0x9f, 0x66, 0xdc, 0xfc, 0x75, 0xd5, 0xf4,
+	0x96, 0xc2, 0x74, 0xea, 0x65, 0xdc, 0xfd, 0x0f, 0x90, 0xcb, 0xbb, 0x92, 0x1d, 0x78, 0x70, 0x19,
+	0xf5, 0x8f, 0x83, 0x94, 0xc6, 0xc3, 0x08, 0x43, 0x5d, 0x8d, 0xec, 0xdf, 0x22, 0x9b, 0xb0, 0x7e,
+	0x05, 0xed, 0x90, 0xaa, 0x94, 0xfd, 0xbf, 0x5f, 0x71, 0x7f, 0xaa, 0xc0, 0xb2, 0xa6, 0xe6, 0xbe,
+	0x20, 0x1f, 0xf3, 0xda, 0x2b, 0xa6, 0xf6, 0x17, 0x37, 0xd4, 0x5e, 0xfa, 0xb2, 0xbc, 0x9e, 0x57,
+	0xed, 0x8e, 0xa0, 0xb7, 0x90, 0x20, 0xeb, 0xb0, 0xba, 0x00, 0xf9, 0x47, 0x11, 0x65, 0xbc, 0x7f,
+	0x8b, 0x6c, 0xc0, 0xda, 0x62, 0xca, 0x9e, 0xf4, 0x79, 0xbf, 0x72, 0x7d, 0xf2, 0x59, 0xbf, 0xea,
+	0x6e, 0x42, 0x43, 0x27, 0xb5, 0x99, 0x09, 0xd4, 0x75, 0x87, 0xcd, 0x74, 0x6e, 0x79, 0x66, 0xed,
+	0xfe, 0x0d, 0x3a, 0xc7, 0xa8, 0xfe, 0xbd, 0xfb, 0xba, 0x74, 0xbf, 0xca, 0xdd, 0xa8, 0x2c, 0x76,
+	0xe3, 0xe5, 0x3f, 0x60, 0x3b, 0x10, 0xf1, 0x40, 0x52, 0x25, 0xe4, 0x84, 0x45, 0x74, 0x28, 0x0b,
+	0x21, 0x22, 0x36, 0xb4, 0xff, 0xbb, 0x0c, 0xb3, 0xd1, 0xcb, 0xb5, 0x13, 0x03, 0x1e, 0x5a, 0x71,
+	0x0e, 0x67, 0xd2, 0xfc, 0x1a, 0x00, 0x00, 0xff, 0xff, 0xd7, 0x6e, 0xfc, 0x59, 0x29, 0x0d, 0x00,
+	0x00,
+}

+ 289 - 0
accounts/usbwallet/trezor/messages-management.proto

@@ -0,0 +1,289 @@
+// This file originates from the SatoshiLabs Trezor `common` repository at:
+//   https://github.com/trezor/trezor-common/blob/master/protob/messages-management.proto
+// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9.
+
+syntax = "proto2";
+package hw.trezor.messages.management;
+
+// Sugar for easier handling in Java
+option java_package = "com.satoshilabs.trezor.lib.protobuf";
+option java_outer_classname = "TrezorMessageManagement";
+
+import "messages-common.proto";
+
+/**
+ * Request: Reset device to default state and ask for device details
+ * @start
+ * @next Features
+ */
+message Initialize {
+    optional bytes state = 1;           // assumed device state, clear session if set and different
+    optional bool skip_passphrase = 2;  // this session should always assume empty passphrase
+}
+
+/**
+ * Request: Ask for device details (no device reset)
+ * @start
+ * @next Features
+ */
+message GetFeatures {
+}
+
+/**
+ * Response: Reports various information about the device
+ * @end
+ */
+message Features {
+    optional string vendor = 1;                 // name of the manufacturer, e.g. "trezor.io"
+    optional uint32 major_version = 2;          // major version of the firmware/bootloader, e.g. 1
+    optional uint32 minor_version = 3;          // minor version of the firmware/bootloader, e.g. 0
+    optional uint32 patch_version = 4;          // patch version of the firmware/bootloader, e.g. 0
+    optional bool bootloader_mode = 5;          // is device in bootloader mode?
+    optional string device_id = 6;              // device's unique identifier
+    optional bool pin_protection = 7;           // is device protected by PIN?
+    optional bool passphrase_protection = 8;    // is node/mnemonic encrypted using passphrase?
+    optional string language = 9;               // device language
+    optional string label = 10;                 // device description label
+    optional bool initialized = 12;             // does device contain seed?
+    optional bytes revision = 13;               // SCM revision of firmware
+    optional bytes bootloader_hash = 14;        // hash of the bootloader
+    optional bool imported = 15;                // was storage imported from an external source?
+    optional bool pin_cached = 16;              // is PIN already cached in session?
+    optional bool passphrase_cached = 17;       // is passphrase already cached in session?
+    optional bool firmware_present = 18;        // is valid firmware loaded?
+    optional bool needs_backup = 19;            // does storage need backup? (equals to Storage.needs_backup)
+    optional uint32 flags = 20;                 // device flags (equals to Storage.flags)
+    optional string model = 21;                 // device hardware model
+    optional uint32 fw_major = 22;              // reported firmware version if in bootloader mode
+    optional uint32 fw_minor = 23;              // reported firmware version if in bootloader mode
+    optional uint32 fw_patch = 24;              // reported firmware version if in bootloader mode
+    optional string fw_vendor = 25;             // reported firmware vendor if in bootloader mode
+    optional bytes fw_vendor_keys = 26;         // reported firmware vendor keys (their hash)
+    optional bool unfinished_backup = 27;       // report unfinished backup (equals to Storage.unfinished_backup)
+    optional bool no_backup = 28;               // report no backup (equals to Storage.no_backup)
+}
+
+/**
+ * Request: clear session (removes cached PIN, passphrase, etc).
+ * @start
+ * @next Success
+ */
+message ClearSession {
+}
+
+/**
+ * Request: change language and/or label of the device
+ * @start
+ * @next Success
+ * @next Failure
+ */
+message ApplySettings {
+    optional string language = 1;
+    optional string label = 2;
+    optional bool use_passphrase = 3;
+    optional bytes homescreen = 4;
+    optional PassphraseSourceType passphrase_source = 5;
+    optional uint32 auto_lock_delay_ms = 6;
+    optional uint32 display_rotation = 7;  // in degrees from North
+    /**
+    * Structure representing passphrase source
+    */
+    enum PassphraseSourceType {
+        ASK = 0;
+        DEVICE = 1;
+        HOST = 2;
+    }
+}
+
+/**
+ * Request: set flags of the device
+ * @start
+ * @next Success
+ * @next Failure
+ */
+message ApplyFlags {
+    optional uint32 flags = 1;  // bitmask, can only set bits, not unset
+}
+
+/**
+ * Request: Starts workflow for setting/changing/removing the PIN
+ * @start
+ * @next Success
+ * @next Failure
+ */
+message ChangePin {
+    optional bool remove = 1;   // is PIN removal requested?
+}
+
+/**
+ * Request: Test if the device is alive, device sends back the message in Success response
+ * @start
+ * @next Success
+ */
+message Ping {
+    optional string message = 1;                // message to send back in Success message
+    optional bool button_protection = 2;        // ask for button press
+    optional bool pin_protection = 3;           // ask for PIN if set in device
+    optional bool passphrase_protection = 4;    // ask for passphrase if set in device
+}
+
+/**
+ * Request: Abort last operation that required user interaction
+ * @start
+ * @next Failure
+ */
+message Cancel {
+}
+
+/**
+ * Request: Request a sample of random data generated by hardware RNG. May be used for testing.
+ * @start
+ * @next Entropy
+ * @next Failure
+ */
+message GetEntropy {
+    required uint32 size = 1;       // size of requested entropy
+}
+
+/**
+ * Response: Reply with random data generated by internal RNG
+ * @end
+ */
+message Entropy {
+    required bytes entropy = 1;     // chunk of random generated bytes
+}
+
+/**
+ * Request: Request device to wipe all sensitive data and settings
+ * @start
+ * @next Success
+ * @next Failure
+ */
+message WipeDevice {
+}
+
+/**
+ * Request: Load seed and related internal settings from the computer
+ * @start
+ * @next Success
+ * @next Failure
+ */
+message LoadDevice {
+    optional string mnemonic = 1;                           // seed encoded as BIP-39 mnemonic (12, 18 or 24 words)
+    optional hw.trezor.messages.common.HDNodeType node = 2; // BIP-32 node
+    optional string pin = 3;                                // set PIN protection
+    optional bool passphrase_protection = 4;                // enable master node encryption using passphrase
+    optional string language = 5 [default='english'];       // device language
+    optional string label = 6;                              // device label
+    optional bool skip_checksum = 7;                        // do not test mnemonic for valid BIP-39 checksum
+    optional uint32 u2f_counter = 8;                        // U2F counter
+}
+
+/**
+ * Request: Ask device to do initialization involving user interaction
+ * @start
+ * @next EntropyRequest
+ * @next Failure
+ */
+message ResetDevice {
+    optional bool display_random = 1;                   // display entropy generated by the device before asking for additional entropy
+    optional uint32 strength = 2 [default=256];         // strength of seed in bits
+    optional bool passphrase_protection = 3;            // enable master node encryption using passphrase
+    optional bool pin_protection = 4;                   // enable PIN protection
+    optional string language = 5 [default='english'];   // device language
+    optional string label = 6;                          // device label
+    optional uint32 u2f_counter = 7;                    // U2F counter
+    optional bool skip_backup = 8;                      // postpone seed backup to BackupDevice workflow
+    optional bool no_backup = 9;                        // indicate that no backup is going to be made
+}
+
+/**
+ * Request: Perform backup of the device seed if not backed up using ResetDevice
+ * @start
+ * @next Success
+ */
+message BackupDevice {
+}
+
+/**
+ * Response: Ask for additional entropy from host computer
+ * @next EntropyAck
+ */
+message EntropyRequest {
+}
+
+/**
+ * Request: Provide additional entropy for seed generation function
+ * @next Success
+ */
+message EntropyAck {
+    optional bytes entropy = 1;     // 256 bits (32 bytes) of random data
+}
+
+/**
+ * Request: Start recovery workflow asking user for specific words of mnemonic
+ * Used to recovery device safely even on untrusted computer.
+ * @start
+ * @next WordRequest
+ */
+message RecoveryDevice {
+    optional uint32 word_count = 1;                     // number of words in BIP-39 mnemonic
+    optional bool passphrase_protection = 2;            // enable master node encryption using passphrase
+    optional bool pin_protection = 3;                   // enable PIN protection
+    optional string language = 4 [default='english'];   // device language
+    optional string label = 5;                          // device label
+    optional bool enforce_wordlist = 6;                 // enforce BIP-39 wordlist during the process
+    // 7 reserved for unused recovery method
+    optional RecoveryDeviceType type = 8;               // supported recovery type
+    optional uint32 u2f_counter = 9;                    // U2F counter
+    optional bool dry_run = 10;                         // perform dry-run recovery workflow (for safe mnemonic validation)
+    /**
+     * Type of recovery procedure. These should be used as bitmask, e.g.,
+     * `RecoveryDeviceType_ScrambledWords | RecoveryDeviceType_Matrix`
+     * listing every method supported by the host computer.
+     *
+     * Note that ScrambledWords must be supported by every implementation
+     * for backward compatibility; there is no way to not support it.
+     */
+    enum RecoveryDeviceType {
+        // use powers of two when extending this field
+        RecoveryDeviceType_ScrambledWords = 0;        // words in scrambled order
+        RecoveryDeviceType_Matrix = 1;                // matrix recovery type
+    }
+}
+
+/**
+ * Response: Device is waiting for user to enter word of the mnemonic
+ * Its position is shown only on device's internal display.
+ * @next WordAck
+ */
+message WordRequest {
+    optional WordRequestType type = 1;
+    /**
+    * Type of Recovery Word request
+    */
+    enum WordRequestType {
+        WordRequestType_Plain = 0;
+        WordRequestType_Matrix9 = 1;
+        WordRequestType_Matrix6 = 2;
+    }
+}
+
+/**
+ * Request: Computer replies with word from the mnemonic
+ * @next WordRequest
+ * @next Success
+ * @next Failure
+ */
+message WordAck {
+    required string word = 1;           // one word of mnemonic on asked position
+}
+
+/**
+ * Request: Set U2F counter
+ * @start
+ * @next Success
+ */
+message SetU2FCounter {
+    optional uint32 u2f_counter = 1;    // counter
+}

+ 784 - 2976
accounts/usbwallet/trezor/messages.pb.go

@@ -3,93 +3,242 @@
 
 package trezor
 
-import proto "github.com/golang/protobuf/proto"
-import fmt "fmt"
-import math "math"
+import (
+	fmt "fmt"
+	math "math"
+
+	proto "github.com/golang/protobuf/proto"
+	descriptor "github.com/golang/protobuf/protoc-gen-go/descriptor"
+)
 
 // Reference imports to suppress errors if they are not otherwise used.
 var _ = proto.Marshal
 var _ = fmt.Errorf
 var _ = math.Inf
 
-// *
-// Mapping between Trezor wire identifier (uint) and a protobuf message
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+//*
+// Mapping between TREZOR wire identifier (uint) and a protobuf message
 type MessageType int32
 
 const (
-	MessageType_MessageType_Initialize               MessageType = 0
-	MessageType_MessageType_Ping                     MessageType = 1
-	MessageType_MessageType_Success                  MessageType = 2
-	MessageType_MessageType_Failure                  MessageType = 3
-	MessageType_MessageType_ChangePin                MessageType = 4
-	MessageType_MessageType_WipeDevice               MessageType = 5
-	MessageType_MessageType_FirmwareErase            MessageType = 6
-	MessageType_MessageType_FirmwareUpload           MessageType = 7
-	MessageType_MessageType_FirmwareRequest          MessageType = 8
-	MessageType_MessageType_GetEntropy               MessageType = 9
-	MessageType_MessageType_Entropy                  MessageType = 10
-	MessageType_MessageType_GetPublicKey             MessageType = 11
-	MessageType_MessageType_PublicKey                MessageType = 12
-	MessageType_MessageType_LoadDevice               MessageType = 13
-	MessageType_MessageType_ResetDevice              MessageType = 14
-	MessageType_MessageType_SignTx                   MessageType = 15
-	MessageType_MessageType_SimpleSignTx             MessageType = 16
-	MessageType_MessageType_Features                 MessageType = 17
-	MessageType_MessageType_PinMatrixRequest         MessageType = 18
-	MessageType_MessageType_PinMatrixAck             MessageType = 19
-	MessageType_MessageType_Cancel                   MessageType = 20
-	MessageType_MessageType_TxRequest                MessageType = 21
-	MessageType_MessageType_TxAck                    MessageType = 22
-	MessageType_MessageType_CipherKeyValue           MessageType = 23
-	MessageType_MessageType_ClearSession             MessageType = 24
-	MessageType_MessageType_ApplySettings            MessageType = 25
-	MessageType_MessageType_ButtonRequest            MessageType = 26
-	MessageType_MessageType_ButtonAck                MessageType = 27
-	MessageType_MessageType_ApplyFlags               MessageType = 28
-	MessageType_MessageType_GetAddress               MessageType = 29
-	MessageType_MessageType_Address                  MessageType = 30
-	MessageType_MessageType_SelfTest                 MessageType = 32
-	MessageType_MessageType_BackupDevice             MessageType = 34
-	MessageType_MessageType_EntropyRequest           MessageType = 35
-	MessageType_MessageType_EntropyAck               MessageType = 36
-	MessageType_MessageType_SignMessage              MessageType = 38
-	MessageType_MessageType_VerifyMessage            MessageType = 39
-	MessageType_MessageType_MessageSignature         MessageType = 40
-	MessageType_MessageType_PassphraseRequest        MessageType = 41
-	MessageType_MessageType_PassphraseAck            MessageType = 42
-	MessageType_MessageType_EstimateTxSize           MessageType = 43
-	MessageType_MessageType_TxSize                   MessageType = 44
-	MessageType_MessageType_RecoveryDevice           MessageType = 45
-	MessageType_MessageType_WordRequest              MessageType = 46
-	MessageType_MessageType_WordAck                  MessageType = 47
-	MessageType_MessageType_CipheredKeyValue         MessageType = 48
-	MessageType_MessageType_EncryptMessage           MessageType = 49
-	MessageType_MessageType_EncryptedMessage         MessageType = 50
-	MessageType_MessageType_DecryptMessage           MessageType = 51
-	MessageType_MessageType_DecryptedMessage         MessageType = 52
-	MessageType_MessageType_SignIdentity             MessageType = 53
-	MessageType_MessageType_SignedIdentity           MessageType = 54
-	MessageType_MessageType_GetFeatures              MessageType = 55
+	// Management
+	MessageType_MessageType_Initialize             MessageType = 0
+	MessageType_MessageType_Ping                   MessageType = 1
+	MessageType_MessageType_Success                MessageType = 2
+	MessageType_MessageType_Failure                MessageType = 3
+	MessageType_MessageType_ChangePin              MessageType = 4
+	MessageType_MessageType_WipeDevice             MessageType = 5
+	MessageType_MessageType_GetEntropy             MessageType = 9
+	MessageType_MessageType_Entropy                MessageType = 10
+	MessageType_MessageType_LoadDevice             MessageType = 13
+	MessageType_MessageType_ResetDevice            MessageType = 14
+	MessageType_MessageType_Features               MessageType = 17
+	MessageType_MessageType_PinMatrixRequest       MessageType = 18
+	MessageType_MessageType_PinMatrixAck           MessageType = 19
+	MessageType_MessageType_Cancel                 MessageType = 20
+	MessageType_MessageType_ClearSession           MessageType = 24
+	MessageType_MessageType_ApplySettings          MessageType = 25
+	MessageType_MessageType_ButtonRequest          MessageType = 26
+	MessageType_MessageType_ButtonAck              MessageType = 27
+	MessageType_MessageType_ApplyFlags             MessageType = 28
+	MessageType_MessageType_BackupDevice           MessageType = 34
+	MessageType_MessageType_EntropyRequest         MessageType = 35
+	MessageType_MessageType_EntropyAck             MessageType = 36
+	MessageType_MessageType_PassphraseRequest      MessageType = 41
+	MessageType_MessageType_PassphraseAck          MessageType = 42
+	MessageType_MessageType_PassphraseStateRequest MessageType = 77
+	MessageType_MessageType_PassphraseStateAck     MessageType = 78
+	MessageType_MessageType_RecoveryDevice         MessageType = 45
+	MessageType_MessageType_WordRequest            MessageType = 46
+	MessageType_MessageType_WordAck                MessageType = 47
+	MessageType_MessageType_GetFeatures            MessageType = 55
+	MessageType_MessageType_SetU2FCounter          MessageType = 63
+	// Bootloader
+	MessageType_MessageType_FirmwareErase   MessageType = 6
+	MessageType_MessageType_FirmwareUpload  MessageType = 7
+	MessageType_MessageType_FirmwareRequest MessageType = 8
+	MessageType_MessageType_SelfTest        MessageType = 32
+	// Bitcoin
+	MessageType_MessageType_GetPublicKey     MessageType = 11
+	MessageType_MessageType_PublicKey        MessageType = 12
+	MessageType_MessageType_SignTx           MessageType = 15
+	MessageType_MessageType_TxRequest        MessageType = 21
+	MessageType_MessageType_TxAck            MessageType = 22
+	MessageType_MessageType_GetAddress       MessageType = 29
+	MessageType_MessageType_Address          MessageType = 30
+	MessageType_MessageType_SignMessage      MessageType = 38
+	MessageType_MessageType_VerifyMessage    MessageType = 39
+	MessageType_MessageType_MessageSignature MessageType = 40
+	// Crypto
+	MessageType_MessageType_CipherKeyValue    MessageType = 23
+	MessageType_MessageType_CipheredKeyValue  MessageType = 48
+	MessageType_MessageType_SignIdentity      MessageType = 53
+	MessageType_MessageType_SignedIdentity    MessageType = 54
+	MessageType_MessageType_GetECDHSessionKey MessageType = 61
+	MessageType_MessageType_ECDHSessionKey    MessageType = 62
+	MessageType_MessageType_CosiCommit        MessageType = 71
+	MessageType_MessageType_CosiCommitment    MessageType = 72
+	MessageType_MessageType_CosiSign          MessageType = 73
+	MessageType_MessageType_CosiSignature     MessageType = 74
+	// Debug
+	MessageType_MessageType_DebugLinkDecision    MessageType = 100
+	MessageType_MessageType_DebugLinkGetState    MessageType = 101
+	MessageType_MessageType_DebugLinkState       MessageType = 102
+	MessageType_MessageType_DebugLinkStop        MessageType = 103
+	MessageType_MessageType_DebugLinkLog         MessageType = 104
+	MessageType_MessageType_DebugLinkMemoryRead  MessageType = 110
+	MessageType_MessageType_DebugLinkMemory      MessageType = 111
+	MessageType_MessageType_DebugLinkMemoryWrite MessageType = 112
+	MessageType_MessageType_DebugLinkFlashErase  MessageType = 113
+	// Ethereum
+	MessageType_MessageType_EthereumGetPublicKey     MessageType = 450
+	MessageType_MessageType_EthereumPublicKey        MessageType = 451
 	MessageType_MessageType_EthereumGetAddress       MessageType = 56
 	MessageType_MessageType_EthereumAddress          MessageType = 57
 	MessageType_MessageType_EthereumSignTx           MessageType = 58
 	MessageType_MessageType_EthereumTxRequest        MessageType = 59
 	MessageType_MessageType_EthereumTxAck            MessageType = 60
-	MessageType_MessageType_GetECDHSessionKey        MessageType = 61
-	MessageType_MessageType_ECDHSessionKey           MessageType = 62
-	MessageType_MessageType_SetU2FCounter            MessageType = 63
 	MessageType_MessageType_EthereumSignMessage      MessageType = 64
 	MessageType_MessageType_EthereumVerifyMessage    MessageType = 65
 	MessageType_MessageType_EthereumMessageSignature MessageType = 66
-	MessageType_MessageType_DebugLinkDecision        MessageType = 100
-	MessageType_MessageType_DebugLinkGetState        MessageType = 101
-	MessageType_MessageType_DebugLinkState           MessageType = 102
-	MessageType_MessageType_DebugLinkStop            MessageType = 103
-	MessageType_MessageType_DebugLinkLog             MessageType = 104
-	MessageType_MessageType_DebugLinkMemoryRead      MessageType = 110
-	MessageType_MessageType_DebugLinkMemory          MessageType = 111
-	MessageType_MessageType_DebugLinkMemoryWrite     MessageType = 112
-	MessageType_MessageType_DebugLinkFlashErase      MessageType = 113
+	// NEM
+	MessageType_MessageType_NEMGetAddress       MessageType = 67
+	MessageType_MessageType_NEMAddress          MessageType = 68
+	MessageType_MessageType_NEMSignTx           MessageType = 69
+	MessageType_MessageType_NEMSignedTx         MessageType = 70
+	MessageType_MessageType_NEMDecryptMessage   MessageType = 75
+	MessageType_MessageType_NEMDecryptedMessage MessageType = 76
+	// Lisk
+	MessageType_MessageType_LiskGetAddress       MessageType = 114
+	MessageType_MessageType_LiskAddress          MessageType = 115
+	MessageType_MessageType_LiskSignTx           MessageType = 116
+	MessageType_MessageType_LiskSignedTx         MessageType = 117
+	MessageType_MessageType_LiskSignMessage      MessageType = 118
+	MessageType_MessageType_LiskMessageSignature MessageType = 119
+	MessageType_MessageType_LiskVerifyMessage    MessageType = 120
+	MessageType_MessageType_LiskGetPublicKey     MessageType = 121
+	MessageType_MessageType_LiskPublicKey        MessageType = 122
+	// Tezos
+	MessageType_MessageType_TezosGetAddress   MessageType = 150
+	MessageType_MessageType_TezosAddress      MessageType = 151
+	MessageType_MessageType_TezosSignTx       MessageType = 152
+	MessageType_MessageType_TezosSignedTx     MessageType = 153
+	MessageType_MessageType_TezosGetPublicKey MessageType = 154
+	MessageType_MessageType_TezosPublicKey    MessageType = 155
+	// Stellar
+	MessageType_MessageType_StellarSignTx               MessageType = 202
+	MessageType_MessageType_StellarTxOpRequest          MessageType = 203
+	MessageType_MessageType_StellarGetAddress           MessageType = 207
+	MessageType_MessageType_StellarAddress              MessageType = 208
+	MessageType_MessageType_StellarCreateAccountOp      MessageType = 210
+	MessageType_MessageType_StellarPaymentOp            MessageType = 211
+	MessageType_MessageType_StellarPathPaymentOp        MessageType = 212
+	MessageType_MessageType_StellarManageOfferOp        MessageType = 213
+	MessageType_MessageType_StellarCreatePassiveOfferOp MessageType = 214
+	MessageType_MessageType_StellarSetOptionsOp         MessageType = 215
+	MessageType_MessageType_StellarChangeTrustOp        MessageType = 216
+	MessageType_MessageType_StellarAllowTrustOp         MessageType = 217
+	MessageType_MessageType_StellarAccountMergeOp       MessageType = 218
+	// omitted: StellarInflationOp is not a supported operation, would be 219
+	MessageType_MessageType_StellarManageDataOp   MessageType = 220
+	MessageType_MessageType_StellarBumpSequenceOp MessageType = 221
+	MessageType_MessageType_StellarSignedTx       MessageType = 230
+	// TRON
+	MessageType_MessageType_TronGetAddress MessageType = 250
+	MessageType_MessageType_TronAddress    MessageType = 251
+	MessageType_MessageType_TronSignTx     MessageType = 252
+	MessageType_MessageType_TronSignedTx   MessageType = 253
+	// Cardano
+	// dropped Sign/VerifyMessage ids 300-302
+	MessageType_MessageType_CardanoSignTx       MessageType = 303
+	MessageType_MessageType_CardanoTxRequest    MessageType = 304
+	MessageType_MessageType_CardanoGetPublicKey MessageType = 305
+	MessageType_MessageType_CardanoPublicKey    MessageType = 306
+	MessageType_MessageType_CardanoGetAddress   MessageType = 307
+	MessageType_MessageType_CardanoAddress      MessageType = 308
+	MessageType_MessageType_CardanoTxAck        MessageType = 309
+	MessageType_MessageType_CardanoSignedTx     MessageType = 310
+	// Ontology
+	MessageType_MessageType_OntologyGetAddress               MessageType = 350
+	MessageType_MessageType_OntologyAddress                  MessageType = 351
+	MessageType_MessageType_OntologyGetPublicKey             MessageType = 352
+	MessageType_MessageType_OntologyPublicKey                MessageType = 353
+	MessageType_MessageType_OntologySignTransfer             MessageType = 354
+	MessageType_MessageType_OntologySignedTransfer           MessageType = 355
+	MessageType_MessageType_OntologySignWithdrawOng          MessageType = 356
+	MessageType_MessageType_OntologySignedWithdrawOng        MessageType = 357
+	MessageType_MessageType_OntologySignOntIdRegister        MessageType = 358
+	MessageType_MessageType_OntologySignedOntIdRegister      MessageType = 359
+	MessageType_MessageType_OntologySignOntIdAddAttributes   MessageType = 360
+	MessageType_MessageType_OntologySignedOntIdAddAttributes MessageType = 361
+	// Ripple
+	MessageType_MessageType_RippleGetAddress MessageType = 400
+	MessageType_MessageType_RippleAddress    MessageType = 401
+	MessageType_MessageType_RippleSignTx     MessageType = 402
+	MessageType_MessageType_RippleSignedTx   MessageType = 403
+	// Monero
+	MessageType_MessageType_MoneroTransactionInitRequest              MessageType = 501
+	MessageType_MessageType_MoneroTransactionInitAck                  MessageType = 502
+	MessageType_MessageType_MoneroTransactionSetInputRequest          MessageType = 503
+	MessageType_MessageType_MoneroTransactionSetInputAck              MessageType = 504
+	MessageType_MessageType_MoneroTransactionInputsPermutationRequest MessageType = 505
+	MessageType_MessageType_MoneroTransactionInputsPermutationAck     MessageType = 506
+	MessageType_MessageType_MoneroTransactionInputViniRequest         MessageType = 507
+	MessageType_MessageType_MoneroTransactionInputViniAck             MessageType = 508
+	MessageType_MessageType_MoneroTransactionAllInputsSetRequest      MessageType = 509
+	MessageType_MessageType_MoneroTransactionAllInputsSetAck          MessageType = 510
+	MessageType_MessageType_MoneroTransactionSetOutputRequest         MessageType = 511
+	MessageType_MessageType_MoneroTransactionSetOutputAck             MessageType = 512
+	MessageType_MessageType_MoneroTransactionAllOutSetRequest         MessageType = 513
+	MessageType_MessageType_MoneroTransactionAllOutSetAck             MessageType = 514
+	MessageType_MessageType_MoneroTransactionSignInputRequest         MessageType = 515
+	MessageType_MessageType_MoneroTransactionSignInputAck             MessageType = 516
+	MessageType_MessageType_MoneroTransactionFinalRequest             MessageType = 517
+	MessageType_MessageType_MoneroTransactionFinalAck                 MessageType = 518
+	MessageType_MessageType_MoneroKeyImageExportInitRequest           MessageType = 530
+	MessageType_MessageType_MoneroKeyImageExportInitAck               MessageType = 531
+	MessageType_MessageType_MoneroKeyImageSyncStepRequest             MessageType = 532
+	MessageType_MessageType_MoneroKeyImageSyncStepAck                 MessageType = 533
+	MessageType_MessageType_MoneroKeyImageSyncFinalRequest            MessageType = 534
+	MessageType_MessageType_MoneroKeyImageSyncFinalAck                MessageType = 535
+	MessageType_MessageType_MoneroGetAddress                          MessageType = 540
+	MessageType_MessageType_MoneroAddress                             MessageType = 541
+	MessageType_MessageType_MoneroGetWatchKey                         MessageType = 542
+	MessageType_MessageType_MoneroWatchKey                            MessageType = 543
+	MessageType_MessageType_DebugMoneroDiagRequest                    MessageType = 546
+	MessageType_MessageType_DebugMoneroDiagAck                        MessageType = 547
+	MessageType_MessageType_MoneroGetTxKeyRequest                     MessageType = 550
+	MessageType_MessageType_MoneroGetTxKeyAck                         MessageType = 551
+	MessageType_MessageType_MoneroLiveRefreshStartRequest             MessageType = 552
+	MessageType_MessageType_MoneroLiveRefreshStartAck                 MessageType = 553
+	MessageType_MessageType_MoneroLiveRefreshStepRequest              MessageType = 554
+	MessageType_MessageType_MoneroLiveRefreshStepAck                  MessageType = 555
+	MessageType_MessageType_MoneroLiveRefreshFinalRequest             MessageType = 556
+	MessageType_MessageType_MoneroLiveRefreshFinalAck                 MessageType = 557
+	// EOS
+	MessageType_MessageType_EosGetPublicKey    MessageType = 600
+	MessageType_MessageType_EosPublicKey       MessageType = 601
+	MessageType_MessageType_EosSignTx          MessageType = 602
+	MessageType_MessageType_EosTxActionRequest MessageType = 603
+	MessageType_MessageType_EosTxActionAck     MessageType = 604
+	MessageType_MessageType_EosSignedTx        MessageType = 605
+	// Binance
+	MessageType_MessageType_BinanceGetAddress   MessageType = 700
+	MessageType_MessageType_BinanceAddress      MessageType = 701
+	MessageType_MessageType_BinanceGetPublicKey MessageType = 702
+	MessageType_MessageType_BinancePublicKey    MessageType = 703
+	MessageType_MessageType_BinanceSignTx       MessageType = 704
+	MessageType_MessageType_BinanceTxRequest    MessageType = 705
+	MessageType_MessageType_BinanceTransferMsg  MessageType = 706
+	MessageType_MessageType_BinanceOrderMsg     MessageType = 707
+	MessageType_MessageType_BinanceCancelMsg    MessageType = 708
+	MessageType_MessageType_BinanceSignedTx     MessageType = 709
 )
 
 var MessageType_name = map[int32]string{
@@ -99,64 +248,55 @@ var MessageType_name = map[int32]string{
 	3:   "MessageType_Failure",
 	4:   "MessageType_ChangePin",
 	5:   "MessageType_WipeDevice",
-	6:   "MessageType_FirmwareErase",
-	7:   "MessageType_FirmwareUpload",
-	8:   "MessageType_FirmwareRequest",
 	9:   "MessageType_GetEntropy",
 	10:  "MessageType_Entropy",
-	11:  "MessageType_GetPublicKey",
-	12:  "MessageType_PublicKey",
 	13:  "MessageType_LoadDevice",
 	14:  "MessageType_ResetDevice",
-	15:  "MessageType_SignTx",
-	16:  "MessageType_SimpleSignTx",
 	17:  "MessageType_Features",
 	18:  "MessageType_PinMatrixRequest",
 	19:  "MessageType_PinMatrixAck",
 	20:  "MessageType_Cancel",
-	21:  "MessageType_TxRequest",
-	22:  "MessageType_TxAck",
-	23:  "MessageType_CipherKeyValue",
 	24:  "MessageType_ClearSession",
 	25:  "MessageType_ApplySettings",
 	26:  "MessageType_ButtonRequest",
 	27:  "MessageType_ButtonAck",
 	28:  "MessageType_ApplyFlags",
-	29:  "MessageType_GetAddress",
-	30:  "MessageType_Address",
-	32:  "MessageType_SelfTest",
 	34:  "MessageType_BackupDevice",
 	35:  "MessageType_EntropyRequest",
 	36:  "MessageType_EntropyAck",
-	38:  "MessageType_SignMessage",
-	39:  "MessageType_VerifyMessage",
-	40:  "MessageType_MessageSignature",
 	41:  "MessageType_PassphraseRequest",
 	42:  "MessageType_PassphraseAck",
-	43:  "MessageType_EstimateTxSize",
-	44:  "MessageType_TxSize",
+	77:  "MessageType_PassphraseStateRequest",
+	78:  "MessageType_PassphraseStateAck",
 	45:  "MessageType_RecoveryDevice",
 	46:  "MessageType_WordRequest",
 	47:  "MessageType_WordAck",
+	55:  "MessageType_GetFeatures",
+	63:  "MessageType_SetU2FCounter",
+	6:   "MessageType_FirmwareErase",
+	7:   "MessageType_FirmwareUpload",
+	8:   "MessageType_FirmwareRequest",
+	32:  "MessageType_SelfTest",
+	11:  "MessageType_GetPublicKey",
+	12:  "MessageType_PublicKey",
+	15:  "MessageType_SignTx",
+	21:  "MessageType_TxRequest",
+	22:  "MessageType_TxAck",
+	29:  "MessageType_GetAddress",
+	30:  "MessageType_Address",
+	38:  "MessageType_SignMessage",
+	39:  "MessageType_VerifyMessage",
+	40:  "MessageType_MessageSignature",
+	23:  "MessageType_CipherKeyValue",
 	48:  "MessageType_CipheredKeyValue",
-	49:  "MessageType_EncryptMessage",
-	50:  "MessageType_EncryptedMessage",
-	51:  "MessageType_DecryptMessage",
-	52:  "MessageType_DecryptedMessage",
 	53:  "MessageType_SignIdentity",
 	54:  "MessageType_SignedIdentity",
-	55:  "MessageType_GetFeatures",
-	56:  "MessageType_EthereumGetAddress",
-	57:  "MessageType_EthereumAddress",
-	58:  "MessageType_EthereumSignTx",
-	59:  "MessageType_EthereumTxRequest",
-	60:  "MessageType_EthereumTxAck",
 	61:  "MessageType_GetECDHSessionKey",
 	62:  "MessageType_ECDHSessionKey",
-	63:  "MessageType_SetU2FCounter",
-	64:  "MessageType_EthereumSignMessage",
-	65:  "MessageType_EthereumVerifyMessage",
-	66:  "MessageType_EthereumMessageSignature",
+	71:  "MessageType_CosiCommit",
+	72:  "MessageType_CosiCommitment",
+	73:  "MessageType_CosiSign",
+	74:  "MessageType_CosiSignature",
 	100: "MessageType_DebugLinkDecision",
 	101: "MessageType_DebugLinkGetState",
 	102: "MessageType_DebugLinkState",
@@ -166,81 +306,331 @@ var MessageType_name = map[int32]string{
 	111: "MessageType_DebugLinkMemory",
 	112: "MessageType_DebugLinkMemoryWrite",
 	113: "MessageType_DebugLinkFlashErase",
+	450: "MessageType_EthereumGetPublicKey",
+	451: "MessageType_EthereumPublicKey",
+	56:  "MessageType_EthereumGetAddress",
+	57:  "MessageType_EthereumAddress",
+	58:  "MessageType_EthereumSignTx",
+	59:  "MessageType_EthereumTxRequest",
+	60:  "MessageType_EthereumTxAck",
+	64:  "MessageType_EthereumSignMessage",
+	65:  "MessageType_EthereumVerifyMessage",
+	66:  "MessageType_EthereumMessageSignature",
+	67:  "MessageType_NEMGetAddress",
+	68:  "MessageType_NEMAddress",
+	69:  "MessageType_NEMSignTx",
+	70:  "MessageType_NEMSignedTx",
+	75:  "MessageType_NEMDecryptMessage",
+	76:  "MessageType_NEMDecryptedMessage",
+	114: "MessageType_LiskGetAddress",
+	115: "MessageType_LiskAddress",
+	116: "MessageType_LiskSignTx",
+	117: "MessageType_LiskSignedTx",
+	118: "MessageType_LiskSignMessage",
+	119: "MessageType_LiskMessageSignature",
+	120: "MessageType_LiskVerifyMessage",
+	121: "MessageType_LiskGetPublicKey",
+	122: "MessageType_LiskPublicKey",
+	150: "MessageType_TezosGetAddress",
+	151: "MessageType_TezosAddress",
+	152: "MessageType_TezosSignTx",
+	153: "MessageType_TezosSignedTx",
+	154: "MessageType_TezosGetPublicKey",
+	155: "MessageType_TezosPublicKey",
+	202: "MessageType_StellarSignTx",
+	203: "MessageType_StellarTxOpRequest",
+	207: "MessageType_StellarGetAddress",
+	208: "MessageType_StellarAddress",
+	210: "MessageType_StellarCreateAccountOp",
+	211: "MessageType_StellarPaymentOp",
+	212: "MessageType_StellarPathPaymentOp",
+	213: "MessageType_StellarManageOfferOp",
+	214: "MessageType_StellarCreatePassiveOfferOp",
+	215: "MessageType_StellarSetOptionsOp",
+	216: "MessageType_StellarChangeTrustOp",
+	217: "MessageType_StellarAllowTrustOp",
+	218: "MessageType_StellarAccountMergeOp",
+	220: "MessageType_StellarManageDataOp",
+	221: "MessageType_StellarBumpSequenceOp",
+	230: "MessageType_StellarSignedTx",
+	250: "MessageType_TronGetAddress",
+	251: "MessageType_TronAddress",
+	252: "MessageType_TronSignTx",
+	253: "MessageType_TronSignedTx",
+	303: "MessageType_CardanoSignTx",
+	304: "MessageType_CardanoTxRequest",
+	305: "MessageType_CardanoGetPublicKey",
+	306: "MessageType_CardanoPublicKey",
+	307: "MessageType_CardanoGetAddress",
+	308: "MessageType_CardanoAddress",
+	309: "MessageType_CardanoTxAck",
+	310: "MessageType_CardanoSignedTx",
+	350: "MessageType_OntologyGetAddress",
+	351: "MessageType_OntologyAddress",
+	352: "MessageType_OntologyGetPublicKey",
+	353: "MessageType_OntologyPublicKey",
+	354: "MessageType_OntologySignTransfer",
+	355: "MessageType_OntologySignedTransfer",
+	356: "MessageType_OntologySignWithdrawOng",
+	357: "MessageType_OntologySignedWithdrawOng",
+	358: "MessageType_OntologySignOntIdRegister",
+	359: "MessageType_OntologySignedOntIdRegister",
+	360: "MessageType_OntologySignOntIdAddAttributes",
+	361: "MessageType_OntologySignedOntIdAddAttributes",
+	400: "MessageType_RippleGetAddress",
+	401: "MessageType_RippleAddress",
+	402: "MessageType_RippleSignTx",
+	403: "MessageType_RippleSignedTx",
+	501: "MessageType_MoneroTransactionInitRequest",
+	502: "MessageType_MoneroTransactionInitAck",
+	503: "MessageType_MoneroTransactionSetInputRequest",
+	504: "MessageType_MoneroTransactionSetInputAck",
+	505: "MessageType_MoneroTransactionInputsPermutationRequest",
+	506: "MessageType_MoneroTransactionInputsPermutationAck",
+	507: "MessageType_MoneroTransactionInputViniRequest",
+	508: "MessageType_MoneroTransactionInputViniAck",
+	509: "MessageType_MoneroTransactionAllInputsSetRequest",
+	510: "MessageType_MoneroTransactionAllInputsSetAck",
+	511: "MessageType_MoneroTransactionSetOutputRequest",
+	512: "MessageType_MoneroTransactionSetOutputAck",
+	513: "MessageType_MoneroTransactionAllOutSetRequest",
+	514: "MessageType_MoneroTransactionAllOutSetAck",
+	515: "MessageType_MoneroTransactionSignInputRequest",
+	516: "MessageType_MoneroTransactionSignInputAck",
+	517: "MessageType_MoneroTransactionFinalRequest",
+	518: "MessageType_MoneroTransactionFinalAck",
+	530: "MessageType_MoneroKeyImageExportInitRequest",
+	531: "MessageType_MoneroKeyImageExportInitAck",
+	532: "MessageType_MoneroKeyImageSyncStepRequest",
+	533: "MessageType_MoneroKeyImageSyncStepAck",
+	534: "MessageType_MoneroKeyImageSyncFinalRequest",
+	535: "MessageType_MoneroKeyImageSyncFinalAck",
+	540: "MessageType_MoneroGetAddress",
+	541: "MessageType_MoneroAddress",
+	542: "MessageType_MoneroGetWatchKey",
+	543: "MessageType_MoneroWatchKey",
+	546: "MessageType_DebugMoneroDiagRequest",
+	547: "MessageType_DebugMoneroDiagAck",
+	550: "MessageType_MoneroGetTxKeyRequest",
+	551: "MessageType_MoneroGetTxKeyAck",
+	552: "MessageType_MoneroLiveRefreshStartRequest",
+	553: "MessageType_MoneroLiveRefreshStartAck",
+	554: "MessageType_MoneroLiveRefreshStepRequest",
+	555: "MessageType_MoneroLiveRefreshStepAck",
+	556: "MessageType_MoneroLiveRefreshFinalRequest",
+	557: "MessageType_MoneroLiveRefreshFinalAck",
+	600: "MessageType_EosGetPublicKey",
+	601: "MessageType_EosPublicKey",
+	602: "MessageType_EosSignTx",
+	603: "MessageType_EosTxActionRequest",
+	604: "MessageType_EosTxActionAck",
+	605: "MessageType_EosSignedTx",
+	700: "MessageType_BinanceGetAddress",
+	701: "MessageType_BinanceAddress",
+	702: "MessageType_BinanceGetPublicKey",
+	703: "MessageType_BinancePublicKey",
+	704: "MessageType_BinanceSignTx",
+	705: "MessageType_BinanceTxRequest",
+	706: "MessageType_BinanceTransferMsg",
+	707: "MessageType_BinanceOrderMsg",
+	708: "MessageType_BinanceCancelMsg",
+	709: "MessageType_BinanceSignedTx",
 }
+
 var MessageType_value = map[string]int32{
-	"MessageType_Initialize":               0,
-	"MessageType_Ping":                     1,
-	"MessageType_Success":                  2,
-	"MessageType_Failure":                  3,
-	"MessageType_ChangePin":                4,
-	"MessageType_WipeDevice":               5,
-	"MessageType_FirmwareErase":            6,
-	"MessageType_FirmwareUpload":           7,
-	"MessageType_FirmwareRequest":          8,
-	"MessageType_GetEntropy":               9,
-	"MessageType_Entropy":                  10,
-	"MessageType_GetPublicKey":             11,
-	"MessageType_PublicKey":                12,
-	"MessageType_LoadDevice":               13,
-	"MessageType_ResetDevice":              14,
-	"MessageType_SignTx":                   15,
-	"MessageType_SimpleSignTx":             16,
-	"MessageType_Features":                 17,
-	"MessageType_PinMatrixRequest":         18,
-	"MessageType_PinMatrixAck":             19,
-	"MessageType_Cancel":                   20,
-	"MessageType_TxRequest":                21,
-	"MessageType_TxAck":                    22,
-	"MessageType_CipherKeyValue":           23,
-	"MessageType_ClearSession":             24,
-	"MessageType_ApplySettings":            25,
-	"MessageType_ButtonRequest":            26,
-	"MessageType_ButtonAck":                27,
-	"MessageType_ApplyFlags":               28,
-	"MessageType_GetAddress":               29,
-	"MessageType_Address":                  30,
-	"MessageType_SelfTest":                 32,
-	"MessageType_BackupDevice":             34,
-	"MessageType_EntropyRequest":           35,
-	"MessageType_EntropyAck":               36,
-	"MessageType_SignMessage":              38,
-	"MessageType_VerifyMessage":            39,
-	"MessageType_MessageSignature":         40,
-	"MessageType_PassphraseRequest":        41,
-	"MessageType_PassphraseAck":            42,
-	"MessageType_EstimateTxSize":           43,
-	"MessageType_TxSize":                   44,
-	"MessageType_RecoveryDevice":           45,
-	"MessageType_WordRequest":              46,
-	"MessageType_WordAck":                  47,
-	"MessageType_CipheredKeyValue":         48,
-	"MessageType_EncryptMessage":           49,
-	"MessageType_EncryptedMessage":         50,
-	"MessageType_DecryptMessage":           51,
-	"MessageType_DecryptedMessage":         52,
-	"MessageType_SignIdentity":             53,
-	"MessageType_SignedIdentity":           54,
-	"MessageType_GetFeatures":              55,
-	"MessageType_EthereumGetAddress":       56,
-	"MessageType_EthereumAddress":          57,
-	"MessageType_EthereumSignTx":           58,
-	"MessageType_EthereumTxRequest":        59,
-	"MessageType_EthereumTxAck":            60,
-	"MessageType_GetECDHSessionKey":        61,
-	"MessageType_ECDHSessionKey":           62,
-	"MessageType_SetU2FCounter":            63,
-	"MessageType_EthereumSignMessage":      64,
-	"MessageType_EthereumVerifyMessage":    65,
-	"MessageType_EthereumMessageSignature": 66,
-	"MessageType_DebugLinkDecision":        100,
-	"MessageType_DebugLinkGetState":        101,
-	"MessageType_DebugLinkState":           102,
-	"MessageType_DebugLinkStop":            103,
-	"MessageType_DebugLinkLog":             104,
-	"MessageType_DebugLinkMemoryRead":      110,
-	"MessageType_DebugLinkMemory":          111,
-	"MessageType_DebugLinkMemoryWrite":     112,
-	"MessageType_DebugLinkFlashErase":      113,
+	"MessageType_Initialize":                                0,
+	"MessageType_Ping":                                      1,
+	"MessageType_Success":                                   2,
+	"MessageType_Failure":                                   3,
+	"MessageType_ChangePin":                                 4,
+	"MessageType_WipeDevice":                                5,
+	"MessageType_GetEntropy":                                9,
+	"MessageType_Entropy":                                   10,
+	"MessageType_LoadDevice":                                13,
+	"MessageType_ResetDevice":                               14,
+	"MessageType_Features":                                  17,
+	"MessageType_PinMatrixRequest":                          18,
+	"MessageType_PinMatrixAck":                              19,
+	"MessageType_Cancel":                                    20,
+	"MessageType_ClearSession":                              24,
+	"MessageType_ApplySettings":                             25,
+	"MessageType_ButtonRequest":                             26,
+	"MessageType_ButtonAck":                                 27,
+	"MessageType_ApplyFlags":                                28,
+	"MessageType_BackupDevice":                              34,
+	"MessageType_EntropyRequest":                            35,
+	"MessageType_EntropyAck":                                36,
+	"MessageType_PassphraseRequest":                         41,
+	"MessageType_PassphraseAck":                             42,
+	"MessageType_PassphraseStateRequest":                    77,
+	"MessageType_PassphraseStateAck":                        78,
+	"MessageType_RecoveryDevice":                            45,
+	"MessageType_WordRequest":                               46,
+	"MessageType_WordAck":                                   47,
+	"MessageType_GetFeatures":                               55,
+	"MessageType_SetU2FCounter":                             63,
+	"MessageType_FirmwareErase":                             6,
+	"MessageType_FirmwareUpload":                            7,
+	"MessageType_FirmwareRequest":                           8,
+	"MessageType_SelfTest":                                  32,
+	"MessageType_GetPublicKey":                              11,
+	"MessageType_PublicKey":                                 12,
+	"MessageType_SignTx":                                    15,
+	"MessageType_TxRequest":                                 21,
+	"MessageType_TxAck":                                     22,
+	"MessageType_GetAddress":                                29,
+	"MessageType_Address":                                   30,
+	"MessageType_SignMessage":                               38,
+	"MessageType_VerifyMessage":                             39,
+	"MessageType_MessageSignature":                          40,
+	"MessageType_CipherKeyValue":                            23,
+	"MessageType_CipheredKeyValue":                          48,
+	"MessageType_SignIdentity":                              53,
+	"MessageType_SignedIdentity":                            54,
+	"MessageType_GetECDHSessionKey":                         61,
+	"MessageType_ECDHSessionKey":                            62,
+	"MessageType_CosiCommit":                                71,
+	"MessageType_CosiCommitment":                            72,
+	"MessageType_CosiSign":                                  73,
+	"MessageType_CosiSignature":                             74,
+	"MessageType_DebugLinkDecision":                         100,
+	"MessageType_DebugLinkGetState":                         101,
+	"MessageType_DebugLinkState":                            102,
+	"MessageType_DebugLinkStop":                             103,
+	"MessageType_DebugLinkLog":                              104,
+	"MessageType_DebugLinkMemoryRead":                       110,
+	"MessageType_DebugLinkMemory":                           111,
+	"MessageType_DebugLinkMemoryWrite":                      112,
+	"MessageType_DebugLinkFlashErase":                       113,
+	"MessageType_EthereumGetPublicKey":                      450,
+	"MessageType_EthereumPublicKey":                         451,
+	"MessageType_EthereumGetAddress":                        56,
+	"MessageType_EthereumAddress":                           57,
+	"MessageType_EthereumSignTx":                            58,
+	"MessageType_EthereumTxRequest":                         59,
+	"MessageType_EthereumTxAck":                             60,
+	"MessageType_EthereumSignMessage":                       64,
+	"MessageType_EthereumVerifyMessage":                     65,
+	"MessageType_EthereumMessageSignature":                  66,
+	"MessageType_NEMGetAddress":                             67,
+	"MessageType_NEMAddress":                                68,
+	"MessageType_NEMSignTx":                                 69,
+	"MessageType_NEMSignedTx":                               70,
+	"MessageType_NEMDecryptMessage":                         75,
+	"MessageType_NEMDecryptedMessage":                       76,
+	"MessageType_LiskGetAddress":                            114,
+	"MessageType_LiskAddress":                               115,
+	"MessageType_LiskSignTx":                                116,
+	"MessageType_LiskSignedTx":                              117,
+	"MessageType_LiskSignMessage":                           118,
+	"MessageType_LiskMessageSignature":                      119,
+	"MessageType_LiskVerifyMessage":                         120,
+	"MessageType_LiskGetPublicKey":                          121,
+	"MessageType_LiskPublicKey":                             122,
+	"MessageType_TezosGetAddress":                           150,
+	"MessageType_TezosAddress":                              151,
+	"MessageType_TezosSignTx":                               152,
+	"MessageType_TezosSignedTx":                             153,
+	"MessageType_TezosGetPublicKey":                         154,
+	"MessageType_TezosPublicKey":                            155,
+	"MessageType_StellarSignTx":                             202,
+	"MessageType_StellarTxOpRequest":                        203,
+	"MessageType_StellarGetAddress":                         207,
+	"MessageType_StellarAddress":                            208,
+	"MessageType_StellarCreateAccountOp":                    210,
+	"MessageType_StellarPaymentOp":                          211,
+	"MessageType_StellarPathPaymentOp":                      212,
+	"MessageType_StellarManageOfferOp":                      213,
+	"MessageType_StellarCreatePassiveOfferOp":               214,
+	"MessageType_StellarSetOptionsOp":                       215,
+	"MessageType_StellarChangeTrustOp":                      216,
+	"MessageType_StellarAllowTrustOp":                       217,
+	"MessageType_StellarAccountMergeOp":                     218,
+	"MessageType_StellarManageDataOp":                       220,
+	"MessageType_StellarBumpSequenceOp":                     221,
+	"MessageType_StellarSignedTx":                           230,
+	"MessageType_TronGetAddress":                            250,
+	"MessageType_TronAddress":                               251,
+	"MessageType_TronSignTx":                                252,
+	"MessageType_TronSignedTx":                              253,
+	"MessageType_CardanoSignTx":                             303,
+	"MessageType_CardanoTxRequest":                          304,
+	"MessageType_CardanoGetPublicKey":                       305,
+	"MessageType_CardanoPublicKey":                          306,
+	"MessageType_CardanoGetAddress":                         307,
+	"MessageType_CardanoAddress":                            308,
+	"MessageType_CardanoTxAck":                              309,
+	"MessageType_CardanoSignedTx":                           310,
+	"MessageType_OntologyGetAddress":                        350,
+	"MessageType_OntologyAddress":                           351,
+	"MessageType_OntologyGetPublicKey":                      352,
+	"MessageType_OntologyPublicKey":                         353,
+	"MessageType_OntologySignTransfer":                      354,
+	"MessageType_OntologySignedTransfer":                    355,
+	"MessageType_OntologySignWithdrawOng":                   356,
+	"MessageType_OntologySignedWithdrawOng":                 357,
+	"MessageType_OntologySignOntIdRegister":                 358,
+	"MessageType_OntologySignedOntIdRegister":               359,
+	"MessageType_OntologySignOntIdAddAttributes":            360,
+	"MessageType_OntologySignedOntIdAddAttributes":          361,
+	"MessageType_RippleGetAddress":                          400,
+	"MessageType_RippleAddress":                             401,
+	"MessageType_RippleSignTx":                              402,
+	"MessageType_RippleSignedTx":                            403,
+	"MessageType_MoneroTransactionInitRequest":              501,
+	"MessageType_MoneroTransactionInitAck":                  502,
+	"MessageType_MoneroTransactionSetInputRequest":          503,
+	"MessageType_MoneroTransactionSetInputAck":              504,
+	"MessageType_MoneroTransactionInputsPermutationRequest": 505,
+	"MessageType_MoneroTransactionInputsPermutationAck":     506,
+	"MessageType_MoneroTransactionInputViniRequest":         507,
+	"MessageType_MoneroTransactionInputViniAck":             508,
+	"MessageType_MoneroTransactionAllInputsSetRequest":      509,
+	"MessageType_MoneroTransactionAllInputsSetAck":          510,
+	"MessageType_MoneroTransactionSetOutputRequest":         511,
+	"MessageType_MoneroTransactionSetOutputAck":             512,
+	"MessageType_MoneroTransactionAllOutSetRequest":         513,
+	"MessageType_MoneroTransactionAllOutSetAck":             514,
+	"MessageType_MoneroTransactionSignInputRequest":         515,
+	"MessageType_MoneroTransactionSignInputAck":             516,
+	"MessageType_MoneroTransactionFinalRequest":             517,
+	"MessageType_MoneroTransactionFinalAck":                 518,
+	"MessageType_MoneroKeyImageExportInitRequest":           530,
+	"MessageType_MoneroKeyImageExportInitAck":               531,
+	"MessageType_MoneroKeyImageSyncStepRequest":             532,
+	"MessageType_MoneroKeyImageSyncStepAck":                 533,
+	"MessageType_MoneroKeyImageSyncFinalRequest":            534,
+	"MessageType_MoneroKeyImageSyncFinalAck":                535,
+	"MessageType_MoneroGetAddress":                          540,
+	"MessageType_MoneroAddress":                             541,
+	"MessageType_MoneroGetWatchKey":                         542,
+	"MessageType_MoneroWatchKey":                            543,
+	"MessageType_DebugMoneroDiagRequest":                    546,
+	"MessageType_DebugMoneroDiagAck":                        547,
+	"MessageType_MoneroGetTxKeyRequest":                     550,
+	"MessageType_MoneroGetTxKeyAck":                         551,
+	"MessageType_MoneroLiveRefreshStartRequest":             552,
+	"MessageType_MoneroLiveRefreshStartAck":                 553,
+	"MessageType_MoneroLiveRefreshStepRequest":              554,
+	"MessageType_MoneroLiveRefreshStepAck":                  555,
+	"MessageType_MoneroLiveRefreshFinalRequest":             556,
+	"MessageType_MoneroLiveRefreshFinalAck":                 557,
+	"MessageType_EosGetPublicKey":                           600,
+	"MessageType_EosPublicKey":                              601,
+	"MessageType_EosSignTx":                                 602,
+	"MessageType_EosTxActionRequest":                        603,
+	"MessageType_EosTxActionAck":                            604,
+	"MessageType_EosSignedTx":                               605,
+	"MessageType_BinanceGetAddress":                         700,
+	"MessageType_BinanceAddress":                            701,
+	"MessageType_BinanceGetPublicKey":                       702,
+	"MessageType_BinancePublicKey":                          703,
+	"MessageType_BinanceSignTx":                             704,
+	"MessageType_BinanceTxRequest":                          705,
+	"MessageType_BinanceTransferMsg":                        706,
+	"MessageType_BinanceOrderMsg":                           707,
+	"MessageType_BinanceCancelMsg":                          708,
+	"MessageType_BinanceSignedTx":                           709,
 }
 
 func (x MessageType) Enum() *MessageType {
@@ -248,9 +638,11 @@ func (x MessageType) Enum() *MessageType {
 	*p = x
 	return p
 }
+
 func (x MessageType) String() string {
 	return proto.EnumName(MessageType_name, int32(x))
 }
+
 func (x *MessageType) UnmarshalJSON(data []byte) error {
 	value, err := proto.UnmarshalJSONEnum(MessageType_value, data, "MessageType")
 	if err != nil {
@@ -259,2823 +651,239 @@ func (x *MessageType) UnmarshalJSON(data []byte) error {
 	*x = MessageType(value)
 	return nil
 }
-func (MessageType) EnumDescriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
-
-// *
-// Request: Reset device to default state and ask for device details
-// @next Features
-type Initialize struct {
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *Initialize) Reset()                    { *m = Initialize{} }
-func (m *Initialize) String() string            { return proto.CompactTextString(m) }
-func (*Initialize) ProtoMessage()               {}
-func (*Initialize) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
-
-// *
-// Request: Ask for device details (no device reset)
-// @next Features
-type GetFeatures struct {
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *GetFeatures) Reset()                    { *m = GetFeatures{} }
-func (m *GetFeatures) String() string            { return proto.CompactTextString(m) }
-func (*GetFeatures) ProtoMessage()               {}
-func (*GetFeatures) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} }
-
-// *
-// Response: Reports various information about the device
-// @prev Initialize
-// @prev GetFeatures
-type Features struct {
-	Vendor               *string     `protobuf:"bytes,1,opt,name=vendor" json:"vendor,omitempty"`
-	MajorVersion         *uint32     `protobuf:"varint,2,opt,name=major_version,json=majorVersion" json:"major_version,omitempty"`
-	MinorVersion         *uint32     `protobuf:"varint,3,opt,name=minor_version,json=minorVersion" json:"minor_version,omitempty"`
-	PatchVersion         *uint32     `protobuf:"varint,4,opt,name=patch_version,json=patchVersion" json:"patch_version,omitempty"`
-	BootloaderMode       *bool       `protobuf:"varint,5,opt,name=bootloader_mode,json=bootloaderMode" json:"bootloader_mode,omitempty"`
-	DeviceId             *string     `protobuf:"bytes,6,opt,name=device_id,json=deviceId" json:"device_id,omitempty"`
-	PinProtection        *bool       `protobuf:"varint,7,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"`
-	PassphraseProtection *bool       `protobuf:"varint,8,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"`
-	Language             *string     `protobuf:"bytes,9,opt,name=language" json:"language,omitempty"`
-	Label                *string     `protobuf:"bytes,10,opt,name=label" json:"label,omitempty"`
-	Coins                []*CoinType `protobuf:"bytes,11,rep,name=coins" json:"coins,omitempty"`
-	Initialized          *bool       `protobuf:"varint,12,opt,name=initialized" json:"initialized,omitempty"`
-	Revision             []byte      `protobuf:"bytes,13,opt,name=revision" json:"revision,omitempty"`
-	BootloaderHash       []byte      `protobuf:"bytes,14,opt,name=bootloader_hash,json=bootloaderHash" json:"bootloader_hash,omitempty"`
-	Imported             *bool       `protobuf:"varint,15,opt,name=imported" json:"imported,omitempty"`
-	PinCached            *bool       `protobuf:"varint,16,opt,name=pin_cached,json=pinCached" json:"pin_cached,omitempty"`
-	PassphraseCached     *bool       `protobuf:"varint,17,opt,name=passphrase_cached,json=passphraseCached" json:"passphrase_cached,omitempty"`
-	FirmwarePresent      *bool       `protobuf:"varint,18,opt,name=firmware_present,json=firmwarePresent" json:"firmware_present,omitempty"`
-	NeedsBackup          *bool       `protobuf:"varint,19,opt,name=needs_backup,json=needsBackup" json:"needs_backup,omitempty"`
-	Flags                *uint32     `protobuf:"varint,20,opt,name=flags" json:"flags,omitempty"`
-	XXX_unrecognized     []byte      `json:"-"`
-}
-
-func (m *Features) Reset()                    { *m = Features{} }
-func (m *Features) String() string            { return proto.CompactTextString(m) }
-func (*Features) ProtoMessage()               {}
-func (*Features) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} }
-
-func (m *Features) GetVendor() string {
-	if m != nil && m.Vendor != nil {
-		return *m.Vendor
-	}
-	return ""
-}
-
-func (m *Features) GetMajorVersion() uint32 {
-	if m != nil && m.MajorVersion != nil {
-		return *m.MajorVersion
-	}
-	return 0
-}
-
-func (m *Features) GetMinorVersion() uint32 {
-	if m != nil && m.MinorVersion != nil {
-		return *m.MinorVersion
-	}
-	return 0
-}
-
-func (m *Features) GetPatchVersion() uint32 {
-	if m != nil && m.PatchVersion != nil {
-		return *m.PatchVersion
-	}
-	return 0
-}
-
-func (m *Features) GetBootloaderMode() bool {
-	if m != nil && m.BootloaderMode != nil {
-		return *m.BootloaderMode
-	}
-	return false
-}
-
-func (m *Features) GetDeviceId() string {
-	if m != nil && m.DeviceId != nil {
-		return *m.DeviceId
-	}
-	return ""
-}
-
-func (m *Features) GetPinProtection() bool {
-	if m != nil && m.PinProtection != nil {
-		return *m.PinProtection
-	}
-	return false
-}
-
-func (m *Features) GetPassphraseProtection() bool {
-	if m != nil && m.PassphraseProtection != nil {
-		return *m.PassphraseProtection
-	}
-	return false
-}
-
-func (m *Features) GetLanguage() string {
-	if m != nil && m.Language != nil {
-		return *m.Language
-	}
-	return ""
-}
-
-func (m *Features) GetLabel() string {
-	if m != nil && m.Label != nil {
-		return *m.Label
-	}
-	return ""
-}
-
-func (m *Features) GetCoins() []*CoinType {
-	if m != nil {
-		return m.Coins
-	}
-	return nil
-}
-
-func (m *Features) GetInitialized() bool {
-	if m != nil && m.Initialized != nil {
-		return *m.Initialized
-	}
-	return false
-}
-
-func (m *Features) GetRevision() []byte {
-	if m != nil {
-		return m.Revision
-	}
-	return nil
-}
-
-func (m *Features) GetBootloaderHash() []byte {
-	if m != nil {
-		return m.BootloaderHash
-	}
-	return nil
-}
-
-func (m *Features) GetImported() bool {
-	if m != nil && m.Imported != nil {
-		return *m.Imported
-	}
-	return false
-}
-
-func (m *Features) GetPinCached() bool {
-	if m != nil && m.PinCached != nil {
-		return *m.PinCached
-	}
-	return false
-}
-
-func (m *Features) GetPassphraseCached() bool {
-	if m != nil && m.PassphraseCached != nil {
-		return *m.PassphraseCached
-	}
-	return false
-}
-
-func (m *Features) GetFirmwarePresent() bool {
-	if m != nil && m.FirmwarePresent != nil {
-		return *m.FirmwarePresent
-	}
-	return false
-}
-
-func (m *Features) GetNeedsBackup() bool {
-	if m != nil && m.NeedsBackup != nil {
-		return *m.NeedsBackup
-	}
-	return false
-}
-
-func (m *Features) GetFlags() uint32 {
-	if m != nil && m.Flags != nil {
-		return *m.Flags
-	}
-	return 0
-}
-
-// *
-// Request: clear session (removes cached PIN, passphrase, etc).
-// @next Success
-type ClearSession struct {
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *ClearSession) Reset()                    { *m = ClearSession{} }
-func (m *ClearSession) String() string            { return proto.CompactTextString(m) }
-func (*ClearSession) ProtoMessage()               {}
-func (*ClearSession) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{3} }
-
-// *
-// Request: change language and/or label of the device
-// @next Success
-// @next Failure
-// @next ButtonRequest
-// @next PinMatrixRequest
-type ApplySettings struct {
-	Language         *string `protobuf:"bytes,1,opt,name=language" json:"language,omitempty"`
-	Label            *string `protobuf:"bytes,2,opt,name=label" json:"label,omitempty"`
-	UsePassphrase    *bool   `protobuf:"varint,3,opt,name=use_passphrase,json=usePassphrase" json:"use_passphrase,omitempty"`
-	Homescreen       []byte  `protobuf:"bytes,4,opt,name=homescreen" json:"homescreen,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *ApplySettings) Reset()                    { *m = ApplySettings{} }
-func (m *ApplySettings) String() string            { return proto.CompactTextString(m) }
-func (*ApplySettings) ProtoMessage()               {}
-func (*ApplySettings) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{4} }
-
-func (m *ApplySettings) GetLanguage() string {
-	if m != nil && m.Language != nil {
-		return *m.Language
-	}
-	return ""
-}
-
-func (m *ApplySettings) GetLabel() string {
-	if m != nil && m.Label != nil {
-		return *m.Label
-	}
-	return ""
-}
-
-func (m *ApplySettings) GetUsePassphrase() bool {
-	if m != nil && m.UsePassphrase != nil {
-		return *m.UsePassphrase
-	}
-	return false
-}
-
-func (m *ApplySettings) GetHomescreen() []byte {
-	if m != nil {
-		return m.Homescreen
-	}
-	return nil
-}
-
-// *
-// Request: set flags of the device
-// @next Success
-// @next Failure
-type ApplyFlags struct {
-	Flags            *uint32 `protobuf:"varint,1,opt,name=flags" json:"flags,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *ApplyFlags) Reset()                    { *m = ApplyFlags{} }
-func (m *ApplyFlags) String() string            { return proto.CompactTextString(m) }
-func (*ApplyFlags) ProtoMessage()               {}
-func (*ApplyFlags) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{5} }
-
-func (m *ApplyFlags) GetFlags() uint32 {
-	if m != nil && m.Flags != nil {
-		return *m.Flags
-	}
-	return 0
-}
-
-// *
-// Request: Starts workflow for setting/changing/removing the PIN
-// @next ButtonRequest
-// @next PinMatrixRequest
-type ChangePin struct {
-	Remove           *bool  `protobuf:"varint,1,opt,name=remove" json:"remove,omitempty"`
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *ChangePin) Reset()                    { *m = ChangePin{} }
-func (m *ChangePin) String() string            { return proto.CompactTextString(m) }
-func (*ChangePin) ProtoMessage()               {}
-func (*ChangePin) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{6} }
-
-func (m *ChangePin) GetRemove() bool {
-	if m != nil && m.Remove != nil {
-		return *m.Remove
-	}
-	return false
-}
-
-// *
-// Request: Test if the device is alive, device sends back the message in Success response
-// @next Success
-type Ping struct {
-	Message              *string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"`
-	ButtonProtection     *bool   `protobuf:"varint,2,opt,name=button_protection,json=buttonProtection" json:"button_protection,omitempty"`
-	PinProtection        *bool   `protobuf:"varint,3,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"`
-	PassphraseProtection *bool   `protobuf:"varint,4,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"`
-	XXX_unrecognized     []byte  `json:"-"`
-}
-
-func (m *Ping) Reset()                    { *m = Ping{} }
-func (m *Ping) String() string            { return proto.CompactTextString(m) }
-func (*Ping) ProtoMessage()               {}
-func (*Ping) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{7} }
-
-func (m *Ping) GetMessage() string {
-	if m != nil && m.Message != nil {
-		return *m.Message
-	}
-	return ""
-}
-
-func (m *Ping) GetButtonProtection() bool {
-	if m != nil && m.ButtonProtection != nil {
-		return *m.ButtonProtection
-	}
-	return false
-}
-
-func (m *Ping) GetPinProtection() bool {
-	if m != nil && m.PinProtection != nil {
-		return *m.PinProtection
-	}
-	return false
-}
-
-func (m *Ping) GetPassphraseProtection() bool {
-	if m != nil && m.PassphraseProtection != nil {
-		return *m.PassphraseProtection
-	}
-	return false
-}
-
-// *
-// Response: Success of the previous request
-type Success struct {
-	Message          *string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *Success) Reset()                    { *m = Success{} }
-func (m *Success) String() string            { return proto.CompactTextString(m) }
-func (*Success) ProtoMessage()               {}
-func (*Success) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{8} }
-
-func (m *Success) GetMessage() string {
-	if m != nil && m.Message != nil {
-		return *m.Message
-	}
-	return ""
-}
-
-// *
-// Response: Failure of the previous request
-type Failure struct {
-	Code             *FailureType `protobuf:"varint,1,opt,name=code,enum=FailureType" json:"code,omitempty"`
-	Message          *string      `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"`
-	XXX_unrecognized []byte       `json:"-"`
-}
-
-func (m *Failure) Reset()                    { *m = Failure{} }
-func (m *Failure) String() string            { return proto.CompactTextString(m) }
-func (*Failure) ProtoMessage()               {}
-func (*Failure) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{9} }
-
-func (m *Failure) GetCode() FailureType {
-	if m != nil && m.Code != nil {
-		return *m.Code
-	}
-	return FailureType_Failure_UnexpectedMessage
-}
-
-func (m *Failure) GetMessage() string {
-	if m != nil && m.Message != nil {
-		return *m.Message
-	}
-	return ""
-}
-
-// *
-// Response: Device is waiting for HW button press.
-// @next ButtonAck
-// @next Cancel
-type ButtonRequest struct {
-	Code             *ButtonRequestType `protobuf:"varint,1,opt,name=code,enum=ButtonRequestType" json:"code,omitempty"`
-	Data             *string            `protobuf:"bytes,2,opt,name=data" json:"data,omitempty"`
-	XXX_unrecognized []byte             `json:"-"`
-}
-
-func (m *ButtonRequest) Reset()                    { *m = ButtonRequest{} }
-func (m *ButtonRequest) String() string            { return proto.CompactTextString(m) }
-func (*ButtonRequest) ProtoMessage()               {}
-func (*ButtonRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{10} }
-
-func (m *ButtonRequest) GetCode() ButtonRequestType {
-	if m != nil && m.Code != nil {
-		return *m.Code
-	}
-	return ButtonRequestType_ButtonRequest_Other
-}
-
-func (m *ButtonRequest) GetData() string {
-	if m != nil && m.Data != nil {
-		return *m.Data
-	}
-	return ""
-}
-
-// *
-// Request: Computer agrees to wait for HW button press
-// @prev ButtonRequest
-type ButtonAck struct {
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *ButtonAck) Reset()                    { *m = ButtonAck{} }
-func (m *ButtonAck) String() string            { return proto.CompactTextString(m) }
-func (*ButtonAck) ProtoMessage()               {}
-func (*ButtonAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{11} }
-
-// *
-// Response: Device is asking computer to show PIN matrix and awaits PIN encoded using this matrix scheme
-// @next PinMatrixAck
-// @next Cancel
-type PinMatrixRequest struct {
-	Type             *PinMatrixRequestType `protobuf:"varint,1,opt,name=type,enum=PinMatrixRequestType" json:"type,omitempty"`
-	XXX_unrecognized []byte                `json:"-"`
-}
-
-func (m *PinMatrixRequest) Reset()                    { *m = PinMatrixRequest{} }
-func (m *PinMatrixRequest) String() string            { return proto.CompactTextString(m) }
-func (*PinMatrixRequest) ProtoMessage()               {}
-func (*PinMatrixRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{12} }
-
-func (m *PinMatrixRequest) GetType() PinMatrixRequestType {
-	if m != nil && m.Type != nil {
-		return *m.Type
-	}
-	return PinMatrixRequestType_PinMatrixRequestType_Current
-}
-
-// *
-// Request: Computer responds with encoded PIN
-// @prev PinMatrixRequest
-type PinMatrixAck struct {
-	Pin              *string `protobuf:"bytes,1,req,name=pin" json:"pin,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *PinMatrixAck) Reset()                    { *m = PinMatrixAck{} }
-func (m *PinMatrixAck) String() string            { return proto.CompactTextString(m) }
-func (*PinMatrixAck) ProtoMessage()               {}
-func (*PinMatrixAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{13} }
-
-func (m *PinMatrixAck) GetPin() string {
-	if m != nil && m.Pin != nil {
-		return *m.Pin
-	}
-	return ""
-}
-
-// *
-// Request: Abort last operation that required user interaction
-// @prev ButtonRequest
-// @prev PinMatrixRequest
-// @prev PassphraseRequest
-type Cancel struct {
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *Cancel) Reset()                    { *m = Cancel{} }
-func (m *Cancel) String() string            { return proto.CompactTextString(m) }
-func (*Cancel) ProtoMessage()               {}
-func (*Cancel) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{14} }
-
-// *
-// Response: Device awaits encryption passphrase
-// @next PassphraseAck
-// @next Cancel
-type PassphraseRequest struct {
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *PassphraseRequest) Reset()                    { *m = PassphraseRequest{} }
-func (m *PassphraseRequest) String() string            { return proto.CompactTextString(m) }
-func (*PassphraseRequest) ProtoMessage()               {}
-func (*PassphraseRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{15} }
-
-// *
-// Request: Send passphrase back
-// @prev PassphraseRequest
-type PassphraseAck struct {
-	Passphrase       *string `protobuf:"bytes,1,req,name=passphrase" json:"passphrase,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *PassphraseAck) Reset()                    { *m = PassphraseAck{} }
-func (m *PassphraseAck) String() string            { return proto.CompactTextString(m) }
-func (*PassphraseAck) ProtoMessage()               {}
-func (*PassphraseAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{16} }
-
-func (m *PassphraseAck) GetPassphrase() string {
-	if m != nil && m.Passphrase != nil {
-		return *m.Passphrase
-	}
-	return ""
-}
-
-// *
-// Request: Request a sample of random data generated by hardware RNG. May be used for testing.
-// @next ButtonRequest
-// @next Entropy
-// @next Failure
-type GetEntropy struct {
-	Size             *uint32 `protobuf:"varint,1,req,name=size" json:"size,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *GetEntropy) Reset()                    { *m = GetEntropy{} }
-func (m *GetEntropy) String() string            { return proto.CompactTextString(m) }
-func (*GetEntropy) ProtoMessage()               {}
-func (*GetEntropy) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{17} }
-
-func (m *GetEntropy) GetSize() uint32 {
-	if m != nil && m.Size != nil {
-		return *m.Size
-	}
-	return 0
-}
-
-// *
-// Response: Reply with random data generated by internal RNG
-// @prev GetEntropy
-type Entropy struct {
-	Entropy          []byte `protobuf:"bytes,1,req,name=entropy" json:"entropy,omitempty"`
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *Entropy) Reset()                    { *m = Entropy{} }
-func (m *Entropy) String() string            { return proto.CompactTextString(m) }
-func (*Entropy) ProtoMessage()               {}
-func (*Entropy) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{18} }
-
-func (m *Entropy) GetEntropy() []byte {
-	if m != nil {
-		return m.Entropy
-	}
-	return nil
-}
-
-// *
-// Request: Ask device for public key corresponding to address_n path
-// @next PassphraseRequest
-// @next PublicKey
-// @next Failure
-type GetPublicKey struct {
-	AddressN         []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
-	EcdsaCurveName   *string  `protobuf:"bytes,2,opt,name=ecdsa_curve_name,json=ecdsaCurveName" json:"ecdsa_curve_name,omitempty"`
-	ShowDisplay      *bool    `protobuf:"varint,3,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"`
-	CoinName         *string  `protobuf:"bytes,4,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"`
-	XXX_unrecognized []byte   `json:"-"`
-}
 
-func (m *GetPublicKey) Reset()                    { *m = GetPublicKey{} }
-func (m *GetPublicKey) String() string            { return proto.CompactTextString(m) }
-func (*GetPublicKey) ProtoMessage()               {}
-func (*GetPublicKey) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{19} }
-
-const Default_GetPublicKey_CoinName string = "Bitcoin"
-
-func (m *GetPublicKey) GetAddressN() []uint32 {
-	if m != nil {
-		return m.AddressN
-	}
-	return nil
+func (MessageType) EnumDescriptor() ([]byte, []int) {
+	return fileDescriptor_4dc296cbfe5ffcd5, []int{0}
 }
 
-func (m *GetPublicKey) GetEcdsaCurveName() string {
-	if m != nil && m.EcdsaCurveName != nil {
-		return *m.EcdsaCurveName
-	}
-	return ""
+var E_WireIn = &proto.ExtensionDesc{
+	ExtendedType:  (*descriptor.EnumValueOptions)(nil),
+	ExtensionType: (*bool)(nil),
+	Field:         50002,
+	Name:          "hw.trezor.messages.wire_in",
+	Tag:           "varint,50002,opt,name=wire_in",
+	Filename:      "messages.proto",
 }
 
-func (m *GetPublicKey) GetShowDisplay() bool {
-	if m != nil && m.ShowDisplay != nil {
-		return *m.ShowDisplay
-	}
-	return false
+var E_WireOut = &proto.ExtensionDesc{
+	ExtendedType:  (*descriptor.EnumValueOptions)(nil),
+	ExtensionType: (*bool)(nil),
+	Field:         50003,
+	Name:          "hw.trezor.messages.wire_out",
+	Tag:           "varint,50003,opt,name=wire_out",
+	Filename:      "messages.proto",
 }
 
-func (m *GetPublicKey) GetCoinName() string {
-	if m != nil && m.CoinName != nil {
-		return *m.CoinName
-	}
-	return Default_GetPublicKey_CoinName
+var E_WireDebugIn = &proto.ExtensionDesc{
+	ExtendedType:  (*descriptor.EnumValueOptions)(nil),
+	ExtensionType: (*bool)(nil),
+	Field:         50004,
+	Name:          "hw.trezor.messages.wire_debug_in",
+	Tag:           "varint,50004,opt,name=wire_debug_in",
+	Filename:      "messages.proto",
 }
 
-// *
-// Response: Contains public key derived from device private seed
-// @prev GetPublicKey
-type PublicKey struct {
-	Node             *HDNodeType `protobuf:"bytes,1,req,name=node" json:"node,omitempty"`
-	Xpub             *string     `protobuf:"bytes,2,opt,name=xpub" json:"xpub,omitempty"`
-	XXX_unrecognized []byte      `json:"-"`
+var E_WireDebugOut = &proto.ExtensionDesc{
+	ExtendedType:  (*descriptor.EnumValueOptions)(nil),
+	ExtensionType: (*bool)(nil),
+	Field:         50005,
+	Name:          "hw.trezor.messages.wire_debug_out",
+	Tag:           "varint,50005,opt,name=wire_debug_out",
+	Filename:      "messages.proto",
 }
 
-func (m *PublicKey) Reset()                    { *m = PublicKey{} }
-func (m *PublicKey) String() string            { return proto.CompactTextString(m) }
-func (*PublicKey) ProtoMessage()               {}
-func (*PublicKey) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{20} }
-
-func (m *PublicKey) GetNode() *HDNodeType {
-	if m != nil {
-		return m.Node
-	}
-	return nil
+var E_WireTiny = &proto.ExtensionDesc{
+	ExtendedType:  (*descriptor.EnumValueOptions)(nil),
+	ExtensionType: (*bool)(nil),
+	Field:         50006,
+	Name:          "hw.trezor.messages.wire_tiny",
+	Tag:           "varint,50006,opt,name=wire_tiny",
+	Filename:      "messages.proto",
 }
 
-func (m *PublicKey) GetXpub() string {
-	if m != nil && m.Xpub != nil {
-		return *m.Xpub
-	}
-	return ""
+var E_WireBootloader = &proto.ExtensionDesc{
+	ExtendedType:  (*descriptor.EnumValueOptions)(nil),
+	ExtensionType: (*bool)(nil),
+	Field:         50007,
+	Name:          "hw.trezor.messages.wire_bootloader",
+	Tag:           "varint,50007,opt,name=wire_bootloader",
+	Filename:      "messages.proto",
 }
 
-// *
-// Request: Ask device for address corresponding to address_n path
-// @next PassphraseRequest
-// @next Address
-// @next Failure
-type GetAddress struct {
-	AddressN         []uint32                  `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
-	CoinName         *string                   `protobuf:"bytes,2,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"`
-	ShowDisplay      *bool                     `protobuf:"varint,3,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"`
-	Multisig         *MultisigRedeemScriptType `protobuf:"bytes,4,opt,name=multisig" json:"multisig,omitempty"`
-	ScriptType       *InputScriptType          `protobuf:"varint,5,opt,name=script_type,json=scriptType,enum=InputScriptType,def=0" json:"script_type,omitempty"`
-	XXX_unrecognized []byte                    `json:"-"`
-}
-
-func (m *GetAddress) Reset()                    { *m = GetAddress{} }
-func (m *GetAddress) String() string            { return proto.CompactTextString(m) }
-func (*GetAddress) ProtoMessage()               {}
-func (*GetAddress) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{21} }
-
-const Default_GetAddress_CoinName string = "Bitcoin"
-const Default_GetAddress_ScriptType InputScriptType = InputScriptType_SPENDADDRESS
-
-func (m *GetAddress) GetAddressN() []uint32 {
-	if m != nil {
-		return m.AddressN
-	}
-	return nil
-}
-
-func (m *GetAddress) GetCoinName() string {
-	if m != nil && m.CoinName != nil {
-		return *m.CoinName
-	}
-	return Default_GetAddress_CoinName
-}
-
-func (m *GetAddress) GetShowDisplay() bool {
-	if m != nil && m.ShowDisplay != nil {
-		return *m.ShowDisplay
-	}
-	return false
-}
-
-func (m *GetAddress) GetMultisig() *MultisigRedeemScriptType {
-	if m != nil {
-		return m.Multisig
-	}
-	return nil
-}
-
-func (m *GetAddress) GetScriptType() InputScriptType {
-	if m != nil && m.ScriptType != nil {
-		return *m.ScriptType
-	}
-	return Default_GetAddress_ScriptType
-}
-
-// *
-// Request: Ask device for Ethereum address corresponding to address_n path
-// @next PassphraseRequest
-// @next EthereumAddress
-// @next Failure
-type EthereumGetAddress struct {
-	AddressN         []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
-	ShowDisplay      *bool    `protobuf:"varint,2,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"`
-	XXX_unrecognized []byte   `json:"-"`
-}
-
-func (m *EthereumGetAddress) Reset()                    { *m = EthereumGetAddress{} }
-func (m *EthereumGetAddress) String() string            { return proto.CompactTextString(m) }
-func (*EthereumGetAddress) ProtoMessage()               {}
-func (*EthereumGetAddress) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{22} }
-
-func (m *EthereumGetAddress) GetAddressN() []uint32 {
-	if m != nil {
-		return m.AddressN
-	}
-	return nil
-}
-
-func (m *EthereumGetAddress) GetShowDisplay() bool {
-	if m != nil && m.ShowDisplay != nil {
-		return *m.ShowDisplay
-	}
-	return false
-}
-
-// *
-// Response: Contains address derived from device private seed
-// @prev GetAddress
-type Address struct {
-	Address          *string `protobuf:"bytes,1,req,name=address" json:"address,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *Address) Reset()                    { *m = Address{} }
-func (m *Address) String() string            { return proto.CompactTextString(m) }
-func (*Address) ProtoMessage()               {}
-func (*Address) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{23} }
-
-func (m *Address) GetAddress() string {
-	if m != nil && m.Address != nil {
-		return *m.Address
-	}
-	return ""
-}
-
-// *
-// Response: Contains an Ethereum address derived from device private seed
-// @prev EthereumGetAddress
-type EthereumAddress struct {
-	Address          []byte `protobuf:"bytes,1,req,name=address" json:"address,omitempty"`
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *EthereumAddress) Reset()                    { *m = EthereumAddress{} }
-func (m *EthereumAddress) String() string            { return proto.CompactTextString(m) }
-func (*EthereumAddress) ProtoMessage()               {}
-func (*EthereumAddress) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{24} }
-
-func (m *EthereumAddress) GetAddress() []byte {
-	if m != nil {
-		return m.Address
-	}
-	return nil
-}
-
-// *
-// Request: Request device to wipe all sensitive data and settings
-// @next ButtonRequest
-type WipeDevice struct {
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *WipeDevice) Reset()                    { *m = WipeDevice{} }
-func (m *WipeDevice) String() string            { return proto.CompactTextString(m) }
-func (*WipeDevice) ProtoMessage()               {}
-func (*WipeDevice) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{25} }
-
-// *
-// Request: Load seed and related internal settings from the computer
-// @next ButtonRequest
-// @next Success
-// @next Failure
-type LoadDevice struct {
-	Mnemonic             *string     `protobuf:"bytes,1,opt,name=mnemonic" json:"mnemonic,omitempty"`
-	Node                 *HDNodeType `protobuf:"bytes,2,opt,name=node" json:"node,omitempty"`
-	Pin                  *string     `protobuf:"bytes,3,opt,name=pin" json:"pin,omitempty"`
-	PassphraseProtection *bool       `protobuf:"varint,4,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"`
-	Language             *string     `protobuf:"bytes,5,opt,name=language,def=english" json:"language,omitempty"`
-	Label                *string     `protobuf:"bytes,6,opt,name=label" json:"label,omitempty"`
-	SkipChecksum         *bool       `protobuf:"varint,7,opt,name=skip_checksum,json=skipChecksum" json:"skip_checksum,omitempty"`
-	U2FCounter           *uint32     `protobuf:"varint,8,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"`
-	XXX_unrecognized     []byte      `json:"-"`
-}
-
-func (m *LoadDevice) Reset()                    { *m = LoadDevice{} }
-func (m *LoadDevice) String() string            { return proto.CompactTextString(m) }
-func (*LoadDevice) ProtoMessage()               {}
-func (*LoadDevice) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{26} }
-
-const Default_LoadDevice_Language string = "english"
-
-func (m *LoadDevice) GetMnemonic() string {
-	if m != nil && m.Mnemonic != nil {
-		return *m.Mnemonic
-	}
-	return ""
-}
-
-func (m *LoadDevice) GetNode() *HDNodeType {
-	if m != nil {
-		return m.Node
-	}
-	return nil
-}
-
-func (m *LoadDevice) GetPin() string {
-	if m != nil && m.Pin != nil {
-		return *m.Pin
-	}
-	return ""
-}
-
-func (m *LoadDevice) GetPassphraseProtection() bool {
-	if m != nil && m.PassphraseProtection != nil {
-		return *m.PassphraseProtection
-	}
-	return false
-}
-
-func (m *LoadDevice) GetLanguage() string {
-	if m != nil && m.Language != nil {
-		return *m.Language
-	}
-	return Default_LoadDevice_Language
-}
-
-func (m *LoadDevice) GetLabel() string {
-	if m != nil && m.Label != nil {
-		return *m.Label
-	}
-	return ""
-}
-
-func (m *LoadDevice) GetSkipChecksum() bool {
-	if m != nil && m.SkipChecksum != nil {
-		return *m.SkipChecksum
-	}
-	return false
-}
-
-func (m *LoadDevice) GetU2FCounter() uint32 {
-	if m != nil && m.U2FCounter != nil {
-		return *m.U2FCounter
-	}
-	return 0
-}
-
-// *
-// Request: Ask device to do initialization involving user interaction
-// @next EntropyRequest
-// @next Failure
-type ResetDevice struct {
-	DisplayRandom        *bool   `protobuf:"varint,1,opt,name=display_random,json=displayRandom" json:"display_random,omitempty"`
-	Strength             *uint32 `protobuf:"varint,2,opt,name=strength,def=256" json:"strength,omitempty"`
-	PassphraseProtection *bool   `protobuf:"varint,3,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"`
-	PinProtection        *bool   `protobuf:"varint,4,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"`
-	Language             *string `protobuf:"bytes,5,opt,name=language,def=english" json:"language,omitempty"`
-	Label                *string `protobuf:"bytes,6,opt,name=label" json:"label,omitempty"`
-	U2FCounter           *uint32 `protobuf:"varint,7,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"`
-	SkipBackup           *bool   `protobuf:"varint,8,opt,name=skip_backup,json=skipBackup" json:"skip_backup,omitempty"`
-	XXX_unrecognized     []byte  `json:"-"`
-}
-
-func (m *ResetDevice) Reset()                    { *m = ResetDevice{} }
-func (m *ResetDevice) String() string            { return proto.CompactTextString(m) }
-func (*ResetDevice) ProtoMessage()               {}
-func (*ResetDevice) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{27} }
-
-const Default_ResetDevice_Strength uint32 = 256
-const Default_ResetDevice_Language string = "english"
-
-func (m *ResetDevice) GetDisplayRandom() bool {
-	if m != nil && m.DisplayRandom != nil {
-		return *m.DisplayRandom
-	}
-	return false
-}
-
-func (m *ResetDevice) GetStrength() uint32 {
-	if m != nil && m.Strength != nil {
-		return *m.Strength
-	}
-	return Default_ResetDevice_Strength
-}
-
-func (m *ResetDevice) GetPassphraseProtection() bool {
-	if m != nil && m.PassphraseProtection != nil {
-		return *m.PassphraseProtection
-	}
-	return false
-}
-
-func (m *ResetDevice) GetPinProtection() bool {
-	if m != nil && m.PinProtection != nil {
-		return *m.PinProtection
-	}
-	return false
-}
-
-func (m *ResetDevice) GetLanguage() string {
-	if m != nil && m.Language != nil {
-		return *m.Language
-	}
-	return Default_ResetDevice_Language
-}
-
-func (m *ResetDevice) GetLabel() string {
-	if m != nil && m.Label != nil {
-		return *m.Label
-	}
-	return ""
-}
-
-func (m *ResetDevice) GetU2FCounter() uint32 {
-	if m != nil && m.U2FCounter != nil {
-		return *m.U2FCounter
-	}
-	return 0
-}
-
-func (m *ResetDevice) GetSkipBackup() bool {
-	if m != nil && m.SkipBackup != nil {
-		return *m.SkipBackup
-	}
-	return false
-}
-
-// *
-// Request: Perform backup of the device seed if not backed up using ResetDevice
-// @next ButtonRequest
-type BackupDevice struct {
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *BackupDevice) Reset()                    { *m = BackupDevice{} }
-func (m *BackupDevice) String() string            { return proto.CompactTextString(m) }
-func (*BackupDevice) ProtoMessage()               {}
-func (*BackupDevice) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{28} }
-
-// *
-// Response: Ask for additional entropy from host computer
-// @prev ResetDevice
-// @next EntropyAck
-type EntropyRequest struct {
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *EntropyRequest) Reset()                    { *m = EntropyRequest{} }
-func (m *EntropyRequest) String() string            { return proto.CompactTextString(m) }
-func (*EntropyRequest) ProtoMessage()               {}
-func (*EntropyRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{29} }
-
-// *
-// Request: Provide additional entropy for seed generation function
-// @prev EntropyRequest
-// @next ButtonRequest
-type EntropyAck struct {
-	Entropy          []byte `protobuf:"bytes,1,opt,name=entropy" json:"entropy,omitempty"`
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *EntropyAck) Reset()                    { *m = EntropyAck{} }
-func (m *EntropyAck) String() string            { return proto.CompactTextString(m) }
-func (*EntropyAck) ProtoMessage()               {}
-func (*EntropyAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{30} }
-
-func (m *EntropyAck) GetEntropy() []byte {
-	if m != nil {
-		return m.Entropy
-	}
-	return nil
-}
-
-// *
-// Request: Start recovery workflow asking user for specific words of mnemonic
-// Used to recovery device safely even on untrusted computer.
-// @next WordRequest
-type RecoveryDevice struct {
-	WordCount            *uint32 `protobuf:"varint,1,opt,name=word_count,json=wordCount" json:"word_count,omitempty"`
-	PassphraseProtection *bool   `protobuf:"varint,2,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"`
-	PinProtection        *bool   `protobuf:"varint,3,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"`
-	Language             *string `protobuf:"bytes,4,opt,name=language,def=english" json:"language,omitempty"`
-	Label                *string `protobuf:"bytes,5,opt,name=label" json:"label,omitempty"`
-	EnforceWordlist      *bool   `protobuf:"varint,6,opt,name=enforce_wordlist,json=enforceWordlist" json:"enforce_wordlist,omitempty"`
-	// 7 reserved for unused recovery method
-	Type             *uint32 `protobuf:"varint,8,opt,name=type" json:"type,omitempty"`
-	U2FCounter       *uint32 `protobuf:"varint,9,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"`
-	DryRun           *bool   `protobuf:"varint,10,opt,name=dry_run,json=dryRun" json:"dry_run,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *RecoveryDevice) Reset()                    { *m = RecoveryDevice{} }
-func (m *RecoveryDevice) String() string            { return proto.CompactTextString(m) }
-func (*RecoveryDevice) ProtoMessage()               {}
-func (*RecoveryDevice) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{31} }
-
-const Default_RecoveryDevice_Language string = "english"
-
-func (m *RecoveryDevice) GetWordCount() uint32 {
-	if m != nil && m.WordCount != nil {
-		return *m.WordCount
-	}
-	return 0
-}
-
-func (m *RecoveryDevice) GetPassphraseProtection() bool {
-	if m != nil && m.PassphraseProtection != nil {
-		return *m.PassphraseProtection
-	}
-	return false
-}
-
-func (m *RecoveryDevice) GetPinProtection() bool {
-	if m != nil && m.PinProtection != nil {
-		return *m.PinProtection
-	}
-	return false
-}
-
-func (m *RecoveryDevice) GetLanguage() string {
-	if m != nil && m.Language != nil {
-		return *m.Language
-	}
-	return Default_RecoveryDevice_Language
-}
-
-func (m *RecoveryDevice) GetLabel() string {
-	if m != nil && m.Label != nil {
-		return *m.Label
-	}
-	return ""
-}
-
-func (m *RecoveryDevice) GetEnforceWordlist() bool {
-	if m != nil && m.EnforceWordlist != nil {
-		return *m.EnforceWordlist
-	}
-	return false
-}
-
-func (m *RecoveryDevice) GetType() uint32 {
-	if m != nil && m.Type != nil {
-		return *m.Type
-	}
-	return 0
-}
-
-func (m *RecoveryDevice) GetU2FCounter() uint32 {
-	if m != nil && m.U2FCounter != nil {
-		return *m.U2FCounter
-	}
-	return 0
-}
-
-func (m *RecoveryDevice) GetDryRun() bool {
-	if m != nil && m.DryRun != nil {
-		return *m.DryRun
-	}
-	return false
-}
-
-// *
-// Response: Device is waiting for user to enter word of the mnemonic
-// Its position is shown only on device's internal display.
-// @prev RecoveryDevice
-// @prev WordAck
-type WordRequest struct {
-	Type             *WordRequestType `protobuf:"varint,1,opt,name=type,enum=WordRequestType" json:"type,omitempty"`
-	XXX_unrecognized []byte           `json:"-"`
-}
-
-func (m *WordRequest) Reset()                    { *m = WordRequest{} }
-func (m *WordRequest) String() string            { return proto.CompactTextString(m) }
-func (*WordRequest) ProtoMessage()               {}
-func (*WordRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{32} }
-
-func (m *WordRequest) GetType() WordRequestType {
-	if m != nil && m.Type != nil {
-		return *m.Type
-	}
-	return WordRequestType_WordRequestType_Plain
-}
-
-// *
-// Request: Computer replies with word from the mnemonic
-// @prev WordRequest
-// @next WordRequest
-// @next Success
-// @next Failure
-type WordAck struct {
-	Word             *string `protobuf:"bytes,1,req,name=word" json:"word,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *WordAck) Reset()                    { *m = WordAck{} }
-func (m *WordAck) String() string            { return proto.CompactTextString(m) }
-func (*WordAck) ProtoMessage()               {}
-func (*WordAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{33} }
-
-func (m *WordAck) GetWord() string {
-	if m != nil && m.Word != nil {
-		return *m.Word
-	}
-	return ""
-}
-
-// *
-// Request: Ask device to sign message
-// @next MessageSignature
-// @next Failure
-type SignMessage struct {
-	AddressN         []uint32         `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
-	Message          []byte           `protobuf:"bytes,2,req,name=message" json:"message,omitempty"`
-	CoinName         *string          `protobuf:"bytes,3,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"`
-	ScriptType       *InputScriptType `protobuf:"varint,4,opt,name=script_type,json=scriptType,enum=InputScriptType,def=0" json:"script_type,omitempty"`
-	XXX_unrecognized []byte           `json:"-"`
-}
-
-func (m *SignMessage) Reset()                    { *m = SignMessage{} }
-func (m *SignMessage) String() string            { return proto.CompactTextString(m) }
-func (*SignMessage) ProtoMessage()               {}
-func (*SignMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{34} }
-
-const Default_SignMessage_CoinName string = "Bitcoin"
-const Default_SignMessage_ScriptType InputScriptType = InputScriptType_SPENDADDRESS
-
-func (m *SignMessage) GetAddressN() []uint32 {
-	if m != nil {
-		return m.AddressN
-	}
-	return nil
-}
-
-func (m *SignMessage) GetMessage() []byte {
-	if m != nil {
-		return m.Message
-	}
-	return nil
-}
-
-func (m *SignMessage) GetCoinName() string {
-	if m != nil && m.CoinName != nil {
-		return *m.CoinName
-	}
-	return Default_SignMessage_CoinName
-}
-
-func (m *SignMessage) GetScriptType() InputScriptType {
-	if m != nil && m.ScriptType != nil {
-		return *m.ScriptType
-	}
-	return Default_SignMessage_ScriptType
-}
-
-// *
-// Request: Ask device to verify message
-// @next Success
-// @next Failure
-type VerifyMessage struct {
-	Address          *string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"`
-	Signature        []byte  `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"`
-	Message          []byte  `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"`
-	CoinName         *string `protobuf:"bytes,4,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *VerifyMessage) Reset()                    { *m = VerifyMessage{} }
-func (m *VerifyMessage) String() string            { return proto.CompactTextString(m) }
-func (*VerifyMessage) ProtoMessage()               {}
-func (*VerifyMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{35} }
-
-const Default_VerifyMessage_CoinName string = "Bitcoin"
-
-func (m *VerifyMessage) GetAddress() string {
-	if m != nil && m.Address != nil {
-		return *m.Address
-	}
-	return ""
-}
-
-func (m *VerifyMessage) GetSignature() []byte {
-	if m != nil {
-		return m.Signature
-	}
-	return nil
-}
-
-func (m *VerifyMessage) GetMessage() []byte {
-	if m != nil {
-		return m.Message
-	}
-	return nil
-}
-
-func (m *VerifyMessage) GetCoinName() string {
-	if m != nil && m.CoinName != nil {
-		return *m.CoinName
-	}
-	return Default_VerifyMessage_CoinName
-}
-
-// *
-// Response: Signed message
-// @prev SignMessage
-type MessageSignature struct {
-	Address          *string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"`
-	Signature        []byte  `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *MessageSignature) Reset()                    { *m = MessageSignature{} }
-func (m *MessageSignature) String() string            { return proto.CompactTextString(m) }
-func (*MessageSignature) ProtoMessage()               {}
-func (*MessageSignature) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{36} }
-
-func (m *MessageSignature) GetAddress() string {
-	if m != nil && m.Address != nil {
-		return *m.Address
-	}
-	return ""
-}
-
-func (m *MessageSignature) GetSignature() []byte {
-	if m != nil {
-		return m.Signature
-	}
-	return nil
-}
-
-// *
-// Request: Ask device to encrypt message
-// @next EncryptedMessage
-// @next Failure
-type EncryptMessage struct {
-	Pubkey           []byte   `protobuf:"bytes,1,opt,name=pubkey" json:"pubkey,omitempty"`
-	Message          []byte   `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"`
-	DisplayOnly      *bool    `protobuf:"varint,3,opt,name=display_only,json=displayOnly" json:"display_only,omitempty"`
-	AddressN         []uint32 `protobuf:"varint,4,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
-	CoinName         *string  `protobuf:"bytes,5,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"`
-	XXX_unrecognized []byte   `json:"-"`
-}
-
-func (m *EncryptMessage) Reset()                    { *m = EncryptMessage{} }
-func (m *EncryptMessage) String() string            { return proto.CompactTextString(m) }
-func (*EncryptMessage) ProtoMessage()               {}
-func (*EncryptMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{37} }
-
-const Default_EncryptMessage_CoinName string = "Bitcoin"
-
-func (m *EncryptMessage) GetPubkey() []byte {
-	if m != nil {
-		return m.Pubkey
-	}
-	return nil
-}
-
-func (m *EncryptMessage) GetMessage() []byte {
-	if m != nil {
-		return m.Message
-	}
-	return nil
-}
-
-func (m *EncryptMessage) GetDisplayOnly() bool {
-	if m != nil && m.DisplayOnly != nil {
-		return *m.DisplayOnly
-	}
-	return false
-}
-
-func (m *EncryptMessage) GetAddressN() []uint32 {
-	if m != nil {
-		return m.AddressN
-	}
-	return nil
-}
-
-func (m *EncryptMessage) GetCoinName() string {
-	if m != nil && m.CoinName != nil {
-		return *m.CoinName
-	}
-	return Default_EncryptMessage_CoinName
-}
-
-// *
-// Response: Encrypted message
-// @prev EncryptMessage
-type EncryptedMessage struct {
-	Nonce            []byte `protobuf:"bytes,1,opt,name=nonce" json:"nonce,omitempty"`
-	Message          []byte `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"`
-	Hmac             []byte `protobuf:"bytes,3,opt,name=hmac" json:"hmac,omitempty"`
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *EncryptedMessage) Reset()                    { *m = EncryptedMessage{} }
-func (m *EncryptedMessage) String() string            { return proto.CompactTextString(m) }
-func (*EncryptedMessage) ProtoMessage()               {}
-func (*EncryptedMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{38} }
-
-func (m *EncryptedMessage) GetNonce() []byte {
-	if m != nil {
-		return m.Nonce
-	}
-	return nil
-}
-
-func (m *EncryptedMessage) GetMessage() []byte {
-	if m != nil {
-		return m.Message
-	}
-	return nil
-}
-
-func (m *EncryptedMessage) GetHmac() []byte {
-	if m != nil {
-		return m.Hmac
-	}
-	return nil
-}
-
-// *
-// Request: Ask device to decrypt message
-// @next Success
-// @next Failure
-type DecryptMessage struct {
-	AddressN         []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
-	Nonce            []byte   `protobuf:"bytes,2,opt,name=nonce" json:"nonce,omitempty"`
-	Message          []byte   `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"`
-	Hmac             []byte   `protobuf:"bytes,4,opt,name=hmac" json:"hmac,omitempty"`
-	XXX_unrecognized []byte   `json:"-"`
-}
-
-func (m *DecryptMessage) Reset()                    { *m = DecryptMessage{} }
-func (m *DecryptMessage) String() string            { return proto.CompactTextString(m) }
-func (*DecryptMessage) ProtoMessage()               {}
-func (*DecryptMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{39} }
-
-func (m *DecryptMessage) GetAddressN() []uint32 {
-	if m != nil {
-		return m.AddressN
-	}
-	return nil
-}
-
-func (m *DecryptMessage) GetNonce() []byte {
-	if m != nil {
-		return m.Nonce
-	}
-	return nil
-}
-
-func (m *DecryptMessage) GetMessage() []byte {
-	if m != nil {
-		return m.Message
-	}
-	return nil
-}
-
-func (m *DecryptMessage) GetHmac() []byte {
-	if m != nil {
-		return m.Hmac
-	}
-	return nil
-}
-
-// *
-// Response: Decrypted message
-// @prev DecryptedMessage
-type DecryptedMessage struct {
-	Message          []byte  `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"`
-	Address          *string `protobuf:"bytes,2,opt,name=address" json:"address,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *DecryptedMessage) Reset()                    { *m = DecryptedMessage{} }
-func (m *DecryptedMessage) String() string            { return proto.CompactTextString(m) }
-func (*DecryptedMessage) ProtoMessage()               {}
-func (*DecryptedMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{40} }
-
-func (m *DecryptedMessage) GetMessage() []byte {
-	if m != nil {
-		return m.Message
-	}
-	return nil
-}
-
-func (m *DecryptedMessage) GetAddress() string {
-	if m != nil && m.Address != nil {
-		return *m.Address
-	}
-	return ""
-}
-
-// *
-// Request: Ask device to encrypt or decrypt value of given key
-// @next CipheredKeyValue
-// @next Failure
-type CipherKeyValue struct {
-	AddressN         []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
-	Key              *string  `protobuf:"bytes,2,opt,name=key" json:"key,omitempty"`
-	Value            []byte   `protobuf:"bytes,3,opt,name=value" json:"value,omitempty"`
-	Encrypt          *bool    `protobuf:"varint,4,opt,name=encrypt" json:"encrypt,omitempty"`
-	AskOnEncrypt     *bool    `protobuf:"varint,5,opt,name=ask_on_encrypt,json=askOnEncrypt" json:"ask_on_encrypt,omitempty"`
-	AskOnDecrypt     *bool    `protobuf:"varint,6,opt,name=ask_on_decrypt,json=askOnDecrypt" json:"ask_on_decrypt,omitempty"`
-	Iv               []byte   `protobuf:"bytes,7,opt,name=iv" json:"iv,omitempty"`
-	XXX_unrecognized []byte   `json:"-"`
-}
-
-func (m *CipherKeyValue) Reset()                    { *m = CipherKeyValue{} }
-func (m *CipherKeyValue) String() string            { return proto.CompactTextString(m) }
-func (*CipherKeyValue) ProtoMessage()               {}
-func (*CipherKeyValue) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{41} }
-
-func (m *CipherKeyValue) GetAddressN() []uint32 {
-	if m != nil {
-		return m.AddressN
-	}
-	return nil
-}
-
-func (m *CipherKeyValue) GetKey() string {
-	if m != nil && m.Key != nil {
-		return *m.Key
-	}
-	return ""
-}
-
-func (m *CipherKeyValue) GetValue() []byte {
-	if m != nil {
-		return m.Value
-	}
-	return nil
-}
-
-func (m *CipherKeyValue) GetEncrypt() bool {
-	if m != nil && m.Encrypt != nil {
-		return *m.Encrypt
-	}
-	return false
-}
-
-func (m *CipherKeyValue) GetAskOnEncrypt() bool {
-	if m != nil && m.AskOnEncrypt != nil {
-		return *m.AskOnEncrypt
-	}
-	return false
-}
-
-func (m *CipherKeyValue) GetAskOnDecrypt() bool {
-	if m != nil && m.AskOnDecrypt != nil {
-		return *m.AskOnDecrypt
-	}
-	return false
-}
-
-func (m *CipherKeyValue) GetIv() []byte {
-	if m != nil {
-		return m.Iv
-	}
-	return nil
-}
-
-// *
-// Response: Return ciphered/deciphered value
-// @prev CipherKeyValue
-type CipheredKeyValue struct {
-	Value            []byte `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"`
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *CipheredKeyValue) Reset()                    { *m = CipheredKeyValue{} }
-func (m *CipheredKeyValue) String() string            { return proto.CompactTextString(m) }
-func (*CipheredKeyValue) ProtoMessage()               {}
-func (*CipheredKeyValue) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{42} }
-
-func (m *CipheredKeyValue) GetValue() []byte {
-	if m != nil {
-		return m.Value
-	}
-	return nil
-}
-
-// *
-// Request: Estimated size of the transaction
-// This behaves exactly like SignTx, which means that it can ask using TxRequest
-// This call is non-blocking (except possible PassphraseRequest to unlock the seed)
-// @next TxSize
-// @next Failure
-type EstimateTxSize struct {
-	OutputsCount     *uint32 `protobuf:"varint,1,req,name=outputs_count,json=outputsCount" json:"outputs_count,omitempty"`
-	InputsCount      *uint32 `protobuf:"varint,2,req,name=inputs_count,json=inputsCount" json:"inputs_count,omitempty"`
-	CoinName         *string `protobuf:"bytes,3,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *EstimateTxSize) Reset()                    { *m = EstimateTxSize{} }
-func (m *EstimateTxSize) String() string            { return proto.CompactTextString(m) }
-func (*EstimateTxSize) ProtoMessage()               {}
-func (*EstimateTxSize) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{43} }
-
-const Default_EstimateTxSize_CoinName string = "Bitcoin"
-
-func (m *EstimateTxSize) GetOutputsCount() uint32 {
-	if m != nil && m.OutputsCount != nil {
-		return *m.OutputsCount
-	}
-	return 0
-}
-
-func (m *EstimateTxSize) GetInputsCount() uint32 {
-	if m != nil && m.InputsCount != nil {
-		return *m.InputsCount
-	}
-	return 0
-}
-
-func (m *EstimateTxSize) GetCoinName() string {
-	if m != nil && m.CoinName != nil {
-		return *m.CoinName
-	}
-	return Default_EstimateTxSize_CoinName
-}
-
-// *
-// Response: Estimated size of the transaction
-// @prev EstimateTxSize
-type TxSize struct {
-	TxSize           *uint32 `protobuf:"varint,1,opt,name=tx_size,json=txSize" json:"tx_size,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *TxSize) Reset()                    { *m = TxSize{} }
-func (m *TxSize) String() string            { return proto.CompactTextString(m) }
-func (*TxSize) ProtoMessage()               {}
-func (*TxSize) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{44} }
-
-func (m *TxSize) GetTxSize() uint32 {
-	if m != nil && m.TxSize != nil {
-		return *m.TxSize
-	}
-	return 0
-}
-
-// *
-// Request: Ask device to sign transaction
-// @next PassphraseRequest
-// @next PinMatrixRequest
-// @next TxRequest
-// @next Failure
-type SignTx struct {
-	OutputsCount     *uint32 `protobuf:"varint,1,req,name=outputs_count,json=outputsCount" json:"outputs_count,omitempty"`
-	InputsCount      *uint32 `protobuf:"varint,2,req,name=inputs_count,json=inputsCount" json:"inputs_count,omitempty"`
-	CoinName         *string `protobuf:"bytes,3,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"`
-	Version          *uint32 `protobuf:"varint,4,opt,name=version,def=1" json:"version,omitempty"`
-	LockTime         *uint32 `protobuf:"varint,5,opt,name=lock_time,json=lockTime,def=0" json:"lock_time,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *SignTx) Reset()                    { *m = SignTx{} }
-func (m *SignTx) String() string            { return proto.CompactTextString(m) }
-func (*SignTx) ProtoMessage()               {}
-func (*SignTx) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{45} }
-
-const Default_SignTx_CoinName string = "Bitcoin"
-const Default_SignTx_Version uint32 = 1
-const Default_SignTx_LockTime uint32 = 0
-
-func (m *SignTx) GetOutputsCount() uint32 {
-	if m != nil && m.OutputsCount != nil {
-		return *m.OutputsCount
-	}
-	return 0
-}
-
-func (m *SignTx) GetInputsCount() uint32 {
-	if m != nil && m.InputsCount != nil {
-		return *m.InputsCount
-	}
-	return 0
-}
-
-func (m *SignTx) GetCoinName() string {
-	if m != nil && m.CoinName != nil {
-		return *m.CoinName
-	}
-	return Default_SignTx_CoinName
-}
-
-func (m *SignTx) GetVersion() uint32 {
-	if m != nil && m.Version != nil {
-		return *m.Version
-	}
-	return Default_SignTx_Version
-}
-
-func (m *SignTx) GetLockTime() uint32 {
-	if m != nil && m.LockTime != nil {
-		return *m.LockTime
-	}
-	return Default_SignTx_LockTime
-}
-
-// *
-// Request: Simplified transaction signing
-// This method doesn't support streaming, so there are hardware limits in number of inputs and outputs.
-// In case of success, the result is returned using TxRequest message.
-// @next PassphraseRequest
-// @next PinMatrixRequest
-// @next TxRequest
-// @next Failure
-type SimpleSignTx struct {
-	Inputs           []*TxInputType     `protobuf:"bytes,1,rep,name=inputs" json:"inputs,omitempty"`
-	Outputs          []*TxOutputType    `protobuf:"bytes,2,rep,name=outputs" json:"outputs,omitempty"`
-	Transactions     []*TransactionType `protobuf:"bytes,3,rep,name=transactions" json:"transactions,omitempty"`
-	CoinName         *string            `protobuf:"bytes,4,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"`
-	Version          *uint32            `protobuf:"varint,5,opt,name=version,def=1" json:"version,omitempty"`
-	LockTime         *uint32            `protobuf:"varint,6,opt,name=lock_time,json=lockTime,def=0" json:"lock_time,omitempty"`
-	XXX_unrecognized []byte             `json:"-"`
-}
-
-func (m *SimpleSignTx) Reset()                    { *m = SimpleSignTx{} }
-func (m *SimpleSignTx) String() string            { return proto.CompactTextString(m) }
-func (*SimpleSignTx) ProtoMessage()               {}
-func (*SimpleSignTx) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{46} }
-
-const Default_SimpleSignTx_CoinName string = "Bitcoin"
-const Default_SimpleSignTx_Version uint32 = 1
-const Default_SimpleSignTx_LockTime uint32 = 0
-
-func (m *SimpleSignTx) GetInputs() []*TxInputType {
-	if m != nil {
-		return m.Inputs
-	}
-	return nil
-}
-
-func (m *SimpleSignTx) GetOutputs() []*TxOutputType {
-	if m != nil {
-		return m.Outputs
-	}
-	return nil
-}
-
-func (m *SimpleSignTx) GetTransactions() []*TransactionType {
-	if m != nil {
-		return m.Transactions
-	}
-	return nil
-}
-
-func (m *SimpleSignTx) GetCoinName() string {
-	if m != nil && m.CoinName != nil {
-		return *m.CoinName
-	}
-	return Default_SimpleSignTx_CoinName
-}
-
-func (m *SimpleSignTx) GetVersion() uint32 {
-	if m != nil && m.Version != nil {
-		return *m.Version
-	}
-	return Default_SimpleSignTx_Version
-}
-
-func (m *SimpleSignTx) GetLockTime() uint32 {
-	if m != nil && m.LockTime != nil {
-		return *m.LockTime
-	}
-	return Default_SimpleSignTx_LockTime
-}
-
-// *
-// Response: Device asks for information for signing transaction or returns the last result
-// If request_index is set, device awaits TxAck message (with fields filled in according to request_type)
-// If signature_index is set, 'signature' contains signed input of signature_index's input
-// @prev SignTx
-// @prev SimpleSignTx
-// @prev TxAck
-type TxRequest struct {
-	RequestType      *RequestType             `protobuf:"varint,1,opt,name=request_type,json=requestType,enum=RequestType" json:"request_type,omitempty"`
-	Details          *TxRequestDetailsType    `protobuf:"bytes,2,opt,name=details" json:"details,omitempty"`
-	Serialized       *TxRequestSerializedType `protobuf:"bytes,3,opt,name=serialized" json:"serialized,omitempty"`
-	XXX_unrecognized []byte                   `json:"-"`
-}
-
-func (m *TxRequest) Reset()                    { *m = TxRequest{} }
-func (m *TxRequest) String() string            { return proto.CompactTextString(m) }
-func (*TxRequest) ProtoMessage()               {}
-func (*TxRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{47} }
-
-func (m *TxRequest) GetRequestType() RequestType {
-	if m != nil && m.RequestType != nil {
-		return *m.RequestType
-	}
-	return RequestType_TXINPUT
-}
-
-func (m *TxRequest) GetDetails() *TxRequestDetailsType {
-	if m != nil {
-		return m.Details
-	}
-	return nil
-}
-
-func (m *TxRequest) GetSerialized() *TxRequestSerializedType {
-	if m != nil {
-		return m.Serialized
-	}
-	return nil
-}
-
-// *
-// Request: Reported transaction data
-// @prev TxRequest
-// @next TxRequest
-type TxAck struct {
-	Tx               *TransactionType `protobuf:"bytes,1,opt,name=tx" json:"tx,omitempty"`
-	XXX_unrecognized []byte           `json:"-"`
-}
-
-func (m *TxAck) Reset()                    { *m = TxAck{} }
-func (m *TxAck) String() string            { return proto.CompactTextString(m) }
-func (*TxAck) ProtoMessage()               {}
-func (*TxAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{48} }
-
-func (m *TxAck) GetTx() *TransactionType {
-	if m != nil {
-		return m.Tx
-	}
-	return nil
-}
-
-// *
-// Request: Ask device to sign transaction
-// All fields are optional from the protocol's point of view. Each field defaults to value `0` if missing.
-// Note: the first at most 1024 bytes of data MUST be transmitted as part of this message.
-// @next PassphraseRequest
-// @next PinMatrixRequest
-// @next EthereumTxRequest
-// @next Failure
-type EthereumSignTx struct {
-	AddressN         []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
-	Nonce            []byte   `protobuf:"bytes,2,opt,name=nonce" json:"nonce,omitempty"`
-	GasPrice         []byte   `protobuf:"bytes,3,opt,name=gas_price,json=gasPrice" json:"gas_price,omitempty"`
-	GasLimit         []byte   `protobuf:"bytes,4,opt,name=gas_limit,json=gasLimit" json:"gas_limit,omitempty"`
-	To               []byte   `protobuf:"bytes,5,opt,name=to" json:"to,omitempty"`
-	Value            []byte   `protobuf:"bytes,6,opt,name=value" json:"value,omitempty"`
-	DataInitialChunk []byte   `protobuf:"bytes,7,opt,name=data_initial_chunk,json=dataInitialChunk" json:"data_initial_chunk,omitempty"`
-	DataLength       *uint32  `protobuf:"varint,8,opt,name=data_length,json=dataLength" json:"data_length,omitempty"`
-	ChainId          *uint32  `protobuf:"varint,9,opt,name=chain_id,json=chainId" json:"chain_id,omitempty"`
-	XXX_unrecognized []byte   `json:"-"`
-}
-
-func (m *EthereumSignTx) Reset()                    { *m = EthereumSignTx{} }
-func (m *EthereumSignTx) String() string            { return proto.CompactTextString(m) }
-func (*EthereumSignTx) ProtoMessage()               {}
-func (*EthereumSignTx) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{49} }
-
-func (m *EthereumSignTx) GetAddressN() []uint32 {
-	if m != nil {
-		return m.AddressN
-	}
-	return nil
-}
-
-func (m *EthereumSignTx) GetNonce() []byte {
-	if m != nil {
-		return m.Nonce
-	}
-	return nil
-}
-
-func (m *EthereumSignTx) GetGasPrice() []byte {
-	if m != nil {
-		return m.GasPrice
-	}
-	return nil
-}
-
-func (m *EthereumSignTx) GetGasLimit() []byte {
-	if m != nil {
-		return m.GasLimit
-	}
-	return nil
-}
-
-func (m *EthereumSignTx) GetTo() []byte {
-	if m != nil {
-		return m.To
-	}
-	return nil
-}
-
-func (m *EthereumSignTx) GetValue() []byte {
-	if m != nil {
-		return m.Value
-	}
-	return nil
-}
-
-func (m *EthereumSignTx) GetDataInitialChunk() []byte {
-	if m != nil {
-		return m.DataInitialChunk
-	}
-	return nil
-}
-
-func (m *EthereumSignTx) GetDataLength() uint32 {
-	if m != nil && m.DataLength != nil {
-		return *m.DataLength
-	}
-	return 0
-}
-
-func (m *EthereumSignTx) GetChainId() uint32 {
-	if m != nil && m.ChainId != nil {
-		return *m.ChainId
-	}
-	return 0
-}
-
-// *
-// Response: Device asks for more data from transaction payload, or returns the signature.
-// If data_length is set, device awaits that many more bytes of payload.
-// Otherwise, the signature_* fields contain the computed transaction signature. All three fields will be present.
-// @prev EthereumSignTx
-// @next EthereumTxAck
-type EthereumTxRequest struct {
-	DataLength       *uint32 `protobuf:"varint,1,opt,name=data_length,json=dataLength" json:"data_length,omitempty"`
-	SignatureV       *uint32 `protobuf:"varint,2,opt,name=signature_v,json=signatureV" json:"signature_v,omitempty"`
-	SignatureR       []byte  `protobuf:"bytes,3,opt,name=signature_r,json=signatureR" json:"signature_r,omitempty"`
-	SignatureS       []byte  `protobuf:"bytes,4,opt,name=signature_s,json=signatureS" json:"signature_s,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *EthereumTxRequest) Reset()                    { *m = EthereumTxRequest{} }
-func (m *EthereumTxRequest) String() string            { return proto.CompactTextString(m) }
-func (*EthereumTxRequest) ProtoMessage()               {}
-func (*EthereumTxRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{50} }
-
-func (m *EthereumTxRequest) GetDataLength() uint32 {
-	if m != nil && m.DataLength != nil {
-		return *m.DataLength
-	}
-	return 0
-}
-
-func (m *EthereumTxRequest) GetSignatureV() uint32 {
-	if m != nil && m.SignatureV != nil {
-		return *m.SignatureV
-	}
-	return 0
-}
-
-func (m *EthereumTxRequest) GetSignatureR() []byte {
-	if m != nil {
-		return m.SignatureR
-	}
-	return nil
-}
-
-func (m *EthereumTxRequest) GetSignatureS() []byte {
-	if m != nil {
-		return m.SignatureS
-	}
-	return nil
-}
-
-// *
-// Request: Transaction payload data.
-// @prev EthereumTxRequest
-// @next EthereumTxRequest
-type EthereumTxAck struct {
-	DataChunk        []byte `protobuf:"bytes,1,opt,name=data_chunk,json=dataChunk" json:"data_chunk,omitempty"`
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *EthereumTxAck) Reset()                    { *m = EthereumTxAck{} }
-func (m *EthereumTxAck) String() string            { return proto.CompactTextString(m) }
-func (*EthereumTxAck) ProtoMessage()               {}
-func (*EthereumTxAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{51} }
-
-func (m *EthereumTxAck) GetDataChunk() []byte {
-	if m != nil {
-		return m.DataChunk
-	}
-	return nil
-}
-
-// *
-// Request: Ask device to sign message
-// @next EthereumMessageSignature
-// @next Failure
-type EthereumSignMessage struct {
-	AddressN         []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
-	Message          []byte   `protobuf:"bytes,2,req,name=message" json:"message,omitempty"`
-	XXX_unrecognized []byte   `json:"-"`
-}
-
-func (m *EthereumSignMessage) Reset()                    { *m = EthereumSignMessage{} }
-func (m *EthereumSignMessage) String() string            { return proto.CompactTextString(m) }
-func (*EthereumSignMessage) ProtoMessage()               {}
-func (*EthereumSignMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{52} }
-
-func (m *EthereumSignMessage) GetAddressN() []uint32 {
-	if m != nil {
-		return m.AddressN
-	}
-	return nil
-}
-
-func (m *EthereumSignMessage) GetMessage() []byte {
-	if m != nil {
-		return m.Message
-	}
-	return nil
-}
-
-// *
-// Request: Ask device to verify message
-// @next Success
-// @next Failure
-type EthereumVerifyMessage struct {
-	Address          []byte `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"`
-	Signature        []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"`
-	Message          []byte `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"`
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *EthereumVerifyMessage) Reset()                    { *m = EthereumVerifyMessage{} }
-func (m *EthereumVerifyMessage) String() string            { return proto.CompactTextString(m) }
-func (*EthereumVerifyMessage) ProtoMessage()               {}
-func (*EthereumVerifyMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{53} }
-
-func (m *EthereumVerifyMessage) GetAddress() []byte {
-	if m != nil {
-		return m.Address
-	}
-	return nil
-}
-
-func (m *EthereumVerifyMessage) GetSignature() []byte {
-	if m != nil {
-		return m.Signature
-	}
-	return nil
-}
-
-func (m *EthereumVerifyMessage) GetMessage() []byte {
-	if m != nil {
-		return m.Message
-	}
-	return nil
-}
-
-// *
-// Response: Signed message
-// @prev EthereumSignMessage
-type EthereumMessageSignature struct {
-	Address          []byte `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"`
-	Signature        []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"`
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *EthereumMessageSignature) Reset()                    { *m = EthereumMessageSignature{} }
-func (m *EthereumMessageSignature) String() string            { return proto.CompactTextString(m) }
-func (*EthereumMessageSignature) ProtoMessage()               {}
-func (*EthereumMessageSignature) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{54} }
-
-func (m *EthereumMessageSignature) GetAddress() []byte {
-	if m != nil {
-		return m.Address
-	}
-	return nil
-}
-
-func (m *EthereumMessageSignature) GetSignature() []byte {
-	if m != nil {
-		return m.Signature
-	}
-	return nil
-}
-
-// *
-// Request: Ask device to sign identity
-// @next SignedIdentity
-// @next Failure
-type SignIdentity struct {
-	Identity         *IdentityType `protobuf:"bytes,1,opt,name=identity" json:"identity,omitempty"`
-	ChallengeHidden  []byte        `protobuf:"bytes,2,opt,name=challenge_hidden,json=challengeHidden" json:"challenge_hidden,omitempty"`
-	ChallengeVisual  *string       `protobuf:"bytes,3,opt,name=challenge_visual,json=challengeVisual" json:"challenge_visual,omitempty"`
-	EcdsaCurveName   *string       `protobuf:"bytes,4,opt,name=ecdsa_curve_name,json=ecdsaCurveName" json:"ecdsa_curve_name,omitempty"`
-	XXX_unrecognized []byte        `json:"-"`
-}
-
-func (m *SignIdentity) Reset()                    { *m = SignIdentity{} }
-func (m *SignIdentity) String() string            { return proto.CompactTextString(m) }
-func (*SignIdentity) ProtoMessage()               {}
-func (*SignIdentity) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{55} }
-
-func (m *SignIdentity) GetIdentity() *IdentityType {
-	if m != nil {
-		return m.Identity
-	}
-	return nil
-}
-
-func (m *SignIdentity) GetChallengeHidden() []byte {
-	if m != nil {
-		return m.ChallengeHidden
-	}
-	return nil
-}
-
-func (m *SignIdentity) GetChallengeVisual() string {
-	if m != nil && m.ChallengeVisual != nil {
-		return *m.ChallengeVisual
-	}
-	return ""
-}
-
-func (m *SignIdentity) GetEcdsaCurveName() string {
-	if m != nil && m.EcdsaCurveName != nil {
-		return *m.EcdsaCurveName
-	}
-	return ""
-}
-
-// *
-// Response: Device provides signed identity
-// @prev SignIdentity
-type SignedIdentity struct {
-	Address          *string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"`
-	PublicKey        []byte  `protobuf:"bytes,2,opt,name=public_key,json=publicKey" json:"public_key,omitempty"`
-	Signature        []byte  `protobuf:"bytes,3,opt,name=signature" json:"signature,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *SignedIdentity) Reset()                    { *m = SignedIdentity{} }
-func (m *SignedIdentity) String() string            { return proto.CompactTextString(m) }
-func (*SignedIdentity) ProtoMessage()               {}
-func (*SignedIdentity) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{56} }
-
-func (m *SignedIdentity) GetAddress() string {
-	if m != nil && m.Address != nil {
-		return *m.Address
-	}
-	return ""
-}
-
-func (m *SignedIdentity) GetPublicKey() []byte {
-	if m != nil {
-		return m.PublicKey
-	}
-	return nil
-}
-
-func (m *SignedIdentity) GetSignature() []byte {
-	if m != nil {
-		return m.Signature
-	}
-	return nil
-}
-
-// *
-// Request: Ask device to generate ECDH session key
-// @next ECDHSessionKey
-// @next Failure
-type GetECDHSessionKey struct {
-	Identity         *IdentityType `protobuf:"bytes,1,opt,name=identity" json:"identity,omitempty"`
-	PeerPublicKey    []byte        `protobuf:"bytes,2,opt,name=peer_public_key,json=peerPublicKey" json:"peer_public_key,omitempty"`
-	EcdsaCurveName   *string       `protobuf:"bytes,3,opt,name=ecdsa_curve_name,json=ecdsaCurveName" json:"ecdsa_curve_name,omitempty"`
-	XXX_unrecognized []byte        `json:"-"`
-}
-
-func (m *GetECDHSessionKey) Reset()                    { *m = GetECDHSessionKey{} }
-func (m *GetECDHSessionKey) String() string            { return proto.CompactTextString(m) }
-func (*GetECDHSessionKey) ProtoMessage()               {}
-func (*GetECDHSessionKey) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{57} }
-
-func (m *GetECDHSessionKey) GetIdentity() *IdentityType {
-	if m != nil {
-		return m.Identity
-	}
-	return nil
-}
-
-func (m *GetECDHSessionKey) GetPeerPublicKey() []byte {
-	if m != nil {
-		return m.PeerPublicKey
-	}
-	return nil
-}
-
-func (m *GetECDHSessionKey) GetEcdsaCurveName() string {
-	if m != nil && m.EcdsaCurveName != nil {
-		return *m.EcdsaCurveName
-	}
-	return ""
-}
-
-// *
-// Response: Device provides ECDH session key
-// @prev GetECDHSessionKey
-type ECDHSessionKey struct {
-	SessionKey       []byte `protobuf:"bytes,1,opt,name=session_key,json=sessionKey" json:"session_key,omitempty"`
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *ECDHSessionKey) Reset()                    { *m = ECDHSessionKey{} }
-func (m *ECDHSessionKey) String() string            { return proto.CompactTextString(m) }
-func (*ECDHSessionKey) ProtoMessage()               {}
-func (*ECDHSessionKey) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{58} }
-
-func (m *ECDHSessionKey) GetSessionKey() []byte {
-	if m != nil {
-		return m.SessionKey
-	}
-	return nil
-}
-
-// *
-// Request: Set U2F counter
-// @next Success
-type SetU2FCounter struct {
-	U2FCounter       *uint32 `protobuf:"varint,1,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *SetU2FCounter) Reset()                    { *m = SetU2FCounter{} }
-func (m *SetU2FCounter) String() string            { return proto.CompactTextString(m) }
-func (*SetU2FCounter) ProtoMessage()               {}
-func (*SetU2FCounter) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{59} }
-
-func (m *SetU2FCounter) GetU2FCounter() uint32 {
-	if m != nil && m.U2FCounter != nil {
-		return *m.U2FCounter
-	}
-	return 0
-}
-
-// *
-// Request: Ask device to erase its firmware (so it can be replaced via FirmwareUpload)
-// @next Success
-// @next FirmwareRequest
-// @next Failure
-type FirmwareErase struct {
-	Length           *uint32 `protobuf:"varint,1,opt,name=length" json:"length,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *FirmwareErase) Reset()                    { *m = FirmwareErase{} }
-func (m *FirmwareErase) String() string            { return proto.CompactTextString(m) }
-func (*FirmwareErase) ProtoMessage()               {}
-func (*FirmwareErase) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{60} }
-
-func (m *FirmwareErase) GetLength() uint32 {
-	if m != nil && m.Length != nil {
-		return *m.Length
-	}
-	return 0
-}
-
-// *
-// Response: Ask for firmware chunk
-// @next FirmwareUpload
-type FirmwareRequest struct {
-	Offset           *uint32 `protobuf:"varint,1,opt,name=offset" json:"offset,omitempty"`
-	Length           *uint32 `protobuf:"varint,2,opt,name=length" json:"length,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *FirmwareRequest) Reset()                    { *m = FirmwareRequest{} }
-func (m *FirmwareRequest) String() string            { return proto.CompactTextString(m) }
-func (*FirmwareRequest) ProtoMessage()               {}
-func (*FirmwareRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{61} }
-
-func (m *FirmwareRequest) GetOffset() uint32 {
-	if m != nil && m.Offset != nil {
-		return *m.Offset
-	}
-	return 0
-}
-
-func (m *FirmwareRequest) GetLength() uint32 {
-	if m != nil && m.Length != nil {
-		return *m.Length
-	}
-	return 0
-}
-
-// *
-// Request: Send firmware in binary form to the device
-// @next Success
-// @next Failure
-type FirmwareUpload struct {
-	Payload          []byte `protobuf:"bytes,1,req,name=payload" json:"payload,omitempty"`
-	Hash             []byte `protobuf:"bytes,2,opt,name=hash" json:"hash,omitempty"`
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *FirmwareUpload) Reset()                    { *m = FirmwareUpload{} }
-func (m *FirmwareUpload) String() string            { return proto.CompactTextString(m) }
-func (*FirmwareUpload) ProtoMessage()               {}
-func (*FirmwareUpload) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{62} }
-
-func (m *FirmwareUpload) GetPayload() []byte {
-	if m != nil {
-		return m.Payload
-	}
-	return nil
-}
-
-func (m *FirmwareUpload) GetHash() []byte {
-	if m != nil {
-		return m.Hash
-	}
-	return nil
-}
-
-// *
-// Request: Perform a device self-test
-// @next Success
-// @next Failure
-type SelfTest struct {
-	Payload          []byte `protobuf:"bytes,1,opt,name=payload" json:"payload,omitempty"`
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *SelfTest) Reset()                    { *m = SelfTest{} }
-func (m *SelfTest) String() string            { return proto.CompactTextString(m) }
-func (*SelfTest) ProtoMessage()               {}
-func (*SelfTest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{63} }
-
-func (m *SelfTest) GetPayload() []byte {
-	if m != nil {
-		return m.Payload
-	}
-	return nil
-}
-
-// *
-// Request: "Press" the button on the device
-// @next Success
-type DebugLinkDecision struct {
-	YesNo            *bool  `protobuf:"varint,1,req,name=yes_no,json=yesNo" json:"yes_no,omitempty"`
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *DebugLinkDecision) Reset()                    { *m = DebugLinkDecision{} }
-func (m *DebugLinkDecision) String() string            { return proto.CompactTextString(m) }
-func (*DebugLinkDecision) ProtoMessage()               {}
-func (*DebugLinkDecision) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{64} }
-
-func (m *DebugLinkDecision) GetYesNo() bool {
-	if m != nil && m.YesNo != nil {
-		return *m.YesNo
-	}
-	return false
-}
-
-// *
-// Request: Computer asks for device state
-// @next DebugLinkState
-type DebugLinkGetState struct {
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *DebugLinkGetState) Reset()                    { *m = DebugLinkGetState{} }
-func (m *DebugLinkGetState) String() string            { return proto.CompactTextString(m) }
-func (*DebugLinkGetState) ProtoMessage()               {}
-func (*DebugLinkGetState) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{65} }
-
-// *
-// Response: Device current state
-// @prev DebugLinkGetState
-type DebugLinkState struct {
-	Layout               []byte      `protobuf:"bytes,1,opt,name=layout" json:"layout,omitempty"`
-	Pin                  *string     `protobuf:"bytes,2,opt,name=pin" json:"pin,omitempty"`
-	Matrix               *string     `protobuf:"bytes,3,opt,name=matrix" json:"matrix,omitempty"`
-	Mnemonic             *string     `protobuf:"bytes,4,opt,name=mnemonic" json:"mnemonic,omitempty"`
-	Node                 *HDNodeType `protobuf:"bytes,5,opt,name=node" json:"node,omitempty"`
-	PassphraseProtection *bool       `protobuf:"varint,6,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"`
-	ResetWord            *string     `protobuf:"bytes,7,opt,name=reset_word,json=resetWord" json:"reset_word,omitempty"`
-	ResetEntropy         []byte      `protobuf:"bytes,8,opt,name=reset_entropy,json=resetEntropy" json:"reset_entropy,omitempty"`
-	RecoveryFakeWord     *string     `protobuf:"bytes,9,opt,name=recovery_fake_word,json=recoveryFakeWord" json:"recovery_fake_word,omitempty"`
-	RecoveryWordPos      *uint32     `protobuf:"varint,10,opt,name=recovery_word_pos,json=recoveryWordPos" json:"recovery_word_pos,omitempty"`
-	XXX_unrecognized     []byte      `json:"-"`
-}
-
-func (m *DebugLinkState) Reset()                    { *m = DebugLinkState{} }
-func (m *DebugLinkState) String() string            { return proto.CompactTextString(m) }
-func (*DebugLinkState) ProtoMessage()               {}
-func (*DebugLinkState) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{66} }
-
-func (m *DebugLinkState) GetLayout() []byte {
-	if m != nil {
-		return m.Layout
-	}
-	return nil
-}
-
-func (m *DebugLinkState) GetPin() string {
-	if m != nil && m.Pin != nil {
-		return *m.Pin
-	}
-	return ""
-}
-
-func (m *DebugLinkState) GetMatrix() string {
-	if m != nil && m.Matrix != nil {
-		return *m.Matrix
-	}
-	return ""
-}
-
-func (m *DebugLinkState) GetMnemonic() string {
-	if m != nil && m.Mnemonic != nil {
-		return *m.Mnemonic
-	}
-	return ""
-}
-
-func (m *DebugLinkState) GetNode() *HDNodeType {
-	if m != nil {
-		return m.Node
-	}
-	return nil
-}
-
-func (m *DebugLinkState) GetPassphraseProtection() bool {
-	if m != nil && m.PassphraseProtection != nil {
-		return *m.PassphraseProtection
-	}
-	return false
-}
-
-func (m *DebugLinkState) GetResetWord() string {
-	if m != nil && m.ResetWord != nil {
-		return *m.ResetWord
-	}
-	return ""
-}
-
-func (m *DebugLinkState) GetResetEntropy() []byte {
-	if m != nil {
-		return m.ResetEntropy
-	}
-	return nil
-}
-
-func (m *DebugLinkState) GetRecoveryFakeWord() string {
-	if m != nil && m.RecoveryFakeWord != nil {
-		return *m.RecoveryFakeWord
-	}
-	return ""
-}
-
-func (m *DebugLinkState) GetRecoveryWordPos() uint32 {
-	if m != nil && m.RecoveryWordPos != nil {
-		return *m.RecoveryWordPos
-	}
-	return 0
-}
-
-// *
-// Request: Ask device to restart
-type DebugLinkStop struct {
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *DebugLinkStop) Reset()                    { *m = DebugLinkStop{} }
-func (m *DebugLinkStop) String() string            { return proto.CompactTextString(m) }
-func (*DebugLinkStop) ProtoMessage()               {}
-func (*DebugLinkStop) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{67} }
-
-// *
-// Response: Device wants host to log event
-type DebugLinkLog struct {
-	Level            *uint32 `protobuf:"varint,1,opt,name=level" json:"level,omitempty"`
-	Bucket           *string `protobuf:"bytes,2,opt,name=bucket" json:"bucket,omitempty"`
-	Text             *string `protobuf:"bytes,3,opt,name=text" json:"text,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *DebugLinkLog) Reset()                    { *m = DebugLinkLog{} }
-func (m *DebugLinkLog) String() string            { return proto.CompactTextString(m) }
-func (*DebugLinkLog) ProtoMessage()               {}
-func (*DebugLinkLog) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{68} }
-
-func (m *DebugLinkLog) GetLevel() uint32 {
-	if m != nil && m.Level != nil {
-		return *m.Level
-	}
-	return 0
-}
-
-func (m *DebugLinkLog) GetBucket() string {
-	if m != nil && m.Bucket != nil {
-		return *m.Bucket
-	}
-	return ""
-}
-
-func (m *DebugLinkLog) GetText() string {
-	if m != nil && m.Text != nil {
-		return *m.Text
-	}
-	return ""
-}
-
-// *
-// Request: Read memory from device
-// @next DebugLinkMemory
-type DebugLinkMemoryRead struct {
-	Address          *uint32 `protobuf:"varint,1,opt,name=address" json:"address,omitempty"`
-	Length           *uint32 `protobuf:"varint,2,opt,name=length" json:"length,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *DebugLinkMemoryRead) Reset()                    { *m = DebugLinkMemoryRead{} }
-func (m *DebugLinkMemoryRead) String() string            { return proto.CompactTextString(m) }
-func (*DebugLinkMemoryRead) ProtoMessage()               {}
-func (*DebugLinkMemoryRead) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{69} }
-
-func (m *DebugLinkMemoryRead) GetAddress() uint32 {
-	if m != nil && m.Address != nil {
-		return *m.Address
-	}
-	return 0
-}
-
-func (m *DebugLinkMemoryRead) GetLength() uint32 {
-	if m != nil && m.Length != nil {
-		return *m.Length
-	}
-	return 0
-}
-
-// *
-// Response: Device sends memory back
-// @prev DebugLinkMemoryRead
-type DebugLinkMemory struct {
-	Memory           []byte `protobuf:"bytes,1,opt,name=memory" json:"memory,omitempty"`
-	XXX_unrecognized []byte `json:"-"`
-}
-
-func (m *DebugLinkMemory) Reset()                    { *m = DebugLinkMemory{} }
-func (m *DebugLinkMemory) String() string            { return proto.CompactTextString(m) }
-func (*DebugLinkMemory) ProtoMessage()               {}
-func (*DebugLinkMemory) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{70} }
-
-func (m *DebugLinkMemory) GetMemory() []byte {
-	if m != nil {
-		return m.Memory
-	}
-	return nil
-}
-
-// *
-// Request: Write memory to device.
-// WARNING: Writing to the wrong location can irreparably break the device.
-type DebugLinkMemoryWrite struct {
-	Address          *uint32 `protobuf:"varint,1,opt,name=address" json:"address,omitempty"`
-	Memory           []byte  `protobuf:"bytes,2,opt,name=memory" json:"memory,omitempty"`
-	Flash            *bool   `protobuf:"varint,3,opt,name=flash" json:"flash,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *DebugLinkMemoryWrite) Reset()                    { *m = DebugLinkMemoryWrite{} }
-func (m *DebugLinkMemoryWrite) String() string            { return proto.CompactTextString(m) }
-func (*DebugLinkMemoryWrite) ProtoMessage()               {}
-func (*DebugLinkMemoryWrite) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{71} }
-
-func (m *DebugLinkMemoryWrite) GetAddress() uint32 {
-	if m != nil && m.Address != nil {
-		return *m.Address
-	}
-	return 0
-}
-
-func (m *DebugLinkMemoryWrite) GetMemory() []byte {
-	if m != nil {
-		return m.Memory
-	}
-	return nil
-}
-
-func (m *DebugLinkMemoryWrite) GetFlash() bool {
-	if m != nil && m.Flash != nil {
-		return *m.Flash
-	}
-	return false
-}
-
-// *
-// Request: Erase block of flash on device
-// WARNING: Writing to the wrong location can irreparably break the device.
-type DebugLinkFlashErase struct {
-	Sector           *uint32 `protobuf:"varint,1,opt,name=sector" json:"sector,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *DebugLinkFlashErase) Reset()                    { *m = DebugLinkFlashErase{} }
-func (m *DebugLinkFlashErase) String() string            { return proto.CompactTextString(m) }
-func (*DebugLinkFlashErase) ProtoMessage()               {}
-func (*DebugLinkFlashErase) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{72} }
-
-func (m *DebugLinkFlashErase) GetSector() uint32 {
-	if m != nil && m.Sector != nil {
-		return *m.Sector
-	}
-	return 0
+var E_WireNoFsm = &proto.ExtensionDesc{
+	ExtendedType:  (*descriptor.EnumValueOptions)(nil),
+	ExtensionType: (*bool)(nil),
+	Field:         50008,
+	Name:          "hw.trezor.messages.wire_no_fsm",
+	Tag:           "varint,50008,opt,name=wire_no_fsm",
+	Filename:      "messages.proto",
 }
 
 func init() {
-	proto.RegisterType((*Initialize)(nil), "Initialize")
-	proto.RegisterType((*GetFeatures)(nil), "GetFeatures")
-	proto.RegisterType((*Features)(nil), "Features")
-	proto.RegisterType((*ClearSession)(nil), "ClearSession")
-	proto.RegisterType((*ApplySettings)(nil), "ApplySettings")
-	proto.RegisterType((*ApplyFlags)(nil), "ApplyFlags")
-	proto.RegisterType((*ChangePin)(nil), "ChangePin")
-	proto.RegisterType((*Ping)(nil), "Ping")
-	proto.RegisterType((*Success)(nil), "Success")
-	proto.RegisterType((*Failure)(nil), "Failure")
-	proto.RegisterType((*ButtonRequest)(nil), "ButtonRequest")
-	proto.RegisterType((*ButtonAck)(nil), "ButtonAck")
-	proto.RegisterType((*PinMatrixRequest)(nil), "PinMatrixRequest")
-	proto.RegisterType((*PinMatrixAck)(nil), "PinMatrixAck")
-	proto.RegisterType((*Cancel)(nil), "Cancel")
-	proto.RegisterType((*PassphraseRequest)(nil), "PassphraseRequest")
-	proto.RegisterType((*PassphraseAck)(nil), "PassphraseAck")
-	proto.RegisterType((*GetEntropy)(nil), "GetEntropy")
-	proto.RegisterType((*Entropy)(nil), "Entropy")
-	proto.RegisterType((*GetPublicKey)(nil), "GetPublicKey")
-	proto.RegisterType((*PublicKey)(nil), "PublicKey")
-	proto.RegisterType((*GetAddress)(nil), "GetAddress")
-	proto.RegisterType((*EthereumGetAddress)(nil), "EthereumGetAddress")
-	proto.RegisterType((*Address)(nil), "Address")
-	proto.RegisterType((*EthereumAddress)(nil), "EthereumAddress")
-	proto.RegisterType((*WipeDevice)(nil), "WipeDevice")
-	proto.RegisterType((*LoadDevice)(nil), "LoadDevice")
-	proto.RegisterType((*ResetDevice)(nil), "ResetDevice")
-	proto.RegisterType((*BackupDevice)(nil), "BackupDevice")
-	proto.RegisterType((*EntropyRequest)(nil), "EntropyRequest")
-	proto.RegisterType((*EntropyAck)(nil), "EntropyAck")
-	proto.RegisterType((*RecoveryDevice)(nil), "RecoveryDevice")
-	proto.RegisterType((*WordRequest)(nil), "WordRequest")
-	proto.RegisterType((*WordAck)(nil), "WordAck")
-	proto.RegisterType((*SignMessage)(nil), "SignMessage")
-	proto.RegisterType((*VerifyMessage)(nil), "VerifyMessage")
-	proto.RegisterType((*MessageSignature)(nil), "MessageSignature")
-	proto.RegisterType((*EncryptMessage)(nil), "EncryptMessage")
-	proto.RegisterType((*EncryptedMessage)(nil), "EncryptedMessage")
-	proto.RegisterType((*DecryptMessage)(nil), "DecryptMessage")
-	proto.RegisterType((*DecryptedMessage)(nil), "DecryptedMessage")
-	proto.RegisterType((*CipherKeyValue)(nil), "CipherKeyValue")
-	proto.RegisterType((*CipheredKeyValue)(nil), "CipheredKeyValue")
-	proto.RegisterType((*EstimateTxSize)(nil), "EstimateTxSize")
-	proto.RegisterType((*TxSize)(nil), "TxSize")
-	proto.RegisterType((*SignTx)(nil), "SignTx")
-	proto.RegisterType((*SimpleSignTx)(nil), "SimpleSignTx")
-	proto.RegisterType((*TxRequest)(nil), "TxRequest")
-	proto.RegisterType((*TxAck)(nil), "TxAck")
-	proto.RegisterType((*EthereumSignTx)(nil), "EthereumSignTx")
-	proto.RegisterType((*EthereumTxRequest)(nil), "EthereumTxRequest")
-	proto.RegisterType((*EthereumTxAck)(nil), "EthereumTxAck")
-	proto.RegisterType((*EthereumSignMessage)(nil), "EthereumSignMessage")
-	proto.RegisterType((*EthereumVerifyMessage)(nil), "EthereumVerifyMessage")
-	proto.RegisterType((*EthereumMessageSignature)(nil), "EthereumMessageSignature")
-	proto.RegisterType((*SignIdentity)(nil), "SignIdentity")
-	proto.RegisterType((*SignedIdentity)(nil), "SignedIdentity")
-	proto.RegisterType((*GetECDHSessionKey)(nil), "GetECDHSessionKey")
-	proto.RegisterType((*ECDHSessionKey)(nil), "ECDHSessionKey")
-	proto.RegisterType((*SetU2FCounter)(nil), "SetU2FCounter")
-	proto.RegisterType((*FirmwareErase)(nil), "FirmwareErase")
-	proto.RegisterType((*FirmwareRequest)(nil), "FirmwareRequest")
-	proto.RegisterType((*FirmwareUpload)(nil), "FirmwareUpload")
-	proto.RegisterType((*SelfTest)(nil), "SelfTest")
-	proto.RegisterType((*DebugLinkDecision)(nil), "DebugLinkDecision")
-	proto.RegisterType((*DebugLinkGetState)(nil), "DebugLinkGetState")
-	proto.RegisterType((*DebugLinkState)(nil), "DebugLinkState")
-	proto.RegisterType((*DebugLinkStop)(nil), "DebugLinkStop")
-	proto.RegisterType((*DebugLinkLog)(nil), "DebugLinkLog")
-	proto.RegisterType((*DebugLinkMemoryRead)(nil), "DebugLinkMemoryRead")
-	proto.RegisterType((*DebugLinkMemory)(nil), "DebugLinkMemory")
-	proto.RegisterType((*DebugLinkMemoryWrite)(nil), "DebugLinkMemoryWrite")
-	proto.RegisterType((*DebugLinkFlashErase)(nil), "DebugLinkFlashErase")
-	proto.RegisterEnum("MessageType", MessageType_name, MessageType_value)
-}
-
-func init() { proto.RegisterFile("messages.proto", fileDescriptor1) }
-
-var fileDescriptor1 = []byte{
-	// 3424 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5a, 0xcb, 0x6f, 0xdc, 0x46,
-	0x9a, 0x5f, 0x76, 0xb7, 0xfa, 0xf1, 0x35, 0xbb, 0x55, 0xa2, 0x2d, 0xbb, 0x2d, 0x5b, 0xb6, 0x4c,
-	0xc9, 0xb6, 0x64, 0x27, 0xed, 0x44, 0x79, 0x6c, 0xd6, 0xbb, 0x79, 0xc8, 0x7a, 0xd8, 0xde, 0xd8,
-	0x8e, 0xc0, 0x56, 0x9c, 0xdb, 0x12, 0x14, 0x59, 0xea, 0xae, 0x55, 0x37, 0xc9, 0xf0, 0xa1, 0xa8,
-	0x7d, 0xd8, 0xeb, 0xee, 0x65, 0x81, 0xec, 0x69, 0x73, 0x1a, 0xe4, 0x36, 0x19, 0x04, 0x18, 0x0c,
-	0x30, 0x18, 0x60, 0x72, 0x9a, 0x3f, 0x60, 0xfe, 0x8b, 0x39, 0xce, 0x1f, 0x30, 0xe7, 0x41, 0x3d,
-	0x48, 0x16, 0x29, 0xb6, 0x6c, 0x27, 0xc0, 0x5c, 0x04, 0xd6, 0x57, 0xbf, 0xfe, 0xea, 0x7b, 0xd5,
-	0x57, 0x5f, 0x7d, 0x25, 0xe8, 0x4e, 0x70, 0x18, 0x5a, 0x43, 0x1c, 0xf6, 0xfd, 0xc0, 0x8b, 0xbc,
-	0xa5, 0x76, 0x34, 0xf5, 0x93, 0x81, 0xae, 0x02, 0x3c, 0x71, 0x49, 0x44, 0xac, 0x31, 0x79, 0x89,
-	0xf5, 0x0e, 0xb4, 0x1f, 0xe1, 0x68, 0x0f, 0x5b, 0x51, 0x1c, 0xe0, 0x50, 0xff, 0x69, 0x0e, 0x9a,
-	0xc9, 0x40, 0xbb, 0x04, 0xf5, 0x13, 0xec, 0x3a, 0x5e, 0xd0, 0x53, 0x56, 0x94, 0xf5, 0x96, 0x21,
-	0x46, 0xda, 0x2a, 0x74, 0x26, 0xd6, 0x7f, 0x7a, 0x81, 0x79, 0x82, 0x83, 0x90, 0x78, 0x6e, 0xaf,
-	0xb2, 0xa2, 0xac, 0x77, 0x0c, 0x95, 0x11, 0x5f, 0x70, 0x1a, 0x03, 0x11, 0x57, 0x02, 0x55, 0x05,
-	0x88, 0x12, 0x25, 0x90, 0x6f, 0x45, 0xf6, 0x28, 0x05, 0xd5, 0x38, 0x88, 0x11, 0x13, 0xd0, 0x1d,
-	0x98, 0x3f, 0xf4, 0xbc, 0x68, 0xec, 0x59, 0x0e, 0x0e, 0xcc, 0x89, 0xe7, 0xe0, 0xde, 0xdc, 0x8a,
-	0xb2, 0xde, 0x34, 0xba, 0x19, 0xf9, 0x99, 0xe7, 0x60, 0xed, 0x2a, 0xb4, 0x1c, 0x7c, 0x42, 0x6c,
-	0x6c, 0x12, 0xa7, 0x57, 0x67, 0x22, 0x37, 0x39, 0xe1, 0x89, 0xa3, 0xdd, 0x82, 0xae, 0x4f, 0x5c,
-	0x93, 0xda, 0x00, 0xdb, 0x11, 0x5d, 0xab, 0xc1, 0x98, 0x74, 0x7c, 0xe2, 0xee, 0xa7, 0x44, 0xed,
-	0x3d, 0x58, 0xf4, 0xad, 0x30, 0xf4, 0x47, 0x81, 0x15, 0x62, 0x19, 0xdd, 0x64, 0xe8, 0x8b, 0xd9,
-	0xa4, 0xf4, 0xa3, 0x25, 0x68, 0x8e, 0x2d, 0x77, 0x18, 0x5b, 0x43, 0xdc, 0x6b, 0xf1, 0x75, 0x93,
-	0xb1, 0x76, 0x11, 0xe6, 0xc6, 0xd6, 0x21, 0x1e, 0xf7, 0x80, 0x4d, 0xf0, 0x81, 0x76, 0x03, 0xe6,
-	0x6c, 0x8f, 0xb8, 0x61, 0xaf, 0xbd, 0x52, 0x5d, 0x6f, 0x6f, 0xb6, 0xfa, 0xdb, 0x1e, 0x71, 0x0f,
-	0xa6, 0x3e, 0x36, 0x38, 0x5d, 0x5b, 0x81, 0x36, 0x49, 0xbd, 0xe4, 0xf4, 0x54, 0xb6, 0xba, 0x4c,
-	0xa2, 0x8b, 0x06, 0xf8, 0x84, 0x30, 0xb3, 0x75, 0x56, 0x94, 0x75, 0xd5, 0x48, 0xc7, 0x05, 0x93,
-	0x8d, 0xac, 0x70, 0xd4, 0xeb, 0x32, 0x88, 0x64, 0xb2, 0xc7, 0x56, 0x38, 0xa2, 0x4c, 0xc8, 0xc4,
-	0xf7, 0x82, 0x08, 0x3b, 0xbd, 0x79, 0xb6, 0x46, 0x3a, 0xd6, 0x96, 0x01, 0xa8, 0xc5, 0x6c, 0xcb,
-	0x1e, 0x61, 0xa7, 0x87, 0xd8, 0x6c, 0xcb, 0x27, 0xee, 0x36, 0x23, 0x68, 0xf7, 0x60, 0x41, 0xb2,
-	0x94, 0x40, 0x2d, 0x30, 0x14, 0xca, 0x26, 0x04, 0x78, 0x03, 0xd0, 0x11, 0x09, 0x26, 0xdf, 0x58,
-	0x01, 0x35, 0x2a, 0x0e, 0xb1, 0x1b, 0xf5, 0x34, 0x86, 0x9d, 0x4f, 0xe8, 0xfb, 0x9c, 0xac, 0xdd,
-	0x04, 0xd5, 0xc5, 0xd8, 0x09, 0xcd, 0x43, 0xcb, 0x3e, 0x8e, 0xfd, 0xde, 0x05, 0xae, 0x3a, 0xa3,
-	0x3d, 0x64, 0x24, 0x6a, 0xd3, 0xa3, 0xb1, 0x35, 0x0c, 0x7b, 0x17, 0x59, 0xb8, 0xf0, 0x81, 0xde,
-	0x05, 0x75, 0x7b, 0x8c, 0xad, 0x60, 0x80, 0x43, 0x6a, 0x04, 0xfd, 0x7f, 0x14, 0xe8, 0x6c, 0xf9,
-	0xfe, 0x78, 0x3a, 0xc0, 0x51, 0x44, 0xdc, 0x61, 0x98, 0xf3, 0x93, 0x32, 0xcb, 0x4f, 0x15, 0xd9,
-	0x4f, 0xb7, 0xa0, 0x1b, 0xd3, 0x38, 0x48, 0xf5, 0x61, 0x61, 0xdc, 0x34, 0x3a, 0x71, 0x88, 0xf7,
-	0x53, 0xa2, 0x76, 0x1d, 0x60, 0xe4, 0x4d, 0x70, 0x68, 0x07, 0x18, 0xf3, 0x20, 0x56, 0x0d, 0x89,
-	0xa2, 0xeb, 0x00, 0x4c, 0x92, 0x3d, 0x2a, 0x68, 0x26, 0xbe, 0x22, 0x8b, 0xbf, 0x0a, 0xad, 0xed,
-	0x91, 0xe5, 0x0e, 0xf1, 0x3e, 0x71, 0xe9, 0xd6, 0x0b, 0xf0, 0xc4, 0x3b, 0xe1, 0x72, 0x36, 0x0d,
-	0x31, 0xd2, 0x7f, 0xa3, 0x40, 0x6d, 0x9f, 0xb8, 0x43, 0xad, 0x07, 0x0d, 0xb1, 0xc9, 0x85, 0x26,
-	0xc9, 0x90, 0xfa, 0xe5, 0x30, 0x8e, 0x22, 0x2f, 0x17, 0xeb, 0x15, 0xee, 0x17, 0x3e, 0x21, 0x45,
-	0xee, 0xd9, 0x5d, 0x51, 0x7d, 0xa3, 0x5d, 0x51, 0x9b, 0xbd, 0x2b, 0xf4, 0x55, 0x68, 0x0c, 0x62,
-	0xdb, 0xc6, 0x61, 0x38, 0x5b, 0x5a, 0x7d, 0x17, 0x1a, 0x7b, 0x16, 0x19, 0xc7, 0x01, 0xd6, 0x56,
-	0xa0, 0x66, 0xd3, 0xcd, 0x4d, 0x11, 0xdd, 0x4d, 0xb5, 0x2f, 0xe8, 0x6c, 0x57, 0xb0, 0x19, 0x99,
-	0x4d, 0x25, 0xcf, 0xe6, 0x73, 0xe8, 0x3c, 0x64, 0xba, 0x19, 0xf8, 0xeb, 0x18, 0x87, 0x91, 0x76,
-	0x3b, 0xc7, 0x4c, 0xeb, 0xe7, 0x66, 0x25, 0x96, 0x1a, 0xd4, 0x1c, 0x2b, 0xb2, 0x04, 0x3f, 0xf6,
-	0xad, 0xb7, 0xa1, 0xc5, 0xe1, 0x5b, 0xf6, 0xb1, 0xfe, 0x31, 0xa0, 0x7d, 0xe2, 0x3e, 0xb3, 0xa2,
-	0x80, 0x9c, 0x26, 0xcc, 0x37, 0xa0, 0x46, 0x33, 0xaa, 0x60, 0xbe, 0xd8, 0x2f, 0x02, 0x38, 0x7f,
-	0x0a, 0xd1, 0x57, 0x40, 0x4d, 0x67, 0xb7, 0xec, 0x63, 0x0d, 0x41, 0xd5, 0x27, 0x6e, 0x4f, 0x59,
-	0xa9, 0xac, 0xb7, 0x0c, 0xfa, 0xa9, 0x37, 0xa1, 0xbe, 0x6d, 0xb9, 0x36, 0x1e, 0xeb, 0x17, 0x60,
-	0x21, 0x8b, 0x29, 0xc1, 0x4a, 0xbf, 0x0f, 0x9d, 0x8c, 0x48, 0x39, 0x5c, 0x07, 0x90, 0xc2, 0x91,
-	0x33, 0x92, 0x28, 0xfa, 0x0a, 0xc0, 0x23, 0x1c, 0xed, 0xba, 0x51, 0xe0, 0xf9, 0x53, 0xaa, 0x5f,
-	0x48, 0x5e, 0x72, 0x5c, 0xc7, 0x60, 0xdf, 0xd4, 0x31, 0xc9, 0x74, 0x0f, 0x1a, 0x98, 0x7f, 0x32,
-	0x84, 0x6a, 0x24, 0x43, 0xfd, 0x57, 0x0a, 0xa8, 0x8f, 0x70, 0xb4, 0x1f, 0x1f, 0x8e, 0x89, 0xfd,
-	0x39, 0x9e, 0xd2, 0xec, 0x6a, 0x39, 0x4e, 0x80, 0xc3, 0xd0, 0xa4, 0xf2, 0x57, 0xd7, 0x3b, 0x46,
-	0x53, 0x10, 0x9e, 0x6b, 0xeb, 0x80, 0xb0, 0xed, 0x84, 0x96, 0x69, 0xc7, 0xc1, 0x09, 0x36, 0x5d,
-	0x6b, 0x92, 0xb8, 0xa8, 0xcb, 0xe8, 0xdb, 0x94, 0xfc, 0xdc, 0x9a, 0x60, 0xba, 0xbd, 0xc3, 0x91,
-	0xf7, 0x8d, 0xe9, 0x90, 0xd0, 0x1f, 0x5b, 0x53, 0x11, 0x6f, 0x6d, 0x4a, 0xdb, 0xe1, 0x24, 0x6d,
-	0x0d, 0x5a, 0x34, 0x09, 0x72, 0x2e, 0x34, 0xc2, 0x5a, 0x0f, 0x1a, 0x0f, 0x49, 0x44, 0x69, 0x46,
-	0x93, 0xfe, 0xa5, 0x8c, 0xf4, 0xcf, 0xa0, 0x95, 0x09, 0x77, 0x03, 0x6a, 0x2e, 0x77, 0x77, 0x65,
-	0xbd, 0xbd, 0xd9, 0xee, 0x3f, 0xde, 0x79, 0xee, 0x39, 0x22, 0x74, 0x5c, 0xe1, 0xe7, 0x53, 0x3f,
-	0x3e, 0x4c, 0xfc, 0x4c, 0xbf, 0xf5, 0xbf, 0x2a, 0xcc, 0x54, 0x5b, 0x5c, 0x89, 0xf3, 0x15, 0xcc,
-	0xc9, 0x54, 0x99, 0x21, 0xd3, 0xeb, 0x28, 0xf7, 0x01, 0x34, 0x27, 0xf1, 0x38, 0x22, 0x21, 0x19,
-	0x32, 0xdd, 0xda, 0x9b, 0x57, 0xfa, 0xcf, 0x04, 0xc1, 0xc0, 0x0e, 0xc6, 0x93, 0x81, 0x1d, 0x10,
-	0x9f, 0xc7, 0x50, 0x0a, 0xd5, 0x3e, 0x85, 0x76, 0xc8, 0xe8, 0x26, 0x8b, 0xbc, 0x39, 0x16, 0x79,
-	0xa8, 0xff, 0xc4, 0xf5, 0xe3, 0x28, 0xfb, 0xc1, 0x03, 0x75, 0xb0, 0xbf, 0xfb, 0x7c, 0x67, 0x6b,
-	0x67, 0xc7, 0xd8, 0x1d, 0x0c, 0x0c, 0x08, 0xd3, 0x19, 0xfd, 0x00, 0xb4, 0xdd, 0x68, 0x84, 0x03,
-	0x1c, 0x4f, 0x5e, 0x57, 0xe7, 0xa2, 0x36, 0x95, 0x33, 0xda, 0xd0, 0x50, 0x4a, 0x58, 0xf5, 0xa0,
-	0x21, 0x7e, 0x29, 0x82, 0x32, 0x19, 0xea, 0xf7, 0x60, 0x3e, 0x59, 0x7a, 0x06, 0x58, 0xcd, 0xc0,
-	0x2a, 0xc0, 0x57, 0xc4, 0xc7, 0x3b, 0xec, 0xdc, 0xd6, 0xff, 0xaf, 0x02, 0xf0, 0xd4, 0xb3, 0x1c,
-	0x3e, 0xa4, 0x09, 0x7c, 0xe2, 0xe2, 0x89, 0xe7, 0x12, 0x3b, 0x49, 0xe0, 0xc9, 0x38, 0x0d, 0x81,
-	0x0a, 0x33, 0x6a, 0x49, 0x08, 0x88, 0xad, 0x57, 0x65, 0xbf, 0xa3, 0x9f, 0x3f, 0x2b, 0xad, 0x69,
-	0xab, 0xd2, 0x21, 0x32, 0xc7, 0x03, 0x01, 0xbb, 0xc3, 0x31, 0x09, 0x47, 0x65, 0xa7, 0x49, 0x5d,
-	0x3e, 0x4d, 0x56, 0xa1, 0x13, 0x1e, 0x13, 0xdf, 0xb4, 0x47, 0xd8, 0x3e, 0x0e, 0xe3, 0x89, 0x28,
-	0x41, 0x54, 0x4a, 0xdc, 0x16, 0x34, 0xed, 0x06, 0xb4, 0xe3, 0xcd, 0x23, 0xd3, 0xf6, 0x62, 0x37,
-	0xc2, 0x01, 0xab, 0x3b, 0x3a, 0x06, 0xc4, 0x9b, 0x47, 0xdb, 0x9c, 0xa2, 0xff, 0xb6, 0x02, 0x6d,
-	0x03, 0x87, 0x38, 0x12, 0x46, 0xb9, 0x05, 0x5d, 0xe1, 0x21, 0x33, 0xb0, 0x5c, 0xc7, 0x9b, 0x88,
-	0x33, 0xa3, 0x23, 0xa8, 0x06, 0x23, 0x6a, 0x37, 0xa0, 0x19, 0x46, 0x01, 0x76, 0x87, 0xd1, 0x88,
-	0x17, 0x6c, 0x0f, 0xaa, 0x9b, 0x1f, 0x7c, 0x68, 0xa4, 0xc4, 0xd9, 0xd6, 0xa8, 0x9e, 0x63, 0x8d,
-	0xb3, 0x07, 0x48, 0xad, 0xec, 0x00, 0xf9, 0x05, 0x46, 0x2b, 0xd8, 0xa3, 0x51, 0xb4, 0x07, 0x05,
-	0x30, 0xab, 0x8a, 0x7a, 0x81, 0x17, 0x6a, 0x40, 0x49, 0xbc, 0x5c, 0xa0, 0x85, 0x01, 0xff, 0x12,
-	0x41, 0x85, 0xa0, 0x2b, 0xf2, 0x5f, 0x92, 0x64, 0x6f, 0x03, 0x08, 0x0a, 0xcd, 0xb0, 0xb9, 0xa4,
-	0xa8, 0xc8, 0x49, 0xf1, 0x4f, 0x15, 0xe8, 0x1a, 0xd8, 0xf6, 0x4e, 0x70, 0x30, 0x15, 0xd6, 0x5f,
-	0x06, 0xf8, 0xc6, 0x0b, 0x1c, 0x2e, 0x9f, 0x38, 0xd1, 0x5b, 0x94, 0xc2, 0xc4, 0x9b, 0x6d, 0xd4,
-	0xca, 0x1b, 0x19, 0xb5, 0xfa, 0x2a, 0xa3, 0xd6, 0x5e, 0x69, 0xd4, 0x39, 0xd9, 0xa8, 0x1b, 0x80,
-	0xb0, 0x7b, 0xe4, 0x05, 0x36, 0x36, 0xa9, 0xac, 0x63, 0x12, 0x46, 0xcc, 0xea, 0x4d, 0x63, 0x5e,
-	0xd0, 0xbf, 0x12, 0x64, 0x9a, 0x39, 0x59, 0xca, 0xe1, 0x81, 0xc8, 0xbe, 0x8b, 0x3e, 0x69, 0x9d,
-	0xf1, 0xc9, 0x65, 0x68, 0x38, 0xc1, 0xd4, 0x0c, 0x62, 0x97, 0xd5, 0xbd, 0x4d, 0xa3, 0xee, 0x04,
-	0x53, 0x23, 0x76, 0xf5, 0xf7, 0xa0, 0x4d, 0x39, 0x27, 0x27, 0xe9, 0x5a, 0xee, 0x24, 0x45, 0x7d,
-	0x69, 0x4e, 0x3a, 0x44, 0x97, 0xa1, 0x41, 0x27, 0xa8, 0x6f, 0x34, 0xa8, 0x51, 0x81, 0x45, 0x8a,
-	0x61, 0xdf, 0xfa, 0x8f, 0x0a, 0xb4, 0x07, 0x64, 0xe8, 0x3e, 0x13, 0x15, 0xd0, 0xb9, 0x49, 0x2d,
-	0x57, 0x43, 0xb0, 0xcc, 0x93, 0x14, 0x4e, 0xb9, 0x14, 0x5f, 0x9d, 0x95, 0xe2, 0x0b, 0x89, 0xb8,
-	0xf6, 0xc6, 0x89, 0xf8, 0xbf, 0x15, 0xe8, 0xbc, 0xc0, 0x01, 0x39, 0x9a, 0x26, 0xf2, 0xe6, 0x92,
-	0xa1, 0x22, 0x65, 0x4e, 0xed, 0x1a, 0xb4, 0x42, 0x32, 0x74, 0xd9, 0x7d, 0x8c, 0x45, 0x8c, 0x6a,
-	0x64, 0x04, 0x59, 0x95, 0x2a, 0x8f, 0xd3, 0x52, 0x55, 0x66, 0x9e, 0xa0, 0xff, 0x0e, 0x48, 0x88,
-	0x30, 0x90, 0x79, 0xfe, 0x1c, 0x59, 0xf4, 0x1f, 0x14, 0xba, 0xa9, 0xec, 0x60, 0xea, 0x47, 0x89,
-	0x5a, 0x97, 0xa0, 0xee, 0xc7, 0x87, 0xc7, 0x38, 0xd9, 0x45, 0x62, 0x54, 0xac, 0xe2, 0x24, 0xb1,
-	0x6f, 0x82, 0x9a, 0x64, 0x32, 0xcf, 0x1d, 0xa7, 0xc7, 0xa7, 0xa0, 0x7d, 0xe1, 0x8e, 0x0b, 0x55,
-	0x48, 0xed, 0xbc, 0x43, 0x7a, 0x6e, 0x96, 0xda, 0x2f, 0x00, 0x09, 0x49, 0xb1, 0x93, 0xc8, 0x7a,
-	0x11, 0xe6, 0x5c, 0xcf, 0xb5, 0xb1, 0x10, 0x95, 0x0f, 0xce, 0x91, 0x54, 0x83, 0xda, 0x68, 0x62,
-	0xd9, 0xc2, 0xee, 0xec, 0x5b, 0xff, 0x1a, 0xba, 0x3b, 0x38, 0x67, 0x81, 0x73, 0x03, 0x31, 0x5d,
-	0xb2, 0x32, 0x63, 0xc9, 0x6a, 0xf9, 0x92, 0x35, 0x69, 0xc9, 0x3d, 0x40, 0x62, 0xc9, 0x4c, 0x95,
-	0x42, 0xad, 0x2d, 0x71, 0x90, 0x7c, 0x5b, 0xc9, 0xf9, 0x56, 0xff, 0xb3, 0x02, 0xdd, 0x6d, 0xe2,
-	0x8f, 0x70, 0xf0, 0x39, 0x9e, 0xbe, 0xb0, 0xc6, 0xf1, 0x2b, 0x64, 0x47, 0x50, 0xa5, 0x7e, 0xe5,
-	0x5c, 0xe8, 0x27, 0xd5, 0xe6, 0x84, 0xfe, 0x4e, 0x48, 0xcd, 0x07, 0x3c, 0x93, 0x32, 0xf9, 0xc4,
-	0xb1, 0x90, 0x0c, 0xb5, 0x35, 0xe8, 0x5a, 0xe1, 0xb1, 0xe9, 0xb9, 0x66, 0x02, 0xe0, 0x77, 0x7a,
-	0xd5, 0x0a, 0x8f, 0xbf, 0x70, 0x77, 0xcf, 0xa0, 0x1c, 0xae, 0xa6, 0x48, 0x52, 0x1c, 0x25, 0x54,
-	0xd7, 0xba, 0x50, 0x21, 0x27, 0xec, 0x60, 0x50, 0x8d, 0x0a, 0x39, 0xd1, 0xd7, 0x01, 0x71, 0x65,
-	0xb0, 0x93, 0xaa, 0x93, 0xca, 0xa7, 0x48, 0xf2, 0xe9, 0xff, 0x05, 0xdd, 0xdd, 0x30, 0x22, 0x13,
-	0x2b, 0xc2, 0x07, 0xa7, 0x03, 0xf2, 0x12, 0xd3, 0x23, 0xda, 0x8b, 0x23, 0x3f, 0x8e, 0xc2, 0x34,
-	0xa3, 0xd3, 0xc2, 0x59, 0x15, 0x44, 0x9e, 0xd4, 0x6f, 0x82, 0x4a, 0x5c, 0x09, 0x53, 0x61, 0x98,
-	0x36, 0xa7, 0x71, 0xc8, 0x6b, 0x25, 0x13, 0xfd, 0x26, 0xd4, 0xc5, 0xba, 0x97, 0xa1, 0x11, 0x9d,
-	0x9a, 0xa2, 0x54, 0xa7, 0xd9, 0xb4, 0x1e, 0xb1, 0x09, 0xfd, 0xf7, 0x0a, 0xd4, 0xe9, 0xf6, 0x3c,
-	0x38, 0xfd, 0xc7, 0xca, 0xa6, 0x5d, 0x85, 0x46, 0xae, 0x2b, 0xf3, 0x40, 0x79, 0xd7, 0x48, 0x28,
-	0xda, 0x75, 0x68, 0x8d, 0x3d, 0xfb, 0xd8, 0x8c, 0x88, 0xd8, 0x69, 0x9d, 0x07, 0xca, 0x3b, 0x46,
-	0x93, 0xd2, 0x0e, 0xc8, 0x04, 0xeb, 0x7f, 0x53, 0x40, 0x1d, 0x90, 0x89, 0x3f, 0xc6, 0x42, 0xf6,
-	0x35, 0xa8, 0x73, 0x11, 0x58, 0x2c, 0xb5, 0x37, 0xd5, 0xfe, 0xc1, 0x29, 0xcb, 0x99, 0x2c, 0xcd,
-	0x8b, 0x39, 0xed, 0x0e, 0x34, 0x84, 0x32, 0xbd, 0x0a, 0x83, 0x75, 0xfa, 0x07, 0xa7, 0x5f, 0x30,
-	0x0a, 0xc3, 0x25, 0xb3, 0xda, 0xfb, 0xa0, 0x46, 0x81, 0xe5, 0x86, 0x16, 0x3b, 0x09, 0xc3, 0x5e,
-	0x95, 0xa1, 0x51, 0xff, 0x20, 0x23, 0xb2, 0x1f, 0xe4, 0x50, 0xaf, 0x97, 0x16, 0x65, 0xc5, 0xe7,
-	0xce, 0x57, 0xbc, 0x7e, 0x56, 0xf1, 0x5f, 0x2b, 0xd0, 0x3a, 0x48, 0x2f, 0x8a, 0xf7, 0x41, 0x0d,
-	0xf8, 0xa7, 0x29, 0x1d, 0x73, 0x6a, 0x5f, 0x3e, 0xe2, 0xda, 0x41, 0x36, 0xd0, 0xee, 0x43, 0xc3,
-	0xc1, 0x91, 0x45, 0xc6, 0xa1, 0xa8, 0x63, 0x17, 0xfb, 0x29, 0xb7, 0x1d, 0x3e, 0xc1, 0x0d, 0x21,
-	0x50, 0xda, 0x47, 0x00, 0x21, 0x0e, 0x92, 0x36, 0x51, 0x95, 0xfd, 0xa6, 0x97, 0xfd, 0x66, 0x90,
-	0xce, 0xb1, 0x9f, 0x49, 0x58, 0x7d, 0x03, 0xe6, 0x0e, 0xd8, 0x95, 0x74, 0x05, 0x2a, 0xd1, 0x29,
-	0x13, 0xad, 0xcc, 0x82, 0x95, 0xe8, 0x54, 0xff, 0xdf, 0x0a, 0x74, 0x93, 0x0a, 0x5e, 0xf8, 0xf3,
-	0x67, 0xa4, 0xb6, 0xab, 0xd0, 0x1a, 0x5a, 0xa1, 0xe9, 0x07, 0xc4, 0x4e, 0xd2, 0x44, 0x73, 0x68,
-	0x85, 0xfb, 0x74, 0x9c, 0x4c, 0x8e, 0xc9, 0x84, 0x44, 0x22, 0xc5, 0xd1, 0xc9, 0xa7, 0x74, 0x4c,
-	0x37, 0x78, 0xe4, 0x31, 0x67, 0xa8, 0x46, 0x25, 0xf2, 0xb2, 0xcd, 0x5c, 0x97, 0x93, 0xcd, 0x5b,
-	0xa0, 0xd1, 0xeb, 0xbb, 0x29, 0x9a, 0x64, 0xa6, 0x3d, 0x8a, 0xdd, 0x63, 0x91, 0x16, 0x10, 0x9d,
-	0x11, 0x6d, 0xcf, 0x6d, 0x4a, 0xa7, 0x25, 0x0c, 0x43, 0x8f, 0x79, 0x45, 0x2c, 0xca, 0x6c, 0x4a,
-	0x7a, 0xca, 0xcb, 0xe1, 0x2b, 0xd0, 0xb4, 0x47, 0x16, 0x71, 0x4d, 0xe2, 0x88, 0x02, 0xa7, 0xc1,
-	0xc6, 0x4f, 0x1c, 0xfd, 0xff, 0x15, 0x58, 0x48, 0xec, 0x91, 0x39, 0xbb, 0xc0, 0x51, 0x39, 0xc3,
-	0x91, 0x16, 0xaa, 0xc9, 0x81, 0x69, 0x9e, 0x88, 0xae, 0x29, 0xa4, 0xa4, 0x17, 0x79, 0x40, 0x20,
-	0x6c, 0x94, 0x01, 0x8c, 0x3c, 0x20, 0x4c, 0x1a, 0x4d, 0x29, 0x69, 0xa0, 0xf7, 0xa1, 0x93, 0x09,
-	0x46, 0x9d, 0xbb, 0x0c, 0x4c, 0x02, 0x61, 0x0c, 0x9e, 0xfc, 0x5a, 0x94, 0xc2, 0xac, 0xa0, 0x3f,
-	0x85, 0x0b, 0xb2, 0x63, 0x7f, 0x59, 0x05, 0xa5, 0x13, 0x58, 0x4c, 0xb8, 0x9d, 0x5b, 0xe1, 0xa8,
-	0xbf, 0xb8, 0xc2, 0xd1, 0x0d, 0xe8, 0x25, 0x4b, 0xbd, 0xaa, 0x86, 0x79, 0xdd, 0xd5, 0xf4, 0x9f,
-	0x58, 0xd2, 0x1a, 0xba, 0x4f, 0x1c, 0xec, 0x46, 0x24, 0x9a, 0x6a, 0x1b, 0xd0, 0x24, 0xe2, 0x5b,
-	0xec, 0x8f, 0x4e, 0x3f, 0x99, 0xe4, 0xf7, 0x73, 0x92, 0x41, 0x91, 0x3d, 0xb2, 0xc6, 0xd4, 0xf7,
-	0xd8, 0x1c, 0x11, 0xc7, 0xc1, 0xae, 0x58, 0x60, 0x3e, 0xa5, 0x3f, 0x66, 0xe4, 0x3c, 0xf4, 0x84,
-	0x84, 0xb1, 0x35, 0x16, 0x97, 0xd2, 0x0c, 0xfa, 0x82, 0x91, 0x4b, 0xdb, 0x2a, 0xb5, 0xb2, 0xb6,
-	0x8a, 0x3e, 0x84, 0x2e, 0x15, 0x1d, 0x3b, 0xa9, 0xf0, 0xb3, 0x2b, 0xb9, 0x65, 0x00, 0x9f, 0x75,
-	0x4e, 0xcc, 0xe4, 0x10, 0x57, 0x8d, 0x96, 0x9f, 0xf6, 0x52, 0x72, 0x46, 0xaa, 0x16, 0x8d, 0xf4,
-	0xad, 0x02, 0x0b, 0x8f, 0x70, 0xb4, 0xbb, 0xbd, 0xf3, 0x58, 0x34, 0x5a, 0xe9, 0x6f, 0xde, 0xc0,
-	0x52, 0xb7, 0x61, 0xde, 0xc7, 0x38, 0x30, 0xcf, 0x88, 0xd0, 0xa1, 0xe4, 0xac, 0xa5, 0x53, 0xa6,
-	0x7b, 0xb5, 0x54, 0xf7, 0x77, 0xa1, 0x5b, 0x10, 0x87, 0xee, 0x13, 0x3e, 0x32, 0xb3, 0xfa, 0x13,
-	0xc2, 0x14, 0xa0, 0xbf, 0x03, 0x9d, 0x01, 0x8e, 0xbe, 0xdc, 0xdc, 0x93, 0x2e, 0x91, 0xf2, 0x8d,
-	0x46, 0x39, 0x73, 0xeb, 0xbe, 0x03, 0x9d, 0x3d, 0xd1, 0xa9, 0xde, 0x65, 0x3d, 0xdf, 0x4b, 0x50,
-	0xcf, 0xed, 0x74, 0x31, 0xd2, 0xb7, 0x60, 0x3e, 0x01, 0x26, 0x99, 0xe1, 0x12, 0xd4, 0xbd, 0xa3,
-	0xa3, 0x10, 0x27, 0xf7, 0x43, 0x31, 0x92, 0x58, 0x54, 0x72, 0x2c, 0x3e, 0x81, 0x6e, 0xc2, 0xe2,
-	0x4b, 0x7f, 0xec, 0x59, 0x0e, 0x75, 0xa6, 0x6f, 0x4d, 0xe9, 0x67, 0xd2, 0x2f, 0x11, 0x43, 0x56,
-	0x16, 0x5a, 0xe1, 0x48, 0xd8, 0x90, 0x7d, 0xeb, 0x6b, 0xd0, 0x1c, 0xe0, 0xf1, 0xd1, 0x01, 0x5d,
-	0x3b, 0xf7, 0x4b, 0x45, 0xfa, 0xa5, 0x7e, 0x17, 0x16, 0x76, 0xf0, 0x61, 0x3c, 0x7c, 0x4a, 0xdc,
-	0xe3, 0x1d, 0x6c, 0xf3, 0x97, 0x83, 0x45, 0xa8, 0x4f, 0x71, 0x68, 0xba, 0x1e, 0x5b, 0xa7, 0x69,
-	0xcc, 0x4d, 0x71, 0xf8, 0xdc, 0xd3, 0x2f, 0x48, 0xd8, 0x47, 0x38, 0x1a, 0x44, 0x56, 0x84, 0xf5,
-	0xbf, 0x54, 0x68, 0xc5, 0x2b, 0xa8, 0x8c, 0xc4, 0x34, 0xb2, 0xa6, 0x5e, 0x1c, 0x25, 0x35, 0x3f,
-	0x1f, 0x25, 0xbd, 0x97, 0x4a, 0xd6, 0x7b, 0xb9, 0x04, 0xf5, 0x09, 0xeb, 0x8a, 0x0a, 0xa7, 0x8a,
-	0x51, 0xae, 0xc5, 0x53, 0x9b, 0xd1, 0xe2, 0x99, 0x9b, 0xd5, 0xe2, 0x99, 0x79, 0xdb, 0xae, 0x9f,
-	0x73, 0xdb, 0x5e, 0x06, 0x08, 0x70, 0x88, 0x23, 0x76, 0x13, 0x66, 0xe7, 0x45, 0xcb, 0x68, 0x31,
-	0x0a, 0xbd, 0x74, 0xd2, 0xaa, 0x8b, 0x4f, 0x27, 0x3d, 0x81, 0x26, 0xd3, 0x4c, 0x65, 0xc4, 0xa4,
-	0x8f, 0xfa, 0x16, 0x68, 0x81, 0xe8, 0x0b, 0x98, 0x47, 0xd6, 0x31, 0xbf, 0x55, 0x8b, 0xb7, 0x20,
-	0x94, 0xcc, 0xec, 0x59, 0xc7, 0xec, 0x5a, 0xad, 0xdd, 0x85, 0x85, 0x14, 0xcd, 0x9a, 0x07, 0xbe,
-	0x17, 0xb2, 0x7b, 0x72, 0xc7, 0x98, 0x4f, 0x26, 0x28, 0x70, 0xdf, 0x0b, 0xf5, 0x79, 0xe8, 0x48,
-	0x36, 0xf6, 0x7c, 0x7d, 0x1f, 0xd4, 0x94, 0xf0, 0xd4, 0x1b, 0xb2, 0x0b, 0x3e, 0x3e, 0xc1, 0xe3,
-	0xe4, 0x35, 0x81, 0x0d, 0xa8, 0x79, 0x0f, 0x63, 0xfb, 0x18, 0x47, 0xc2, 0xe6, 0x62, 0xc4, 0x6e,
-	0xf3, 0xf8, 0x34, 0x12, 0x46, 0x67, 0xdf, 0xfa, 0x23, 0xb8, 0x90, 0x72, 0x7c, 0x86, 0x27, 0x5e,
-	0x30, 0x35, 0x30, 0x8f, 0x39, 0x39, 0x81, 0x74, 0xb2, 0x04, 0x32, 0x2b, 0x6e, 0x37, 0x60, 0xbe,
-	0xc0, 0x88, 0xb9, 0x99, 0x7d, 0x25, 0x01, 0xc1, 0x47, 0xfa, 0x7f, 0xc0, 0xc5, 0x02, 0xf4, 0xab,
-	0x80, 0x44, 0xf8, 0xfc, 0x45, 0x05, 0xa7, 0x8a, 0xcc, 0x49, 0xbc, 0xa6, 0x84, 0x23, 0x71, 0x5b,
-	0xe4, 0x03, 0xfd, 0x6d, 0x49, 0xa7, 0x3d, 0x4a, 0x49, 0x37, 0x6d, 0x88, 0xed, 0xc8, 0x4b, 0x76,
-	0xb8, 0x18, 0xdd, 0xfd, 0x71, 0x11, 0xda, 0xe2, 0x1c, 0x61, 0x75, 0xd8, 0x0a, 0x5c, 0x92, 0x86,
-	0x66, 0xf6, 0x60, 0x8a, 0xfe, 0x69, 0xa9, 0xf6, 0xed, 0x1f, 0x7a, 0x8a, 0xb6, 0x94, 0x5e, 0x9e,
-	0x19, 0x62, 0x9f, 0xb8, 0x43, 0xa4, 0x88, 0xb9, 0x65, 0xb8, 0x20, 0xcf, 0x89, 0x57, 0x10, 0x54,
-	0x59, 0xaa, 0x7d, 0x57, 0x32, 0x2d, 0xde, 0x39, 0x50, 0x55, 0x4c, 0xdf, 0x80, 0x45, 0x79, 0x3a,
-	0x7d, 0x14, 0x42, 0x35, 0xc1, 0xbe, 0x20, 0x5c, 0xd6, 0x2e, 0x45, 0x73, 0x02, 0x71, 0x07, 0xae,
-	0xe4, 0x56, 0x90, 0x13, 0x17, 0xaa, 0x2f, 0x35, 0x29, 0xe8, 0x8f, 0x14, 0xb8, 0x0e, 0x4b, 0x65,
-	0x40, 0x9e, 0x75, 0x50, 0x43, 0x42, 0x6e, 0xc0, 0xd5, 0x32, 0xa4, 0x48, 0x71, 0xa8, 0xb9, 0xd4,
-	0xfc, 0x2e, 0x81, 0x16, 0xe4, 0xcb, 0x5e, 0x23, 0x50, 0xab, 0xdc, 0x40, 0xc9, 0x34, 0x08, 0x0b,
-	0xe8, 0xd0, 0x2b, 0x30, 0x48, 0x8f, 0x05, 0xd4, 0x16, 0x2c, 0x0a, 0x56, 0xca, 0x00, 0xaa, 0x60,
-	0x52, 0x90, 0x22, 0xeb, 0x22, 0xa3, 0x8e, 0x60, 0x71, 0x13, 0x2e, 0xcb, 0x08, 0xa9, 0xa7, 0x8a,
-	0xba, 0x02, 0x72, 0x0d, 0xb4, 0x9c, 0x27, 0x59, 0xf1, 0x8b, 0xe6, 0xc5, 0xec, 0x5a, 0x5e, 0x4e,
-	0xf9, 0xc2, 0x83, 0xd0, 0x52, 0x9d, 0x62, 0x9a, 0x8a, 0x76, 0x1d, 0x2e, 0xe6, 0x2c, 0x27, 0x9e,
-	0xd7, 0xd1, 0x82, 0x10, 0xf4, 0x36, 0x5c, 0x2b, 0x44, 0x52, 0xee, 0x31, 0x09, 0x69, 0x29, 0xae,
-	0x57, 0x8a, 0xdb, 0xb2, 0x8f, 0xd1, 0x05, 0xee, 0xa9, 0xdf, 0x95, 0xc8, 0xcc, 0x1f, 0x97, 0xd0,
-	0xc5, 0x72, 0xbb, 0xa5, 0xe5, 0x2b, 0x5a, 0x14, 0xcb, 0x5c, 0x85, 0x85, 0x3c, 0x80, 0xf2, 0xbf,
-	0x94, 0x6a, 0x9c, 0x8b, 0x97, 0x7c, 0xcf, 0x00, 0x5d, 0x16, 0xa8, 0x82, 0xff, 0xe4, 0x57, 0x59,
-	0xd4, 0x13, 0x98, 0xd5, 0x7c, 0x88, 0xe6, 0x1e, 0x6a, 0xd1, 0x95, 0x72, 0x50, 0xee, 0x11, 0x0f,
-	0x2d, 0x09, 0x81, 0x57, 0xf3, 0x1a, 0xa5, 0x4f, 0x77, 0xe8, 0xaa, 0x64, 0x94, 0x42, 0x34, 0x64,
-	0xaf, 0xb1, 0xe8, 0x5a, 0xf9, 0xae, 0xca, 0x1e, 0x49, 0xd0, 0x72, 0x79, 0xd4, 0x26, 0xd3, 0xd7,
-	0xd3, 0xa8, 0xcd, 0xf9, 0x39, 0x39, 0x81, 0xd1, 0x8a, 0xb4, 0x8b, 0x0a, 0x96, 0x91, 0xdb, 0xd2,
-	0x48, 0x2f, 0xb7, 0x71, 0xbe, 0x55, 0x8d, 0x56, 0xcb, 0xc3, 0x3b, 0x6b, 0x5f, 0xa3, 0xb5, 0xf2,
-	0xf0, 0x96, 0xea, 0x7b, 0x74, 0xbb, 0xdc, 0xbe, 0xb9, 0xa2, 0x1d, 0xdd, 0x11, 0xa0, 0x42, 0x7c,
-	0x16, 0xcb, 0x6d, 0xb4, 0x2e, 0x24, 0xba, 0x03, 0xcb, 0xb9, 0xf8, 0x2c, 0x3e, 0x65, 0xa2, 0x8d,
-	0x14, 0x78, 0xa5, 0x1c, 0x48, 0xa5, 0xbf, 0x2b, 0x39, 0xed, 0x76, 0xc1, 0x12, 0xb9, 0x56, 0x0d,
-	0xba, 0x27, 0xed, 0x30, 0x2d, 0x1f, 0xb2, 0x6c, 0xfe, 0xad, 0xa5, 0xfa, 0x77, 0x7c, 0xbe, 0x60,
-	0xd1, 0x7c, 0x07, 0x1f, 0xbd, 0x5d, 0x6e, 0x2f, 0xa9, 0x15, 0x8d, 0xfa, 0xe5, 0x99, 0x5b, 0x34,
-	0xa5, 0xd1, 0xfd, 0x72, 0x4b, 0x15, 0x9b, 0x50, 0xe8, 0x9d, 0x74, 0x27, 0x17, 0x3c, 0x2c, 0x77,
-	0x0d, 0xd1, 0xbb, 0xa9, 0x5e, 0xeb, 0x79, 0x7e, 0xc5, 0xae, 0x25, 0xda, 0x4c, 0x35, 0x2c, 0x70,
-	0xcc, 0xf7, 0x21, 0xd1, 0x7b, 0xb3, 0x38, 0x16, 0x9b, 0x87, 0xe8, 0xfd, 0x94, 0xa3, 0x5e, 0xcc,
-	0x6d, 0xd9, 0xbd, 0x08, 0x7d, 0x50, 0x1e, 0xa9, 0xf9, 0x0b, 0x08, 0xfa, 0x50, 0x68, 0x5b, 0xb0,
-	0xab, 0xf4, 0xef, 0x46, 0xe8, 0x9f, 0x05, 0xa3, 0x75, 0xb8, 0x9e, 0x53, 0xf4, 0xcc, 0x43, 0x25,
-	0xfa, 0x48, 0x20, 0x6f, 0xe5, 0x8f, 0xa1, 0xc2, 0xbb, 0x22, 0xfa, 0x17, 0xb1, 0x66, 0x71, 0x0f,
-	0xe5, 0x9a, 0x17, 0xe8, 0x41, 0x7a, 0x4c, 0x2e, 0x97, 0xa1, 0xb2, 0x9c, 0xf8, 0xaf, 0x69, 0x8a,
-	0xb9, 0x52, 0x0e, 0xa4, 0xde, 0xff, 0xb7, 0x72, 0x6e, 0x67, 0x2e, 0x49, 0xe8, 0xe3, 0x19, 0x1b,
-	0x3c, 0x8f, 0xfa, 0xa4, 0x7c, 0xcd, 0xdc, 0x75, 0x05, 0x7d, 0x2a, 0x58, 0x6d, 0xc0, 0x8d, 0x59,
-	0x7a, 0x26, 0x2e, 0xfd, 0x4c, 0x40, 0xef, 0xc1, 0xcd, 0x32, 0x68, 0x7e, 0xcf, 0x6f, 0x09, 0x70,
-	0x1f, 0xd6, 0xca, 0xc0, 0x67, 0xf6, 0xfe, 0x43, 0x21, 0xec, 0xbd, 0xbc, 0xee, 0x67, 0xee, 0x15,
-	0xc8, 0x59, 0x6a, 0x7e, 0x9f, 0x6c, 0xeb, 0x3b, 0x33, 0xc0, 0xc9, 0xc5, 0x02, 0xe1, 0xa5, 0xda,
-	0xf7, 0x25, 0x86, 0xca, 0xdf, 0x35, 0xd0, 0xd1, 0x52, 0xed, 0x87, 0x12, 0x43, 0xe5, 0xaa, 0x65,
-	0x34, 0x14, 0xac, 0x0a, 0xe1, 0x2c, 0x57, 0xd0, 0x68, 0x24, 0x18, 0x15, 0x8c, 0x59, 0x52, 0x13,
-	0x23, 0x57, 0xb0, 0x2b, 0x84, 0x61, 0x01, 0x8a, 0x3c, 0xc1, 0xf1, 0x2e, 0xac, 0x9c, 0x03, 0x63,
-	0x15, 0x2f, 0xf2, 0x05, 0xcb, 0x59, 0xab, 0x67, 0xd5, 0x2b, 0xfa, 0x9a, 0x43, 0x1f, 0xbe, 0x0f,
-	0xab, 0xb6, 0x37, 0xe9, 0x87, 0x56, 0xe4, 0x85, 0x23, 0x32, 0xb6, 0x0e, 0xc3, 0x7e, 0x14, 0xe0,
-	0x97, 0x5e, 0xd0, 0x1f, 0x93, 0x43, 0xfe, 0x6f, 0x7e, 0x87, 0xf1, 0xd1, 0xc3, 0xce, 0x01, 0x23,
-	0x0a, 0xae, 0x7f, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x2a, 0xe4, 0xc0, 0x85, 0x16, 0x28, 0x00, 0x00,
+	proto.RegisterEnum("hw.trezor.messages.MessageType", MessageType_name, MessageType_value)
+	proto.RegisterExtension(E_WireIn)
+	proto.RegisterExtension(E_WireOut)
+	proto.RegisterExtension(E_WireDebugIn)
+	proto.RegisterExtension(E_WireDebugOut)
+	proto.RegisterExtension(E_WireTiny)
+	proto.RegisterExtension(E_WireBootloader)
+	proto.RegisterExtension(E_WireNoFsm)
+}
+
+func init() { proto.RegisterFile("messages.proto", fileDescriptor_4dc296cbfe5ffcd5) }
+
+var fileDescriptor_4dc296cbfe5ffcd5 = []byte{
+	// 2430 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x9a, 0xd9, 0x73, 0x1c, 0xc5,
+	0x1d, 0xc7, 0xb3, 0xab, 0x11, 0x88, 0xf6, 0x41, 0x23, 0xb0, 0x2d, 0xaf, 0x2f, 0xf9, 0xc0, 0x96,
+	0x2f, 0xd9, 0x10, 0x0c, 0x44, 0x38, 0x60, 0x69, 0xb5, 0x12, 0x8a, 0xb5, 0x5a, 0x97, 0x76, 0xb1,
+	0x1f, 0x5d, 0xa3, 0x9d, 0xd6, 0x6e, 0x97, 0x67, 0x67, 0x86, 0x9e, 0x1e, 0x49, 0xeb, 0xa7, 0x9c,
+	0x3c, 0x13, 0x48, 0xc0, 0xb9, 0xa9, 0xa4, 0x2a, 0x21, 0x57, 0x85, 0x1c, 0x4e, 0x25, 0x55, 0x39,
+	0x08, 0x24, 0x2f, 0xc9, 0x43, 0x52, 0x9c, 0x86, 0x40, 0xee, 0x90, 0xe4, 0x0f, 0xc8, 0xc5, 0x91,
+	0xa4, 0x7a, 0xa6, 0xbb, 0xe7, 0xd8, 0xdf, 0xae, 0x36, 0x6f, 0x58, 0xf3, 0xf9, 0x7d, 0x7f, 0x47,
+	0xff, 0xfa, 0x37, 0xdd, 0xb3, 0xa0, 0xcd, 0x2d, 0xe2, 0xfb, 0x66, 0x83, 0xf8, 0xe3, 0x1e, 0x73,
+	0xb9, 0x3b, 0x3c, 0xdc, 0x5c, 0x1d, 0xe7, 0x8c, 0x5c, 0x76, 0xd9, 0xb8, 0x7a, 0x52, 0x18, 0x6d,
+	0xb8, 0x6e, 0xc3, 0x26, 0x27, 0x42, 0x62, 0x29, 0x58, 0x3e, 0x61, 0x11, 0xbf, 0xce, 0xa8, 0xc7,
+	0x5d, 0x16, 0x59, 0x1d, 0xf9, 0xfe, 0x7d, 0x68, 0x43, 0x39, 0xc2, 0x6b, 0x6d, 0x8f, 0x0c, 0x1f,
+	0x40, 0x5b, 0x13, 0xff, 0xbc, 0x38, 0xe7, 0x50, 0x4e, 0x4d, 0x9b, 0x5e, 0x26, 0xf8, 0x5d, 0x85,
+	0xa1, 0x87, 0xaf, 0x8e, 0xe4, 0x9e, 0xba, 0x3a, 0x92, 0x1b, 0x2e, 0x20, 0x9c, 0xa4, 0xce, 0x51,
+	0xa7, 0x81, 0x73, 0x05, 0x43, 0x3c, 0x1f, 0xde, 0x85, 0x6e, 0x4e, 0x3e, 0xab, 0x06, 0xf5, 0x3a,
+	0xf1, 0x7d, 0x9c, 0x2f, 0x18, 0x57, 0x80, 0xc7, 0x33, 0x26, 0xb5, 0x03, 0x46, 0xf0, 0x80, 0x7c,
+	0xbc, 0x07, 0x6d, 0x49, 0x3e, 0x2e, 0x36, 0x4d, 0xa7, 0x41, 0xce, 0x51, 0x07, 0x1b, 0x52, 0x7e,
+	0x34, 0x1d, 0xe0, 0x05, 0xea, 0x91, 0x69, 0xb2, 0x42, 0xeb, 0x04, 0x0f, 0xc2, 0xc4, 0x2c, 0xe1,
+	0x25, 0x87, 0x33, 0xd7, 0x6b, 0xe3, 0x1b, 0xe0, 0x10, 0xd5, 0x63, 0x24, 0x63, 0xc8, 0x08, 0xcc,
+	0xbb, 0xa6, 0x25, 0x5d, 0x6c, 0x92, 0x02, 0x7b, 0xd1, 0xb6, 0x24, 0xb1, 0x48, 0x7c, 0xc2, 0x25,
+	0xb2, 0x59, 0x22, 0xbb, 0xd1, 0x2d, 0xa9, 0x3c, 0x89, 0xc9, 0x03, 0x46, 0x7c, 0x7c, 0x93, 0x74,
+	0x72, 0x10, 0xed, 0xcc, 0x94, 0xb0, 0x6c, 0x72, 0x46, 0xd7, 0x16, 0xc9, 0x83, 0x01, 0xf1, 0x39,
+	0x1e, 0x96, 0xdc, 0x11, 0x34, 0x02, 0x72, 0x93, 0xf5, 0x4b, 0xf8, 0xe6, 0xc2, 0x46, 0xb5, 0x24,
+	0x4f, 0x47, 0x81, 0x0f, 0xa7, 0x8a, 0x67, 0x3a, 0x75, 0x62, 0xe3, 0x5b, 0x12, 0x0b, 0xb7, 0x2f,
+	0xad, 0x56, 0xb4, 0x89, 0xc9, 0xaa, 0xc4, 0xf7, 0xa9, 0xeb, 0xe0, 0x11, 0x19, 0xf9, 0x7e, 0xb4,
+	0x3d, 0xc9, 0x4c, 0x7a, 0x9e, 0xdd, 0xae, 0x12, 0xce, 0xa9, 0xd3, 0xf0, 0xf1, 0x76, 0x18, 0x9a,
+	0x0a, 0x38, 0x77, 0x1d, 0x15, 0x7b, 0x41, 0xc6, 0x7e, 0x28, 0xbd, 0x98, 0x11, 0x24, 0x02, 0xdf,
+	0xd1, 0x11, 0xf8, 0xd6, 0x0e, 0x97, 0x33, 0xb6, 0xd9, 0xf0, 0xf1, 0x4e, 0xe9, 0x2f, 0x13, 0xf8,
+	0x94, 0x59, 0xbf, 0x14, 0x78, 0xb2, 0xe4, 0xfb, 0x24, 0x73, 0x00, 0x15, 0x80, 0x65, 0x55, 0x41,
+	0xed, 0x87, 0x57, 0x57, 0x52, 0x22, 0xaa, 0x03, 0x52, 0xe7, 0x10, 0xda, 0x95, 0x2a, 0xb9, 0xe9,
+	0xfb, 0x5e, 0x93, 0x99, 0x3e, 0x51, 0x52, 0x87, 0xa5, 0xd4, 0xd1, 0x74, 0x11, 0x62, 0x50, 0xa8,
+	0x1d, 0xc9, 0xe4, 0x78, 0x0c, 0xed, 0x83, 0xe1, 0x2a, 0x37, 0xb9, 0x96, 0x2e, 0x4b, 0xe9, 0x93,
+	0x68, 0x77, 0x0f, 0x5a, 0xe8, 0x2f, 0x64, 0xf4, 0x33, 0xd9, 0x2f, 0x92, 0xba, 0xbb, 0x42, 0x58,
+	0x5b, 0xd6, 0xe8, 0x38, 0xdc, 0xb9, 0x17, 0x5c, 0x66, 0x29, 0xd7, 0xe3, 0xf0, 0x0e, 0x15, 0x88,
+	0xf0, 0x77, 0x02, 0x56, 0x98, 0x25, 0x5c, 0xf7, 0xf6, 0x5d, 0x70, 0x73, 0x54, 0x09, 0x7f, 0xe0,
+	0xf6, 0x99, 0xa2, 0x1b, 0x38, 0x9c, 0x30, 0x7c, 0x9f, 0xae, 0x72, 0x0a, 0x9a, 0xa1, 0xac, 0xb5,
+	0x6a, 0x32, 0x52, 0x12, 0x49, 0xe2, 0xeb, 0xa2, 0x9e, 0xfd, 0x9e, 0x00, 0xc7, 0xd2, 0x89, 0x29,
+	0xf0, 0x01, 0xcf, 0x76, 0x4d, 0x0b, 0x5f, 0x9f, 0x20, 0x0f, 0xa3, 0x1d, 0x10, 0xa9, 0x12, 0x1c,
+	0x2a, 0x0c, 0x5d, 0x51, 0xe8, 0xbe, 0xf4, 0xf6, 0xac, 0x12, 0x7b, 0xb9, 0x26, 0x98, 0xd1, 0x84,
+	0x5c, 0xa6, 0xe7, 0x66, 0x09, 0x3f, 0x17, 0x2c, 0xd9, 0xb4, 0x7e, 0x96, 0xb4, 0xf1, 0x06, 0x99,
+	0x45, 0x66, 0x5e, 0xc5, 0xc0, 0x46, 0x59, 0xcd, 0x9d, 0xe9, 0x3d, 0x59, 0xa5, 0x0d, 0xa7, 0xb6,
+	0x86, 0x6f, 0x84, 0xcd, 0x6b, 0x7a, 0xfb, 0x6f, 0x91, 0xe6, 0x3b, 0xd0, 0x4d, 0x69, 0x40, 0x2c,
+	0xc5, 0xd6, 0xae, 0x93, 0x6e, 0xd2, 0xb2, 0x98, 0x98, 0xb6, 0xbb, 0xe0, 0x49, 0xa7, 0x1e, 0xef,
+	0x96, 0xea, 0x99, 0xb5, 0x14, 0xc1, 0xc9, 0x7f, 0xe3, 0x83, 0xf0, 0x5a, 0x9e, 0x27, 0x8c, 0x2e,
+	0xb7, 0x15, 0x74, 0x48, 0x42, 0x99, 0x61, 0x26, 0xff, 0x5b, 0xc8, 0x85, 0x9d, 0x81, 0xc7, 0xa4,
+	0xbf, 0x4c, 0x8f, 0x16, 0xa9, 0xd7, 0x24, 0xec, 0x2c, 0x69, 0x9f, 0x37, 0xed, 0x80, 0xe0, 0x6d,
+	0xb0, 0x5a, 0x44, 0x11, 0x4b, 0x73, 0x27, 0xa5, 0x5a, 0x66, 0x7d, 0x84, 0xbb, 0x39, 0x8b, 0x38,
+	0x9c, 0xf2, 0x36, 0x3e, 0x05, 0xcf, 0x04, 0xc1, 0x10, 0x4b, 0x53, 0x77, 0xea, 0x41, 0xb5, 0x2b,
+	0xfb, 0xca, 0x28, 0x4e, 0xdf, 0x2f, 0x07, 0xa3, 0x58, 0xcd, 0xf7, 0x76, 0x19, 0x31, 0x69, 0xea,
+	0x5e, 0x78, 0xc4, 0x14, 0x5d, 0x9f, 0x16, 0xdd, 0x56, 0x8b, 0x72, 0x3c, 0x0b, 0xeb, 0xc4, 0x44,
+	0x8b, 0x38, 0x1c, 0xdf, 0x2f, 0x75, 0x32, 0xef, 0x10, 0x41, 0x89, 0x04, 0xf0, 0x1c, 0xbc, 0x36,
+	0xea, 0x79, 0x54, 0xf3, 0xf7, 0x49, 0x91, 0x13, 0xe9, 0xdc, 0xa6, 0xc9, 0x52, 0xd0, 0x98, 0xa7,
+	0xce, 0xa5, 0x69, 0x52, 0xa7, 0xe1, 0xdc, 0xb7, 0x0a, 0x1b, 0x9f, 0x48, 0x0e, 0x92, 0xa3, 0x5d,
+	0x0c, 0x66, 0x09, 0x0f, 0x87, 0x0f, 0x26, 0x85, 0x21, 0x65, 0x90, 0x4d, 0x44, 0xc3, 0x11, 0xb9,
+	0x5c, 0x30, 0x9e, 0x04, 0x02, 0x4d, 0x50, 0xae, 0x87, 0x1b, 0x05, 0xe3, 0x09, 0x60, 0x39, 0x35,
+	0x34, 0xef, 0x36, 0x70, 0x53, 0x0a, 0x1d, 0x46, 0x7b, 0x40, 0xa6, 0x4c, 0x5a, 0x2e, 0x6b, 0x2f,
+	0x12, 0xd3, 0xc2, 0x8e, 0x94, 0xbb, 0x35, 0x3d, 0x0c, 0x32, 0x28, 0x76, 0xa5, 0xe2, 0x11, 0x34,
+	0xda, 0x03, 0xbb, 0xc0, 0x28, 0x27, 0xd8, 0x93, 0x92, 0xdd, 0xbc, 0xcf, 0xd8, 0xa6, 0xdf, 0x8c,
+	0x06, 0xd7, 0x83, 0x12, 0x3d, 0x9a, 0x96, 0x2d, 0x71, 0xd1, 0xc2, 0x41, 0x2b, 0x35, 0x43, 0x9e,
+	0x19, 0x90, 0xeb, 0x38, 0x96, 0xae, 0xb8, 0x82, 0x63, 0xf2, 0x59, 0x75, 0x3c, 0x1a, 0x4b, 0xbf,
+	0x16, 0x12, 0xb2, 0x6a, 0x6b, 0xdf, 0x2d, 0x35, 0x33, 0xe9, 0x2b, 0x52, 0x61, 0xef, 0x81, 0x77,
+	0xa4, 0xc2, 0xe4, 0x98, 0x9a, 0x80, 0xdf, 0x88, 0x8a, 0x8a, 0xc7, 0xd5, 0x3d, 0x52, 0x2e, 0xb3,
+	0xd0, 0x31, 0x28, 0xc6, 0xd6, 0x69, 0xa9, 0x96, 0x29, 0x63, 0xd2, 0xa7, 0x1a, 0x2c, 0x67, 0x24,
+	0x7a, 0x14, 0xed, 0x85, 0xd0, 0xf4, 0x14, 0x9a, 0x94, 0xf0, 0x38, 0x3a, 0x00, 0xc1, 0x1d, 0xd3,
+	0x68, 0x0a, 0x0e, 0x76, 0xa1, 0x54, 0x4e, 0xd4, 0xb1, 0x08, 0xcf, 0xd8, 0x85, 0x52, 0x59, 0x11,
+	0xd3, 0xf0, 0x91, 0x75, 0xa1, 0x54, 0x96, 0xd5, 0x2b, 0xc1, 0x6f, 0x4c, 0x09, 0x10, 0xab, 0xb6,
+	0x86, 0x67, 0xe0, 0x01, 0xb4, 0x50, 0x2a, 0x4f, 0x93, 0x3a, 0x6b, 0x7b, 0x5c, 0xe5, 0x78, 0x16,
+	0xae, 0x5d, 0x0c, 0x12, 0x4b, 0xa1, 0xf3, 0xf0, 0xd2, 0xce, 0x53, 0xff, 0x52, 0x22, 0x3f, 0x06,
+	0x07, 0x27, 0x28, 0x85, 0xf8, 0x5d, 0xce, 0xc3, 0xd4, 0xbf, 0x24, 0x33, 0xe4, 0xf0, 0xe9, 0x4c,
+	0x11, 0x61, 0x8a, 0x81, 0x54, 0xc9, 0x34, 0xa4, 0x62, 0x54, 0xd4, 0x2b, 0x52, 0x2a, 0xb3, 0x1f,
+	0x05, 0xd6, 0xb1, 0x80, 0xab, 0x70, 0xd5, 0x04, 0x9b, 0xee, 0x8c, 0x35, 0xf8, 0x8d, 0x22, 0x4b,
+	0x11, 0xef, 0xaf, 0x36, 0x3c, 0x50, 0x05, 0x17, 0x43, 0x97, 0xf5, 0xc9, 0x3d, 0x95, 0x48, 0x8d,
+	0x5c, 0x76, 0xfd, 0x44, 0x61, 0x1f, 0xcb, 0x69, 0xb1, 0x91, 0x0e, 0x4e, 0x41, 0x8f, 0xe7, 0xf4,
+	0x3b, 0x6c, 0x5b, 0x07, 0x24, 0x8b, 0x7b, 0x25, 0xa7, 0x5f, 0x16, 0xdb, 0x41, 0x26, 0x2c, 0xef,
+	0x27, 0x72, 0x7a, 0x34, 0xec, 0x82, 0xc2, 0x8a, 0xe3, 0xff, 0x64, 0x4e, 0x8f, 0x86, 0x42, 0x07,
+	0x19, 0x63, 0x9f, 0xca, 0xe9, 0xfe, 0x49, 0x9f, 0xe2, 0x38, 0xb1, 0x6d, 0x93, 0xc9, 0xe0, 0x7e,
+	0x9e, 0xd3, 0x0d, 0xb9, 0x1b, 0xa0, 0x6a, 0x6b, 0x15, 0x4f, 0xcd, 0x86, 0x5f, 0x74, 0x89, 0x50,
+	0xa2, 0x89, 0xd2, 0xfd, 0xb2, 0x4b, 0x84, 0x92, 0x54, 0xd8, 0xaf, 0x94, 0xe0, 0xf1, 0xf4, 0x91,
+	0x5a, 0x62, 0x45, 0x46, 0xc2, 0x23, 0x72, 0x5d, 0x1c, 0x38, 0x2b, 0x1e, 0x7e, 0x2e, 0xa7, 0xa7,
+	0xd8, 0x4e, 0x00, 0x3f, 0x67, 0xb6, 0xc5, 0x4b, 0xb7, 0xe2, 0xe1, 0xe7, 0x73, 0x7a, 0xea, 0x8c,
+	0x82, 0x20, 0x6f, 0xc6, 0xf0, 0x0b, 0xbd, 0xe1, 0xb2, 0xe9, 0x98, 0x0d, 0x52, 0x59, 0x5e, 0x26,
+	0xac, 0xe2, 0xe1, 0x17, 0x15, 0x7c, 0x3b, 0x3a, 0xd4, 0x35, 0x62, 0x71, 0xc6, 0xa7, 0x2b, 0xda,
+	0xe6, 0xa5, 0x9c, 0xde, 0x11, 0x7b, 0xa0, 0x75, 0x20, 0xbc, 0xe2, 0x71, 0xea, 0x3a, 0x7e, 0xc5,
+	0xc3, 0x2f, 0xf7, 0x0e, 0x26, 0xba, 0x45, 0xd7, 0x58, 0xe0, 0x8b, 0xc8, 0xaf, 0xf5, 0x16, 0x9e,
+	0xb4, 0x6d, 0x77, 0x55, 0xb1, 0xaf, 0x28, 0xf6, 0x58, 0x7a, 0x10, 0x2b, 0x36, 0x2a, 0x72, 0x99,
+	0xb0, 0x06, 0xa9, 0x78, 0xf8, 0xd5, 0xde, 0xca, 0x51, 0x4d, 0xa6, 0x4d, 0x6e, 0x56, 0x3c, 0xfc,
+	0x5a, 0x6f, 0xe5, 0xa9, 0xa0, 0xe5, 0x55, 0x45, 0x03, 0x39, 0x75, 0xa1, 0xfc, 0x7a, 0x4e, 0xef,
+	0xe4, 0x1d, 0x5d, 0x9a, 0x32, 0xdc, 0x0d, 0x6f, 0xe4, 0xf4, 0xb4, 0x49, 0xf7, 0x38, 0x73, 0x9d,
+	0x44, 0xa3, 0xbd, 0x99, 0xd3, 0x83, 0x6b, 0x5b, 0x16, 0x53, 0xcc, 0x5b, 0x39, 0x7d, 0x48, 0xde,
+	0x9a, 0x65, 0xe4, 0x26, 0x78, 0xbb, 0xdb, 0x56, 0x97, 0x48, 0x18, 0xd2, 0x3b, 0x5d, 0xf6, 0x53,
+	0xd1, 0x64, 0x96, 0xe9, 0xb8, 0x52, 0xea, 0x1b, 0x79, 0xb8, 0x49, 0x25, 0x15, 0xbf, 0x69, 0x9f,
+	0xca, 0xeb, 0x0f, 0x03, 0x7b, 0x00, 0x30, 0xb5, 0xe3, 0xbf, 0xd9, 0x5b, 0x34, 0x06, 0xbf, 0x95,
+	0x87, 0xb7, 0x68, 0x2c, 0xaa, 0xaa, 0xf2, 0xed, 0x3c, 0xbc, 0x45, 0x25, 0xa9, 0xb0, 0xef, 0xe4,
+	0xf5, 0x3b, 0x76, 0x04, 0x4c, 0x47, 0x9c, 0x07, 0xae, 0xe6, 0xe1, 0x45, 0x4d, 0x54, 0x26, 0xac,
+	0xe0, 0x77, 0x95, 0x58, 0x66, 0xd6, 0x54, 0x1c, 0xee, 0xda, 0x6e, 0xa3, 0x9d, 0x08, 0xef, 0x37,
+	0x5d, 0x24, 0x15, 0xaa, 0xb8, 0xdf, 0xe6, 0xf5, 0x15, 0x7e, 0xb4, 0x8b, 0x64, 0x5c, 0x9d, 0xdf,
+	0xe5, 0xe1, 0x73, 0x9a, 0x82, 0x63, 0xf2, 0xf7, 0xeb, 0xc8, 0x86, 0x8b, 0xcd, 0x4c, 0xc7, 0x5f,
+	0x26, 0x0c, 0xff, 0x41, 0xc9, 0x66, 0xc6, 0x58, 0x12, 0x26, 0x96, 0xc6, 0xff, 0xa8, 0xb4, 0xc7,
+	0xd1, 0xfe, 0x6e, 0xf8, 0x05, 0xca, 0x9b, 0x16, 0x33, 0x57, 0x2b, 0x4e, 0x03, 0xff, 0x49, 0xc9,
+	0x9f, 0x44, 0xb7, 0x76, 0x97, 0x4f, 0x5a, 0xfc, 0x39, 0xaf, 0x3f, 0x3e, 0x74, 0xb5, 0xa8, 0x38,
+	0x7c, 0xce, 0x5a, 0x24, 0x0d, 0xea, 0x8b, 0xbb, 0xfc, 0x1b, 0x79, 0x78, 0xae, 0xa5, 0x7d, 0xa4,
+	0x6d, 0xfe, 0xa2, 0xbc, 0x9c, 0x42, 0x47, 0x7a, 0x7a, 0x99, 0xb4, 0xac, 0x49, 0xce, 0x19, 0x5d,
+	0x0a, 0x38, 0xf1, 0xf1, 0x5f, 0x95, 0xab, 0xbb, 0xd0, 0xb1, 0x75, 0x5c, 0xa5, 0x0d, 0xff, 0x96,
+	0xd7, 0xa7, 0x85, 0xd4, 0x26, 0x58, 0xa4, 0x9e, 0x67, 0x93, 0x44, 0xef, 0x3c, 0x3c, 0x00, 0xbf,
+	0x6f, 0x23, 0x50, 0x51, 0x1f, 0x1d, 0x80, 0x3b, 0x3b, 0xa2, 0xe4, 0x6e, 0x7e, 0x64, 0x00, 0xde,
+	0x25, 0x31, 0x14, 0x36, 0xf6, 0xa3, 0x0a, 0x7b, 0x37, 0x1a, 0x4b, 0xdd, 0x9f, 0x5d, 0x87, 0x30,
+	0x37, 0x5c, 0x79, 0xb3, 0x2e, 0x66, 0xfc, 0x9c, 0x43, 0xb9, 0x1a, 0x00, 0x7f, 0x1f, 0xd0, 0x17,
+	0xbb, 0x03, 0xeb, 0x1a, 0x89, 0x6d, 0xf6, 0x0f, 0x65, 0x90, 0xa9, 0x5c, 0x87, 0x41, 0x95, 0xf0,
+	0x39, 0xc7, 0x0b, 0xb4, 0xa7, 0x7f, 0x2a, 0xc3, 0xf5, 0xc2, 0x53, 0x86, 0xc2, 0xdb, 0xbf, 0x94,
+	0xd1, 0x19, 0x74, 0x6a, 0x9d, 0xf0, 0xbc, 0x80, 0xfb, 0xe7, 0x08, 0x6b, 0x05, 0xdc, 0x14, 0x7f,
+	0x50, 0x6e, 0xff, 0xad, 0x14, 0x4e, 0xa3, 0xdb, 0xfe, 0x3f, 0x05, 0xe1, 0xff, 0x4d, 0x65, 0x7d,
+	0x37, 0x3a, 0xbe, 0xbe, 0xf5, 0x79, 0xea, 0x50, 0xe5, 0xf7, 0x2d, 0x65, 0x79, 0x07, 0x3a, 0xdc,
+	0x9f, 0xa5, 0xf0, 0xf7, 0xb6, 0xb2, 0xba, 0x07, 0x9d, 0xec, 0x69, 0x35, 0x69, 0xdb, 0x51, 0xc0,
+	0x55, 0xa2, 0x2b, 0xfc, 0x4e, 0xbf, 0x4b, 0x93, 0x34, 0x16, 0x5e, 0xff, 0xd3, 0x6f, 0x96, 0xe2,
+	0x98, 0x10, 0xf0, 0xc4, 0xa2, 0xfe, 0xb7, 0xdf, 0x2c, 0xb5, 0xa5, 0xf0, 0xf7, 0x7e, 0xa3, 0x4f,
+	0x7f, 0x93, 0xb6, 0x5d, 0x09, 0x78, 0x22, 0xc5, 0x0f, 0x18, 0x7d, 0xfa, 0xd3, 0x96, 0xc2, 0xdf,
+	0x07, 0xfb, 0xf5, 0x17, 0x7e, 0xf4, 0x49, 0x36, 0xed, 0x87, 0xfa, 0xf5, 0xa7, 0x2d, 0x85, 0xbf,
+	0x0f, 0xf7, 0x6b, 0x35, 0x43, 0x1d, 0xd3, 0x56, 0xbe, 0x3e, 0x62, 0xc0, 0x03, 0x13, 0xb6, 0x12,
+	0x7e, 0x1e, 0x52, 0x16, 0x77, 0xa2, 0xa3, 0x9d, 0x16, 0x67, 0x49, 0x7b, 0xae, 0x65, 0x36, 0x48,
+	0x69, 0xcd, 0x73, 0x19, 0x4f, 0x6e, 0xfa, 0x47, 0x94, 0x5d, 0x66, 0xd0, 0x76, 0xb3, 0x13, 0xbe,
+	0x1e, 0xed, 0x99, 0x93, 0xb2, 0xa9, 0xb6, 0x9d, 0x7a, 0x95, 0x13, 0x7d, 0x5a, 0xff, 0x58, 0xcf,
+	0x9c, 0xb2, 0x56, 0xc2, 0xcf, 0xc7, 0x0d, 0x78, 0xa0, 0x77, 0x5a, 0xa4, 0x8a, 0xf7, 0x98, 0x32,
+	0xbb, 0x0d, 0x1d, 0xec, 0xc3, 0x4c, 0x78, 0x7a, 0xdc, 0x80, 0x47, 0x79, 0x64, 0x92, 0x18, 0xe5,
+	0x9f, 0x36, 0xe0, 0x51, 0x1e, 0x81, 0x8a, 0xfa, 0x8c, 0x01, 0x9f, 0x7a, 0xb4, 0xdc, 0x05, 0x93,
+	0xd7, 0x9b, 0xe2, 0xbd, 0xfe, 0x59, 0x03, 0x9e, 0xe7, 0x11, 0xa9, 0xb1, 0xcf, 0x19, 0xf0, 0xc5,
+	0x24, 0xfc, 0x50, 0x14, 0xb1, 0xd3, 0xd4, 0x6c, 0xa8, 0x0a, 0x7c, 0xde, 0x80, 0xef, 0x50, 0x19,
+	0x5c, 0x64, 0xfe, 0x05, 0xa5, 0x9c, 0x39, 0x2d, 0xeb, 0x50, 0x6b, 0x6b, 0x67, 0x89, 0xfe, 0xa9,
+	0xe3, 0x8b, 0x06, 0x7c, 0x60, 0x49, 0xd3, 0x42, 0xf7, 0x4b, 0x3d, 0x7b, 0x64, 0x9e, 0xae, 0x90,
+	0x45, 0xb2, 0xcc, 0x88, 0xdf, 0xac, 0x72, 0x93, 0xe9, 0x6e, 0x7c, 0xd2, 0x80, 0x8f, 0x16, 0xb0,
+	0x95, 0xf0, 0xf3, 0x65, 0xa3, 0xd7, 0xab, 0x24, 0x65, 0x11, 0xb7, 0xe2, 0x57, 0x94, 0x1b, 0xf0,
+	0x4d, 0x97, 0x31, 0x12, 0x5e, 0xbe, 0xda, 0x6f, 0x36, 0xa9, 0x46, 0xfc, 0x5a, 0xbf, 0xd9, 0xe8,
+	0x3e, 0xfc, 0xba, 0x01, 0x7f, 0x0a, 0x28, 0x65, 0x6e, 0xdc, 0xd7, 0x0c, 0xf8, 0x7e, 0x50, 0x4a,
+	0xde, 0xb7, 0x5f, 0x31, 0xf4, 0x67, 0x96, 0x2d, 0x19, 0x48, 0x9e, 0x26, 0x5e, 0xed, 0xd2, 0x27,
+	0x25, 0xd7, 0x17, 0x07, 0xe9, 0xe4, 0xbb, 0xf3, 0xd7, 0x06, 0x7c, 0xff, 0x49, 0xa0, 0x22, 0x81,
+	0xd7, 0x0c, 0xf8, 0xfe, 0x53, 0x4a, 0x7c, 0x58, 0x78, 0xbd, 0xcb, 0xee, 0x98, 0xa2, 0x8e, 0xe9,
+	0xd4, 0x93, 0x07, 0xa7, 0x1f, 0x0c, 0xc2, 0xbb, 0x43, 0x92, 0x0a, 0xfb, 0xe1, 0x20, 0x7c, 0x73,
+	0x89, 0x05, 0xe3, 0xa2, 0xfc, 0x68, 0x10, 0xbe, 0xb9, 0x48, 0x36, 0x06, 0x7f, 0x3c, 0x08, 0xdf,
+	0xae, 0x24, 0x28, 0x2b, 0xf8, 0x74, 0x6f, 0xb9, 0xf8, 0x76, 0xf5, 0x93, 0x41, 0xf8, 0xaa, 0xa1,
+	0x40, 0x79, 0x18, 0x2f, 0xfb, 0x0d, 0xfc, 0xcc, 0x20, 0x7c, 0xd5, 0x90, 0x68, 0x85, 0x59, 0x11,
+	0xf7, 0x6c, 0x6f, 0xdf, 0xd1, 0x8f, 0xb4, 0x02, 0xfc, 0x69, 0x6f, 0x41, 0xbd, 0x30, 0x3f, 0x93,
+	0x31, 0x4e, 0x9c, 0x46, 0xd7, 0xaf, 0x52, 0x46, 0x2e, 0x52, 0x67, 0x78, 0xef, 0x78, 0xf4, 0x4b,
+	0xff, 0xb8, 0xfa, 0xa5, 0x7f, 0xbc, 0xe4, 0x04, 0xad, 0xf0, 0xe7, 0x12, 0xf9, 0x95, 0x60, 0xe4,
+	0xb9, 0x87, 0x06, 0x46, 0x73, 0x63, 0x43, 0x8b, 0xd7, 0x09, 0x9b, 0x39, 0x67, 0xe2, 0x5e, 0x34,
+	0x14, 0x5a, 0xbb, 0x01, 0xef, 0xc7, 0xfc, 0x79, 0x69, 0x1e, 0xba, 0xac, 0x04, 0x7c, 0x62, 0x16,
+	0x6d, 0x0a, 0xed, 0x2d, 0x31, 0xad, 0xfa, 0x8c, 0xe1, 0x05, 0x29, 0xb2, 0x41, 0x58, 0x86, 0x63,
+	0x6e, 0xce, 0x99, 0x98, 0x43, 0x9b, 0x13, 0x42, 0x7d, 0x86, 0xf3, 0xa2, 0x54, 0xda, 0xa8, 0x95,
+	0x44, 0x4c, 0x67, 0xd0, 0x0d, 0xa1, 0x14, 0xa7, 0x4e, 0xbb, 0x1f, 0x95, 0x97, 0xa4, 0x4a, 0x58,
+	0x89, 0x1a, 0x75, 0xda, 0x13, 0xf3, 0xe8, 0xc6, 0x50, 0x61, 0xc9, 0x75, 0xb9, 0xed, 0x9a, 0x16,
+	0x61, 0xfd, 0xe8, 0xbc, 0x2c, 0x75, 0xc2, 0x44, 0xa6, 0xb4, 0xe9, 0x44, 0x11, 0x85, 0x99, 0x5e,
+	0x74, 0xdc, 0x8b, 0xcb, 0x7e, 0xab, 0x1f, 0xa5, 0x6b, 0x52, 0x29, 0xcc, 0x63, 0xc1, 0x9d, 0xf1,
+	0x5b, 0x53, 0x77, 0xa0, 0xfd, 0x75, 0xb7, 0x35, 0xee, 0x9b, 0xdc, 0xf5, 0x9b, 0xd4, 0x36, 0x97,
+	0x7c, 0xf5, 0xff, 0x79, 0xd8, 0x74, 0x49, 0x4b, 0x4d, 0x6d, 0xaa, 0x85, 0x7f, 0x94, 0x9d, 0xf3,
+	0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa3, 0x69, 0x67, 0x5d, 0x1f, 0x22, 0x00, 0x00,
 }

+ 242 - 883
accounts/usbwallet/trezor/messages.proto

@@ -1,8 +1,9 @@
 // This file originates from the SatoshiLabs Trezor `common` repository at:
 //   https://github.com/trezor/trezor-common/blob/master/protob/messages.proto
-// dated 28.07.2017, commit dd8ec3231fb5f7992360aff9bdfe30bb58130f4b.
+// dated 28.05.2019, commit 893fd219d4a01bcffa0cd9cfa631856371ec5aa9.
 
 syntax = "proto2";
+package hw.trezor.messages;
 
 /**
  * Messages for TREZOR communication
@@ -12,894 +13,252 @@ syntax = "proto2";
 option java_package = "com.satoshilabs.trezor.lib.protobuf";
 option java_outer_classname = "TrezorMessage";
 
-import "types.proto";
+import "google/protobuf/descriptor.proto";
 
 /**
- * Mapping between Trezor wire identifier (uint) and a protobuf message
+ * Options for specifying message direction and type of wire (normal/debug)
  */
-enum MessageType {
-	MessageType_Initialize = 0 [(wire_in) = true];
-	MessageType_Ping = 1 [(wire_in) = true];
-	MessageType_Success = 2 [(wire_out) = true];
-	MessageType_Failure = 3 [(wire_out) = true];
-	MessageType_ChangePin = 4 [(wire_in) = true];
-	MessageType_WipeDevice = 5 [(wire_in) = true];
-	MessageType_FirmwareErase = 6 [(wire_in) = true, (wire_bootloader) = true];
-	MessageType_FirmwareUpload = 7 [(wire_in) = true, (wire_bootloader) = true];
-	MessageType_FirmwareRequest = 8 [(wire_out) = true, (wire_bootloader) = true];
-	MessageType_GetEntropy = 9 [(wire_in) = true];
-	MessageType_Entropy = 10 [(wire_out) = true];
-	MessageType_GetPublicKey = 11 [(wire_in) = true];
-	MessageType_PublicKey = 12 [(wire_out) = true];
-	MessageType_LoadDevice = 13 [(wire_in) = true];
-	MessageType_ResetDevice = 14 [(wire_in) = true];
-	MessageType_SignTx = 15 [(wire_in) = true];
-	MessageType_SimpleSignTx = 16 [(wire_in) = true, deprecated = true];
-	MessageType_Features = 17 [(wire_out) = true];
-	MessageType_PinMatrixRequest = 18 [(wire_out) = true];
-	MessageType_PinMatrixAck = 19 [(wire_in) = true, (wire_tiny) = true];
-	MessageType_Cancel = 20 [(wire_in) = true];
-	MessageType_TxRequest = 21 [(wire_out) = true];
-	MessageType_TxAck = 22 [(wire_in) = true];
-	MessageType_CipherKeyValue = 23 [(wire_in) = true];
-	MessageType_ClearSession = 24 [(wire_in) = true];
-	MessageType_ApplySettings = 25 [(wire_in) = true];
-	MessageType_ButtonRequest = 26 [(wire_out) = true];
-	MessageType_ButtonAck = 27 [(wire_in) = true, (wire_tiny) = true];
-	MessageType_ApplyFlags = 28 [(wire_in) = true];
-	MessageType_GetAddress = 29 [(wire_in) = true];
-	MessageType_Address = 30 [(wire_out) = true];
-	MessageType_SelfTest = 32 [(wire_in) = true, (wire_bootloader) = true];
-	MessageType_BackupDevice = 34 [(wire_in) = true];
-	MessageType_EntropyRequest = 35 [(wire_out) = true];
-	MessageType_EntropyAck = 36 [(wire_in) = true];
-	MessageType_SignMessage = 38 [(wire_in) = true];
-	MessageType_VerifyMessage = 39 [(wire_in) = true];
-	MessageType_MessageSignature = 40 [(wire_out) = true];
-	MessageType_PassphraseRequest = 41 [(wire_out) = true];
-	MessageType_PassphraseAck = 42 [(wire_in) = true, (wire_tiny) = true];
-	MessageType_EstimateTxSize = 43 [(wire_in) = true, deprecated = true];
-	MessageType_TxSize = 44 [(wire_out) = true, deprecated = true];
-	MessageType_RecoveryDevice = 45 [(wire_in) = true];
-	MessageType_WordRequest = 46 [(wire_out) = true];
-	MessageType_WordAck = 47 [(wire_in) = true];
-	MessageType_CipheredKeyValue = 48 [(wire_out) = true];
-	MessageType_EncryptMessage = 49 [(wire_in) = true, deprecated = true];
-	MessageType_EncryptedMessage = 50 [(wire_out) = true, deprecated = true];
-	MessageType_DecryptMessage = 51 [(wire_in) = true, deprecated = true];
-	MessageType_DecryptedMessage = 52 [(wire_out) = true, deprecated = true];
-	MessageType_SignIdentity = 53 [(wire_in) = true];
-	MessageType_SignedIdentity = 54 [(wire_out) = true];
-	MessageType_GetFeatures = 55 [(wire_in) = true];
-	MessageType_EthereumGetAddress = 56 [(wire_in) = true];
-	MessageType_EthereumAddress = 57 [(wire_out) = true];
-	MessageType_EthereumSignTx = 58 [(wire_in) = true];
-	MessageType_EthereumTxRequest = 59 [(wire_out) = true];
-	MessageType_EthereumTxAck = 60 [(wire_in) = true];
-	MessageType_GetECDHSessionKey = 61 [(wire_in) = true];
-	MessageType_ECDHSessionKey = 62 [(wire_out) = true];
-	MessageType_SetU2FCounter = 63 [(wire_in) = true];
-	MessageType_EthereumSignMessage = 64 [(wire_in) = true];
-	MessageType_EthereumVerifyMessage = 65 [(wire_in) = true];
-	MessageType_EthereumMessageSignature = 66 [(wire_out) = true];
-	MessageType_DebugLinkDecision = 100 [(wire_debug_in) = true, (wire_tiny) = true];
-	MessageType_DebugLinkGetState = 101 [(wire_debug_in) = true];
-	MessageType_DebugLinkState = 102 [(wire_debug_out) = true];
-	MessageType_DebugLinkStop = 103 [(wire_debug_in) = true];
-	MessageType_DebugLinkLog = 104 [(wire_debug_out) = true];
-	MessageType_DebugLinkMemoryRead = 110 [(wire_debug_in) = true];
-	MessageType_DebugLinkMemory = 111 [(wire_debug_out) = true];
-	MessageType_DebugLinkMemoryWrite = 112 [(wire_debug_in) = true];
-	MessageType_DebugLinkFlashErase = 113 [(wire_debug_in) = true];
-}
-
-////////////////////
-// Basic messages //
-////////////////////
-
-/**
- * Request: Reset device to default state and ask for device details
- * @next Features
- */
-message Initialize {
-}
-
-/**
- * Request: Ask for device details (no device reset)
- * @next Features
- */
-message GetFeatures {
-}
-
-/**
- * Response: Reports various information about the device
- * @prev Initialize
- * @prev GetFeatures
- */
-message Features {
-	optional string vendor = 1;			// name of the manufacturer, e.g. "bitcointrezor.com"
-	optional uint32 major_version = 2;		// major version of the device, e.g. 1
-	optional uint32 minor_version = 3;		// minor version of the device, e.g. 0
-	optional uint32 patch_version = 4;		// patch version of the device, e.g. 0
-	optional bool bootloader_mode = 5;		// is device in bootloader mode?
-	optional string device_id = 6;			// device's unique identifier
-	optional bool pin_protection = 7;		// is device protected by PIN?
-	optional bool passphrase_protection = 8;	// is node/mnemonic encrypted using passphrase?
-	optional string language = 9;			// device language
-	optional string label = 10;			// device description label
-	repeated CoinType coins = 11;			// supported coins
-	optional bool initialized = 12;			// does device contain seed?
-	optional bytes revision = 13;			// SCM revision of firmware
-	optional bytes bootloader_hash = 14;		// hash of the bootloader
-	optional bool imported = 15;			// was storage imported from an external source?
-	optional bool pin_cached = 16;			// is PIN already cached in session?
-	optional bool passphrase_cached = 17;		// is passphrase already cached in session?
-	optional bool firmware_present = 18;		// is valid firmware loaded?
-	optional bool needs_backup = 19;		// does storage need backup? (equals to Storage.needs_backup)
-	optional uint32 flags = 20;			// device flags (equals to Storage.flags)
-}
-
-/**
- * Request: clear session (removes cached PIN, passphrase, etc).
- * @next Success
- */
-message ClearSession {
-}
-
-/**
- * Request: change language and/or label of the device
- * @next Success
- * @next Failure
- * @next ButtonRequest
- * @next PinMatrixRequest
- */
-message ApplySettings {
-	optional string language = 1;
-	optional string label = 2;
-	optional bool use_passphrase = 3;
-	optional bytes homescreen = 4;
-}
-
-/**
- * Request: set flags of the device
- * @next Success
- * @next Failure
- */
-message ApplyFlags {
-	optional uint32 flags = 1;	// bitmask, can only set bits, not unset
-}
-
-/**
- * Request: Starts workflow for setting/changing/removing the PIN
- * @next ButtonRequest
- * @next PinMatrixRequest
- */
-message ChangePin {
-	optional bool remove = 1;	// is PIN removal requested?
-}
-
-/**
- * Request: Test if the device is alive, device sends back the message in Success response
- * @next Success
- */
-message Ping {
-	optional string message = 1;			// message to send back in Success message
-	optional bool button_protection = 2;		// ask for button press
-	optional bool pin_protection = 3;		// ask for PIN if set in device
-	optional bool passphrase_protection = 4;	// ask for passphrase if set in device
-}
-
-/**
- * Response: Success of the previous request
- */
-message Success {
-	optional string message = 1;	// human readable description of action or request-specific payload
-}
-
-/**
- * Response: Failure of the previous request
- */
-message Failure {
-	optional FailureType code = 1;	// computer-readable definition of the error state
-	optional string message = 2;	// human-readable message of the error state
-}
-
-/**
- * Response: Device is waiting for HW button press.
- * @next ButtonAck
- * @next Cancel
- */
-message ButtonRequest {
-	optional ButtonRequestType code = 1;
-	optional string data = 2;
-}
-
-/**
- * Request: Computer agrees to wait for HW button press
- * @prev ButtonRequest
- */
-message ButtonAck {
-}
-
-/**
- * Response: Device is asking computer to show PIN matrix and awaits PIN encoded using this matrix scheme
- * @next PinMatrixAck
- * @next Cancel
- */
-message PinMatrixRequest {
-	optional PinMatrixRequestType type = 1;
-}
-
-/**
- * Request: Computer responds with encoded PIN
- * @prev PinMatrixRequest
- */
-message PinMatrixAck {
-	required string pin = 1;		// matrix encoded PIN entered by user
-}
-
-/**
- * Request: Abort last operation that required user interaction
- * @prev ButtonRequest
- * @prev PinMatrixRequest
- * @prev PassphraseRequest
- */
-message Cancel {
-}
-
-/**
- * Response: Device awaits encryption passphrase
- * @next PassphraseAck
- * @next Cancel
- */
-message PassphraseRequest {
-}
-
-/**
- * Request: Send passphrase back
- * @prev PassphraseRequest
- */
-message PassphraseAck {
-	required string passphrase = 1;
-}
-
-/**
- * Request: Request a sample of random data generated by hardware RNG. May be used for testing.
- * @next ButtonRequest
- * @next Entropy
- * @next Failure
- */
-message GetEntropy {
-	required uint32 size = 1;		// size of requested entropy
-}
-
-/**
- * Response: Reply with random data generated by internal RNG
- * @prev GetEntropy
- */
-message Entropy {
-	required bytes entropy = 1;		// stream of random generated bytes
-}
-
-/**
- * Request: Ask device for public key corresponding to address_n path
- * @next PassphraseRequest
- * @next PublicKey
- * @next Failure
- */
-message GetPublicKey {
-	repeated uint32 address_n = 1;		// BIP-32 path to derive the key from master node
-	optional string ecdsa_curve_name = 2;	// ECDSA curve name to use
-	optional bool show_display = 3;		// optionally show on display before sending the result
-	optional string coin_name = 4 [default='Bitcoin'];
-}
-
-/**
- * Response: Contains public key derived from device private seed
- * @prev GetPublicKey
- */
-message PublicKey {
-	required HDNodeType node = 1;		// BIP32 public node
-	optional string xpub = 2;		// serialized form of public node
-}
-
-/**
- * Request: Ask device for address corresponding to address_n path
- * @next PassphraseRequest
- * @next Address
- * @next Failure
- */
-message GetAddress {
-	repeated uint32 address_n = 1;						// BIP-32 path to derive the key from master node
-	optional string coin_name = 2 [default='Bitcoin'];
-	optional bool show_display = 3			;			// optionally show on display before sending the result
-	optional MultisigRedeemScriptType multisig = 4;				// filled if we are showing a multisig address
-	optional InputScriptType script_type = 5 [default=SPENDADDRESS];	// used to distinguish between various address formats (non-segwit, segwit, etc.)
-}
-
-/**
- * Request: Ask device for Ethereum address corresponding to address_n path
- * @next PassphraseRequest
- * @next EthereumAddress
- * @next Failure
- */
-message EthereumGetAddress {
-	repeated uint32 address_n = 1;			// BIP-32 path to derive the key from master node
-	optional bool show_display = 2;			// optionally show on display before sending the result
-}
-
-/**
- * Response: Contains address derived from device private seed
- * @prev GetAddress
- */
-message Address {
-	required string address = 1;		// Coin address in Base58 encoding
-}
-
-/**
- * Response: Contains an Ethereum address derived from device private seed
- * @prev EthereumGetAddress
- */
-message EthereumAddress {
-	required bytes address = 1;		// Coin address as an Ethereum 160 bit hash
-}
-
-/**
- * Request: Request device to wipe all sensitive data and settings
- * @next ButtonRequest
- */
-message WipeDevice {
-}
-
-/**
- * Request: Load seed and related internal settings from the computer
- * @next ButtonRequest
- * @next Success
- * @next Failure
- */
-message LoadDevice {
-	optional string mnemonic = 1;				// seed encoded as BIP-39 mnemonic (12, 18 or 24 words)
-	optional HDNodeType node = 2;				// BIP-32 node
-	optional string pin = 3;				// set PIN protection
-	optional bool passphrase_protection = 4;		// enable master node encryption using passphrase
-	optional string language = 5 [default='english'];	// device language
-	optional string label = 6;				// device label
-	optional bool skip_checksum = 7;			// do not test mnemonic for valid BIP-39 checksum
-	optional uint32 u2f_counter = 8;			// U2F counter
-}
-
-/**
- * Request: Ask device to do initialization involving user interaction
- * @next EntropyRequest
- * @next Failure
- */
-message ResetDevice {
-	optional bool display_random = 1;			// display entropy generated by the device before asking for additional entropy
-	optional uint32 strength = 2 [default=256];		// strength of seed in bits
-	optional bool passphrase_protection = 3;		// enable master node encryption using passphrase
-	optional bool pin_protection = 4;			// enable PIN protection
-	optional string language = 5 [default='english'];	// device language
-	optional string label = 6;				// device label
-	optional uint32 u2f_counter = 7;			// U2F counter
-	optional bool skip_backup = 8;				// postpone seed backup to BackupDevice workflow
-}
-
-/**
- * Request: Perform backup of the device seed if not backed up using ResetDevice
- * @next ButtonRequest
- */
-message BackupDevice {
-}
-
-/**
- * Response: Ask for additional entropy from host computer
- * @prev ResetDevice
- * @next EntropyAck
- */
-message EntropyRequest {
-}
-
-/**
- * Request: Provide additional entropy for seed generation function
- * @prev EntropyRequest
- * @next ButtonRequest
- */
-message EntropyAck {
-	optional bytes entropy = 1;				// 256 bits (32 bytes) of random data
-}
-
-/**
- * Request: Start recovery workflow asking user for specific words of mnemonic
- * Used to recovery device safely even on untrusted computer.
- * @next WordRequest
- */
-message RecoveryDevice {
-	optional uint32 word_count = 1;				// number of words in BIP-39 mnemonic
-	optional bool passphrase_protection = 2;		// enable master node encryption using passphrase
-	optional bool pin_protection = 3;			// enable PIN protection
-	optional string language = 4 [default='english'];	// device language
-	optional string label = 5;				// device label
-	optional bool enforce_wordlist = 6;			// enforce BIP-39 wordlist during the process
-	// 7 reserved for unused recovery method
-	optional uint32 type = 8;				// supported recovery type (see RecoveryType)
-	optional uint32 u2f_counter = 9;			// U2F counter
-	optional bool dry_run = 10;				// perform dry-run recovery workflow (for safe mnemonic validation)
-}
-
-/**
- * Response: Device is waiting for user to enter word of the mnemonic
- * Its position is shown only on device's internal display.
- * @prev RecoveryDevice
- * @prev WordAck
- */
-message WordRequest {
-	optional WordRequestType type = 1;
-}
-
-/**
- * Request: Computer replies with word from the mnemonic
- * @prev WordRequest
- * @next WordRequest
- * @next Success
- * @next Failure
- */
-message WordAck {
-	required string word = 1;				// one word of mnemonic on asked position
-}
-
-//////////////////////////////
-// Message signing messages //
-//////////////////////////////
-
-/**
- * Request: Ask device to sign message
- * @next MessageSignature
- * @next Failure
- */
-message SignMessage {
-	repeated uint32 address_n = 1;						// BIP-32 path to derive the key from master node
-	required bytes message = 2;						// message to be signed
-	optional string coin_name = 3 [default='Bitcoin'];			// coin to use for signing
-	optional InputScriptType script_type = 4 [default=SPENDADDRESS];	// used to distinguish between various address formats (non-segwit, segwit, etc.)
-}
-
-/**
- * Request: Ask device to verify message
- * @next Success
- * @next Failure
- */
-message VerifyMessage {
-	optional string address = 1;				// address to verify
-	optional bytes signature = 2;				// signature to verify
-	optional bytes message = 3;				// message to verify
-	optional string coin_name = 4 [default='Bitcoin'];	// coin to use for verifying
-}
-
-/**
- * Response: Signed message
- * @prev SignMessage
- */
-message MessageSignature {
-	optional string address = 1;				// address used to sign the message
-	optional bytes signature = 2;				// signature of the message
-}
-
-///////////////////////////
-// Encryption/decryption //
-///////////////////////////
-
-/**
- * Request: Ask device to encrypt message
- * @next EncryptedMessage
- * @next Failure
- */
-message EncryptMessage {
-	optional bytes pubkey = 1;				// public key
-	optional bytes message = 2;				// message to encrypt
-	optional bool display_only = 3;				// show just on display? (don't send back via wire)
-	repeated uint32 address_n = 4;				// BIP-32 path to derive the signing key from master node
-	optional string coin_name = 5 [default='Bitcoin'];	// coin to use for signing
-}
-
-/**
- * Response: Encrypted message
- * @prev EncryptMessage
- */
-message EncryptedMessage {
-	optional bytes nonce = 1;				// nonce used during encryption
-	optional bytes message = 2;				// encrypted message
-	optional bytes hmac = 3;				// message hmac
-}
-
-/**
- * Request: Ask device to decrypt message
- * @next Success
- * @next Failure
- */
-message DecryptMessage {
-	repeated uint32 address_n = 1;				// BIP-32 path to derive the decryption key from master node
-	optional bytes nonce = 2;				// nonce used during encryption
-	optional bytes message = 3;				// message to decrypt
-	optional bytes hmac = 4;				// message hmac
-}
-
-/**
- * Response: Decrypted message
- * @prev DecryptedMessage
- */
-message DecryptedMessage {
-	optional bytes message = 1;				// decrypted message
-	optional string address = 2;				// address used to sign the message (if used)
-}
-
-/**
- * Request: Ask device to encrypt or decrypt value of given key
- * @next CipheredKeyValue
- * @next Failure
- */
-message CipherKeyValue {
-	repeated uint32 address_n = 1;		// BIP-32 path to derive the key from master node
-	optional string key = 2;		// key component of key:value
-	optional bytes value = 3;		// value component of key:value
-	optional bool encrypt = 4;		// are we encrypting (True) or decrypting (False)?
-	optional bool ask_on_encrypt = 5;	// should we ask on encrypt operation?
-	optional bool ask_on_decrypt = 6;	// should we ask on decrypt operation?
-	optional bytes iv = 7;			// initialization vector (will be computed if not set)
-}
-
-/**
- * Response: Return ciphered/deciphered value
- * @prev CipherKeyValue
- */
-message CipheredKeyValue {
-	optional bytes value = 1;		// ciphered/deciphered value
-}
-
-//////////////////////////////////
-// Transaction signing messages //
-//////////////////////////////////
-
-/**
- * Request: Estimated size of the transaction
- * This behaves exactly like SignTx, which means that it can ask using TxRequest
- * This call is non-blocking (except possible PassphraseRequest to unlock the seed)
- * @next TxSize
- * @next Failure
- */
-message EstimateTxSize {
-	required uint32 outputs_count = 1;			// number of transaction outputs
-	required uint32 inputs_count = 2;			// number of transaction inputs
-	optional string coin_name = 3 [default='Bitcoin'];	// coin to use
-}
-
-/**
- * Response: Estimated size of the transaction
- * @prev EstimateTxSize
- */
-message TxSize {
-	optional uint32 tx_size = 1;				// estimated size of transaction in bytes
-}
-
-/**
- * Request: Ask device to sign transaction
- * @next PassphraseRequest
- * @next PinMatrixRequest
- * @next TxRequest
- * @next Failure
- */
-message SignTx {
-	required uint32 outputs_count = 1;			// number of transaction outputs
-	required uint32 inputs_count = 2;			// number of transaction inputs
-	optional string coin_name = 3 [default='Bitcoin'];	// coin to use
-	optional uint32 version = 4 [default=1];		// transaction version
-	optional uint32 lock_time = 5 [default=0];		// transaction lock_time
-}
-
-/**
- * Request: Simplified transaction signing
- * This method doesn't support streaming, so there are hardware limits in number of inputs and outputs.
- * In case of success, the result is returned using TxRequest message.
- * @next PassphraseRequest
- * @next PinMatrixRequest
- * @next TxRequest
- * @next Failure
- */
-message SimpleSignTx {
-	repeated TxInputType inputs = 1;			// transaction inputs
-	repeated TxOutputType outputs = 2;			// transaction outputs
-	repeated TransactionType transactions = 3;		// transactions whose outputs are used to build current inputs
-	optional string coin_name = 4 [default='Bitcoin'];	// coin to use
-	optional uint32 version = 5 [default=1];		// transaction version
-	optional uint32 lock_time = 6 [default=0];		// transaction lock_time
-}
-
-/**
- * Response: Device asks for information for signing transaction or returns the last result
- * If request_index is set, device awaits TxAck message (with fields filled in according to request_type)
- * If signature_index is set, 'signature' contains signed input of signature_index's input
- * @prev SignTx
- * @prev SimpleSignTx
- * @prev TxAck
- */
-message TxRequest {
-	optional RequestType request_type = 1;			// what should be filled in TxAck message?
-	optional TxRequestDetailsType details = 2;		// request for tx details
-	optional TxRequestSerializedType serialized = 3;	// serialized data and request for next
-}
-
-/**
- * Request: Reported transaction data
- * @prev TxRequest
- * @next TxRequest
- */
-message TxAck {
-	optional TransactionType tx = 1;
-}
-
-/**
- * Request: Ask device to sign transaction
- * All fields are optional from the protocol's point of view. Each field defaults to value `0` if missing.
- * Note: the first at most 1024 bytes of data MUST be transmitted as part of this message.
- * @next PassphraseRequest
- * @next PinMatrixRequest
- * @next EthereumTxRequest
- * @next Failure
- */
-message EthereumSignTx {
-	repeated uint32 address_n = 1;			// BIP-32 path to derive the key from master node
-	optional bytes nonce = 2;			// <=256 bit unsigned big endian
-	optional bytes gas_price = 3;			// <=256 bit unsigned big endian (in wei)
-	optional bytes gas_limit = 4;			// <=256 bit unsigned big endian
-	optional bytes to = 5;				// 160 bit address hash
-	optional bytes value = 6;			// <=256 bit unsigned big endian (in wei)
-	optional bytes data_initial_chunk = 7;		// The initial data chunk (<= 1024 bytes)
-	optional uint32 data_length = 8;		// Length of transaction payload
-	optional uint32 chain_id = 9;			// Chain Id for EIP 155
-}
-
-/**
- * Response: Device asks for more data from transaction payload, or returns the signature.
- * If data_length is set, device awaits that many more bytes of payload.
- * Otherwise, the signature_* fields contain the computed transaction signature. All three fields will be present.
- * @prev EthereumSignTx
- * @next EthereumTxAck
- */
-message EthereumTxRequest {
-	optional uint32 data_length = 1;		// Number of bytes being requested (<= 1024)
-	optional uint32 signature_v = 2;		// Computed signature (recovery parameter, limited to 27 or 28)
-	optional bytes signature_r = 3;			// Computed signature R component (256 bit)
-	optional bytes signature_s = 4;			// Computed signature S component (256 bit)
-}
-
-/**
- * Request: Transaction payload data.
- * @prev EthereumTxRequest
- * @next EthereumTxRequest
- */
-message EthereumTxAck {
-	optional bytes data_chunk = 1;			// Bytes from transaction payload (<= 1024 bytes)
-}
-
-////////////////////////////////////////
-// Ethereum: Message signing messages //
-////////////////////////////////////////
-
-/**
- * Request: Ask device to sign message
- * @next EthereumMessageSignature
- * @next Failure
- */
-message EthereumSignMessage {
-	repeated uint32 address_n = 1;				// BIP-32 path to derive the key from master node
-	required bytes message = 2;				// message to be signed
-}
-
-/**
- * Request: Ask device to verify message
- * @next Success
- * @next Failure
- */
-message EthereumVerifyMessage {
-	optional bytes address = 1;				// address to verify
-	optional bytes signature = 2;				// signature to verify
-	optional bytes message = 3;				// message to verify
-}
-
-/**
- * Response: Signed message
- * @prev EthereumSignMessage
- */
-message EthereumMessageSignature {
-	optional bytes address = 1;				// address used to sign the message
-	optional bytes signature = 2;				// signature of the message
-}
-
-///////////////////////
-// Identity messages //
-///////////////////////
-
-/**
- * Request: Ask device to sign identity
- * @next SignedIdentity
- * @next Failure
- */
-message SignIdentity {
-	optional IdentityType identity = 1;		// identity
-	optional bytes challenge_hidden = 2;		// non-visible challenge
-	optional string challenge_visual = 3;		// challenge shown on display (e.g. date+time)
-	optional string ecdsa_curve_name = 4;		// ECDSA curve name to use
-}
-
-/**
- * Response: Device provides signed identity
- * @prev SignIdentity
- */
-message SignedIdentity {
-	optional string address = 1;			// identity address
-	optional bytes public_key = 2;			// identity public key
-	optional bytes signature = 3;			// signature of the identity data
-}
-
-///////////////////
-// ECDH messages //
-///////////////////
-
-/**
- * Request: Ask device to generate ECDH session key
- * @next ECDHSessionKey
- * @next Failure
- */
-message GetECDHSessionKey {
-	optional IdentityType identity = 1;		// identity
-	optional bytes peer_public_key = 2;		// peer's public key
-	optional string ecdsa_curve_name = 3;		// ECDSA curve name to use
-}
-
-/**
- * Response: Device provides ECDH session key
- * @prev GetECDHSessionKey
- */
-message ECDHSessionKey {
-	optional bytes session_key = 1;			// ECDH session key
+extend google.protobuf.EnumValueOptions {
+    optional bool wire_in = 50002;              // message can be transmitted via wire from PC to TREZOR
+    optional bool wire_out = 50003;             // message can be transmitted via wire from TREZOR to PC
+    optional bool wire_debug_in = 50004;        // message can be transmitted via debug wire from PC to TREZOR
+    optional bool wire_debug_out = 50005;       // message can be transmitted via debug wire from TREZOR to PC
+    optional bool wire_tiny = 50006;            // message is handled by TREZOR when the USB stack is in tiny mode
+    optional bool wire_bootloader = 50007;      // message is only handled by TREZOR Bootloader
+    optional bool wire_no_fsm = 50008;          // message is not handled by TREZOR unless the USB stack is in tiny mode
 }
 
-///////////////////
-// U2F messages //
-///////////////////
-
-/**
- * Request: Set U2F counter
- * @next Success
- */
-message SetU2FCounter {
-	optional uint32 u2f_counter = 1;		// counter
-}
-
-/////////////////////////
-// Bootloader messages //
-/////////////////////////
-
-/**
- * Request: Ask device to erase its firmware (so it can be replaced via FirmwareUpload)
- * @next Success
- * @next FirmwareRequest
- * @next Failure
- */
-message FirmwareErase {
-	optional uint32 length = 1;			// length of new firmware
-}
-
-/**
- * Response: Ask for firmware chunk
- * @next FirmwareUpload
- */
-message FirmwareRequest {
-	optional uint32 offset = 1;			// offset of requested firmware chunk
-	optional uint32 length = 2;			// length of requested firmware chunk
-}
-
-/**
- * Request: Send firmware in binary form to the device
- * @next Success
- * @next Failure
- */
-message FirmwareUpload {
-	required bytes payload = 1;			// firmware to be loaded into device
-	optional bytes hash = 2;			// hash of the payload
-}
-
-
 /**
- * Request: Perform a device self-test
- * @next Success
- * @next Failure
+ * Mapping between TREZOR wire identifier (uint) and a protobuf message
  */
-message SelfTest {
-	optional bytes payload = 1;			// payload to be used in self-test
-}
-
-/////////////////////////////////////////////////////////////
-// Debug messages (only available if DebugLink is enabled) //
-/////////////////////////////////////////////////////////////
-
-/**
- * Request: "Press" the button on the device
- * @next Success
- */
-message DebugLinkDecision {
-	required bool yes_no = 1;			// true for "Confirm", false for "Cancel"
-}
-
-/**
- * Request: Computer asks for device state
- * @next DebugLinkState
- */
-message DebugLinkGetState {
-}
-
-/**
- * Response: Device current state
- * @prev DebugLinkGetState
- */
-message DebugLinkState {
-	optional bytes layout = 1;			// raw buffer of display
-	optional string pin = 2;			// current PIN, blank if PIN is not set/enabled
-	optional string matrix = 3;			// current PIN matrix
-	optional string mnemonic = 4;			// current BIP-39 mnemonic
-	optional HDNodeType node = 5;			// current BIP-32 node
-	optional bool passphrase_protection = 6;	// is node/mnemonic encrypted using passphrase?
-	optional string reset_word = 7;			// word on device display during ResetDevice workflow
-	optional bytes reset_entropy = 8;		// current entropy during ResetDevice workflow
-	optional string recovery_fake_word = 9;		// (fake) word on display during RecoveryDevice workflow
-	optional uint32 recovery_word_pos = 10;		// index of mnemonic word the device is expecting during RecoveryDevice workflow
-}
-
-/**
- * Request: Ask device to restart
- */
-message DebugLinkStop {
-}
-
-/**
- * Response: Device wants host to log event
- */
-message DebugLinkLog {
-	optional uint32 level = 1;
-	optional string bucket = 2;
-	optional string text = 3;
-}
-
-/**
- * Request: Read memory from device
- * @next DebugLinkMemory
- */
-message DebugLinkMemoryRead {
-	optional uint32 address = 1;
-	optional uint32 length = 2;
-}
-
-/**
- * Response: Device sends memory back
- * @prev DebugLinkMemoryRead
- */
-message DebugLinkMemory {
-	optional bytes memory = 1;
-}
-
-/**
- * Request: Write memory to device.
- * WARNING: Writing to the wrong location can irreparably break the device.
- */
-message DebugLinkMemoryWrite {
-	optional uint32 address = 1;
-	optional bytes memory = 2;
-	optional bool flash = 3;
-}
+enum MessageType {
 
-/**
- * Request: Erase block of flash on device
- * WARNING: Writing to the wrong location can irreparably break the device.
- */
-message DebugLinkFlashErase {
-	optional uint32 sector = 1;
+    // Management
+    MessageType_Initialize = 0 [(wire_in) = true, (wire_tiny) = true];
+    MessageType_Ping = 1 [(wire_in) = true];
+    MessageType_Success = 2 [(wire_out) = true];
+    MessageType_Failure = 3 [(wire_out) = true];
+    MessageType_ChangePin = 4 [(wire_in) = true];
+    MessageType_WipeDevice = 5 [(wire_in) = true];
+    MessageType_GetEntropy = 9 [(wire_in) = true];
+    MessageType_Entropy = 10 [(wire_out) = true];
+    MessageType_LoadDevice = 13 [(wire_in) = true];
+    MessageType_ResetDevice = 14 [(wire_in) = true];
+    MessageType_Features = 17 [(wire_out) = true];
+    MessageType_PinMatrixRequest = 18 [(wire_out) = true];
+    MessageType_PinMatrixAck = 19 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
+    MessageType_Cancel = 20 [(wire_in) = true, (wire_tiny) = true];
+    MessageType_ClearSession = 24 [(wire_in) = true];
+    MessageType_ApplySettings = 25 [(wire_in) = true];
+    MessageType_ButtonRequest = 26 [(wire_out) = true];
+    MessageType_ButtonAck = 27 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
+    MessageType_ApplyFlags = 28 [(wire_in) = true];
+    MessageType_BackupDevice = 34 [(wire_in) = true];
+    MessageType_EntropyRequest = 35 [(wire_out) = true];
+    MessageType_EntropyAck = 36 [(wire_in) = true];
+    MessageType_PassphraseRequest = 41 [(wire_out) = true];
+    MessageType_PassphraseAck = 42 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
+    MessageType_PassphraseStateRequest = 77 [(wire_out) = true];
+    MessageType_PassphraseStateAck = 78 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
+    MessageType_RecoveryDevice = 45 [(wire_in) = true];
+    MessageType_WordRequest = 46 [(wire_out) = true];
+    MessageType_WordAck = 47 [(wire_in) = true];
+    MessageType_GetFeatures = 55 [(wire_in) = true];
+    MessageType_SetU2FCounter = 63 [(wire_in) = true];
+
+    // Bootloader
+    MessageType_FirmwareErase = 6 [(wire_in) = true, (wire_bootloader) = true];
+    MessageType_FirmwareUpload = 7 [(wire_in) = true, (wire_bootloader) = true];
+    MessageType_FirmwareRequest = 8 [(wire_out) = true, (wire_bootloader) = true];
+    MessageType_SelfTest = 32 [(wire_in) = true, (wire_bootloader) = true];
+
+    // Bitcoin
+    MessageType_GetPublicKey = 11 [(wire_in) = true];
+    MessageType_PublicKey = 12 [(wire_out) = true];
+    MessageType_SignTx = 15 [(wire_in) = true];
+    MessageType_TxRequest = 21 [(wire_out) = true];
+    MessageType_TxAck = 22 [(wire_in) = true];
+    MessageType_GetAddress = 29 [(wire_in) = true];
+    MessageType_Address = 30 [(wire_out) = true];
+    MessageType_SignMessage = 38 [(wire_in) = true];
+    MessageType_VerifyMessage = 39 [(wire_in) = true];
+    MessageType_MessageSignature = 40 [(wire_out) = true];
+
+    // Crypto
+    MessageType_CipherKeyValue = 23 [(wire_in) = true];
+    MessageType_CipheredKeyValue = 48 [(wire_out) = true];
+    MessageType_SignIdentity = 53 [(wire_in) = true];
+    MessageType_SignedIdentity = 54 [(wire_out) = true];
+    MessageType_GetECDHSessionKey = 61 [(wire_in) = true];
+    MessageType_ECDHSessionKey = 62 [(wire_out) = true];
+    MessageType_CosiCommit = 71 [(wire_in) = true];
+    MessageType_CosiCommitment = 72 [(wire_out) = true];
+    MessageType_CosiSign = 73 [(wire_in) = true];
+    MessageType_CosiSignature = 74 [(wire_out) = true];
+
+    // Debug
+    MessageType_DebugLinkDecision = 100 [(wire_debug_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
+    MessageType_DebugLinkGetState = 101 [(wire_debug_in) = true, (wire_tiny) = true];
+    MessageType_DebugLinkState = 102 [(wire_debug_out) = true];
+    MessageType_DebugLinkStop = 103 [(wire_debug_in) = true];
+    MessageType_DebugLinkLog = 104 [(wire_debug_out) = true];
+    MessageType_DebugLinkMemoryRead = 110 [(wire_debug_in) = true];
+    MessageType_DebugLinkMemory = 111 [(wire_debug_out) = true];
+    MessageType_DebugLinkMemoryWrite = 112 [(wire_debug_in) = true];
+    MessageType_DebugLinkFlashErase = 113 [(wire_debug_in) = true];
+
+    // Ethereum
+    MessageType_EthereumGetPublicKey = 450 [(wire_in) = true];
+    MessageType_EthereumPublicKey = 451 [(wire_out) = true];
+    MessageType_EthereumGetAddress = 56 [(wire_in) = true];
+    MessageType_EthereumAddress = 57 [(wire_out) = true];
+    MessageType_EthereumSignTx = 58 [(wire_in) = true];
+    MessageType_EthereumTxRequest = 59 [(wire_out) = true];
+    MessageType_EthereumTxAck = 60 [(wire_in) = true];
+    MessageType_EthereumSignMessage = 64 [(wire_in) = true];
+    MessageType_EthereumVerifyMessage = 65 [(wire_in) = true];
+    MessageType_EthereumMessageSignature = 66 [(wire_out) = true];
+
+    // NEM
+    MessageType_NEMGetAddress = 67 [(wire_in) = true];
+    MessageType_NEMAddress = 68 [(wire_out) = true];
+    MessageType_NEMSignTx = 69 [(wire_in) = true];
+    MessageType_NEMSignedTx = 70 [(wire_out) = true];
+    MessageType_NEMDecryptMessage = 75 [(wire_in) = true];
+    MessageType_NEMDecryptedMessage = 76 [(wire_out) = true];
+
+    // Lisk
+    MessageType_LiskGetAddress = 114 [(wire_in) = true];
+    MessageType_LiskAddress = 115 [(wire_out) = true];
+    MessageType_LiskSignTx = 116 [(wire_in) = true];
+    MessageType_LiskSignedTx = 117 [(wire_out) = true];
+    MessageType_LiskSignMessage = 118 [(wire_in) = true];
+    MessageType_LiskMessageSignature = 119 [(wire_out) = true];
+    MessageType_LiskVerifyMessage = 120 [(wire_in) = true];
+    MessageType_LiskGetPublicKey = 121 [(wire_in) = true];
+    MessageType_LiskPublicKey = 122 [(wire_out) = true];
+
+    // Tezos
+    MessageType_TezosGetAddress = 150 [(wire_in) = true];
+    MessageType_TezosAddress = 151 [(wire_out) = true];
+    MessageType_TezosSignTx = 152 [(wire_in) = true];
+    MessageType_TezosSignedTx = 153 [(wire_out) = true];
+    MessageType_TezosGetPublicKey = 154 [(wire_in) = true];
+    MessageType_TezosPublicKey = 155 [(wire_out) = true];
+
+    // Stellar
+    MessageType_StellarSignTx = 202 [(wire_in) = true];
+    MessageType_StellarTxOpRequest = 203 [(wire_out) = true];
+    MessageType_StellarGetAddress = 207 [(wire_in) = true];
+    MessageType_StellarAddress = 208 [(wire_out) = true];
+    MessageType_StellarCreateAccountOp = 210 [(wire_in) = true];
+    MessageType_StellarPaymentOp = 211 [(wire_in) = true];
+    MessageType_StellarPathPaymentOp = 212 [(wire_in) = true];
+    MessageType_StellarManageOfferOp = 213 [(wire_in) = true];
+    MessageType_StellarCreatePassiveOfferOp = 214 [(wire_in) = true];
+    MessageType_StellarSetOptionsOp = 215 [(wire_in) = true];
+    MessageType_StellarChangeTrustOp = 216 [(wire_in) = true];
+    MessageType_StellarAllowTrustOp = 217 [(wire_in) = true];
+    MessageType_StellarAccountMergeOp = 218 [(wire_in) = true];
+    // omitted: StellarInflationOp is not a supported operation, would be 219
+    MessageType_StellarManageDataOp = 220 [(wire_in) = true];
+    MessageType_StellarBumpSequenceOp = 221 [(wire_in) = true];
+    MessageType_StellarSignedTx = 230 [(wire_out) = true];
+
+    // TRON
+    MessageType_TronGetAddress = 250 [(wire_in) = true];
+    MessageType_TronAddress = 251 [(wire_out) = true];
+    MessageType_TronSignTx = 252 [(wire_in) = true];
+    MessageType_TronSignedTx = 253 [(wire_out) = true];
+
+    // Cardano
+    // dropped Sign/VerifyMessage ids 300-302
+    MessageType_CardanoSignTx = 303 [(wire_in) = true];
+    MessageType_CardanoTxRequest = 304 [(wire_out) = true];
+    MessageType_CardanoGetPublicKey = 305 [(wire_in) = true];
+    MessageType_CardanoPublicKey = 306 [(wire_out) = true];
+    MessageType_CardanoGetAddress = 307 [(wire_in) = true];
+    MessageType_CardanoAddress = 308 [(wire_out) = true];
+    MessageType_CardanoTxAck = 309 [(wire_in) = true];
+    MessageType_CardanoSignedTx = 310 [(wire_out) = true];
+
+    // Ontology
+    MessageType_OntologyGetAddress = 350 [(wire_in) = true];
+    MessageType_OntologyAddress = 351 [(wire_out) = true];
+    MessageType_OntologyGetPublicKey = 352 [(wire_in) = true];
+    MessageType_OntologyPublicKey = 353 [(wire_out) = true];
+    MessageType_OntologySignTransfer = 354 [(wire_in) = true];
+    MessageType_OntologySignedTransfer = 355 [(wire_out) = true];
+    MessageType_OntologySignWithdrawOng = 356 [(wire_in) = true];
+    MessageType_OntologySignedWithdrawOng = 357 [(wire_out) = true];
+    MessageType_OntologySignOntIdRegister = 358 [(wire_in) = true];
+    MessageType_OntologySignedOntIdRegister = 359 [(wire_out) = true];
+    MessageType_OntologySignOntIdAddAttributes = 360 [(wire_in) = true];
+    MessageType_OntologySignedOntIdAddAttributes = 361 [(wire_out) = true];
+
+    // Ripple
+    MessageType_RippleGetAddress = 400 [(wire_in) = true];
+    MessageType_RippleAddress = 401 [(wire_out) = true];
+    MessageType_RippleSignTx = 402 [(wire_in) = true];
+    MessageType_RippleSignedTx = 403 [(wire_in) = true];
+
+    // Monero
+    MessageType_MoneroTransactionInitRequest = 501 [(wire_out) = true];
+    MessageType_MoneroTransactionInitAck = 502 [(wire_out) = true];
+    MessageType_MoneroTransactionSetInputRequest = 503 [(wire_out) = true];
+    MessageType_MoneroTransactionSetInputAck = 504 [(wire_out) = true];
+    MessageType_MoneroTransactionInputsPermutationRequest = 505 [(wire_out) = true];
+    MessageType_MoneroTransactionInputsPermutationAck = 506 [(wire_out) = true];
+    MessageType_MoneroTransactionInputViniRequest = 507 [(wire_out) = true];
+    MessageType_MoneroTransactionInputViniAck = 508 [(wire_out) = true];
+    MessageType_MoneroTransactionAllInputsSetRequest = 509 [(wire_out) = true];
+    MessageType_MoneroTransactionAllInputsSetAck = 510 [(wire_out) = true];
+    MessageType_MoneroTransactionSetOutputRequest = 511 [(wire_out) = true];
+    MessageType_MoneroTransactionSetOutputAck = 512 [(wire_out) = true];
+    MessageType_MoneroTransactionAllOutSetRequest = 513 [(wire_out) = true];
+    MessageType_MoneroTransactionAllOutSetAck = 514 [(wire_out) = true];
+    MessageType_MoneroTransactionSignInputRequest = 515 [(wire_out) = true];
+    MessageType_MoneroTransactionSignInputAck = 516 [(wire_out) = true];
+    MessageType_MoneroTransactionFinalRequest = 517 [(wire_out) = true];
+    MessageType_MoneroTransactionFinalAck = 518 [(wire_out) = true];
+    MessageType_MoneroKeyImageExportInitRequest = 530 [(wire_out) = true];
+    MessageType_MoneroKeyImageExportInitAck = 531 [(wire_out) = true];
+    MessageType_MoneroKeyImageSyncStepRequest = 532 [(wire_out) = true];
+    MessageType_MoneroKeyImageSyncStepAck = 533 [(wire_out) = true];
+    MessageType_MoneroKeyImageSyncFinalRequest = 534 [(wire_out) = true];
+    MessageType_MoneroKeyImageSyncFinalAck = 535 [(wire_out) = true];
+    MessageType_MoneroGetAddress = 540 [(wire_in) = true];
+    MessageType_MoneroAddress = 541 [(wire_out) = true];
+    MessageType_MoneroGetWatchKey = 542 [(wire_in) = true];
+    MessageType_MoneroWatchKey = 543 [(wire_out) = true];
+    MessageType_DebugMoneroDiagRequest = 546 [(wire_in) = true];
+    MessageType_DebugMoneroDiagAck = 547 [(wire_out) = true];
+    MessageType_MoneroGetTxKeyRequest = 550 [(wire_in) = true];
+    MessageType_MoneroGetTxKeyAck = 551 [(wire_out) = true];
+    MessageType_MoneroLiveRefreshStartRequest = 552 [(wire_in) = true];
+    MessageType_MoneroLiveRefreshStartAck = 553 [(wire_out) = true];
+    MessageType_MoneroLiveRefreshStepRequest = 554 [(wire_in) = true];
+    MessageType_MoneroLiveRefreshStepAck = 555 [(wire_out) = true];
+    MessageType_MoneroLiveRefreshFinalRequest = 556 [(wire_in) = true];
+    MessageType_MoneroLiveRefreshFinalAck = 557 [(wire_out) = true];
+
+    // EOS
+    MessageType_EosGetPublicKey = 600 [(wire_in) = true];
+    MessageType_EosPublicKey = 601 [(wire_out) = true];
+    MessageType_EosSignTx = 602 [(wire_in) = true];
+    MessageType_EosTxActionRequest = 603 [(wire_out) = true];
+    MessageType_EosTxActionAck = 604 [(wire_in) = true];
+    MessageType_EosSignedTx = 605 [(wire_out) = true];
+
+    // Binance
+    MessageType_BinanceGetAddress = 700 [(wire_in) = true];
+    MessageType_BinanceAddress = 701 [(wire_out) = true];
+    MessageType_BinanceGetPublicKey = 702 [(wire_in) = true];
+    MessageType_BinancePublicKey = 703 [(wire_out) = true];
+    MessageType_BinanceSignTx = 704 [(wire_in) = true];
+    MessageType_BinanceTxRequest = 705 [(wire_out) = true];
+    MessageType_BinanceTransferMsg = 706 [(wire_in) = true];
+    MessageType_BinanceOrderMsg = 707 [(wire_in) = true];
+    MessageType_BinanceCancelMsg = 708 [(wire_in) = true];
+    MessageType_BinanceSignedTx = 709 [(wire_out) = true];
 }

+ 28 - 4
accounts/usbwallet/trezor/trezor.go

@@ -1,4 +1,4 @@
-// Copyright 2017 The go-ethereum Authors
+// Copyright 2019 The go-ethereum Authors
 // This file is part of the go-ethereum library.
 //
 // The go-ethereum library is free software: you can redistribute it and/or modify
@@ -16,11 +16,35 @@
 
 // This file contains the implementation for interacting with the Trezor hardware
 // wallets. The wire protocol spec can be found on the SatoshiLabs website:
-// https://doc.satoshilabs.com/trezor-tech/api-protobuf.html
+// https://wiki.trezor.io/Developers_guide-Message_Workflows
 
-//go:generate protoc --go_out=import_path=trezor:. types.proto messages.proto
+// !!! STAHP !!!
+//
+// Before you touch the protocol files, you need to be aware of a breaking change
+// that occurred between firmware versions 1.7.3->1.8.0 (Model One) and 2.0.10->
+// 2.1.0 (Model T). The Ethereum address representation was changed from the 20
+// byte binary blob to a 42 byte hex string. The upstream protocol buffer files
+// only support the new format, so blindly pulling in a new spec will break old
+// devices!
+//
+// The Trezor devs had the foresight to add the string version as a new message
+// code instead of replacing the binary one. This means that the proto file can
+// actually define both the old and the new versions as optional. Please ensure
+// that you add back the old addresses everywhere (to avoid name clash. use the
+// addressBin and addressHex names).
+//
+// If in doubt, reach out to @karalabe.
+
+// To regenerate the protocol files in this package:
+//   - Download the latest protoc https://github.com/protocolbuffers/protobuf/releases
+//   - Build with the usual `./configure && make` and ensure it's on your $PATH
+//   - Delete all the .proto and .pb.go files, pull in fresh ones from Trezor
+//   - Grab the latest Go plugin `go get -u github.com/golang/protobuf/protoc-gen-go`
+//   - Vendor in the latest Go plugin `govendor fetch github.com/golang/protobuf/...`
+
+//go:generate protoc -I/usr/local/include:. --go_out=import_path=trezor:. messages.proto messages-common.proto messages-management.proto messages-ethereum.proto
 
-// Package trezor contains the wire protocol wrapper in Go.
+// Package trezor contains the wire protocol.
 package trezor
 
 import (

+ 0 - 1333
accounts/usbwallet/trezor/types.pb.go

@@ -1,1333 +0,0 @@
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// source: types.proto
-
-/*
-Package trezor is a generated protocol buffer package.
-
-It is generated from these files:
-	types.proto
-	messages.proto
-
-It has these top-level messages:
-	HDNodeType
-	HDNodePathType
-	CoinType
-	MultisigRedeemScriptType
-	TxInputType
-	TxOutputType
-	TxOutputBinType
-	TransactionType
-	TxRequestDetailsType
-	TxRequestSerializedType
-	IdentityType
-	Initialize
-	GetFeatures
-	Features
-	ClearSession
-	ApplySettings
-	ApplyFlags
-	ChangePin
-	Ping
-	Success
-	Failure
-	ButtonRequest
-	ButtonAck
-	PinMatrixRequest
-	PinMatrixAck
-	Cancel
-	PassphraseRequest
-	PassphraseAck
-	GetEntropy
-	Entropy
-	GetPublicKey
-	PublicKey
-	GetAddress
-	EthereumGetAddress
-	Address
-	EthereumAddress
-	WipeDevice
-	LoadDevice
-	ResetDevice
-	BackupDevice
-	EntropyRequest
-	EntropyAck
-	RecoveryDevice
-	WordRequest
-	WordAck
-	SignMessage
-	VerifyMessage
-	MessageSignature
-	EncryptMessage
-	EncryptedMessage
-	DecryptMessage
-	DecryptedMessage
-	CipherKeyValue
-	CipheredKeyValue
-	EstimateTxSize
-	TxSize
-	SignTx
-	SimpleSignTx
-	TxRequest
-	TxAck
-	EthereumSignTx
-	EthereumTxRequest
-	EthereumTxAck
-	EthereumSignMessage
-	EthereumVerifyMessage
-	EthereumMessageSignature
-	SignIdentity
-	SignedIdentity
-	GetECDHSessionKey
-	ECDHSessionKey
-	SetU2FCounter
-	FirmwareErase
-	FirmwareRequest
-	FirmwareUpload
-	SelfTest
-	DebugLinkDecision
-	DebugLinkGetState
-	DebugLinkState
-	DebugLinkStop
-	DebugLinkLog
-	DebugLinkMemoryRead
-	DebugLinkMemory
-	DebugLinkMemoryWrite
-	DebugLinkFlashErase
-*/
-package trezor
-
-import proto "github.com/golang/protobuf/proto"
-import fmt "fmt"
-import math "math"
-import google_protobuf "github.com/golang/protobuf/protoc-gen-go/descriptor"
-
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
-
-// *
-// Type of failures returned by Failure message
-// @used_in Failure
-type FailureType int32
-
-const (
-	FailureType_Failure_UnexpectedMessage FailureType = 1
-	FailureType_Failure_ButtonExpected    FailureType = 2
-	FailureType_Failure_DataError         FailureType = 3
-	FailureType_Failure_ActionCancelled   FailureType = 4
-	FailureType_Failure_PinExpected       FailureType = 5
-	FailureType_Failure_PinCancelled      FailureType = 6
-	FailureType_Failure_PinInvalid        FailureType = 7
-	FailureType_Failure_InvalidSignature  FailureType = 8
-	FailureType_Failure_ProcessError      FailureType = 9
-	FailureType_Failure_NotEnoughFunds    FailureType = 10
-	FailureType_Failure_NotInitialized    FailureType = 11
-	FailureType_Failure_FirmwareError     FailureType = 99
-)
-
-var FailureType_name = map[int32]string{
-	1:  "Failure_UnexpectedMessage",
-	2:  "Failure_ButtonExpected",
-	3:  "Failure_DataError",
-	4:  "Failure_ActionCancelled",
-	5:  "Failure_PinExpected",
-	6:  "Failure_PinCancelled",
-	7:  "Failure_PinInvalid",
-	8:  "Failure_InvalidSignature",
-	9:  "Failure_ProcessError",
-	10: "Failure_NotEnoughFunds",
-	11: "Failure_NotInitialized",
-	99: "Failure_FirmwareError",
-}
-var FailureType_value = map[string]int32{
-	"Failure_UnexpectedMessage": 1,
-	"Failure_ButtonExpected":    2,
-	"Failure_DataError":         3,
-	"Failure_ActionCancelled":   4,
-	"Failure_PinExpected":       5,
-	"Failure_PinCancelled":      6,
-	"Failure_PinInvalid":        7,
-	"Failure_InvalidSignature":  8,
-	"Failure_ProcessError":      9,
-	"Failure_NotEnoughFunds":    10,
-	"Failure_NotInitialized":    11,
-	"Failure_FirmwareError":     99,
-}
-
-func (x FailureType) Enum() *FailureType {
-	p := new(FailureType)
-	*p = x
-	return p
-}
-func (x FailureType) String() string {
-	return proto.EnumName(FailureType_name, int32(x))
-}
-func (x *FailureType) UnmarshalJSON(data []byte) error {
-	value, err := proto.UnmarshalJSONEnum(FailureType_value, data, "FailureType")
-	if err != nil {
-		return err
-	}
-	*x = FailureType(value)
-	return nil
-}
-func (FailureType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
-
-// *
-// Type of script which will be used for transaction output
-// @used_in TxOutputType
-type OutputScriptType int32
-
-const (
-	OutputScriptType_PAYTOADDRESS     OutputScriptType = 0
-	OutputScriptType_PAYTOSCRIPTHASH  OutputScriptType = 1
-	OutputScriptType_PAYTOMULTISIG    OutputScriptType = 2
-	OutputScriptType_PAYTOOPRETURN    OutputScriptType = 3
-	OutputScriptType_PAYTOWITNESS     OutputScriptType = 4
-	OutputScriptType_PAYTOP2SHWITNESS OutputScriptType = 5
-)
-
-var OutputScriptType_name = map[int32]string{
-	0: "PAYTOADDRESS",
-	1: "PAYTOSCRIPTHASH",
-	2: "PAYTOMULTISIG",
-	3: "PAYTOOPRETURN",
-	4: "PAYTOWITNESS",
-	5: "PAYTOP2SHWITNESS",
-}
-var OutputScriptType_value = map[string]int32{
-	"PAYTOADDRESS":     0,
-	"PAYTOSCRIPTHASH":  1,
-	"PAYTOMULTISIG":    2,
-	"PAYTOOPRETURN":    3,
-	"PAYTOWITNESS":     4,
-	"PAYTOP2SHWITNESS": 5,
-}
-
-func (x OutputScriptType) Enum() *OutputScriptType {
-	p := new(OutputScriptType)
-	*p = x
-	return p
-}
-func (x OutputScriptType) String() string {
-	return proto.EnumName(OutputScriptType_name, int32(x))
-}
-func (x *OutputScriptType) UnmarshalJSON(data []byte) error {
-	value, err := proto.UnmarshalJSONEnum(OutputScriptType_value, data, "OutputScriptType")
-	if err != nil {
-		return err
-	}
-	*x = OutputScriptType(value)
-	return nil
-}
-func (OutputScriptType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
-
-// *
-// Type of script which will be used for transaction output
-// @used_in TxInputType
-type InputScriptType int32
-
-const (
-	InputScriptType_SPENDADDRESS     InputScriptType = 0
-	InputScriptType_SPENDMULTISIG    InputScriptType = 1
-	InputScriptType_EXTERNAL         InputScriptType = 2
-	InputScriptType_SPENDWITNESS     InputScriptType = 3
-	InputScriptType_SPENDP2SHWITNESS InputScriptType = 4
-)
-
-var InputScriptType_name = map[int32]string{
-	0: "SPENDADDRESS",
-	1: "SPENDMULTISIG",
-	2: "EXTERNAL",
-	3: "SPENDWITNESS",
-	4: "SPENDP2SHWITNESS",
-}
-var InputScriptType_value = map[string]int32{
-	"SPENDADDRESS":     0,
-	"SPENDMULTISIG":    1,
-	"EXTERNAL":         2,
-	"SPENDWITNESS":     3,
-	"SPENDP2SHWITNESS": 4,
-}
-
-func (x InputScriptType) Enum() *InputScriptType {
-	p := new(InputScriptType)
-	*p = x
-	return p
-}
-func (x InputScriptType) String() string {
-	return proto.EnumName(InputScriptType_name, int32(x))
-}
-func (x *InputScriptType) UnmarshalJSON(data []byte) error {
-	value, err := proto.UnmarshalJSONEnum(InputScriptType_value, data, "InputScriptType")
-	if err != nil {
-		return err
-	}
-	*x = InputScriptType(value)
-	return nil
-}
-func (InputScriptType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
-
-// *
-// Type of information required by transaction signing process
-// @used_in TxRequest
-type RequestType int32
-
-const (
-	RequestType_TXINPUT     RequestType = 0
-	RequestType_TXOUTPUT    RequestType = 1
-	RequestType_TXMETA      RequestType = 2
-	RequestType_TXFINISHED  RequestType = 3
-	RequestType_TXEXTRADATA RequestType = 4
-)
-
-var RequestType_name = map[int32]string{
-	0: "TXINPUT",
-	1: "TXOUTPUT",
-	2: "TXMETA",
-	3: "TXFINISHED",
-	4: "TXEXTRADATA",
-}
-var RequestType_value = map[string]int32{
-	"TXINPUT":     0,
-	"TXOUTPUT":    1,
-	"TXMETA":      2,
-	"TXFINISHED":  3,
-	"TXEXTRADATA": 4,
-}
-
-func (x RequestType) Enum() *RequestType {
-	p := new(RequestType)
-	*p = x
-	return p
-}
-func (x RequestType) String() string {
-	return proto.EnumName(RequestType_name, int32(x))
-}
-func (x *RequestType) UnmarshalJSON(data []byte) error {
-	value, err := proto.UnmarshalJSONEnum(RequestType_value, data, "RequestType")
-	if err != nil {
-		return err
-	}
-	*x = RequestType(value)
-	return nil
-}
-func (RequestType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
-
-// *
-// Type of button request
-// @used_in ButtonRequest
-type ButtonRequestType int32
-
-const (
-	ButtonRequestType_ButtonRequest_Other            ButtonRequestType = 1
-	ButtonRequestType_ButtonRequest_FeeOverThreshold ButtonRequestType = 2
-	ButtonRequestType_ButtonRequest_ConfirmOutput    ButtonRequestType = 3
-	ButtonRequestType_ButtonRequest_ResetDevice      ButtonRequestType = 4
-	ButtonRequestType_ButtonRequest_ConfirmWord      ButtonRequestType = 5
-	ButtonRequestType_ButtonRequest_WipeDevice       ButtonRequestType = 6
-	ButtonRequestType_ButtonRequest_ProtectCall      ButtonRequestType = 7
-	ButtonRequestType_ButtonRequest_SignTx           ButtonRequestType = 8
-	ButtonRequestType_ButtonRequest_FirmwareCheck    ButtonRequestType = 9
-	ButtonRequestType_ButtonRequest_Address          ButtonRequestType = 10
-	ButtonRequestType_ButtonRequest_PublicKey        ButtonRequestType = 11
-)
-
-var ButtonRequestType_name = map[int32]string{
-	1:  "ButtonRequest_Other",
-	2:  "ButtonRequest_FeeOverThreshold",
-	3:  "ButtonRequest_ConfirmOutput",
-	4:  "ButtonRequest_ResetDevice",
-	5:  "ButtonRequest_ConfirmWord",
-	6:  "ButtonRequest_WipeDevice",
-	7:  "ButtonRequest_ProtectCall",
-	8:  "ButtonRequest_SignTx",
-	9:  "ButtonRequest_FirmwareCheck",
-	10: "ButtonRequest_Address",
-	11: "ButtonRequest_PublicKey",
-}
-var ButtonRequestType_value = map[string]int32{
-	"ButtonRequest_Other":            1,
-	"ButtonRequest_FeeOverThreshold": 2,
-	"ButtonRequest_ConfirmOutput":    3,
-	"ButtonRequest_ResetDevice":      4,
-	"ButtonRequest_ConfirmWord":      5,
-	"ButtonRequest_WipeDevice":       6,
-	"ButtonRequest_ProtectCall":      7,
-	"ButtonRequest_SignTx":           8,
-	"ButtonRequest_FirmwareCheck":    9,
-	"ButtonRequest_Address":          10,
-	"ButtonRequest_PublicKey":        11,
-}
-
-func (x ButtonRequestType) Enum() *ButtonRequestType {
-	p := new(ButtonRequestType)
-	*p = x
-	return p
-}
-func (x ButtonRequestType) String() string {
-	return proto.EnumName(ButtonRequestType_name, int32(x))
-}
-func (x *ButtonRequestType) UnmarshalJSON(data []byte) error {
-	value, err := proto.UnmarshalJSONEnum(ButtonRequestType_value, data, "ButtonRequestType")
-	if err != nil {
-		return err
-	}
-	*x = ButtonRequestType(value)
-	return nil
-}
-func (ButtonRequestType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
-
-// *
-// Type of PIN request
-// @used_in PinMatrixRequest
-type PinMatrixRequestType int32
-
-const (
-	PinMatrixRequestType_PinMatrixRequestType_Current   PinMatrixRequestType = 1
-	PinMatrixRequestType_PinMatrixRequestType_NewFirst  PinMatrixRequestType = 2
-	PinMatrixRequestType_PinMatrixRequestType_NewSecond PinMatrixRequestType = 3
-)
-
-var PinMatrixRequestType_name = map[int32]string{
-	1: "PinMatrixRequestType_Current",
-	2: "PinMatrixRequestType_NewFirst",
-	3: "PinMatrixRequestType_NewSecond",
-}
-var PinMatrixRequestType_value = map[string]int32{
-	"PinMatrixRequestType_Current":   1,
-	"PinMatrixRequestType_NewFirst":  2,
-	"PinMatrixRequestType_NewSecond": 3,
-}
-
-func (x PinMatrixRequestType) Enum() *PinMatrixRequestType {
-	p := new(PinMatrixRequestType)
-	*p = x
-	return p
-}
-func (x PinMatrixRequestType) String() string {
-	return proto.EnumName(PinMatrixRequestType_name, int32(x))
-}
-func (x *PinMatrixRequestType) UnmarshalJSON(data []byte) error {
-	value, err := proto.UnmarshalJSONEnum(PinMatrixRequestType_value, data, "PinMatrixRequestType")
-	if err != nil {
-		return err
-	}
-	*x = PinMatrixRequestType(value)
-	return nil
-}
-func (PinMatrixRequestType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
-
-// *
-// Type of recovery procedure. These should be used as bitmask, e.g.,
-// `RecoveryDeviceType_ScrambledWords | RecoveryDeviceType_Matrix`
-// listing every method supported by the host computer.
-//
-// Note that ScrambledWords must be supported by every implementation
-// for backward compatibility; there is no way to not support it.
-//
-// @used_in RecoveryDevice
-type RecoveryDeviceType int32
-
-const (
-	// use powers of two when extending this field
-	RecoveryDeviceType_RecoveryDeviceType_ScrambledWords RecoveryDeviceType = 0
-	RecoveryDeviceType_RecoveryDeviceType_Matrix         RecoveryDeviceType = 1
-)
-
-var RecoveryDeviceType_name = map[int32]string{
-	0: "RecoveryDeviceType_ScrambledWords",
-	1: "RecoveryDeviceType_Matrix",
-}
-var RecoveryDeviceType_value = map[string]int32{
-	"RecoveryDeviceType_ScrambledWords": 0,
-	"RecoveryDeviceType_Matrix":         1,
-}
-
-func (x RecoveryDeviceType) Enum() *RecoveryDeviceType {
-	p := new(RecoveryDeviceType)
-	*p = x
-	return p
-}
-func (x RecoveryDeviceType) String() string {
-	return proto.EnumName(RecoveryDeviceType_name, int32(x))
-}
-func (x *RecoveryDeviceType) UnmarshalJSON(data []byte) error {
-	value, err := proto.UnmarshalJSONEnum(RecoveryDeviceType_value, data, "RecoveryDeviceType")
-	if err != nil {
-		return err
-	}
-	*x = RecoveryDeviceType(value)
-	return nil
-}
-func (RecoveryDeviceType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
-
-// *
-// Type of Recovery Word request
-// @used_in WordRequest
-type WordRequestType int32
-
-const (
-	WordRequestType_WordRequestType_Plain   WordRequestType = 0
-	WordRequestType_WordRequestType_Matrix9 WordRequestType = 1
-	WordRequestType_WordRequestType_Matrix6 WordRequestType = 2
-)
-
-var WordRequestType_name = map[int32]string{
-	0: "WordRequestType_Plain",
-	1: "WordRequestType_Matrix9",
-	2: "WordRequestType_Matrix6",
-}
-var WordRequestType_value = map[string]int32{
-	"WordRequestType_Plain":   0,
-	"WordRequestType_Matrix9": 1,
-	"WordRequestType_Matrix6": 2,
-}
-
-func (x WordRequestType) Enum() *WordRequestType {
-	p := new(WordRequestType)
-	*p = x
-	return p
-}
-func (x WordRequestType) String() string {
-	return proto.EnumName(WordRequestType_name, int32(x))
-}
-func (x *WordRequestType) UnmarshalJSON(data []byte) error {
-	value, err := proto.UnmarshalJSONEnum(WordRequestType_value, data, "WordRequestType")
-	if err != nil {
-		return err
-	}
-	*x = WordRequestType(value)
-	return nil
-}
-func (WordRequestType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
-
-// *
-// Structure representing BIP32 (hierarchical deterministic) node
-// Used for imports of private key into the device and exporting public key out of device
-// @used_in PublicKey
-// @used_in LoadDevice
-// @used_in DebugLinkState
-// @used_in Storage
-type HDNodeType struct {
-	Depth            *uint32 `protobuf:"varint,1,req,name=depth" json:"depth,omitempty"`
-	Fingerprint      *uint32 `protobuf:"varint,2,req,name=fingerprint" json:"fingerprint,omitempty"`
-	ChildNum         *uint32 `protobuf:"varint,3,req,name=child_num,json=childNum" json:"child_num,omitempty"`
-	ChainCode        []byte  `protobuf:"bytes,4,req,name=chain_code,json=chainCode" json:"chain_code,omitempty"`
-	PrivateKey       []byte  `protobuf:"bytes,5,opt,name=private_key,json=privateKey" json:"private_key,omitempty"`
-	PublicKey        []byte  `protobuf:"bytes,6,opt,name=public_key,json=publicKey" json:"public_key,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *HDNodeType) Reset()                    { *m = HDNodeType{} }
-func (m *HDNodeType) String() string            { return proto.CompactTextString(m) }
-func (*HDNodeType) ProtoMessage()               {}
-func (*HDNodeType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
-
-func (m *HDNodeType) GetDepth() uint32 {
-	if m != nil && m.Depth != nil {
-		return *m.Depth
-	}
-	return 0
-}
-
-func (m *HDNodeType) GetFingerprint() uint32 {
-	if m != nil && m.Fingerprint != nil {
-		return *m.Fingerprint
-	}
-	return 0
-}
-
-func (m *HDNodeType) GetChildNum() uint32 {
-	if m != nil && m.ChildNum != nil {
-		return *m.ChildNum
-	}
-	return 0
-}
-
-func (m *HDNodeType) GetChainCode() []byte {
-	if m != nil {
-		return m.ChainCode
-	}
-	return nil
-}
-
-func (m *HDNodeType) GetPrivateKey() []byte {
-	if m != nil {
-		return m.PrivateKey
-	}
-	return nil
-}
-
-func (m *HDNodeType) GetPublicKey() []byte {
-	if m != nil {
-		return m.PublicKey
-	}
-	return nil
-}
-
-type HDNodePathType struct {
-	Node             *HDNodeType `protobuf:"bytes,1,req,name=node" json:"node,omitempty"`
-	AddressN         []uint32    `protobuf:"varint,2,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
-	XXX_unrecognized []byte      `json:"-"`
-}
-
-func (m *HDNodePathType) Reset()                    { *m = HDNodePathType{} }
-func (m *HDNodePathType) String() string            { return proto.CompactTextString(m) }
-func (*HDNodePathType) ProtoMessage()               {}
-func (*HDNodePathType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
-
-func (m *HDNodePathType) GetNode() *HDNodeType {
-	if m != nil {
-		return m.Node
-	}
-	return nil
-}
-
-func (m *HDNodePathType) GetAddressN() []uint32 {
-	if m != nil {
-		return m.AddressN
-	}
-	return nil
-}
-
-// *
-// Structure representing Coin
-// @used_in Features
-type CoinType struct {
-	CoinName            *string `protobuf:"bytes,1,opt,name=coin_name,json=coinName" json:"coin_name,omitempty"`
-	CoinShortcut        *string `protobuf:"bytes,2,opt,name=coin_shortcut,json=coinShortcut" json:"coin_shortcut,omitempty"`
-	AddressType         *uint32 `protobuf:"varint,3,opt,name=address_type,json=addressType,def=0" json:"address_type,omitempty"`
-	MaxfeeKb            *uint64 `protobuf:"varint,4,opt,name=maxfee_kb,json=maxfeeKb" json:"maxfee_kb,omitempty"`
-	AddressTypeP2Sh     *uint32 `protobuf:"varint,5,opt,name=address_type_p2sh,json=addressTypeP2sh,def=5" json:"address_type_p2sh,omitempty"`
-	SignedMessageHeader *string `protobuf:"bytes,8,opt,name=signed_message_header,json=signedMessageHeader" json:"signed_message_header,omitempty"`
-	XpubMagic           *uint32 `protobuf:"varint,9,opt,name=xpub_magic,json=xpubMagic,def=76067358" json:"xpub_magic,omitempty"`
-	XprvMagic           *uint32 `protobuf:"varint,10,opt,name=xprv_magic,json=xprvMagic,def=76066276" json:"xprv_magic,omitempty"`
-	Segwit              *bool   `protobuf:"varint,11,opt,name=segwit" json:"segwit,omitempty"`
-	Forkid              *uint32 `protobuf:"varint,12,opt,name=forkid" json:"forkid,omitempty"`
-	XXX_unrecognized    []byte  `json:"-"`
-}
-
-func (m *CoinType) Reset()                    { *m = CoinType{} }
-func (m *CoinType) String() string            { return proto.CompactTextString(m) }
-func (*CoinType) ProtoMessage()               {}
-func (*CoinType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
-
-const Default_CoinType_AddressType uint32 = 0
-const Default_CoinType_AddressTypeP2Sh uint32 = 5
-const Default_CoinType_XpubMagic uint32 = 76067358
-const Default_CoinType_XprvMagic uint32 = 76066276
-
-func (m *CoinType) GetCoinName() string {
-	if m != nil && m.CoinName != nil {
-		return *m.CoinName
-	}
-	return ""
-}
-
-func (m *CoinType) GetCoinShortcut() string {
-	if m != nil && m.CoinShortcut != nil {
-		return *m.CoinShortcut
-	}
-	return ""
-}
-
-func (m *CoinType) GetAddressType() uint32 {
-	if m != nil && m.AddressType != nil {
-		return *m.AddressType
-	}
-	return Default_CoinType_AddressType
-}
-
-func (m *CoinType) GetMaxfeeKb() uint64 {
-	if m != nil && m.MaxfeeKb != nil {
-		return *m.MaxfeeKb
-	}
-	return 0
-}
-
-func (m *CoinType) GetAddressTypeP2Sh() uint32 {
-	if m != nil && m.AddressTypeP2Sh != nil {
-		return *m.AddressTypeP2Sh
-	}
-	return Default_CoinType_AddressTypeP2Sh
-}
-
-func (m *CoinType) GetSignedMessageHeader() string {
-	if m != nil && m.SignedMessageHeader != nil {
-		return *m.SignedMessageHeader
-	}
-	return ""
-}
-
-func (m *CoinType) GetXpubMagic() uint32 {
-	if m != nil && m.XpubMagic != nil {
-		return *m.XpubMagic
-	}
-	return Default_CoinType_XpubMagic
-}
-
-func (m *CoinType) GetXprvMagic() uint32 {
-	if m != nil && m.XprvMagic != nil {
-		return *m.XprvMagic
-	}
-	return Default_CoinType_XprvMagic
-}
-
-func (m *CoinType) GetSegwit() bool {
-	if m != nil && m.Segwit != nil {
-		return *m.Segwit
-	}
-	return false
-}
-
-func (m *CoinType) GetForkid() uint32 {
-	if m != nil && m.Forkid != nil {
-		return *m.Forkid
-	}
-	return 0
-}
-
-// *
-// Type of redeem script used in input
-// @used_in TxInputType
-type MultisigRedeemScriptType struct {
-	Pubkeys          []*HDNodePathType `protobuf:"bytes,1,rep,name=pubkeys" json:"pubkeys,omitempty"`
-	Signatures       [][]byte          `protobuf:"bytes,2,rep,name=signatures" json:"signatures,omitempty"`
-	M                *uint32           `protobuf:"varint,3,opt,name=m" json:"m,omitempty"`
-	XXX_unrecognized []byte            `json:"-"`
-}
-
-func (m *MultisigRedeemScriptType) Reset()                    { *m = MultisigRedeemScriptType{} }
-func (m *MultisigRedeemScriptType) String() string            { return proto.CompactTextString(m) }
-func (*MultisigRedeemScriptType) ProtoMessage()               {}
-func (*MultisigRedeemScriptType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
-
-func (m *MultisigRedeemScriptType) GetPubkeys() []*HDNodePathType {
-	if m != nil {
-		return m.Pubkeys
-	}
-	return nil
-}
-
-func (m *MultisigRedeemScriptType) GetSignatures() [][]byte {
-	if m != nil {
-		return m.Signatures
-	}
-	return nil
-}
-
-func (m *MultisigRedeemScriptType) GetM() uint32 {
-	if m != nil && m.M != nil {
-		return *m.M
-	}
-	return 0
-}
-
-// *
-// Structure representing transaction input
-// @used_in SimpleSignTx
-// @used_in TransactionType
-type TxInputType struct {
-	AddressN         []uint32                  `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
-	PrevHash         []byte                    `protobuf:"bytes,2,req,name=prev_hash,json=prevHash" json:"prev_hash,omitempty"`
-	PrevIndex        *uint32                   `protobuf:"varint,3,req,name=prev_index,json=prevIndex" json:"prev_index,omitempty"`
-	ScriptSig        []byte                    `protobuf:"bytes,4,opt,name=script_sig,json=scriptSig" json:"script_sig,omitempty"`
-	Sequence         *uint32                   `protobuf:"varint,5,opt,name=sequence,def=4294967295" json:"sequence,omitempty"`
-	ScriptType       *InputScriptType          `protobuf:"varint,6,opt,name=script_type,json=scriptType,enum=InputScriptType,def=0" json:"script_type,omitempty"`
-	Multisig         *MultisigRedeemScriptType `protobuf:"bytes,7,opt,name=multisig" json:"multisig,omitempty"`
-	Amount           *uint64                   `protobuf:"varint,8,opt,name=amount" json:"amount,omitempty"`
-	XXX_unrecognized []byte                    `json:"-"`
-}
-
-func (m *TxInputType) Reset()                    { *m = TxInputType{} }
-func (m *TxInputType) String() string            { return proto.CompactTextString(m) }
-func (*TxInputType) ProtoMessage()               {}
-func (*TxInputType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
-
-const Default_TxInputType_Sequence uint32 = 4294967295
-const Default_TxInputType_ScriptType InputScriptType = InputScriptType_SPENDADDRESS
-
-func (m *TxInputType) GetAddressN() []uint32 {
-	if m != nil {
-		return m.AddressN
-	}
-	return nil
-}
-
-func (m *TxInputType) GetPrevHash() []byte {
-	if m != nil {
-		return m.PrevHash
-	}
-	return nil
-}
-
-func (m *TxInputType) GetPrevIndex() uint32 {
-	if m != nil && m.PrevIndex != nil {
-		return *m.PrevIndex
-	}
-	return 0
-}
-
-func (m *TxInputType) GetScriptSig() []byte {
-	if m != nil {
-		return m.ScriptSig
-	}
-	return nil
-}
-
-func (m *TxInputType) GetSequence() uint32 {
-	if m != nil && m.Sequence != nil {
-		return *m.Sequence
-	}
-	return Default_TxInputType_Sequence
-}
-
-func (m *TxInputType) GetScriptType() InputScriptType {
-	if m != nil && m.ScriptType != nil {
-		return *m.ScriptType
-	}
-	return Default_TxInputType_ScriptType
-}
-
-func (m *TxInputType) GetMultisig() *MultisigRedeemScriptType {
-	if m != nil {
-		return m.Multisig
-	}
-	return nil
-}
-
-func (m *TxInputType) GetAmount() uint64 {
-	if m != nil && m.Amount != nil {
-		return *m.Amount
-	}
-	return 0
-}
-
-// *
-// Structure representing transaction output
-// @used_in SimpleSignTx
-// @used_in TransactionType
-type TxOutputType struct {
-	Address          *string                   `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"`
-	AddressN         []uint32                  `protobuf:"varint,2,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
-	Amount           *uint64                   `protobuf:"varint,3,req,name=amount" json:"amount,omitempty"`
-	ScriptType       *OutputScriptType         `protobuf:"varint,4,req,name=script_type,json=scriptType,enum=OutputScriptType" json:"script_type,omitempty"`
-	Multisig         *MultisigRedeemScriptType `protobuf:"bytes,5,opt,name=multisig" json:"multisig,omitempty"`
-	OpReturnData     []byte                    `protobuf:"bytes,6,opt,name=op_return_data,json=opReturnData" json:"op_return_data,omitempty"`
-	XXX_unrecognized []byte                    `json:"-"`
-}
-
-func (m *TxOutputType) Reset()                    { *m = TxOutputType{} }
-func (m *TxOutputType) String() string            { return proto.CompactTextString(m) }
-func (*TxOutputType) ProtoMessage()               {}
-func (*TxOutputType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
-
-func (m *TxOutputType) GetAddress() string {
-	if m != nil && m.Address != nil {
-		return *m.Address
-	}
-	return ""
-}
-
-func (m *TxOutputType) GetAddressN() []uint32 {
-	if m != nil {
-		return m.AddressN
-	}
-	return nil
-}
-
-func (m *TxOutputType) GetAmount() uint64 {
-	if m != nil && m.Amount != nil {
-		return *m.Amount
-	}
-	return 0
-}
-
-func (m *TxOutputType) GetScriptType() OutputScriptType {
-	if m != nil && m.ScriptType != nil {
-		return *m.ScriptType
-	}
-	return OutputScriptType_PAYTOADDRESS
-}
-
-func (m *TxOutputType) GetMultisig() *MultisigRedeemScriptType {
-	if m != nil {
-		return m.Multisig
-	}
-	return nil
-}
-
-func (m *TxOutputType) GetOpReturnData() []byte {
-	if m != nil {
-		return m.OpReturnData
-	}
-	return nil
-}
-
-// *
-// Structure representing compiled transaction output
-// @used_in TransactionType
-type TxOutputBinType struct {
-	Amount           *uint64 `protobuf:"varint,1,req,name=amount" json:"amount,omitempty"`
-	ScriptPubkey     []byte  `protobuf:"bytes,2,req,name=script_pubkey,json=scriptPubkey" json:"script_pubkey,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *TxOutputBinType) Reset()                    { *m = TxOutputBinType{} }
-func (m *TxOutputBinType) String() string            { return proto.CompactTextString(m) }
-func (*TxOutputBinType) ProtoMessage()               {}
-func (*TxOutputBinType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
-
-func (m *TxOutputBinType) GetAmount() uint64 {
-	if m != nil && m.Amount != nil {
-		return *m.Amount
-	}
-	return 0
-}
-
-func (m *TxOutputBinType) GetScriptPubkey() []byte {
-	if m != nil {
-		return m.ScriptPubkey
-	}
-	return nil
-}
-
-// *
-// Structure representing transaction
-// @used_in SimpleSignTx
-type TransactionType struct {
-	Version          *uint32            `protobuf:"varint,1,opt,name=version" json:"version,omitempty"`
-	Inputs           []*TxInputType     `protobuf:"bytes,2,rep,name=inputs" json:"inputs,omitempty"`
-	BinOutputs       []*TxOutputBinType `protobuf:"bytes,3,rep,name=bin_outputs,json=binOutputs" json:"bin_outputs,omitempty"`
-	Outputs          []*TxOutputType    `protobuf:"bytes,5,rep,name=outputs" json:"outputs,omitempty"`
-	LockTime         *uint32            `protobuf:"varint,4,opt,name=lock_time,json=lockTime" json:"lock_time,omitempty"`
-	InputsCnt        *uint32            `protobuf:"varint,6,opt,name=inputs_cnt,json=inputsCnt" json:"inputs_cnt,omitempty"`
-	OutputsCnt       *uint32            `protobuf:"varint,7,opt,name=outputs_cnt,json=outputsCnt" json:"outputs_cnt,omitempty"`
-	ExtraData        []byte             `protobuf:"bytes,8,opt,name=extra_data,json=extraData" json:"extra_data,omitempty"`
-	ExtraDataLen     *uint32            `protobuf:"varint,9,opt,name=extra_data_len,json=extraDataLen" json:"extra_data_len,omitempty"`
-	XXX_unrecognized []byte             `json:"-"`
-}
-
-func (m *TransactionType) Reset()                    { *m = TransactionType{} }
-func (m *TransactionType) String() string            { return proto.CompactTextString(m) }
-func (*TransactionType) ProtoMessage()               {}
-func (*TransactionType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
-
-func (m *TransactionType) GetVersion() uint32 {
-	if m != nil && m.Version != nil {
-		return *m.Version
-	}
-	return 0
-}
-
-func (m *TransactionType) GetInputs() []*TxInputType {
-	if m != nil {
-		return m.Inputs
-	}
-	return nil
-}
-
-func (m *TransactionType) GetBinOutputs() []*TxOutputBinType {
-	if m != nil {
-		return m.BinOutputs
-	}
-	return nil
-}
-
-func (m *TransactionType) GetOutputs() []*TxOutputType {
-	if m != nil {
-		return m.Outputs
-	}
-	return nil
-}
-
-func (m *TransactionType) GetLockTime() uint32 {
-	if m != nil && m.LockTime != nil {
-		return *m.LockTime
-	}
-	return 0
-}
-
-func (m *TransactionType) GetInputsCnt() uint32 {
-	if m != nil && m.InputsCnt != nil {
-		return *m.InputsCnt
-	}
-	return 0
-}
-
-func (m *TransactionType) GetOutputsCnt() uint32 {
-	if m != nil && m.OutputsCnt != nil {
-		return *m.OutputsCnt
-	}
-	return 0
-}
-
-func (m *TransactionType) GetExtraData() []byte {
-	if m != nil {
-		return m.ExtraData
-	}
-	return nil
-}
-
-func (m *TransactionType) GetExtraDataLen() uint32 {
-	if m != nil && m.ExtraDataLen != nil {
-		return *m.ExtraDataLen
-	}
-	return 0
-}
-
-// *
-// Structure representing request details
-// @used_in TxRequest
-type TxRequestDetailsType struct {
-	RequestIndex     *uint32 `protobuf:"varint,1,opt,name=request_index,json=requestIndex" json:"request_index,omitempty"`
-	TxHash           []byte  `protobuf:"bytes,2,opt,name=tx_hash,json=txHash" json:"tx_hash,omitempty"`
-	ExtraDataLen     *uint32 `protobuf:"varint,3,opt,name=extra_data_len,json=extraDataLen" json:"extra_data_len,omitempty"`
-	ExtraDataOffset  *uint32 `protobuf:"varint,4,opt,name=extra_data_offset,json=extraDataOffset" json:"extra_data_offset,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *TxRequestDetailsType) Reset()                    { *m = TxRequestDetailsType{} }
-func (m *TxRequestDetailsType) String() string            { return proto.CompactTextString(m) }
-func (*TxRequestDetailsType) ProtoMessage()               {}
-func (*TxRequestDetailsType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
-
-func (m *TxRequestDetailsType) GetRequestIndex() uint32 {
-	if m != nil && m.RequestIndex != nil {
-		return *m.RequestIndex
-	}
-	return 0
-}
-
-func (m *TxRequestDetailsType) GetTxHash() []byte {
-	if m != nil {
-		return m.TxHash
-	}
-	return nil
-}
-
-func (m *TxRequestDetailsType) GetExtraDataLen() uint32 {
-	if m != nil && m.ExtraDataLen != nil {
-		return *m.ExtraDataLen
-	}
-	return 0
-}
-
-func (m *TxRequestDetailsType) GetExtraDataOffset() uint32 {
-	if m != nil && m.ExtraDataOffset != nil {
-		return *m.ExtraDataOffset
-	}
-	return 0
-}
-
-// *
-// Structure representing serialized data
-// @used_in TxRequest
-type TxRequestSerializedType struct {
-	SignatureIndex   *uint32 `protobuf:"varint,1,opt,name=signature_index,json=signatureIndex" json:"signature_index,omitempty"`
-	Signature        []byte  `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"`
-	SerializedTx     []byte  `protobuf:"bytes,3,opt,name=serialized_tx,json=serializedTx" json:"serialized_tx,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *TxRequestSerializedType) Reset()                    { *m = TxRequestSerializedType{} }
-func (m *TxRequestSerializedType) String() string            { return proto.CompactTextString(m) }
-func (*TxRequestSerializedType) ProtoMessage()               {}
-func (*TxRequestSerializedType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
-
-func (m *TxRequestSerializedType) GetSignatureIndex() uint32 {
-	if m != nil && m.SignatureIndex != nil {
-		return *m.SignatureIndex
-	}
-	return 0
-}
-
-func (m *TxRequestSerializedType) GetSignature() []byte {
-	if m != nil {
-		return m.Signature
-	}
-	return nil
-}
-
-func (m *TxRequestSerializedType) GetSerializedTx() []byte {
-	if m != nil {
-		return m.SerializedTx
-	}
-	return nil
-}
-
-// *
-// Structure representing identity data
-// @used_in IdentityType
-type IdentityType struct {
-	Proto            *string `protobuf:"bytes,1,opt,name=proto" json:"proto,omitempty"`
-	User             *string `protobuf:"bytes,2,opt,name=user" json:"user,omitempty"`
-	Host             *string `protobuf:"bytes,3,opt,name=host" json:"host,omitempty"`
-	Port             *string `protobuf:"bytes,4,opt,name=port" json:"port,omitempty"`
-	Path             *string `protobuf:"bytes,5,opt,name=path" json:"path,omitempty"`
-	Index            *uint32 `protobuf:"varint,6,opt,name=index,def=0" json:"index,omitempty"`
-	XXX_unrecognized []byte  `json:"-"`
-}
-
-func (m *IdentityType) Reset()                    { *m = IdentityType{} }
-func (m *IdentityType) String() string            { return proto.CompactTextString(m) }
-func (*IdentityType) ProtoMessage()               {}
-func (*IdentityType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
-
-const Default_IdentityType_Index uint32 = 0
-
-func (m *IdentityType) GetProto() string {
-	if m != nil && m.Proto != nil {
-		return *m.Proto
-	}
-	return ""
-}
-
-func (m *IdentityType) GetUser() string {
-	if m != nil && m.User != nil {
-		return *m.User
-	}
-	return ""
-}
-
-func (m *IdentityType) GetHost() string {
-	if m != nil && m.Host != nil {
-		return *m.Host
-	}
-	return ""
-}
-
-func (m *IdentityType) GetPort() string {
-	if m != nil && m.Port != nil {
-		return *m.Port
-	}
-	return ""
-}
-
-func (m *IdentityType) GetPath() string {
-	if m != nil && m.Path != nil {
-		return *m.Path
-	}
-	return ""
-}
-
-func (m *IdentityType) GetIndex() uint32 {
-	if m != nil && m.Index != nil {
-		return *m.Index
-	}
-	return Default_IdentityType_Index
-}
-
-var E_WireIn = &proto.ExtensionDesc{
-	ExtendedType:  (*google_protobuf.EnumValueOptions)(nil),
-	ExtensionType: (*bool)(nil),
-	Field:         50002,
-	Name:          "wire_in",
-	Tag:           "varint,50002,opt,name=wire_in,json=wireIn",
-	Filename:      "types.proto",
-}
-
-var E_WireOut = &proto.ExtensionDesc{
-	ExtendedType:  (*google_protobuf.EnumValueOptions)(nil),
-	ExtensionType: (*bool)(nil),
-	Field:         50003,
-	Name:          "wire_out",
-	Tag:           "varint,50003,opt,name=wire_out,json=wireOut",
-	Filename:      "types.proto",
-}
-
-var E_WireDebugIn = &proto.ExtensionDesc{
-	ExtendedType:  (*google_protobuf.EnumValueOptions)(nil),
-	ExtensionType: (*bool)(nil),
-	Field:         50004,
-	Name:          "wire_debug_in",
-	Tag:           "varint,50004,opt,name=wire_debug_in,json=wireDebugIn",
-	Filename:      "types.proto",
-}
-
-var E_WireDebugOut = &proto.ExtensionDesc{
-	ExtendedType:  (*google_protobuf.EnumValueOptions)(nil),
-	ExtensionType: (*bool)(nil),
-	Field:         50005,
-	Name:          "wire_debug_out",
-	Tag:           "varint,50005,opt,name=wire_debug_out,json=wireDebugOut",
-	Filename:      "types.proto",
-}
-
-var E_WireTiny = &proto.ExtensionDesc{
-	ExtendedType:  (*google_protobuf.EnumValueOptions)(nil),
-	ExtensionType: (*bool)(nil),
-	Field:         50006,
-	Name:          "wire_tiny",
-	Tag:           "varint,50006,opt,name=wire_tiny,json=wireTiny",
-	Filename:      "types.proto",
-}
-
-var E_WireBootloader = &proto.ExtensionDesc{
-	ExtendedType:  (*google_protobuf.EnumValueOptions)(nil),
-	ExtensionType: (*bool)(nil),
-	Field:         50007,
-	Name:          "wire_bootloader",
-	Tag:           "varint,50007,opt,name=wire_bootloader,json=wireBootloader",
-	Filename:      "types.proto",
-}
-
-func init() {
-	proto.RegisterType((*HDNodeType)(nil), "HDNodeType")
-	proto.RegisterType((*HDNodePathType)(nil), "HDNodePathType")
-	proto.RegisterType((*CoinType)(nil), "CoinType")
-	proto.RegisterType((*MultisigRedeemScriptType)(nil), "MultisigRedeemScriptType")
-	proto.RegisterType((*TxInputType)(nil), "TxInputType")
-	proto.RegisterType((*TxOutputType)(nil), "TxOutputType")
-	proto.RegisterType((*TxOutputBinType)(nil), "TxOutputBinType")
-	proto.RegisterType((*TransactionType)(nil), "TransactionType")
-	proto.RegisterType((*TxRequestDetailsType)(nil), "TxRequestDetailsType")
-	proto.RegisterType((*TxRequestSerializedType)(nil), "TxRequestSerializedType")
-	proto.RegisterType((*IdentityType)(nil), "IdentityType")
-	proto.RegisterEnum("FailureType", FailureType_name, FailureType_value)
-	proto.RegisterEnum("OutputScriptType", OutputScriptType_name, OutputScriptType_value)
-	proto.RegisterEnum("InputScriptType", InputScriptType_name, InputScriptType_value)
-	proto.RegisterEnum("RequestType", RequestType_name, RequestType_value)
-	proto.RegisterEnum("ButtonRequestType", ButtonRequestType_name, ButtonRequestType_value)
-	proto.RegisterEnum("PinMatrixRequestType", PinMatrixRequestType_name, PinMatrixRequestType_value)
-	proto.RegisterEnum("RecoveryDeviceType", RecoveryDeviceType_name, RecoveryDeviceType_value)
-	proto.RegisterEnum("WordRequestType", WordRequestType_name, WordRequestType_value)
-	proto.RegisterExtension(E_WireIn)
-	proto.RegisterExtension(E_WireOut)
-	proto.RegisterExtension(E_WireDebugIn)
-	proto.RegisterExtension(E_WireDebugOut)
-	proto.RegisterExtension(E_WireTiny)
-	proto.RegisterExtension(E_WireBootloader)
-}
-
-func init() { proto.RegisterFile("types.proto", fileDescriptor0) }
-
-var fileDescriptor0 = []byte{
-	// 1899 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x57, 0xdb, 0x72, 0x1a, 0xc9,
-	0x19, 0xf6, 0x00, 0x92, 0xe0, 0x07, 0xc4, 0xa8, 0x7d, 0xd0, 0x78, 0x6d, 0xaf, 0x31, 0x76, 0x62,
-	0x45, 0x55, 0x61, 0x77, 0xc9, 0x5a, 0x8e, 0x55, 0xa9, 0x24, 0x3a, 0xa0, 0x15, 0x65, 0x0b, 0x51,
-	0xc3, 0x28, 0x56, 0x72, 0x33, 0x35, 0xcc, 0xb4, 0xa0, 0x4b, 0x43, 0x37, 0xe9, 0xe9, 0x91, 0xd1,
-	0xde, 0xe4, 0x2a, 0xc9, 0x55, 0x5e, 0x23, 0x6f, 0x91, 0xaa, 0xbc, 0x41, 0xaa, 0x36, 0xa7, 0xcb,
-	0xbc, 0x41, 0xae, 0xf2, 0x00, 0xa9, 0x3e, 0x0c, 0x02, 0xc9, 0xde, 0xd2, 0x1d, 0xfd, 0x7d, 0xff,
-	0xf9, 0xd0, 0x3d, 0x40, 0x59, 0x5c, 0x4e, 0x70, 0xd2, 0x9c, 0x70, 0x26, 0xd8, 0x67, 0xf5, 0x21,
-	0x63, 0xc3, 0x18, 0x7f, 0xa1, 0x4e, 0x83, 0xf4, 0xec, 0x8b, 0x08, 0x27, 0x21, 0x27, 0x13, 0xc1,
-	0xb8, 0x96, 0x68, 0xfc, 0xd5, 0x02, 0x38, 0xdc, 0xef, 0xb2, 0x08, 0x7b, 0x97, 0x13, 0x8c, 0xee,
-	0xc1, 0x52, 0x84, 0x27, 0x62, 0xe4, 0x58, 0xf5, 0xdc, 0x46, 0xd5, 0xd5, 0x07, 0x54, 0x87, 0xf2,
-	0x19, 0xa1, 0x43, 0xcc, 0x27, 0x9c, 0x50, 0xe1, 0xe4, 0x14, 0x37, 0x0f, 0xa1, 0x47, 0x50, 0x0a,
-	0x47, 0x24, 0x8e, 0x7c, 0x9a, 0x8e, 0x9d, 0xbc, 0xe2, 0x8b, 0x0a, 0xe8, 0xa6, 0x63, 0xf4, 0x04,
-	0x20, 0x1c, 0x05, 0x84, 0xfa, 0x21, 0x8b, 0xb0, 0x53, 0xa8, 0xe7, 0x36, 0x2a, 0x6e, 0x49, 0x21,
-	0x7b, 0x2c, 0xc2, 0xe8, 0x29, 0x94, 0x27, 0x9c, 0x5c, 0x04, 0x02, 0xfb, 0xe7, 0xf8, 0xd2, 0x59,
-	0xaa, 0x5b, 0x1b, 0x15, 0x17, 0x0c, 0xf4, 0x16, 0x5f, 0x4a, 0xfd, 0x49, 0x3a, 0x88, 0x49, 0xa8,
-	0xf8, 0x65, 0xc5, 0x97, 0x34, 0xf2, 0x16, 0x5f, 0x36, 0xba, 0xb0, 0xaa, 0x33, 0xe8, 0x05, 0x62,
-	0xa4, 0xb2, 0x78, 0x0a, 0x05, 0x2a, 0x5d, 0xc9, 0x24, 0xca, 0xad, 0x72, 0xf3, 0x2a, 0x41, 0x57,
-	0x11, 0x32, 0xdc, 0x20, 0x8a, 0x38, 0x4e, 0x12, 0x9f, 0x3a, 0xb9, 0x7a, 0x5e, 0x86, 0x6b, 0x80,
-	0x6e, 0xe3, 0x7f, 0x39, 0x28, 0xee, 0x31, 0x42, 0x95, 0x29, 0x99, 0x18, 0x23, 0xd4, 0xa7, 0xc1,
-	0x58, 0xda, 0xb3, 0x36, 0x4a, 0x6e, 0x51, 0x02, 0xdd, 0x60, 0x8c, 0xd1, 0x73, 0xa8, 0x2a, 0x32,
-	0x19, 0x31, 0x2e, 0xc2, 0x54, 0x56, 0x46, 0x0a, 0x54, 0x24, 0xd8, 0x37, 0x18, 0x7a, 0x01, 0x95,
-	0xcc, 0x97, 0x6c, 0x8d, 0x93, 0xaf, 0x5b, 0x1b, 0xd5, 0x6d, 0xeb, 0x4b, 0xb7, 0x6c, 0xe0, 0xcc,
-	0xcf, 0x38, 0x98, 0x9e, 0x61, 0xec, 0x9f, 0x0f, 0x9c, 0x42, 0xdd, 0xda, 0x28, 0xb8, 0x45, 0x0d,
-	0xbc, 0x1d, 0xa0, 0x1f, 0xc3, 0xda, 0xbc, 0x09, 0x7f, 0xd2, 0x4a, 0x46, 0xaa, 0x4e, 0xd5, 0x6d,
-	0xeb, 0x95, 0x5b, 0x9b, 0xb3, 0xd3, 0x6b, 0x25, 0x23, 0xd4, 0x82, 0xfb, 0x09, 0x19, 0x52, 0x1c,
-	0xf9, 0x63, 0x9c, 0x24, 0xc1, 0x10, 0xfb, 0x23, 0x1c, 0x44, 0x98, 0x3b, 0x45, 0x15, 0xde, 0x5d,
-	0x4d, 0x1e, 0x69, 0xee, 0x50, 0x51, 0xe8, 0x25, 0xc0, 0x74, 0x92, 0x0e, 0xfc, 0x71, 0x30, 0x24,
-	0xa1, 0x53, 0x52, 0xb6, 0x8b, 0xaf, 0xb7, 0xbe, 0xdc, 0x7a, 0xfd, 0x93, 0x57, 0x3f, 0x75, 0x4b,
-	0x92, 0x3b, 0x92, 0x94, 0x16, 0xe4, 0x17, 0x46, 0x10, 0xae, 0x04, 0xb7, 0x5a, 0xaf, 0xb7, 0xa4,
-	0x20, 0xbf, 0xd0, 0x82, 0x0f, 0x60, 0x39, 0xc1, 0xc3, 0x0f, 0x44, 0x38, 0xe5, 0xba, 0xb5, 0x51,
-	0x74, 0xcd, 0x49, 0xe2, 0x67, 0x8c, 0x9f, 0x93, 0xc8, 0xa9, 0x48, 0x65, 0xd7, 0x9c, 0x1a, 0x09,
-	0x38, 0x47, 0x69, 0x2c, 0x48, 0x42, 0x86, 0x2e, 0x8e, 0x30, 0x1e, 0xf7, 0xd5, 0xa4, 0xaa, 0xea,
-	0xfc, 0x08, 0x56, 0x26, 0xe9, 0xe0, 0x1c, 0x5f, 0x26, 0x8e, 0x55, 0xcf, 0x6f, 0x94, 0x5b, 0xb5,
-	0xe6, 0x62, 0xcb, 0xdd, 0x8c, 0x47, 0x9f, 0x03, 0xc8, 0xfc, 0x02, 0x91, 0x72, 0x9c, 0xa8, 0xde,
-	0x56, 0xdc, 0x39, 0x04, 0x55, 0xc0, 0x1a, 0xeb, 0x1e, 0xb8, 0xd6, 0xb8, 0xf1, 0x97, 0x1c, 0x94,
-	0xbd, 0x69, 0x87, 0x4e, 0x52, 0x91, 0xb5, 0xe1, 0x6a, 0x30, 0xac, 0xc5, 0xc1, 0x90, 0xe4, 0x84,
-	0xe3, 0x0b, 0x7f, 0x14, 0x24, 0x23, 0xb5, 0x04, 0x15, 0xb7, 0x28, 0x81, 0xc3, 0x20, 0x19, 0xa9,
-	0x21, 0x95, 0x24, 0xa1, 0x11, 0x9e, 0x9a, 0x15, 0x50, 0xe2, 0x1d, 0x09, 0x48, 0x5a, 0x6f, 0x9e,
-	0x9f, 0x90, 0xa1, 0x6a, 0x70, 0xc5, 0x2d, 0x69, 0xa4, 0x4f, 0x86, 0xe8, 0x87, 0x50, 0x4c, 0xf0,
-	0x6f, 0x53, 0x4c, 0x43, 0x6c, 0x1a, 0x0b, 0x5f, 0xb7, 0xde, 0x7c, 0xfd, 0x66, 0xeb, 0x75, 0xeb,
-	0xcd, 0x2b, 0x77, 0xc6, 0xa1, 0x5f, 0x40, 0xd9, 0x98, 0x51, 0xb3, 0x24, 0x77, 0x61, 0xb5, 0x65,
-	0x37, 0x55, 0x02, 0x57, 0xf5, 0xda, 0xae, 0xf4, 0x7b, 0xed, 0xee, 0xfe, 0xce, 0xfe, 0xbe, 0xdb,
-	0xee, 0xf7, 0x5d, 0xe3, 0x59, 0x25, 0xf8, 0x0a, 0x8a, 0x63, 0x53, 0x65, 0x67, 0xa5, 0x6e, 0x6d,
-	0x94, 0x5b, 0x0f, 0x9b, 0x9f, 0x2a, 0xbb, 0x3b, 0x13, 0x95, 0x4d, 0x0b, 0xc6, 0x2c, 0xa5, 0x42,
-	0xcd, 0x50, 0xc1, 0x35, 0xa7, 0xc6, 0x7f, 0x2d, 0xa8, 0x78, 0xd3, 0xe3, 0x54, 0x64, 0x05, 0x74,
-	0x60, 0xc5, 0xd4, 0xcb, 0x6c, 0x4b, 0x76, 0xfc, 0xde, 0x9d, 0x9b, 0xb3, 0x2f, 0x2b, 0x37, 0xb3,
-	0x8f, 0x5a, 0x8b, 0xf9, 0xca, 0xbb, 0x63, 0xb5, 0xb5, 0xd6, 0xd4, 0x0e, 0xe7, 0x22, 0xfd, 0x54,
-	0x8a, 0x4b, 0xb7, 0x4f, 0xf1, 0x05, 0xac, 0xb2, 0x89, 0xcf, 0xb1, 0x48, 0x39, 0xf5, 0xa3, 0x40,
-	0x04, 0xe6, 0xa6, 0xa9, 0xb0, 0x89, 0xab, 0xc0, 0xfd, 0x40, 0x04, 0x8d, 0x2e, 0xd4, 0xb2, 0x7c,
-	0x77, 0xcd, 0x15, 0x71, 0x15, 0xbb, 0xb5, 0x10, 0xfb, 0x73, 0xa8, 0x9a, 0xd8, 0xf5, 0x6c, 0x9a,
-	0x91, 0xa9, 0x68, 0xb0, 0xa7, 0xb0, 0xc6, 0xdf, 0x72, 0x50, 0xf3, 0x78, 0x40, 0x93, 0x20, 0x14,
-	0x84, 0xd1, 0xac, 0x86, 0x17, 0x98, 0x27, 0x84, 0x51, 0x55, 0xc3, 0xaa, 0x9b, 0x1d, 0xd1, 0x0b,
-	0x58, 0x26, 0xb2, 0xd5, 0x7a, 0xb0, 0xcb, 0xad, 0x4a, 0x73, 0x6e, 0x78, 0x5d, 0xc3, 0xa1, 0xaf,
-	0xa0, 0x3c, 0x20, 0xd4, 0x67, 0x2a, 0xca, 0xc4, 0xc9, 0x2b, 0x51, 0xbb, 0x79, 0x2d, 0x6e, 0x17,
-	0x06, 0x84, 0x6a, 0x24, 0x41, 0x2f, 0x61, 0x25, 0x13, 0x5f, 0x52, 0xe2, 0xd5, 0xe6, 0x7c, 0x5b,
-	0xdd, 0x8c, 0x95, 0x5d, 0x8c, 0x59, 0x78, 0xee, 0x0b, 0x32, 0xc6, 0x6a, 0x8c, 0xab, 0x6e, 0x51,
-	0x02, 0x1e, 0x19, 0x63, 0x39, 0xe4, 0x3a, 0x04, 0x3f, 0xa4, 0x42, 0x95, 0xaf, 0xea, 0x96, 0x34,
-	0xb2, 0x47, 0x85, 0xbc, 0xe8, 0x8d, 0x19, 0xc5, 0xaf, 0x28, 0x1e, 0x0c, 0x24, 0x05, 0x9e, 0x00,
-	0xe0, 0xa9, 0xe0, 0x81, 0x2e, 0x7f, 0x51, 0x2f, 0x89, 0x42, 0x64, 0xed, 0x65, 0x87, 0xae, 0x68,
-	0x3f, 0xc6, 0x54, 0xdf, 0x53, 0x6e, 0x65, 0x26, 0xf2, 0x0e, 0xd3, 0xc6, 0x9f, 0x2d, 0xb8, 0xe7,
-	0x4d, 0x5d, 0xb9, 0x31, 0x89, 0xd8, 0xc7, 0x22, 0x20, 0xb1, 0xbe, 0x62, 0x9f, 0x43, 0x95, 0x6b,
-	0xd4, 0x2c, 0xa9, 0x2e, 0x6e, 0xc5, 0x80, 0x7a, 0x4f, 0xd7, 0x61, 0x45, 0x4c, 0xb3, 0x0d, 0x97,
-	0xfe, 0x97, 0xc5, 0x54, 0xed, 0xf7, 0x4d, 0xe7, 0xf9, 0x9b, 0xce, 0xd1, 0x26, 0xac, 0xcd, 0x49,
-	0xb1, 0xb3, 0xb3, 0x04, 0x0b, 0x53, 0xa6, 0xda, 0x4c, 0xf0, 0x58, 0xc1, 0x8d, 0xdf, 0x5b, 0xb0,
-	0x3e, 0x0b, 0xb4, 0x8f, 0x39, 0x09, 0x62, 0xf2, 0x2d, 0x8e, 0x54, 0xac, 0x2f, 0xa1, 0x36, 0xbb,
-	0xb3, 0x16, 0xa2, 0x5d, 0x9d, 0xc1, 0x3a, 0xde, 0xc7, 0x50, 0x9a, 0x21, 0x26, 0xe2, 0x2b, 0x40,
-	0x8d, 0xe0, 0xcc, 0xb0, 0x2f, 0xa6, 0x2a, 0x66, 0x39, 0x82, 0x57, 0xde, 0xa6, 0x8d, 0x3f, 0x59,
-	0x50, 0xe9, 0x44, 0x98, 0x0a, 0x22, 0x2e, 0xb3, 0x8f, 0x00, 0xf5, 0x71, 0x60, 0x36, 0x58, 0x1f,
-	0x10, 0x82, 0x42, 0x9a, 0x60, 0x6e, 0xde, 0x38, 0xf5, 0x5b, 0x62, 0x23, 0x96, 0x08, 0x65, 0xb6,
-	0xe4, 0xaa, 0xdf, 0x12, 0x9b, 0x30, 0xae, 0xb3, 0x2e, 0xb9, 0xea, 0xb7, 0xc2, 0x02, 0xa1, 0xdf,
-	0x2c, 0x89, 0x05, 0x62, 0x84, 0xd6, 0x61, 0x49, 0x27, 0xb6, 0x9c, 0x3d, 0x88, 0xfa, 0xbc, 0xf9,
-	0x5d, 0x0e, 0xca, 0x07, 0x01, 0x89, 0x53, 0xae, 0xbf, 0x49, 0x9e, 0xc0, 0x43, 0x73, 0xf4, 0x4f,
-	0x28, 0x9e, 0x4e, 0x70, 0x28, 0x66, 0xaf, 0x97, 0x6d, 0xa1, 0xcf, 0xe0, 0x41, 0x46, 0xef, 0xa6,
-	0x42, 0x30, 0xda, 0x36, 0x22, 0x76, 0x0e, 0xdd, 0x87, 0xb5, 0x8c, 0x93, 0x85, 0x6f, 0x73, 0xce,
-	0xb8, 0x9d, 0x47, 0x8f, 0x60, 0x3d, 0x83, 0x77, 0xd4, 0xda, 0xed, 0x05, 0x34, 0xc4, 0x71, 0x8c,
-	0x23, 0xbb, 0x80, 0xd6, 0xe1, 0x6e, 0x46, 0xf6, 0xc8, 0x95, 0xb1, 0x25, 0xe4, 0xc0, 0xbd, 0x39,
-	0xe2, 0x4a, 0x65, 0x19, 0x3d, 0x00, 0x34, 0xc7, 0x74, 0xe8, 0x45, 0x10, 0x93, 0xc8, 0x5e, 0x41,
-	0x8f, 0xc1, 0xc9, 0x70, 0x03, 0xf6, 0xb3, 0xd6, 0xd8, 0xc5, 0x05, 0x7b, 0x9c, 0x85, 0x38, 0x49,
-	0x74, 0x7c, 0xa5, 0xf9, 0x94, 0xba, 0x4c, 0xb4, 0x29, 0x4b, 0x87, 0xa3, 0x83, 0x94, 0x46, 0x89,
-	0x0d, 0xd7, 0xb8, 0x0e, 0x25, 0xc2, 0x74, 0xd2, 0x2e, 0xa3, 0x87, 0x70, 0x3f, 0xe3, 0x0e, 0x08,
-	0x1f, 0x7f, 0x08, 0x38, 0xd6, 0x26, 0xc3, 0xcd, 0x3f, 0x5a, 0x60, 0x5f, 0xbf, 0x35, 0x91, 0x0d,
-	0x95, 0xde, 0xce, 0xaf, 0xbd, 0x63, 0xf3, 0x50, 0xd8, 0x77, 0xd0, 0x5d, 0xa8, 0x29, 0xa4, 0xbf,
-	0xe7, 0x76, 0x7a, 0xde, 0xe1, 0x4e, 0xff, 0xd0, 0xb6, 0xd0, 0x1a, 0x54, 0x15, 0x78, 0x74, 0xf2,
-	0xce, 0xeb, 0xf4, 0x3b, 0xdf, 0xd8, 0xb9, 0x19, 0x74, 0xdc, 0x73, 0xdb, 0xde, 0x89, 0xdb, 0xb5,
-	0xf3, 0x33, 0x63, 0xef, 0x3b, 0x5e, 0x57, 0x1a, 0x2b, 0xa0, 0x7b, 0x60, 0x2b, 0xa4, 0xd7, 0xea,
-	0x1f, 0x66, 0xe8, 0xd2, 0x66, 0x0c, 0xb5, 0x6b, 0xcf, 0x95, 0x54, 0x9d, 0x7f, 0xb0, 0xec, 0x3b,
-	0xd2, 0xbe, 0x42, 0x66, 0x2e, 0x2d, 0x54, 0x81, 0x62, 0xfb, 0xd4, 0x6b, 0xbb, 0xdd, 0x9d, 0x77,
-	0x76, 0x6e, 0xa6, 0x92, 0xd9, 0xcd, 0x4b, 0x6f, 0x0a, 0x99, 0xf7, 0x56, 0xd8, 0x3c, 0x81, 0xb2,
-	0xd9, 0x30, 0xe5, 0xa9, 0x0c, 0x2b, 0xde, 0x69, 0xa7, 0xdb, 0x3b, 0xf1, 0xec, 0x3b, 0xd2, 0xa2,
-	0x77, 0x7a, 0x7c, 0xe2, 0xc9, 0x93, 0x85, 0x00, 0x96, 0xbd, 0xd3, 0xa3, 0xb6, 0xb7, 0x63, 0xe7,
-	0xd0, 0x2a, 0x80, 0x77, 0x7a, 0xd0, 0xe9, 0x76, 0xfa, 0x87, 0xed, 0x7d, 0x3b, 0x8f, 0x6a, 0x50,
-	0xf6, 0x4e, 0xdb, 0xa7, 0x9e, 0xbb, 0xb3, 0xbf, 0xe3, 0xed, 0xd8, 0x85, 0xcd, 0xff, 0xe4, 0x60,
-	0x4d, 0x4f, 0xdb, 0xbc, 0xf5, 0x75, 0xb8, 0xbb, 0x00, 0xfa, 0xc7, 0x62, 0x84, 0xb9, 0x6d, 0xa1,
-	0x06, 0x7c, 0xbe, 0x48, 0x1c, 0x60, 0x7c, 0x7c, 0x81, 0xb9, 0x37, 0xe2, 0x38, 0x19, 0xb1, 0x58,
-	0xce, 0xea, 0x53, 0x78, 0xb4, 0x28, 0xb3, 0xc7, 0xe8, 0x19, 0xe1, 0x63, 0xdd, 0x35, 0x3b, 0x2f,
-	0xf7, 0x60, 0x51, 0xc0, 0xc5, 0x09, 0x16, 0xfb, 0xf8, 0x82, 0x84, 0xd8, 0x2e, 0xdc, 0xa4, 0x8d,
-	0xfe, 0x7b, 0xc6, 0xe5, 0xf4, 0x3e, 0x06, 0x67, 0x91, 0x7e, 0x4f, 0x26, 0xd8, 0x28, 0x2f, 0xdf,
-	0x54, 0xee, 0x71, 0x26, 0x70, 0x28, 0xf6, 0x82, 0x38, 0xb6, 0x57, 0xe4, 0xa8, 0x2e, 0xd2, 0x72,
-	0x8e, 0xbd, 0xa9, 0x5d, 0xbc, 0x19, 0x75, 0x36, 0x78, 0x7b, 0x23, 0x1c, 0x9e, 0xdb, 0x25, 0x39,
-	0x93, 0x8b, 0x02, 0x3b, 0xfa, 0xcd, 0xb7, 0x41, 0xae, 0xe1, 0x35, 0xa7, 0xd9, 0x37, 0xbd, 0x5d,
-	0xde, 0xfc, 0x1d, 0xdc, 0xeb, 0x11, 0x7a, 0x14, 0x08, 0x4e, 0xa6, 0xf3, 0x35, 0xae, 0xc3, 0xe3,
-	0x8f, 0xe1, 0xfe, 0x5e, 0xca, 0x39, 0xa6, 0xc2, 0xb6, 0xd0, 0x33, 0x78, 0xf2, 0x51, 0x89, 0x2e,
-	0xfe, 0x70, 0x40, 0x78, 0x22, 0xec, 0x9c, 0xec, 0xc7, 0xa7, 0x44, 0xfa, 0x38, 0x64, 0x34, 0xb2,
-	0xf3, 0x9b, 0xbf, 0x01, 0xe4, 0xe2, 0x90, 0x5d, 0x60, 0x7e, 0xa9, 0xcb, 0xa4, 0xdc, 0xff, 0x00,
-	0x9e, 0xdd, 0x44, 0xfd, 0x7e, 0xc8, 0x83, 0xf1, 0x20, 0xc6, 0x91, 0x2c, 0x76, 0x62, 0xdf, 0x91,
-	0xf5, 0xfc, 0x88, 0x98, 0x76, 0x68, 0x5b, 0x9b, 0x67, 0x50, 0x93, 0x92, 0xf3, 0x79, 0x3d, 0x84,
-	0xfb, 0xd7, 0x20, 0xbf, 0x17, 0x07, 0x84, 0xda, 0x77, 0x64, 0x9d, 0xae, 0x53, 0xda, 0xd2, 0x1b,
-	0xdb, 0xfa, 0x34, 0xb9, 0x65, 0xe7, 0xb6, 0x7f, 0x06, 0x2b, 0x1f, 0x88, 0x7a, 0x41, 0xd0, 0xb3,
-	0xa6, 0xfe, 0x2f, 0xd8, 0xcc, 0xfe, 0x0b, 0x36, 0xdb, 0x34, 0x1d, 0xff, 0x2a, 0x88, 0x53, 0x7c,
-	0x3c, 0x91, 0x77, 0x60, 0xe2, 0x7c, 0xf7, 0x87, 0xbc, 0xfe, 0x52, 0x97, 0x3a, 0x1d, 0xba, 0xfd,
-	0x73, 0x28, 0x2a, 0x6d, 0x96, 0x8a, 0xdb, 0xa8, 0xff, 0xdd, 0xa8, 0x2b, 0x97, 0xc7, 0xa9, 0xd8,
-	0xfe, 0x06, 0xaa, 0x4a, 0x3f, 0xc2, 0x83, 0x74, 0x78, 0xcb, 0x18, 0xfe, 0x61, 0x8c, 0x94, 0xa5,
-	0xe6, 0xbe, 0x54, 0xec, 0xd0, 0xed, 0x0e, 0xac, 0xce, 0x19, 0xba, 0x65, 0x38, 0xff, 0x34, 0x96,
-	0x2a, 0x33, 0x4b, 0x32, 0xa6, 0x5f, 0x42, 0x49, 0x99, 0x12, 0x84, 0x5e, 0xde, 0xc6, 0xca, 0xbf,
-	0x8c, 0x15, 0x55, 0x09, 0x8f, 0xd0, 0xcb, 0xed, 0x77, 0x50, 0x53, 0x16, 0x06, 0x8c, 0x89, 0x98,
-	0xa9, 0x3f, 0x4f, 0xb7, 0xb0, 0xf3, 0x6f, 0x63, 0x47, 0x25, 0xb2, 0x3b, 0x53, 0xdd, 0xfd, 0x0a,
-	0x9e, 0x87, 0x6c, 0xdc, 0x4c, 0x02, 0xc1, 0x92, 0x11, 0x89, 0x83, 0x41, 0xd2, 0x14, 0x1c, 0x7f,
-	0xcb, 0x78, 0x33, 0x26, 0x83, 0x99, 0xbd, 0x5d, 0xf0, 0x14, 0x28, 0xdb, 0xfb, 0xff, 0x00, 0x00,
-	0x00, 0xff, 0xff, 0x70, 0x88, 0xcd, 0x71, 0xe2, 0x0f, 0x00, 0x00,
-}

+ 0 - 278
accounts/usbwallet/trezor/types.proto

@@ -1,278 +0,0 @@
-// This file originates from the SatoshiLabs Trezor `common` repository at:
-//   https://github.com/trezor/trezor-common/blob/master/protob/types.proto
-// dated 28.07.2017, commit dd8ec3231fb5f7992360aff9bdfe30bb58130f4b.
-
-syntax = "proto2";
-
-/**
- * Types for TREZOR communication
- *
- * @author	Marek Palatinus <slush@satoshilabs.com>
- * @version	1.2
- */
-
-// Sugar for easier handling in Java
-option java_package = "com.satoshilabs.trezor.lib.protobuf";
-option java_outer_classname = "TrezorType";
-
-import "google/protobuf/descriptor.proto";
-
-/**
- * Options for specifying message direction and type of wire (normal/debug)
- */
-extend google.protobuf.EnumValueOptions {
-	optional bool wire_in = 50002;		// message can be transmitted via wire from PC to TREZOR
-	optional bool wire_out = 50003;		// message can be transmitted via wire from TREZOR to PC
-	optional bool wire_debug_in = 50004;	// message can be transmitted via debug wire from PC to TREZOR
-	optional bool wire_debug_out = 50005;	// message can be transmitted via debug wire from TREZOR to PC
-	optional bool wire_tiny = 50006;	// message is handled by TREZOR when the USB stack is in tiny mode
-	optional bool wire_bootloader = 50007;  // message is only handled by TREZOR Bootloader
-}
-
-/**
- * Type of failures returned by Failure message
- * @used_in Failure
- */
-enum FailureType {
-	Failure_UnexpectedMessage = 1;
-	Failure_ButtonExpected = 2;
-	Failure_DataError = 3;
-	Failure_ActionCancelled = 4;
-	Failure_PinExpected = 5;
-	Failure_PinCancelled = 6;
-	Failure_PinInvalid = 7;
-	Failure_InvalidSignature = 8;
-	Failure_ProcessError = 9;
-	Failure_NotEnoughFunds = 10;
-	Failure_NotInitialized = 11;
-	Failure_FirmwareError = 99;
-}
-
-/**
- * Type of script which will be used for transaction output
- * @used_in TxOutputType
- */
-enum OutputScriptType {
-	PAYTOADDRESS = 0;	// used for all addresses (bitcoin, p2sh, witness)
-	PAYTOSCRIPTHASH = 1;	// p2sh address (deprecated; use PAYTOADDRESS)
-	PAYTOMULTISIG = 2;	// only for change output
-	PAYTOOPRETURN = 3;	// op_return
-	PAYTOWITNESS = 4;	// only for change output
-	PAYTOP2SHWITNESS = 5;	// only for change output
-}
-
-/**
- * Type of script which will be used for transaction output
- * @used_in TxInputType
- */
-enum InputScriptType {
-	SPENDADDRESS = 0;		// standard p2pkh address
-	SPENDMULTISIG = 1;		// p2sh multisig address
-	EXTERNAL = 2;			// reserved for external inputs (coinjoin)
-	SPENDWITNESS = 3;		// native segwit
-	SPENDP2SHWITNESS = 4;		// segwit over p2sh (backward compatible)
-}
-
-/**
- * Type of information required by transaction signing process
- * @used_in TxRequest
- */
-enum RequestType {
-	TXINPUT = 0;
-	TXOUTPUT = 1;
-	TXMETA = 2;
-	TXFINISHED = 3;
-	TXEXTRADATA = 4;
-}
-
-/**
- * Type of button request
- * @used_in ButtonRequest
- */
-enum ButtonRequestType {
-	ButtonRequest_Other = 1;
-	ButtonRequest_FeeOverThreshold = 2;
-	ButtonRequest_ConfirmOutput = 3;
-	ButtonRequest_ResetDevice = 4;
-	ButtonRequest_ConfirmWord = 5;
-	ButtonRequest_WipeDevice = 6;
-	ButtonRequest_ProtectCall = 7;
-	ButtonRequest_SignTx = 8;
-	ButtonRequest_FirmwareCheck = 9;
-	ButtonRequest_Address = 10;
-	ButtonRequest_PublicKey = 11;
-}
-
-/**
- * Type of PIN request
- * @used_in PinMatrixRequest
- */
-enum PinMatrixRequestType {
-	PinMatrixRequestType_Current = 1;
-	PinMatrixRequestType_NewFirst = 2;
-	PinMatrixRequestType_NewSecond = 3;
-}
-
-/**
- * Type of recovery procedure. These should be used as bitmask, e.g.,
- * `RecoveryDeviceType_ScrambledWords | RecoveryDeviceType_Matrix`
- * listing every method supported by the host computer.
- *
- * Note that ScrambledWords must be supported by every implementation
- * for backward compatibility; there is no way to not support it.
- *
- * @used_in RecoveryDevice
- */
-enum RecoveryDeviceType {
-	// use powers of two when extending this field
-	RecoveryDeviceType_ScrambledWords = 0;		// words in scrambled order
-	RecoveryDeviceType_Matrix = 1;				// matrix recovery type
-}
-
-/**
- * Type of Recovery Word request
- * @used_in WordRequest
- */
-enum WordRequestType {
-	WordRequestType_Plain = 0;
-	WordRequestType_Matrix9 = 1;
-	WordRequestType_Matrix6 = 2;
-}
-
-/**
- * Structure representing BIP32 (hierarchical deterministic) node
- * Used for imports of private key into the device and exporting public key out of device
- * @used_in PublicKey
- * @used_in LoadDevice
- * @used_in DebugLinkState
- * @used_in Storage
- */
-message HDNodeType {
-	required uint32 depth = 1;
-	required uint32 fingerprint = 2;
-	required uint32 child_num = 3;
-	required bytes chain_code = 4;
-	optional bytes private_key = 5;
-	optional bytes public_key = 6;
-}
-
-message HDNodePathType {
-	required HDNodeType node = 1;						// BIP-32 node in deserialized form
-	repeated uint32 address_n = 2;						// BIP-32 path to derive the key from node
-}
-
-/**
- * Structure representing Coin
- * @used_in Features
- */
-message CoinType {
-	optional string coin_name = 1;
-	optional string coin_shortcut = 2;
-	optional uint32 address_type = 3 [default=0];
-	optional uint64 maxfee_kb = 4;
-	optional uint32 address_type_p2sh = 5 [default=5];
-	optional string signed_message_header = 8;
-	optional uint32 xpub_magic = 9 [default=76067358];	// default=0x0488b21e
-	optional uint32 xprv_magic = 10 [default=76066276];	// default=0x0488ade4
-	optional bool segwit = 11;
-	optional uint32 forkid = 12;
-}
-
-/**
- * Type of redeem script used in input
- * @used_in TxInputType
- */
-message MultisigRedeemScriptType {
-	repeated HDNodePathType pubkeys = 1;					// pubkeys from multisig address (sorted lexicographically)
-	repeated bytes signatures = 2;						// existing signatures for partially signed input
-	optional uint32 m = 3;							// "m" from n, how many valid signatures is necessary for spending
-}
-
-/**
- * Structure representing transaction input
- * @used_in SimpleSignTx
- * @used_in TransactionType
- */
-message TxInputType {
-	repeated uint32 address_n = 1;						// BIP-32 path to derive the key from master node
-	required bytes prev_hash = 2;						// hash of previous transaction output to spend by this input
-	required uint32 prev_index = 3;						// index of previous output to spend
-	optional bytes script_sig = 4;						// script signature, unset for tx to sign
-	optional uint32 sequence = 5 [default=4294967295];			// sequence (default=0xffffffff)
-	optional InputScriptType script_type = 6 [default=SPENDADDRESS];	// defines template of input script
-	optional MultisigRedeemScriptType multisig = 7;				// Filled if input is going to spend multisig tx
-	optional uint64 amount = 8;						// amount of previous transaction output (for segwit only)
-}
-
-/**
- * Structure representing transaction output
- * @used_in SimpleSignTx
- * @used_in TransactionType
- */
-message TxOutputType {
-	optional string address = 1;			// target coin address in Base58 encoding
-	repeated uint32 address_n = 2;			// BIP-32 path to derive the key from master node; has higher priority than "address"
-	required uint64 amount = 3;			// amount to spend in satoshis
-	required OutputScriptType script_type = 4;	// output script type
-	optional MultisigRedeemScriptType multisig = 5; // defines multisig address; script_type must be PAYTOMULTISIG
-	optional bytes op_return_data = 6;		// defines op_return data; script_type must be PAYTOOPRETURN, amount must be 0
-}
-
-/**
- * Structure representing compiled transaction output
- * @used_in TransactionType
- */
-message TxOutputBinType {
-	required uint64 amount = 1;
-	required bytes script_pubkey = 2;
-}
-
-/**
- * Structure representing transaction
- * @used_in SimpleSignTx
- */
-message TransactionType {
-	optional uint32 version = 1;
-	repeated TxInputType inputs = 2;
-	repeated TxOutputBinType bin_outputs = 3;
-	repeated TxOutputType outputs = 5;
-	optional uint32 lock_time = 4;
-	optional uint32 inputs_cnt = 6;
-	optional uint32 outputs_cnt = 7;
-	optional bytes extra_data = 8;
-	optional uint32 extra_data_len = 9;
-}
-
-/**
- * Structure representing request details
- * @used_in TxRequest
- */
-message TxRequestDetailsType {
-	optional uint32 request_index = 1;	// device expects TxAck message from the computer
-	optional bytes tx_hash = 2;		// tx_hash of requested transaction
-	optional uint32 extra_data_len = 3;	// length of requested extra data
-	optional uint32 extra_data_offset = 4;	// offset of requested extra data
-}
-
-/**
- * Structure representing serialized data
- * @used_in TxRequest
- */
-message TxRequestSerializedType {
-	optional uint32 signature_index = 1;	// 'signature' field contains signed input of this index
-	optional bytes signature = 2;		// signature of the signature_index input
-	optional bytes serialized_tx = 3;	// part of serialized and signed transaction
-}
-
-/**
- * Structure representing identity data
- * @used_in IdentityType
- */
-message IdentityType {
-	optional string proto = 1;			// proto part of URI
-	optional string user = 2;			// user part of URI
-	optional string host = 3;			// host part of URI
-	optional string port = 4;			// port part of URI
-	optional string path = 5;			// path part of URI
-	optional uint32 index = 6 [default=0];		// identity index
-}

+ 3 - 3
accounts/usbwallet/wallet.go

@@ -31,7 +31,7 @@ import (
 	"github.com/ethereum/go-ethereum/core/types"
 	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/log"
-	"github.com/karalabe/hid"
+	"github.com/karalabe/usb"
 )
 
 // Maximum time between wallet health checks to detect USB unplugs.
@@ -77,8 +77,8 @@ type wallet struct {
 	driver driver        // Hardware implementation of the low level device operations
 	url    *accounts.URL // Textual URL uniquely identifying this wallet
 
-	info   hid.DeviceInfo // Known USB device infos about the wallet
-	device *hid.Device    // USB device advertising itself as a hardware wallet
+	info   usb.DeviceInfo // Known USB device infos about the wallet
+	device usb.Device     // USB device advertising itself as a hardware wallet
 
 	accounts []accounts.Account                         // List of derive accounts pinned on the hardware wallet
 	paths    map[common.Address]accounts.DerivationPath // Known derivation paths for signing operations

+ 9 - 3
node/config.go

@@ -501,9 +501,15 @@ func makeAccountManager(conf *Config) (*accounts.Manager, string, error) {
 			} else {
 				backends = append(backends, ledgerhub)
 			}
-			// Start a USB hub for Trezor hardware wallets
-			if trezorhub, err := usbwallet.NewTrezorHub(); err != nil {
-				log.Warn(fmt.Sprintf("Failed to start Trezor hub, disabling: %v", err))
+			// Start a USB hub for Trezor hardware wallets (HID version)
+			if trezorhub, err := usbwallet.NewTrezorHubWithHID(); err != nil {
+				log.Warn(fmt.Sprintf("Failed to start HID Trezor hub, disabling: %v", err))
+			} else {
+				backends = append(backends, trezorhub)
+			}
+			// Start a USB hub for Trezor hardware wallets (WebUSB version)
+			if trezorhub, err := usbwallet.NewTrezorHubWithWebUSB(); err != nil {
+				log.Warn(fmt.Sprintf("Failed to start WebUSB Trezor hub, disabling: %v", err))
 			} else {
 				backends = append(backends, trezorhub)
 			}

+ 11 - 4
signer/core/api.go

@@ -144,12 +144,19 @@ func StartClefAccountManager(ksLocation string, nousb, lightKDF bool) *accounts.
 			backends = append(backends, ledgerhub)
 			log.Debug("Ledger support enabled")
 		}
-		// Start a USB hub for Trezor hardware wallets
-		if trezorhub, err := usbwallet.NewTrezorHub(); err != nil {
-			log.Warn(fmt.Sprintf("Failed to start Trezor hub, disabling: %v", err))
+		// Start a USB hub for Trezor hardware wallets (HID version)
+		if trezorhub, err := usbwallet.NewTrezorHubWithHID(); err != nil {
+			log.Warn(fmt.Sprintf("Failed to start HID Trezor hub, disabling: %v", err))
 		} else {
 			backends = append(backends, trezorhub)
-			log.Debug("Trezor support enabled")
+			log.Debug("Trezor support enabled via HID")
+		}
+		// Start a USB hub for Trezor hardware wallets (WebUSB version)
+		if trezorhub, err := usbwallet.NewTrezorHubWithWebUSB(); err != nil {
+			log.Warn(fmt.Sprintf("Failed to start WebUSB Trezor hub, disabling: %v", err))
+		} else {
+			backends = append(backends, trezorhub)
+			log.Debug("Trezor support enabled via WebUSB")
 		}
 	}
 	// Clef doesn't allow insecure http account unlock.

+ 0 - 3
vendor/github.com/golang/protobuf/LICENSE

@@ -1,7 +1,4 @@
-Go support for Protocol Buffers - Google's data interchange format
-
 Copyright 2010 The Go Authors.  All rights reserved.
-https://github.com/golang/protobuf
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are

+ 0 - 43
vendor/github.com/golang/protobuf/proto/Makefile

@@ -1,43 +0,0 @@
-# Go support for Protocol Buffers - Google's data interchange format
-#
-# Copyright 2010 The Go Authors.  All rights reserved.
-# https://github.com/golang/protobuf
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-install:
-	go install
-
-test: install generate-test-pbs
-	go test
-
-
-generate-test-pbs:
-	make install
-	make -C testdata
-	protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata,Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any:. proto3_proto/proto3.proto
-	make

+ 35 - 11
vendor/github.com/golang/protobuf/proto/clone.go

@@ -35,22 +35,39 @@
 package proto
 
 import (
+	"fmt"
 	"log"
 	"reflect"
 	"strings"
 )
 
 // Clone returns a deep copy of a protocol buffer.
-func Clone(pb Message) Message {
-	in := reflect.ValueOf(pb)
+func Clone(src Message) Message {
+	in := reflect.ValueOf(src)
 	if in.IsNil() {
-		return pb
+		return src
 	}
-
 	out := reflect.New(in.Type().Elem())
-	// out is empty so a merge is a deep copy.
-	mergeStruct(out.Elem(), in.Elem())
-	return out.Interface().(Message)
+	dst := out.Interface().(Message)
+	Merge(dst, src)
+	return dst
+}
+
+// Merger is the interface representing objects that can merge messages of the same type.
+type Merger interface {
+	// Merge merges src into this message.
+	// Required and optional fields that are set in src will be set to that value in dst.
+	// Elements of repeated fields will be appended.
+	//
+	// Merge may panic if called with a different argument type than the receiver.
+	Merge(src Message)
+}
+
+// generatedMerger is the custom merge method that generated protos will have.
+// We must add this method since a generate Merge method will conflict with
+// many existing protos that have a Merge data field already defined.
+type generatedMerger interface {
+	XXX_Merge(src Message)
 }
 
 // Merge merges src into dst.
@@ -58,17 +75,24 @@ func Clone(pb Message) Message {
 // Elements of repeated fields will be appended.
 // Merge panics if src and dst are not the same type, or if dst is nil.
 func Merge(dst, src Message) {
+	if m, ok := dst.(Merger); ok {
+		m.Merge(src)
+		return
+	}
+
 	in := reflect.ValueOf(src)
 	out := reflect.ValueOf(dst)
 	if out.IsNil() {
 		panic("proto: nil destination")
 	}
 	if in.Type() != out.Type() {
-		// Explicit test prior to mergeStruct so that mistyped nils will fail
-		panic("proto: type mismatch")
+		panic(fmt.Sprintf("proto.Merge(%T, %T) type mismatch", dst, src))
 	}
 	if in.IsNil() {
-		// Merging nil into non-nil is a quiet no-op
+		return // Merge from nil src is a noop
+	}
+	if m, ok := dst.(generatedMerger); ok {
+		m.XXX_Merge(src)
 		return
 	}
 	mergeStruct(out.Elem(), in.Elem())
@@ -84,7 +108,7 @@ func mergeStruct(out, in reflect.Value) {
 		mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i])
 	}
 
-	if emIn, ok := extendable(in.Addr().Interface()); ok {
+	if emIn, err := extendable(in.Addr().Interface()); err == nil {
 		emOut, _ := extendable(out.Addr().Interface())
 		mIn, muIn := emIn.extensionsRead()
 		if mIn != nil {

+ 63 - 606
vendor/github.com/golang/protobuf/proto/decode.go

@@ -39,8 +39,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"os"
-	"reflect"
 )
 
 // errOverflow is returned when an integer is too large to be represented.
@@ -50,10 +48,6 @@ var errOverflow = errors.New("proto: integer overflow")
 // wire type is encountered. It does not get returned to user code.
 var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
 
-// The fundamental decoders that interpret bytes on the wire.
-// Those that take integer types all return uint64 and are
-// therefore of type valueDecoder.
-
 // DecodeVarint reads a varint-encoded integer from the slice.
 // It returns the integer and the number of bytes consumed, or
 // zero if there is not enough.
@@ -192,7 +186,6 @@ func (p *Buffer) DecodeVarint() (x uint64, err error) {
 	if b&0x80 == 0 {
 		goto done
 	}
-	// x -= 0x80 << 63 // Always zero.
 
 	return 0, errOverflow
 
@@ -267,9 +260,6 @@ func (p *Buffer) DecodeZigzag32() (x uint64, err error) {
 	return
 }
 
-// These are not ValueDecoders: they produce an array of bytes or a string.
-// bytes, embedded messages
-
 // DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
 // This is the format used for the bytes protocol buffer
 // type and for embedded messages.
@@ -311,81 +301,29 @@ func (p *Buffer) DecodeStringBytes() (s string, err error) {
 	return string(buf), nil
 }
 
-// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
-// If the protocol buffer has extensions, and the field matches, add it as an extension.
-// Otherwise, if the XXX_unrecognized field exists, append the skipped data there.
-func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base structPointer, unrecField field) error {
-	oi := o.index
-
-	err := o.skip(t, tag, wire)
-	if err != nil {
-		return err
-	}
-
-	if !unrecField.IsValid() {
-		return nil
-	}
-
-	ptr := structPointer_Bytes(base, unrecField)
-
-	// Add the skipped field to struct field
-	obuf := o.buf
-
-	o.buf = *ptr
-	o.EncodeVarint(uint64(tag<<3 | wire))
-	*ptr = append(o.buf, obuf[oi:o.index]...)
-
-	o.buf = obuf
-
-	return nil
-}
-
-// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
-func (o *Buffer) skip(t reflect.Type, tag, wire int) error {
-
-	var u uint64
-	var err error
-
-	switch wire {
-	case WireVarint:
-		_, err = o.DecodeVarint()
-	case WireFixed64:
-		_, err = o.DecodeFixed64()
-	case WireBytes:
-		_, err = o.DecodeRawBytes(false)
-	case WireFixed32:
-		_, err = o.DecodeFixed32()
-	case WireStartGroup:
-		for {
-			u, err = o.DecodeVarint()
-			if err != nil {
-				break
-			}
-			fwire := int(u & 0x7)
-			if fwire == WireEndGroup {
-				break
-			}
-			ftag := int(u >> 3)
-			err = o.skip(t, ftag, fwire)
-			if err != nil {
-				break
-			}
-		}
-	default:
-		err = fmt.Errorf("proto: can't skip unknown wire type %d for %s", wire, t)
-	}
-	return err
-}
-
 // Unmarshaler is the interface representing objects that can
-// unmarshal themselves.  The method should reset the receiver before
-// decoding starts.  The argument points to data that may be
+// unmarshal themselves.  The argument points to data that may be
 // overwritten, so implementations should not keep references to the
 // buffer.
+// Unmarshal implementations should not clear the receiver.
+// Any unmarshaled data should be merged into the receiver.
+// Callers of Unmarshal that do not want to retain existing data
+// should Reset the receiver before calling Unmarshal.
 type Unmarshaler interface {
 	Unmarshal([]byte) error
 }
 
+// newUnmarshaler is the interface representing objects that can
+// unmarshal themselves. The semantics are identical to Unmarshaler.
+//
+// This exists to support protoc-gen-go generated messages.
+// The proto package will stop type-asserting to this interface in the future.
+//
+// DO NOT DEPEND ON THIS.
+type newUnmarshaler interface {
+	XXX_Unmarshal([]byte) error
+}
+
 // Unmarshal parses the protocol buffer representation in buf and places the
 // decoded result in pb.  If the struct underlying pb does not match
 // the data in buf, the results can be unpredictable.
@@ -395,7 +333,13 @@ type Unmarshaler interface {
 // to preserve and append to existing data.
 func Unmarshal(buf []byte, pb Message) error {
 	pb.Reset()
-	return UnmarshalMerge(buf, pb)
+	if u, ok := pb.(newUnmarshaler); ok {
+		return u.XXX_Unmarshal(buf)
+	}
+	if u, ok := pb.(Unmarshaler); ok {
+		return u.Unmarshal(buf)
+	}
+	return NewBuffer(buf).Unmarshal(pb)
 }
 
 // UnmarshalMerge parses the protocol buffer representation in buf and
@@ -405,8 +349,16 @@ func Unmarshal(buf []byte, pb Message) error {
 // UnmarshalMerge merges into existing data in pb.
 // Most code should use Unmarshal instead.
 func UnmarshalMerge(buf []byte, pb Message) error {
-	// If the object can unmarshal itself, let it.
+	if u, ok := pb.(newUnmarshaler); ok {
+		return u.XXX_Unmarshal(buf)
+	}
 	if u, ok := pb.(Unmarshaler); ok {
+		// NOTE: The history of proto have unfortunately been inconsistent
+		// whether Unmarshaler should or should not implicitly clear itself.
+		// Some implementations do, most do not.
+		// Thus, calling this here may or may not do what people want.
+		//
+		// See https://github.com/golang/protobuf/issues/424
 		return u.Unmarshal(buf)
 	}
 	return NewBuffer(buf).Unmarshal(pb)
@@ -422,12 +374,17 @@ func (p *Buffer) DecodeMessage(pb Message) error {
 }
 
 // DecodeGroup reads a tag-delimited group from the Buffer.
+// StartGroup tag is already consumed. This function consumes
+// EndGroup tag.
 func (p *Buffer) DecodeGroup(pb Message) error {
-	typ, base, err := getbase(pb)
-	if err != nil {
-		return err
+	b := p.buf[p.index:]
+	x, y := findEndGroup(b)
+	if x < 0 {
+		return io.ErrUnexpectedEOF
 	}
-	return p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), true, base)
+	err := Unmarshal(b[:x], pb)
+	p.index += y
+	return err
 }
 
 // Unmarshal parses the protocol buffer representation in the
@@ -438,533 +395,33 @@ func (p *Buffer) DecodeGroup(pb Message) error {
 // Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal.
 func (p *Buffer) Unmarshal(pb Message) error {
 	// If the object can unmarshal itself, let it.
-	if u, ok := pb.(Unmarshaler); ok {
-		err := u.Unmarshal(p.buf[p.index:])
+	if u, ok := pb.(newUnmarshaler); ok {
+		err := u.XXX_Unmarshal(p.buf[p.index:])
 		p.index = len(p.buf)
 		return err
 	}
-
-	typ, base, err := getbase(pb)
-	if err != nil {
-		return err
-	}
-
-	err = p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), false, base)
-
-	if collectStats {
-		stats.Decode++
-	}
-
-	return err
-}
-
-// unmarshalType does the work of unmarshaling a structure.
-func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group bool, base structPointer) error {
-	var state errorState
-	required, reqFields := prop.reqCount, uint64(0)
-
-	var err error
-	for err == nil && o.index < len(o.buf) {
-		oi := o.index
-		var u uint64
-		u, err = o.DecodeVarint()
-		if err != nil {
-			break
-		}
-		wire := int(u & 0x7)
-		if wire == WireEndGroup {
-			if is_group {
-				if required > 0 {
-					// Not enough information to determine the exact field.
-					// (See below.)
-					return &RequiredNotSetError{"{Unknown}"}
-				}
-				return nil // input is satisfied
-			}
-			return fmt.Errorf("proto: %s: wiretype end group for non-group", st)
-		}
-		tag := int(u >> 3)
-		if tag <= 0 {
-			return fmt.Errorf("proto: %s: illegal tag %d (wire type %d)", st, tag, wire)
-		}
-		fieldnum, ok := prop.decoderTags.get(tag)
-		if !ok {
-			// Maybe it's an extension?
-			if prop.extendable {
-				if e, _ := extendable(structPointer_Interface(base, st)); isExtensionField(e, int32(tag)) {
-					if err = o.skip(st, tag, wire); err == nil {
-						extmap := e.extensionsWrite()
-						ext := extmap[int32(tag)] // may be missing
-						ext.enc = append(ext.enc, o.buf[oi:o.index]...)
-						extmap[int32(tag)] = ext
-					}
-					continue
-				}
-			}
-			// Maybe it's a oneof?
-			if prop.oneofUnmarshaler != nil {
-				m := structPointer_Interface(base, st).(Message)
-				// First return value indicates whether tag is a oneof field.
-				ok, err = prop.oneofUnmarshaler(m, tag, wire, o)
-				if err == ErrInternalBadWireType {
-					// Map the error to something more descriptive.
-					// Do the formatting here to save generated code space.
-					err = fmt.Errorf("bad wiretype for oneof field in %T", m)
-				}
-				if ok {
-					continue
-				}
-			}
-			err = o.skipAndSave(st, tag, wire, base, prop.unrecField)
-			continue
-		}
-		p := prop.Prop[fieldnum]
-
-		if p.dec == nil {
-			fmt.Fprintf(os.Stderr, "proto: no protobuf decoder for %s.%s\n", st, st.Field(fieldnum).Name)
-			continue
-		}
-		dec := p.dec
-		if wire != WireStartGroup && wire != p.WireType {
-			if wire == WireBytes && p.packedDec != nil {
-				// a packable field
-				dec = p.packedDec
-			} else {
-				err = fmt.Errorf("proto: bad wiretype for field %s.%s: got wiretype %d, want %d", st, st.Field(fieldnum).Name, wire, p.WireType)
-				continue
-			}
-		}
-		decErr := dec(o, p, base)
-		if decErr != nil && !state.shouldContinue(decErr, p) {
-			err = decErr
-		}
-		if err == nil && p.Required {
-			// Successfully decoded a required field.
-			if tag <= 64 {
-				// use bitmap for fields 1-64 to catch field reuse.
-				var mask uint64 = 1 << uint64(tag-1)
-				if reqFields&mask == 0 {
-					// new required field
-					reqFields |= mask
-					required--
-				}
-			} else {
-				// This is imprecise. It can be fooled by a required field
-				// with a tag > 64 that is encoded twice; that's very rare.
-				// A fully correct implementation would require allocating
-				// a data structure, which we would like to avoid.
-				required--
-			}
-		}
-	}
-	if err == nil {
-		if is_group {
-			return io.ErrUnexpectedEOF
-		}
-		if state.err != nil {
-			return state.err
-		}
-		if required > 0 {
-			// Not enough information to determine the exact field. If we use extra
-			// CPU, we could determine the field only if the missing required field
-			// has a tag <= 64 and we check reqFields.
-			return &RequiredNotSetError{"{Unknown}"}
-		}
-	}
-	return err
-}
-
-// Individual type decoders
-// For each,
-//	u is the decoded value,
-//	v is a pointer to the field (pointer) in the struct
-
-// Sizes of the pools to allocate inside the Buffer.
-// The goal is modest amortization and allocation
-// on at least 16-byte boundaries.
-const (
-	boolPoolSize   = 16
-	uint32PoolSize = 8
-	uint64PoolSize = 4
-)
-
-// Decode a bool.
-func (o *Buffer) dec_bool(p *Properties, base structPointer) error {
-	u, err := p.valDec(o)
-	if err != nil {
-		return err
-	}
-	if len(o.bools) == 0 {
-		o.bools = make([]bool, boolPoolSize)
-	}
-	o.bools[0] = u != 0
-	*structPointer_Bool(base, p.field) = &o.bools[0]
-	o.bools = o.bools[1:]
-	return nil
-}
-
-func (o *Buffer) dec_proto3_bool(p *Properties, base structPointer) error {
-	u, err := p.valDec(o)
-	if err != nil {
-		return err
-	}
-	*structPointer_BoolVal(base, p.field) = u != 0
-	return nil
-}
-
-// Decode an int32.
-func (o *Buffer) dec_int32(p *Properties, base structPointer) error {
-	u, err := p.valDec(o)
-	if err != nil {
-		return err
-	}
-	word32_Set(structPointer_Word32(base, p.field), o, uint32(u))
-	return nil
-}
-
-func (o *Buffer) dec_proto3_int32(p *Properties, base structPointer) error {
-	u, err := p.valDec(o)
-	if err != nil {
-		return err
-	}
-	word32Val_Set(structPointer_Word32Val(base, p.field), uint32(u))
-	return nil
-}
-
-// Decode an int64.
-func (o *Buffer) dec_int64(p *Properties, base structPointer) error {
-	u, err := p.valDec(o)
-	if err != nil {
-		return err
-	}
-	word64_Set(structPointer_Word64(base, p.field), o, u)
-	return nil
-}
-
-func (o *Buffer) dec_proto3_int64(p *Properties, base structPointer) error {
-	u, err := p.valDec(o)
-	if err != nil {
-		return err
-	}
-	word64Val_Set(structPointer_Word64Val(base, p.field), o, u)
-	return nil
-}
-
-// Decode a string.
-func (o *Buffer) dec_string(p *Properties, base structPointer) error {
-	s, err := o.DecodeStringBytes()
-	if err != nil {
-		return err
-	}
-	*structPointer_String(base, p.field) = &s
-	return nil
-}
-
-func (o *Buffer) dec_proto3_string(p *Properties, base structPointer) error {
-	s, err := o.DecodeStringBytes()
-	if err != nil {
-		return err
-	}
-	*structPointer_StringVal(base, p.field) = s
-	return nil
-}
-
-// Decode a slice of bytes ([]byte).
-func (o *Buffer) dec_slice_byte(p *Properties, base structPointer) error {
-	b, err := o.DecodeRawBytes(true)
-	if err != nil {
-		return err
-	}
-	*structPointer_Bytes(base, p.field) = b
-	return nil
-}
-
-// Decode a slice of bools ([]bool).
-func (o *Buffer) dec_slice_bool(p *Properties, base structPointer) error {
-	u, err := p.valDec(o)
-	if err != nil {
-		return err
-	}
-	v := structPointer_BoolSlice(base, p.field)
-	*v = append(*v, u != 0)
-	return nil
-}
-
-// Decode a slice of bools ([]bool) in packed format.
-func (o *Buffer) dec_slice_packed_bool(p *Properties, base structPointer) error {
-	v := structPointer_BoolSlice(base, p.field)
-
-	nn, err := o.DecodeVarint()
-	if err != nil {
-		return err
-	}
-	nb := int(nn) // number of bytes of encoded bools
-	fin := o.index + nb
-	if fin < o.index {
-		return errOverflow
-	}
-
-	y := *v
-	for o.index < fin {
-		u, err := p.valDec(o)
-		if err != nil {
-			return err
-		}
-		y = append(y, u != 0)
-	}
-
-	*v = y
-	return nil
-}
-
-// Decode a slice of int32s ([]int32).
-func (o *Buffer) dec_slice_int32(p *Properties, base structPointer) error {
-	u, err := p.valDec(o)
-	if err != nil {
-		return err
-	}
-	structPointer_Word32Slice(base, p.field).Append(uint32(u))
-	return nil
-}
-
-// Decode a slice of int32s ([]int32) in packed format.
-func (o *Buffer) dec_slice_packed_int32(p *Properties, base structPointer) error {
-	v := structPointer_Word32Slice(base, p.field)
-
-	nn, err := o.DecodeVarint()
-	if err != nil {
-		return err
-	}
-	nb := int(nn) // number of bytes of encoded int32s
-
-	fin := o.index + nb
-	if fin < o.index {
-		return errOverflow
-	}
-	for o.index < fin {
-		u, err := p.valDec(o)
-		if err != nil {
-			return err
-		}
-		v.Append(uint32(u))
-	}
-	return nil
-}
-
-// Decode a slice of int64s ([]int64).
-func (o *Buffer) dec_slice_int64(p *Properties, base structPointer) error {
-	u, err := p.valDec(o)
-	if err != nil {
-		return err
-	}
-
-	structPointer_Word64Slice(base, p.field).Append(u)
-	return nil
-}
-
-// Decode a slice of int64s ([]int64) in packed format.
-func (o *Buffer) dec_slice_packed_int64(p *Properties, base structPointer) error {
-	v := structPointer_Word64Slice(base, p.field)
-
-	nn, err := o.DecodeVarint()
-	if err != nil {
-		return err
-	}
-	nb := int(nn) // number of bytes of encoded int64s
-
-	fin := o.index + nb
-	if fin < o.index {
-		return errOverflow
-	}
-	for o.index < fin {
-		u, err := p.valDec(o)
-		if err != nil {
-			return err
-		}
-		v.Append(u)
-	}
-	return nil
-}
-
-// Decode a slice of strings ([]string).
-func (o *Buffer) dec_slice_string(p *Properties, base structPointer) error {
-	s, err := o.DecodeStringBytes()
-	if err != nil {
-		return err
-	}
-	v := structPointer_StringSlice(base, p.field)
-	*v = append(*v, s)
-	return nil
-}
-
-// Decode a slice of slice of bytes ([][]byte).
-func (o *Buffer) dec_slice_slice_byte(p *Properties, base structPointer) error {
-	b, err := o.DecodeRawBytes(true)
-	if err != nil {
-		return err
-	}
-	v := structPointer_BytesSlice(base, p.field)
-	*v = append(*v, b)
-	return nil
-}
-
-// Decode a map field.
-func (o *Buffer) dec_new_map(p *Properties, base structPointer) error {
-	raw, err := o.DecodeRawBytes(false)
-	if err != nil {
-		return err
-	}
-	oi := o.index       // index at the end of this map entry
-	o.index -= len(raw) // move buffer back to start of map entry
-
-	mptr := structPointer_NewAt(base, p.field, p.mtype) // *map[K]V
-	if mptr.Elem().IsNil() {
-		mptr.Elem().Set(reflect.MakeMap(mptr.Type().Elem()))
-	}
-	v := mptr.Elem() // map[K]V
-
-	// Prepare addressable doubly-indirect placeholders for the key and value types.
-	// See enc_new_map for why.
-	keyptr := reflect.New(reflect.PtrTo(p.mtype.Key())).Elem() // addressable *K
-	keybase := toStructPointer(keyptr.Addr())                  // **K
-
-	var valbase structPointer
-	var valptr reflect.Value
-	switch p.mtype.Elem().Kind() {
-	case reflect.Slice:
-		// []byte
-		var dummy []byte
-		valptr = reflect.ValueOf(&dummy)  // *[]byte
-		valbase = toStructPointer(valptr) // *[]byte
-	case reflect.Ptr:
-		// message; valptr is **Msg; need to allocate the intermediate pointer
-		valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V
-		valptr.Set(reflect.New(valptr.Type().Elem()))
-		valbase = toStructPointer(valptr)
-	default:
-		// everything else
-		valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V
-		valbase = toStructPointer(valptr.Addr())                   // **V
-	}
-
-	// Decode.
-	// This parses a restricted wire format, namely the encoding of a message
-	// with two fields. See enc_new_map for the format.
-	for o.index < oi {
-		// tagcode for key and value properties are always a single byte
-		// because they have tags 1 and 2.
-		tagcode := o.buf[o.index]
-		o.index++
-		switch tagcode {
-		case p.mkeyprop.tagcode[0]:
-			if err := p.mkeyprop.dec(o, p.mkeyprop, keybase); err != nil {
-				return err
-			}
-		case p.mvalprop.tagcode[0]:
-			if err := p.mvalprop.dec(o, p.mvalprop, valbase); err != nil {
-				return err
-			}
-		default:
-			// TODO: Should we silently skip this instead?
-			return fmt.Errorf("proto: bad map data tag %d", raw[0])
-		}
-	}
-	keyelem, valelem := keyptr.Elem(), valptr.Elem()
-	if !keyelem.IsValid() {
-		keyelem = reflect.Zero(p.mtype.Key())
-	}
-	if !valelem.IsValid() {
-		valelem = reflect.Zero(p.mtype.Elem())
-	}
-
-	v.SetMapIndex(keyelem, valelem)
-	return nil
-}
-
-// Decode a group.
-func (o *Buffer) dec_struct_group(p *Properties, base structPointer) error {
-	bas := structPointer_GetStructPointer(base, p.field)
-	if structPointer_IsNil(bas) {
-		// allocate new nested message
-		bas = toStructPointer(reflect.New(p.stype))
-		structPointer_SetStructPointer(base, p.field, bas)
-	}
-	return o.unmarshalType(p.stype, p.sprop, true, bas)
-}
-
-// Decode an embedded message.
-func (o *Buffer) dec_struct_message(p *Properties, base structPointer) (err error) {
-	raw, e := o.DecodeRawBytes(false)
-	if e != nil {
-		return e
-	}
-
-	bas := structPointer_GetStructPointer(base, p.field)
-	if structPointer_IsNil(bas) {
-		// allocate new nested message
-		bas = toStructPointer(reflect.New(p.stype))
-		structPointer_SetStructPointer(base, p.field, bas)
-	}
-
-	// If the object can unmarshal itself, let it.
-	if p.isUnmarshaler {
-		iv := structPointer_Interface(bas, p.stype)
-		return iv.(Unmarshaler).Unmarshal(raw)
-	}
-
-	obuf := o.buf
-	oi := o.index
-	o.buf = raw
-	o.index = 0
-
-	err = o.unmarshalType(p.stype, p.sprop, false, bas)
-	o.buf = obuf
-	o.index = oi
-
-	return err
-}
-
-// Decode a slice of embedded messages.
-func (o *Buffer) dec_slice_struct_message(p *Properties, base structPointer) error {
-	return o.dec_slice_struct(p, false, base)
-}
-
-// Decode a slice of embedded groups.
-func (o *Buffer) dec_slice_struct_group(p *Properties, base structPointer) error {
-	return o.dec_slice_struct(p, true, base)
-}
-
-// Decode a slice of structs ([]*struct).
-func (o *Buffer) dec_slice_struct(p *Properties, is_group bool, base structPointer) error {
-	v := reflect.New(p.stype)
-	bas := toStructPointer(v)
-	structPointer_StructPointerSlice(base, p.field).Append(bas)
-
-	if is_group {
-		err := o.unmarshalType(p.stype, p.sprop, is_group, bas)
-		return err
-	}
-
-	raw, err := o.DecodeRawBytes(false)
-	if err != nil {
+	if u, ok := pb.(Unmarshaler); ok {
+		// NOTE: The history of proto have unfortunately been inconsistent
+		// whether Unmarshaler should or should not implicitly clear itself.
+		// Some implementations do, most do not.
+		// Thus, calling this here may or may not do what people want.
+		//
+		// See https://github.com/golang/protobuf/issues/424
+		err := u.Unmarshal(p.buf[p.index:])
+		p.index = len(p.buf)
 		return err
 	}
 
-	// If the object can unmarshal itself, let it.
-	if p.isUnmarshaler {
-		iv := v.Interface()
-		return iv.(Unmarshaler).Unmarshal(raw)
-	}
-
-	obuf := o.buf
-	oi := o.index
-	o.buf = raw
-	o.index = 0
-
-	err = o.unmarshalType(p.stype, p.sprop, is_group, bas)
-
-	o.buf = obuf
-	o.index = oi
-
+	// Slow workaround for messages that aren't Unmarshalers.
+	// This includes some hand-coded .pb.go files and
+	// bootstrap protos.
+	// TODO: fix all of those and then add Unmarshal to
+	// the Message interface. Then:
+	// The cast above and code below can be deleted.
+	// The old unmarshaler can be deleted.
+	// Clients can call Unmarshal directly (can already do that, actually).
+	var info InternalMessageInfo
+	err := info.Unmarshal(pb, p.buf[p.index:])
+	p.index = len(p.buf)
 	return err
 }

+ 63 - 0
vendor/github.com/golang/protobuf/proto/deprecated.go

@@ -0,0 +1,63 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2018 The Go Authors.  All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+import "errors"
+
+// 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) {}

+ 350 - 0
vendor/github.com/golang/protobuf/proto/discard.go

@@ -0,0 +1,350 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2017 The Go Authors.  All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+import (
+	"fmt"
+	"reflect"
+	"strings"
+	"sync"
+	"sync/atomic"
+)
+
+type generatedDiscarder interface {
+	XXX_DiscardUnknown()
+}
+
+// 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.
+//
+// For proto2 messages, the unknown fields of message extensions are only
+// discarded from messages that have been accessed via GetExtension.
+func DiscardUnknown(m Message) {
+	if m, ok := m.(generatedDiscarder); ok {
+		m.XXX_DiscardUnknown()
+		return
+	}
+	// TODO: Dynamically populate a InternalMessageInfo for legacy messages,
+	// but the master branch has no implementation for InternalMessageInfo,
+	// so it would be more work to replicate that approach.
+	discardLegacy(m)
+}
+
+// DiscardUnknown recursively discards all unknown fields.
+func (a *InternalMessageInfo) DiscardUnknown(m Message) {
+	di := atomicLoadDiscardInfo(&a.discard)
+	if di == nil {
+		di = getDiscardInfo(reflect.TypeOf(m).Elem())
+		atomicStoreDiscardInfo(&a.discard, di)
+	}
+	di.discard(toPointer(&m))
+}
+
+type discardInfo struct {
+	typ reflect.Type
+
+	initialized int32 // 0: only typ is valid, 1: everything is valid
+	lock        sync.Mutex
+
+	fields       []discardFieldInfo
+	unrecognized field
+}
+
+type discardFieldInfo struct {
+	field   field // Offset of field, guaranteed to be valid
+	discard func(src pointer)
+}
+
+var (
+	discardInfoMap  = map[reflect.Type]*discardInfo{}
+	discardInfoLock sync.Mutex
+)
+
+func getDiscardInfo(t reflect.Type) *discardInfo {
+	discardInfoLock.Lock()
+	defer discardInfoLock.Unlock()
+	di := discardInfoMap[t]
+	if di == nil {
+		di = &discardInfo{typ: t}
+		discardInfoMap[t] = di
+	}
+	return di
+}
+
+func (di *discardInfo) discard(src pointer) {
+	if src.isNil() {
+		return // Nothing to do.
+	}
+
+	if atomic.LoadInt32(&di.initialized) == 0 {
+		di.computeDiscardInfo()
+	}
+
+	for _, fi := range di.fields {
+		sfp := src.offset(fi.field)
+		fi.discard(sfp)
+	}
+
+	// For proto2 messages, only discard unknown fields in message extensions
+	// that have been accessed via GetExtension.
+	if em, err := extendable(src.asPointerTo(di.typ).Interface()); err == nil {
+		// Ignore lock since DiscardUnknown is not concurrency safe.
+		emm, _ := em.extensionsRead()
+		for _, mx := range emm {
+			if m, ok := mx.value.(Message); ok {
+				DiscardUnknown(m)
+			}
+		}
+	}
+
+	if di.unrecognized.IsValid() {
+		*src.offset(di.unrecognized).toBytes() = nil
+	}
+}
+
+func (di *discardInfo) computeDiscardInfo() {
+	di.lock.Lock()
+	defer di.lock.Unlock()
+	if di.initialized != 0 {
+		return
+	}
+	t := di.typ
+	n := t.NumField()
+
+	for i := 0; i < n; i++ {
+		f := t.Field(i)
+		if strings.HasPrefix(f.Name, "XXX_") {
+			continue
+		}
+
+		dfi := discardFieldInfo{field: toField(&f)}
+		tf := f.Type
+
+		// Unwrap tf to get its most basic type.
+		var isPointer, isSlice bool
+		if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
+			isSlice = true
+			tf = tf.Elem()
+		}
+		if tf.Kind() == reflect.Ptr {
+			isPointer = true
+			tf = tf.Elem()
+		}
+		if isPointer && isSlice && tf.Kind() != reflect.Struct {
+			panic(fmt.Sprintf("%v.%s cannot be a slice of pointers to primitive types", t, f.Name))
+		}
+
+		switch tf.Kind() {
+		case reflect.Struct:
+			switch {
+			case !isPointer:
+				panic(fmt.Sprintf("%v.%s cannot be a direct struct value", t, f.Name))
+			case isSlice: // E.g., []*pb.T
+				di := getDiscardInfo(tf)
+				dfi.discard = func(src pointer) {
+					sps := src.getPointerSlice()
+					for _, sp := range sps {
+						if !sp.isNil() {
+							di.discard(sp)
+						}
+					}
+				}
+			default: // E.g., *pb.T
+				di := getDiscardInfo(tf)
+				dfi.discard = func(src pointer) {
+					sp := src.getPointer()
+					if !sp.isNil() {
+						di.discard(sp)
+					}
+				}
+			}
+		case reflect.Map:
+			switch {
+			case isPointer || isSlice:
+				panic(fmt.Sprintf("%v.%s cannot be a pointer to a map or a slice of map values", t, f.Name))
+			default: // E.g., map[K]V
+				if tf.Elem().Kind() == reflect.Ptr { // Proto struct (e.g., *T)
+					dfi.discard = func(src pointer) {
+						sm := src.asPointerTo(tf).Elem()
+						if sm.Len() == 0 {
+							return
+						}
+						for _, key := range sm.MapKeys() {
+							val := sm.MapIndex(key)
+							DiscardUnknown(val.Interface().(Message))
+						}
+					}
+				} else {
+					dfi.discard = func(pointer) {} // Noop
+				}
+			}
+		case reflect.Interface:
+			// Must be oneof field.
+			switch {
+			case isPointer || isSlice:
+				panic(fmt.Sprintf("%v.%s cannot be a pointer to a interface or a slice of interface values", t, f.Name))
+			default: // E.g., interface{}
+				// TODO: Make this faster?
+				dfi.discard = func(src pointer) {
+					su := src.asPointerTo(tf).Elem()
+					if !su.IsNil() {
+						sv := su.Elem().Elem().Field(0)
+						if sv.Kind() == reflect.Ptr && sv.IsNil() {
+							return
+						}
+						switch sv.Type().Kind() {
+						case reflect.Ptr: // Proto struct (e.g., *T)
+							DiscardUnknown(sv.Interface().(Message))
+						}
+					}
+				}
+			}
+		default:
+			continue
+		}
+		di.fields = append(di.fields, dfi)
+	}
+
+	di.unrecognized = invalidField
+	if f, ok := t.FieldByName("XXX_unrecognized"); ok {
+		if f.Type != reflect.TypeOf([]byte{}) {
+			panic("expected XXX_unrecognized to be of type []byte")
+		}
+		di.unrecognized = toField(&f)
+	}
+
+	atomic.StoreInt32(&di.initialized, 1)
+}
+
+func discardLegacy(m Message) {
+	v := reflect.ValueOf(m)
+	if v.Kind() != reflect.Ptr || v.IsNil() {
+		return
+	}
+	v = v.Elem()
+	if v.Kind() != reflect.Struct {
+		return
+	}
+	t := v.Type()
+
+	for i := 0; i < v.NumField(); i++ {
+		f := t.Field(i)
+		if strings.HasPrefix(f.Name, "XXX_") {
+			continue
+		}
+		vf := v.Field(i)
+		tf := f.Type
+
+		// Unwrap tf to get its most basic type.
+		var isPointer, isSlice bool
+		if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
+			isSlice = true
+			tf = tf.Elem()
+		}
+		if tf.Kind() == reflect.Ptr {
+			isPointer = true
+			tf = tf.Elem()
+		}
+		if isPointer && isSlice && tf.Kind() != reflect.Struct {
+			panic(fmt.Sprintf("%T.%s cannot be a slice of pointers to primitive types", m, f.Name))
+		}
+
+		switch tf.Kind() {
+		case reflect.Struct:
+			switch {
+			case !isPointer:
+				panic(fmt.Sprintf("%T.%s cannot be a direct struct value", m, f.Name))
+			case isSlice: // E.g., []*pb.T
+				for j := 0; j < vf.Len(); j++ {
+					discardLegacy(vf.Index(j).Interface().(Message))
+				}
+			default: // E.g., *pb.T
+				discardLegacy(vf.Interface().(Message))
+			}
+		case reflect.Map:
+			switch {
+			case isPointer || isSlice:
+				panic(fmt.Sprintf("%T.%s cannot be a pointer to a map or a slice of map values", m, f.Name))
+			default: // E.g., map[K]V
+				tv := vf.Type().Elem()
+				if tv.Kind() == reflect.Ptr && tv.Implements(protoMessageType) { // Proto struct (e.g., *T)
+					for _, key := range vf.MapKeys() {
+						val := vf.MapIndex(key)
+						discardLegacy(val.Interface().(Message))
+					}
+				}
+			}
+		case reflect.Interface:
+			// Must be oneof field.
+			switch {
+			case isPointer || isSlice:
+				panic(fmt.Sprintf("%T.%s cannot be a pointer to a interface or a slice of interface values", m, f.Name))
+			default: // E.g., test_proto.isCommunique_Union interface
+				if !vf.IsNil() && f.Tag.Get("protobuf_oneof") != "" {
+					vf = vf.Elem() // E.g., *test_proto.Communique_Msg
+					if !vf.IsNil() {
+						vf = vf.Elem()   // E.g., test_proto.Communique_Msg
+						vf = vf.Field(0) // E.g., Proto struct (e.g., *T) or primitive value
+						if vf.Kind() == reflect.Ptr {
+							discardLegacy(vf.Interface().(Message))
+						}
+					}
+				}
+			}
+		}
+	}
+
+	if vf := v.FieldByName("XXX_unrecognized"); vf.IsValid() {
+		if vf.Type() != reflect.TypeOf([]byte{}) {
+			panic("expected XXX_unrecognized to be of type []byte")
+		}
+		vf.Set(reflect.ValueOf([]byte(nil)))
+	}
+
+	// For proto2 messages, only discard unknown fields in message extensions
+	// that have been accessed via GetExtension.
+	if em, err := extendable(m); err == nil {
+		// Ignore lock since discardLegacy is not concurrency safe.
+		emm, _ := em.extensionsRead()
+		for _, mx := range emm {
+			if m, ok := mx.value.(Message); ok {
+				discardLegacy(m)
+			}
+		}
+	}
+}

+ 25 - 1184
vendor/github.com/golang/protobuf/proto/encode.go

@@ -37,28 +37,9 @@ package proto
 
 import (
 	"errors"
-	"fmt"
 	"reflect"
-	"sort"
 )
 
-// RequiredNotSetError is the error returned if Marshal is called with
-// a protocol buffer struct whose required fields have not
-// all been initialized. It is also the error returned if Unmarshal is
-// called with an encoded protocol buffer that does not include all the
-// required fields.
-//
-// When printed, RequiredNotSetError reports the first unset required field in a
-// message. If the field cannot be precisely determined, it is reported as
-// "{Unknown}".
-type RequiredNotSetError struct {
-	field string
-}
-
-func (e *RequiredNotSetError) Error() string {
-	return fmt.Sprintf("proto: required field %q not set", e.field)
-}
-
 var (
 	// errRepeatedHasNil is the error returned if Marshal is called with
 	// a struct with a repeated field containing a nil element.
@@ -82,10 +63,6 @@ var (
 
 const maxVarintBytes = 10 // maximum length of a varint
 
-// maxMarshalSize is the largest allowed size of an encoded protobuf,
-// since C++ and Java use signed int32s for the size.
-const maxMarshalSize = 1<<31 - 1
-
 // EncodeVarint returns the varint encoding of x.
 // This is the format for the
 // int32, int64, uint32, uint64, bool, and enum
@@ -119,18 +96,27 @@ func (p *Buffer) EncodeVarint(x uint64) error {
 
 // SizeVarint returns the varint encoding size of an integer.
 func SizeVarint(x uint64) int {
-	return sizeVarint(x)
-}
-
-func sizeVarint(x uint64) (n int) {
-	for {
-		n++
-		x >>= 7
-		if x == 0 {
-			break
-		}
-	}
-	return n
+	switch {
+	case x < 1<<7:
+		return 1
+	case x < 1<<14:
+		return 2
+	case x < 1<<21:
+		return 3
+	case x < 1<<28:
+		return 4
+	case x < 1<<35:
+		return 5
+	case x < 1<<42:
+		return 6
+	case x < 1<<49:
+		return 7
+	case x < 1<<56:
+		return 8
+	case x < 1<<63:
+		return 9
+	}
+	return 10
 }
 
 // EncodeFixed64 writes a 64-bit integer to the Buffer.
@@ -149,10 +135,6 @@ func (p *Buffer) EncodeFixed64(x uint64) error {
 	return nil
 }
 
-func sizeFixed64(x uint64) int {
-	return 8
-}
-
 // EncodeFixed32 writes a 32-bit integer to the Buffer.
 // This is the format for the
 // fixed32, sfixed32, and float protocol buffer types.
@@ -165,20 +147,12 @@ func (p *Buffer) EncodeFixed32(x uint64) error {
 	return nil
 }
 
-func sizeFixed32(x uint64) int {
-	return 4
-}
-
 // EncodeZigzag64 writes a zigzag-encoded 64-bit integer
 // to the Buffer.
 // This is the format used for the sint64 protocol buffer type.
 func (p *Buffer) EncodeZigzag64(x uint64) error {
 	// use signed number to get arithmetic right shift.
-	return p.EncodeVarint((x << 1) ^ uint64((int64(x) >> 63)))
-}
-
-func sizeZigzag64(x uint64) int {
-	return sizeVarint((x << 1) ^ uint64((int64(x) >> 63)))
+	return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
 }
 
 // EncodeZigzag32 writes a zigzag-encoded 32-bit integer
@@ -189,10 +163,6 @@ func (p *Buffer) EncodeZigzag32(x uint64) error {
 	return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
 }
 
-func sizeZigzag32(x uint64) int {
-	return sizeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
-}
-
 // EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
 // This is the format used for the bytes protocol buffer
 // type and for embedded messages.
@@ -202,11 +172,6 @@ func (p *Buffer) EncodeRawBytes(b []byte) error {
 	return nil
 }
 
-func sizeRawBytes(b []byte) int {
-	return sizeVarint(uint64(len(b))) +
-		len(b)
-}
-
 // EncodeStringBytes writes an encoded string to the Buffer.
 // This is the format used for the proto2 string type.
 func (p *Buffer) EncodeStringBytes(s string) error {
@@ -215,319 +180,17 @@ func (p *Buffer) EncodeStringBytes(s string) error {
 	return nil
 }
 
-func sizeStringBytes(s string) int {
-	return sizeVarint(uint64(len(s))) +
-		len(s)
-}
-
 // Marshaler is the interface representing objects that can marshal themselves.
 type Marshaler interface {
 	Marshal() ([]byte, error)
 }
 
-// Marshal takes the protocol buffer
-// and encodes it into the wire format, returning the data.
-func Marshal(pb Message) ([]byte, error) {
-	// Can the object marshal itself?
-	if m, ok := pb.(Marshaler); ok {
-		return m.Marshal()
-	}
-	p := NewBuffer(nil)
-	err := p.Marshal(pb)
-	if p.buf == nil && err == nil {
-		// Return a non-nil slice on success.
-		return []byte{}, nil
-	}
-	return p.buf, err
-}
-
 // EncodeMessage writes the protocol buffer to the Buffer,
 // prefixed by a varint-encoded length.
 func (p *Buffer) EncodeMessage(pb Message) error {
-	t, base, err := getbase(pb)
-	if structPointer_IsNil(base) {
-		return ErrNil
-	}
-	if err == nil {
-		var state errorState
-		err = p.enc_len_struct(GetProperties(t.Elem()), base, &state)
-	}
-	return err
-}
-
-// Marshal takes the protocol buffer
-// and encodes it into the wire format, writing the result to the
-// Buffer.
-func (p *Buffer) Marshal(pb Message) error {
-	// Can the object marshal itself?
-	if m, ok := pb.(Marshaler); ok {
-		data, err := m.Marshal()
-		p.buf = append(p.buf, data...)
-		return err
-	}
-
-	t, base, err := getbase(pb)
-	if structPointer_IsNil(base) {
-		return ErrNil
-	}
-	if err == nil {
-		err = p.enc_struct(GetProperties(t.Elem()), base)
-	}
-
-	if collectStats {
-		(stats).Encode++ // Parens are to work around a goimports bug.
-	}
-
-	if len(p.buf) > maxMarshalSize {
-		return ErrTooLarge
-	}
-	return err
-}
-
-// Size returns the encoded size of a protocol buffer.
-func Size(pb Message) (n int) {
-	// Can the object marshal itself?  If so, Size is slow.
-	// TODO: add Size to Marshaler, or add a Sizer interface.
-	if m, ok := pb.(Marshaler); ok {
-		b, _ := m.Marshal()
-		return len(b)
-	}
-
-	t, base, err := getbase(pb)
-	if structPointer_IsNil(base) {
-		return 0
-	}
-	if err == nil {
-		n = size_struct(GetProperties(t.Elem()), base)
-	}
-
-	if collectStats {
-		(stats).Size++ // Parens are to work around a goimports bug.
-	}
-
-	return
-}
-
-// Individual type encoders.
-
-// Encode a bool.
-func (o *Buffer) enc_bool(p *Properties, base structPointer) error {
-	v := *structPointer_Bool(base, p.field)
-	if v == nil {
-		return ErrNil
-	}
-	x := 0
-	if *v {
-		x = 1
-	}
-	o.buf = append(o.buf, p.tagcode...)
-	p.valEnc(o, uint64(x))
-	return nil
-}
-
-func (o *Buffer) enc_proto3_bool(p *Properties, base structPointer) error {
-	v := *structPointer_BoolVal(base, p.field)
-	if !v {
-		return ErrNil
-	}
-	o.buf = append(o.buf, p.tagcode...)
-	p.valEnc(o, 1)
-	return nil
-}
-
-func size_bool(p *Properties, base structPointer) int {
-	v := *structPointer_Bool(base, p.field)
-	if v == nil {
-		return 0
-	}
-	return len(p.tagcode) + 1 // each bool takes exactly one byte
-}
-
-func size_proto3_bool(p *Properties, base structPointer) int {
-	v := *structPointer_BoolVal(base, p.field)
-	if !v && !p.oneof {
-		return 0
-	}
-	return len(p.tagcode) + 1 // each bool takes exactly one byte
-}
-
-// Encode an int32.
-func (o *Buffer) enc_int32(p *Properties, base structPointer) error {
-	v := structPointer_Word32(base, p.field)
-	if word32_IsNil(v) {
-		return ErrNil
-	}
-	x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range
-	o.buf = append(o.buf, p.tagcode...)
-	p.valEnc(o, uint64(x))
-	return nil
-}
-
-func (o *Buffer) enc_proto3_int32(p *Properties, base structPointer) error {
-	v := structPointer_Word32Val(base, p.field)
-	x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range
-	if x == 0 {
-		return ErrNil
-	}
-	o.buf = append(o.buf, p.tagcode...)
-	p.valEnc(o, uint64(x))
-	return nil
-}
-
-func size_int32(p *Properties, base structPointer) (n int) {
-	v := structPointer_Word32(base, p.field)
-	if word32_IsNil(v) {
-		return 0
-	}
-	x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range
-	n += len(p.tagcode)
-	n += p.valSize(uint64(x))
-	return
-}
-
-func size_proto3_int32(p *Properties, base structPointer) (n int) {
-	v := structPointer_Word32Val(base, p.field)
-	x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range
-	if x == 0 && !p.oneof {
-		return 0
-	}
-	n += len(p.tagcode)
-	n += p.valSize(uint64(x))
-	return
-}
-
-// Encode a uint32.
-// Exactly the same as int32, except for no sign extension.
-func (o *Buffer) enc_uint32(p *Properties, base structPointer) error {
-	v := structPointer_Word32(base, p.field)
-	if word32_IsNil(v) {
-		return ErrNil
-	}
-	x := word32_Get(v)
-	o.buf = append(o.buf, p.tagcode...)
-	p.valEnc(o, uint64(x))
-	return nil
-}
-
-func (o *Buffer) enc_proto3_uint32(p *Properties, base structPointer) error {
-	v := structPointer_Word32Val(base, p.field)
-	x := word32Val_Get(v)
-	if x == 0 {
-		return ErrNil
-	}
-	o.buf = append(o.buf, p.tagcode...)
-	p.valEnc(o, uint64(x))
-	return nil
-}
-
-func size_uint32(p *Properties, base structPointer) (n int) {
-	v := structPointer_Word32(base, p.field)
-	if word32_IsNil(v) {
-		return 0
-	}
-	x := word32_Get(v)
-	n += len(p.tagcode)
-	n += p.valSize(uint64(x))
-	return
-}
-
-func size_proto3_uint32(p *Properties, base structPointer) (n int) {
-	v := structPointer_Word32Val(base, p.field)
-	x := word32Val_Get(v)
-	if x == 0 && !p.oneof {
-		return 0
-	}
-	n += len(p.tagcode)
-	n += p.valSize(uint64(x))
-	return
-}
-
-// Encode an int64.
-func (o *Buffer) enc_int64(p *Properties, base structPointer) error {
-	v := structPointer_Word64(base, p.field)
-	if word64_IsNil(v) {
-		return ErrNil
-	}
-	x := word64_Get(v)
-	o.buf = append(o.buf, p.tagcode...)
-	p.valEnc(o, x)
-	return nil
-}
-
-func (o *Buffer) enc_proto3_int64(p *Properties, base structPointer) error {
-	v := structPointer_Word64Val(base, p.field)
-	x := word64Val_Get(v)
-	if x == 0 {
-		return ErrNil
-	}
-	o.buf = append(o.buf, p.tagcode...)
-	p.valEnc(o, x)
-	return nil
-}
-
-func size_int64(p *Properties, base structPointer) (n int) {
-	v := structPointer_Word64(base, p.field)
-	if word64_IsNil(v) {
-		return 0
-	}
-	x := word64_Get(v)
-	n += len(p.tagcode)
-	n += p.valSize(x)
-	return
-}
-
-func size_proto3_int64(p *Properties, base structPointer) (n int) {
-	v := structPointer_Word64Val(base, p.field)
-	x := word64Val_Get(v)
-	if x == 0 && !p.oneof {
-		return 0
-	}
-	n += len(p.tagcode)
-	n += p.valSize(x)
-	return
-}
-
-// Encode a string.
-func (o *Buffer) enc_string(p *Properties, base structPointer) error {
-	v := *structPointer_String(base, p.field)
-	if v == nil {
-		return ErrNil
-	}
-	x := *v
-	o.buf = append(o.buf, p.tagcode...)
-	o.EncodeStringBytes(x)
-	return nil
-}
-
-func (o *Buffer) enc_proto3_string(p *Properties, base structPointer) error {
-	v := *structPointer_StringVal(base, p.field)
-	if v == "" {
-		return ErrNil
-	}
-	o.buf = append(o.buf, p.tagcode...)
-	o.EncodeStringBytes(v)
-	return nil
-}
-
-func size_string(p *Properties, base structPointer) (n int) {
-	v := *structPointer_String(base, p.field)
-	if v == nil {
-		return 0
-	}
-	x := *v
-	n += len(p.tagcode)
-	n += sizeStringBytes(x)
-	return
-}
-
-func size_proto3_string(p *Properties, base structPointer) (n int) {
-	v := *structPointer_StringVal(base, p.field)
-	if v == "" && !p.oneof {
-		return 0
-	}
-	n += len(p.tagcode)
-	n += sizeStringBytes(v)
-	return
+	siz := Size(pb)
+	p.EncodeVarint(uint64(siz))
+	return p.Marshal(pb)
 }
 
 // All protocol buffer fields are nillable, but be careful.
@@ -538,825 +201,3 @@ func isNil(v reflect.Value) bool {
 	}
 	return false
 }
-
-// Encode a message struct.
-func (o *Buffer) enc_struct_message(p *Properties, base structPointer) error {
-	var state errorState
-	structp := structPointer_GetStructPointer(base, p.field)
-	if structPointer_IsNil(structp) {
-		return ErrNil
-	}
-
-	// Can the object marshal itself?
-	if p.isMarshaler {
-		m := structPointer_Interface(structp, p.stype).(Marshaler)
-		data, err := m.Marshal()
-		if err != nil && !state.shouldContinue(err, nil) {
-			return err
-		}
-		o.buf = append(o.buf, p.tagcode...)
-		o.EncodeRawBytes(data)
-		return state.err
-	}
-
-	o.buf = append(o.buf, p.tagcode...)
-	return o.enc_len_struct(p.sprop, structp, &state)
-}
-
-func size_struct_message(p *Properties, base structPointer) int {
-	structp := structPointer_GetStructPointer(base, p.field)
-	if structPointer_IsNil(structp) {
-		return 0
-	}
-
-	// Can the object marshal itself?
-	if p.isMarshaler {
-		m := structPointer_Interface(structp, p.stype).(Marshaler)
-		data, _ := m.Marshal()
-		n0 := len(p.tagcode)
-		n1 := sizeRawBytes(data)
-		return n0 + n1
-	}
-
-	n0 := len(p.tagcode)
-	n1 := size_struct(p.sprop, structp)
-	n2 := sizeVarint(uint64(n1)) // size of encoded length
-	return n0 + n1 + n2
-}
-
-// Encode a group struct.
-func (o *Buffer) enc_struct_group(p *Properties, base structPointer) error {
-	var state errorState
-	b := structPointer_GetStructPointer(base, p.field)
-	if structPointer_IsNil(b) {
-		return ErrNil
-	}
-
-	o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
-	err := o.enc_struct(p.sprop, b)
-	if err != nil && !state.shouldContinue(err, nil) {
-		return err
-	}
-	o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
-	return state.err
-}
-
-func size_struct_group(p *Properties, base structPointer) (n int) {
-	b := structPointer_GetStructPointer(base, p.field)
-	if structPointer_IsNil(b) {
-		return 0
-	}
-
-	n += sizeVarint(uint64((p.Tag << 3) | WireStartGroup))
-	n += size_struct(p.sprop, b)
-	n += sizeVarint(uint64((p.Tag << 3) | WireEndGroup))
-	return
-}
-
-// Encode a slice of bools ([]bool).
-func (o *Buffer) enc_slice_bool(p *Properties, base structPointer) error {
-	s := *structPointer_BoolSlice(base, p.field)
-	l := len(s)
-	if l == 0 {
-		return ErrNil
-	}
-	for _, x := range s {
-		o.buf = append(o.buf, p.tagcode...)
-		v := uint64(0)
-		if x {
-			v = 1
-		}
-		p.valEnc(o, v)
-	}
-	return nil
-}
-
-func size_slice_bool(p *Properties, base structPointer) int {
-	s := *structPointer_BoolSlice(base, p.field)
-	l := len(s)
-	if l == 0 {
-		return 0
-	}
-	return l * (len(p.tagcode) + 1) // each bool takes exactly one byte
-}
-
-// Encode a slice of bools ([]bool) in packed format.
-func (o *Buffer) enc_slice_packed_bool(p *Properties, base structPointer) error {
-	s := *structPointer_BoolSlice(base, p.field)
-	l := len(s)
-	if l == 0 {
-		return ErrNil
-	}
-	o.buf = append(o.buf, p.tagcode...)
-	o.EncodeVarint(uint64(l)) // each bool takes exactly one byte
-	for _, x := range s {
-		v := uint64(0)
-		if x {
-			v = 1
-		}
-		p.valEnc(o, v)
-	}
-	return nil
-}
-
-func size_slice_packed_bool(p *Properties, base structPointer) (n int) {
-	s := *structPointer_BoolSlice(base, p.field)
-	l := len(s)
-	if l == 0 {
-		return 0
-	}
-	n += len(p.tagcode)
-	n += sizeVarint(uint64(l))
-	n += l // each bool takes exactly one byte
-	return
-}
-
-// Encode a slice of bytes ([]byte).
-func (o *Buffer) enc_slice_byte(p *Properties, base structPointer) error {
-	s := *structPointer_Bytes(base, p.field)
-	if s == nil {
-		return ErrNil
-	}
-	o.buf = append(o.buf, p.tagcode...)
-	o.EncodeRawBytes(s)
-	return nil
-}
-
-func (o *Buffer) enc_proto3_slice_byte(p *Properties, base structPointer) error {
-	s := *structPointer_Bytes(base, p.field)
-	if len(s) == 0 {
-		return ErrNil
-	}
-	o.buf = append(o.buf, p.tagcode...)
-	o.EncodeRawBytes(s)
-	return nil
-}
-
-func size_slice_byte(p *Properties, base structPointer) (n int) {
-	s := *structPointer_Bytes(base, p.field)
-	if s == nil && !p.oneof {
-		return 0
-	}
-	n += len(p.tagcode)
-	n += sizeRawBytes(s)
-	return
-}
-
-func size_proto3_slice_byte(p *Properties, base structPointer) (n int) {
-	s := *structPointer_Bytes(base, p.field)
-	if len(s) == 0 && !p.oneof {
-		return 0
-	}
-	n += len(p.tagcode)
-	n += sizeRawBytes(s)
-	return
-}
-
-// Encode a slice of int32s ([]int32).
-func (o *Buffer) enc_slice_int32(p *Properties, base structPointer) error {
-	s := structPointer_Word32Slice(base, p.field)
-	l := s.Len()
-	if l == 0 {
-		return ErrNil
-	}
-	for i := 0; i < l; i++ {
-		o.buf = append(o.buf, p.tagcode...)
-		x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
-		p.valEnc(o, uint64(x))
-	}
-	return nil
-}
-
-func size_slice_int32(p *Properties, base structPointer) (n int) {
-	s := structPointer_Word32Slice(base, p.field)
-	l := s.Len()
-	if l == 0 {
-		return 0
-	}
-	for i := 0; i < l; i++ {
-		n += len(p.tagcode)
-		x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
-		n += p.valSize(uint64(x))
-	}
-	return
-}
-
-// Encode a slice of int32s ([]int32) in packed format.
-func (o *Buffer) enc_slice_packed_int32(p *Properties, base structPointer) error {
-	s := structPointer_Word32Slice(base, p.field)
-	l := s.Len()
-	if l == 0 {
-		return ErrNil
-	}
-	// TODO: Reuse a Buffer.
-	buf := NewBuffer(nil)
-	for i := 0; i < l; i++ {
-		x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
-		p.valEnc(buf, uint64(x))
-	}
-
-	o.buf = append(o.buf, p.tagcode...)
-	o.EncodeVarint(uint64(len(buf.buf)))
-	o.buf = append(o.buf, buf.buf...)
-	return nil
-}
-
-func size_slice_packed_int32(p *Properties, base structPointer) (n int) {
-	s := structPointer_Word32Slice(base, p.field)
-	l := s.Len()
-	if l == 0 {
-		return 0
-	}
-	var bufSize int
-	for i := 0; i < l; i++ {
-		x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
-		bufSize += p.valSize(uint64(x))
-	}
-
-	n += len(p.tagcode)
-	n += sizeVarint(uint64(bufSize))
-	n += bufSize
-	return
-}
-
-// Encode a slice of uint32s ([]uint32).
-// Exactly the same as int32, except for no sign extension.
-func (o *Buffer) enc_slice_uint32(p *Properties, base structPointer) error {
-	s := structPointer_Word32Slice(base, p.field)
-	l := s.Len()
-	if l == 0 {
-		return ErrNil
-	}
-	for i := 0; i < l; i++ {
-		o.buf = append(o.buf, p.tagcode...)
-		x := s.Index(i)
-		p.valEnc(o, uint64(x))
-	}
-	return nil
-}
-
-func size_slice_uint32(p *Properties, base structPointer) (n int) {
-	s := structPointer_Word32Slice(base, p.field)
-	l := s.Len()
-	if l == 0 {
-		return 0
-	}
-	for i := 0; i < l; i++ {
-		n += len(p.tagcode)
-		x := s.Index(i)
-		n += p.valSize(uint64(x))
-	}
-	return
-}
-
-// Encode a slice of uint32s ([]uint32) in packed format.
-// Exactly the same as int32, except for no sign extension.
-func (o *Buffer) enc_slice_packed_uint32(p *Properties, base structPointer) error {
-	s := structPointer_Word32Slice(base, p.field)
-	l := s.Len()
-	if l == 0 {
-		return ErrNil
-	}
-	// TODO: Reuse a Buffer.
-	buf := NewBuffer(nil)
-	for i := 0; i < l; i++ {
-		p.valEnc(buf, uint64(s.Index(i)))
-	}
-
-	o.buf = append(o.buf, p.tagcode...)
-	o.EncodeVarint(uint64(len(buf.buf)))
-	o.buf = append(o.buf, buf.buf...)
-	return nil
-}
-
-func size_slice_packed_uint32(p *Properties, base structPointer) (n int) {
-	s := structPointer_Word32Slice(base, p.field)
-	l := s.Len()
-	if l == 0 {
-		return 0
-	}
-	var bufSize int
-	for i := 0; i < l; i++ {
-		bufSize += p.valSize(uint64(s.Index(i)))
-	}
-
-	n += len(p.tagcode)
-	n += sizeVarint(uint64(bufSize))
-	n += bufSize
-	return
-}
-
-// Encode a slice of int64s ([]int64).
-func (o *Buffer) enc_slice_int64(p *Properties, base structPointer) error {
-	s := structPointer_Word64Slice(base, p.field)
-	l := s.Len()
-	if l == 0 {
-		return ErrNil
-	}
-	for i := 0; i < l; i++ {
-		o.buf = append(o.buf, p.tagcode...)
-		p.valEnc(o, s.Index(i))
-	}
-	return nil
-}
-
-func size_slice_int64(p *Properties, base structPointer) (n int) {
-	s := structPointer_Word64Slice(base, p.field)
-	l := s.Len()
-	if l == 0 {
-		return 0
-	}
-	for i := 0; i < l; i++ {
-		n += len(p.tagcode)
-		n += p.valSize(s.Index(i))
-	}
-	return
-}
-
-// Encode a slice of int64s ([]int64) in packed format.
-func (o *Buffer) enc_slice_packed_int64(p *Properties, base structPointer) error {
-	s := structPointer_Word64Slice(base, p.field)
-	l := s.Len()
-	if l == 0 {
-		return ErrNil
-	}
-	// TODO: Reuse a Buffer.
-	buf := NewBuffer(nil)
-	for i := 0; i < l; i++ {
-		p.valEnc(buf, s.Index(i))
-	}
-
-	o.buf = append(o.buf, p.tagcode...)
-	o.EncodeVarint(uint64(len(buf.buf)))
-	o.buf = append(o.buf, buf.buf...)
-	return nil
-}
-
-func size_slice_packed_int64(p *Properties, base structPointer) (n int) {
-	s := structPointer_Word64Slice(base, p.field)
-	l := s.Len()
-	if l == 0 {
-		return 0
-	}
-	var bufSize int
-	for i := 0; i < l; i++ {
-		bufSize += p.valSize(s.Index(i))
-	}
-
-	n += len(p.tagcode)
-	n += sizeVarint(uint64(bufSize))
-	n += bufSize
-	return
-}
-
-// Encode a slice of slice of bytes ([][]byte).
-func (o *Buffer) enc_slice_slice_byte(p *Properties, base structPointer) error {
-	ss := *structPointer_BytesSlice(base, p.field)
-	l := len(ss)
-	if l == 0 {
-		return ErrNil
-	}
-	for i := 0; i < l; i++ {
-		o.buf = append(o.buf, p.tagcode...)
-		o.EncodeRawBytes(ss[i])
-	}
-	return nil
-}
-
-func size_slice_slice_byte(p *Properties, base structPointer) (n int) {
-	ss := *structPointer_BytesSlice(base, p.field)
-	l := len(ss)
-	if l == 0 {
-		return 0
-	}
-	n += l * len(p.tagcode)
-	for i := 0; i < l; i++ {
-		n += sizeRawBytes(ss[i])
-	}
-	return
-}
-
-// Encode a slice of strings ([]string).
-func (o *Buffer) enc_slice_string(p *Properties, base structPointer) error {
-	ss := *structPointer_StringSlice(base, p.field)
-	l := len(ss)
-	for i := 0; i < l; i++ {
-		o.buf = append(o.buf, p.tagcode...)
-		o.EncodeStringBytes(ss[i])
-	}
-	return nil
-}
-
-func size_slice_string(p *Properties, base structPointer) (n int) {
-	ss := *structPointer_StringSlice(base, p.field)
-	l := len(ss)
-	n += l * len(p.tagcode)
-	for i := 0; i < l; i++ {
-		n += sizeStringBytes(ss[i])
-	}
-	return
-}
-
-// Encode a slice of message structs ([]*struct).
-func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) error {
-	var state errorState
-	s := structPointer_StructPointerSlice(base, p.field)
-	l := s.Len()
-
-	for i := 0; i < l; i++ {
-		structp := s.Index(i)
-		if structPointer_IsNil(structp) {
-			return errRepeatedHasNil
-		}
-
-		// Can the object marshal itself?
-		if p.isMarshaler {
-			m := structPointer_Interface(structp, p.stype).(Marshaler)
-			data, err := m.Marshal()
-			if err != nil && !state.shouldContinue(err, nil) {
-				return err
-			}
-			o.buf = append(o.buf, p.tagcode...)
-			o.EncodeRawBytes(data)
-			continue
-		}
-
-		o.buf = append(o.buf, p.tagcode...)
-		err := o.enc_len_struct(p.sprop, structp, &state)
-		if err != nil && !state.shouldContinue(err, nil) {
-			if err == ErrNil {
-				return errRepeatedHasNil
-			}
-			return err
-		}
-	}
-	return state.err
-}
-
-func size_slice_struct_message(p *Properties, base structPointer) (n int) {
-	s := structPointer_StructPointerSlice(base, p.field)
-	l := s.Len()
-	n += l * len(p.tagcode)
-	for i := 0; i < l; i++ {
-		structp := s.Index(i)
-		if structPointer_IsNil(structp) {
-			return // return the size up to this point
-		}
-
-		// Can the object marshal itself?
-		if p.isMarshaler {
-			m := structPointer_Interface(structp, p.stype).(Marshaler)
-			data, _ := m.Marshal()
-			n += sizeRawBytes(data)
-			continue
-		}
-
-		n0 := size_struct(p.sprop, structp)
-		n1 := sizeVarint(uint64(n0)) // size of encoded length
-		n += n0 + n1
-	}
-	return
-}
-
-// Encode a slice of group structs ([]*struct).
-func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointer) error {
-	var state errorState
-	s := structPointer_StructPointerSlice(base, p.field)
-	l := s.Len()
-
-	for i := 0; i < l; i++ {
-		b := s.Index(i)
-		if structPointer_IsNil(b) {
-			return errRepeatedHasNil
-		}
-
-		o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
-
-		err := o.enc_struct(p.sprop, b)
-
-		if err != nil && !state.shouldContinue(err, nil) {
-			if err == ErrNil {
-				return errRepeatedHasNil
-			}
-			return err
-		}
-
-		o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
-	}
-	return state.err
-}
-
-func size_slice_struct_group(p *Properties, base structPointer) (n int) {
-	s := structPointer_StructPointerSlice(base, p.field)
-	l := s.Len()
-
-	n += l * sizeVarint(uint64((p.Tag<<3)|WireStartGroup))
-	n += l * sizeVarint(uint64((p.Tag<<3)|WireEndGroup))
-	for i := 0; i < l; i++ {
-		b := s.Index(i)
-		if structPointer_IsNil(b) {
-			return // return size up to this point
-		}
-
-		n += size_struct(p.sprop, b)
-	}
-	return
-}
-
-// Encode an extension map.
-func (o *Buffer) enc_map(p *Properties, base structPointer) error {
-	exts := structPointer_ExtMap(base, p.field)
-	if err := encodeExtensionsMap(*exts); err != nil {
-		return err
-	}
-
-	return o.enc_map_body(*exts)
-}
-
-func (o *Buffer) enc_exts(p *Properties, base structPointer) error {
-	exts := structPointer_Extensions(base, p.field)
-
-	v, mu := exts.extensionsRead()
-	if v == nil {
-		return nil
-	}
-
-	mu.Lock()
-	defer mu.Unlock()
-	if err := encodeExtensionsMap(v); err != nil {
-		return err
-	}
-
-	return o.enc_map_body(v)
-}
-
-func (o *Buffer) enc_map_body(v map[int32]Extension) error {
-	// Fast-path for common cases: zero or one extensions.
-	if len(v) <= 1 {
-		for _, e := range v {
-			o.buf = append(o.buf, e.enc...)
-		}
-		return nil
-	}
-
-	// Sort keys to provide a deterministic encoding.
-	keys := make([]int, 0, len(v))
-	for k := range v {
-		keys = append(keys, int(k))
-	}
-	sort.Ints(keys)
-
-	for _, k := range keys {
-		o.buf = append(o.buf, v[int32(k)].enc...)
-	}
-	return nil
-}
-
-func size_map(p *Properties, base structPointer) int {
-	v := structPointer_ExtMap(base, p.field)
-	return extensionsMapSize(*v)
-}
-
-func size_exts(p *Properties, base structPointer) int {
-	v := structPointer_Extensions(base, p.field)
-	return extensionsSize(v)
-}
-
-// Encode a map field.
-func (o *Buffer) enc_new_map(p *Properties, base structPointer) error {
-	var state errorState // XXX: or do we need to plumb this through?
-
-	/*
-		A map defined as
-			map<key_type, value_type> map_field = N;
-		is encoded in the same way as
-			message MapFieldEntry {
-				key_type key = 1;
-				value_type value = 2;
-			}
-			repeated MapFieldEntry map_field = N;
-	*/
-
-	v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V
-	if v.Len() == 0 {
-		return nil
-	}
-
-	keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype)
-
-	enc := func() error {
-		if err := p.mkeyprop.enc(o, p.mkeyprop, keybase); err != nil {
-			return err
-		}
-		if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil && err != ErrNil {
-			return err
-		}
-		return nil
-	}
-
-	// Don't sort map keys. It is not required by the spec, and C++ doesn't do it.
-	for _, key := range v.MapKeys() {
-		val := v.MapIndex(key)
-
-		keycopy.Set(key)
-		valcopy.Set(val)
-
-		o.buf = append(o.buf, p.tagcode...)
-		if err := o.enc_len_thing(enc, &state); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-func size_new_map(p *Properties, base structPointer) int {
-	v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V
-
-	keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype)
-
-	n := 0
-	for _, key := range v.MapKeys() {
-		val := v.MapIndex(key)
-		keycopy.Set(key)
-		valcopy.Set(val)
-
-		// Tag codes for key and val are the responsibility of the sub-sizer.
-		keysize := p.mkeyprop.size(p.mkeyprop, keybase)
-		valsize := p.mvalprop.size(p.mvalprop, valbase)
-		entry := keysize + valsize
-		// Add on tag code and length of map entry itself.
-		n += len(p.tagcode) + sizeVarint(uint64(entry)) + entry
-	}
-	return n
-}
-
-// mapEncodeScratch returns a new reflect.Value matching the map's value type,
-// and a structPointer suitable for passing to an encoder or sizer.
-func mapEncodeScratch(mapType reflect.Type) (keycopy, valcopy reflect.Value, keybase, valbase structPointer) {
-	// Prepare addressable doubly-indirect placeholders for the key and value types.
-	// This is needed because the element-type encoders expect **T, but the map iteration produces T.
-
-	keycopy = reflect.New(mapType.Key()).Elem()                 // addressable K
-	keyptr := reflect.New(reflect.PtrTo(keycopy.Type())).Elem() // addressable *K
-	keyptr.Set(keycopy.Addr())                                  //
-	keybase = toStructPointer(keyptr.Addr())                    // **K
-
-	// Value types are more varied and require special handling.
-	switch mapType.Elem().Kind() {
-	case reflect.Slice:
-		// []byte
-		var dummy []byte
-		valcopy = reflect.ValueOf(&dummy).Elem() // addressable []byte
-		valbase = toStructPointer(valcopy.Addr())
-	case reflect.Ptr:
-		// message; the generated field type is map[K]*Msg (so V is *Msg),
-		// so we only need one level of indirection.
-		valcopy = reflect.New(mapType.Elem()).Elem() // addressable V
-		valbase = toStructPointer(valcopy.Addr())
-	default:
-		// everything else
-		valcopy = reflect.New(mapType.Elem()).Elem()                // addressable V
-		valptr := reflect.New(reflect.PtrTo(valcopy.Type())).Elem() // addressable *V
-		valptr.Set(valcopy.Addr())                                  //
-		valbase = toStructPointer(valptr.Addr())                    // **V
-	}
-	return
-}
-
-// Encode a struct.
-func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error {
-	var state errorState
-	// Encode fields in tag order so that decoders may use optimizations
-	// that depend on the ordering.
-	// https://developers.google.com/protocol-buffers/docs/encoding#order
-	for _, i := range prop.order {
-		p := prop.Prop[i]
-		if p.enc != nil {
-			err := p.enc(o, p, base)
-			if err != nil {
-				if err == ErrNil {
-					if p.Required && state.err == nil {
-						state.err = &RequiredNotSetError{p.Name}
-					}
-				} else if err == errRepeatedHasNil {
-					// Give more context to nil values in repeated fields.
-					return errors.New("repeated field " + p.OrigName + " has nil element")
-				} else if !state.shouldContinue(err, p) {
-					return err
-				}
-			}
-			if len(o.buf) > maxMarshalSize {
-				return ErrTooLarge
-			}
-		}
-	}
-
-	// Do oneof fields.
-	if prop.oneofMarshaler != nil {
-		m := structPointer_Interface(base, prop.stype).(Message)
-		if err := prop.oneofMarshaler(m, o); err == ErrNil {
-			return errOneofHasNil
-		} else if err != nil {
-			return err
-		}
-	}
-
-	// Add unrecognized fields at the end.
-	if prop.unrecField.IsValid() {
-		v := *structPointer_Bytes(base, prop.unrecField)
-		if len(o.buf)+len(v) > maxMarshalSize {
-			return ErrTooLarge
-		}
-		if len(v) > 0 {
-			o.buf = append(o.buf, v...)
-		}
-	}
-
-	return state.err
-}
-
-func size_struct(prop *StructProperties, base structPointer) (n int) {
-	for _, i := range prop.order {
-		p := prop.Prop[i]
-		if p.size != nil {
-			n += p.size(p, base)
-		}
-	}
-
-	// Add unrecognized fields at the end.
-	if prop.unrecField.IsValid() {
-		v := *structPointer_Bytes(base, prop.unrecField)
-		n += len(v)
-	}
-
-	// Factor in any oneof fields.
-	if prop.oneofSizer != nil {
-		m := structPointer_Interface(base, prop.stype).(Message)
-		n += prop.oneofSizer(m)
-	}
-
-	return
-}
-
-var zeroes [20]byte // longer than any conceivable sizeVarint
-
-// Encode a struct, preceded by its encoded length (as a varint).
-func (o *Buffer) enc_len_struct(prop *StructProperties, base structPointer, state *errorState) error {
-	return o.enc_len_thing(func() error { return o.enc_struct(prop, base) }, state)
-}
-
-// Encode something, preceded by its encoded length (as a varint).
-func (o *Buffer) enc_len_thing(enc func() error, state *errorState) error {
-	iLen := len(o.buf)
-	o.buf = append(o.buf, 0, 0, 0, 0) // reserve four bytes for length
-	iMsg := len(o.buf)
-	err := enc()
-	if err != nil && !state.shouldContinue(err, nil) {
-		return err
-	}
-	lMsg := len(o.buf) - iMsg
-	lLen := sizeVarint(uint64(lMsg))
-	switch x := lLen - (iMsg - iLen); {
-	case x > 0: // actual length is x bytes larger than the space we reserved
-		// Move msg x bytes right.
-		o.buf = append(o.buf, zeroes[:x]...)
-		copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg])
-	case x < 0: // actual length is x bytes smaller than the space we reserved
-		// Move msg x bytes left.
-		copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg])
-		o.buf = o.buf[:len(o.buf)+x] // x is negative
-	}
-	// Encode the length in the reserved space.
-	o.buf = o.buf[:iLen]
-	o.EncodeVarint(uint64(lMsg))
-	o.buf = o.buf[:len(o.buf)+lMsg]
-	return state.err
-}
-
-// errorState maintains the first error that occurs and updates that error
-// with additional context.
-type errorState struct {
-	err error
-}
-
-// shouldContinue reports whether encoding should continue upon encountering the
-// given error. If the error is RequiredNotSetError, shouldContinue returns true
-// and, if this is the first appearance of that error, remembers it for future
-// reporting.
-//
-// If prop is not nil, it may update any error with additional context about the
-// field with the error.
-func (s *errorState) shouldContinue(err error, prop *Properties) bool {
-	// Ignore unset required fields.
-	reqNotSet, ok := err.(*RequiredNotSetError)
-	if !ok {
-		return false
-	}
-	if s.err == nil {
-		if prop != nil {
-			err = &RequiredNotSetError{prop.Name + "." + reqNotSet.field}
-		}
-		s.err = err
-	}
-	return true
-}

+ 17 - 16
vendor/github.com/golang/protobuf/proto/equal.go

@@ -109,15 +109,6 @@ func equalStruct(v1, v2 reflect.Value) bool {
 				// set/unset mismatch
 				return false
 			}
-			b1, ok := f1.Interface().(raw)
-			if ok {
-				b2 := f2.Interface().(raw)
-				// RawMessage
-				if !bytes.Equal(b1.Bytes(), b2.Bytes()) {
-					return false
-				}
-				continue
-			}
 			f1, f2 = f1.Elem(), f2.Elem()
 		}
 		if !equalAny(f1, f2, sprop.Prop[i]) {
@@ -146,11 +137,7 @@ func equalStruct(v1, v2 reflect.Value) bool {
 
 	u1 := uf.Bytes()
 	u2 := v2.FieldByName("XXX_unrecognized").Bytes()
-	if !bytes.Equal(u1, u2) {
-		return false
-	}
-
-	return true
+	return bytes.Equal(u1, u2)
 }
 
 // v1 and v2 are known to have the same type.
@@ -259,7 +246,17 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
 			return false
 		}
 
-		m1, m2 := e1.value, e2.value
+		m1 := extensionAsLegacyType(e1.value)
+		m2 := extensionAsLegacyType(e2.value)
+
+		if m1 == nil && m2 == nil {
+			// Both have only encoded form.
+			if bytes.Equal(e1.enc, e2.enc) {
+				continue
+			}
+			// The bytes are different, but the extensions might still be
+			// equal. We need to decode them to compare.
+		}
 
 		if m1 != nil && m2 != nil {
 			// Both are unencoded.
@@ -276,8 +273,12 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
 			desc = m[extNum]
 		}
 		if desc == nil {
+			// If both have only encoded form and the bytes are the same,
+			// it is handled above. We get here when the bytes are different.
+			// We don't know how to decode it, so just compare them as byte
+			// slices.
 			log.Printf("proto: don't know how to compare extension %d of %v", extNum, base)
-			continue
+			return false
 		}
 		var err error
 		if m1 == nil {

+ 151 - 131
vendor/github.com/golang/protobuf/proto/extensions.go

@@ -38,6 +38,7 @@ package proto
 import (
 	"errors"
 	"fmt"
+	"io"
 	"reflect"
 	"strconv"
 	"sync"
@@ -91,14 +92,29 @@ func (n notLocker) Unlock() {}
 // extendable returns the extendableProto interface for the given generated proto message.
 // If the proto message has the old extension format, it returns a wrapper that implements
 // the extendableProto interface.
-func extendable(p interface{}) (extendableProto, bool) {
-	if ep, ok := p.(extendableProto); ok {
-		return ep, ok
-	}
-	if ep, ok := p.(extendableProtoV1); ok {
-		return extensionAdapter{ep}, ok
+func extendable(p interface{}) (extendableProto, error) {
+	switch p := p.(type) {
+	case extendableProto:
+		if isNilPtr(p) {
+			return nil, fmt.Errorf("proto: nil %T is not extendable", p)
+		}
+		return p, nil
+	case extendableProtoV1:
+		if isNilPtr(p) {
+			return nil, fmt.Errorf("proto: nil %T is not extendable", p)
+		}
+		return extensionAdapter{p}, nil
 	}
-	return nil, false
+	// Don't allocate a specific error containing %T:
+	// this is the hot path for Clone and MarshalText.
+	return nil, errNotExtendable
+}
+
+var errNotExtendable = errors.New("proto: not an extendable proto.Message")
+
+func isNilPtr(x interface{}) bool {
+	v := reflect.ValueOf(x)
+	return v.Kind() == reflect.Ptr && v.IsNil()
 }
 
 // XXX_InternalExtensions is an internal representation of proto extensions.
@@ -143,9 +159,6 @@ func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Loc
 	return e.p.extensionMap, &e.p.mu
 }
 
-var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem()
-var extendableProtoV1Type = reflect.TypeOf((*extendableProtoV1)(nil)).Elem()
-
 // ExtensionDesc represents an extension specification.
 // Used in generated code from the protocol compiler.
 type ExtensionDesc struct {
@@ -172,15 +185,31 @@ type Extension struct {
 	// extension will have only enc set. When such an extension is
 	// accessed using GetExtension (or GetExtensions) desc and value
 	// will be set.
-	desc  *ExtensionDesc
+	desc *ExtensionDesc
+
+	// value is a concrete value for the extension field. Let the type of
+	// desc.ExtensionType be the "API type" and the type of Extension.value
+	// be the "storage type". The API type and storage type are the same except:
+	//	* For scalars (except []byte), the API type uses *T,
+	//	while the storage type uses T.
+	//	* For repeated fields, the API type uses []T, while the storage type
+	//	uses *[]T.
+	//
+	// The reason for the divergence is so that the storage type more naturally
+	// matches what is expected of when retrieving the values through the
+	// protobuf reflection APIs.
+	//
+	// The value may only be populated if desc is also populated.
 	value interface{}
-	enc   []byte
+
+	// enc is the raw bytes for the extension field.
+	enc []byte
 }
 
 // SetRawExtension is for testing only.
 func SetRawExtension(base Message, id int32, b []byte) {
-	epb, ok := extendable(base)
-	if !ok {
+	epb, err := extendable(base)
+	if err != nil {
 		return
 	}
 	extmap := epb.extensionsWrite()
@@ -205,7 +234,7 @@ func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error {
 		pbi = ea.extendableProtoV1
 	}
 	if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b {
-		return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String())
+		return fmt.Errorf("proto: bad extended type; %v does not extend %v", b, a)
 	}
 	// Check the range.
 	if !isExtensionField(pb, extension.Field) {
@@ -250,85 +279,11 @@ func extensionProperties(ed *ExtensionDesc) *Properties {
 	return prop
 }
 
-// encode encodes any unmarshaled (unencoded) extensions in e.
-func encodeExtensions(e *XXX_InternalExtensions) error {
-	m, mu := e.extensionsRead()
-	if m == nil {
-		return nil // fast path
-	}
-	mu.Lock()
-	defer mu.Unlock()
-	return encodeExtensionsMap(m)
-}
-
-// encode encodes any unmarshaled (unencoded) extensions in e.
-func encodeExtensionsMap(m map[int32]Extension) error {
-	for k, e := range m {
-		if e.value == nil || e.desc == nil {
-			// Extension is only in its encoded form.
-			continue
-		}
-
-		// We don't skip extensions that have an encoded form set,
-		// because the extension value may have been mutated after
-		// the last time this function was called.
-
-		et := reflect.TypeOf(e.desc.ExtensionType)
-		props := extensionProperties(e.desc)
-
-		p := NewBuffer(nil)
-		// If e.value has type T, the encoder expects a *struct{ X T }.
-		// Pass a *T with a zero field and hope it all works out.
-		x := reflect.New(et)
-		x.Elem().Set(reflect.ValueOf(e.value))
-		if err := props.enc(p, props, toStructPointer(x)); err != nil {
-			return err
-		}
-		e.enc = p.buf
-		m[k] = e
-	}
-	return nil
-}
-
-func extensionsSize(e *XXX_InternalExtensions) (n int) {
-	m, mu := e.extensionsRead()
-	if m == nil {
-		return 0
-	}
-	mu.Lock()
-	defer mu.Unlock()
-	return extensionsMapSize(m)
-}
-
-func extensionsMapSize(m map[int32]Extension) (n int) {
-	for _, e := range m {
-		if e.value == nil || e.desc == nil {
-			// Extension is only in its encoded form.
-			n += len(e.enc)
-			continue
-		}
-
-		// We don't skip extensions that have an encoded form set,
-		// because the extension value may have been mutated after
-		// the last time this function was called.
-
-		et := reflect.TypeOf(e.desc.ExtensionType)
-		props := extensionProperties(e.desc)
-
-		// If e.value has type T, the encoder expects a *struct{ X T }.
-		// Pass a *T with a zero field and hope it all works out.
-		x := reflect.New(et)
-		x.Elem().Set(reflect.ValueOf(e.value))
-		n += props.size(props, toStructPointer(x))
-	}
-	return
-}
-
 // HasExtension returns whether the given extension is present in pb.
 func HasExtension(pb Message, extension *ExtensionDesc) bool {
 	// TODO: Check types, field numbers, etc.?
-	epb, ok := extendable(pb)
-	if !ok {
+	epb, err := extendable(pb)
+	if err != nil {
 		return false
 	}
 	extmap, mu := epb.extensionsRead()
@@ -336,15 +291,15 @@ func HasExtension(pb Message, extension *ExtensionDesc) bool {
 		return false
 	}
 	mu.Lock()
-	_, ok = extmap[extension.Field]
+	_, ok := extmap[extension.Field]
 	mu.Unlock()
 	return ok
 }
 
 // ClearExtension removes the given extension from pb.
 func ClearExtension(pb Message, extension *ExtensionDesc) {
-	epb, ok := extendable(pb)
-	if !ok {
+	epb, err := extendable(pb)
+	if err != nil {
 		return
 	}
 	// TODO: Check types, field numbers, etc.?
@@ -352,16 +307,26 @@ func ClearExtension(pb Message, extension *ExtensionDesc) {
 	delete(extmap, extension.Field)
 }
 
-// GetExtension parses and returns the given extension of pb.
-// If the extension is not present and has no default value it returns ErrMissingExtension.
+// GetExtension retrieves a proto2 extended field from pb.
+//
+// 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 not type complete (i.e., ExtensionDesc.ExtensionType is nil),
+// then GetExtension returns the raw encoded bytes of the field extension.
 func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
-	epb, ok := extendable(pb)
-	if !ok {
-		return nil, errors.New("proto: not an extendable proto")
+	epb, err := extendable(pb)
+	if err != nil {
+		return nil, err
 	}
 
-	if err := checkExtensionTypes(epb, extension); err != nil {
-		return nil, err
+	if extension.ExtendedType != nil {
+		// can only check type if this is a complete descriptor
+		if err := checkExtensionTypes(epb, extension); err != nil {
+			return nil, err
+		}
 	}
 
 	emap, mu := epb.extensionsRead()
@@ -385,7 +350,12 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
 			// descriptors with the same field number.
 			return nil, errors.New("proto: descriptor conflict")
 		}
-		return e.value, nil
+		return extensionAsLegacyType(e.value), nil
+	}
+
+	if extension.ExtensionType == nil {
+		// incomplete descriptor
+		return e.enc, nil
 	}
 
 	v, err := decodeExtension(e.enc, extension)
@@ -395,16 +365,21 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
 
 	// Remember the decoded version and drop the encoded version.
 	// That way it is safe to mutate what we return.
-	e.value = v
+	e.value = extensionAsStorageType(v)
 	e.desc = extension
 	e.enc = nil
 	emap[extension.Field] = e
-	return e.value, nil
+	return extensionAsLegacyType(e.value), nil
 }
 
 // defaultExtensionValue returns the default value for extension.
 // If no default for an extension is defined ErrMissingExtension is returned.
 func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
+	if extension.ExtensionType == nil {
+		// incomplete descriptor, so no default
+		return nil, ErrMissingExtension
+	}
+
 	t := reflect.TypeOf(extension.ExtensionType)
 	props := extensionProperties(extension)
 
@@ -439,31 +414,28 @@ func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
 
 // decodeExtension decodes an extension encoded in b.
 func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
-	o := NewBuffer(b)
-
 	t := reflect.TypeOf(extension.ExtensionType)
-
-	props := extensionProperties(extension)
+	unmarshal := typeUnmarshaler(t, extension.Tag)
 
 	// t is a pointer to a struct, pointer to basic type or a slice.
-	// Allocate a "field" to store the pointer/slice itself; the
-	// pointer/slice will be stored here. We pass
-	// the address of this field to props.dec.
-	// This passes a zero field and a *t and lets props.dec
-	// interpret it as a *struct{ x t }.
+	// Allocate space to store the pointer/slice.
 	value := reflect.New(t).Elem()
 
+	var err error
 	for {
-		// Discard wire type and field number varint. It isn't needed.
-		if _, err := o.DecodeVarint(); err != nil {
-			return nil, err
+		x, n := decodeVarint(b)
+		if n == 0 {
+			return nil, io.ErrUnexpectedEOF
 		}
+		b = b[n:]
+		wire := int(x) & 7
 
-		if err := props.dec(o, props, toStructPointer(value.Addr())); err != nil {
+		b, err = unmarshal(b, valToPointer(value.Addr()), wire)
+		if err != nil {
 			return nil, err
 		}
 
-		if o.index >= len(o.buf) {
+		if len(b) == 0 {
 			break
 		}
 	}
@@ -473,9 +445,9 @@ func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
 // GetExtensions returns a slice of the extensions present in pb that are also listed in es.
 // The returned slice has the same length as es; missing extensions will appear as nil elements.
 func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) {
-	epb, ok := extendable(pb)
-	if !ok {
-		return nil, errors.New("proto: not an extendable proto")
+	epb, err := extendable(pb)
+	if err != nil {
+		return nil, err
 	}
 	extensions = make([]interface{}, len(es))
 	for i, e := range es {
@@ -494,9 +466,9 @@ func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, e
 // For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing
 // just the Field field, which defines the extension's field number.
 func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
-	epb, ok := extendable(pb)
-	if !ok {
-		return nil, fmt.Errorf("proto: %T is not an extendable proto.Message", pb)
+	epb, err := extendable(pb)
+	if err != nil {
+		return nil, err
 	}
 	registeredExtensions := RegisteredExtensions(pb)
 
@@ -523,16 +495,16 @@ func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
 
 // SetExtension sets the specified extension of pb to the specified value.
 func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error {
-	epb, ok := extendable(pb)
-	if !ok {
-		return errors.New("proto: not an extendable proto")
+	epb, err := extendable(pb)
+	if err != nil {
+		return err
 	}
 	if err := checkExtensionTypes(epb, extension); err != nil {
 		return err
 	}
 	typ := reflect.TypeOf(extension.ExtensionType)
 	if typ != reflect.TypeOf(value) {
-		return errors.New("proto: bad extension value type")
+		return fmt.Errorf("proto: bad extension value type. got: %T, want: %T", value, extension.ExtensionType)
 	}
 	// nil extension values need to be caught early, because the
 	// encoder can't distinguish an ErrNil due to a nil extension
@@ -544,14 +516,14 @@ func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error
 	}
 
 	extmap := epb.extensionsWrite()
-	extmap[extension.Field] = Extension{desc: extension, value: value}
+	extmap[extension.Field] = Extension{desc: extension, value: extensionAsStorageType(value)}
 	return nil
 }
 
 // ClearAllExtensions clears all extensions from pb.
 func ClearAllExtensions(pb Message) {
-	epb, ok := extendable(pb)
-	if !ok {
+	epb, err := extendable(pb)
+	if err != nil {
 		return
 	}
 	m := epb.extensionsWrite()
@@ -585,3 +557,51 @@ func RegisterExtension(desc *ExtensionDesc) {
 func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc {
 	return extensionMaps[reflect.TypeOf(pb).Elem()]
 }
+
+// extensionAsLegacyType converts an value in the storage type as the API type.
+// See Extension.value.
+func extensionAsLegacyType(v interface{}) interface{} {
+	switch rv := reflect.ValueOf(v); rv.Kind() {
+	case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
+		// Represent primitive types as a pointer to the value.
+		rv2 := reflect.New(rv.Type())
+		rv2.Elem().Set(rv)
+		v = rv2.Interface()
+	case reflect.Ptr:
+		// Represent slice types as the value itself.
+		switch rv.Type().Elem().Kind() {
+		case reflect.Slice:
+			if rv.IsNil() {
+				v = reflect.Zero(rv.Type().Elem()).Interface()
+			} else {
+				v = rv.Elem().Interface()
+			}
+		}
+	}
+	return v
+}
+
+// extensionAsStorageType converts an value in the API type as the storage type.
+// See Extension.value.
+func extensionAsStorageType(v interface{}) interface{} {
+	switch rv := reflect.ValueOf(v); rv.Kind() {
+	case reflect.Ptr:
+		// Represent slice types as the value itself.
+		switch rv.Type().Elem().Kind() {
+		case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
+			if rv.IsNil() {
+				v = reflect.Zero(rv.Type().Elem()).Interface()
+			} else {
+				v = rv.Elem().Interface()
+			}
+		}
+	case reflect.Slice:
+		// Represent slice types as a pointer to the value.
+		if rv.Type().Elem().Kind() != reflect.Uint8 {
+			rv2 := reflect.New(rv.Type())
+			rv2.Elem().Set(rv)
+			v = rv2.Interface()
+		}
+	}
+	return v
+}

+ 117 - 49
vendor/github.com/golang/protobuf/proto/lib.go

@@ -273,32 +273,73 @@ import (
 	"sync"
 )
 
-// Message is implemented by generated protocol buffer messages.
-type Message interface {
-	Reset()
-	String() string
-	ProtoMessage()
+// RequiredNotSetError is an error type returned by either Marshal or Unmarshal.
+// Marshal reports this when a required field is not initialized.
+// Unmarshal reports this when a required field is missing from the wire data.
+type RequiredNotSetError struct{ field string }
+
+func (e *RequiredNotSetError) Error() string {
+	if e.field == "" {
+		return fmt.Sprintf("proto: required field not set")
+	}
+	return fmt.Sprintf("proto: required field %q not set", e.field)
+}
+func (e *RequiredNotSetError) RequiredNotSet() bool {
+	return true
 }
 
-// Stats records allocation details about the protocol buffer encoders
-// and decoders.  Useful for tuning the library itself.
-type Stats struct {
-	Emalloc uint64 // mallocs in encode
-	Dmalloc uint64 // mallocs in decode
-	Encode  uint64 // number of encodes
-	Decode  uint64 // number of decodes
-	Chit    uint64 // number of cache hits
-	Cmiss   uint64 // number of cache misses
-	Size    uint64 // number of sizes
+type invalidUTF8Error struct{ field string }
+
+func (e *invalidUTF8Error) Error() string {
+	if e.field == "" {
+		return "proto: invalid UTF-8 detected"
+	}
+	return fmt.Sprintf("proto: field %q contains invalid UTF-8", e.field)
+}
+func (e *invalidUTF8Error) InvalidUTF8() bool {
+	return true
 }
 
-// Set to true to enable stats collection.
-const collectStats = false
+// errInvalidUTF8 is a sentinel error to identify fields with invalid UTF-8.
+// This error should not be exposed to the external API as such errors should
+// be recreated with the field information.
+var errInvalidUTF8 = &invalidUTF8Error{}
 
-var stats Stats
+// isNonFatal reports whether the error is either a RequiredNotSet error
+// or a InvalidUTF8 error.
+func isNonFatal(err error) bool {
+	if re, ok := err.(interface{ RequiredNotSet() bool }); ok && re.RequiredNotSet() {
+		return true
+	}
+	if re, ok := err.(interface{ InvalidUTF8() bool }); ok && re.InvalidUTF8() {
+		return true
+	}
+	return false
+}
 
-// GetStats returns a copy of the global Stats structure.
-func GetStats() Stats { return stats }
+type nonFatal struct{ E error }
+
+// Merge merges err into nf and reports whether it was successful.
+// Otherwise it returns false for any fatal non-nil errors.
+func (nf *nonFatal) Merge(err error) (ok bool) {
+	if err == nil {
+		return true // not an error
+	}
+	if !isNonFatal(err) {
+		return false // fatal error
+	}
+	if nf.E == nil {
+		nf.E = err // store first instance of non-fatal error
+	}
+	return true
+}
+
+// Message is implemented by generated protocol buffer messages.
+type Message interface {
+	Reset()
+	String() string
+	ProtoMessage()
+}
 
 // A Buffer is a buffer manager for marshaling and unmarshaling
 // protocol buffers.  It may be reused between invocations to
@@ -309,16 +350,7 @@ type Buffer struct {
 	buf   []byte // encode/decode byte stream
 	index int    // read point
 
-	// pools of basic types to amortize allocation.
-	bools   []bool
-	uint32s []uint32
-	uint64s []uint64
-
-	// extra pools, only used with pointer_reflect.go
-	int32s   []int32
-	int64s   []int64
-	float32s []float32
-	float64s []float64
+	deterministic bool
 }
 
 // NewBuffer allocates a new Buffer and initializes its internal data to
@@ -343,6 +375,30 @@ func (p *Buffer) SetBuf(s []byte) {
 // Bytes returns the contents of the Buffer.
 func (p *Buffer) Bytes() []byte { return p.buf }
 
+// SetDeterministic sets 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 (p *Buffer) SetDeterministic(deterministic bool) {
+	p.deterministic = deterministic
+}
+
 /*
  * Helper routines for simplifying the creation of optional fields of basic type.
  */
@@ -831,22 +887,12 @@ func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMes
 	return sf, false, nil
 }
 
+// mapKeys returns a sort.Interface to be used for sorting the map keys.
 // Map fields may have key types of non-float scalars, strings and enums.
-// The easiest way to sort them in some deterministic order is to use fmt.
-// If this turns out to be inefficient we can always consider other options,
-// such as doing a Schwartzian transform.
-
 func mapKeys(vs []reflect.Value) sort.Interface {
-	s := mapKeySorter{
-		vs: vs,
-		// default Less function: textual comparison
-		less: func(a, b reflect.Value) bool {
-			return fmt.Sprint(a.Interface()) < fmt.Sprint(b.Interface())
-		},
-	}
+	s := mapKeySorter{vs: vs}
 
-	// Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps;
-	// numeric keys are sorted numerically.
+	// Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps.
 	if len(vs) == 0 {
 		return s
 	}
@@ -855,6 +901,12 @@ func mapKeys(vs []reflect.Value) sort.Interface {
 		s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() }
 	case reflect.Uint32, reflect.Uint64:
 		s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() }
+	case reflect.Bool:
+		s.less = func(a, b reflect.Value) bool { return !a.Bool() && b.Bool() } // false < true
+	case reflect.String:
+		s.less = func(a, b reflect.Value) bool { return a.String() < b.String() }
+	default:
+		panic(fmt.Sprintf("unsupported map key type: %v", vs[0].Kind()))
 	}
 
 	return s
@@ -888,10 +940,26 @@ func isProto3Zero(v reflect.Value) bool {
 	return false
 }
 
-// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
-// to assert that that code is compatible with this version of the proto package.
-const ProtoPackageIsVersion2 = true
+const (
+	// ProtoPackageIsVersion3 is referenced from generated protocol buffer files
+	// to assert that that code is compatible with this version of the proto package.
+	ProtoPackageIsVersion3 = true
+
+	// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
+	// to assert that that code is compatible with this version of the proto package.
+	ProtoPackageIsVersion2 = true
 
-// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
-// to assert that that code is compatible with this version of the proto package.
-const ProtoPackageIsVersion1 = true
+	// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
+	// to assert that that code is compatible with this version of the proto package.
+	ProtoPackageIsVersion1 = true
+)
+
+// InternalMessageInfo is a type used internally by generated .pb.go files.
+// This type is not intended to be used by non-generated code.
+// This type is not subject to any compatibility guarantee.
+type InternalMessageInfo struct {
+	marshal   *marshalInfo
+	unmarshal *unmarshalInfo
+	merge     *mergeInfo
+	discard   *discardInfo
+}

+ 4 - 134
vendor/github.com/golang/protobuf/proto/message_set.go

@@ -36,12 +36,7 @@ package proto
  */
 
 import (
-	"bytes"
-	"encoding/json"
 	"errors"
-	"fmt"
-	"reflect"
-	"sort"
 )
 
 // errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
@@ -94,10 +89,7 @@ func (ms *messageSet) find(pb Message) *_MessageSet_Item {
 }
 
 func (ms *messageSet) Has(pb Message) bool {
-	if ms.find(pb) != nil {
-		return true
-	}
-	return false
+	return ms.find(pb) != nil
 }
 
 func (ms *messageSet) Unmarshal(pb Message) error {
@@ -147,50 +139,9 @@ func skipVarint(buf []byte) []byte {
 	return buf[i+1:]
 }
 
-// MarshalMessageSet encodes the extension map represented by m in the message set wire format.
-// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option.
-func MarshalMessageSet(exts interface{}) ([]byte, error) {
-	var m map[int32]Extension
-	switch exts := exts.(type) {
-	case *XXX_InternalExtensions:
-		if err := encodeExtensions(exts); err != nil {
-			return nil, err
-		}
-		m, _ = exts.extensionsRead()
-	case map[int32]Extension:
-		if err := encodeExtensionsMap(exts); err != nil {
-			return nil, err
-		}
-		m = exts
-	default:
-		return nil, errors.New("proto: not an extension map")
-	}
-
-	// Sort extension IDs to provide a deterministic encoding.
-	// See also enc_map in encode.go.
-	ids := make([]int, 0, len(m))
-	for id := range m {
-		ids = append(ids, int(id))
-	}
-	sort.Ints(ids)
-
-	ms := &messageSet{Item: make([]*_MessageSet_Item, 0, len(m))}
-	for _, id := range ids {
-		e := m[int32(id)]
-		// Remove the wire type and field number varint, as well as the length varint.
-		msg := skipVarint(skipVarint(e.enc))
-
-		ms.Item = append(ms.Item, &_MessageSet_Item{
-			TypeId:  Int32(int32(id)),
-			Message: msg,
-		})
-	}
-	return Marshal(ms)
-}
-
-// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
-// It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
-func UnmarshalMessageSet(buf []byte, exts interface{}) error {
+// unmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
+// It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
+func unmarshalMessageSet(buf []byte, exts interface{}) error {
 	var m map[int32]Extension
 	switch exts := exts.(type) {
 	case *XXX_InternalExtensions:
@@ -228,84 +179,3 @@ func UnmarshalMessageSet(buf []byte, exts interface{}) error {
 	}
 	return nil
 }
-
-// MarshalMessageSetJSON encodes the extension map represented by m in JSON format.
-// It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
-func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
-	var m map[int32]Extension
-	switch exts := exts.(type) {
-	case *XXX_InternalExtensions:
-		m, _ = exts.extensionsRead()
-	case map[int32]Extension:
-		m = exts
-	default:
-		return nil, errors.New("proto: not an extension map")
-	}
-	var b bytes.Buffer
-	b.WriteByte('{')
-
-	// Process the map in key order for deterministic output.
-	ids := make([]int32, 0, len(m))
-	for id := range m {
-		ids = append(ids, id)
-	}
-	sort.Sort(int32Slice(ids)) // int32Slice defined in text.go
-
-	for i, id := range ids {
-		ext := m[id]
-		if i > 0 {
-			b.WriteByte(',')
-		}
-
-		msd, ok := messageSetMap[id]
-		if !ok {
-			// Unknown type; we can't render it, so skip it.
-			continue
-		}
-		fmt.Fprintf(&b, `"[%s]":`, msd.name)
-
-		x := ext.value
-		if x == nil {
-			x = reflect.New(msd.t.Elem()).Interface()
-			if err := Unmarshal(ext.enc, x.(Message)); err != nil {
-				return nil, err
-			}
-		}
-		d, err := json.Marshal(x)
-		if err != nil {
-			return nil, err
-		}
-		b.Write(d)
-	}
-	b.WriteByte('}')
-	return b.Bytes(), nil
-}
-
-// UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format.
-// It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
-func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error {
-	// Common-case fast path.
-	if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) {
-		return nil
-	}
-
-	// This is fairly tricky, and it's not clear that it is needed.
-	return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented")
-}
-
-// A global registry of types that can be used in a MessageSet.
-
-var messageSetMap = make(map[int32]messageSetDesc)
-
-type messageSetDesc struct {
-	t    reflect.Type // pointer to struct
-	name string
-}
-
-// RegisterMessageSetType is called from the generated code.
-func RegisterMessageSetType(m Message, fieldNum int32, name string) {
-	messageSetMap[fieldNum] = messageSetDesc{
-		t:    reflect.TypeOf(m),
-		name: name,
-	}
-}

+ 237 - 361
vendor/github.com/golang/protobuf/proto/pointer_reflect.go

@@ -29,7 +29,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// +build appengine js
+// +build purego appengine js
 
 // This file contains an implementation of proto field accesses using package reflect.
 // It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can
@@ -38,32 +38,13 @@
 package proto
 
 import (
-	"math"
 	"reflect"
+	"sync"
 )
 
-// A structPointer is a pointer to a struct.
-type structPointer struct {
-	v reflect.Value
-}
-
-// toStructPointer returns a structPointer equivalent to the given reflect value.
-// The reflect value must itself be a pointer to a struct.
-func toStructPointer(v reflect.Value) structPointer {
-	return structPointer{v}
-}
-
-// IsNil reports whether p is nil.
-func structPointer_IsNil(p structPointer) bool {
-	return p.v.IsNil()
-}
+const unsafeAllowed = false
 
-// Interface returns the struct pointer as an interface value.
-func structPointer_Interface(p structPointer, _ reflect.Type) interface{} {
-	return p.v.Interface()
-}
-
-// A field identifies a field in a struct, accessible from a structPointer.
+// A field identifies a field in a struct, accessible from a pointer.
 // In this implementation, a field is identified by the sequence of field indices
 // passed to reflect's FieldByIndex.
 type field []int
@@ -76,409 +57,304 @@ func toField(f *reflect.StructField) field {
 // invalidField is an invalid field identifier.
 var invalidField = field(nil)
 
+// zeroField is a noop when calling pointer.offset.
+var zeroField = field([]int{})
+
 // IsValid reports whether the field identifier is valid.
 func (f field) IsValid() bool { return f != nil }
 
-// field returns the given field in the struct as a reflect value.
-func structPointer_field(p structPointer, f field) reflect.Value {
-	// Special case: an extension map entry with a value of type T
-	// passes a *T to the struct-handling code with a zero field,
-	// expecting that it will be treated as equivalent to *struct{ X T },
-	// which has the same memory layout. We have to handle that case
-	// specially, because reflect will panic if we call FieldByIndex on a
-	// non-struct.
-	if f == nil {
-		return p.v.Elem()
-	}
-
-	return p.v.Elem().FieldByIndex(f)
+// The pointer type is for the table-driven decoder.
+// The implementation here uses a reflect.Value of pointer type to
+// create a generic pointer. In pointer_unsafe.go we use unsafe
+// instead of reflect to implement the same (but faster) interface.
+type pointer struct {
+	v reflect.Value
 }
 
-// ifield returns the given field in the struct as an interface value.
-func structPointer_ifield(p structPointer, f field) interface{} {
-	return structPointer_field(p, f).Addr().Interface()
+// toPointer converts an interface of pointer type to a pointer
+// that points to the same target.
+func toPointer(i *Message) pointer {
+	return pointer{v: reflect.ValueOf(*i)}
 }
 
-// Bytes returns the address of a []byte field in the struct.
-func structPointer_Bytes(p structPointer, f field) *[]byte {
-	return structPointer_ifield(p, f).(*[]byte)
+// toAddrPointer converts an interface to a pointer that points to
+// the interface data.
+func toAddrPointer(i *interface{}, isptr, deref bool) pointer {
+	v := reflect.ValueOf(*i)
+	u := reflect.New(v.Type())
+	u.Elem().Set(v)
+	if deref {
+		u = u.Elem()
+	}
+	return pointer{v: u}
 }
 
-// BytesSlice returns the address of a [][]byte field in the struct.
-func structPointer_BytesSlice(p structPointer, f field) *[][]byte {
-	return structPointer_ifield(p, f).(*[][]byte)
+// valToPointer converts v to a pointer.  v must be of pointer type.
+func valToPointer(v reflect.Value) pointer {
+	return pointer{v: v}
 }
 
-// Bool returns the address of a *bool field in the struct.
-func structPointer_Bool(p structPointer, f field) **bool {
-	return structPointer_ifield(p, f).(**bool)
+// offset converts from a pointer to a structure to a pointer to
+// one of its fields.
+func (p pointer) offset(f field) pointer {
+	return pointer{v: p.v.Elem().FieldByIndex(f).Addr()}
 }
 
-// BoolVal returns the address of a bool field in the struct.
-func structPointer_BoolVal(p structPointer, f field) *bool {
-	return structPointer_ifield(p, f).(*bool)
+func (p pointer) isNil() bool {
+	return p.v.IsNil()
 }
 
-// BoolSlice returns the address of a []bool field in the struct.
-func structPointer_BoolSlice(p structPointer, f field) *[]bool {
-	return structPointer_ifield(p, f).(*[]bool)
+// grow updates the slice s in place to make it one element longer.
+// s must be addressable.
+// Returns the (addressable) new element.
+func grow(s reflect.Value) reflect.Value {
+	n, m := s.Len(), s.Cap()
+	if n < m {
+		s.SetLen(n + 1)
+	} else {
+		s.Set(reflect.Append(s, reflect.Zero(s.Type().Elem())))
+	}
+	return s.Index(n)
 }
 
-// String returns the address of a *string field in the struct.
-func structPointer_String(p structPointer, f field) **string {
-	return structPointer_ifield(p, f).(**string)
+func (p pointer) toInt64() *int64 {
+	return p.v.Interface().(*int64)
 }
-
-// StringVal returns the address of a string field in the struct.
-func structPointer_StringVal(p structPointer, f field) *string {
-	return structPointer_ifield(p, f).(*string)
+func (p pointer) toInt64Ptr() **int64 {
+	return p.v.Interface().(**int64)
 }
-
-// StringSlice returns the address of a []string field in the struct.
-func structPointer_StringSlice(p structPointer, f field) *[]string {
-	return structPointer_ifield(p, f).(*[]string)
+func (p pointer) toInt64Slice() *[]int64 {
+	return p.v.Interface().(*[]int64)
 }
 
-// Extensions returns the address of an extension map field in the struct.
-func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
-	return structPointer_ifield(p, f).(*XXX_InternalExtensions)
-}
+var int32ptr = reflect.TypeOf((*int32)(nil))
 
-// ExtMap returns the address of an extension map field in the struct.
-func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
-	return structPointer_ifield(p, f).(*map[int32]Extension)
+func (p pointer) toInt32() *int32 {
+	return p.v.Convert(int32ptr).Interface().(*int32)
 }
 
-// NewAt returns the reflect.Value for a pointer to a field in the struct.
-func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
-	return structPointer_field(p, f).Addr()
+// The toInt32Ptr/Slice methods don't work because of enums.
+// Instead, we must use set/get methods for the int32ptr/slice case.
+/*
+	func (p pointer) toInt32Ptr() **int32 {
+		return p.v.Interface().(**int32)
 }
-
-// SetStructPointer writes a *struct field in the struct.
-func structPointer_SetStructPointer(p structPointer, f field, q structPointer) {
-	structPointer_field(p, f).Set(q.v)
+	func (p pointer) toInt32Slice() *[]int32 {
+		return p.v.Interface().(*[]int32)
 }
-
-// GetStructPointer reads a *struct field in the struct.
-func structPointer_GetStructPointer(p structPointer, f field) structPointer {
-	return structPointer{structPointer_field(p, f)}
+*/
+func (p pointer) getInt32Ptr() *int32 {
+	if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
+		// raw int32 type
+		return p.v.Elem().Interface().(*int32)
+	}
+	// an enum
+	return p.v.Elem().Convert(int32PtrType).Interface().(*int32)
+}
+func (p pointer) setInt32Ptr(v int32) {
+	// Allocate value in a *int32. Possibly convert that to a *enum.
+	// Then assign it to a **int32 or **enum.
+	// Note: we can convert *int32 to *enum, but we can't convert
+	// **int32 to **enum!
+	p.v.Elem().Set(reflect.ValueOf(&v).Convert(p.v.Type().Elem()))
+}
+
+// getInt32Slice copies []int32 from p as a new slice.
+// This behavior differs from the implementation in pointer_unsafe.go.
+func (p pointer) getInt32Slice() []int32 {
+	if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
+		// raw int32 type
+		return p.v.Elem().Interface().([]int32)
+	}
+	// an enum
+	// Allocate a []int32, then assign []enum's values into it.
+	// Note: we can't convert []enum to []int32.
+	slice := p.v.Elem()
+	s := make([]int32, slice.Len())
+	for i := 0; i < slice.Len(); i++ {
+		s[i] = int32(slice.Index(i).Int())
+	}
+	return s
 }
 
-// StructPointerSlice the address of a []*struct field in the struct.
-func structPointer_StructPointerSlice(p structPointer, f field) structPointerSlice {
-	return structPointerSlice{structPointer_field(p, f)}
+// setInt32Slice copies []int32 into p as a new slice.
+// This behavior differs from the implementation in pointer_unsafe.go.
+func (p pointer) setInt32Slice(v []int32) {
+	if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
+		// raw int32 type
+		p.v.Elem().Set(reflect.ValueOf(v))
+		return
+	}
+	// an enum
+	// Allocate a []enum, then assign []int32's values into it.
+	// Note: we can't convert []enum to []int32.
+	slice := reflect.MakeSlice(p.v.Type().Elem(), len(v), cap(v))
+	for i, x := range v {
+		slice.Index(i).SetInt(int64(x))
+	}
+	p.v.Elem().Set(slice)
 }
-
-// A structPointerSlice represents the address of a slice of pointers to structs
-// (themselves messages or groups). That is, v.Type() is *[]*struct{...}.
-type structPointerSlice struct {
-	v reflect.Value
+func (p pointer) appendInt32Slice(v int32) {
+	grow(p.v.Elem()).SetInt(int64(v))
 }
 
-func (p structPointerSlice) Len() int                  { return p.v.Len() }
-func (p structPointerSlice) Index(i int) structPointer { return structPointer{p.v.Index(i)} }
-func (p structPointerSlice) Append(q structPointer) {
-	p.v.Set(reflect.Append(p.v, q.v))
+func (p pointer) toUint64() *uint64 {
+	return p.v.Interface().(*uint64)
 }
-
-var (
-	int32Type   = reflect.TypeOf(int32(0))
-	uint32Type  = reflect.TypeOf(uint32(0))
-	float32Type = reflect.TypeOf(float32(0))
-	int64Type   = reflect.TypeOf(int64(0))
-	uint64Type  = reflect.TypeOf(uint64(0))
-	float64Type = reflect.TypeOf(float64(0))
-)
-
-// A word32 represents a field of type *int32, *uint32, *float32, or *enum.
-// That is, v.Type() is *int32, *uint32, *float32, or *enum and v is assignable.
-type word32 struct {
-	v reflect.Value
+func (p pointer) toUint64Ptr() **uint64 {
+	return p.v.Interface().(**uint64)
 }
-
-// IsNil reports whether p is nil.
-func word32_IsNil(p word32) bool {
-	return p.v.IsNil()
+func (p pointer) toUint64Slice() *[]uint64 {
+	return p.v.Interface().(*[]uint64)
 }
-
-// Set sets p to point at a newly allocated word with bits set to x.
-func word32_Set(p word32, o *Buffer, x uint32) {
-	t := p.v.Type().Elem()
-	switch t {
-	case int32Type:
-		if len(o.int32s) == 0 {
-			o.int32s = make([]int32, uint32PoolSize)
-		}
-		o.int32s[0] = int32(x)
-		p.v.Set(reflect.ValueOf(&o.int32s[0]))
-		o.int32s = o.int32s[1:]
-		return
-	case uint32Type:
-		if len(o.uint32s) == 0 {
-			o.uint32s = make([]uint32, uint32PoolSize)
-		}
-		o.uint32s[0] = x
-		p.v.Set(reflect.ValueOf(&o.uint32s[0]))
-		o.uint32s = o.uint32s[1:]
-		return
-	case float32Type:
-		if len(o.float32s) == 0 {
-			o.float32s = make([]float32, uint32PoolSize)
-		}
-		o.float32s[0] = math.Float32frombits(x)
-		p.v.Set(reflect.ValueOf(&o.float32s[0]))
-		o.float32s = o.float32s[1:]
-		return
-	}
-
-	// must be enum
-	p.v.Set(reflect.New(t))
-	p.v.Elem().SetInt(int64(int32(x)))
+func (p pointer) toUint32() *uint32 {
+	return p.v.Interface().(*uint32)
 }
-
-// Get gets the bits pointed at by p, as a uint32.
-func word32_Get(p word32) uint32 {
-	elem := p.v.Elem()
-	switch elem.Kind() {
-	case reflect.Int32:
-		return uint32(elem.Int())
-	case reflect.Uint32:
-		return uint32(elem.Uint())
-	case reflect.Float32:
-		return math.Float32bits(float32(elem.Float()))
-	}
-	panic("unreachable")
+func (p pointer) toUint32Ptr() **uint32 {
+	return p.v.Interface().(**uint32)
 }
-
-// Word32 returns a reference to a *int32, *uint32, *float32, or *enum field in the struct.
-func structPointer_Word32(p structPointer, f field) word32 {
-	return word32{structPointer_field(p, f)}
+func (p pointer) toUint32Slice() *[]uint32 {
+	return p.v.Interface().(*[]uint32)
 }
-
-// A word32Val represents a field of type int32, uint32, float32, or enum.
-// That is, v.Type() is int32, uint32, float32, or enum and v is assignable.
-type word32Val struct {
-	v reflect.Value
+func (p pointer) toBool() *bool {
+	return p.v.Interface().(*bool)
 }
-
-// Set sets *p to x.
-func word32Val_Set(p word32Val, x uint32) {
-	switch p.v.Type() {
-	case int32Type:
-		p.v.SetInt(int64(x))
-		return
-	case uint32Type:
-		p.v.SetUint(uint64(x))
-		return
-	case float32Type:
-		p.v.SetFloat(float64(math.Float32frombits(x)))
-		return
-	}
-
-	// must be enum
-	p.v.SetInt(int64(int32(x)))
+func (p pointer) toBoolPtr() **bool {
+	return p.v.Interface().(**bool)
 }
-
-// Get gets the bits pointed at by p, as a uint32.
-func word32Val_Get(p word32Val) uint32 {
-	elem := p.v
-	switch elem.Kind() {
-	case reflect.Int32:
-		return uint32(elem.Int())
-	case reflect.Uint32:
-		return uint32(elem.Uint())
-	case reflect.Float32:
-		return math.Float32bits(float32(elem.Float()))
-	}
-	panic("unreachable")
+func (p pointer) toBoolSlice() *[]bool {
+	return p.v.Interface().(*[]bool)
 }
-
-// Word32Val returns a reference to a int32, uint32, float32, or enum field in the struct.
-func structPointer_Word32Val(p structPointer, f field) word32Val {
-	return word32Val{structPointer_field(p, f)}
+func (p pointer) toFloat64() *float64 {
+	return p.v.Interface().(*float64)
 }
-
-// A word32Slice is a slice of 32-bit values.
-// That is, v.Type() is []int32, []uint32, []float32, or []enum.
-type word32Slice struct {
-	v reflect.Value
+func (p pointer) toFloat64Ptr() **float64 {
+	return p.v.Interface().(**float64)
 }
-
-func (p word32Slice) Append(x uint32) {
-	n, m := p.v.Len(), p.v.Cap()
-	if n < m {
-		p.v.SetLen(n + 1)
-	} else {
-		t := p.v.Type().Elem()
-		p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
-	}
-	elem := p.v.Index(n)
-	switch elem.Kind() {
-	case reflect.Int32:
-		elem.SetInt(int64(int32(x)))
-	case reflect.Uint32:
-		elem.SetUint(uint64(x))
-	case reflect.Float32:
-		elem.SetFloat(float64(math.Float32frombits(x)))
-	}
+func (p pointer) toFloat64Slice() *[]float64 {
+	return p.v.Interface().(*[]float64)
 }
-
-func (p word32Slice) Len() int {
-	return p.v.Len()
+func (p pointer) toFloat32() *float32 {
+	return p.v.Interface().(*float32)
 }
-
-func (p word32Slice) Index(i int) uint32 {
-	elem := p.v.Index(i)
-	switch elem.Kind() {
-	case reflect.Int32:
-		return uint32(elem.Int())
-	case reflect.Uint32:
-		return uint32(elem.Uint())
-	case reflect.Float32:
-		return math.Float32bits(float32(elem.Float()))
-	}
-	panic("unreachable")
+func (p pointer) toFloat32Ptr() **float32 {
+	return p.v.Interface().(**float32)
 }
-
-// Word32Slice returns a reference to a []int32, []uint32, []float32, or []enum field in the struct.
-func structPointer_Word32Slice(p structPointer, f field) word32Slice {
-	return word32Slice{structPointer_field(p, f)}
+func (p pointer) toFloat32Slice() *[]float32 {
+	return p.v.Interface().(*[]float32)
 }
-
-// word64 is like word32 but for 64-bit values.
-type word64 struct {
-	v reflect.Value
+func (p pointer) toString() *string {
+	return p.v.Interface().(*string)
 }
-
-func word64_Set(p word64, o *Buffer, x uint64) {
-	t := p.v.Type().Elem()
-	switch t {
-	case int64Type:
-		if len(o.int64s) == 0 {
-			o.int64s = make([]int64, uint64PoolSize)
-		}
-		o.int64s[0] = int64(x)
-		p.v.Set(reflect.ValueOf(&o.int64s[0]))
-		o.int64s = o.int64s[1:]
-		return
-	case uint64Type:
-		if len(o.uint64s) == 0 {
-			o.uint64s = make([]uint64, uint64PoolSize)
-		}
-		o.uint64s[0] = x
-		p.v.Set(reflect.ValueOf(&o.uint64s[0]))
-		o.uint64s = o.uint64s[1:]
-		return
-	case float64Type:
-		if len(o.float64s) == 0 {
-			o.float64s = make([]float64, uint64PoolSize)
-		}
-		o.float64s[0] = math.Float64frombits(x)
-		p.v.Set(reflect.ValueOf(&o.float64s[0]))
-		o.float64s = o.float64s[1:]
-		return
-	}
-	panic("unreachable")
+func (p pointer) toStringPtr() **string {
+	return p.v.Interface().(**string)
 }
-
-func word64_IsNil(p word64) bool {
-	return p.v.IsNil()
+func (p pointer) toStringSlice() *[]string {
+	return p.v.Interface().(*[]string)
 }
-
-func word64_Get(p word64) uint64 {
-	elem := p.v.Elem()
-	switch elem.Kind() {
-	case reflect.Int64:
-		return uint64(elem.Int())
-	case reflect.Uint64:
-		return elem.Uint()
-	case reflect.Float64:
-		return math.Float64bits(elem.Float())
-	}
-	panic("unreachable")
+func (p pointer) toBytes() *[]byte {
+	return p.v.Interface().(*[]byte)
 }
-
-func structPointer_Word64(p structPointer, f field) word64 {
-	return word64{structPointer_field(p, f)}
+func (p pointer) toBytesSlice() *[][]byte {
+	return p.v.Interface().(*[][]byte)
+}
+func (p pointer) toExtensions() *XXX_InternalExtensions {
+	return p.v.Interface().(*XXX_InternalExtensions)
+}
+func (p pointer) toOldExtensions() *map[int32]Extension {
+	return p.v.Interface().(*map[int32]Extension)
+}
+func (p pointer) getPointer() pointer {
+	return pointer{v: p.v.Elem()}
+}
+func (p pointer) setPointer(q pointer) {
+	p.v.Elem().Set(q.v)
+}
+func (p pointer) appendPointer(q pointer) {
+	grow(p.v.Elem()).Set(q.v)
 }
 
-// word64Val is like word32Val but for 64-bit values.
-type word64Val struct {
-	v reflect.Value
+// getPointerSlice copies []*T from p as a new []pointer.
+// This behavior differs from the implementation in pointer_unsafe.go.
+func (p pointer) getPointerSlice() []pointer {
+	if p.v.IsNil() {
+		return nil
+	}
+	n := p.v.Elem().Len()
+	s := make([]pointer, n)
+	for i := 0; i < n; i++ {
+		s[i] = pointer{v: p.v.Elem().Index(i)}
+	}
+	return s
 }
 
-func word64Val_Set(p word64Val, o *Buffer, x uint64) {
-	switch p.v.Type() {
-	case int64Type:
-		p.v.SetInt(int64(x))
-		return
-	case uint64Type:
-		p.v.SetUint(x)
-		return
-	case float64Type:
-		p.v.SetFloat(math.Float64frombits(x))
+// setPointerSlice copies []pointer into p as a new []*T.
+// This behavior differs from the implementation in pointer_unsafe.go.
+func (p pointer) setPointerSlice(v []pointer) {
+	if v == nil {
+		p.v.Elem().Set(reflect.New(p.v.Elem().Type()).Elem())
 		return
 	}
-	panic("unreachable")
+	s := reflect.MakeSlice(p.v.Elem().Type(), 0, len(v))
+	for _, p := range v {
+		s = reflect.Append(s, p.v)
+	}
+	p.v.Elem().Set(s)
 }
 
-func word64Val_Get(p word64Val) uint64 {
-	elem := p.v
-	switch elem.Kind() {
-	case reflect.Int64:
-		return uint64(elem.Int())
-	case reflect.Uint64:
-		return elem.Uint()
-	case reflect.Float64:
-		return math.Float64bits(elem.Float())
+// getInterfacePointer returns a pointer that points to the
+// interface data of the interface pointed by p.
+func (p pointer) getInterfacePointer() pointer {
+	if p.v.Elem().IsNil() {
+		return pointer{v: p.v.Elem()}
 	}
-	panic("unreachable")
+	return pointer{v: p.v.Elem().Elem().Elem().Field(0).Addr()} // *interface -> interface -> *struct -> struct
 }
 
-func structPointer_Word64Val(p structPointer, f field) word64Val {
-	return word64Val{structPointer_field(p, f)}
+func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
+	// TODO: check that p.v.Type().Elem() == t?
+	return p.v
 }
 
-type word64Slice struct {
-	v reflect.Value
+func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
+	atomicLock.Lock()
+	defer atomicLock.Unlock()
+	return *p
 }
-
-func (p word64Slice) Append(x uint64) {
-	n, m := p.v.Len(), p.v.Cap()
-	if n < m {
-		p.v.SetLen(n + 1)
-	} else {
-		t := p.v.Type().Elem()
-		p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
-	}
-	elem := p.v.Index(n)
-	switch elem.Kind() {
-	case reflect.Int64:
-		elem.SetInt(int64(int64(x)))
-	case reflect.Uint64:
-		elem.SetUint(uint64(x))
-	case reflect.Float64:
-		elem.SetFloat(float64(math.Float64frombits(x)))
-	}
+func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
+	atomicLock.Lock()
+	defer atomicLock.Unlock()
+	*p = v
 }
-
-func (p word64Slice) Len() int {
-	return p.v.Len()
+func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
+	atomicLock.Lock()
+	defer atomicLock.Unlock()
+	return *p
 }
-
-func (p word64Slice) Index(i int) uint64 {
-	elem := p.v.Index(i)
-	switch elem.Kind() {
-	case reflect.Int64:
-		return uint64(elem.Int())
-	case reflect.Uint64:
-		return uint64(elem.Uint())
-	case reflect.Float64:
-		return math.Float64bits(float64(elem.Float()))
-	}
-	panic("unreachable")
+func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
+	atomicLock.Lock()
+	defer atomicLock.Unlock()
+	*p = v
 }
-
-func structPointer_Word64Slice(p structPointer, f field) word64Slice {
-	return word64Slice{structPointer_field(p, f)}
+func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
+	atomicLock.Lock()
+	defer atomicLock.Unlock()
+	return *p
+}
+func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
+	atomicLock.Lock()
+	defer atomicLock.Unlock()
+	*p = v
 }
+func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
+	atomicLock.Lock()
+	defer atomicLock.Unlock()
+	return *p
+}
+func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
+	atomicLock.Lock()
+	defer atomicLock.Unlock()
+	*p = v
+}
+
+var atomicLock sync.Mutex

+ 210 - 167
vendor/github.com/golang/protobuf/proto/pointer_unsafe.go

@@ -29,7 +29,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// +build !appengine,!js
+// +build !purego,!appengine,!js
 
 // This file contains the implementation of the proto field accesses using package unsafe.
 
@@ -37,38 +37,13 @@ package proto
 
 import (
 	"reflect"
+	"sync/atomic"
 	"unsafe"
 )
 
-// NOTE: These type_Foo functions would more idiomatically be methods,
-// but Go does not allow methods on pointer types, and we must preserve
-// some pointer type for the garbage collector. We use these
-// funcs with clunky names as our poor approximation to methods.
-//
-// An alternative would be
-//	type structPointer struct { p unsafe.Pointer }
-// but that does not registerize as well.
-
-// A structPointer is a pointer to a struct.
-type structPointer unsafe.Pointer
-
-// toStructPointer returns a structPointer equivalent to the given reflect value.
-func toStructPointer(v reflect.Value) structPointer {
-	return structPointer(unsafe.Pointer(v.Pointer()))
-}
-
-// IsNil reports whether p is nil.
-func structPointer_IsNil(p structPointer) bool {
-	return p == nil
-}
-
-// Interface returns the struct pointer, assumed to have element type t,
-// as an interface value.
-func structPointer_Interface(p structPointer, t reflect.Type) interface{} {
-	return reflect.NewAt(t, unsafe.Pointer(p)).Interface()
-}
+const unsafeAllowed = true
 
-// A field identifies a field in a struct, accessible from a structPointer.
+// A field identifies a field in a struct, accessible from a pointer.
 // In this implementation, a field is identified by its byte offset from the start of the struct.
 type field uintptr
 
@@ -80,191 +55,259 @@ func toField(f *reflect.StructField) field {
 // invalidField is an invalid field identifier.
 const invalidField = ^field(0)
 
+// zeroField is a noop when calling pointer.offset.
+const zeroField = field(0)
+
 // IsValid reports whether the field identifier is valid.
 func (f field) IsValid() bool {
-	return f != ^field(0)
+	return f != invalidField
+}
+
+// The pointer type below is for the new table-driven encoder/decoder.
+// The implementation here uses unsafe.Pointer to create a generic pointer.
+// In pointer_reflect.go we use reflect instead of unsafe to implement
+// the same (but slower) interface.
+type pointer struct {
+	p unsafe.Pointer
+}
+
+// size of pointer
+var ptrSize = unsafe.Sizeof(uintptr(0))
+
+// toPointer converts an interface of pointer type to a pointer
+// that points to the same target.
+func toPointer(i *Message) pointer {
+	// Super-tricky - read pointer out of data word of interface value.
+	// Saves ~25ns over the equivalent:
+	// return valToPointer(reflect.ValueOf(*i))
+	return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
+}
+
+// toAddrPointer converts an interface to a pointer that points to
+// the interface data.
+func toAddrPointer(i *interface{}, isptr, deref bool) (p pointer) {
+	// Super-tricky - read or get the address of data word of interface value.
+	if isptr {
+		// The interface is of pointer type, thus it is a direct interface.
+		// The data word is the pointer data itself. We take its address.
+		p = pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)}
+	} else {
+		// The interface is not of pointer type. The data word is the pointer
+		// to the data.
+		p = pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
+	}
+	if deref {
+		p.p = *(*unsafe.Pointer)(p.p)
+	}
+	return p
 }
 
-// Bytes returns the address of a []byte field in the struct.
-func structPointer_Bytes(p structPointer, f field) *[]byte {
-	return (*[]byte)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+// valToPointer converts v to a pointer. v must be of pointer type.
+func valToPointer(v reflect.Value) pointer {
+	return pointer{p: unsafe.Pointer(v.Pointer())}
 }
 
-// BytesSlice returns the address of a [][]byte field in the struct.
-func structPointer_BytesSlice(p structPointer, f field) *[][]byte {
-	return (*[][]byte)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+// offset converts from a pointer to a structure to a pointer to
+// one of its fields.
+func (p pointer) offset(f field) pointer {
+	// For safety, we should panic if !f.IsValid, however calling panic causes
+	// this to no longer be inlineable, which is a serious performance cost.
+	/*
+		if !f.IsValid() {
+			panic("invalid field")
+		}
+	*/
+	return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))}
 }
 
-// Bool returns the address of a *bool field in the struct.
-func structPointer_Bool(p structPointer, f field) **bool {
-	return (**bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+func (p pointer) isNil() bool {
+	return p.p == nil
 }
 
-// BoolVal returns the address of a bool field in the struct.
-func structPointer_BoolVal(p structPointer, f field) *bool {
-	return (*bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+func (p pointer) toInt64() *int64 {
+	return (*int64)(p.p)
 }
-
-// BoolSlice returns the address of a []bool field in the struct.
-func structPointer_BoolSlice(p structPointer, f field) *[]bool {
-	return (*[]bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+func (p pointer) toInt64Ptr() **int64 {
+	return (**int64)(p.p)
 }
-
-// String returns the address of a *string field in the struct.
-func structPointer_String(p structPointer, f field) **string {
-	return (**string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+func (p pointer) toInt64Slice() *[]int64 {
+	return (*[]int64)(p.p)
 }
-
-// StringVal returns the address of a string field in the struct.
-func structPointer_StringVal(p structPointer, f field) *string {
-	return (*string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+func (p pointer) toInt32() *int32 {
+	return (*int32)(p.p)
 }
 
-// StringSlice returns the address of a []string field in the struct.
-func structPointer_StringSlice(p structPointer, f field) *[]string {
-	return (*[]string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+// See pointer_reflect.go for why toInt32Ptr/Slice doesn't exist.
+/*
+	func (p pointer) toInt32Ptr() **int32 {
+		return (**int32)(p.p)
+	}
+	func (p pointer) toInt32Slice() *[]int32 {
+		return (*[]int32)(p.p)
+	}
+*/
+func (p pointer) getInt32Ptr() *int32 {
+	return *(**int32)(p.p)
 }
-
-// ExtMap returns the address of an extension map field in the struct.
-func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
-	return (*XXX_InternalExtensions)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+func (p pointer) setInt32Ptr(v int32) {
+	*(**int32)(p.p) = &v
 }
 
-func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
-	return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+// getInt32Slice loads a []int32 from p.
+// The value returned is aliased with the original slice.
+// This behavior differs from the implementation in pointer_reflect.go.
+func (p pointer) getInt32Slice() []int32 {
+	return *(*[]int32)(p.p)
 }
 
-// NewAt returns the reflect.Value for a pointer to a field in the struct.
-func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
-	return reflect.NewAt(typ, unsafe.Pointer(uintptr(p)+uintptr(f)))
+// setInt32Slice stores a []int32 to p.
+// The value set is aliased with the input slice.
+// This behavior differs from the implementation in pointer_reflect.go.
+func (p pointer) setInt32Slice(v []int32) {
+	*(*[]int32)(p.p) = v
 }
 
-// SetStructPointer writes a *struct field in the struct.
-func structPointer_SetStructPointer(p structPointer, f field, q structPointer) {
-	*(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) = q
+// TODO: Can we get rid of appendInt32Slice and use setInt32Slice instead?
+func (p pointer) appendInt32Slice(v int32) {
+	s := (*[]int32)(p.p)
+	*s = append(*s, v)
 }
 
-// GetStructPointer reads a *struct field in the struct.
-func structPointer_GetStructPointer(p structPointer, f field) structPointer {
-	return *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+func (p pointer) toUint64() *uint64 {
+	return (*uint64)(p.p)
 }
-
-// StructPointerSlice the address of a []*struct field in the struct.
-func structPointer_StructPointerSlice(p structPointer, f field) *structPointerSlice {
-	return (*structPointerSlice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+func (p pointer) toUint64Ptr() **uint64 {
+	return (**uint64)(p.p)
 }
-
-// A structPointerSlice represents a slice of pointers to structs (themselves submessages or groups).
-type structPointerSlice []structPointer
-
-func (v *structPointerSlice) Len() int                  { return len(*v) }
-func (v *structPointerSlice) Index(i int) structPointer { return (*v)[i] }
-func (v *structPointerSlice) Append(p structPointer)    { *v = append(*v, p) }
-
-// A word32 is the address of a "pointer to 32-bit value" field.
-type word32 **uint32
-
-// IsNil reports whether *v is nil.
-func word32_IsNil(p word32) bool {
-	return *p == nil
+func (p pointer) toUint64Slice() *[]uint64 {
+	return (*[]uint64)(p.p)
 }
-
-// Set sets *v to point at a newly allocated word set to x.
-func word32_Set(p word32, o *Buffer, x uint32) {
-	if len(o.uint32s) == 0 {
-		o.uint32s = make([]uint32, uint32PoolSize)
-	}
-	o.uint32s[0] = x
-	*p = &o.uint32s[0]
-	o.uint32s = o.uint32s[1:]
+func (p pointer) toUint32() *uint32 {
+	return (*uint32)(p.p)
 }
-
-// Get gets the value pointed at by *v.
-func word32_Get(p word32) uint32 {
-	return **p
+func (p pointer) toUint32Ptr() **uint32 {
+	return (**uint32)(p.p)
 }
-
-// Word32 returns the address of a *int32, *uint32, *float32, or *enum field in the struct.
-func structPointer_Word32(p structPointer, f field) word32 {
-	return word32((**uint32)(unsafe.Pointer(uintptr(p) + uintptr(f))))
+func (p pointer) toUint32Slice() *[]uint32 {
+	return (*[]uint32)(p.p)
 }
-
-// A word32Val is the address of a 32-bit value field.
-type word32Val *uint32
-
-// Set sets *p to x.
-func word32Val_Set(p word32Val, x uint32) {
-	*p = x
+func (p pointer) toBool() *bool {
+	return (*bool)(p.p)
 }
-
-// Get gets the value pointed at by p.
-func word32Val_Get(p word32Val) uint32 {
-	return *p
+func (p pointer) toBoolPtr() **bool {
+	return (**bool)(p.p)
 }
-
-// Word32Val returns the address of a *int32, *uint32, *float32, or *enum field in the struct.
-func structPointer_Word32Val(p structPointer, f field) word32Val {
-	return word32Val((*uint32)(unsafe.Pointer(uintptr(p) + uintptr(f))))
+func (p pointer) toBoolSlice() *[]bool {
+	return (*[]bool)(p.p)
 }
-
-// A word32Slice is a slice of 32-bit values.
-type word32Slice []uint32
-
-func (v *word32Slice) Append(x uint32)    { *v = append(*v, x) }
-func (v *word32Slice) Len() int           { return len(*v) }
-func (v *word32Slice) Index(i int) uint32 { return (*v)[i] }
-
-// Word32Slice returns the address of a []int32, []uint32, []float32, or []enum field in the struct.
-func structPointer_Word32Slice(p structPointer, f field) *word32Slice {
-	return (*word32Slice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+func (p pointer) toFloat64() *float64 {
+	return (*float64)(p.p)
 }
-
-// word64 is like word32 but for 64-bit values.
-type word64 **uint64
-
-func word64_Set(p word64, o *Buffer, x uint64) {
-	if len(o.uint64s) == 0 {
-		o.uint64s = make([]uint64, uint64PoolSize)
-	}
-	o.uint64s[0] = x
-	*p = &o.uint64s[0]
-	o.uint64s = o.uint64s[1:]
+func (p pointer) toFloat64Ptr() **float64 {
+	return (**float64)(p.p)
 }
-
-func word64_IsNil(p word64) bool {
-	return *p == nil
+func (p pointer) toFloat64Slice() *[]float64 {
+	return (*[]float64)(p.p)
 }
-
-func word64_Get(p word64) uint64 {
-	return **p
+func (p pointer) toFloat32() *float32 {
+	return (*float32)(p.p)
+}
+func (p pointer) toFloat32Ptr() **float32 {
+	return (**float32)(p.p)
+}
+func (p pointer) toFloat32Slice() *[]float32 {
+	return (*[]float32)(p.p)
+}
+func (p pointer) toString() *string {
+	return (*string)(p.p)
+}
+func (p pointer) toStringPtr() **string {
+	return (**string)(p.p)
+}
+func (p pointer) toStringSlice() *[]string {
+	return (*[]string)(p.p)
+}
+func (p pointer) toBytes() *[]byte {
+	return (*[]byte)(p.p)
+}
+func (p pointer) toBytesSlice() *[][]byte {
+	return (*[][]byte)(p.p)
+}
+func (p pointer) toExtensions() *XXX_InternalExtensions {
+	return (*XXX_InternalExtensions)(p.p)
+}
+func (p pointer) toOldExtensions() *map[int32]Extension {
+	return (*map[int32]Extension)(p.p)
 }
 
-func structPointer_Word64(p structPointer, f field) word64 {
-	return word64((**uint64)(unsafe.Pointer(uintptr(p) + uintptr(f))))
+// getPointerSlice loads []*T from p as a []pointer.
+// The value returned is aliased with the original slice.
+// This behavior differs from the implementation in pointer_reflect.go.
+func (p pointer) getPointerSlice() []pointer {
+	// Super-tricky - p should point to a []*T where T is a
+	// message type. We load it as []pointer.
+	return *(*[]pointer)(p.p)
 }
 
-// word64Val is like word32Val but for 64-bit values.
-type word64Val *uint64
+// setPointerSlice stores []pointer into p as a []*T.
+// The value set is aliased with the input slice.
+// This behavior differs from the implementation in pointer_reflect.go.
+func (p pointer) setPointerSlice(v []pointer) {
+	// Super-tricky - p should point to a []*T where T is a
+	// message type. We store it as []pointer.
+	*(*[]pointer)(p.p) = v
+}
 
-func word64Val_Set(p word64Val, o *Buffer, x uint64) {
-	*p = x
+// getPointer loads the pointer at p and returns it.
+func (p pointer) getPointer() pointer {
+	return pointer{p: *(*unsafe.Pointer)(p.p)}
 }
 
-func word64Val_Get(p word64Val) uint64 {
-	return *p
+// setPointer stores the pointer q at p.
+func (p pointer) setPointer(q pointer) {
+	*(*unsafe.Pointer)(p.p) = q.p
 }
 
-func structPointer_Word64Val(p structPointer, f field) word64Val {
-	return word64Val((*uint64)(unsafe.Pointer(uintptr(p) + uintptr(f))))
+// append q to the slice pointed to by p.
+func (p pointer) appendPointer(q pointer) {
+	s := (*[]unsafe.Pointer)(p.p)
+	*s = append(*s, q.p)
 }
 
-// word64Slice is like word32Slice but for 64-bit values.
-type word64Slice []uint64
+// getInterfacePointer returns a pointer that points to the
+// interface data of the interface pointed by p.
+func (p pointer) getInterfacePointer() pointer {
+	// Super-tricky - read pointer out of data word of interface value.
+	return pointer{p: (*(*[2]unsafe.Pointer)(p.p))[1]}
+}
 
-func (v *word64Slice) Append(x uint64)    { *v = append(*v, x) }
-func (v *word64Slice) Len() int           { return len(*v) }
-func (v *word64Slice) Index(i int) uint64 { return (*v)[i] }
+// asPointerTo returns a reflect.Value that is a pointer to an
+// object of type t stored at p.
+func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
+	return reflect.NewAt(t, p.p)
+}
 
-func structPointer_Word64Slice(p structPointer, f field) *word64Slice {
-	return (*word64Slice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
+	return (*unmarshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
+}
+func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
+	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
+}
+func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
+	return (*marshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
+}
+func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
+	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
+}
+func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
+	return (*mergeInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
+}
+func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
+	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
+}
+func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
+	return (*discardInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
+}
+func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
+	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
 }

+ 74 - 402
vendor/github.com/golang/protobuf/proto/properties.go

@@ -38,7 +38,6 @@ package proto
 import (
 	"fmt"
 	"log"
-	"os"
 	"reflect"
 	"sort"
 	"strconv"
@@ -58,42 +57,6 @@ const (
 	WireFixed32    = 5
 )
 
-const startSize = 10 // initial slice/string sizes
-
-// Encoders are defined in encode.go
-// An encoder outputs the full representation of a field, including its
-// tag and encoder type.
-type encoder func(p *Buffer, prop *Properties, base structPointer) error
-
-// A valueEncoder encodes a single integer in a particular encoding.
-type valueEncoder func(o *Buffer, x uint64) error
-
-// Sizers are defined in encode.go
-// A sizer returns the encoded size of a field, including its tag and encoder
-// type.
-type sizer func(prop *Properties, base structPointer) int
-
-// A valueSizer returns the encoded size of a single integer in a particular
-// encoding.
-type valueSizer func(x uint64) int
-
-// Decoders are defined in decode.go
-// A decoder creates a value from its wire representation.
-// Unrecognized subelements are saved in unrec.
-type decoder func(p *Buffer, prop *Properties, base structPointer) error
-
-// A valueDecoder decodes a single integer in a particular encoding.
-type valueDecoder func(o *Buffer) (x uint64, err error)
-
-// A oneofMarshaler does the marshaling for all oneof fields in a message.
-type oneofMarshaler func(Message, *Buffer) error
-
-// A oneofUnmarshaler does the unmarshaling for a oneof field in a message.
-type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error)
-
-// A oneofSizer does the sizing for all oneof fields in a message.
-type oneofSizer func(Message) int
-
 // tagMap is an optimization over map[int]int for typical protocol buffer
 // use-cases. Encoded protocol buffers are often in tag order with small tag
 // numbers.
@@ -140,13 +103,6 @@ type StructProperties struct {
 	decoderTags      tagMap         // map from proto tag to struct field number
 	decoderOrigNames map[string]int // map from original name to struct field number
 	order            []int          // list of struct field numbers in tag order
-	unrecField       field          // field id of the XXX_unrecognized []byte field
-	extendable       bool           // is this an extendable proto
-
-	oneofMarshaler   oneofMarshaler
-	oneofUnmarshaler oneofUnmarshaler
-	oneofSizer       oneofSizer
-	stype            reflect.Type
 
 	// OneofTypes contains information about the oneof fields in this message.
 	// It is keyed by the original name of a field.
@@ -182,41 +138,24 @@ type Properties struct {
 	Repeated bool
 	Packed   bool   // relevant for repeated primitives only
 	Enum     string // set for enum types only
-	proto3   bool   // whether this is known to be a proto3 field; set for []byte only
+	proto3   bool   // whether this is known to be a proto3 field
 	oneof    bool   // whether this is a oneof field
 
 	Default    string // default value
 	HasDefault bool   // whether an explicit default was provided
-	def_uint64 uint64
-
-	enc           encoder
-	valEnc        valueEncoder // set for bool and numeric types only
-	field         field
-	tagcode       []byte // encoding of EncodeVarint((Tag<<3)|WireType)
-	tagbuf        [8]byte
-	stype         reflect.Type      // set for struct types only
-	sprop         *StructProperties // set for struct types only
-	isMarshaler   bool
-	isUnmarshaler bool
-
-	mtype    reflect.Type // set for map types only
-	mkeyprop *Properties  // set for map types only
-	mvalprop *Properties  // set for map types only
-
-	size    sizer
-	valSize valueSizer // set for bool and numeric types only
-
-	dec    decoder
-	valDec valueDecoder // set for bool and numeric types only
-
-	// If this is a packable field, this will be the decoder for the packed version of the field.
-	packedDec decoder
+
+	stype reflect.Type      // set for struct types only
+	sprop *StructProperties // set for struct types only
+
+	mtype      reflect.Type // set for map types only
+	MapKeyProp *Properties  // set for map types only
+	MapValProp *Properties  // set for map types only
 }
 
 // String formats the properties in the protobuf struct field tag style.
 func (p *Properties) String() string {
 	s := p.Wire
-	s = ","
+	s += ","
 	s += strconv.Itoa(p.Tag)
 	if p.Required {
 		s += ",req"
@@ -254,7 +193,7 @@ func (p *Properties) Parse(s string) {
 	// "bytes,49,opt,name=foo,def=hello!"
 	fields := strings.Split(s, ",") // breaks def=, but handled below.
 	if len(fields) < 2 {
-		fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s)
+		log.Printf("proto: tag has too few fields: %q", s)
 		return
 	}
 
@@ -262,34 +201,19 @@ func (p *Properties) Parse(s string) {
 	switch p.Wire {
 	case "varint":
 		p.WireType = WireVarint
-		p.valEnc = (*Buffer).EncodeVarint
-		p.valDec = (*Buffer).DecodeVarint
-		p.valSize = sizeVarint
 	case "fixed32":
 		p.WireType = WireFixed32
-		p.valEnc = (*Buffer).EncodeFixed32
-		p.valDec = (*Buffer).DecodeFixed32
-		p.valSize = sizeFixed32
 	case "fixed64":
 		p.WireType = WireFixed64
-		p.valEnc = (*Buffer).EncodeFixed64
-		p.valDec = (*Buffer).DecodeFixed64
-		p.valSize = sizeFixed64
 	case "zigzag32":
 		p.WireType = WireVarint
-		p.valEnc = (*Buffer).EncodeZigzag32
-		p.valDec = (*Buffer).DecodeZigzag32
-		p.valSize = sizeZigzag32
 	case "zigzag64":
 		p.WireType = WireVarint
-		p.valEnc = (*Buffer).EncodeZigzag64
-		p.valDec = (*Buffer).DecodeZigzag64
-		p.valSize = sizeZigzag64
 	case "bytes", "group":
 		p.WireType = WireBytes
 		// no numeric converter for non-numeric types
 	default:
-		fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s)
+		log.Printf("proto: tag has unknown wire type: %q", s)
 		return
 	}
 
@@ -299,6 +223,7 @@ func (p *Properties) Parse(s string) {
 		return
 	}
 
+outer:
 	for i := 2; i < len(fields); i++ {
 		f := fields[i]
 		switch {
@@ -326,255 +251,40 @@ func (p *Properties) Parse(s string) {
 			if i+1 < len(fields) {
 				// Commas aren't escaped, and def is always last.
 				p.Default += "," + strings.Join(fields[i+1:], ",")
-				break
+				break outer
 			}
 		}
 	}
 }
 
-func logNoSliceEnc(t1, t2 reflect.Type) {
-	fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2)
-}
-
 var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
 
-// Initialize the fields for encoding and decoding.
-func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
-	p.enc = nil
-	p.dec = nil
-	p.size = nil
-
+// setFieldProps initializes the field properties for submessages and maps.
+func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
 	switch t1 := typ; t1.Kind() {
-	default:
-		fmt.Fprintf(os.Stderr, "proto: no coders for %v\n", t1)
-
-	// proto3 scalar types
-
-	case reflect.Bool:
-		p.enc = (*Buffer).enc_proto3_bool
-		p.dec = (*Buffer).dec_proto3_bool
-		p.size = size_proto3_bool
-	case reflect.Int32:
-		p.enc = (*Buffer).enc_proto3_int32
-		p.dec = (*Buffer).dec_proto3_int32
-		p.size = size_proto3_int32
-	case reflect.Uint32:
-		p.enc = (*Buffer).enc_proto3_uint32
-		p.dec = (*Buffer).dec_proto3_int32 // can reuse
-		p.size = size_proto3_uint32
-	case reflect.Int64, reflect.Uint64:
-		p.enc = (*Buffer).enc_proto3_int64
-		p.dec = (*Buffer).dec_proto3_int64
-		p.size = size_proto3_int64
-	case reflect.Float32:
-		p.enc = (*Buffer).enc_proto3_uint32 // can just treat them as bits
-		p.dec = (*Buffer).dec_proto3_int32
-		p.size = size_proto3_uint32
-	case reflect.Float64:
-		p.enc = (*Buffer).enc_proto3_int64 // can just treat them as bits
-		p.dec = (*Buffer).dec_proto3_int64
-		p.size = size_proto3_int64
-	case reflect.String:
-		p.enc = (*Buffer).enc_proto3_string
-		p.dec = (*Buffer).dec_proto3_string
-		p.size = size_proto3_string
-
 	case reflect.Ptr:
-		switch t2 := t1.Elem(); t2.Kind() {
-		default:
-			fmt.Fprintf(os.Stderr, "proto: no encoder function for %v -> %v\n", t1, t2)
-			break
-		case reflect.Bool:
-			p.enc = (*Buffer).enc_bool
-			p.dec = (*Buffer).dec_bool
-			p.size = size_bool
-		case reflect.Int32:
-			p.enc = (*Buffer).enc_int32
-			p.dec = (*Buffer).dec_int32
-			p.size = size_int32
-		case reflect.Uint32:
-			p.enc = (*Buffer).enc_uint32
-			p.dec = (*Buffer).dec_int32 // can reuse
-			p.size = size_uint32
-		case reflect.Int64, reflect.Uint64:
-			p.enc = (*Buffer).enc_int64
-			p.dec = (*Buffer).dec_int64
-			p.size = size_int64
-		case reflect.Float32:
-			p.enc = (*Buffer).enc_uint32 // can just treat them as bits
-			p.dec = (*Buffer).dec_int32
-			p.size = size_uint32
-		case reflect.Float64:
-			p.enc = (*Buffer).enc_int64 // can just treat them as bits
-			p.dec = (*Buffer).dec_int64
-			p.size = size_int64
-		case reflect.String:
-			p.enc = (*Buffer).enc_string
-			p.dec = (*Buffer).dec_string
-			p.size = size_string
-		case reflect.Struct:
+		if t1.Elem().Kind() == reflect.Struct {
 			p.stype = t1.Elem()
-			p.isMarshaler = isMarshaler(t1)
-			p.isUnmarshaler = isUnmarshaler(t1)
-			if p.Wire == "bytes" {
-				p.enc = (*Buffer).enc_struct_message
-				p.dec = (*Buffer).dec_struct_message
-				p.size = size_struct_message
-			} else {
-				p.enc = (*Buffer).enc_struct_group
-				p.dec = (*Buffer).dec_struct_group
-				p.size = size_struct_group
-			}
 		}
 
 	case reflect.Slice:
-		switch t2 := t1.Elem(); t2.Kind() {
-		default:
-			logNoSliceEnc(t1, t2)
-			break
-		case reflect.Bool:
-			if p.Packed {
-				p.enc = (*Buffer).enc_slice_packed_bool
-				p.size = size_slice_packed_bool
-			} else {
-				p.enc = (*Buffer).enc_slice_bool
-				p.size = size_slice_bool
-			}
-			p.dec = (*Buffer).dec_slice_bool
-			p.packedDec = (*Buffer).dec_slice_packed_bool
-		case reflect.Int32:
-			if p.Packed {
-				p.enc = (*Buffer).enc_slice_packed_int32
-				p.size = size_slice_packed_int32
-			} else {
-				p.enc = (*Buffer).enc_slice_int32
-				p.size = size_slice_int32
-			}
-			p.dec = (*Buffer).dec_slice_int32
-			p.packedDec = (*Buffer).dec_slice_packed_int32
-		case reflect.Uint32:
-			if p.Packed {
-				p.enc = (*Buffer).enc_slice_packed_uint32
-				p.size = size_slice_packed_uint32
-			} else {
-				p.enc = (*Buffer).enc_slice_uint32
-				p.size = size_slice_uint32
-			}
-			p.dec = (*Buffer).dec_slice_int32
-			p.packedDec = (*Buffer).dec_slice_packed_int32
-		case reflect.Int64, reflect.Uint64:
-			if p.Packed {
-				p.enc = (*Buffer).enc_slice_packed_int64
-				p.size = size_slice_packed_int64
-			} else {
-				p.enc = (*Buffer).enc_slice_int64
-				p.size = size_slice_int64
-			}
-			p.dec = (*Buffer).dec_slice_int64
-			p.packedDec = (*Buffer).dec_slice_packed_int64
-		case reflect.Uint8:
-			p.dec = (*Buffer).dec_slice_byte
-			if p.proto3 {
-				p.enc = (*Buffer).enc_proto3_slice_byte
-				p.size = size_proto3_slice_byte
-			} else {
-				p.enc = (*Buffer).enc_slice_byte
-				p.size = size_slice_byte
-			}
-		case reflect.Float32, reflect.Float64:
-			switch t2.Bits() {
-			case 32:
-				// can just treat them as bits
-				if p.Packed {
-					p.enc = (*Buffer).enc_slice_packed_uint32
-					p.size = size_slice_packed_uint32
-				} else {
-					p.enc = (*Buffer).enc_slice_uint32
-					p.size = size_slice_uint32
-				}
-				p.dec = (*Buffer).dec_slice_int32
-				p.packedDec = (*Buffer).dec_slice_packed_int32
-			case 64:
-				// can just treat them as bits
-				if p.Packed {
-					p.enc = (*Buffer).enc_slice_packed_int64
-					p.size = size_slice_packed_int64
-				} else {
-					p.enc = (*Buffer).enc_slice_int64
-					p.size = size_slice_int64
-				}
-				p.dec = (*Buffer).dec_slice_int64
-				p.packedDec = (*Buffer).dec_slice_packed_int64
-			default:
-				logNoSliceEnc(t1, t2)
-				break
-			}
-		case reflect.String:
-			p.enc = (*Buffer).enc_slice_string
-			p.dec = (*Buffer).dec_slice_string
-			p.size = size_slice_string
-		case reflect.Ptr:
-			switch t3 := t2.Elem(); t3.Kind() {
-			default:
-				fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3)
-				break
-			case reflect.Struct:
-				p.stype = t2.Elem()
-				p.isMarshaler = isMarshaler(t2)
-				p.isUnmarshaler = isUnmarshaler(t2)
-				if p.Wire == "bytes" {
-					p.enc = (*Buffer).enc_slice_struct_message
-					p.dec = (*Buffer).dec_slice_struct_message
-					p.size = size_slice_struct_message
-				} else {
-					p.enc = (*Buffer).enc_slice_struct_group
-					p.dec = (*Buffer).dec_slice_struct_group
-					p.size = size_slice_struct_group
-				}
-			}
-		case reflect.Slice:
-			switch t2.Elem().Kind() {
-			default:
-				fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem())
-				break
-			case reflect.Uint8:
-				p.enc = (*Buffer).enc_slice_slice_byte
-				p.dec = (*Buffer).dec_slice_slice_byte
-				p.size = size_slice_slice_byte
-			}
+		if t2 := t1.Elem(); t2.Kind() == reflect.Ptr && t2.Elem().Kind() == reflect.Struct {
+			p.stype = t2.Elem()
 		}
 
 	case reflect.Map:
-		p.enc = (*Buffer).enc_new_map
-		p.dec = (*Buffer).dec_new_map
-		p.size = size_new_map
-
 		p.mtype = t1
-		p.mkeyprop = &Properties{}
-		p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
-		p.mvalprop = &Properties{}
+		p.MapKeyProp = &Properties{}
+		p.MapKeyProp.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
+		p.MapValProp = &Properties{}
 		vtype := p.mtype.Elem()
 		if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice {
 			// The value type is not a message (*T) or bytes ([]byte),
 			// so we need encoders for the pointer to this type.
 			vtype = reflect.PtrTo(vtype)
 		}
-		p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
-	}
-
-	// precalculate tag code
-	wire := p.WireType
-	if p.Packed {
-		wire = WireBytes
+		p.MapValProp.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
 	}
-	x := uint32(p.Tag)<<3 | uint32(wire)
-	i := 0
-	for i = 0; x > 127; i++ {
-		p.tagbuf[i] = 0x80 | uint8(x&0x7F)
-		x >>= 7
-	}
-	p.tagbuf[i] = uint8(x)
-	p.tagcode = p.tagbuf[0 : i+1]
 
 	if p.stype != nil {
 		if lockGetProp {
@@ -586,32 +296,9 @@ func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lock
 }
 
 var (
-	marshalerType   = reflect.TypeOf((*Marshaler)(nil)).Elem()
-	unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
+	marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
 )
 
-// isMarshaler reports whether type t implements Marshaler.
-func isMarshaler(t reflect.Type) bool {
-	// We're checking for (likely) pointer-receiver methods
-	// so if t is not a pointer, something is very wrong.
-	// The calls above only invoke isMarshaler on pointer types.
-	if t.Kind() != reflect.Ptr {
-		panic("proto: misuse of isMarshaler")
-	}
-	return t.Implements(marshalerType)
-}
-
-// isUnmarshaler reports whether type t implements Unmarshaler.
-func isUnmarshaler(t reflect.Type) bool {
-	// We're checking for (likely) pointer-receiver methods
-	// so if t is not a pointer, something is very wrong.
-	// The calls above only invoke isUnmarshaler on pointer types.
-	if t.Kind() != reflect.Ptr {
-		panic("proto: misuse of isUnmarshaler")
-	}
-	return t.Implements(unmarshalerType)
-}
-
 // Init populates the properties from a protocol buffer struct tag.
 func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
 	p.init(typ, name, tag, f, true)
@@ -621,14 +308,11 @@ func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructF
 	// "bytes,49,opt,def=hello!"
 	p.Name = name
 	p.OrigName = name
-	if f != nil {
-		p.field = toField(f)
-	}
 	if tag == "" {
 		return
 	}
 	p.Parse(tag)
-	p.setEncAndDec(typ, f, lockGetProp)
+	p.setFieldProps(typ, f, lockGetProp)
 }
 
 var (
@@ -649,9 +333,6 @@ func GetProperties(t reflect.Type) *StructProperties {
 	sprop, ok := propertiesMap[t]
 	propertiesMu.RUnlock()
 	if ok {
-		if collectStats {
-			stats.Chit++
-		}
 		return sprop
 	}
 
@@ -661,26 +342,26 @@ func GetProperties(t reflect.Type) *StructProperties {
 	return sprop
 }
 
+type (
+	oneofFuncsIface interface {
+		XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
+	}
+	oneofWrappersIface interface {
+		XXX_OneofWrappers() []interface{}
+	}
+)
+
 // getPropertiesLocked requires that propertiesMu is held.
 func getPropertiesLocked(t reflect.Type) *StructProperties {
 	if prop, ok := propertiesMap[t]; ok {
-		if collectStats {
-			stats.Chit++
-		}
 		return prop
 	}
-	if collectStats {
-		stats.Cmiss++
-	}
 
 	prop := new(StructProperties)
 	// in case of recursive protos, fill this in now.
 	propertiesMap[t] = prop
 
 	// build properties
-	prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) ||
-		reflect.PtrTo(t).Implements(extendableProtoV1Type)
-	prop.unrecField = invalidField
 	prop.Prop = make([]*Properties, t.NumField())
 	prop.order = make([]int, t.NumField())
 
@@ -690,17 +371,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
 		name := f.Name
 		p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
 
-		if f.Name == "XXX_InternalExtensions" { // special case
-			p.enc = (*Buffer).enc_exts
-			p.dec = nil // not needed
-			p.size = size_exts
-		} else if f.Name == "XXX_extensions" { // special case
-			p.enc = (*Buffer).enc_map
-			p.dec = nil // not needed
-			p.size = size_map
-		} else if f.Name == "XXX_unrecognized" { // special case
-			prop.unrecField = toField(&f)
-		}
 		oneof := f.Tag.Get("protobuf_oneof") // special case
 		if oneof != "" {
 			// Oneof fields don't use the traditional protobuf tag.
@@ -715,22 +385,19 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
 			}
 			print("\n")
 		}
-		if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && oneof == "" {
-			fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]")
-		}
 	}
 
 	// Re-order prop.order.
 	sort.Sort(prop)
 
-	type oneofMessage interface {
-		XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
+	var oots []interface{}
+	switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
+	case oneofFuncsIface:
+		_, _, _, oots = m.XXX_OneofFuncs()
+	case oneofWrappersIface:
+		oots = m.XXX_OneofWrappers()
 	}
-	if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
-		var oots []interface{}
-		prop.oneofMarshaler, prop.oneofUnmarshaler, prop.oneofSizer, oots = om.XXX_OneofFuncs()
-		prop.stype = t
-
+	if len(oots) > 0 {
 		// Interpret oneof metadata.
 		prop.OneofTypes = make(map[string]*OneofProperties)
 		for _, oot := range oots {
@@ -779,30 +446,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
 	return prop
 }
 
-// Return the Properties object for the x[0]'th field of the structure.
-func propByIndex(t reflect.Type, x []int) *Properties {
-	if len(x) != 1 {
-		fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t)
-		return nil
-	}
-	prop := GetProperties(t)
-	return prop.Prop[x[0]]
-}
-
-// Get the address and type of a pointer to a struct from an interface.
-func getbase(pb Message) (t reflect.Type, b structPointer, err error) {
-	if pb == nil {
-		err = ErrNil
-		return
-	}
-	// get the reflect type of the pointer to the struct.
-	t = reflect.TypeOf(pb)
-	// get the address of the struct.
-	value := reflect.ValueOf(pb)
-	b = toStructPointer(value)
-	return
-}
-
 // A global registry of enum types.
 // The generated code will register the generated maps by calling RegisterEnum.
 
@@ -826,20 +469,42 @@ func EnumValueMap(enumType string) map[string]int32 {
 // A registry of all linked message types.
 // The string is a fully-qualified proto name ("pkg.Message").
 var (
-	protoTypes    = make(map[string]reflect.Type)
-	revProtoTypes = make(map[reflect.Type]string)
+	protoTypedNils = make(map[string]Message)      // a map from proto names to typed nil pointers
+	protoMapTypes  = make(map[string]reflect.Type) // a map from proto names to map types
+	revProtoTypes  = make(map[reflect.Type]string)
 )
 
 // RegisterType is called from generated code and maps from the fully qualified
 // proto name to the type (pointer to struct) of the protocol buffer.
 func RegisterType(x Message, name string) {
-	if _, ok := protoTypes[name]; ok {
+	if _, ok := protoTypedNils[name]; ok {
 		// TODO: Some day, make this a panic.
 		log.Printf("proto: duplicate proto type registered: %s", name)
 		return
 	}
 	t := reflect.TypeOf(x)
-	protoTypes[name] = t
+	if v := reflect.ValueOf(x); v.Kind() == reflect.Ptr && v.Pointer() == 0 {
+		// Generated code always calls RegisterType with nil x.
+		// This check is just for extra safety.
+		protoTypedNils[name] = x
+	} else {
+		protoTypedNils[name] = reflect.Zero(t).Interface().(Message)
+	}
+	revProtoTypes[t] = name
+}
+
+// RegisterMapType is called from generated code and maps from the fully qualified
+// proto name to the native map type of the proto map definition.
+func RegisterMapType(x interface{}, name string) {
+	if reflect.TypeOf(x).Kind() != reflect.Map {
+		panic(fmt.Sprintf("RegisterMapType(%T, %q); want map", x, name))
+	}
+	if _, ok := protoMapTypes[name]; ok {
+		log.Printf("proto: duplicate proto type registered: %s", name)
+		return
+	}
+	t := reflect.TypeOf(x)
+	protoMapTypes[name] = t
 	revProtoTypes[t] = name
 }
 
@@ -855,7 +520,14 @@ func MessageName(x Message) string {
 }
 
 // MessageType returns the message type (pointer to struct) for a named message.
-func MessageType(name string) reflect.Type { return protoTypes[name] }
+// The type is not guaranteed to implement proto.Message if the name refers to a
+// map entry.
+func MessageType(name string) reflect.Type {
+	if t, ok := protoTypedNils[name]; ok {
+		return reflect.TypeOf(t)
+	}
+	return protoMapTypes[name]
+}
 
 // A registry of all linked proto files.
 var (

+ 2776 - 0
vendor/github.com/golang/protobuf/proto/table_marshal.go

@@ -0,0 +1,2776 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors.  All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+import (
+	"errors"
+	"fmt"
+	"math"
+	"reflect"
+	"sort"
+	"strconv"
+	"strings"
+	"sync"
+	"sync/atomic"
+	"unicode/utf8"
+)
+
+// a sizer takes a pointer to a field and the size of its tag, computes the size of
+// the encoded data.
+type sizer func(pointer, int) int
+
+// a marshaler takes a byte slice, a pointer to a field, and its tag (in wire format),
+// marshals the field to the end of the slice, returns the slice and error (if any).
+type marshaler func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error)
+
+// marshalInfo is the information used for marshaling a message.
+type marshalInfo struct {
+	typ          reflect.Type
+	fields       []*marshalFieldInfo
+	unrecognized field                      // offset of XXX_unrecognized
+	extensions   field                      // offset of XXX_InternalExtensions
+	v1extensions field                      // offset of XXX_extensions
+	sizecache    field                      // offset of XXX_sizecache
+	initialized  int32                      // 0 -- only typ is set, 1 -- fully initialized
+	messageset   bool                       // uses message set wire format
+	hasmarshaler bool                       // has custom marshaler
+	sync.RWMutex                            // protect extElems map, also for initialization
+	extElems     map[int32]*marshalElemInfo // info of extension elements
+}
+
+// marshalFieldInfo is the information used for marshaling a field of a message.
+type marshalFieldInfo struct {
+	field      field
+	wiretag    uint64 // tag in wire format
+	tagsize    int    // size of tag in wire format
+	sizer      sizer
+	marshaler  marshaler
+	isPointer  bool
+	required   bool                              // field is required
+	name       string                            // name of the field, for error reporting
+	oneofElems map[reflect.Type]*marshalElemInfo // info of oneof elements
+}
+
+// marshalElemInfo is the information used for marshaling an extension or oneof element.
+type marshalElemInfo struct {
+	wiretag   uint64 // tag in wire format
+	tagsize   int    // size of tag in wire format
+	sizer     sizer
+	marshaler marshaler
+	isptr     bool // elem is pointer typed, thus interface of this type is a direct interface (extension only)
+	deref     bool // dereference the pointer before operating on it; implies isptr
+}
+
+var (
+	marshalInfoMap  = map[reflect.Type]*marshalInfo{}
+	marshalInfoLock sync.Mutex
+)
+
+// getMarshalInfo returns the information to marshal a given type of message.
+// The info it returns may not necessarily initialized.
+// t is the type of the message (NOT the pointer to it).
+func getMarshalInfo(t reflect.Type) *marshalInfo {
+	marshalInfoLock.Lock()
+	u, ok := marshalInfoMap[t]
+	if !ok {
+		u = &marshalInfo{typ: t}
+		marshalInfoMap[t] = u
+	}
+	marshalInfoLock.Unlock()
+	return u
+}
+
+// Size is the entry point from generated code,
+// and should be ONLY called by generated code.
+// It computes the size of encoded data of msg.
+// a is a pointer to a place to store cached marshal info.
+func (a *InternalMessageInfo) Size(msg Message) int {
+	u := getMessageMarshalInfo(msg, a)
+	ptr := toPointer(&msg)
+	if ptr.isNil() {
+		// We get here if msg is a typed nil ((*SomeMessage)(nil)),
+		// so it satisfies the interface, and msg == nil wouldn't
+		// catch it. We don't want crash in this case.
+		return 0
+	}
+	return u.size(ptr)
+}
+
+// Marshal is the entry point from generated code,
+// and should be ONLY called by generated code.
+// It marshals msg to the end of b.
+// a is a pointer to a place to store cached marshal info.
+func (a *InternalMessageInfo) Marshal(b []byte, msg Message, deterministic bool) ([]byte, error) {
+	u := getMessageMarshalInfo(msg, a)
+	ptr := toPointer(&msg)
+	if ptr.isNil() {
+		// We get here if msg is a typed nil ((*SomeMessage)(nil)),
+		// so it satisfies the interface, and msg == nil wouldn't
+		// catch it. We don't want crash in this case.
+		return b, ErrNil
+	}
+	return u.marshal(b, ptr, deterministic)
+}
+
+func getMessageMarshalInfo(msg interface{}, a *InternalMessageInfo) *marshalInfo {
+	// u := a.marshal, but atomically.
+	// We use an atomic here to ensure memory consistency.
+	u := atomicLoadMarshalInfo(&a.marshal)
+	if u == nil {
+		// Get marshal information from type of message.
+		t := reflect.ValueOf(msg).Type()
+		if t.Kind() != reflect.Ptr {
+			panic(fmt.Sprintf("cannot handle non-pointer message type %v", t))
+		}
+		u = getMarshalInfo(t.Elem())
+		// Store it in the cache for later users.
+		// a.marshal = u, but atomically.
+		atomicStoreMarshalInfo(&a.marshal, u)
+	}
+	return u
+}
+
+// size is the main function to compute the size of the encoded data of a message.
+// ptr is the pointer to the message.
+func (u *marshalInfo) size(ptr pointer) int {
+	if atomic.LoadInt32(&u.initialized) == 0 {
+		u.computeMarshalInfo()
+	}
+
+	// If the message can marshal itself, let it do it, for compatibility.
+	// NOTE: This is not efficient.
+	if u.hasmarshaler {
+		m := ptr.asPointerTo(u.typ).Interface().(Marshaler)
+		b, _ := m.Marshal()
+		return len(b)
+	}
+
+	n := 0
+	for _, f := range u.fields {
+		if f.isPointer && ptr.offset(f.field).getPointer().isNil() {
+			// nil pointer always marshals to nothing
+			continue
+		}
+		n += f.sizer(ptr.offset(f.field), f.tagsize)
+	}
+	if u.extensions.IsValid() {
+		e := ptr.offset(u.extensions).toExtensions()
+		if u.messageset {
+			n += u.sizeMessageSet(e)
+		} else {
+			n += u.sizeExtensions(e)
+		}
+	}
+	if u.v1extensions.IsValid() {
+		m := *ptr.offset(u.v1extensions).toOldExtensions()
+		n += u.sizeV1Extensions(m)
+	}
+	if u.unrecognized.IsValid() {
+		s := *ptr.offset(u.unrecognized).toBytes()
+		n += len(s)
+	}
+	// cache the result for use in marshal
+	if u.sizecache.IsValid() {
+		atomic.StoreInt32(ptr.offset(u.sizecache).toInt32(), int32(n))
+	}
+	return n
+}
+
+// cachedsize gets the size from cache. If there is no cache (i.e. message is not generated),
+// fall back to compute the size.
+func (u *marshalInfo) cachedsize(ptr pointer) int {
+	if u.sizecache.IsValid() {
+		return int(atomic.LoadInt32(ptr.offset(u.sizecache).toInt32()))
+	}
+	return u.size(ptr)
+}
+
+// marshal is the main function to marshal a message. It takes a byte slice and appends
+// the encoded data to the end of the slice, returns the slice and error (if any).
+// ptr is the pointer to the message.
+// If deterministic is true, map is marshaled in deterministic order.
+func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte, error) {
+	if atomic.LoadInt32(&u.initialized) == 0 {
+		u.computeMarshalInfo()
+	}
+
+	// If the message can marshal itself, let it do it, for compatibility.
+	// NOTE: This is not efficient.
+	if u.hasmarshaler {
+		m := ptr.asPointerTo(u.typ).Interface().(Marshaler)
+		b1, err := m.Marshal()
+		b = append(b, b1...)
+		return b, err
+	}
+
+	var err, errLater error
+	// The old marshaler encodes extensions at beginning.
+	if u.extensions.IsValid() {
+		e := ptr.offset(u.extensions).toExtensions()
+		if u.messageset {
+			b, err = u.appendMessageSet(b, e, deterministic)
+		} else {
+			b, err = u.appendExtensions(b, e, deterministic)
+		}
+		if err != nil {
+			return b, err
+		}
+	}
+	if u.v1extensions.IsValid() {
+		m := *ptr.offset(u.v1extensions).toOldExtensions()
+		b, err = u.appendV1Extensions(b, m, deterministic)
+		if err != nil {
+			return b, err
+		}
+	}
+	for _, f := range u.fields {
+		if f.required {
+			if ptr.offset(f.field).getPointer().isNil() {
+				// Required field is not set.
+				// We record the error but keep going, to give a complete marshaling.
+				if errLater == nil {
+					errLater = &RequiredNotSetError{f.name}
+				}
+				continue
+			}
+		}
+		if f.isPointer && ptr.offset(f.field).getPointer().isNil() {
+			// nil pointer always marshals to nothing
+			continue
+		}
+		b, err = f.marshaler(b, ptr.offset(f.field), f.wiretag, deterministic)
+		if err != nil {
+			if err1, ok := err.(*RequiredNotSetError); ok {
+				// Required field in submessage is not set.
+				// We record the error but keep going, to give a complete marshaling.
+				if errLater == nil {
+					errLater = &RequiredNotSetError{f.name + "." + err1.field}
+				}
+				continue
+			}
+			if err == errRepeatedHasNil {
+				err = errors.New("proto: repeated field " + f.name + " has nil element")
+			}
+			if err == errInvalidUTF8 {
+				if errLater == nil {
+					fullName := revProtoTypes[reflect.PtrTo(u.typ)] + "." + f.name
+					errLater = &invalidUTF8Error{fullName}
+				}
+				continue
+			}
+			return b, err
+		}
+	}
+	if u.unrecognized.IsValid() {
+		s := *ptr.offset(u.unrecognized).toBytes()
+		b = append(b, s...)
+	}
+	return b, errLater
+}
+
+// computeMarshalInfo initializes the marshal info.
+func (u *marshalInfo) computeMarshalInfo() {
+	u.Lock()
+	defer u.Unlock()
+	if u.initialized != 0 { // non-atomic read is ok as it is protected by the lock
+		return
+	}
+
+	t := u.typ
+	u.unrecognized = invalidField
+	u.extensions = invalidField
+	u.v1extensions = invalidField
+	u.sizecache = invalidField
+
+	// If the message can marshal itself, let it do it, for compatibility.
+	// NOTE: This is not efficient.
+	if reflect.PtrTo(t).Implements(marshalerType) {
+		u.hasmarshaler = true
+		atomic.StoreInt32(&u.initialized, 1)
+		return
+	}
+
+	// get oneof implementers
+	var oneofImplementers []interface{}
+	switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
+	case oneofFuncsIface:
+		_, _, _, oneofImplementers = m.XXX_OneofFuncs()
+	case oneofWrappersIface:
+		oneofImplementers = m.XXX_OneofWrappers()
+	}
+
+	n := t.NumField()
+
+	// deal with XXX fields first
+	for i := 0; i < t.NumField(); i++ {
+		f := t.Field(i)
+		if !strings.HasPrefix(f.Name, "XXX_") {
+			continue
+		}
+		switch f.Name {
+		case "XXX_sizecache":
+			u.sizecache = toField(&f)
+		case "XXX_unrecognized":
+			u.unrecognized = toField(&f)
+		case "XXX_InternalExtensions":
+			u.extensions = toField(&f)
+			u.messageset = f.Tag.Get("protobuf_messageset") == "1"
+		case "XXX_extensions":
+			u.v1extensions = toField(&f)
+		case "XXX_NoUnkeyedLiteral":
+			// nothing to do
+		default:
+			panic("unknown XXX field: " + f.Name)
+		}
+		n--
+	}
+
+	// normal fields
+	fields := make([]marshalFieldInfo, n) // batch allocation
+	u.fields = make([]*marshalFieldInfo, 0, n)
+	for i, j := 0, 0; i < t.NumField(); i++ {
+		f := t.Field(i)
+
+		if strings.HasPrefix(f.Name, "XXX_") {
+			continue
+		}
+		field := &fields[j]
+		j++
+		field.name = f.Name
+		u.fields = append(u.fields, field)
+		if f.Tag.Get("protobuf_oneof") != "" {
+			field.computeOneofFieldInfo(&f, oneofImplementers)
+			continue
+		}
+		if f.Tag.Get("protobuf") == "" {
+			// field has no tag (not in generated message), ignore it
+			u.fields = u.fields[:len(u.fields)-1]
+			j--
+			continue
+		}
+		field.computeMarshalFieldInfo(&f)
+	}
+
+	// fields are marshaled in tag order on the wire.
+	sort.Sort(byTag(u.fields))
+
+	atomic.StoreInt32(&u.initialized, 1)
+}
+
+// helper for sorting fields by tag
+type byTag []*marshalFieldInfo
+
+func (a byTag) Len() int           { return len(a) }
+func (a byTag) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a byTag) Less(i, j int) bool { return a[i].wiretag < a[j].wiretag }
+
+// getExtElemInfo returns the information to marshal an extension element.
+// The info it returns is initialized.
+func (u *marshalInfo) getExtElemInfo(desc *ExtensionDesc) *marshalElemInfo {
+	// get from cache first
+	u.RLock()
+	e, ok := u.extElems[desc.Field]
+	u.RUnlock()
+	if ok {
+		return e
+	}
+
+	t := reflect.TypeOf(desc.ExtensionType) // pointer or slice to basic type or struct
+	tags := strings.Split(desc.Tag, ",")
+	tag, err := strconv.Atoi(tags[1])
+	if err != nil {
+		panic("tag is not an integer")
+	}
+	wt := wiretype(tags[0])
+	if t.Kind() == reflect.Ptr && t.Elem().Kind() != reflect.Struct {
+		t = t.Elem()
+	}
+	sizer, marshaler := typeMarshaler(t, tags, false, false)
+	var deref bool
+	if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 {
+		t = reflect.PtrTo(t)
+		deref = true
+	}
+	e = &marshalElemInfo{
+		wiretag:   uint64(tag)<<3 | wt,
+		tagsize:   SizeVarint(uint64(tag) << 3),
+		sizer:     sizer,
+		marshaler: marshaler,
+		isptr:     t.Kind() == reflect.Ptr,
+		deref:     deref,
+	}
+
+	// update cache
+	u.Lock()
+	if u.extElems == nil {
+		u.extElems = make(map[int32]*marshalElemInfo)
+	}
+	u.extElems[desc.Field] = e
+	u.Unlock()
+	return e
+}
+
+// computeMarshalFieldInfo fills up the information to marshal a field.
+func (fi *marshalFieldInfo) computeMarshalFieldInfo(f *reflect.StructField) {
+	// parse protobuf tag of the field.
+	// tag has format of "bytes,49,opt,name=foo,def=hello!"
+	tags := strings.Split(f.Tag.Get("protobuf"), ",")
+	if tags[0] == "" {
+		return
+	}
+	tag, err := strconv.Atoi(tags[1])
+	if err != nil {
+		panic("tag is not an integer")
+	}
+	wt := wiretype(tags[0])
+	if tags[2] == "req" {
+		fi.required = true
+	}
+	fi.setTag(f, tag, wt)
+	fi.setMarshaler(f, tags)
+}
+
+func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofImplementers []interface{}) {
+	fi.field = toField(f)
+	fi.wiretag = math.MaxInt32 // Use a large tag number, make oneofs sorted at the end. This tag will not appear on the wire.
+	fi.isPointer = true
+	fi.sizer, fi.marshaler = makeOneOfMarshaler(fi, f)
+	fi.oneofElems = make(map[reflect.Type]*marshalElemInfo)
+
+	ityp := f.Type // interface type
+	for _, o := range oneofImplementers {
+		t := reflect.TypeOf(o)
+		if !t.Implements(ityp) {
+			continue
+		}
+		sf := t.Elem().Field(0) // oneof implementer is a struct with a single field
+		tags := strings.Split(sf.Tag.Get("protobuf"), ",")
+		tag, err := strconv.Atoi(tags[1])
+		if err != nil {
+			panic("tag is not an integer")
+		}
+		wt := wiretype(tags[0])
+		sizer, marshaler := typeMarshaler(sf.Type, tags, false, true) // oneof should not omit any zero value
+		fi.oneofElems[t.Elem()] = &marshalElemInfo{
+			wiretag:   uint64(tag)<<3 | wt,
+			tagsize:   SizeVarint(uint64(tag) << 3),
+			sizer:     sizer,
+			marshaler: marshaler,
+		}
+	}
+}
+
+// wiretype returns the wire encoding of the type.
+func wiretype(encoding string) uint64 {
+	switch encoding {
+	case "fixed32":
+		return WireFixed32
+	case "fixed64":
+		return WireFixed64
+	case "varint", "zigzag32", "zigzag64":
+		return WireVarint
+	case "bytes":
+		return WireBytes
+	case "group":
+		return WireStartGroup
+	}
+	panic("unknown wire type " + encoding)
+}
+
+// setTag fills up the tag (in wire format) and its size in the info of a field.
+func (fi *marshalFieldInfo) setTag(f *reflect.StructField, tag int, wt uint64) {
+	fi.field = toField(f)
+	fi.wiretag = uint64(tag)<<3 | wt
+	fi.tagsize = SizeVarint(uint64(tag) << 3)
+}
+
+// setMarshaler fills up the sizer and marshaler in the info of a field.
+func (fi *marshalFieldInfo) setMarshaler(f *reflect.StructField, tags []string) {
+	switch f.Type.Kind() {
+	case reflect.Map:
+		// map field
+		fi.isPointer = true
+		fi.sizer, fi.marshaler = makeMapMarshaler(f)
+		return
+	case reflect.Ptr, reflect.Slice:
+		fi.isPointer = true
+	}
+	fi.sizer, fi.marshaler = typeMarshaler(f.Type, tags, true, false)
+}
+
+// typeMarshaler returns the sizer and marshaler of a given field.
+// t is the type of the field.
+// tags is the generated "protobuf" tag of the field.
+// If nozero is true, zero value is not marshaled to the wire.
+// If oneof is true, it is a oneof field.
+func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, marshaler) {
+	encoding := tags[0]
+
+	pointer := false
+	slice := false
+	if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 {
+		slice = true
+		t = t.Elem()
+	}
+	if t.Kind() == reflect.Ptr {
+		pointer = true
+		t = t.Elem()
+	}
+
+	packed := false
+	proto3 := false
+	validateUTF8 := true
+	for i := 2; i < len(tags); i++ {
+		if tags[i] == "packed" {
+			packed = true
+		}
+		if tags[i] == "proto3" {
+			proto3 = true
+		}
+	}
+	validateUTF8 = validateUTF8 && proto3
+
+	switch t.Kind() {
+	case reflect.Bool:
+		if pointer {
+			return sizeBoolPtr, appendBoolPtr
+		}
+		if slice {
+			if packed {
+				return sizeBoolPackedSlice, appendBoolPackedSlice
+			}
+			return sizeBoolSlice, appendBoolSlice
+		}
+		if nozero {
+			return sizeBoolValueNoZero, appendBoolValueNoZero
+		}
+		return sizeBoolValue, appendBoolValue
+	case reflect.Uint32:
+		switch encoding {
+		case "fixed32":
+			if pointer {
+				return sizeFixed32Ptr, appendFixed32Ptr
+			}
+			if slice {
+				if packed {
+					return sizeFixed32PackedSlice, appendFixed32PackedSlice
+				}
+				return sizeFixed32Slice, appendFixed32Slice
+			}
+			if nozero {
+				return sizeFixed32ValueNoZero, appendFixed32ValueNoZero
+			}
+			return sizeFixed32Value, appendFixed32Value
+		case "varint":
+			if pointer {
+				return sizeVarint32Ptr, appendVarint32Ptr
+			}
+			if slice {
+				if packed {
+					return sizeVarint32PackedSlice, appendVarint32PackedSlice
+				}
+				return sizeVarint32Slice, appendVarint32Slice
+			}
+			if nozero {
+				return sizeVarint32ValueNoZero, appendVarint32ValueNoZero
+			}
+			return sizeVarint32Value, appendVarint32Value
+		}
+	case reflect.Int32:
+		switch encoding {
+		case "fixed32":
+			if pointer {
+				return sizeFixedS32Ptr, appendFixedS32Ptr
+			}
+			if slice {
+				if packed {
+					return sizeFixedS32PackedSlice, appendFixedS32PackedSlice
+				}
+				return sizeFixedS32Slice, appendFixedS32Slice
+			}
+			if nozero {
+				return sizeFixedS32ValueNoZero, appendFixedS32ValueNoZero
+			}
+			return sizeFixedS32Value, appendFixedS32Value
+		case "varint":
+			if pointer {
+				return sizeVarintS32Ptr, appendVarintS32Ptr
+			}
+			if slice {
+				if packed {
+					return sizeVarintS32PackedSlice, appendVarintS32PackedSlice
+				}
+				return sizeVarintS32Slice, appendVarintS32Slice
+			}
+			if nozero {
+				return sizeVarintS32ValueNoZero, appendVarintS32ValueNoZero
+			}
+			return sizeVarintS32Value, appendVarintS32Value
+		case "zigzag32":
+			if pointer {
+				return sizeZigzag32Ptr, appendZigzag32Ptr
+			}
+			if slice {
+				if packed {
+					return sizeZigzag32PackedSlice, appendZigzag32PackedSlice
+				}
+				return sizeZigzag32Slice, appendZigzag32Slice
+			}
+			if nozero {
+				return sizeZigzag32ValueNoZero, appendZigzag32ValueNoZero
+			}
+			return sizeZigzag32Value, appendZigzag32Value
+		}
+	case reflect.Uint64:
+		switch encoding {
+		case "fixed64":
+			if pointer {
+				return sizeFixed64Ptr, appendFixed64Ptr
+			}
+			if slice {
+				if packed {
+					return sizeFixed64PackedSlice, appendFixed64PackedSlice
+				}
+				return sizeFixed64Slice, appendFixed64Slice
+			}
+			if nozero {
+				return sizeFixed64ValueNoZero, appendFixed64ValueNoZero
+			}
+			return sizeFixed64Value, appendFixed64Value
+		case "varint":
+			if pointer {
+				return sizeVarint64Ptr, appendVarint64Ptr
+			}
+			if slice {
+				if packed {
+					return sizeVarint64PackedSlice, appendVarint64PackedSlice
+				}
+				return sizeVarint64Slice, appendVarint64Slice
+			}
+			if nozero {
+				return sizeVarint64ValueNoZero, appendVarint64ValueNoZero
+			}
+			return sizeVarint64Value, appendVarint64Value
+		}
+	case reflect.Int64:
+		switch encoding {
+		case "fixed64":
+			if pointer {
+				return sizeFixedS64Ptr, appendFixedS64Ptr
+			}
+			if slice {
+				if packed {
+					return sizeFixedS64PackedSlice, appendFixedS64PackedSlice
+				}
+				return sizeFixedS64Slice, appendFixedS64Slice
+			}
+			if nozero {
+				return sizeFixedS64ValueNoZero, appendFixedS64ValueNoZero
+			}
+			return sizeFixedS64Value, appendFixedS64Value
+		case "varint":
+			if pointer {
+				return sizeVarintS64Ptr, appendVarintS64Ptr
+			}
+			if slice {
+				if packed {
+					return sizeVarintS64PackedSlice, appendVarintS64PackedSlice
+				}
+				return sizeVarintS64Slice, appendVarintS64Slice
+			}
+			if nozero {
+				return sizeVarintS64ValueNoZero, appendVarintS64ValueNoZero
+			}
+			return sizeVarintS64Value, appendVarintS64Value
+		case "zigzag64":
+			if pointer {
+				return sizeZigzag64Ptr, appendZigzag64Ptr
+			}
+			if slice {
+				if packed {
+					return sizeZigzag64PackedSlice, appendZigzag64PackedSlice
+				}
+				return sizeZigzag64Slice, appendZigzag64Slice
+			}
+			if nozero {
+				return sizeZigzag64ValueNoZero, appendZigzag64ValueNoZero
+			}
+			return sizeZigzag64Value, appendZigzag64Value
+		}
+	case reflect.Float32:
+		if pointer {
+			return sizeFloat32Ptr, appendFloat32Ptr
+		}
+		if slice {
+			if packed {
+				return sizeFloat32PackedSlice, appendFloat32PackedSlice
+			}
+			return sizeFloat32Slice, appendFloat32Slice
+		}
+		if nozero {
+			return sizeFloat32ValueNoZero, appendFloat32ValueNoZero
+		}
+		return sizeFloat32Value, appendFloat32Value
+	case reflect.Float64:
+		if pointer {
+			return sizeFloat64Ptr, appendFloat64Ptr
+		}
+		if slice {
+			if packed {
+				return sizeFloat64PackedSlice, appendFloat64PackedSlice
+			}
+			return sizeFloat64Slice, appendFloat64Slice
+		}
+		if nozero {
+			return sizeFloat64ValueNoZero, appendFloat64ValueNoZero
+		}
+		return sizeFloat64Value, appendFloat64Value
+	case reflect.String:
+		if validateUTF8 {
+			if pointer {
+				return sizeStringPtr, appendUTF8StringPtr
+			}
+			if slice {
+				return sizeStringSlice, appendUTF8StringSlice
+			}
+			if nozero {
+				return sizeStringValueNoZero, appendUTF8StringValueNoZero
+			}
+			return sizeStringValue, appendUTF8StringValue
+		}
+		if pointer {
+			return sizeStringPtr, appendStringPtr
+		}
+		if slice {
+			return sizeStringSlice, appendStringSlice
+		}
+		if nozero {
+			return sizeStringValueNoZero, appendStringValueNoZero
+		}
+		return sizeStringValue, appendStringValue
+	case reflect.Slice:
+		if slice {
+			return sizeBytesSlice, appendBytesSlice
+		}
+		if oneof {
+			// Oneof bytes field may also have "proto3" tag.
+			// We want to marshal it as a oneof field. Do this
+			// check before the proto3 check.
+			return sizeBytesOneof, appendBytesOneof
+		}
+		if proto3 {
+			return sizeBytes3, appendBytes3
+		}
+		return sizeBytes, appendBytes
+	case reflect.Struct:
+		switch encoding {
+		case "group":
+			if slice {
+				return makeGroupSliceMarshaler(getMarshalInfo(t))
+			}
+			return makeGroupMarshaler(getMarshalInfo(t))
+		case "bytes":
+			if slice {
+				return makeMessageSliceMarshaler(getMarshalInfo(t))
+			}
+			return makeMessageMarshaler(getMarshalInfo(t))
+		}
+	}
+	panic(fmt.Sprintf("unknown or mismatched type: type: %v, wire type: %v", t, encoding))
+}
+
+// Below are functions to size/marshal a specific type of a field.
+// They are stored in the field's info, and called by function pointers.
+// They have type sizer or marshaler.
+
+func sizeFixed32Value(_ pointer, tagsize int) int {
+	return 4 + tagsize
+}
+func sizeFixed32ValueNoZero(ptr pointer, tagsize int) int {
+	v := *ptr.toUint32()
+	if v == 0 {
+		return 0
+	}
+	return 4 + tagsize
+}
+func sizeFixed32Ptr(ptr pointer, tagsize int) int {
+	p := *ptr.toUint32Ptr()
+	if p == nil {
+		return 0
+	}
+	return 4 + tagsize
+}
+func sizeFixed32Slice(ptr pointer, tagsize int) int {
+	s := *ptr.toUint32Slice()
+	return (4 + tagsize) * len(s)
+}
+func sizeFixed32PackedSlice(ptr pointer, tagsize int) int {
+	s := *ptr.toUint32Slice()
+	if len(s) == 0 {
+		return 0
+	}
+	return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize
+}
+func sizeFixedS32Value(_ pointer, tagsize int) int {
+	return 4 + tagsize
+}
+func sizeFixedS32ValueNoZero(ptr pointer, tagsize int) int {
+	v := *ptr.toInt32()
+	if v == 0 {
+		return 0
+	}
+	return 4 + tagsize
+}
+func sizeFixedS32Ptr(ptr pointer, tagsize int) int {
+	p := ptr.getInt32Ptr()
+	if p == nil {
+		return 0
+	}
+	return 4 + tagsize
+}
+func sizeFixedS32Slice(ptr pointer, tagsize int) int {
+	s := ptr.getInt32Slice()
+	return (4 + tagsize) * len(s)
+}
+func sizeFixedS32PackedSlice(ptr pointer, tagsize int) int {
+	s := ptr.getInt32Slice()
+	if len(s) == 0 {
+		return 0
+	}
+	return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize
+}
+func sizeFloat32Value(_ pointer, tagsize int) int {
+	return 4 + tagsize
+}
+func sizeFloat32ValueNoZero(ptr pointer, tagsize int) int {
+	v := math.Float32bits(*ptr.toFloat32())
+	if v == 0 {
+		return 0
+	}
+	return 4 + tagsize
+}
+func sizeFloat32Ptr(ptr pointer, tagsize int) int {
+	p := *ptr.toFloat32Ptr()
+	if p == nil {
+		return 0
+	}
+	return 4 + tagsize
+}
+func sizeFloat32Slice(ptr pointer, tagsize int) int {
+	s := *ptr.toFloat32Slice()
+	return (4 + tagsize) * len(s)
+}
+func sizeFloat32PackedSlice(ptr pointer, tagsize int) int {
+	s := *ptr.toFloat32Slice()
+	if len(s) == 0 {
+		return 0
+	}
+	return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize
+}
+func sizeFixed64Value(_ pointer, tagsize int) int {
+	return 8 + tagsize
+}
+func sizeFixed64ValueNoZero(ptr pointer, tagsize int) int {
+	v := *ptr.toUint64()
+	if v == 0 {
+		return 0
+	}
+	return 8 + tagsize
+}
+func sizeFixed64Ptr(ptr pointer, tagsize int) int {
+	p := *ptr.toUint64Ptr()
+	if p == nil {
+		return 0
+	}
+	return 8 + tagsize
+}
+func sizeFixed64Slice(ptr pointer, tagsize int) int {
+	s := *ptr.toUint64Slice()
+	return (8 + tagsize) * len(s)
+}
+func sizeFixed64PackedSlice(ptr pointer, tagsize int) int {
+	s := *ptr.toUint64Slice()
+	if len(s) == 0 {
+		return 0
+	}
+	return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize
+}
+func sizeFixedS64Value(_ pointer, tagsize int) int {
+	return 8 + tagsize
+}
+func sizeFixedS64ValueNoZero(ptr pointer, tagsize int) int {
+	v := *ptr.toInt64()
+	if v == 0 {
+		return 0
+	}
+	return 8 + tagsize
+}
+func sizeFixedS64Ptr(ptr pointer, tagsize int) int {
+	p := *ptr.toInt64Ptr()
+	if p == nil {
+		return 0
+	}
+	return 8 + tagsize
+}
+func sizeFixedS64Slice(ptr pointer, tagsize int) int {
+	s := *ptr.toInt64Slice()
+	return (8 + tagsize) * len(s)
+}
+func sizeFixedS64PackedSlice(ptr pointer, tagsize int) int {
+	s := *ptr.toInt64Slice()
+	if len(s) == 0 {
+		return 0
+	}
+	return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize
+}
+func sizeFloat64Value(_ pointer, tagsize int) int {
+	return 8 + tagsize
+}
+func sizeFloat64ValueNoZero(ptr pointer, tagsize int) int {
+	v := math.Float64bits(*ptr.toFloat64())
+	if v == 0 {
+		return 0
+	}
+	return 8 + tagsize
+}
+func sizeFloat64Ptr(ptr pointer, tagsize int) int {
+	p := *ptr.toFloat64Ptr()
+	if p == nil {
+		return 0
+	}
+	return 8 + tagsize
+}
+func sizeFloat64Slice(ptr pointer, tagsize int) int {
+	s := *ptr.toFloat64Slice()
+	return (8 + tagsize) * len(s)
+}
+func sizeFloat64PackedSlice(ptr pointer, tagsize int) int {
+	s := *ptr.toFloat64Slice()
+	if len(s) == 0 {
+		return 0
+	}
+	return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize
+}
+func sizeVarint32Value(ptr pointer, tagsize int) int {
+	v := *ptr.toUint32()
+	return SizeVarint(uint64(v)) + tagsize
+}
+func sizeVarint32ValueNoZero(ptr pointer, tagsize int) int {
+	v := *ptr.toUint32()
+	if v == 0 {
+		return 0
+	}
+	return SizeVarint(uint64(v)) + tagsize
+}
+func sizeVarint32Ptr(ptr pointer, tagsize int) int {
+	p := *ptr.toUint32Ptr()
+	if p == nil {
+		return 0
+	}
+	return SizeVarint(uint64(*p)) + tagsize
+}
+func sizeVarint32Slice(ptr pointer, tagsize int) int {
+	s := *ptr.toUint32Slice()
+	n := 0
+	for _, v := range s {
+		n += SizeVarint(uint64(v)) + tagsize
+	}
+	return n
+}
+func sizeVarint32PackedSlice(ptr pointer, tagsize int) int {
+	s := *ptr.toUint32Slice()
+	if len(s) == 0 {
+		return 0
+	}
+	n := 0
+	for _, v := range s {
+		n += SizeVarint(uint64(v))
+	}
+	return n + SizeVarint(uint64(n)) + tagsize
+}
+func sizeVarintS32Value(ptr pointer, tagsize int) int {
+	v := *ptr.toInt32()
+	return SizeVarint(uint64(v)) + tagsize
+}
+func sizeVarintS32ValueNoZero(ptr pointer, tagsize int) int {
+	v := *ptr.toInt32()
+	if v == 0 {
+		return 0
+	}
+	return SizeVarint(uint64(v)) + tagsize
+}
+func sizeVarintS32Ptr(ptr pointer, tagsize int) int {
+	p := ptr.getInt32Ptr()
+	if p == nil {
+		return 0
+	}
+	return SizeVarint(uint64(*p)) + tagsize
+}
+func sizeVarintS32Slice(ptr pointer, tagsize int) int {
+	s := ptr.getInt32Slice()
+	n := 0
+	for _, v := range s {
+		n += SizeVarint(uint64(v)) + tagsize
+	}
+	return n
+}
+func sizeVarintS32PackedSlice(ptr pointer, tagsize int) int {
+	s := ptr.getInt32Slice()
+	if len(s) == 0 {
+		return 0
+	}
+	n := 0
+	for _, v := range s {
+		n += SizeVarint(uint64(v))
+	}
+	return n + SizeVarint(uint64(n)) + tagsize
+}
+func sizeVarint64Value(ptr pointer, tagsize int) int {
+	v := *ptr.toUint64()
+	return SizeVarint(v) + tagsize
+}
+func sizeVarint64ValueNoZero(ptr pointer, tagsize int) int {
+	v := *ptr.toUint64()
+	if v == 0 {
+		return 0
+	}
+	return SizeVarint(v) + tagsize
+}
+func sizeVarint64Ptr(ptr pointer, tagsize int) int {
+	p := *ptr.toUint64Ptr()
+	if p == nil {
+		return 0
+	}
+	return SizeVarint(*p) + tagsize
+}
+func sizeVarint64Slice(ptr pointer, tagsize int) int {
+	s := *ptr.toUint64Slice()
+	n := 0
+	for _, v := range s {
+		n += SizeVarint(v) + tagsize
+	}
+	return n
+}
+func sizeVarint64PackedSlice(ptr pointer, tagsize int) int {
+	s := *ptr.toUint64Slice()
+	if len(s) == 0 {
+		return 0
+	}
+	n := 0
+	for _, v := range s {
+		n += SizeVarint(v)
+	}
+	return n + SizeVarint(uint64(n)) + tagsize
+}
+func sizeVarintS64Value(ptr pointer, tagsize int) int {
+	v := *ptr.toInt64()
+	return SizeVarint(uint64(v)) + tagsize
+}
+func sizeVarintS64ValueNoZero(ptr pointer, tagsize int) int {
+	v := *ptr.toInt64()
+	if v == 0 {
+		return 0
+	}
+	return SizeVarint(uint64(v)) + tagsize
+}
+func sizeVarintS64Ptr(ptr pointer, tagsize int) int {
+	p := *ptr.toInt64Ptr()
+	if p == nil {
+		return 0
+	}
+	return SizeVarint(uint64(*p)) + tagsize
+}
+func sizeVarintS64Slice(ptr pointer, tagsize int) int {
+	s := *ptr.toInt64Slice()
+	n := 0
+	for _, v := range s {
+		n += SizeVarint(uint64(v)) + tagsize
+	}
+	return n
+}
+func sizeVarintS64PackedSlice(ptr pointer, tagsize int) int {
+	s := *ptr.toInt64Slice()
+	if len(s) == 0 {
+		return 0
+	}
+	n := 0
+	for _, v := range s {
+		n += SizeVarint(uint64(v))
+	}
+	return n + SizeVarint(uint64(n)) + tagsize
+}
+func sizeZigzag32Value(ptr pointer, tagsize int) int {
+	v := *ptr.toInt32()
+	return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize
+}
+func sizeZigzag32ValueNoZero(ptr pointer, tagsize int) int {
+	v := *ptr.toInt32()
+	if v == 0 {
+		return 0
+	}
+	return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize
+}
+func sizeZigzag32Ptr(ptr pointer, tagsize int) int {
+	p := ptr.getInt32Ptr()
+	if p == nil {
+		return 0
+	}
+	v := *p
+	return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize
+}
+func sizeZigzag32Slice(ptr pointer, tagsize int) int {
+	s := ptr.getInt32Slice()
+	n := 0
+	for _, v := range s {
+		n += SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize
+	}
+	return n
+}
+func sizeZigzag32PackedSlice(ptr pointer, tagsize int) int {
+	s := ptr.getInt32Slice()
+	if len(s) == 0 {
+		return 0
+	}
+	n := 0
+	for _, v := range s {
+		n += SizeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31))))
+	}
+	return n + SizeVarint(uint64(n)) + tagsize
+}
+func sizeZigzag64Value(ptr pointer, tagsize int) int {
+	v := *ptr.toInt64()
+	return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize
+}
+func sizeZigzag64ValueNoZero(ptr pointer, tagsize int) int {
+	v := *ptr.toInt64()
+	if v == 0 {
+		return 0
+	}
+	return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize
+}
+func sizeZigzag64Ptr(ptr pointer, tagsize int) int {
+	p := *ptr.toInt64Ptr()
+	if p == nil {
+		return 0
+	}
+	v := *p
+	return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize
+}
+func sizeZigzag64Slice(ptr pointer, tagsize int) int {
+	s := *ptr.toInt64Slice()
+	n := 0
+	for _, v := range s {
+		n += SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize
+	}
+	return n
+}
+func sizeZigzag64PackedSlice(ptr pointer, tagsize int) int {
+	s := *ptr.toInt64Slice()
+	if len(s) == 0 {
+		return 0
+	}
+	n := 0
+	for _, v := range s {
+		n += SizeVarint(uint64(v<<1) ^ uint64((int64(v) >> 63)))
+	}
+	return n + SizeVarint(uint64(n)) + tagsize
+}
+func sizeBoolValue(_ pointer, tagsize int) int {
+	return 1 + tagsize
+}
+func sizeBoolValueNoZero(ptr pointer, tagsize int) int {
+	v := *ptr.toBool()
+	if !v {
+		return 0
+	}
+	return 1 + tagsize
+}
+func sizeBoolPtr(ptr pointer, tagsize int) int {
+	p := *ptr.toBoolPtr()
+	if p == nil {
+		return 0
+	}
+	return 1 + tagsize
+}
+func sizeBoolSlice(ptr pointer, tagsize int) int {
+	s := *ptr.toBoolSlice()
+	return (1 + tagsize) * len(s)
+}
+func sizeBoolPackedSlice(ptr pointer, tagsize int) int {
+	s := *ptr.toBoolSlice()
+	if len(s) == 0 {
+		return 0
+	}
+	return len(s) + SizeVarint(uint64(len(s))) + tagsize
+}
+func sizeStringValue(ptr pointer, tagsize int) int {
+	v := *ptr.toString()
+	return len(v) + SizeVarint(uint64(len(v))) + tagsize
+}
+func sizeStringValueNoZero(ptr pointer, tagsize int) int {
+	v := *ptr.toString()
+	if v == "" {
+		return 0
+	}
+	return len(v) + SizeVarint(uint64(len(v))) + tagsize
+}
+func sizeStringPtr(ptr pointer, tagsize int) int {
+	p := *ptr.toStringPtr()
+	if p == nil {
+		return 0
+	}
+	v := *p
+	return len(v) + SizeVarint(uint64(len(v))) + tagsize
+}
+func sizeStringSlice(ptr pointer, tagsize int) int {
+	s := *ptr.toStringSlice()
+	n := 0
+	for _, v := range s {
+		n += len(v) + SizeVarint(uint64(len(v))) + tagsize
+	}
+	return n
+}
+func sizeBytes(ptr pointer, tagsize int) int {
+	v := *ptr.toBytes()
+	if v == nil {
+		return 0
+	}
+	return len(v) + SizeVarint(uint64(len(v))) + tagsize
+}
+func sizeBytes3(ptr pointer, tagsize int) int {
+	v := *ptr.toBytes()
+	if len(v) == 0 {
+		return 0
+	}
+	return len(v) + SizeVarint(uint64(len(v))) + tagsize
+}
+func sizeBytesOneof(ptr pointer, tagsize int) int {
+	v := *ptr.toBytes()
+	return len(v) + SizeVarint(uint64(len(v))) + tagsize
+}
+func sizeBytesSlice(ptr pointer, tagsize int) int {
+	s := *ptr.toBytesSlice()
+	n := 0
+	for _, v := range s {
+		n += len(v) + SizeVarint(uint64(len(v))) + tagsize
+	}
+	return n
+}
+
+// appendFixed32 appends an encoded fixed32 to b.
+func appendFixed32(b []byte, v uint32) []byte {
+	b = append(b,
+		byte(v),
+		byte(v>>8),
+		byte(v>>16),
+		byte(v>>24))
+	return b
+}
+
+// appendFixed64 appends an encoded fixed64 to b.
+func appendFixed64(b []byte, v uint64) []byte {
+	b = append(b,
+		byte(v),
+		byte(v>>8),
+		byte(v>>16),
+		byte(v>>24),
+		byte(v>>32),
+		byte(v>>40),
+		byte(v>>48),
+		byte(v>>56))
+	return b
+}
+
+// appendVarint appends an encoded varint to b.
+func appendVarint(b []byte, v uint64) []byte {
+	// TODO: make 1-byte (maybe 2-byte) case inline-able, once we
+	// have non-leaf inliner.
+	switch {
+	case v < 1<<7:
+		b = append(b, byte(v))
+	case v < 1<<14:
+		b = append(b,
+			byte(v&0x7f|0x80),
+			byte(v>>7))
+	case v < 1<<21:
+		b = append(b,
+			byte(v&0x7f|0x80),
+			byte((v>>7)&0x7f|0x80),
+			byte(v>>14))
+	case v < 1<<28:
+		b = append(b,
+			byte(v&0x7f|0x80),
+			byte((v>>7)&0x7f|0x80),
+			byte((v>>14)&0x7f|0x80),
+			byte(v>>21))
+	case v < 1<<35:
+		b = append(b,
+			byte(v&0x7f|0x80),
+			byte((v>>7)&0x7f|0x80),
+			byte((v>>14)&0x7f|0x80),
+			byte((v>>21)&0x7f|0x80),
+			byte(v>>28))
+	case v < 1<<42:
+		b = append(b,
+			byte(v&0x7f|0x80),
+			byte((v>>7)&0x7f|0x80),
+			byte((v>>14)&0x7f|0x80),
+			byte((v>>21)&0x7f|0x80),
+			byte((v>>28)&0x7f|0x80),
+			byte(v>>35))
+	case v < 1<<49:
+		b = append(b,
+			byte(v&0x7f|0x80),
+			byte((v>>7)&0x7f|0x80),
+			byte((v>>14)&0x7f|0x80),
+			byte((v>>21)&0x7f|0x80),
+			byte((v>>28)&0x7f|0x80),
+			byte((v>>35)&0x7f|0x80),
+			byte(v>>42))
+	case v < 1<<56:
+		b = append(b,
+			byte(v&0x7f|0x80),
+			byte((v>>7)&0x7f|0x80),
+			byte((v>>14)&0x7f|0x80),
+			byte((v>>21)&0x7f|0x80),
+			byte((v>>28)&0x7f|0x80),
+			byte((v>>35)&0x7f|0x80),
+			byte((v>>42)&0x7f|0x80),
+			byte(v>>49))
+	case v < 1<<63:
+		b = append(b,
+			byte(v&0x7f|0x80),
+			byte((v>>7)&0x7f|0x80),
+			byte((v>>14)&0x7f|0x80),
+			byte((v>>21)&0x7f|0x80),
+			byte((v>>28)&0x7f|0x80),
+			byte((v>>35)&0x7f|0x80),
+			byte((v>>42)&0x7f|0x80),
+			byte((v>>49)&0x7f|0x80),
+			byte(v>>56))
+	default:
+		b = append(b,
+			byte(v&0x7f|0x80),
+			byte((v>>7)&0x7f|0x80),
+			byte((v>>14)&0x7f|0x80),
+			byte((v>>21)&0x7f|0x80),
+			byte((v>>28)&0x7f|0x80),
+			byte((v>>35)&0x7f|0x80),
+			byte((v>>42)&0x7f|0x80),
+			byte((v>>49)&0x7f|0x80),
+			byte((v>>56)&0x7f|0x80),
+			1)
+	}
+	return b
+}
+
+func appendFixed32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toUint32()
+	b = appendVarint(b, wiretag)
+	b = appendFixed32(b, v)
+	return b, nil
+}
+func appendFixed32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toUint32()
+	if v == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendFixed32(b, v)
+	return b, nil
+}
+func appendFixed32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	p := *ptr.toUint32Ptr()
+	if p == nil {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendFixed32(b, *p)
+	return b, nil
+}
+func appendFixed32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toUint32Slice()
+	for _, v := range s {
+		b = appendVarint(b, wiretag)
+		b = appendFixed32(b, v)
+	}
+	return b, nil
+}
+func appendFixed32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toUint32Slice()
+	if len(s) == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag&^7|WireBytes)
+	b = appendVarint(b, uint64(4*len(s)))
+	for _, v := range s {
+		b = appendFixed32(b, v)
+	}
+	return b, nil
+}
+func appendFixedS32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toInt32()
+	b = appendVarint(b, wiretag)
+	b = appendFixed32(b, uint32(v))
+	return b, nil
+}
+func appendFixedS32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toInt32()
+	if v == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendFixed32(b, uint32(v))
+	return b, nil
+}
+func appendFixedS32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	p := ptr.getInt32Ptr()
+	if p == nil {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendFixed32(b, uint32(*p))
+	return b, nil
+}
+func appendFixedS32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := ptr.getInt32Slice()
+	for _, v := range s {
+		b = appendVarint(b, wiretag)
+		b = appendFixed32(b, uint32(v))
+	}
+	return b, nil
+}
+func appendFixedS32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := ptr.getInt32Slice()
+	if len(s) == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag&^7|WireBytes)
+	b = appendVarint(b, uint64(4*len(s)))
+	for _, v := range s {
+		b = appendFixed32(b, uint32(v))
+	}
+	return b, nil
+}
+func appendFloat32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := math.Float32bits(*ptr.toFloat32())
+	b = appendVarint(b, wiretag)
+	b = appendFixed32(b, v)
+	return b, nil
+}
+func appendFloat32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := math.Float32bits(*ptr.toFloat32())
+	if v == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendFixed32(b, v)
+	return b, nil
+}
+func appendFloat32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	p := *ptr.toFloat32Ptr()
+	if p == nil {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendFixed32(b, math.Float32bits(*p))
+	return b, nil
+}
+func appendFloat32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toFloat32Slice()
+	for _, v := range s {
+		b = appendVarint(b, wiretag)
+		b = appendFixed32(b, math.Float32bits(v))
+	}
+	return b, nil
+}
+func appendFloat32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toFloat32Slice()
+	if len(s) == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag&^7|WireBytes)
+	b = appendVarint(b, uint64(4*len(s)))
+	for _, v := range s {
+		b = appendFixed32(b, math.Float32bits(v))
+	}
+	return b, nil
+}
+func appendFixed64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toUint64()
+	b = appendVarint(b, wiretag)
+	b = appendFixed64(b, v)
+	return b, nil
+}
+func appendFixed64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toUint64()
+	if v == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendFixed64(b, v)
+	return b, nil
+}
+func appendFixed64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	p := *ptr.toUint64Ptr()
+	if p == nil {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendFixed64(b, *p)
+	return b, nil
+}
+func appendFixed64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toUint64Slice()
+	for _, v := range s {
+		b = appendVarint(b, wiretag)
+		b = appendFixed64(b, v)
+	}
+	return b, nil
+}
+func appendFixed64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toUint64Slice()
+	if len(s) == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag&^7|WireBytes)
+	b = appendVarint(b, uint64(8*len(s)))
+	for _, v := range s {
+		b = appendFixed64(b, v)
+	}
+	return b, nil
+}
+func appendFixedS64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toInt64()
+	b = appendVarint(b, wiretag)
+	b = appendFixed64(b, uint64(v))
+	return b, nil
+}
+func appendFixedS64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toInt64()
+	if v == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendFixed64(b, uint64(v))
+	return b, nil
+}
+func appendFixedS64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	p := *ptr.toInt64Ptr()
+	if p == nil {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendFixed64(b, uint64(*p))
+	return b, nil
+}
+func appendFixedS64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toInt64Slice()
+	for _, v := range s {
+		b = appendVarint(b, wiretag)
+		b = appendFixed64(b, uint64(v))
+	}
+	return b, nil
+}
+func appendFixedS64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toInt64Slice()
+	if len(s) == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag&^7|WireBytes)
+	b = appendVarint(b, uint64(8*len(s)))
+	for _, v := range s {
+		b = appendFixed64(b, uint64(v))
+	}
+	return b, nil
+}
+func appendFloat64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := math.Float64bits(*ptr.toFloat64())
+	b = appendVarint(b, wiretag)
+	b = appendFixed64(b, v)
+	return b, nil
+}
+func appendFloat64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := math.Float64bits(*ptr.toFloat64())
+	if v == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendFixed64(b, v)
+	return b, nil
+}
+func appendFloat64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	p := *ptr.toFloat64Ptr()
+	if p == nil {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendFixed64(b, math.Float64bits(*p))
+	return b, nil
+}
+func appendFloat64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toFloat64Slice()
+	for _, v := range s {
+		b = appendVarint(b, wiretag)
+		b = appendFixed64(b, math.Float64bits(v))
+	}
+	return b, nil
+}
+func appendFloat64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toFloat64Slice()
+	if len(s) == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag&^7|WireBytes)
+	b = appendVarint(b, uint64(8*len(s)))
+	for _, v := range s {
+		b = appendFixed64(b, math.Float64bits(v))
+	}
+	return b, nil
+}
+func appendVarint32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toUint32()
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64(v))
+	return b, nil
+}
+func appendVarint32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toUint32()
+	if v == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64(v))
+	return b, nil
+}
+func appendVarint32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	p := *ptr.toUint32Ptr()
+	if p == nil {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64(*p))
+	return b, nil
+}
+func appendVarint32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toUint32Slice()
+	for _, v := range s {
+		b = appendVarint(b, wiretag)
+		b = appendVarint(b, uint64(v))
+	}
+	return b, nil
+}
+func appendVarint32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toUint32Slice()
+	if len(s) == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag&^7|WireBytes)
+	// compute size
+	n := 0
+	for _, v := range s {
+		n += SizeVarint(uint64(v))
+	}
+	b = appendVarint(b, uint64(n))
+	for _, v := range s {
+		b = appendVarint(b, uint64(v))
+	}
+	return b, nil
+}
+func appendVarintS32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toInt32()
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64(v))
+	return b, nil
+}
+func appendVarintS32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toInt32()
+	if v == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64(v))
+	return b, nil
+}
+func appendVarintS32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	p := ptr.getInt32Ptr()
+	if p == nil {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64(*p))
+	return b, nil
+}
+func appendVarintS32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := ptr.getInt32Slice()
+	for _, v := range s {
+		b = appendVarint(b, wiretag)
+		b = appendVarint(b, uint64(v))
+	}
+	return b, nil
+}
+func appendVarintS32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := ptr.getInt32Slice()
+	if len(s) == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag&^7|WireBytes)
+	// compute size
+	n := 0
+	for _, v := range s {
+		n += SizeVarint(uint64(v))
+	}
+	b = appendVarint(b, uint64(n))
+	for _, v := range s {
+		b = appendVarint(b, uint64(v))
+	}
+	return b, nil
+}
+func appendVarint64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toUint64()
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, v)
+	return b, nil
+}
+func appendVarint64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toUint64()
+	if v == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, v)
+	return b, nil
+}
+func appendVarint64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	p := *ptr.toUint64Ptr()
+	if p == nil {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, *p)
+	return b, nil
+}
+func appendVarint64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toUint64Slice()
+	for _, v := range s {
+		b = appendVarint(b, wiretag)
+		b = appendVarint(b, v)
+	}
+	return b, nil
+}
+func appendVarint64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toUint64Slice()
+	if len(s) == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag&^7|WireBytes)
+	// compute size
+	n := 0
+	for _, v := range s {
+		n += SizeVarint(v)
+	}
+	b = appendVarint(b, uint64(n))
+	for _, v := range s {
+		b = appendVarint(b, v)
+	}
+	return b, nil
+}
+func appendVarintS64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toInt64()
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64(v))
+	return b, nil
+}
+func appendVarintS64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toInt64()
+	if v == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64(v))
+	return b, nil
+}
+func appendVarintS64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	p := *ptr.toInt64Ptr()
+	if p == nil {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64(*p))
+	return b, nil
+}
+func appendVarintS64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toInt64Slice()
+	for _, v := range s {
+		b = appendVarint(b, wiretag)
+		b = appendVarint(b, uint64(v))
+	}
+	return b, nil
+}
+func appendVarintS64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toInt64Slice()
+	if len(s) == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag&^7|WireBytes)
+	// compute size
+	n := 0
+	for _, v := range s {
+		n += SizeVarint(uint64(v))
+	}
+	b = appendVarint(b, uint64(n))
+	for _, v := range s {
+		b = appendVarint(b, uint64(v))
+	}
+	return b, nil
+}
+func appendZigzag32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toInt32()
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31))))
+	return b, nil
+}
+func appendZigzag32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toInt32()
+	if v == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31))))
+	return b, nil
+}
+func appendZigzag32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	p := ptr.getInt32Ptr()
+	if p == nil {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	v := *p
+	b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31))))
+	return b, nil
+}
+func appendZigzag32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := ptr.getInt32Slice()
+	for _, v := range s {
+		b = appendVarint(b, wiretag)
+		b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31))))
+	}
+	return b, nil
+}
+func appendZigzag32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := ptr.getInt32Slice()
+	if len(s) == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag&^7|WireBytes)
+	// compute size
+	n := 0
+	for _, v := range s {
+		n += SizeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31))))
+	}
+	b = appendVarint(b, uint64(n))
+	for _, v := range s {
+		b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31))))
+	}
+	return b, nil
+}
+func appendZigzag64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toInt64()
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63)))
+	return b, nil
+}
+func appendZigzag64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toInt64()
+	if v == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63)))
+	return b, nil
+}
+func appendZigzag64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	p := *ptr.toInt64Ptr()
+	if p == nil {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	v := *p
+	b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63)))
+	return b, nil
+}
+func appendZigzag64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toInt64Slice()
+	for _, v := range s {
+		b = appendVarint(b, wiretag)
+		b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63)))
+	}
+	return b, nil
+}
+func appendZigzag64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toInt64Slice()
+	if len(s) == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag&^7|WireBytes)
+	// compute size
+	n := 0
+	for _, v := range s {
+		n += SizeVarint(uint64(v<<1) ^ uint64((int64(v) >> 63)))
+	}
+	b = appendVarint(b, uint64(n))
+	for _, v := range s {
+		b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63)))
+	}
+	return b, nil
+}
+func appendBoolValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toBool()
+	b = appendVarint(b, wiretag)
+	if v {
+		b = append(b, 1)
+	} else {
+		b = append(b, 0)
+	}
+	return b, nil
+}
+func appendBoolValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toBool()
+	if !v {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = append(b, 1)
+	return b, nil
+}
+
+func appendBoolPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	p := *ptr.toBoolPtr()
+	if p == nil {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	if *p {
+		b = append(b, 1)
+	} else {
+		b = append(b, 0)
+	}
+	return b, nil
+}
+func appendBoolSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toBoolSlice()
+	for _, v := range s {
+		b = appendVarint(b, wiretag)
+		if v {
+			b = append(b, 1)
+		} else {
+			b = append(b, 0)
+		}
+	}
+	return b, nil
+}
+func appendBoolPackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toBoolSlice()
+	if len(s) == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag&^7|WireBytes)
+	b = appendVarint(b, uint64(len(s)))
+	for _, v := range s {
+		if v {
+			b = append(b, 1)
+		} else {
+			b = append(b, 0)
+		}
+	}
+	return b, nil
+}
+func appendStringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toString()
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64(len(v)))
+	b = append(b, v...)
+	return b, nil
+}
+func appendStringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toString()
+	if v == "" {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64(len(v)))
+	b = append(b, v...)
+	return b, nil
+}
+func appendStringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	p := *ptr.toStringPtr()
+	if p == nil {
+		return b, nil
+	}
+	v := *p
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64(len(v)))
+	b = append(b, v...)
+	return b, nil
+}
+func appendStringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toStringSlice()
+	for _, v := range s {
+		b = appendVarint(b, wiretag)
+		b = appendVarint(b, uint64(len(v)))
+		b = append(b, v...)
+	}
+	return b, nil
+}
+func appendUTF8StringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	var invalidUTF8 bool
+	v := *ptr.toString()
+	if !utf8.ValidString(v) {
+		invalidUTF8 = true
+	}
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64(len(v)))
+	b = append(b, v...)
+	if invalidUTF8 {
+		return b, errInvalidUTF8
+	}
+	return b, nil
+}
+func appendUTF8StringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	var invalidUTF8 bool
+	v := *ptr.toString()
+	if v == "" {
+		return b, nil
+	}
+	if !utf8.ValidString(v) {
+		invalidUTF8 = true
+	}
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64(len(v)))
+	b = append(b, v...)
+	if invalidUTF8 {
+		return b, errInvalidUTF8
+	}
+	return b, nil
+}
+func appendUTF8StringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	var invalidUTF8 bool
+	p := *ptr.toStringPtr()
+	if p == nil {
+		return b, nil
+	}
+	v := *p
+	if !utf8.ValidString(v) {
+		invalidUTF8 = true
+	}
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64(len(v)))
+	b = append(b, v...)
+	if invalidUTF8 {
+		return b, errInvalidUTF8
+	}
+	return b, nil
+}
+func appendUTF8StringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	var invalidUTF8 bool
+	s := *ptr.toStringSlice()
+	for _, v := range s {
+		if !utf8.ValidString(v) {
+			invalidUTF8 = true
+		}
+		b = appendVarint(b, wiretag)
+		b = appendVarint(b, uint64(len(v)))
+		b = append(b, v...)
+	}
+	if invalidUTF8 {
+		return b, errInvalidUTF8
+	}
+	return b, nil
+}
+func appendBytes(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toBytes()
+	if v == nil {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64(len(v)))
+	b = append(b, v...)
+	return b, nil
+}
+func appendBytes3(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toBytes()
+	if len(v) == 0 {
+		return b, nil
+	}
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64(len(v)))
+	b = append(b, v...)
+	return b, nil
+}
+func appendBytesOneof(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	v := *ptr.toBytes()
+	b = appendVarint(b, wiretag)
+	b = appendVarint(b, uint64(len(v)))
+	b = append(b, v...)
+	return b, nil
+}
+func appendBytesSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+	s := *ptr.toBytesSlice()
+	for _, v := range s {
+		b = appendVarint(b, wiretag)
+		b = appendVarint(b, uint64(len(v)))
+		b = append(b, v...)
+	}
+	return b, nil
+}
+
+// makeGroupMarshaler returns the sizer and marshaler for a group.
+// u is the marshal info of the underlying message.
+func makeGroupMarshaler(u *marshalInfo) (sizer, marshaler) {
+	return func(ptr pointer, tagsize int) int {
+			p := ptr.getPointer()
+			if p.isNil() {
+				return 0
+			}
+			return u.size(p) + 2*tagsize
+		},
+		func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
+			p := ptr.getPointer()
+			if p.isNil() {
+				return b, nil
+			}
+			var err error
+			b = appendVarint(b, wiretag) // start group
+			b, err = u.marshal(b, p, deterministic)
+			b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group
+			return b, err
+		}
+}
+
+// makeGroupSliceMarshaler returns the sizer and marshaler for a group slice.
+// u is the marshal info of the underlying message.
+func makeGroupSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
+	return func(ptr pointer, tagsize int) int {
+			s := ptr.getPointerSlice()
+			n := 0
+			for _, v := range s {
+				if v.isNil() {
+					continue
+				}
+				n += u.size(v) + 2*tagsize
+			}
+			return n
+		},
+		func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
+			s := ptr.getPointerSlice()
+			var err error
+			var nerr nonFatal
+			for _, v := range s {
+				if v.isNil() {
+					return b, errRepeatedHasNil
+				}
+				b = appendVarint(b, wiretag) // start group
+				b, err = u.marshal(b, v, deterministic)
+				b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group
+				if !nerr.Merge(err) {
+					if err == ErrNil {
+						err = errRepeatedHasNil
+					}
+					return b, err
+				}
+			}
+			return b, nerr.E
+		}
+}
+
+// makeMessageMarshaler returns the sizer and marshaler for a message field.
+// u is the marshal info of the message.
+func makeMessageMarshaler(u *marshalInfo) (sizer, marshaler) {
+	return func(ptr pointer, tagsize int) int {
+			p := ptr.getPointer()
+			if p.isNil() {
+				return 0
+			}
+			siz := u.size(p)
+			return siz + SizeVarint(uint64(siz)) + tagsize
+		},
+		func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
+			p := ptr.getPointer()
+			if p.isNil() {
+				return b, nil
+			}
+			b = appendVarint(b, wiretag)
+			siz := u.cachedsize(p)
+			b = appendVarint(b, uint64(siz))
+			return u.marshal(b, p, deterministic)
+		}
+}
+
+// makeMessageSliceMarshaler returns the sizer and marshaler for a message slice.
+// u is the marshal info of the message.
+func makeMessageSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
+	return func(ptr pointer, tagsize int) int {
+			s := ptr.getPointerSlice()
+			n := 0
+			for _, v := range s {
+				if v.isNil() {
+					continue
+				}
+				siz := u.size(v)
+				n += siz + SizeVarint(uint64(siz)) + tagsize
+			}
+			return n
+		},
+		func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
+			s := ptr.getPointerSlice()
+			var err error
+			var nerr nonFatal
+			for _, v := range s {
+				if v.isNil() {
+					return b, errRepeatedHasNil
+				}
+				b = appendVarint(b, wiretag)
+				siz := u.cachedsize(v)
+				b = appendVarint(b, uint64(siz))
+				b, err = u.marshal(b, v, deterministic)
+
+				if !nerr.Merge(err) {
+					if err == ErrNil {
+						err = errRepeatedHasNil
+					}
+					return b, err
+				}
+			}
+			return b, nerr.E
+		}
+}
+
+// makeMapMarshaler returns the sizer and marshaler for a map field.
+// f is the pointer to the reflect data structure of the field.
+func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
+	// figure out key and value type
+	t := f.Type
+	keyType := t.Key()
+	valType := t.Elem()
+	keyTags := strings.Split(f.Tag.Get("protobuf_key"), ",")
+	valTags := strings.Split(f.Tag.Get("protobuf_val"), ",")
+	keySizer, keyMarshaler := typeMarshaler(keyType, keyTags, false, false) // don't omit zero value in map
+	valSizer, valMarshaler := typeMarshaler(valType, valTags, false, false) // don't omit zero value in map
+	keyWireTag := 1<<3 | wiretype(keyTags[0])
+	valWireTag := 2<<3 | wiretype(valTags[0])
+
+	// We create an interface to get the addresses of the map key and value.
+	// If value is pointer-typed, the interface is a direct interface, the
+	// idata itself is the value. Otherwise, the idata is the pointer to the
+	// value.
+	// Key cannot be pointer-typed.
+	valIsPtr := valType.Kind() == reflect.Ptr
+
+	// If value is a message with nested maps, calling
+	// valSizer in marshal may be quadratic. We should use
+	// cached version in marshal (but not in size).
+	// If value is not message type, we don't have size cache,
+	// but it cannot be nested either. Just use valSizer.
+	valCachedSizer := valSizer
+	if valIsPtr && valType.Elem().Kind() == reflect.Struct {
+		u := getMarshalInfo(valType.Elem())
+		valCachedSizer = func(ptr pointer, tagsize int) int {
+			// Same as message sizer, but use cache.
+			p := ptr.getPointer()
+			if p.isNil() {
+				return 0
+			}
+			siz := u.cachedsize(p)
+			return siz + SizeVarint(uint64(siz)) + tagsize
+		}
+	}
+	return func(ptr pointer, tagsize int) int {
+			m := ptr.asPointerTo(t).Elem() // the map
+			n := 0
+			for _, k := range m.MapKeys() {
+				ki := k.Interface()
+				vi := m.MapIndex(k).Interface()
+				kaddr := toAddrPointer(&ki, false, false)      // pointer to key
+				vaddr := toAddrPointer(&vi, valIsPtr, false)   // pointer to value
+				siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
+				n += siz + SizeVarint(uint64(siz)) + tagsize
+			}
+			return n
+		},
+		func(b []byte, ptr pointer, tag uint64, deterministic bool) ([]byte, error) {
+			m := ptr.asPointerTo(t).Elem() // the map
+			var err error
+			keys := m.MapKeys()
+			if len(keys) > 1 && deterministic {
+				sort.Sort(mapKeys(keys))
+			}
+
+			var nerr nonFatal
+			for _, k := range keys {
+				ki := k.Interface()
+				vi := m.MapIndex(k).Interface()
+				kaddr := toAddrPointer(&ki, false, false)    // pointer to key
+				vaddr := toAddrPointer(&vi, valIsPtr, false) // pointer to value
+				b = appendVarint(b, tag)
+				siz := keySizer(kaddr, 1) + valCachedSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
+				b = appendVarint(b, uint64(siz))
+				b, err = keyMarshaler(b, kaddr, keyWireTag, deterministic)
+				if !nerr.Merge(err) {
+					return b, err
+				}
+				b, err = valMarshaler(b, vaddr, valWireTag, deterministic)
+				if err != ErrNil && !nerr.Merge(err) { // allow nil value in map
+					return b, err
+				}
+			}
+			return b, nerr.E
+		}
+}
+
+// makeOneOfMarshaler returns the sizer and marshaler for a oneof field.
+// fi is the marshal info of the field.
+// f is the pointer to the reflect data structure of the field.
+func makeOneOfMarshaler(fi *marshalFieldInfo, f *reflect.StructField) (sizer, marshaler) {
+	// Oneof field is an interface. We need to get the actual data type on the fly.
+	t := f.Type
+	return func(ptr pointer, _ int) int {
+			p := ptr.getInterfacePointer()
+			if p.isNil() {
+				return 0
+			}
+			v := ptr.asPointerTo(t).Elem().Elem().Elem() // *interface -> interface -> *struct -> struct
+			telem := v.Type()
+			e := fi.oneofElems[telem]
+			return e.sizer(p, e.tagsize)
+		},
+		func(b []byte, ptr pointer, _ uint64, deterministic bool) ([]byte, error) {
+			p := ptr.getInterfacePointer()
+			if p.isNil() {
+				return b, nil
+			}
+			v := ptr.asPointerTo(t).Elem().Elem().Elem() // *interface -> interface -> *struct -> struct
+			telem := v.Type()
+			if telem.Field(0).Type.Kind() == reflect.Ptr && p.getPointer().isNil() {
+				return b, errOneofHasNil
+			}
+			e := fi.oneofElems[telem]
+			return e.marshaler(b, p, e.wiretag, deterministic)
+		}
+}
+
+// sizeExtensions computes the size of encoded data for a XXX_InternalExtensions field.
+func (u *marshalInfo) sizeExtensions(ext *XXX_InternalExtensions) int {
+	m, mu := ext.extensionsRead()
+	if m == nil {
+		return 0
+	}
+	mu.Lock()
+
+	n := 0
+	for _, e := range m {
+		if e.value == nil || e.desc == nil {
+			// Extension is only in its encoded form.
+			n += len(e.enc)
+			continue
+		}
+
+		// We don't skip extensions that have an encoded form set,
+		// because the extension value may have been mutated after
+		// the last time this function was called.
+		ei := u.getExtElemInfo(e.desc)
+		v := e.value
+		p := toAddrPointer(&v, ei.isptr, ei.deref)
+		n += ei.sizer(p, ei.tagsize)
+	}
+	mu.Unlock()
+	return n
+}
+
+// appendExtensions marshals a XXX_InternalExtensions field to the end of byte slice b.
+func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, deterministic bool) ([]byte, error) {
+	m, mu := ext.extensionsRead()
+	if m == nil {
+		return b, nil
+	}
+	mu.Lock()
+	defer mu.Unlock()
+
+	var err error
+	var nerr nonFatal
+
+	// Fast-path for common cases: zero or one extensions.
+	// Don't bother sorting the keys.
+	if len(m) <= 1 {
+		for _, e := range m {
+			if e.value == nil || e.desc == nil {
+				// Extension is only in its encoded form.
+				b = append(b, e.enc...)
+				continue
+			}
+
+			// We don't skip extensions that have an encoded form set,
+			// because the extension value may have been mutated after
+			// the last time this function was called.
+
+			ei := u.getExtElemInfo(e.desc)
+			v := e.value
+			p := toAddrPointer(&v, ei.isptr, ei.deref)
+			b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
+			if !nerr.Merge(err) {
+				return b, err
+			}
+		}
+		return b, nerr.E
+	}
+
+	// Sort the keys to provide a deterministic encoding.
+	// Not sure this is required, but the old code does it.
+	keys := make([]int, 0, len(m))
+	for k := range m {
+		keys = append(keys, int(k))
+	}
+	sort.Ints(keys)
+
+	for _, k := range keys {
+		e := m[int32(k)]
+		if e.value == nil || e.desc == nil {
+			// Extension is only in its encoded form.
+			b = append(b, e.enc...)
+			continue
+		}
+
+		// We don't skip extensions that have an encoded form set,
+		// because the extension value may have been mutated after
+		// the last time this function was called.
+
+		ei := u.getExtElemInfo(e.desc)
+		v := e.value
+		p := toAddrPointer(&v, ei.isptr, ei.deref)
+		b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
+		if !nerr.Merge(err) {
+			return b, err
+		}
+	}
+	return b, nerr.E
+}
+
+// message set format is:
+//   message MessageSet {
+//     repeated group Item = 1 {
+//       required int32 type_id = 2;
+//       required string message = 3;
+//     };
+//   }
+
+// sizeMessageSet computes the size of encoded data for a XXX_InternalExtensions field
+// in message set format (above).
+func (u *marshalInfo) sizeMessageSet(ext *XXX_InternalExtensions) int {
+	m, mu := ext.extensionsRead()
+	if m == nil {
+		return 0
+	}
+	mu.Lock()
+
+	n := 0
+	for id, e := range m {
+		n += 2                          // start group, end group. tag = 1 (size=1)
+		n += SizeVarint(uint64(id)) + 1 // type_id, tag = 2 (size=1)
+
+		if e.value == nil || e.desc == nil {
+			// Extension is only in its encoded form.
+			msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint
+			siz := len(msgWithLen)
+			n += siz + 1 // message, tag = 3 (size=1)
+			continue
+		}
+
+		// We don't skip extensions that have an encoded form set,
+		// because the extension value may have been mutated after
+		// the last time this function was called.
+
+		ei := u.getExtElemInfo(e.desc)
+		v := e.value
+		p := toAddrPointer(&v, ei.isptr, ei.deref)
+		n += ei.sizer(p, 1) // message, tag = 3 (size=1)
+	}
+	mu.Unlock()
+	return n
+}
+
+// appendMessageSet marshals a XXX_InternalExtensions field in message set format (above)
+// to the end of byte slice b.
+func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, deterministic bool) ([]byte, error) {
+	m, mu := ext.extensionsRead()
+	if m == nil {
+		return b, nil
+	}
+	mu.Lock()
+	defer mu.Unlock()
+
+	var err error
+	var nerr nonFatal
+
+	// Fast-path for common cases: zero or one extensions.
+	// Don't bother sorting the keys.
+	if len(m) <= 1 {
+		for id, e := range m {
+			b = append(b, 1<<3|WireStartGroup)
+			b = append(b, 2<<3|WireVarint)
+			b = appendVarint(b, uint64(id))
+
+			if e.value == nil || e.desc == nil {
+				// Extension is only in its encoded form.
+				msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint
+				b = append(b, 3<<3|WireBytes)
+				b = append(b, msgWithLen...)
+				b = append(b, 1<<3|WireEndGroup)
+				continue
+			}
+
+			// We don't skip extensions that have an encoded form set,
+			// because the extension value may have been mutated after
+			// the last time this function was called.
+
+			ei := u.getExtElemInfo(e.desc)
+			v := e.value
+			p := toAddrPointer(&v, ei.isptr, ei.deref)
+			b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
+			if !nerr.Merge(err) {
+				return b, err
+			}
+			b = append(b, 1<<3|WireEndGroup)
+		}
+		return b, nerr.E
+	}
+
+	// Sort the keys to provide a deterministic encoding.
+	keys := make([]int, 0, len(m))
+	for k := range m {
+		keys = append(keys, int(k))
+	}
+	sort.Ints(keys)
+
+	for _, id := range keys {
+		e := m[int32(id)]
+		b = append(b, 1<<3|WireStartGroup)
+		b = append(b, 2<<3|WireVarint)
+		b = appendVarint(b, uint64(id))
+
+		if e.value == nil || e.desc == nil {
+			// Extension is only in its encoded form.
+			msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint
+			b = append(b, 3<<3|WireBytes)
+			b = append(b, msgWithLen...)
+			b = append(b, 1<<3|WireEndGroup)
+			continue
+		}
+
+		// We don't skip extensions that have an encoded form set,
+		// because the extension value may have been mutated after
+		// the last time this function was called.
+
+		ei := u.getExtElemInfo(e.desc)
+		v := e.value
+		p := toAddrPointer(&v, ei.isptr, ei.deref)
+		b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
+		b = append(b, 1<<3|WireEndGroup)
+		if !nerr.Merge(err) {
+			return b, err
+		}
+	}
+	return b, nerr.E
+}
+
+// sizeV1Extensions computes the size of encoded data for a V1-API extension field.
+func (u *marshalInfo) sizeV1Extensions(m map[int32]Extension) int {
+	if m == nil {
+		return 0
+	}
+
+	n := 0
+	for _, e := range m {
+		if e.value == nil || e.desc == nil {
+			// Extension is only in its encoded form.
+			n += len(e.enc)
+			continue
+		}
+
+		// We don't skip extensions that have an encoded form set,
+		// because the extension value may have been mutated after
+		// the last time this function was called.
+
+		ei := u.getExtElemInfo(e.desc)
+		v := e.value
+		p := toAddrPointer(&v, ei.isptr, ei.deref)
+		n += ei.sizer(p, ei.tagsize)
+	}
+	return n
+}
+
+// appendV1Extensions marshals a V1-API extension field to the end of byte slice b.
+func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, deterministic bool) ([]byte, error) {
+	if m == nil {
+		return b, nil
+	}
+
+	// Sort the keys to provide a deterministic encoding.
+	keys := make([]int, 0, len(m))
+	for k := range m {
+		keys = append(keys, int(k))
+	}
+	sort.Ints(keys)
+
+	var err error
+	var nerr nonFatal
+	for _, k := range keys {
+		e := m[int32(k)]
+		if e.value == nil || e.desc == nil {
+			// Extension is only in its encoded form.
+			b = append(b, e.enc...)
+			continue
+		}
+
+		// We don't skip extensions that have an encoded form set,
+		// because the extension value may have been mutated after
+		// the last time this function was called.
+
+		ei := u.getExtElemInfo(e.desc)
+		v := e.value
+		p := toAddrPointer(&v, ei.isptr, ei.deref)
+		b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
+		if !nerr.Merge(err) {
+			return b, err
+		}
+	}
+	return b, nerr.E
+}
+
+// newMarshaler is the interface representing objects that can marshal themselves.
+//
+// This exists to support protoc-gen-go generated messages.
+// The proto package will stop type-asserting to this interface in the future.
+//
+// DO NOT DEPEND ON THIS.
+type newMarshaler interface {
+	XXX_Size() int
+	XXX_Marshal(b []byte, deterministic bool) ([]byte, error)
+}
+
+// Size returns the encoded size of a protocol buffer message.
+// This is the main entry point.
+func Size(pb Message) int {
+	if m, ok := pb.(newMarshaler); ok {
+		return m.XXX_Size()
+	}
+	if m, ok := pb.(Marshaler); ok {
+		// If the message can marshal itself, let it do it, for compatibility.
+		// NOTE: This is not efficient.
+		b, _ := m.Marshal()
+		return len(b)
+	}
+	// in case somehow we didn't generate the wrapper
+	if pb == nil {
+		return 0
+	}
+	var info InternalMessageInfo
+	return info.Size(pb)
+}
+
+// Marshal takes a protocol buffer message
+// and encodes it into the wire format, returning the data.
+// This is the main entry point.
+func Marshal(pb Message) ([]byte, error) {
+	if m, ok := pb.(newMarshaler); ok {
+		siz := m.XXX_Size()
+		b := make([]byte, 0, siz)
+		return m.XXX_Marshal(b, false)
+	}
+	if m, ok := pb.(Marshaler); ok {
+		// If the message can marshal itself, let it do it, for compatibility.
+		// NOTE: This is not efficient.
+		return m.Marshal()
+	}
+	// in case somehow we didn't generate the wrapper
+	if pb == nil {
+		return nil, ErrNil
+	}
+	var info InternalMessageInfo
+	siz := info.Size(pb)
+	b := make([]byte, 0, siz)
+	return info.Marshal(b, pb, false)
+}
+
+// Marshal takes a protocol buffer message
+// and encodes it into the wire format, writing the result to the
+// Buffer.
+// This is an alternative entry point. It is not necessary to use
+// a Buffer for most applications.
+func (p *Buffer) Marshal(pb Message) error {
+	var err error
+	if m, ok := pb.(newMarshaler); ok {
+		siz := m.XXX_Size()
+		p.grow(siz) // make sure buf has enough capacity
+		p.buf, err = m.XXX_Marshal(p.buf, p.deterministic)
+		return err
+	}
+	if m, ok := pb.(Marshaler); ok {
+		// If the message can marshal itself, let it do it, for compatibility.
+		// NOTE: This is not efficient.
+		b, err := m.Marshal()
+		p.buf = append(p.buf, b...)
+		return err
+	}
+	// in case somehow we didn't generate the wrapper
+	if pb == nil {
+		return ErrNil
+	}
+	var info InternalMessageInfo
+	siz := info.Size(pb)
+	p.grow(siz) // make sure buf has enough capacity
+	p.buf, err = info.Marshal(p.buf, pb, p.deterministic)
+	return err
+}
+
+// grow grows the buffer's capacity, if necessary, to guarantee space for
+// another n bytes. After grow(n), at least n bytes can be written to the
+// buffer without another allocation.
+func (p *Buffer) grow(n int) {
+	need := len(p.buf) + n
+	if need <= cap(p.buf) {
+		return
+	}
+	newCap := len(p.buf) * 2
+	if newCap < need {
+		newCap = need
+	}
+	p.buf = append(make([]byte, 0, newCap), p.buf...)
+}

+ 654 - 0
vendor/github.com/golang/protobuf/proto/table_merge.go

@@ -0,0 +1,654 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors.  All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+import (
+	"fmt"
+	"reflect"
+	"strings"
+	"sync"
+	"sync/atomic"
+)
+
+// Merge merges the src message into dst.
+// This assumes that dst and src of the same type and are non-nil.
+func (a *InternalMessageInfo) Merge(dst, src Message) {
+	mi := atomicLoadMergeInfo(&a.merge)
+	if mi == nil {
+		mi = getMergeInfo(reflect.TypeOf(dst).Elem())
+		atomicStoreMergeInfo(&a.merge, mi)
+	}
+	mi.merge(toPointer(&dst), toPointer(&src))
+}
+
+type mergeInfo struct {
+	typ reflect.Type
+
+	initialized int32 // 0: only typ is valid, 1: everything is valid
+	lock        sync.Mutex
+
+	fields       []mergeFieldInfo
+	unrecognized field // Offset of XXX_unrecognized
+}
+
+type mergeFieldInfo struct {
+	field field // Offset of field, guaranteed to be valid
+
+	// isPointer reports whether the value in the field is a pointer.
+	// This is true for the following situations:
+	//	* Pointer to struct
+	//	* Pointer to basic type (proto2 only)
+	//	* Slice (first value in slice header is a pointer)
+	//	* String (first value in string header is a pointer)
+	isPointer bool
+
+	// basicWidth reports the width of the field assuming that it is directly
+	// embedded in the struct (as is the case for basic types in proto3).
+	// The possible values are:
+	// 	0: invalid
+	//	1: bool
+	//	4: int32, uint32, float32
+	//	8: int64, uint64, float64
+	basicWidth int
+
+	// Where dst and src are pointers to the types being merged.
+	merge func(dst, src pointer)
+}
+
+var (
+	mergeInfoMap  = map[reflect.Type]*mergeInfo{}
+	mergeInfoLock sync.Mutex
+)
+
+func getMergeInfo(t reflect.Type) *mergeInfo {
+	mergeInfoLock.Lock()
+	defer mergeInfoLock.Unlock()
+	mi := mergeInfoMap[t]
+	if mi == nil {
+		mi = &mergeInfo{typ: t}
+		mergeInfoMap[t] = mi
+	}
+	return mi
+}
+
+// merge merges src into dst assuming they are both of type *mi.typ.
+func (mi *mergeInfo) merge(dst, src pointer) {
+	if dst.isNil() {
+		panic("proto: nil destination")
+	}
+	if src.isNil() {
+		return // Nothing to do.
+	}
+
+	if atomic.LoadInt32(&mi.initialized) == 0 {
+		mi.computeMergeInfo()
+	}
+
+	for _, fi := range mi.fields {
+		sfp := src.offset(fi.field)
+
+		// As an optimization, we can avoid the merge function call cost
+		// if we know for sure that the source will have no effect
+		// by checking if it is the zero value.
+		if unsafeAllowed {
+			if fi.isPointer && sfp.getPointer().isNil() { // Could be slice or string
+				continue
+			}
+			if fi.basicWidth > 0 {
+				switch {
+				case fi.basicWidth == 1 && !*sfp.toBool():
+					continue
+				case fi.basicWidth == 4 && *sfp.toUint32() == 0:
+					continue
+				case fi.basicWidth == 8 && *sfp.toUint64() == 0:
+					continue
+				}
+			}
+		}
+
+		dfp := dst.offset(fi.field)
+		fi.merge(dfp, sfp)
+	}
+
+	// TODO: Make this faster?
+	out := dst.asPointerTo(mi.typ).Elem()
+	in := src.asPointerTo(mi.typ).Elem()
+	if emIn, err := extendable(in.Addr().Interface()); err == nil {
+		emOut, _ := extendable(out.Addr().Interface())
+		mIn, muIn := emIn.extensionsRead()
+		if mIn != nil {
+			mOut := emOut.extensionsWrite()
+			muIn.Lock()
+			mergeExtension(mOut, mIn)
+			muIn.Unlock()
+		}
+	}
+
+	if mi.unrecognized.IsValid() {
+		if b := *src.offset(mi.unrecognized).toBytes(); len(b) > 0 {
+			*dst.offset(mi.unrecognized).toBytes() = append([]byte(nil), b...)
+		}
+	}
+}
+
+func (mi *mergeInfo) computeMergeInfo() {
+	mi.lock.Lock()
+	defer mi.lock.Unlock()
+	if mi.initialized != 0 {
+		return
+	}
+	t := mi.typ
+	n := t.NumField()
+
+	props := GetProperties(t)
+	for i := 0; i < n; i++ {
+		f := t.Field(i)
+		if strings.HasPrefix(f.Name, "XXX_") {
+			continue
+		}
+
+		mfi := mergeFieldInfo{field: toField(&f)}
+		tf := f.Type
+
+		// As an optimization, we can avoid the merge function call cost
+		// if we know for sure that the source will have no effect
+		// by checking if it is the zero value.
+		if unsafeAllowed {
+			switch tf.Kind() {
+			case reflect.Ptr, reflect.Slice, reflect.String:
+				// As a special case, we assume slices and strings are pointers
+				// since we know that the first field in the SliceSlice or
+				// StringHeader is a data pointer.
+				mfi.isPointer = true
+			case reflect.Bool:
+				mfi.basicWidth = 1
+			case reflect.Int32, reflect.Uint32, reflect.Float32:
+				mfi.basicWidth = 4
+			case reflect.Int64, reflect.Uint64, reflect.Float64:
+				mfi.basicWidth = 8
+			}
+		}
+
+		// Unwrap tf to get at its most basic type.
+		var isPointer, isSlice bool
+		if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
+			isSlice = true
+			tf = tf.Elem()
+		}
+		if tf.Kind() == reflect.Ptr {
+			isPointer = true
+			tf = tf.Elem()
+		}
+		if isPointer && isSlice && tf.Kind() != reflect.Struct {
+			panic("both pointer and slice for basic type in " + tf.Name())
+		}
+
+		switch tf.Kind() {
+		case reflect.Int32:
+			switch {
+			case isSlice: // E.g., []int32
+				mfi.merge = func(dst, src pointer) {
+					// NOTE: toInt32Slice is not defined (see pointer_reflect.go).
+					/*
+						sfsp := src.toInt32Slice()
+						if *sfsp != nil {
+							dfsp := dst.toInt32Slice()
+							*dfsp = append(*dfsp, *sfsp...)
+							if *dfsp == nil {
+								*dfsp = []int64{}
+							}
+						}
+					*/
+					sfs := src.getInt32Slice()
+					if sfs != nil {
+						dfs := dst.getInt32Slice()
+						dfs = append(dfs, sfs...)
+						if dfs == nil {
+							dfs = []int32{}
+						}
+						dst.setInt32Slice(dfs)
+					}
+				}
+			case isPointer: // E.g., *int32
+				mfi.merge = func(dst, src pointer) {
+					// NOTE: toInt32Ptr is not defined (see pointer_reflect.go).
+					/*
+						sfpp := src.toInt32Ptr()
+						if *sfpp != nil {
+							dfpp := dst.toInt32Ptr()
+							if *dfpp == nil {
+								*dfpp = Int32(**sfpp)
+							} else {
+								**dfpp = **sfpp
+							}
+						}
+					*/
+					sfp := src.getInt32Ptr()
+					if sfp != nil {
+						dfp := dst.getInt32Ptr()
+						if dfp == nil {
+							dst.setInt32Ptr(*sfp)
+						} else {
+							*dfp = *sfp
+						}
+					}
+				}
+			default: // E.g., int32
+				mfi.merge = func(dst, src pointer) {
+					if v := *src.toInt32(); v != 0 {
+						*dst.toInt32() = v
+					}
+				}
+			}
+		case reflect.Int64:
+			switch {
+			case isSlice: // E.g., []int64
+				mfi.merge = func(dst, src pointer) {
+					sfsp := src.toInt64Slice()
+					if *sfsp != nil {
+						dfsp := dst.toInt64Slice()
+						*dfsp = append(*dfsp, *sfsp...)
+						if *dfsp == nil {
+							*dfsp = []int64{}
+						}
+					}
+				}
+			case isPointer: // E.g., *int64
+				mfi.merge = func(dst, src pointer) {
+					sfpp := src.toInt64Ptr()
+					if *sfpp != nil {
+						dfpp := dst.toInt64Ptr()
+						if *dfpp == nil {
+							*dfpp = Int64(**sfpp)
+						} else {
+							**dfpp = **sfpp
+						}
+					}
+				}
+			default: // E.g., int64
+				mfi.merge = func(dst, src pointer) {
+					if v := *src.toInt64(); v != 0 {
+						*dst.toInt64() = v
+					}
+				}
+			}
+		case reflect.Uint32:
+			switch {
+			case isSlice: // E.g., []uint32
+				mfi.merge = func(dst, src pointer) {
+					sfsp := src.toUint32Slice()
+					if *sfsp != nil {
+						dfsp := dst.toUint32Slice()
+						*dfsp = append(*dfsp, *sfsp...)
+						if *dfsp == nil {
+							*dfsp = []uint32{}
+						}
+					}
+				}
+			case isPointer: // E.g., *uint32
+				mfi.merge = func(dst, src pointer) {
+					sfpp := src.toUint32Ptr()
+					if *sfpp != nil {
+						dfpp := dst.toUint32Ptr()
+						if *dfpp == nil {
+							*dfpp = Uint32(**sfpp)
+						} else {
+							**dfpp = **sfpp
+						}
+					}
+				}
+			default: // E.g., uint32
+				mfi.merge = func(dst, src pointer) {
+					if v := *src.toUint32(); v != 0 {
+						*dst.toUint32() = v
+					}
+				}
+			}
+		case reflect.Uint64:
+			switch {
+			case isSlice: // E.g., []uint64
+				mfi.merge = func(dst, src pointer) {
+					sfsp := src.toUint64Slice()
+					if *sfsp != nil {
+						dfsp := dst.toUint64Slice()
+						*dfsp = append(*dfsp, *sfsp...)
+						if *dfsp == nil {
+							*dfsp = []uint64{}
+						}
+					}
+				}
+			case isPointer: // E.g., *uint64
+				mfi.merge = func(dst, src pointer) {
+					sfpp := src.toUint64Ptr()
+					if *sfpp != nil {
+						dfpp := dst.toUint64Ptr()
+						if *dfpp == nil {
+							*dfpp = Uint64(**sfpp)
+						} else {
+							**dfpp = **sfpp
+						}
+					}
+				}
+			default: // E.g., uint64
+				mfi.merge = func(dst, src pointer) {
+					if v := *src.toUint64(); v != 0 {
+						*dst.toUint64() = v
+					}
+				}
+			}
+		case reflect.Float32:
+			switch {
+			case isSlice: // E.g., []float32
+				mfi.merge = func(dst, src pointer) {
+					sfsp := src.toFloat32Slice()
+					if *sfsp != nil {
+						dfsp := dst.toFloat32Slice()
+						*dfsp = append(*dfsp, *sfsp...)
+						if *dfsp == nil {
+							*dfsp = []float32{}
+						}
+					}
+				}
+			case isPointer: // E.g., *float32
+				mfi.merge = func(dst, src pointer) {
+					sfpp := src.toFloat32Ptr()
+					if *sfpp != nil {
+						dfpp := dst.toFloat32Ptr()
+						if *dfpp == nil {
+							*dfpp = Float32(**sfpp)
+						} else {
+							**dfpp = **sfpp
+						}
+					}
+				}
+			default: // E.g., float32
+				mfi.merge = func(dst, src pointer) {
+					if v := *src.toFloat32(); v != 0 {
+						*dst.toFloat32() = v
+					}
+				}
+			}
+		case reflect.Float64:
+			switch {
+			case isSlice: // E.g., []float64
+				mfi.merge = func(dst, src pointer) {
+					sfsp := src.toFloat64Slice()
+					if *sfsp != nil {
+						dfsp := dst.toFloat64Slice()
+						*dfsp = append(*dfsp, *sfsp...)
+						if *dfsp == nil {
+							*dfsp = []float64{}
+						}
+					}
+				}
+			case isPointer: // E.g., *float64
+				mfi.merge = func(dst, src pointer) {
+					sfpp := src.toFloat64Ptr()
+					if *sfpp != nil {
+						dfpp := dst.toFloat64Ptr()
+						if *dfpp == nil {
+							*dfpp = Float64(**sfpp)
+						} else {
+							**dfpp = **sfpp
+						}
+					}
+				}
+			default: // E.g., float64
+				mfi.merge = func(dst, src pointer) {
+					if v := *src.toFloat64(); v != 0 {
+						*dst.toFloat64() = v
+					}
+				}
+			}
+		case reflect.Bool:
+			switch {
+			case isSlice: // E.g., []bool
+				mfi.merge = func(dst, src pointer) {
+					sfsp := src.toBoolSlice()
+					if *sfsp != nil {
+						dfsp := dst.toBoolSlice()
+						*dfsp = append(*dfsp, *sfsp...)
+						if *dfsp == nil {
+							*dfsp = []bool{}
+						}
+					}
+				}
+			case isPointer: // E.g., *bool
+				mfi.merge = func(dst, src pointer) {
+					sfpp := src.toBoolPtr()
+					if *sfpp != nil {
+						dfpp := dst.toBoolPtr()
+						if *dfpp == nil {
+							*dfpp = Bool(**sfpp)
+						} else {
+							**dfpp = **sfpp
+						}
+					}
+				}
+			default: // E.g., bool
+				mfi.merge = func(dst, src pointer) {
+					if v := *src.toBool(); v {
+						*dst.toBool() = v
+					}
+				}
+			}
+		case reflect.String:
+			switch {
+			case isSlice: // E.g., []string
+				mfi.merge = func(dst, src pointer) {
+					sfsp := src.toStringSlice()
+					if *sfsp != nil {
+						dfsp := dst.toStringSlice()
+						*dfsp = append(*dfsp, *sfsp...)
+						if *dfsp == nil {
+							*dfsp = []string{}
+						}
+					}
+				}
+			case isPointer: // E.g., *string
+				mfi.merge = func(dst, src pointer) {
+					sfpp := src.toStringPtr()
+					if *sfpp != nil {
+						dfpp := dst.toStringPtr()
+						if *dfpp == nil {
+							*dfpp = String(**sfpp)
+						} else {
+							**dfpp = **sfpp
+						}
+					}
+				}
+			default: // E.g., string
+				mfi.merge = func(dst, src pointer) {
+					if v := *src.toString(); v != "" {
+						*dst.toString() = v
+					}
+				}
+			}
+		case reflect.Slice:
+			isProto3 := props.Prop[i].proto3
+			switch {
+			case isPointer:
+				panic("bad pointer in byte slice case in " + tf.Name())
+			case tf.Elem().Kind() != reflect.Uint8:
+				panic("bad element kind in byte slice case in " + tf.Name())
+			case isSlice: // E.g., [][]byte
+				mfi.merge = func(dst, src pointer) {
+					sbsp := src.toBytesSlice()
+					if *sbsp != nil {
+						dbsp := dst.toBytesSlice()
+						for _, sb := range *sbsp {
+							if sb == nil {
+								*dbsp = append(*dbsp, nil)
+							} else {
+								*dbsp = append(*dbsp, append([]byte{}, sb...))
+							}
+						}
+						if *dbsp == nil {
+							*dbsp = [][]byte{}
+						}
+					}
+				}
+			default: // E.g., []byte
+				mfi.merge = func(dst, src pointer) {
+					sbp := src.toBytes()
+					if *sbp != nil {
+						dbp := dst.toBytes()
+						if !isProto3 || len(*sbp) > 0 {
+							*dbp = append([]byte{}, *sbp...)
+						}
+					}
+				}
+			}
+		case reflect.Struct:
+			switch {
+			case !isPointer:
+				panic(fmt.Sprintf("message field %s without pointer", tf))
+			case isSlice: // E.g., []*pb.T
+				mi := getMergeInfo(tf)
+				mfi.merge = func(dst, src pointer) {
+					sps := src.getPointerSlice()
+					if sps != nil {
+						dps := dst.getPointerSlice()
+						for _, sp := range sps {
+							var dp pointer
+							if !sp.isNil() {
+								dp = valToPointer(reflect.New(tf))
+								mi.merge(dp, sp)
+							}
+							dps = append(dps, dp)
+						}
+						if dps == nil {
+							dps = []pointer{}
+						}
+						dst.setPointerSlice(dps)
+					}
+				}
+			default: // E.g., *pb.T
+				mi := getMergeInfo(tf)
+				mfi.merge = func(dst, src pointer) {
+					sp := src.getPointer()
+					if !sp.isNil() {
+						dp := dst.getPointer()
+						if dp.isNil() {
+							dp = valToPointer(reflect.New(tf))
+							dst.setPointer(dp)
+						}
+						mi.merge(dp, sp)
+					}
+				}
+			}
+		case reflect.Map:
+			switch {
+			case isPointer || isSlice:
+				panic("bad pointer or slice in map case in " + tf.Name())
+			default: // E.g., map[K]V
+				mfi.merge = func(dst, src pointer) {
+					sm := src.asPointerTo(tf).Elem()
+					if sm.Len() == 0 {
+						return
+					}
+					dm := dst.asPointerTo(tf).Elem()
+					if dm.IsNil() {
+						dm.Set(reflect.MakeMap(tf))
+					}
+
+					switch tf.Elem().Kind() {
+					case reflect.Ptr: // Proto struct (e.g., *T)
+						for _, key := range sm.MapKeys() {
+							val := sm.MapIndex(key)
+							val = reflect.ValueOf(Clone(val.Interface().(Message)))
+							dm.SetMapIndex(key, val)
+						}
+					case reflect.Slice: // E.g. Bytes type (e.g., []byte)
+						for _, key := range sm.MapKeys() {
+							val := sm.MapIndex(key)
+							val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
+							dm.SetMapIndex(key, val)
+						}
+					default: // Basic type (e.g., string)
+						for _, key := range sm.MapKeys() {
+							val := sm.MapIndex(key)
+							dm.SetMapIndex(key, val)
+						}
+					}
+				}
+			}
+		case reflect.Interface:
+			// Must be oneof field.
+			switch {
+			case isPointer || isSlice:
+				panic("bad pointer or slice in interface case in " + tf.Name())
+			default: // E.g., interface{}
+				// TODO: Make this faster?
+				mfi.merge = func(dst, src pointer) {
+					su := src.asPointerTo(tf).Elem()
+					if !su.IsNil() {
+						du := dst.asPointerTo(tf).Elem()
+						typ := su.Elem().Type()
+						if du.IsNil() || du.Elem().Type() != typ {
+							du.Set(reflect.New(typ.Elem())) // Initialize interface if empty
+						}
+						sv := su.Elem().Elem().Field(0)
+						if sv.Kind() == reflect.Ptr && sv.IsNil() {
+							return
+						}
+						dv := du.Elem().Elem().Field(0)
+						if dv.Kind() == reflect.Ptr && dv.IsNil() {
+							dv.Set(reflect.New(sv.Type().Elem())) // Initialize proto message if empty
+						}
+						switch sv.Type().Kind() {
+						case reflect.Ptr: // Proto struct (e.g., *T)
+							Merge(dv.Interface().(Message), sv.Interface().(Message))
+						case reflect.Slice: // E.g. Bytes type (e.g., []byte)
+							dv.Set(reflect.ValueOf(append([]byte{}, sv.Bytes()...)))
+						default: // Basic type (e.g., string)
+							dv.Set(sv)
+						}
+					}
+				}
+			}
+		default:
+			panic(fmt.Sprintf("merger not found for type:%s", tf))
+		}
+		mi.fields = append(mi.fields, mfi)
+	}
+
+	mi.unrecognized = invalidField
+	if f, ok := t.FieldByName("XXX_unrecognized"); ok {
+		if f.Type != reflect.TypeOf([]byte{}) {
+			panic("expected XXX_unrecognized to be of type []byte")
+		}
+		mi.unrecognized = toField(&f)
+	}
+
+	atomic.StoreInt32(&mi.initialized, 1)
+}

+ 2053 - 0
vendor/github.com/golang/protobuf/proto/table_unmarshal.go

@@ -0,0 +1,2053 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors.  All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"math"
+	"reflect"
+	"strconv"
+	"strings"
+	"sync"
+	"sync/atomic"
+	"unicode/utf8"
+)
+
+// Unmarshal is the entry point from the generated .pb.go files.
+// This function is not intended to be used by non-generated code.
+// This function is not subject to any compatibility guarantee.
+// msg contains a pointer to a protocol buffer struct.
+// b is the data to be unmarshaled into the protocol buffer.
+// a is a pointer to a place to store cached unmarshal information.
+func (a *InternalMessageInfo) Unmarshal(msg Message, b []byte) error {
+	// Load the unmarshal information for this message type.
+	// The atomic load ensures memory consistency.
+	u := atomicLoadUnmarshalInfo(&a.unmarshal)
+	if u == nil {
+		// Slow path: find unmarshal info for msg, update a with it.
+		u = getUnmarshalInfo(reflect.TypeOf(msg).Elem())
+		atomicStoreUnmarshalInfo(&a.unmarshal, u)
+	}
+	// Then do the unmarshaling.
+	err := u.unmarshal(toPointer(&msg), b)
+	return err
+}
+
+type unmarshalInfo struct {
+	typ reflect.Type // type of the protobuf struct
+
+	// 0 = only typ field is initialized
+	// 1 = completely initialized
+	initialized     int32
+	lock            sync.Mutex                    // prevents double initialization
+	dense           []unmarshalFieldInfo          // fields indexed by tag #
+	sparse          map[uint64]unmarshalFieldInfo // fields indexed by tag #
+	reqFields       []string                      // names of required fields
+	reqMask         uint64                        // 1<<len(reqFields)-1
+	unrecognized    field                         // offset of []byte to put unrecognized data (or invalidField if we should throw it away)
+	extensions      field                         // offset of extensions field (of type proto.XXX_InternalExtensions), or invalidField if it does not exist
+	oldExtensions   field                         // offset of old-form extensions field (of type map[int]Extension)
+	extensionRanges []ExtensionRange              // if non-nil, implies extensions field is valid
+	isMessageSet    bool                          // if true, implies extensions field is valid
+}
+
+// An unmarshaler takes a stream of bytes and a pointer to a field of a message.
+// It decodes the field, stores it at f, and returns the unused bytes.
+// w is the wire encoding.
+// b is the data after the tag and wire encoding have been read.
+type unmarshaler func(b []byte, f pointer, w int) ([]byte, error)
+
+type unmarshalFieldInfo struct {
+	// location of the field in the proto message structure.
+	field field
+
+	// function to unmarshal the data for the field.
+	unmarshal unmarshaler
+
+	// if a required field, contains a single set bit at this field's index in the required field list.
+	reqMask uint64
+
+	name string // name of the field, for error reporting
+}
+
+var (
+	unmarshalInfoMap  = map[reflect.Type]*unmarshalInfo{}
+	unmarshalInfoLock sync.Mutex
+)
+
+// getUnmarshalInfo returns the data structure which can be
+// subsequently used to unmarshal a message of the given type.
+// t is the type of the message (note: not pointer to message).
+func getUnmarshalInfo(t reflect.Type) *unmarshalInfo {
+	// It would be correct to return a new unmarshalInfo
+	// unconditionally. We would end up allocating one
+	// per occurrence of that type as a message or submessage.
+	// We use a cache here just to reduce memory usage.
+	unmarshalInfoLock.Lock()
+	defer unmarshalInfoLock.Unlock()
+	u := unmarshalInfoMap[t]
+	if u == nil {
+		u = &unmarshalInfo{typ: t}
+		// Note: we just set the type here. The rest of the fields
+		// will be initialized on first use.
+		unmarshalInfoMap[t] = u
+	}
+	return u
+}
+
+// unmarshal does the main work of unmarshaling a message.
+// u provides type information used to unmarshal the message.
+// m is a pointer to a protocol buffer message.
+// b is a byte stream to unmarshal into m.
+// This is top routine used when recursively unmarshaling submessages.
+func (u *unmarshalInfo) unmarshal(m pointer, b []byte) error {
+	if atomic.LoadInt32(&u.initialized) == 0 {
+		u.computeUnmarshalInfo()
+	}
+	if u.isMessageSet {
+		return unmarshalMessageSet(b, m.offset(u.extensions).toExtensions())
+	}
+	var reqMask uint64 // bitmask of required fields we've seen.
+	var errLater error
+	for len(b) > 0 {
+		// Read tag and wire type.
+		// Special case 1 and 2 byte varints.
+		var x uint64
+		if b[0] < 128 {
+			x = uint64(b[0])
+			b = b[1:]
+		} else if len(b) >= 2 && b[1] < 128 {
+			x = uint64(b[0]&0x7f) + uint64(b[1])<<7
+			b = b[2:]
+		} else {
+			var n int
+			x, n = decodeVarint(b)
+			if n == 0 {
+				return io.ErrUnexpectedEOF
+			}
+			b = b[n:]
+		}
+		tag := x >> 3
+		wire := int(x) & 7
+
+		// Dispatch on the tag to one of the unmarshal* functions below.
+		var f unmarshalFieldInfo
+		if tag < uint64(len(u.dense)) {
+			f = u.dense[tag]
+		} else {
+			f = u.sparse[tag]
+		}
+		if fn := f.unmarshal; fn != nil {
+			var err error
+			b, err = fn(b, m.offset(f.field), wire)
+			if err == nil {
+				reqMask |= f.reqMask
+				continue
+			}
+			if r, ok := err.(*RequiredNotSetError); ok {
+				// Remember this error, but keep parsing. We need to produce
+				// a full parse even if a required field is missing.
+				if errLater == nil {
+					errLater = r
+				}
+				reqMask |= f.reqMask
+				continue
+			}
+			if err != errInternalBadWireType {
+				if err == errInvalidUTF8 {
+					if errLater == nil {
+						fullName := revProtoTypes[reflect.PtrTo(u.typ)] + "." + f.name
+						errLater = &invalidUTF8Error{fullName}
+					}
+					continue
+				}
+				return err
+			}
+			// Fragments with bad wire type are treated as unknown fields.
+		}
+
+		// Unknown tag.
+		if !u.unrecognized.IsValid() {
+			// Don't keep unrecognized data; just skip it.
+			var err error
+			b, err = skipField(b, wire)
+			if err != nil {
+				return err
+			}
+			continue
+		}
+		// Keep unrecognized data around.
+		// maybe in extensions, maybe in the unrecognized field.
+		z := m.offset(u.unrecognized).toBytes()
+		var emap map[int32]Extension
+		var e Extension
+		for _, r := range u.extensionRanges {
+			if uint64(r.Start) <= tag && tag <= uint64(r.End) {
+				if u.extensions.IsValid() {
+					mp := m.offset(u.extensions).toExtensions()
+					emap = mp.extensionsWrite()
+					e = emap[int32(tag)]
+					z = &e.enc
+					break
+				}
+				if u.oldExtensions.IsValid() {
+					p := m.offset(u.oldExtensions).toOldExtensions()
+					emap = *p
+					if emap == nil {
+						emap = map[int32]Extension{}
+						*p = emap
+					}
+					e = emap[int32(tag)]
+					z = &e.enc
+					break
+				}
+				panic("no extensions field available")
+			}
+		}
+
+		// Use wire type to skip data.
+		var err error
+		b0 := b
+		b, err = skipField(b, wire)
+		if err != nil {
+			return err
+		}
+		*z = encodeVarint(*z, tag<<3|uint64(wire))
+		*z = append(*z, b0[:len(b0)-len(b)]...)
+
+		if emap != nil {
+			emap[int32(tag)] = e
+		}
+	}
+	if reqMask != u.reqMask && errLater == nil {
+		// A required field of this message is missing.
+		for _, n := range u.reqFields {
+			if reqMask&1 == 0 {
+				errLater = &RequiredNotSetError{n}
+			}
+			reqMask >>= 1
+		}
+	}
+	return errLater
+}
+
+// computeUnmarshalInfo fills in u with information for use
+// in unmarshaling protocol buffers of type u.typ.
+func (u *unmarshalInfo) computeUnmarshalInfo() {
+	u.lock.Lock()
+	defer u.lock.Unlock()
+	if u.initialized != 0 {
+		return
+	}
+	t := u.typ
+	n := t.NumField()
+
+	// Set up the "not found" value for the unrecognized byte buffer.
+	// This is the default for proto3.
+	u.unrecognized = invalidField
+	u.extensions = invalidField
+	u.oldExtensions = invalidField
+
+	// List of the generated type and offset for each oneof field.
+	type oneofField struct {
+		ityp  reflect.Type // interface type of oneof field
+		field field        // offset in containing message
+	}
+	var oneofFields []oneofField
+
+	for i := 0; i < n; i++ {
+		f := t.Field(i)
+		if f.Name == "XXX_unrecognized" {
+			// The byte slice used to hold unrecognized input is special.
+			if f.Type != reflect.TypeOf(([]byte)(nil)) {
+				panic("bad type for XXX_unrecognized field: " + f.Type.Name())
+			}
+			u.unrecognized = toField(&f)
+			continue
+		}
+		if f.Name == "XXX_InternalExtensions" {
+			// Ditto here.
+			if f.Type != reflect.TypeOf(XXX_InternalExtensions{}) {
+				panic("bad type for XXX_InternalExtensions field: " + f.Type.Name())
+			}
+			u.extensions = toField(&f)
+			if f.Tag.Get("protobuf_messageset") == "1" {
+				u.isMessageSet = true
+			}
+			continue
+		}
+		if f.Name == "XXX_extensions" {
+			// An older form of the extensions field.
+			if f.Type != reflect.TypeOf((map[int32]Extension)(nil)) {
+				panic("bad type for XXX_extensions field: " + f.Type.Name())
+			}
+			u.oldExtensions = toField(&f)
+			continue
+		}
+		if f.Name == "XXX_NoUnkeyedLiteral" || f.Name == "XXX_sizecache" {
+			continue
+		}
+
+		oneof := f.Tag.Get("protobuf_oneof")
+		if oneof != "" {
+			oneofFields = append(oneofFields, oneofField{f.Type, toField(&f)})
+			// The rest of oneof processing happens below.
+			continue
+		}
+
+		tags := f.Tag.Get("protobuf")
+		tagArray := strings.Split(tags, ",")
+		if len(tagArray) < 2 {
+			panic("protobuf tag not enough fields in " + t.Name() + "." + f.Name + ": " + tags)
+		}
+		tag, err := strconv.Atoi(tagArray[1])
+		if err != nil {
+			panic("protobuf tag field not an integer: " + tagArray[1])
+		}
+
+		name := ""
+		for _, tag := range tagArray[3:] {
+			if strings.HasPrefix(tag, "name=") {
+				name = tag[5:]
+			}
+		}
+
+		// Extract unmarshaling function from the field (its type and tags).
+		unmarshal := fieldUnmarshaler(&f)
+
+		// Required field?
+		var reqMask uint64
+		if tagArray[2] == "req" {
+			bit := len(u.reqFields)
+			u.reqFields = append(u.reqFields, name)
+			reqMask = uint64(1) << uint(bit)
+			// TODO: if we have more than 64 required fields, we end up
+			// not verifying that all required fields are present.
+			// Fix this, perhaps using a count of required fields?
+		}
+
+		// Store the info in the correct slot in the message.
+		u.setTag(tag, toField(&f), unmarshal, reqMask, name)
+	}
+
+	// Find any types associated with oneof fields.
+	var oneofImplementers []interface{}
+	switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
+	case oneofFuncsIface:
+		_, _, _, oneofImplementers = m.XXX_OneofFuncs()
+	case oneofWrappersIface:
+		oneofImplementers = m.XXX_OneofWrappers()
+	}
+	for _, v := range oneofImplementers {
+		tptr := reflect.TypeOf(v) // *Msg_X
+		typ := tptr.Elem()        // Msg_X
+
+		f := typ.Field(0) // oneof implementers have one field
+		baseUnmarshal := fieldUnmarshaler(&f)
+		tags := strings.Split(f.Tag.Get("protobuf"), ",")
+		fieldNum, err := strconv.Atoi(tags[1])
+		if err != nil {
+			panic("protobuf tag field not an integer: " + tags[1])
+		}
+		var name string
+		for _, tag := range tags {
+			if strings.HasPrefix(tag, "name=") {
+				name = strings.TrimPrefix(tag, "name=")
+				break
+			}
+		}
+
+		// Find the oneof field that this struct implements.
+		// Might take O(n^2) to process all of the oneofs, but who cares.
+		for _, of := range oneofFields {
+			if tptr.Implements(of.ityp) {
+				// We have found the corresponding interface for this struct.
+				// That lets us know where this struct should be stored
+				// when we encounter it during unmarshaling.
+				unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal)
+				u.setTag(fieldNum, of.field, unmarshal, 0, name)
+			}
+		}
+
+	}
+
+	// Get extension ranges, if any.
+	fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray")
+	if fn.IsValid() {
+		if !u.extensions.IsValid() && !u.oldExtensions.IsValid() {
+			panic("a message with extensions, but no extensions field in " + t.Name())
+		}
+		u.extensionRanges = fn.Call(nil)[0].Interface().([]ExtensionRange)
+	}
+
+	// Explicitly disallow tag 0. This will ensure we flag an error
+	// when decoding a buffer of all zeros. Without this code, we
+	// would decode and skip an all-zero buffer of even length.
+	// [0 0] is [tag=0/wiretype=varint varint-encoded-0].
+	u.setTag(0, zeroField, func(b []byte, f pointer, w int) ([]byte, error) {
+		return nil, fmt.Errorf("proto: %s: illegal tag 0 (wire type %d)", t, w)
+	}, 0, "")
+
+	// Set mask for required field check.
+	u.reqMask = uint64(1)<<uint(len(u.reqFields)) - 1
+
+	atomic.StoreInt32(&u.initialized, 1)
+}
+
+// setTag stores the unmarshal information for the given tag.
+// tag = tag # for field
+// field/unmarshal = unmarshal info for that field.
+// reqMask = if required, bitmask for field position in required field list. 0 otherwise.
+// name = short name of the field.
+func (u *unmarshalInfo) setTag(tag int, field field, unmarshal unmarshaler, reqMask uint64, name string) {
+	i := unmarshalFieldInfo{field: field, unmarshal: unmarshal, reqMask: reqMask, name: name}
+	n := u.typ.NumField()
+	if tag >= 0 && (tag < 16 || tag < 2*n) { // TODO: what are the right numbers here?
+		for len(u.dense) <= tag {
+			u.dense = append(u.dense, unmarshalFieldInfo{})
+		}
+		u.dense[tag] = i
+		return
+	}
+	if u.sparse == nil {
+		u.sparse = map[uint64]unmarshalFieldInfo{}
+	}
+	u.sparse[uint64(tag)] = i
+}
+
+// fieldUnmarshaler returns an unmarshaler for the given field.
+func fieldUnmarshaler(f *reflect.StructField) unmarshaler {
+	if f.Type.Kind() == reflect.Map {
+		return makeUnmarshalMap(f)
+	}
+	return typeUnmarshaler(f.Type, f.Tag.Get("protobuf"))
+}
+
+// typeUnmarshaler returns an unmarshaler for the given field type / field tag pair.
+func typeUnmarshaler(t reflect.Type, tags string) unmarshaler {
+	tagArray := strings.Split(tags, ",")
+	encoding := tagArray[0]
+	name := "unknown"
+	proto3 := false
+	validateUTF8 := true
+	for _, tag := range tagArray[3:] {
+		if strings.HasPrefix(tag, "name=") {
+			name = tag[5:]
+		}
+		if tag == "proto3" {
+			proto3 = true
+		}
+	}
+	validateUTF8 = validateUTF8 && proto3
+
+	// Figure out packaging (pointer, slice, or both)
+	slice := false
+	pointer := false
+	if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 {
+		slice = true
+		t = t.Elem()
+	}
+	if t.Kind() == reflect.Ptr {
+		pointer = true
+		t = t.Elem()
+	}
+
+	// We'll never have both pointer and slice for basic types.
+	if pointer && slice && t.Kind() != reflect.Struct {
+		panic("both pointer and slice for basic type in " + t.Name())
+	}
+
+	switch t.Kind() {
+	case reflect.Bool:
+		if pointer {
+			return unmarshalBoolPtr
+		}
+		if slice {
+			return unmarshalBoolSlice
+		}
+		return unmarshalBoolValue
+	case reflect.Int32:
+		switch encoding {
+		case "fixed32":
+			if pointer {
+				return unmarshalFixedS32Ptr
+			}
+			if slice {
+				return unmarshalFixedS32Slice
+			}
+			return unmarshalFixedS32Value
+		case "varint":
+			// this could be int32 or enum
+			if pointer {
+				return unmarshalInt32Ptr
+			}
+			if slice {
+				return unmarshalInt32Slice
+			}
+			return unmarshalInt32Value
+		case "zigzag32":
+			if pointer {
+				return unmarshalSint32Ptr
+			}
+			if slice {
+				return unmarshalSint32Slice
+			}
+			return unmarshalSint32Value
+		}
+	case reflect.Int64:
+		switch encoding {
+		case "fixed64":
+			if pointer {
+				return unmarshalFixedS64Ptr
+			}
+			if slice {
+				return unmarshalFixedS64Slice
+			}
+			return unmarshalFixedS64Value
+		case "varint":
+			if pointer {
+				return unmarshalInt64Ptr
+			}
+			if slice {
+				return unmarshalInt64Slice
+			}
+			return unmarshalInt64Value
+		case "zigzag64":
+			if pointer {
+				return unmarshalSint64Ptr
+			}
+			if slice {
+				return unmarshalSint64Slice
+			}
+			return unmarshalSint64Value
+		}
+	case reflect.Uint32:
+		switch encoding {
+		case "fixed32":
+			if pointer {
+				return unmarshalFixed32Ptr
+			}
+			if slice {
+				return unmarshalFixed32Slice
+			}
+			return unmarshalFixed32Value
+		case "varint":
+			if pointer {
+				return unmarshalUint32Ptr
+			}
+			if slice {
+				return unmarshalUint32Slice
+			}
+			return unmarshalUint32Value
+		}
+	case reflect.Uint64:
+		switch encoding {
+		case "fixed64":
+			if pointer {
+				return unmarshalFixed64Ptr
+			}
+			if slice {
+				return unmarshalFixed64Slice
+			}
+			return unmarshalFixed64Value
+		case "varint":
+			if pointer {
+				return unmarshalUint64Ptr
+			}
+			if slice {
+				return unmarshalUint64Slice
+			}
+			return unmarshalUint64Value
+		}
+	case reflect.Float32:
+		if pointer {
+			return unmarshalFloat32Ptr
+		}
+		if slice {
+			return unmarshalFloat32Slice
+		}
+		return unmarshalFloat32Value
+	case reflect.Float64:
+		if pointer {
+			return unmarshalFloat64Ptr
+		}
+		if slice {
+			return unmarshalFloat64Slice
+		}
+		return unmarshalFloat64Value
+	case reflect.Map:
+		panic("map type in typeUnmarshaler in " + t.Name())
+	case reflect.Slice:
+		if pointer {
+			panic("bad pointer in slice case in " + t.Name())
+		}
+		if slice {
+			return unmarshalBytesSlice
+		}
+		return unmarshalBytesValue
+	case reflect.String:
+		if validateUTF8 {
+			if pointer {
+				return unmarshalUTF8StringPtr
+			}
+			if slice {
+				return unmarshalUTF8StringSlice
+			}
+			return unmarshalUTF8StringValue
+		}
+		if pointer {
+			return unmarshalStringPtr
+		}
+		if slice {
+			return unmarshalStringSlice
+		}
+		return unmarshalStringValue
+	case reflect.Struct:
+		// message or group field
+		if !pointer {
+			panic(fmt.Sprintf("message/group field %s:%s without pointer", t, encoding))
+		}
+		switch encoding {
+		case "bytes":
+			if slice {
+				return makeUnmarshalMessageSlicePtr(getUnmarshalInfo(t), name)
+			}
+			return makeUnmarshalMessagePtr(getUnmarshalInfo(t), name)
+		case "group":
+			if slice {
+				return makeUnmarshalGroupSlicePtr(getUnmarshalInfo(t), name)
+			}
+			return makeUnmarshalGroupPtr(getUnmarshalInfo(t), name)
+		}
+	}
+	panic(fmt.Sprintf("unmarshaler not found type:%s encoding:%s", t, encoding))
+}
+
+// Below are all the unmarshalers for individual fields of various types.
+
+func unmarshalInt64Value(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireVarint {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	v := int64(x)
+	*f.toInt64() = v
+	return b, nil
+}
+
+func unmarshalInt64Ptr(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireVarint {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	v := int64(x)
+	*f.toInt64Ptr() = &v
+	return b, nil
+}
+
+func unmarshalInt64Slice(b []byte, f pointer, w int) ([]byte, error) {
+	if w == WireBytes { // packed
+		x, n := decodeVarint(b)
+		if n == 0 {
+			return nil, io.ErrUnexpectedEOF
+		}
+		b = b[n:]
+		if x > uint64(len(b)) {
+			return nil, io.ErrUnexpectedEOF
+		}
+		res := b[x:]
+		b = b[:x]
+		for len(b) > 0 {
+			x, n = decodeVarint(b)
+			if n == 0 {
+				return nil, io.ErrUnexpectedEOF
+			}
+			b = b[n:]
+			v := int64(x)
+			s := f.toInt64Slice()
+			*s = append(*s, v)
+		}
+		return res, nil
+	}
+	if w != WireVarint {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	v := int64(x)
+	s := f.toInt64Slice()
+	*s = append(*s, v)
+	return b, nil
+}
+
+func unmarshalSint64Value(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireVarint {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	v := int64(x>>1) ^ int64(x)<<63>>63
+	*f.toInt64() = v
+	return b, nil
+}
+
+func unmarshalSint64Ptr(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireVarint {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	v := int64(x>>1) ^ int64(x)<<63>>63
+	*f.toInt64Ptr() = &v
+	return b, nil
+}
+
+func unmarshalSint64Slice(b []byte, f pointer, w int) ([]byte, error) {
+	if w == WireBytes { // packed
+		x, n := decodeVarint(b)
+		if n == 0 {
+			return nil, io.ErrUnexpectedEOF
+		}
+		b = b[n:]
+		if x > uint64(len(b)) {
+			return nil, io.ErrUnexpectedEOF
+		}
+		res := b[x:]
+		b = b[:x]
+		for len(b) > 0 {
+			x, n = decodeVarint(b)
+			if n == 0 {
+				return nil, io.ErrUnexpectedEOF
+			}
+			b = b[n:]
+			v := int64(x>>1) ^ int64(x)<<63>>63
+			s := f.toInt64Slice()
+			*s = append(*s, v)
+		}
+		return res, nil
+	}
+	if w != WireVarint {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	v := int64(x>>1) ^ int64(x)<<63>>63
+	s := f.toInt64Slice()
+	*s = append(*s, v)
+	return b, nil
+}
+
+func unmarshalUint64Value(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireVarint {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	v := uint64(x)
+	*f.toUint64() = v
+	return b, nil
+}
+
+func unmarshalUint64Ptr(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireVarint {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	v := uint64(x)
+	*f.toUint64Ptr() = &v
+	return b, nil
+}
+
+func unmarshalUint64Slice(b []byte, f pointer, w int) ([]byte, error) {
+	if w == WireBytes { // packed
+		x, n := decodeVarint(b)
+		if n == 0 {
+			return nil, io.ErrUnexpectedEOF
+		}
+		b = b[n:]
+		if x > uint64(len(b)) {
+			return nil, io.ErrUnexpectedEOF
+		}
+		res := b[x:]
+		b = b[:x]
+		for len(b) > 0 {
+			x, n = decodeVarint(b)
+			if n == 0 {
+				return nil, io.ErrUnexpectedEOF
+			}
+			b = b[n:]
+			v := uint64(x)
+			s := f.toUint64Slice()
+			*s = append(*s, v)
+		}
+		return res, nil
+	}
+	if w != WireVarint {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	v := uint64(x)
+	s := f.toUint64Slice()
+	*s = append(*s, v)
+	return b, nil
+}
+
+func unmarshalInt32Value(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireVarint {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	v := int32(x)
+	*f.toInt32() = v
+	return b, nil
+}
+
+func unmarshalInt32Ptr(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireVarint {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	v := int32(x)
+	f.setInt32Ptr(v)
+	return b, nil
+}
+
+func unmarshalInt32Slice(b []byte, f pointer, w int) ([]byte, error) {
+	if w == WireBytes { // packed
+		x, n := decodeVarint(b)
+		if n == 0 {
+			return nil, io.ErrUnexpectedEOF
+		}
+		b = b[n:]
+		if x > uint64(len(b)) {
+			return nil, io.ErrUnexpectedEOF
+		}
+		res := b[x:]
+		b = b[:x]
+		for len(b) > 0 {
+			x, n = decodeVarint(b)
+			if n == 0 {
+				return nil, io.ErrUnexpectedEOF
+			}
+			b = b[n:]
+			v := int32(x)
+			f.appendInt32Slice(v)
+		}
+		return res, nil
+	}
+	if w != WireVarint {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	v := int32(x)
+	f.appendInt32Slice(v)
+	return b, nil
+}
+
+func unmarshalSint32Value(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireVarint {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	v := int32(x>>1) ^ int32(x)<<31>>31
+	*f.toInt32() = v
+	return b, nil
+}
+
+func unmarshalSint32Ptr(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireVarint {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	v := int32(x>>1) ^ int32(x)<<31>>31
+	f.setInt32Ptr(v)
+	return b, nil
+}
+
+func unmarshalSint32Slice(b []byte, f pointer, w int) ([]byte, error) {
+	if w == WireBytes { // packed
+		x, n := decodeVarint(b)
+		if n == 0 {
+			return nil, io.ErrUnexpectedEOF
+		}
+		b = b[n:]
+		if x > uint64(len(b)) {
+			return nil, io.ErrUnexpectedEOF
+		}
+		res := b[x:]
+		b = b[:x]
+		for len(b) > 0 {
+			x, n = decodeVarint(b)
+			if n == 0 {
+				return nil, io.ErrUnexpectedEOF
+			}
+			b = b[n:]
+			v := int32(x>>1) ^ int32(x)<<31>>31
+			f.appendInt32Slice(v)
+		}
+		return res, nil
+	}
+	if w != WireVarint {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	v := int32(x>>1) ^ int32(x)<<31>>31
+	f.appendInt32Slice(v)
+	return b, nil
+}
+
+func unmarshalUint32Value(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireVarint {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	v := uint32(x)
+	*f.toUint32() = v
+	return b, nil
+}
+
+func unmarshalUint32Ptr(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireVarint {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	v := uint32(x)
+	*f.toUint32Ptr() = &v
+	return b, nil
+}
+
+func unmarshalUint32Slice(b []byte, f pointer, w int) ([]byte, error) {
+	if w == WireBytes { // packed
+		x, n := decodeVarint(b)
+		if n == 0 {
+			return nil, io.ErrUnexpectedEOF
+		}
+		b = b[n:]
+		if x > uint64(len(b)) {
+			return nil, io.ErrUnexpectedEOF
+		}
+		res := b[x:]
+		b = b[:x]
+		for len(b) > 0 {
+			x, n = decodeVarint(b)
+			if n == 0 {
+				return nil, io.ErrUnexpectedEOF
+			}
+			b = b[n:]
+			v := uint32(x)
+			s := f.toUint32Slice()
+			*s = append(*s, v)
+		}
+		return res, nil
+	}
+	if w != WireVarint {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	v := uint32(x)
+	s := f.toUint32Slice()
+	*s = append(*s, v)
+	return b, nil
+}
+
+func unmarshalFixed64Value(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireFixed64 {
+		return b, errInternalBadWireType
+	}
+	if len(b) < 8 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
+	*f.toUint64() = v
+	return b[8:], nil
+}
+
+func unmarshalFixed64Ptr(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireFixed64 {
+		return b, errInternalBadWireType
+	}
+	if len(b) < 8 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
+	*f.toUint64Ptr() = &v
+	return b[8:], nil
+}
+
+func unmarshalFixed64Slice(b []byte, f pointer, w int) ([]byte, error) {
+	if w == WireBytes { // packed
+		x, n := decodeVarint(b)
+		if n == 0 {
+			return nil, io.ErrUnexpectedEOF
+		}
+		b = b[n:]
+		if x > uint64(len(b)) {
+			return nil, io.ErrUnexpectedEOF
+		}
+		res := b[x:]
+		b = b[:x]
+		for len(b) > 0 {
+			if len(b) < 8 {
+				return nil, io.ErrUnexpectedEOF
+			}
+			v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
+			s := f.toUint64Slice()
+			*s = append(*s, v)
+			b = b[8:]
+		}
+		return res, nil
+	}
+	if w != WireFixed64 {
+		return b, errInternalBadWireType
+	}
+	if len(b) < 8 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
+	s := f.toUint64Slice()
+	*s = append(*s, v)
+	return b[8:], nil
+}
+
+func unmarshalFixedS64Value(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireFixed64 {
+		return b, errInternalBadWireType
+	}
+	if len(b) < 8 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56
+	*f.toInt64() = v
+	return b[8:], nil
+}
+
+func unmarshalFixedS64Ptr(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireFixed64 {
+		return b, errInternalBadWireType
+	}
+	if len(b) < 8 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56
+	*f.toInt64Ptr() = &v
+	return b[8:], nil
+}
+
+func unmarshalFixedS64Slice(b []byte, f pointer, w int) ([]byte, error) {
+	if w == WireBytes { // packed
+		x, n := decodeVarint(b)
+		if n == 0 {
+			return nil, io.ErrUnexpectedEOF
+		}
+		b = b[n:]
+		if x > uint64(len(b)) {
+			return nil, io.ErrUnexpectedEOF
+		}
+		res := b[x:]
+		b = b[:x]
+		for len(b) > 0 {
+			if len(b) < 8 {
+				return nil, io.ErrUnexpectedEOF
+			}
+			v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56
+			s := f.toInt64Slice()
+			*s = append(*s, v)
+			b = b[8:]
+		}
+		return res, nil
+	}
+	if w != WireFixed64 {
+		return b, errInternalBadWireType
+	}
+	if len(b) < 8 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56
+	s := f.toInt64Slice()
+	*s = append(*s, v)
+	return b[8:], nil
+}
+
+func unmarshalFixed32Value(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireFixed32 {
+		return b, errInternalBadWireType
+	}
+	if len(b) < 4 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+	*f.toUint32() = v
+	return b[4:], nil
+}
+
+func unmarshalFixed32Ptr(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireFixed32 {
+		return b, errInternalBadWireType
+	}
+	if len(b) < 4 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+	*f.toUint32Ptr() = &v
+	return b[4:], nil
+}
+
+func unmarshalFixed32Slice(b []byte, f pointer, w int) ([]byte, error) {
+	if w == WireBytes { // packed
+		x, n := decodeVarint(b)
+		if n == 0 {
+			return nil, io.ErrUnexpectedEOF
+		}
+		b = b[n:]
+		if x > uint64(len(b)) {
+			return nil, io.ErrUnexpectedEOF
+		}
+		res := b[x:]
+		b = b[:x]
+		for len(b) > 0 {
+			if len(b) < 4 {
+				return nil, io.ErrUnexpectedEOF
+			}
+			v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+			s := f.toUint32Slice()
+			*s = append(*s, v)
+			b = b[4:]
+		}
+		return res, nil
+	}
+	if w != WireFixed32 {
+		return b, errInternalBadWireType
+	}
+	if len(b) < 4 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+	s := f.toUint32Slice()
+	*s = append(*s, v)
+	return b[4:], nil
+}
+
+func unmarshalFixedS32Value(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireFixed32 {
+		return b, errInternalBadWireType
+	}
+	if len(b) < 4 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24
+	*f.toInt32() = v
+	return b[4:], nil
+}
+
+func unmarshalFixedS32Ptr(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireFixed32 {
+		return b, errInternalBadWireType
+	}
+	if len(b) < 4 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24
+	f.setInt32Ptr(v)
+	return b[4:], nil
+}
+
+func unmarshalFixedS32Slice(b []byte, f pointer, w int) ([]byte, error) {
+	if w == WireBytes { // packed
+		x, n := decodeVarint(b)
+		if n == 0 {
+			return nil, io.ErrUnexpectedEOF
+		}
+		b = b[n:]
+		if x > uint64(len(b)) {
+			return nil, io.ErrUnexpectedEOF
+		}
+		res := b[x:]
+		b = b[:x]
+		for len(b) > 0 {
+			if len(b) < 4 {
+				return nil, io.ErrUnexpectedEOF
+			}
+			v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24
+			f.appendInt32Slice(v)
+			b = b[4:]
+		}
+		return res, nil
+	}
+	if w != WireFixed32 {
+		return b, errInternalBadWireType
+	}
+	if len(b) < 4 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24
+	f.appendInt32Slice(v)
+	return b[4:], nil
+}
+
+func unmarshalBoolValue(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireVarint {
+		return b, errInternalBadWireType
+	}
+	// Note: any length varint is allowed, even though any sane
+	// encoder will use one byte.
+	// See https://github.com/golang/protobuf/issues/76
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	// TODO: check if x>1? Tests seem to indicate no.
+	v := x != 0
+	*f.toBool() = v
+	return b[n:], nil
+}
+
+func unmarshalBoolPtr(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireVarint {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := x != 0
+	*f.toBoolPtr() = &v
+	return b[n:], nil
+}
+
+func unmarshalBoolSlice(b []byte, f pointer, w int) ([]byte, error) {
+	if w == WireBytes { // packed
+		x, n := decodeVarint(b)
+		if n == 0 {
+			return nil, io.ErrUnexpectedEOF
+		}
+		b = b[n:]
+		if x > uint64(len(b)) {
+			return nil, io.ErrUnexpectedEOF
+		}
+		res := b[x:]
+		b = b[:x]
+		for len(b) > 0 {
+			x, n = decodeVarint(b)
+			if n == 0 {
+				return nil, io.ErrUnexpectedEOF
+			}
+			v := x != 0
+			s := f.toBoolSlice()
+			*s = append(*s, v)
+			b = b[n:]
+		}
+		return res, nil
+	}
+	if w != WireVarint {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := x != 0
+	s := f.toBoolSlice()
+	*s = append(*s, v)
+	return b[n:], nil
+}
+
+func unmarshalFloat64Value(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireFixed64 {
+		return b, errInternalBadWireType
+	}
+	if len(b) < 8 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56)
+	*f.toFloat64() = v
+	return b[8:], nil
+}
+
+func unmarshalFloat64Ptr(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireFixed64 {
+		return b, errInternalBadWireType
+	}
+	if len(b) < 8 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56)
+	*f.toFloat64Ptr() = &v
+	return b[8:], nil
+}
+
+func unmarshalFloat64Slice(b []byte, f pointer, w int) ([]byte, error) {
+	if w == WireBytes { // packed
+		x, n := decodeVarint(b)
+		if n == 0 {
+			return nil, io.ErrUnexpectedEOF
+		}
+		b = b[n:]
+		if x > uint64(len(b)) {
+			return nil, io.ErrUnexpectedEOF
+		}
+		res := b[x:]
+		b = b[:x]
+		for len(b) > 0 {
+			if len(b) < 8 {
+				return nil, io.ErrUnexpectedEOF
+			}
+			v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56)
+			s := f.toFloat64Slice()
+			*s = append(*s, v)
+			b = b[8:]
+		}
+		return res, nil
+	}
+	if w != WireFixed64 {
+		return b, errInternalBadWireType
+	}
+	if len(b) < 8 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56)
+	s := f.toFloat64Slice()
+	*s = append(*s, v)
+	return b[8:], nil
+}
+
+func unmarshalFloat32Value(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireFixed32 {
+		return b, errInternalBadWireType
+	}
+	if len(b) < 4 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24)
+	*f.toFloat32() = v
+	return b[4:], nil
+}
+
+func unmarshalFloat32Ptr(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireFixed32 {
+		return b, errInternalBadWireType
+	}
+	if len(b) < 4 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24)
+	*f.toFloat32Ptr() = &v
+	return b[4:], nil
+}
+
+func unmarshalFloat32Slice(b []byte, f pointer, w int) ([]byte, error) {
+	if w == WireBytes { // packed
+		x, n := decodeVarint(b)
+		if n == 0 {
+			return nil, io.ErrUnexpectedEOF
+		}
+		b = b[n:]
+		if x > uint64(len(b)) {
+			return nil, io.ErrUnexpectedEOF
+		}
+		res := b[x:]
+		b = b[:x]
+		for len(b) > 0 {
+			if len(b) < 4 {
+				return nil, io.ErrUnexpectedEOF
+			}
+			v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24)
+			s := f.toFloat32Slice()
+			*s = append(*s, v)
+			b = b[4:]
+		}
+		return res, nil
+	}
+	if w != WireFixed32 {
+		return b, errInternalBadWireType
+	}
+	if len(b) < 4 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24)
+	s := f.toFloat32Slice()
+	*s = append(*s, v)
+	return b[4:], nil
+}
+
+func unmarshalStringValue(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireBytes {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	if x > uint64(len(b)) {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := string(b[:x])
+	*f.toString() = v
+	return b[x:], nil
+}
+
+func unmarshalStringPtr(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireBytes {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	if x > uint64(len(b)) {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := string(b[:x])
+	*f.toStringPtr() = &v
+	return b[x:], nil
+}
+
+func unmarshalStringSlice(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireBytes {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	if x > uint64(len(b)) {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := string(b[:x])
+	s := f.toStringSlice()
+	*s = append(*s, v)
+	return b[x:], nil
+}
+
+func unmarshalUTF8StringValue(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireBytes {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	if x > uint64(len(b)) {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := string(b[:x])
+	*f.toString() = v
+	if !utf8.ValidString(v) {
+		return b[x:], errInvalidUTF8
+	}
+	return b[x:], nil
+}
+
+func unmarshalUTF8StringPtr(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireBytes {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	if x > uint64(len(b)) {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := string(b[:x])
+	*f.toStringPtr() = &v
+	if !utf8.ValidString(v) {
+		return b[x:], errInvalidUTF8
+	}
+	return b[x:], nil
+}
+
+func unmarshalUTF8StringSlice(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireBytes {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	if x > uint64(len(b)) {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := string(b[:x])
+	s := f.toStringSlice()
+	*s = append(*s, v)
+	if !utf8.ValidString(v) {
+		return b[x:], errInvalidUTF8
+	}
+	return b[x:], nil
+}
+
+var emptyBuf [0]byte
+
+func unmarshalBytesValue(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireBytes {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	if x > uint64(len(b)) {
+		return nil, io.ErrUnexpectedEOF
+	}
+	// The use of append here is a trick which avoids the zeroing
+	// that would be required if we used a make/copy pair.
+	// We append to emptyBuf instead of nil because we want
+	// a non-nil result even when the length is 0.
+	v := append(emptyBuf[:], b[:x]...)
+	*f.toBytes() = v
+	return b[x:], nil
+}
+
+func unmarshalBytesSlice(b []byte, f pointer, w int) ([]byte, error) {
+	if w != WireBytes {
+		return b, errInternalBadWireType
+	}
+	x, n := decodeVarint(b)
+	if n == 0 {
+		return nil, io.ErrUnexpectedEOF
+	}
+	b = b[n:]
+	if x > uint64(len(b)) {
+		return nil, io.ErrUnexpectedEOF
+	}
+	v := append(emptyBuf[:], b[:x]...)
+	s := f.toBytesSlice()
+	*s = append(*s, v)
+	return b[x:], nil
+}
+
+func makeUnmarshalMessagePtr(sub *unmarshalInfo, name string) unmarshaler {
+	return func(b []byte, f pointer, w int) ([]byte, error) {
+		if w != WireBytes {
+			return b, errInternalBadWireType
+		}
+		x, n := decodeVarint(b)
+		if n == 0 {
+			return nil, io.ErrUnexpectedEOF
+		}
+		b = b[n:]
+		if x > uint64(len(b)) {
+			return nil, io.ErrUnexpectedEOF
+		}
+		// First read the message field to see if something is there.
+		// The semantics of multiple submessages are weird.  Instead of
+		// the last one winning (as it is for all other fields), multiple
+		// submessages are merged.
+		v := f.getPointer()
+		if v.isNil() {
+			v = valToPointer(reflect.New(sub.typ))
+			f.setPointer(v)
+		}
+		err := sub.unmarshal(v, b[:x])
+		if err != nil {
+			if r, ok := err.(*RequiredNotSetError); ok {
+				r.field = name + "." + r.field
+			} else {
+				return nil, err
+			}
+		}
+		return b[x:], err
+	}
+}
+
+func makeUnmarshalMessageSlicePtr(sub *unmarshalInfo, name string) unmarshaler {
+	return func(b []byte, f pointer, w int) ([]byte, error) {
+		if w != WireBytes {
+			return b, errInternalBadWireType
+		}
+		x, n := decodeVarint(b)
+		if n == 0 {
+			return nil, io.ErrUnexpectedEOF
+		}
+		b = b[n:]
+		if x > uint64(len(b)) {
+			return nil, io.ErrUnexpectedEOF
+		}
+		v := valToPointer(reflect.New(sub.typ))
+		err := sub.unmarshal(v, b[:x])
+		if err != nil {
+			if r, ok := err.(*RequiredNotSetError); ok {
+				r.field = name + "." + r.field
+			} else {
+				return nil, err
+			}
+		}
+		f.appendPointer(v)
+		return b[x:], err
+	}
+}
+
+func makeUnmarshalGroupPtr(sub *unmarshalInfo, name string) unmarshaler {
+	return func(b []byte, f pointer, w int) ([]byte, error) {
+		if w != WireStartGroup {
+			return b, errInternalBadWireType
+		}
+		x, y := findEndGroup(b)
+		if x < 0 {
+			return nil, io.ErrUnexpectedEOF
+		}
+		v := f.getPointer()
+		if v.isNil() {
+			v = valToPointer(reflect.New(sub.typ))
+			f.setPointer(v)
+		}
+		err := sub.unmarshal(v, b[:x])
+		if err != nil {
+			if r, ok := err.(*RequiredNotSetError); ok {
+				r.field = name + "." + r.field
+			} else {
+				return nil, err
+			}
+		}
+		return b[y:], err
+	}
+}
+
+func makeUnmarshalGroupSlicePtr(sub *unmarshalInfo, name string) unmarshaler {
+	return func(b []byte, f pointer, w int) ([]byte, error) {
+		if w != WireStartGroup {
+			return b, errInternalBadWireType
+		}
+		x, y := findEndGroup(b)
+		if x < 0 {
+			return nil, io.ErrUnexpectedEOF
+		}
+		v := valToPointer(reflect.New(sub.typ))
+		err := sub.unmarshal(v, b[:x])
+		if err != nil {
+			if r, ok := err.(*RequiredNotSetError); ok {
+				r.field = name + "." + r.field
+			} else {
+				return nil, err
+			}
+		}
+		f.appendPointer(v)
+		return b[y:], err
+	}
+}
+
+func makeUnmarshalMap(f *reflect.StructField) unmarshaler {
+	t := f.Type
+	kt := t.Key()
+	vt := t.Elem()
+	unmarshalKey := typeUnmarshaler(kt, f.Tag.Get("protobuf_key"))
+	unmarshalVal := typeUnmarshaler(vt, f.Tag.Get("protobuf_val"))
+	return func(b []byte, f pointer, w int) ([]byte, error) {
+		// The map entry is a submessage. Figure out how big it is.
+		if w != WireBytes {
+			return nil, fmt.Errorf("proto: bad wiretype for map field: got %d want %d", w, WireBytes)
+		}
+		x, n := decodeVarint(b)
+		if n == 0 {
+			return nil, io.ErrUnexpectedEOF
+		}
+		b = b[n:]
+		if x > uint64(len(b)) {
+			return nil, io.ErrUnexpectedEOF
+		}
+		r := b[x:] // unused data to return
+		b = b[:x]  // data for map entry
+
+		// Note: we could use #keys * #values ~= 200 functions
+		// to do map decoding without reflection. Probably not worth it.
+		// Maps will be somewhat slow. Oh well.
+
+		// Read key and value from data.
+		var nerr nonFatal
+		k := reflect.New(kt)
+		v := reflect.New(vt)
+		for len(b) > 0 {
+			x, n := decodeVarint(b)
+			if n == 0 {
+				return nil, io.ErrUnexpectedEOF
+			}
+			wire := int(x) & 7
+			b = b[n:]
+
+			var err error
+			switch x >> 3 {
+			case 1:
+				b, err = unmarshalKey(b, valToPointer(k), wire)
+			case 2:
+				b, err = unmarshalVal(b, valToPointer(v), wire)
+			default:
+				err = errInternalBadWireType // skip unknown tag
+			}
+
+			if nerr.Merge(err) {
+				continue
+			}
+			if err != errInternalBadWireType {
+				return nil, err
+			}
+
+			// Skip past unknown fields.
+			b, err = skipField(b, wire)
+			if err != nil {
+				return nil, err
+			}
+		}
+
+		// Get map, allocate if needed.
+		m := f.asPointerTo(t).Elem() // an addressable map[K]T
+		if m.IsNil() {
+			m.Set(reflect.MakeMap(t))
+		}
+
+		// Insert into map.
+		m.SetMapIndex(k.Elem(), v.Elem())
+
+		return r, nerr.E
+	}
+}
+
+// makeUnmarshalOneof makes an unmarshaler for oneof fields.
+// for:
+// message Msg {
+//   oneof F {
+//     int64 X = 1;
+//     float64 Y = 2;
+//   }
+// }
+// typ is the type of the concrete entry for a oneof case (e.g. Msg_X).
+// ityp is the interface type of the oneof field (e.g. isMsg_F).
+// unmarshal is the unmarshaler for the base type of the oneof case (e.g. int64).
+// Note that this function will be called once for each case in the oneof.
+func makeUnmarshalOneof(typ, ityp reflect.Type, unmarshal unmarshaler) unmarshaler {
+	sf := typ.Field(0)
+	field0 := toField(&sf)
+	return func(b []byte, f pointer, w int) ([]byte, error) {
+		// Allocate holder for value.
+		v := reflect.New(typ)
+
+		// Unmarshal data into holder.
+		// We unmarshal into the first field of the holder object.
+		var err error
+		var nerr nonFatal
+		b, err = unmarshal(b, valToPointer(v).offset(field0), w)
+		if !nerr.Merge(err) {
+			return nil, err
+		}
+
+		// Write pointer to holder into target field.
+		f.asPointerTo(ityp).Elem().Set(v)
+
+		return b, nerr.E
+	}
+}
+
+// Error used by decode internally.
+var errInternalBadWireType = errors.New("proto: internal error: bad wiretype")
+
+// skipField skips past a field of type wire and returns the remaining bytes.
+func skipField(b []byte, wire int) ([]byte, error) {
+	switch wire {
+	case WireVarint:
+		_, k := decodeVarint(b)
+		if k == 0 {
+			return b, io.ErrUnexpectedEOF
+		}
+		b = b[k:]
+	case WireFixed32:
+		if len(b) < 4 {
+			return b, io.ErrUnexpectedEOF
+		}
+		b = b[4:]
+	case WireFixed64:
+		if len(b) < 8 {
+			return b, io.ErrUnexpectedEOF
+		}
+		b = b[8:]
+	case WireBytes:
+		m, k := decodeVarint(b)
+		if k == 0 || uint64(len(b)-k) < m {
+			return b, io.ErrUnexpectedEOF
+		}
+		b = b[uint64(k)+m:]
+	case WireStartGroup:
+		_, i := findEndGroup(b)
+		if i == -1 {
+			return b, io.ErrUnexpectedEOF
+		}
+		b = b[i:]
+	default:
+		return b, fmt.Errorf("proto: can't skip unknown wire type %d", wire)
+	}
+	return b, nil
+}
+
+// findEndGroup finds the index of the next EndGroup tag.
+// Groups may be nested, so the "next" EndGroup tag is the first
+// unpaired EndGroup.
+// findEndGroup returns the indexes of the start and end of the EndGroup tag.
+// Returns (-1,-1) if it can't find one.
+func findEndGroup(b []byte) (int, int) {
+	depth := 1
+	i := 0
+	for {
+		x, n := decodeVarint(b[i:])
+		if n == 0 {
+			return -1, -1
+		}
+		j := i
+		i += n
+		switch x & 7 {
+		case WireVarint:
+			_, k := decodeVarint(b[i:])
+			if k == 0 {
+				return -1, -1
+			}
+			i += k
+		case WireFixed32:
+			if len(b)-4 < i {
+				return -1, -1
+			}
+			i += 4
+		case WireFixed64:
+			if len(b)-8 < i {
+				return -1, -1
+			}
+			i += 8
+		case WireBytes:
+			m, k := decodeVarint(b[i:])
+			if k == 0 {
+				return -1, -1
+			}
+			i += k
+			if uint64(len(b)-i) < m {
+				return -1, -1
+			}
+			i += int(m)
+		case WireStartGroup:
+			depth++
+		case WireEndGroup:
+			depth--
+			if depth == 0 {
+				return j, i
+			}
+		default:
+			return -1, -1
+		}
+	}
+}
+
+// encodeVarint appends a varint-encoded integer to b and returns the result.
+func encodeVarint(b []byte, x uint64) []byte {
+	for x >= 1<<7 {
+		b = append(b, byte(x&0x7f|0x80))
+		x >>= 7
+	}
+	return append(b, byte(x))
+}
+
+// decodeVarint reads a varint-encoded integer from b.
+// Returns the decoded integer and the number of bytes read.
+// If there is an error, it returns 0,0.
+func decodeVarint(b []byte) (uint64, int) {
+	var x, y uint64
+	if len(b) == 0 {
+		goto bad
+	}
+	x = uint64(b[0])
+	if x < 0x80 {
+		return x, 1
+	}
+	x -= 0x80
+
+	if len(b) <= 1 {
+		goto bad
+	}
+	y = uint64(b[1])
+	x += y << 7
+	if y < 0x80 {
+		return x, 2
+	}
+	x -= 0x80 << 7
+
+	if len(b) <= 2 {
+		goto bad
+	}
+	y = uint64(b[2])
+	x += y << 14
+	if y < 0x80 {
+		return x, 3
+	}
+	x -= 0x80 << 14
+
+	if len(b) <= 3 {
+		goto bad
+	}
+	y = uint64(b[3])
+	x += y << 21
+	if y < 0x80 {
+		return x, 4
+	}
+	x -= 0x80 << 21
+
+	if len(b) <= 4 {
+		goto bad
+	}
+	y = uint64(b[4])
+	x += y << 28
+	if y < 0x80 {
+		return x, 5
+	}
+	x -= 0x80 << 28
+
+	if len(b) <= 5 {
+		goto bad
+	}
+	y = uint64(b[5])
+	x += y << 35
+	if y < 0x80 {
+		return x, 6
+	}
+	x -= 0x80 << 35
+
+	if len(b) <= 6 {
+		goto bad
+	}
+	y = uint64(b[6])
+	x += y << 42
+	if y < 0x80 {
+		return x, 7
+	}
+	x -= 0x80 << 42
+
+	if len(b) <= 7 {
+		goto bad
+	}
+	y = uint64(b[7])
+	x += y << 49
+	if y < 0x80 {
+		return x, 8
+	}
+	x -= 0x80 << 49
+
+	if len(b) <= 8 {
+		goto bad
+	}
+	y = uint64(b[8])
+	x += y << 56
+	if y < 0x80 {
+		return x, 9
+	}
+	x -= 0x80 << 56
+
+	if len(b) <= 9 {
+		goto bad
+	}
+	y = uint64(b[9])
+	x += y << 63
+	if y < 2 {
+		return x, 10
+	}
+
+bad:
+	return 0, 0
+}

+ 27 - 38
vendor/github.com/golang/protobuf/proto/text.go

@@ -50,7 +50,6 @@ import (
 var (
 	newline         = []byte("\n")
 	spaces          = []byte("                                        ")
-	gtNewline       = []byte(">\n")
 	endBraceNewline = []byte("}\n")
 	backslashN      = []byte{'\\', 'n'}
 	backslashR      = []byte{'\\', 'r'}
@@ -170,11 +169,6 @@ func writeName(w *textWriter, props *Properties) error {
 	return nil
 }
 
-// raw is the interface satisfied by RawMessage.
-type raw interface {
-	Bytes() []byte
-}
-
 func requiresQuotes(u string) bool {
 	// When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
 	for _, ch := range u {
@@ -269,6 +263,10 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
 		props := sprops.Prop[i]
 		name := st.Field(i).Name
 
+		if name == "XXX_NoUnkeyedLiteral" {
+			continue
+		}
+
 		if strings.HasPrefix(name, "XXX_") {
 			// There are two XXX_ fields:
 			//   XXX_unrecognized []byte
@@ -355,7 +353,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
 						return err
 					}
 				}
-				if err := tm.writeAny(w, key, props.mkeyprop); err != nil {
+				if err := tm.writeAny(w, key, props.MapKeyProp); err != nil {
 					return err
 				}
 				if err := w.WriteByte('\n'); err != nil {
@@ -372,7 +370,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
 							return err
 						}
 					}
-					if err := tm.writeAny(w, val, props.mvalprop); err != nil {
+					if err := tm.writeAny(w, val, props.MapValProp); err != nil {
 						return err
 					}
 					if err := w.WriteByte('\n'); err != nil {
@@ -436,12 +434,6 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
 				return err
 			}
 		}
-		if b, ok := fv.Interface().(raw); ok {
-			if err := writeRaw(w, b.Bytes()); err != nil {
-				return err
-			}
-			continue
-		}
 
 		// Enums have a String method, so writeAny will work fine.
 		if err := tm.writeAny(w, fv, props); err != nil {
@@ -455,7 +447,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
 
 	// Extensions (the XXX_extensions field).
 	pv := sv.Addr()
-	if _, ok := extendable(pv.Interface()); ok {
+	if _, err := extendable(pv.Interface()); err == nil {
 		if err := tm.writeExtensions(w, pv); err != nil {
 			return err
 		}
@@ -464,27 +456,6 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
 	return nil
 }
 
-// writeRaw writes an uninterpreted raw message.
-func writeRaw(w *textWriter, b []byte) error {
-	if err := w.WriteByte('<'); err != nil {
-		return err
-	}
-	if !w.compact {
-		if err := w.WriteByte('\n'); err != nil {
-			return err
-		}
-	}
-	w.indent()
-	if err := writeUnknownStruct(w, b); err != nil {
-		return err
-	}
-	w.unindent()
-	if err := w.WriteByte('>'); err != nil {
-		return err
-	}
-	return nil
-}
-
 // writeAny writes an arbitrary field.
 func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
 	v = reflect.Indirect(v)
@@ -535,6 +506,19 @@ func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Propert
 			}
 		}
 		w.indent()
+		if v.CanAddr() {
+			// Calling v.Interface on a struct causes the reflect package to
+			// copy the entire struct. This is racy with the new Marshaler
+			// since we atomically update the XXX_sizecache.
+			//
+			// Thus, we retrieve a pointer to the struct if possible to avoid
+			// a race since v.Interface on the pointer doesn't copy the struct.
+			//
+			// If v is not addressable, then we are not worried about a race
+			// since it implies that the binary Marshaler cannot possibly be
+			// mutating this value.
+			v = v.Addr()
+		}
 		if etm, ok := v.Interface().(encoding.TextMarshaler); ok {
 			text, err := etm.MarshalText()
 			if err != nil {
@@ -543,8 +527,13 @@ func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Propert
 			if _, err = w.Write(text); err != nil {
 				return err
 			}
-		} else if err := tm.writeStruct(w, v); err != nil {
-			return err
+		} else {
+			if v.Kind() == reflect.Ptr {
+				v = v.Elem()
+			}
+			if err := tm.writeStruct(w, v); err != nil {
+				return err
+			}
 		}
 		w.unindent()
 		if err := w.WriteByte(ket); err != nil {

+ 34 - 49
vendor/github.com/golang/protobuf/proto/text_parser.go

@@ -206,7 +206,6 @@ func (p *textParser) advance() {
 
 var (
 	errBadUTF8 = errors.New("proto: bad UTF-8")
-	errBadHex  = errors.New("proto: bad hexadecimal")
 )
 
 func unquoteC(s string, quote rune) (string, error) {
@@ -277,60 +276,47 @@ func unescape(s string) (ch string, tail string, err error) {
 		return "?", s, nil // trigraph workaround
 	case '\'', '"', '\\':
 		return string(r), s, nil
-	case '0', '1', '2', '3', '4', '5', '6', '7', 'x', 'X':
+	case '0', '1', '2', '3', '4', '5', '6', '7':
 		if len(s) < 2 {
 			return "", "", fmt.Errorf(`\%c requires 2 following digits`, r)
 		}
-		base := 8
-		ss := s[:2]
+		ss := string(r) + s[:2]
 		s = s[2:]
-		if r == 'x' || r == 'X' {
-			base = 16
-		} else {
-			ss = string(r) + ss
-		}
-		i, err := strconv.ParseUint(ss, base, 8)
+		i, err := strconv.ParseUint(ss, 8, 8)
 		if err != nil {
-			return "", "", err
+			return "", "", fmt.Errorf(`\%s contains non-octal digits`, ss)
 		}
 		return string([]byte{byte(i)}), s, nil
-	case 'u', 'U':
-		n := 4
-		if r == 'U' {
+	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 digits`, r, n)
-		}
-
-		bs := make([]byte, n/2)
-		for i := 0; i < n; i += 2 {
-			a, ok1 := unhex(s[i])
-			b, ok2 := unhex(s[i+1])
-			if !ok1 || !ok2 {
-				return "", "", errBadHex
-			}
-			bs[i/2] = a<<4 | b
+			return "", "", fmt.Errorf(`\%c requires %d following digits`, r, n)
 		}
+		ss := s[:n]
 		s = s[n:]
-		return string(bs), s, nil
+		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(i), s, nil
 	}
 	return "", "", fmt.Errorf(`unknown escape \%c`, r)
 }
 
-// Adapted from src/pkg/strconv/quote.go.
-func unhex(b byte) (v byte, ok bool) {
-	switch {
-	case '0' <= b && b <= '9':
-		return b - '0', true
-	case 'a' <= b && b <= 'f':
-		return b - 'a' + 10, true
-	case 'A' <= b && b <= 'F':
-		return b - 'A' + 10, true
-	}
-	return 0, false
-}
-
 // 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 }
@@ -644,17 +630,17 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
 					if err := p.consumeToken(":"); err != nil {
 						return err
 					}
-					if err := p.readAny(key, props.mkeyprop); err != nil {
+					if err := p.readAny(key, props.MapKeyProp); err != nil {
 						return err
 					}
 					if err := p.consumeOptionalSeparator(); err != nil {
 						return err
 					}
 				case "value":
-					if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil {
+					if err := p.checkForColon(props.MapValProp, dst.Type().Elem()); err != nil {
 						return err
 					}
-					if err := p.readAny(val, props.mvalprop); err != nil {
+					if err := p.readAny(val, props.MapValProp); err != nil {
 						return err
 					}
 					if err := p.consumeOptionalSeparator(); err != nil {
@@ -728,6 +714,9 @@ func (p *textParser) consumeExtName() (string, error) {
 		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
 }
@@ -865,7 +854,7 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error {
 		return p.readStruct(fv, terminator)
 	case reflect.Uint32:
 		if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
-			fv.SetUint(x)
+			fv.SetUint(uint64(x))
 			return nil
 		}
 	case reflect.Uint64:
@@ -883,13 +872,9 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error {
 // UnmarshalText returns *RequiredNotSetError.
 func UnmarshalText(s string, pb Message) error {
 	if um, ok := pb.(encoding.TextUnmarshaler); ok {
-		err := um.UnmarshalText([]byte(s))
-		return err
+		return um.UnmarshalText([]byte(s))
 	}
 	pb.Reset()
 	v := reflect.ValueOf(pb)
-	if pe := newTextParser(s).readStruct(v.Elem(), ""); pe != nil {
-		return pe
-	}
-	return nil
+	return newTextParser(s).readStruct(v.Elem(), "")
 }

+ 0 - 36
vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/Makefile

@@ -1,36 +0,0 @@
-# Go support for Protocol Buffers - Google's data interchange format
-#
-# Copyright 2010 The Go Authors.  All rights reserved.
-# https://github.com/golang/protobuf
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# Not stored here, but descriptor.proto is in https://github.com/google/protobuf/
-# at src/google/protobuf/descriptor.proto
-regenerate:
-	@echo WARNING! THIS RULE IS PROBABLY NOT RIGHT FOR YOUR INSTALLATION
-	protoc --go_out=../../../../.. -I$(HOME)/src/protobuf/include $(HOME)/src/protobuf/include/google/protobuf/descriptor.proto

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 556 - 115
vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go


+ 883 - 0
vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto

@@ -0,0 +1,883 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+//  Based on original Protocol Buffers design by
+//  Sanjay Ghemawat, Jeff Dean, and others.
+//
+// The messages in this file describe the definitions found in .proto files.
+// A valid .proto file can be translated directly to a FileDescriptorProto
+// without any other information (e.g. without reading its imports).
+
+
+syntax = "proto2";
+
+package google.protobuf;
+option go_package = "github.com/golang/protobuf/protoc-gen-go/descriptor;descriptor";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "DescriptorProtos";
+option csharp_namespace = "Google.Protobuf.Reflection";
+option objc_class_prefix = "GPB";
+option cc_enable_arenas = true;
+
+// descriptor.proto must be optimized for speed because reflection-based
+// algorithms don't work during bootstrapping.
+option optimize_for = SPEED;
+
+// The protocol compiler can output a FileDescriptorSet containing the .proto
+// files it parses.
+message FileDescriptorSet {
+  repeated FileDescriptorProto file = 1;
+}
+
+// Describes a complete .proto file.
+message FileDescriptorProto {
+  optional string name = 1;       // file name, relative to root of source tree
+  optional string package = 2;    // e.g. "foo", "foo.bar", etc.
+
+  // Names of files imported by this file.
+  repeated string dependency = 3;
+  // Indexes of the public imported files in the dependency list above.
+  repeated int32 public_dependency = 10;
+  // Indexes of the weak imported files in the dependency list.
+  // For Google-internal migration only. Do not use.
+  repeated int32 weak_dependency = 11;
+
+  // All top-level definitions in this file.
+  repeated DescriptorProto message_type = 4;
+  repeated EnumDescriptorProto enum_type = 5;
+  repeated ServiceDescriptorProto service = 6;
+  repeated FieldDescriptorProto extension = 7;
+
+  optional FileOptions options = 8;
+
+  // This field contains optional information about the original source code.
+  // You may safely remove this entire field without harming runtime
+  // functionality of the descriptors -- the information is needed only by
+  // development tools.
+  optional SourceCodeInfo source_code_info = 9;
+
+  // The syntax of the proto file.
+  // The supported values are "proto2" and "proto3".
+  optional string syntax = 12;
+}
+
+// Describes a message type.
+message DescriptorProto {
+  optional string name = 1;
+
+  repeated FieldDescriptorProto field = 2;
+  repeated FieldDescriptorProto extension = 6;
+
+  repeated DescriptorProto nested_type = 3;
+  repeated EnumDescriptorProto enum_type = 4;
+
+  message ExtensionRange {
+    optional int32 start = 1;
+    optional int32 end = 2;
+
+    optional ExtensionRangeOptions options = 3;
+  }
+  repeated ExtensionRange extension_range = 5;
+
+  repeated OneofDescriptorProto oneof_decl = 8;
+
+  optional MessageOptions options = 7;
+
+  // Range of reserved tag numbers. Reserved tag numbers may not be used by
+  // fields or extension ranges in the same message. Reserved ranges may
+  // not overlap.
+  message ReservedRange {
+    optional int32 start = 1; // Inclusive.
+    optional int32 end = 2;   // Exclusive.
+  }
+  repeated ReservedRange reserved_range = 9;
+  // Reserved field names, which may not be used by fields in the same message.
+  // A given name may only be reserved once.
+  repeated string reserved_name = 10;
+}
+
+message ExtensionRangeOptions {
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+}
+
+// Describes a field within a message.
+message FieldDescriptorProto {
+  enum Type {
+    // 0 is reserved for errors.
+    // Order is weird for historical reasons.
+    TYPE_DOUBLE         = 1;
+    TYPE_FLOAT          = 2;
+    // Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT64 if
+    // negative values are likely.
+    TYPE_INT64          = 3;
+    TYPE_UINT64         = 4;
+    // Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT32 if
+    // negative values are likely.
+    TYPE_INT32          = 5;
+    TYPE_FIXED64        = 6;
+    TYPE_FIXED32        = 7;
+    TYPE_BOOL           = 8;
+    TYPE_STRING         = 9;
+    // Tag-delimited aggregate.
+    // Group type is deprecated and not supported in proto3. However, Proto3
+    // implementations should still be able to parse the group wire format and
+    // treat group fields as unknown fields.
+    TYPE_GROUP          = 10;
+    TYPE_MESSAGE        = 11;  // Length-delimited aggregate.
+
+    // New in version 2.
+    TYPE_BYTES          = 12;
+    TYPE_UINT32         = 13;
+    TYPE_ENUM           = 14;
+    TYPE_SFIXED32       = 15;
+    TYPE_SFIXED64       = 16;
+    TYPE_SINT32         = 17;  // Uses ZigZag encoding.
+    TYPE_SINT64         = 18;  // Uses ZigZag encoding.
+  };
+
+  enum Label {
+    // 0 is reserved for errors
+    LABEL_OPTIONAL      = 1;
+    LABEL_REQUIRED      = 2;
+    LABEL_REPEATED      = 3;
+  };
+
+  optional string name = 1;
+  optional int32 number = 3;
+  optional Label label = 4;
+
+  // If type_name is set, this need not be set.  If both this and type_name
+  // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
+  optional Type type = 5;
+
+  // For message and enum types, this is the name of the type.  If the name
+  // starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
+  // rules are used to find the type (i.e. first the nested types within this
+  // message are searched, then within the parent, on up to the root
+  // namespace).
+  optional string type_name = 6;
+
+  // For extensions, this is the name of the type being extended.  It is
+  // resolved in the same manner as type_name.
+  optional string extendee = 2;
+
+  // For numeric types, contains the original text representation of the value.
+  // For booleans, "true" or "false".
+  // For strings, contains the default text contents (not escaped in any way).
+  // For bytes, contains the C escaped value.  All bytes >= 128 are escaped.
+  // TODO(kenton):  Base-64 encode?
+  optional string default_value = 7;
+
+  // If set, gives the index of a oneof in the containing type's oneof_decl
+  // list.  This field is a member of that oneof.
+  optional int32 oneof_index = 9;
+
+  // JSON name of this field. The value is set by protocol compiler. If the
+  // user has set a "json_name" option on this field, that option's value
+  // will be used. Otherwise, it's deduced from the field's name by converting
+  // it to camelCase.
+  optional string json_name = 10;
+
+  optional FieldOptions options = 8;
+}
+
+// Describes a oneof.
+message OneofDescriptorProto {
+  optional string name = 1;
+  optional OneofOptions options = 2;
+}
+
+// Describes an enum type.
+message EnumDescriptorProto {
+  optional string name = 1;
+
+  repeated EnumValueDescriptorProto value = 2;
+
+  optional EnumOptions options = 3;
+
+  // Range of reserved numeric values. Reserved values may not be used by
+  // entries in the same enum. Reserved ranges may not overlap.
+  //
+  // Note that this is distinct from DescriptorProto.ReservedRange in that it
+  // is inclusive such that it can appropriately represent the entire int32
+  // domain.
+  message EnumReservedRange {
+    optional int32 start = 1; // Inclusive.
+    optional int32 end = 2;   // Inclusive.
+  }
+
+  // Range of reserved numeric values. Reserved numeric values may not be used
+  // by enum values in the same enum declaration. Reserved ranges may not
+  // overlap.
+  repeated EnumReservedRange reserved_range = 4;
+
+  // Reserved enum value names, which may not be reused. A given name may only
+  // be reserved once.
+  repeated string reserved_name = 5;
+}
+
+// Describes a value within an enum.
+message EnumValueDescriptorProto {
+  optional string name = 1;
+  optional int32 number = 2;
+
+  optional EnumValueOptions options = 3;
+}
+
+// Describes a service.
+message ServiceDescriptorProto {
+  optional string name = 1;
+  repeated MethodDescriptorProto method = 2;
+
+  optional ServiceOptions options = 3;
+}
+
+// Describes a method of a service.
+message MethodDescriptorProto {
+  optional string name = 1;
+
+  // Input and output type names.  These are resolved in the same way as
+  // FieldDescriptorProto.type_name, but must refer to a message type.
+  optional string input_type = 2;
+  optional string output_type = 3;
+
+  optional MethodOptions options = 4;
+
+  // Identifies if client streams multiple client messages
+  optional bool client_streaming = 5 [default=false];
+  // Identifies if server streams multiple server messages
+  optional bool server_streaming = 6 [default=false];
+}
+
+
+// ===================================================================
+// Options
+
+// Each of the definitions above may have "options" attached.  These are
+// just annotations which may cause code to be generated slightly differently
+// or may contain hints for code that manipulates protocol messages.
+//
+// Clients may define custom options as extensions of the *Options messages.
+// These extensions may not yet be known at parsing time, so the parser cannot
+// store the values in them.  Instead it stores them in a field in the *Options
+// message called uninterpreted_option. This field must have the same name
+// across all *Options messages. We then use this field to populate the
+// extensions when we build a descriptor, at which point all protos have been
+// parsed and so all extensions are known.
+//
+// Extension numbers for custom options may be chosen as follows:
+// * For options which will only be used within a single application or
+//   organization, or for experimental options, use field numbers 50000
+//   through 99999.  It is up to you to ensure that you do not use the
+//   same number for multiple options.
+// * For options which will be published and used publicly by multiple
+//   independent entities, e-mail protobuf-global-extension-registry@google.com
+//   to reserve extension numbers. Simply provide your project name (e.g.
+//   Objective-C plugin) and your project website (if available) -- there's no
+//   need to explain how you intend to use them. Usually you only need one
+//   extension number. You can declare multiple options with only one extension
+//   number by putting them in a sub-message. See the Custom Options section of
+//   the docs for examples:
+//   https://developers.google.com/protocol-buffers/docs/proto#options
+//   If this turns out to be popular, a web service will be set up
+//   to automatically assign option numbers.
+
+
+message FileOptions {
+
+  // Sets the Java package where classes generated from this .proto will be
+  // placed.  By default, the proto package is used, but this is often
+  // inappropriate because proto packages do not normally start with backwards
+  // domain names.
+  optional string java_package = 1;
+
+
+  // If set, all the classes from the .proto file are wrapped in a single
+  // outer class with the given name.  This applies to both Proto1
+  // (equivalent to the old "--one_java_file" option) and Proto2 (where
+  // a .proto always translates to a single class, but you may want to
+  // explicitly choose the class name).
+  optional string java_outer_classname = 8;
+
+  // If set true, then the Java code generator will generate a separate .java
+  // file for each top-level message, enum, and service defined in the .proto
+  // file.  Thus, these types will *not* be nested inside the outer class
+  // named by java_outer_classname.  However, the outer class will still be
+  // generated to contain the file's getDescriptor() method as well as any
+  // top-level extensions defined in the file.
+  optional bool java_multiple_files = 10 [default=false];
+
+  // This option does nothing.
+  optional bool java_generate_equals_and_hash = 20 [deprecated=true];
+
+  // If set true, then the Java2 code generator will generate code that
+  // throws an exception whenever an attempt is made to assign a non-UTF-8
+  // byte sequence to a string field.
+  // Message reflection will do the same.
+  // However, an extension field still accepts non-UTF-8 byte sequences.
+  // This option has no effect on when used with the lite runtime.
+  optional bool java_string_check_utf8 = 27 [default=false];
+
+
+  // Generated classes can be optimized for speed or code size.
+  enum OptimizeMode {
+    SPEED = 1;        // Generate complete code for parsing, serialization,
+                      // etc.
+    CODE_SIZE = 2;    // Use ReflectionOps to implement these methods.
+    LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime.
+  }
+  optional OptimizeMode optimize_for = 9 [default=SPEED];
+
+  // Sets the Go package where structs generated from this .proto will be
+  // placed. If omitted, the Go package will be derived from the following:
+  //   - The basename of the package import path, if provided.
+  //   - Otherwise, the package statement in the .proto file, if present.
+  //   - Otherwise, the basename of the .proto file, without extension.
+  optional string go_package = 11;
+
+
+
+  // Should generic services be generated in each language?  "Generic" services
+  // are not specific to any particular RPC system.  They are generated by the
+  // main code generators in each language (without additional plugins).
+  // Generic services were the only kind of service generation supported by
+  // early versions of google.protobuf.
+  //
+  // Generic services are now considered deprecated in favor of using plugins
+  // that generate code specific to your particular RPC system.  Therefore,
+  // these default to false.  Old code which depends on generic services should
+  // explicitly set them to true.
+  optional bool cc_generic_services = 16 [default=false];
+  optional bool java_generic_services = 17 [default=false];
+  optional bool py_generic_services = 18 [default=false];
+  optional bool php_generic_services = 42 [default=false];
+
+  // Is this file deprecated?
+  // Depending on the target platform, this can emit Deprecated annotations
+  // for everything in the file, or it will be completely ignored; in the very
+  // least, this is a formalization for deprecating files.
+  optional bool deprecated = 23 [default=false];
+
+  // Enables the use of arenas for the proto messages in this file. This applies
+  // only to generated classes for C++.
+  optional bool cc_enable_arenas = 31 [default=false];
+
+
+  // Sets the objective c class prefix which is prepended to all objective c
+  // generated classes from this .proto. There is no default.
+  optional string objc_class_prefix = 36;
+
+  // Namespace for generated classes; defaults to the package.
+  optional string csharp_namespace = 37;
+
+  // By default Swift generators will take the proto package and CamelCase it
+  // replacing '.' with underscore and use that to prefix the types/symbols
+  // defined. When this options is provided, they will use this value instead
+  // to prefix the types/symbols defined.
+  optional string swift_prefix = 39;
+
+  // Sets the php class prefix which is prepended to all php generated classes
+  // from this .proto. Default is empty.
+  optional string php_class_prefix = 40;
+
+  // Use this option to change the namespace of php generated classes. Default
+  // is empty. When this option is empty, the package name will be used for
+  // determining the namespace.
+  optional string php_namespace = 41;
+
+
+  // Use this option to change the namespace of php generated metadata classes.
+  // Default is empty. When this option is empty, the proto file name will be used
+  // for determining the namespace.
+  optional string php_metadata_namespace = 44;
+
+  // Use this option to change the package of ruby generated classes. Default
+  // is empty. When this option is not set, the package name will be used for
+  // determining the ruby package.
+  optional string ruby_package = 45;
+
+  // The parser stores options it doesn't recognize here.
+  // See the documentation for the "Options" section above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message.
+  // See the documentation for the "Options" section above.
+  extensions 1000 to max;
+
+  reserved 38;
+}
+
+message MessageOptions {
+  // Set true to use the old proto1 MessageSet wire format for extensions.
+  // This is provided for backwards-compatibility with the MessageSet wire
+  // format.  You should not use this for any other reason:  It's less
+  // efficient, has fewer features, and is more complicated.
+  //
+  // The message must be defined exactly as follows:
+  //   message Foo {
+  //     option message_set_wire_format = true;
+  //     extensions 4 to max;
+  //   }
+  // Note that the message cannot have any defined fields; MessageSets only
+  // have extensions.
+  //
+  // All extensions of your type must be singular messages; e.g. they cannot
+  // be int32s, enums, or repeated messages.
+  //
+  // Because this is an option, the above two restrictions are not enforced by
+  // the protocol compiler.
+  optional bool message_set_wire_format = 1 [default=false];
+
+  // Disables the generation of the standard "descriptor()" accessor, which can
+  // conflict with a field of the same name.  This is meant to make migration
+  // from proto1 easier; new code should avoid fields named "descriptor".
+  optional bool no_standard_descriptor_accessor = 2 [default=false];
+
+  // Is this message deprecated?
+  // Depending on the target platform, this can emit Deprecated annotations
+  // for the message, or it will be completely ignored; in the very least,
+  // this is a formalization for deprecating messages.
+  optional bool deprecated = 3 [default=false];
+
+  // Whether the message is an automatically generated map entry type for the
+  // maps field.
+  //
+  // For maps fields:
+  //     map<KeyType, ValueType> map_field = 1;
+  // The parsed descriptor looks like:
+  //     message MapFieldEntry {
+  //         option map_entry = true;
+  //         optional KeyType key = 1;
+  //         optional ValueType value = 2;
+  //     }
+  //     repeated MapFieldEntry map_field = 1;
+  //
+  // Implementations may choose not to generate the map_entry=true message, but
+  // use a native map in the target language to hold the keys and values.
+  // The reflection APIs in such implementions still need to work as
+  // if the field is a repeated message field.
+  //
+  // NOTE: Do not set the option in .proto files. Always use the maps syntax
+  // instead. The option should only be implicitly set by the proto compiler
+  // parser.
+  optional bool map_entry = 7;
+
+  reserved 8;  // javalite_serializable
+  reserved 9;  // javanano_as_lite
+
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+}
+
+message FieldOptions {
+  // The ctype option instructs the C++ code generator to use a different
+  // representation of the field than it normally would.  See the specific
+  // options below.  This option is not yet implemented in the open source
+  // release -- sorry, we'll try to include it in a future version!
+  optional CType ctype = 1 [default = STRING];
+  enum CType {
+    // Default mode.
+    STRING = 0;
+
+    CORD = 1;
+
+    STRING_PIECE = 2;
+  }
+  // The packed option can be enabled for repeated primitive fields to enable
+  // a more efficient representation on the wire. Rather than repeatedly
+  // writing the tag and type for each element, the entire array is encoded as
+  // a single length-delimited blob. In proto3, only explicit setting it to
+  // false will avoid using packed encoding.
+  optional bool packed = 2;
+
+  // The jstype option determines the JavaScript type used for values of the
+  // field.  The option is permitted only for 64 bit integral and fixed types
+  // (int64, uint64, sint64, fixed64, sfixed64).  A field with jstype JS_STRING
+  // is represented as JavaScript string, which avoids loss of precision that
+  // can happen when a large value is converted to a floating point JavaScript.
+  // Specifying JS_NUMBER for the jstype causes the generated JavaScript code to
+  // use the JavaScript "number" type.  The behavior of the default option
+  // JS_NORMAL is implementation dependent.
+  //
+  // This option is an enum to permit additional types to be added, e.g.
+  // goog.math.Integer.
+  optional JSType jstype = 6 [default = JS_NORMAL];
+  enum JSType {
+    // Use the default type.
+    JS_NORMAL = 0;
+
+    // Use JavaScript strings.
+    JS_STRING = 1;
+
+    // Use JavaScript numbers.
+    JS_NUMBER = 2;
+  }
+
+  // Should this field be parsed lazily?  Lazy applies only to message-type
+  // fields.  It means that when the outer message is initially parsed, the
+  // inner message's contents will not be parsed but instead stored in encoded
+  // form.  The inner message will actually be parsed when it is first accessed.
+  //
+  // This is only a hint.  Implementations are free to choose whether to use
+  // eager or lazy parsing regardless of the value of this option.  However,
+  // setting this option true suggests that the protocol author believes that
+  // using lazy parsing on this field is worth the additional bookkeeping
+  // overhead typically needed to implement it.
+  //
+  // This option does not affect the public interface of any generated code;
+  // all method signatures remain the same.  Furthermore, thread-safety of the
+  // interface is not affected by this option; const methods remain safe to
+  // call from multiple threads concurrently, while non-const methods continue
+  // to require exclusive access.
+  //
+  //
+  // Note that implementations may choose not to check required fields within
+  // a lazy sub-message.  That is, calling IsInitialized() on the outer message
+  // may return true even if the inner message has missing required fields.
+  // This is necessary because otherwise the inner message would have to be
+  // parsed in order to perform the check, defeating the purpose of lazy
+  // parsing.  An implementation which chooses not to check required fields
+  // must be consistent about it.  That is, for any particular sub-message, the
+  // implementation must either *always* check its required fields, or *never*
+  // check its required fields, regardless of whether or not the message has
+  // been parsed.
+  optional bool lazy = 5 [default=false];
+
+  // Is this field deprecated?
+  // Depending on the target platform, this can emit Deprecated annotations
+  // for accessors, or it will be completely ignored; in the very least, this
+  // is a formalization for deprecating fields.
+  optional bool deprecated = 3 [default=false];
+
+  // For Google-internal migration only. Do not use.
+  optional bool weak = 10 [default=false];
+
+
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+
+  reserved 4;  // removed jtype
+}
+
+message OneofOptions {
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+}
+
+message EnumOptions {
+
+  // Set this option to true to allow mapping different tag names to the same
+  // value.
+  optional bool allow_alias = 2;
+
+  // Is this enum deprecated?
+  // Depending on the target platform, this can emit Deprecated annotations
+  // for the enum, or it will be completely ignored; in the very least, this
+  // is a formalization for deprecating enums.
+  optional bool deprecated = 3 [default=false];
+
+  reserved 5;  // javanano_as_lite
+
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+}
+
+message EnumValueOptions {
+  // Is this enum value deprecated?
+  // Depending on the target platform, this can emit Deprecated annotations
+  // for the enum value, or it will be completely ignored; in the very least,
+  // this is a formalization for deprecating enum values.
+  optional bool deprecated = 1 [default=false];
+
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+}
+
+message ServiceOptions {
+
+  // Note:  Field numbers 1 through 32 are reserved for Google's internal RPC
+  //   framework.  We apologize for hoarding these numbers to ourselves, but
+  //   we were already using them long before we decided to release Protocol
+  //   Buffers.
+
+  // Is this service deprecated?
+  // Depending on the target platform, this can emit Deprecated annotations
+  // for the service, or it will be completely ignored; in the very least,
+  // this is a formalization for deprecating services.
+  optional bool deprecated = 33 [default=false];
+
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+}
+
+message MethodOptions {
+
+  // Note:  Field numbers 1 through 32 are reserved for Google's internal RPC
+  //   framework.  We apologize for hoarding these numbers to ourselves, but
+  //   we were already using them long before we decided to release Protocol
+  //   Buffers.
+
+  // Is this method deprecated?
+  // Depending on the target platform, this can emit Deprecated annotations
+  // for the method, or it will be completely ignored; in the very least,
+  // this is a formalization for deprecating methods.
+  optional bool deprecated = 33 [default=false];
+
+  // Is this method side-effect-free (or safe in HTTP parlance), or idempotent,
+  // or neither? HTTP based RPC implementation may choose GET verb for safe
+  // methods, and PUT verb for idempotent methods instead of the default POST.
+  enum IdempotencyLevel {
+    IDEMPOTENCY_UNKNOWN = 0;
+    NO_SIDE_EFFECTS     = 1; // implies idempotent
+    IDEMPOTENT          = 2; // idempotent, but may have side effects
+  }
+  optional IdempotencyLevel idempotency_level =
+      34 [default=IDEMPOTENCY_UNKNOWN];
+
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+}
+
+
+// A message representing a option the parser does not recognize. This only
+// appears in options protos created by the compiler::Parser class.
+// DescriptorPool resolves these when building Descriptor objects. Therefore,
+// options protos in descriptor objects (e.g. returned by Descriptor::options(),
+// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
+// in them.
+message UninterpretedOption {
+  // The name of the uninterpreted option.  Each string represents a segment in
+  // a dot-separated name.  is_extension is true iff a segment represents an
+  // extension (denoted with parentheses in options specs in .proto files).
+  // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
+  // "foo.(bar.baz).qux".
+  message NamePart {
+    required string name_part = 1;
+    required bool is_extension = 2;
+  }
+  repeated NamePart name = 2;
+
+  // The value of the uninterpreted option, in whatever type the tokenizer
+  // identified it as during parsing. Exactly one of these should be set.
+  optional string identifier_value = 3;
+  optional uint64 positive_int_value = 4;
+  optional int64 negative_int_value = 5;
+  optional double double_value = 6;
+  optional bytes string_value = 7;
+  optional string aggregate_value = 8;
+}
+
+// ===================================================================
+// Optional source code info
+
+// Encapsulates information about the original source file from which a
+// FileDescriptorProto was generated.
+message SourceCodeInfo {
+  // A Location identifies a piece of source code in a .proto file which
+  // corresponds to a particular definition.  This information is intended
+  // to be useful to IDEs, code indexers, documentation generators, and similar
+  // tools.
+  //
+  // For example, say we have a file like:
+  //   message Foo {
+  //     optional string foo = 1;
+  //   }
+  // Let's look at just the field definition:
+  //   optional string foo = 1;
+  //   ^       ^^     ^^  ^  ^^^
+  //   a       bc     de  f  ghi
+  // We have the following locations:
+  //   span   path               represents
+  //   [a,i)  [ 4, 0, 2, 0 ]     The whole field definition.
+  //   [a,b)  [ 4, 0, 2, 0, 4 ]  The label (optional).
+  //   [c,d)  [ 4, 0, 2, 0, 5 ]  The type (string).
+  //   [e,f)  [ 4, 0, 2, 0, 1 ]  The name (foo).
+  //   [g,h)  [ 4, 0, 2, 0, 3 ]  The number (1).
+  //
+  // Notes:
+  // - A location may refer to a repeated field itself (i.e. not to any
+  //   particular index within it).  This is used whenever a set of elements are
+  //   logically enclosed in a single code segment.  For example, an entire
+  //   extend block (possibly containing multiple extension definitions) will
+  //   have an outer location whose path refers to the "extensions" repeated
+  //   field without an index.
+  // - Multiple locations may have the same path.  This happens when a single
+  //   logical declaration is spread out across multiple places.  The most
+  //   obvious example is the "extend" block again -- there may be multiple
+  //   extend blocks in the same scope, each of which will have the same path.
+  // - A location's span is not always a subset of its parent's span.  For
+  //   example, the "extendee" of an extension declaration appears at the
+  //   beginning of the "extend" block and is shared by all extensions within
+  //   the block.
+  // - Just because a location's span is a subset of some other location's span
+  //   does not mean that it is a descendent.  For example, a "group" defines
+  //   both a type and a field in a single declaration.  Thus, the locations
+  //   corresponding to the type and field and their components will overlap.
+  // - Code which tries to interpret locations should probably be designed to
+  //   ignore those that it doesn't understand, as more types of locations could
+  //   be recorded in the future.
+  repeated Location location = 1;
+  message Location {
+    // Identifies which part of the FileDescriptorProto was defined at this
+    // location.
+    //
+    // Each element is a field number or an index.  They form a path from
+    // the root FileDescriptorProto to the place where the definition.  For
+    // example, this path:
+    //   [ 4, 3, 2, 7, 1 ]
+    // refers to:
+    //   file.message_type(3)  // 4, 3
+    //       .field(7)         // 2, 7
+    //       .name()           // 1
+    // This is because FileDescriptorProto.message_type has field number 4:
+    //   repeated DescriptorProto message_type = 4;
+    // and DescriptorProto.field has field number 2:
+    //   repeated FieldDescriptorProto field = 2;
+    // and FieldDescriptorProto.name has field number 1:
+    //   optional string name = 1;
+    //
+    // Thus, the above path gives the location of a field name.  If we removed
+    // the last element:
+    //   [ 4, 3, 2, 7 ]
+    // this path refers to the whole field declaration (from the beginning
+    // of the label to the terminating semicolon).
+    repeated int32 path = 1 [packed=true];
+
+    // Always has exactly three or four elements: start line, start column,
+    // end line (optional, otherwise assumed same as start line), end column.
+    // These are packed into a single field for efficiency.  Note that line
+    // and column numbers are zero-based -- typically you will want to add
+    // 1 to each before displaying to a user.
+    repeated int32 span = 2 [packed=true];
+
+    // If this SourceCodeInfo represents a complete declaration, these are any
+    // comments appearing before and after the declaration which appear to be
+    // attached to the declaration.
+    //
+    // A series of line comments appearing on consecutive lines, with no other
+    // tokens appearing on those lines, will be treated as a single comment.
+    //
+    // leading_detached_comments will keep paragraphs of comments that appear
+    // before (but not connected to) the current element. Each paragraph,
+    // separated by empty lines, will be one comment element in the repeated
+    // field.
+    //
+    // Only the comment content is provided; comment markers (e.g. //) are
+    // stripped out.  For block comments, leading whitespace and an asterisk
+    // will be stripped from the beginning of each line other than the first.
+    // Newlines are included in the output.
+    //
+    // Examples:
+    //
+    //   optional int32 foo = 1;  // Comment attached to foo.
+    //   // Comment attached to bar.
+    //   optional int32 bar = 2;
+    //
+    //   optional string baz = 3;
+    //   // Comment attached to baz.
+    //   // Another line attached to baz.
+    //
+    //   // Comment attached to qux.
+    //   //
+    //   // Another line attached to qux.
+    //   optional double qux = 4;
+    //
+    //   // Detached comment for corge. This is not leading or trailing comments
+    //   // to qux or corge because there are blank lines separating it from
+    //   // both.
+    //
+    //   // Detached comment for corge paragraph 2.
+    //
+    //   optional string corge = 5;
+    //   /* Block comment attached
+    //    * to corge.  Leading asterisks
+    //    * will be removed. */
+    //   /* Block comment attached to
+    //    * grault. */
+    //   optional int32 grault = 6;
+    //
+    //   // ignored detached comments.
+    optional string leading_comments = 3;
+    optional string trailing_comments = 4;
+    repeated string leading_detached_comments = 6;
+  }
+}
+
+// Describes the relationship between generated code and its original source
+// file. A GeneratedCodeInfo message is associated with only one generated
+// source file, but may contain references to different source .proto files.
+message GeneratedCodeInfo {
+  // An Annotation connects some span of text in generated code to an element
+  // of its generating .proto file.
+  repeated Annotation annotation = 1;
+  message Annotation {
+    // Identifies the element in the original source .proto file. This field
+    // is formatted the same as SourceCodeInfo.Location.path.
+    repeated int32 path = 1 [packed=true];
+
+    // Identifies the filesystem path to the original source .proto.
+    optional string source_file = 2;
+
+    // Identifies the starting offset in bytes in the generated code
+    // that relates to the identified object.
+    optional int32 begin = 3;
+
+    // Identifies the ending offset in bytes in the generated code that
+    // relates to the identified offset. The end offset should be one past
+    // the last relevant byte (so the length of the text = end - begin).
+    optional int32 end = 4;
+  }
+}

+ 0 - 8
vendor/github.com/karalabe/hid/LICENSE.md

@@ -1,8 +0,0 @@
-The components of `hid` are licensed as such:
-
- * `hidapi` is released under the [3-clause BSD](https://github.com/signal11/hidapi/blob/master/LICENSE-bsd.txt) license.
- * `libusb` is released under the [GNU LGPL 2.1](https://github.com/libusb/libusb/blob/master/COPYING)license.
- * `go.hid` is released under the [2-clause BSD](https://github.com/GeertJohan/go.hid/blob/master/LICENSE) license.
- * `gowchar` is released under the [3-clause BSD](https://github.com/orofarne/gowchar/blob/master/LICENSE) license.
-
-Given the above, `hid` is licensed under GNU LGPL 2.1 or later on Linux and 3-clause BSD on other platforms.

+ 0 - 53
vendor/github.com/karalabe/hid/README.md

@@ -1,53 +0,0 @@
-[![Travis][travisimg]][travisurl]
-[![AppVeyor][appveyorimg]][appveyorurl]
-[![GoDoc][docimg]][docurl]
-
-[travisimg]:   https://travis-ci.org/karalabe/hid.svg?branch=master
-[travisurl]:   https://travis-ci.org/karalabe/hid
-[appveyorimg]: https://ci.appveyor.com/api/projects/status/plroy54odykb0ch3/branch/master?svg=true
-[appveyorurl]: https://ci.appveyor.com/project/karalabe/hid
-[docimg]:      https://godoc.org/github.com/karalabe/hid?status.svg
-[docurl]:      https://godoc.org/github.com/karalabe/hid
-
-# Gopher Interface Devices (USB HID)
-
-The `hid` package is a cross platform library for accessing and communicating with USB Human Interface
-Devices (HID). It is an alternative package to [`gousb`](https://github.com/karalabe/gousb) for use
-cases where devices support this ligher mode of operation (e.g. input devices, hardware crypto wallets).
-
-The package wraps [`hidapi`](https://github.com/signal11/hidapi) for accessing OS specific USB HID APIs
-directly instead of using low level USB constructs, which might have permission issues on some platforms.
-On Linux the package also wraps [`libusb`](https://github.com/libusb/libusb). Both of these dependencies
-are vendored directly into the repository and wrapped using CGO, making the `hid` package self-contained
-and go-gettable.
-
-Supported platforms at the moment are Linux, macOS and Windows (exclude constraints are also specified
-for Android and iOS to allow smoother vendoring into cross platform projects).
-
-## Cross-compiling
-
-Using `go get` the embedded C library is compiled into the binary format of your host OS. Cross compiling to a different platform or architecture entails disabling CGO by default in Go, causing device enumeration `hid.Enumerate()` to yield no results.
-
-To cross compile a functional version of this library, you'll need to enable CGO during cross compilation via `CGO_ENABLED=1` and you'll need to install and set a cross compilation enabled C toolkit via `CC=your-cross-gcc`.
-
-## Acknowledgements
-
-Although the `hid` package is an implementation from scratch, it was heavily inspired by the existing
-[`go.hid`](https://github.com/GeertJohan/go.hid) library, which seems abandoned since 2015; is incompatible
-with Go 1.6+; and has various external dependencies. Given its inspirational roots, I thought it important
-to give credit to the author of said package too.
-
-Wide character support in the `hid` package is done via the [`gowchar`](https://github.com/orofarne/gowchar)
-library, unmaintained since 2013; non buildable with a modern Go release and failing `go vet` checks. As
-such, `gowchar` was also vendored in inline (copyright headers and origins preserved).
-
-## License
-
-The components of `hid` are licensed as such:
-
- * `hidapi` is released under the [3-clause BSD](https://github.com/signal11/hidapi/blob/master/LICENSE-bsd.txt) license.
- * `libusb` is released under the [GNU LGPL 2.1](https://github.com/libusb/libusb/blob/master/COPYING)license.
- * `go.hid` is released under the [2-clause BSD](https://github.com/GeertJohan/go.hid/blob/master/LICENSE) license.
- * `gowchar` is released under the [3-clause BSD](https://github.com/orofarne/gowchar/blob/master/LICENSE) license.
-
-Given the above, `hid` is licensed under GNU LGPL 2.1 or later on Linux and 3-clause BSD on other platforms.

+ 0 - 37
vendor/github.com/karalabe/hid/hid.go

@@ -1,37 +0,0 @@
-// hid - Gopher Interface Devices (USB HID)
-// Copyright (c) 2017 Péter Szilágyi. All rights reserved.
-//
-// This file is released under the 3-clause BSD license. Note however that Linux
-// support depends on libusb, released under GNU LGPL 2.1 or later.
-
-// Package hid provides an interface for USB HID devices.
-package hid
-
-import "errors"
-
-// ErrDeviceClosed is returned for operations where the device closed before or
-// during the execution.
-var ErrDeviceClosed = errors.New("hid: device closed")
-
-// ErrUnsupportedPlatform is returned for all operations where the underlying
-// operating system is not supported by the library.
-var ErrUnsupportedPlatform = errors.New("hid: unsupported platform")
-
-// DeviceInfo is a hidapi info structure.
-type DeviceInfo struct {
-	Path         string // Platform-specific device path
-	VendorID     uint16 // Device Vendor ID
-	ProductID    uint16 // Device Product ID
-	Release      uint16 // Device Release Number in binary-coded decimal, also known as Device Version Number
-	Serial       string // Serial Number
-	Manufacturer string // Manufacturer String
-	Product      string // Product string
-	UsagePage    uint16 // Usage Page for this Device/Interface (Windows/Mac only)
-	Usage        uint16 // Usage for this Device/Interface (Windows/Mac only)
-
-	// The USB interface which this logical device
-	// represents. Valid on both Linux implementations
-	// in all cases, and valid on the Windows implementation
-	// only if the device contains more than one interface.
-	Interface int
-}

+ 0 - 51
vendor/github.com/karalabe/hid/hid_disabled.go

@@ -1,51 +0,0 @@
-// hid - Gopher Interface Devices (USB HID)
-// Copyright (c) 2017 Péter Szilágyi. All rights reserved.
-//
-// This file is released under the 3-clause BSD license. Note however that Linux
-// support depends on libusb, released under GNU LGPL 2.1 or later.
-
-// +build !linux,!darwin,!windows ios !cgo
-
-package hid
-
-// Supported returns whether this platform is supported by the HID library or not.
-// The goal of this method is to allow programatically handling platforms that do
-// not support USB HID and not having to fall back to build constraints.
-func Supported() bool {
-	return false
-}
-
-// Enumerate returns a list of all the HID devices attached to the system which
-// match the vendor and product id. On platforms that this file implements the
-// function is a noop and returns an empty list always.
-func Enumerate(vendorID uint16, productID uint16) []DeviceInfo {
-	return nil
-}
-
-// Device is a live HID USB connected device handle. On platforms that this file
-// implements the type lacks the actual HID device and all methods are noop.
-type Device struct {
-	DeviceInfo // Embed the infos for easier access
-}
-
-// Open connects to an HID device by its path name. On platforms that this file
-// implements the method just returns an error.
-func (info DeviceInfo) Open() (*Device, error) {
-	return nil, ErrUnsupportedPlatform
-}
-
-// Close releases the HID USB device handle. On platforms that this file implements
-// the method is just a noop.
-func (dev *Device) Close() error { return nil }
-
-// Write sends an output report to a HID device. On platforms that this file
-// implements the method just returns an error.
-func (dev *Device) Write(b []byte) (int, error) {
-	return 0, ErrUnsupportedPlatform
-}
-
-// Read retrieves an input report from a HID device. On platforms that this file
-// implements the method just returns an error.
-func (dev *Device) Read(b []byte) (int, error) {
-	return 0, ErrUnsupportedPlatform
-}

+ 0 - 728
vendor/github.com/karalabe/hid/libusb/libusb/os/poll_windows.c

@@ -1,728 +0,0 @@
-/*
- * poll_windows: poll compatibility wrapper for Windows
- * Copyright © 2012-2013 RealVNC Ltd.
- * Copyright © 2009-2010 Pete Batard <pete@akeo.ie>
- * With contributions from Michael Plante, Orin Eman et al.
- * Parts of poll implementation from libusb-win32, by Stephan Meyer et al.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-/*
- * poll() and pipe() Windows compatibility layer for libusb 1.0
- *
- * The way this layer works is by using OVERLAPPED with async I/O transfers, as
- * OVERLAPPED have an associated event which is flagged for I/O completion.
- *
- * For USB pollable async I/O, you would typically:
- * - obtain a Windows HANDLE to a file or device that has been opened in
- *   OVERLAPPED mode
- * - call usbi_create_fd with this handle to obtain a custom fd.
- *   Note that if you need simultaneous R/W access, you need to call create_fd
- *   twice, once in RW_READ and once in RW_WRITE mode to obtain 2 separate
- *   pollable fds
- * - leave the core functions call the poll routine and flag POLLIN/POLLOUT
- *
- * The pipe pollable synchronous I/O works using the overlapped event associated
- * with a fake pipe. The read/write functions are only meant to be used in that
- * context.
- */
-#include <config.h>
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "libusbi.h"
-
-// Uncomment to debug the polling layer
-//#define DEBUG_POLL_WINDOWS
-#if defined(DEBUG_POLL_WINDOWS)
-#define poll_dbg usbi_dbg
-#else
-// MSVC++ < 2005 cannot use a variadic argument and non MSVC
-// compilers produce warnings if parenthesis are omitted.
-#if defined(_MSC_VER) && (_MSC_VER < 1400)
-#define poll_dbg
-#else
-#define poll_dbg(...)
-#endif
-#endif
-
-#if defined(_PREFAST_)
-#pragma warning(disable:28719)
-#endif
-
-#define CHECK_INIT_POLLING do {if(!is_polling_set) init_polling();} while(0)
-
-// public fd data
-const struct winfd INVALID_WINFD = {-1, INVALID_HANDLE_VALUE, NULL, NULL, NULL, RW_NONE};
-struct winfd poll_fd[MAX_FDS];
-// internal fd data
-struct {
-	CRITICAL_SECTION mutex; // lock for fds
-	// Additional variables for XP CancelIoEx partial emulation
-	HANDLE original_handle;
-	DWORD thread_id;
-} _poll_fd[MAX_FDS];
-
-// globals
-BOOLEAN is_polling_set = FALSE;
-LONG pipe_number = 0;
-static volatile LONG compat_spinlock = 0;
-
-#if !defined(_WIN32_WCE)
-// CancelIoEx, available on Vista and later only, provides the ability to cancel
-// a single transfer (OVERLAPPED) when used. As it may not be part of any of the
-// platform headers, we hook into the Kernel32 system DLL directly to seek it.
-static BOOL (__stdcall *pCancelIoEx)(HANDLE, LPOVERLAPPED) = NULL;
-#define Use_Duplicate_Handles (pCancelIoEx == NULL)
-
-static inline void setup_cancel_io(void)
-{
-	HMODULE hKernel32 = GetModuleHandleA("KERNEL32");
-	if (hKernel32 != NULL) {
-		pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED))
-			GetProcAddress(hKernel32, "CancelIoEx");
-	}
-	usbi_dbg("Will use CancelIo%s for I/O cancellation",
-		Use_Duplicate_Handles?"":"Ex");
-}
-
-static inline BOOL cancel_io(int _index)
-{
-	if ((_index < 0) || (_index >= MAX_FDS)) {
-		return FALSE;
-	}
-
-	if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE)
-	  || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) {
-		return TRUE;
-	}
-	if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) {
-		// Cancel outstanding transfer via the specific callback
-		(*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer);
-		return TRUE;
-	}
-	if (pCancelIoEx != NULL) {
-		return (*pCancelIoEx)(poll_fd[_index].handle, poll_fd[_index].overlapped);
-	}
-	if (_poll_fd[_index].thread_id == GetCurrentThreadId()) {
-		return CancelIo(poll_fd[_index].handle);
-	}
-	usbi_warn(NULL, "Unable to cancel I/O that was started from another thread");
-	return FALSE;
-}
-#else
-#define Use_Duplicate_Handles FALSE
-
-static __inline void setup_cancel_io()
-{
-	// No setup needed on WinCE
-}
-
-static __inline BOOL cancel_io(int _index)
-{
-	if ((_index < 0) || (_index >= MAX_FDS)) {
-		return FALSE;
-	}
-	if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE)
-	  || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) {
-		return TRUE;
-	}
-	if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) {
-		// Cancel outstanding transfer via the specific callback
-		(*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer);
-	}
-	return TRUE;
-}
-#endif
-
-// Init
-void init_polling(void)
-{
-	int i;
-
-	while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
-		SleepEx(0, TRUE);
-	}
-	if (!is_polling_set) {
-		setup_cancel_io();
-		for (i=0; i<MAX_FDS; i++) {
-			poll_fd[i] = INVALID_WINFD;
-			_poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
-			_poll_fd[i].thread_id = 0;
-			InitializeCriticalSection(&_poll_fd[i].mutex);
-		}
-		is_polling_set = TRUE;
-	}
-	InterlockedExchange((LONG *)&compat_spinlock, 0);
-}
-
-// Internal function to retrieve the table index (and lock the fd mutex)
-static int _fd_to_index_and_lock(int fd)
-{
-	int i;
-
-	if (fd < 0)
-		return -1;
-
-	for (i=0; i<MAX_FDS; i++) {
-		if (poll_fd[i].fd == fd) {
-			EnterCriticalSection(&_poll_fd[i].mutex);
-			// fd might have changed before we got to critical
-			if (poll_fd[i].fd != fd) {
-				LeaveCriticalSection(&_poll_fd[i].mutex);
-				continue;
-			}
-			return i;
-		}
-	}
-	return -1;
-}
-
-static OVERLAPPED *create_overlapped(void)
-{
-	OVERLAPPED *overlapped = (OVERLAPPED*) calloc(1, sizeof(OVERLAPPED));
-	if (overlapped == NULL) {
-		return NULL;
-	}
-	overlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-	if(overlapped->hEvent == NULL) {
-		free (overlapped);
-		return NULL;
-	}
-	return overlapped;
-}
-
-static void free_overlapped(OVERLAPPED *overlapped)
-{
-	if (overlapped == NULL)
-		return;
-
-	if ( (overlapped->hEvent != 0)
-	  && (overlapped->hEvent != INVALID_HANDLE_VALUE) ) {
-		CloseHandle(overlapped->hEvent);
-	}
-	free(overlapped);
-}
-
-void exit_polling(void)
-{
-	int i;
-
-	while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
-		SleepEx(0, TRUE);
-	}
-	if (is_polling_set) {
-		is_polling_set = FALSE;
-
-		for (i=0; i<MAX_FDS; i++) {
-			// Cancel any async I/O (handle can be invalid)
-			cancel_io(i);
-			// If anything was pending on that I/O, it should be
-			// terminating, and we should be able to access the fd
-			// mutex lock before too long
-			EnterCriticalSection(&_poll_fd[i].mutex);
-			free_overlapped(poll_fd[i].overlapped);
-			if (Use_Duplicate_Handles) {
-				// Close duplicate handle
-				if (_poll_fd[i].original_handle != INVALID_HANDLE_VALUE) {
-					CloseHandle(poll_fd[i].handle);
-				}
-			}
-			poll_fd[i] = INVALID_WINFD;
-			LeaveCriticalSection(&_poll_fd[i].mutex);
-			DeleteCriticalSection(&_poll_fd[i].mutex);
-		}
-	}
-	InterlockedExchange((LONG *)&compat_spinlock, 0);
-}
-
-/*
- * Create a fake pipe.
- * As libusb only uses pipes for signaling, all we need from a pipe is an
- * event. To that extent, we create a single wfd and overlapped as a means
- * to access that event.
- */
-int usbi_pipe(int filedes[2])
-{
-	int i;
-	OVERLAPPED* overlapped;
-
-	CHECK_INIT_POLLING;
-
-	overlapped = create_overlapped();
-
-	if (overlapped == NULL) {
-		return -1;
-	}
-	// The overlapped must have status pending for signaling to work in poll
-	overlapped->Internal = STATUS_PENDING;
-	overlapped->InternalHigh = 0;
-
-	for (i=0; i<MAX_FDS; i++) {
-		if (poll_fd[i].fd < 0) {
-			EnterCriticalSection(&_poll_fd[i].mutex);
-			// fd might have been allocated before we got to critical
-			if (poll_fd[i].fd >= 0) {
-				LeaveCriticalSection(&_poll_fd[i].mutex);
-				continue;
-			}
-
-			// Use index as the unique fd number
-			poll_fd[i].fd = i;
-			// Read end of the "pipe"
-			filedes[0] = poll_fd[i].fd;
-			// We can use the same handle for both ends
-			filedes[1] = filedes[0];
-
-			poll_fd[i].handle = DUMMY_HANDLE;
-			poll_fd[i].overlapped = overlapped;
-			// There's no polling on the write end, so we just use READ for our needs
-			poll_fd[i].rw = RW_READ;
-			_poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
-			LeaveCriticalSection(&_poll_fd[i].mutex);
-			return 0;
-		}
-	}
-	free_overlapped(overlapped);
-	return -1;
-}
-
-/*
- * Create both an fd and an OVERLAPPED from an open Windows handle, so that
- * it can be used with our polling function
- * The handle MUST support overlapped transfers (usually requires CreateFile
- * with FILE_FLAG_OVERLAPPED)
- * Return a pollable file descriptor struct, or INVALID_WINFD on error
- *
- * Note that the fd returned by this function is a per-transfer fd, rather
- * than a per-session fd and cannot be used for anything else but our
- * custom functions (the fd itself points to the NUL: device)
- * if you plan to do R/W on the same handle, you MUST create 2 fds: one for
- * read and one for write. Using a single R/W fd is unsupported and will
- * produce unexpected results
- */
-struct winfd usbi_create_fd(HANDLE handle, int access_mode, struct usbi_transfer *itransfer, cancel_transfer *cancel_fn)
-{
-	int i;
-	struct winfd wfd = INVALID_WINFD;
-	OVERLAPPED* overlapped = NULL;
-
-	CHECK_INIT_POLLING;
-
-	if ((handle == 0) || (handle == INVALID_HANDLE_VALUE)) {
-		return INVALID_WINFD;
-	}
-
-	wfd.itransfer = itransfer;
-	wfd.cancel_fn = cancel_fn;
-
-	if ((access_mode != RW_READ) && (access_mode != RW_WRITE)) {
-		usbi_warn(NULL, "only one of RW_READ or RW_WRITE are supported. "
-			"If you want to poll for R/W simultaneously, create multiple fds from the same handle.");
-		return INVALID_WINFD;
-	}
-	if (access_mode == RW_READ) {
-		wfd.rw = RW_READ;
-	} else {
-		wfd.rw = RW_WRITE;
-	}
-
-	overlapped = create_overlapped();
-	if(overlapped == NULL) {
-		return INVALID_WINFD;
-	}
-
-	for (i=0; i<MAX_FDS; i++) {
-		if (poll_fd[i].fd < 0) {
-			EnterCriticalSection(&_poll_fd[i].mutex);
-			// fd might have been removed before we got to critical
-			if (poll_fd[i].fd >= 0) {
-				LeaveCriticalSection(&_poll_fd[i].mutex);
-				continue;
-			}
-			// Use index as the unique fd number
-			wfd.fd = i;
-			// Attempt to emulate some of the CancelIoEx behaviour on platforms
-			// that don't have it
-			if (Use_Duplicate_Handles) {
-				_poll_fd[i].thread_id = GetCurrentThreadId();
-				if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(),
-					&wfd.handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
-					usbi_dbg("could not duplicate handle for CancelIo - using original one");
-					wfd.handle = handle;
-					// Make sure we won't close the original handle on fd deletion then
-					_poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
-				} else {
-					_poll_fd[i].original_handle = handle;
-				}
-			} else {
-				wfd.handle = handle;
-			}
-			wfd.overlapped = overlapped;
-			memcpy(&poll_fd[i], &wfd, sizeof(struct winfd));
-			LeaveCriticalSection(&_poll_fd[i].mutex);
-			return wfd;
-		}
-	}
-	free_overlapped(overlapped);
-	return INVALID_WINFD;
-}
-
-static void _free_index(int _index)
-{
-	// Cancel any async IO (Don't care about the validity of our handles for this)
-	cancel_io(_index);
-	// close the duplicate handle (if we have an actual duplicate)
-	if (Use_Duplicate_Handles) {
-		if (_poll_fd[_index].original_handle != INVALID_HANDLE_VALUE) {
-			CloseHandle(poll_fd[_index].handle);
-		}
-		_poll_fd[_index].original_handle = INVALID_HANDLE_VALUE;
-		_poll_fd[_index].thread_id = 0;
-	}
-	free_overlapped(poll_fd[_index].overlapped);
-	poll_fd[_index] = INVALID_WINFD;
-}
-
-/*
- * Release a pollable file descriptor.
- *
- * Note that the associated Windows handle is not closed by this call
- */
-void usbi_free_fd(struct winfd *wfd)
-{
-	int _index;
-
-	CHECK_INIT_POLLING;
-
-	_index = _fd_to_index_and_lock(wfd->fd);
-	if (_index < 0) {
-		return;
-	}
-	_free_index(_index);
-	*wfd = INVALID_WINFD;
-	LeaveCriticalSection(&_poll_fd[_index].mutex);
-}
-
-/*
- * The functions below perform various conversions between fd, handle and OVERLAPPED
- */
-struct winfd fd_to_winfd(int fd)
-{
-	int i;
-	struct winfd wfd;
-
-	CHECK_INIT_POLLING;
-
-	if (fd < 0)
-		return INVALID_WINFD;
-
-	for (i=0; i<MAX_FDS; i++) {
-		if (poll_fd[i].fd == fd) {
-			EnterCriticalSection(&_poll_fd[i].mutex);
-			// fd might have been deleted before we got to critical
-			if (poll_fd[i].fd != fd) {
-				LeaveCriticalSection(&_poll_fd[i].mutex);
-				continue;
-			}
-			memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
-			LeaveCriticalSection(&_poll_fd[i].mutex);
-			return wfd;
-		}
-	}
-	return INVALID_WINFD;
-}
-
-struct winfd handle_to_winfd(HANDLE handle)
-{
-	int i;
-	struct winfd wfd;
-
-	CHECK_INIT_POLLING;
-
-	if ((handle == 0) || (handle == INVALID_HANDLE_VALUE))
-		return INVALID_WINFD;
-
-	for (i=0; i<MAX_FDS; i++) {
-		if (poll_fd[i].handle == handle) {
-			EnterCriticalSection(&_poll_fd[i].mutex);
-			// fd might have been deleted before we got to critical
-			if (poll_fd[i].handle != handle) {
-				LeaveCriticalSection(&_poll_fd[i].mutex);
-				continue;
-			}
-			memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
-			LeaveCriticalSection(&_poll_fd[i].mutex);
-			return wfd;
-		}
-	}
-	return INVALID_WINFD;
-}
-
-struct winfd overlapped_to_winfd(OVERLAPPED* overlapped)
-{
-	int i;
-	struct winfd wfd;
-
-	CHECK_INIT_POLLING;
-
-	if (overlapped == NULL)
-		return INVALID_WINFD;
-
-	for (i=0; i<MAX_FDS; i++) {
-		if (poll_fd[i].overlapped == overlapped) {
-			EnterCriticalSection(&_poll_fd[i].mutex);
-			// fd might have been deleted before we got to critical
-			if (poll_fd[i].overlapped != overlapped) {
-				LeaveCriticalSection(&_poll_fd[i].mutex);
-				continue;
-			}
-			memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
-			LeaveCriticalSection(&_poll_fd[i].mutex);
-			return wfd;
-		}
-	}
-	return INVALID_WINFD;
-}
-
-/*
- * POSIX poll equivalent, using Windows OVERLAPPED
- * Currently, this function only accepts one of POLLIN or POLLOUT per fd
- * (but you can create multiple fds from the same handle for read and write)
- */
-int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
-{
-	unsigned i;
-	int _index, object_index, triggered;
-	HANDLE *handles_to_wait_on;
-	int *handle_to_index;
-	DWORD nb_handles_to_wait_on = 0;
-	DWORD ret;
-
-	CHECK_INIT_POLLING;
-
-	triggered = 0;
-	handles_to_wait_on = (HANDLE*) calloc(nfds+1, sizeof(HANDLE));	// +1 for fd_update
-	handle_to_index = (int*) calloc(nfds, sizeof(int));
-	if ((handles_to_wait_on == NULL) || (handle_to_index == NULL)) {
-		errno = ENOMEM;
-		triggered = -1;
-		goto poll_exit;
-	}
-
-	for (i = 0; i < nfds; ++i) {
-		fds[i].revents = 0;
-
-		// Only one of POLLIN or POLLOUT can be selected with this version of poll (not both)
-		if ((fds[i].events & ~POLLIN) && (!(fds[i].events & POLLOUT))) {
-			fds[i].revents |= POLLERR;
-			errno = EACCES;
-			usbi_warn(NULL, "unsupported set of events");
-			triggered = -1;
-			goto poll_exit;
-		}
-
-		_index = _fd_to_index_and_lock(fds[i].fd);
-		poll_dbg("fd[%d]=%d: (overlapped=%p) got events %04X", i, poll_fd[_index].fd, poll_fd[_index].overlapped, fds[i].events);
-
-		if ( (_index < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE)
-		  || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL)) {
-			fds[i].revents |= POLLNVAL | POLLERR;
-			errno = EBADF;
-			if (_index >= 0) {
-				LeaveCriticalSection(&_poll_fd[_index].mutex);
-			}
-			usbi_warn(NULL, "invalid fd");
-			triggered = -1;
-			goto poll_exit;
-		}
-
-		// IN or OUT must match our fd direction
-		if ((fds[i].events & POLLIN) && (poll_fd[_index].rw != RW_READ)) {
-			fds[i].revents |= POLLNVAL | POLLERR;
-			errno = EBADF;
-			usbi_warn(NULL, "attempted POLLIN on fd without READ access");
-			LeaveCriticalSection(&_poll_fd[_index].mutex);
-			triggered = -1;
-			goto poll_exit;
-		}
-
-		if ((fds[i].events & POLLOUT) && (poll_fd[_index].rw != RW_WRITE)) {
-			fds[i].revents |= POLLNVAL | POLLERR;
-			errno = EBADF;
-			usbi_warn(NULL, "attempted POLLOUT on fd without WRITE access");
-			LeaveCriticalSection(&_poll_fd[_index].mutex);
-			triggered = -1;
-			goto poll_exit;
-		}
-
-		// The following macro only works if overlapped I/O was reported pending
-		if ( (HasOverlappedIoCompleted(poll_fd[_index].overlapped))
-		  || (HasOverlappedIoCompletedSync(poll_fd[_index].overlapped)) ) {
-			poll_dbg("  completed");
-			// checks above should ensure this works:
-			fds[i].revents = fds[i].events;
-			triggered++;
-		} else {
-			handles_to_wait_on[nb_handles_to_wait_on] = poll_fd[_index].overlapped->hEvent;
-			handle_to_index[nb_handles_to_wait_on] = i;
-			nb_handles_to_wait_on++;
-		}
-		LeaveCriticalSection(&_poll_fd[_index].mutex);
-	}
-
-	// If nothing was triggered, wait on all fds that require it
-	if ((timeout != 0) && (triggered == 0) && (nb_handles_to_wait_on != 0)) {
-		if (timeout < 0) {
-			poll_dbg("starting infinite wait for %u handles...", (unsigned int)nb_handles_to_wait_on);
-		} else {
-			poll_dbg("starting %d ms wait for %u handles...", timeout, (unsigned int)nb_handles_to_wait_on);
-		}
-		ret = WaitForMultipleObjects(nb_handles_to_wait_on, handles_to_wait_on,
-			FALSE, (timeout<0)?INFINITE:(DWORD)timeout);
-		object_index = ret-WAIT_OBJECT_0;
-		if ((object_index >= 0) && ((DWORD)object_index < nb_handles_to_wait_on)) {
-			poll_dbg("  completed after wait");
-			i = handle_to_index[object_index];
-			_index = _fd_to_index_and_lock(fds[i].fd);
-			fds[i].revents = fds[i].events;
-			triggered++;
-			if (_index >= 0) {
-				LeaveCriticalSection(&_poll_fd[_index].mutex);
-			}
-		} else if (ret == WAIT_TIMEOUT) {
-			poll_dbg("  timed out");
-			triggered = 0;	// 0 = timeout
-		} else {
-			errno = EIO;
-			triggered = -1;	// error
-		}
-	}
-
-poll_exit:
-	if (handles_to_wait_on != NULL) {
-		free(handles_to_wait_on);
-	}
-	if (handle_to_index != NULL) {
-		free(handle_to_index);
-	}
-	return triggered;
-}
-
-/*
- * close a fake pipe fd
- */
-int usbi_close(int fd)
-{
-	int _index;
-	int r = -1;
-
-	CHECK_INIT_POLLING;
-
-	_index = _fd_to_index_and_lock(fd);
-
-	if (_index < 0) {
-		errno = EBADF;
-	} else {
-		free_overlapped(poll_fd[_index].overlapped);
-		poll_fd[_index] = INVALID_WINFD;
-		LeaveCriticalSection(&_poll_fd[_index].mutex);
-	}
-	return r;
-}
-
-/*
- * synchronous write for fake "pipe" signaling
- */
-ssize_t usbi_write(int fd, const void *buf, size_t count)
-{
-	int _index;
-	UNUSED(buf);
-
-	CHECK_INIT_POLLING;
-
-	if (count != sizeof(unsigned char)) {
-		usbi_err(NULL, "this function should only used for signaling");
-		return -1;
-	}
-
-	_index = _fd_to_index_and_lock(fd);
-
-	if ( (_index < 0) || (poll_fd[_index].overlapped == NULL) ) {
-		errno = EBADF;
-		if (_index >= 0) {
-			LeaveCriticalSection(&_poll_fd[_index].mutex);
-		}
-		return -1;
-	}
-
-	poll_dbg("set pipe event (fd = %d, thread = %08X)", _index, (unsigned int)GetCurrentThreadId());
-	SetEvent(poll_fd[_index].overlapped->hEvent);
-	poll_fd[_index].overlapped->Internal = STATUS_WAIT_0;
-	// If two threads write on the pipe at the same time, we need to
-	// process two separate reads => use the overlapped as a counter
-	poll_fd[_index].overlapped->InternalHigh++;
-
-	LeaveCriticalSection(&_poll_fd[_index].mutex);
-	return sizeof(unsigned char);
-}
-
-/*
- * synchronous read for fake "pipe" signaling
- */
-ssize_t usbi_read(int fd, void *buf, size_t count)
-{
-	int _index;
-	ssize_t r = -1;
-	UNUSED(buf);
-
-	CHECK_INIT_POLLING;
-
-	if (count != sizeof(unsigned char)) {
-		usbi_err(NULL, "this function should only used for signaling");
-		return -1;
-	}
-
-	_index = _fd_to_index_and_lock(fd);
-
-	if (_index < 0) {
-		errno = EBADF;
-		return -1;
-	}
-
-	if (WaitForSingleObject(poll_fd[_index].overlapped->hEvent, INFINITE) != WAIT_OBJECT_0) {
-		usbi_warn(NULL, "waiting for event failed: %u", (unsigned int)GetLastError());
-		errno = EIO;
-		goto out;
-	}
-
-	poll_dbg("clr pipe event (fd = %d, thread = %08X)", _index, (unsigned int)GetCurrentThreadId());
-	poll_fd[_index].overlapped->InternalHigh--;
-	// Don't reset unless we don't have any more events to process
-	if (poll_fd[_index].overlapped->InternalHigh <= 0) {
-		ResetEvent(poll_fd[_index].overlapped->hEvent);
-		poll_fd[_index].overlapped->Internal = STATUS_PENDING;
-	}
-
-	r = sizeof(unsigned char);
-
-out:
-	LeaveCriticalSection(&_poll_fd[_index].mutex);
-	return r;
-}

+ 0 - 55
vendor/github.com/karalabe/hid/libusb/libusb/os/threads_posix.h

@@ -1,55 +0,0 @@
-/*
- * libusb synchronization using POSIX Threads
- *
- * Copyright © 2010 Peter Stuge <peter@stuge.se>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef LIBUSB_THREADS_POSIX_H
-#define LIBUSB_THREADS_POSIX_H
-
-#include <pthread.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#define usbi_mutex_static_t		pthread_mutex_t
-#define USBI_MUTEX_INITIALIZER		PTHREAD_MUTEX_INITIALIZER
-#define usbi_mutex_static_lock		pthread_mutex_lock
-#define usbi_mutex_static_unlock	pthread_mutex_unlock
-
-#define usbi_mutex_t			pthread_mutex_t
-#define usbi_mutex_init(mutex)		pthread_mutex_init((mutex), NULL)
-#define usbi_mutex_lock			pthread_mutex_lock
-#define usbi_mutex_unlock		pthread_mutex_unlock
-#define usbi_mutex_trylock		pthread_mutex_trylock
-#define usbi_mutex_destroy		pthread_mutex_destroy
-
-#define usbi_cond_t			pthread_cond_t
-#define usbi_cond_init(cond)		pthread_cond_init((cond), NULL)
-#define usbi_cond_wait			pthread_cond_wait
-#define usbi_cond_broadcast		pthread_cond_broadcast
-#define usbi_cond_destroy		pthread_cond_destroy
-
-#define usbi_tls_key_t			pthread_key_t
-#define usbi_tls_key_create(key)	pthread_key_create((key), NULL)
-#define usbi_tls_key_get		pthread_getspecific
-#define usbi_tls_key_set		pthread_setspecific
-#define usbi_tls_key_delete		pthread_key_delete
-
-int usbi_get_tid(void);
-
-#endif /* LIBUSB_THREADS_POSIX_H */

+ 0 - 259
vendor/github.com/karalabe/hid/libusb/libusb/os/threads_windows.c

@@ -1,259 +0,0 @@
-/*
- * libusb synchronization on Microsoft Windows
- *
- * Copyright © 2010 Michael Plante <michael.plante@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <config.h>
-
-#include <objbase.h>
-#include <errno.h>
-
-#include "libusbi.h"
-
-struct usbi_cond_perthread {
-	struct list_head list;
-	DWORD tid;
-	HANDLE event;
-};
-
-int usbi_mutex_static_lock(usbi_mutex_static_t *mutex)
-{
-	if (!mutex)
-		return EINVAL;
-	while (InterlockedExchange(mutex, 1) == 1)
-		SleepEx(0, TRUE);
-	return 0;
-}
-
-int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex)
-{
-	if (!mutex)
-		return EINVAL;
-	InterlockedExchange(mutex, 0);
-	return 0;
-}
-
-int usbi_mutex_init(usbi_mutex_t *mutex)
-{
-	if (!mutex)
-		return EINVAL;
-	*mutex = CreateMutex(NULL, FALSE, NULL);
-	if (!*mutex)
-		return ENOMEM;
-	return 0;
-}
-
-int usbi_mutex_lock(usbi_mutex_t *mutex)
-{
-	DWORD result;
-
-	if (!mutex)
-		return EINVAL;
-	result = WaitForSingleObject(*mutex, INFINITE);
-	if (result == WAIT_OBJECT_0 || result == WAIT_ABANDONED)
-		return 0; // acquired (ToDo: check that abandoned is ok)
-	else
-		return EINVAL; // don't know how this would happen
-			       //   so don't know proper errno
-}
-
-int usbi_mutex_unlock(usbi_mutex_t *mutex)
-{
-	if (!mutex)
-		return EINVAL;
-	if (ReleaseMutex(*mutex))
-		return 0;
-	else
-		return EPERM;
-}
-
-int usbi_mutex_trylock(usbi_mutex_t *mutex)
-{
-	DWORD result;
-
-	if (!mutex)
-		return EINVAL;
-	result = WaitForSingleObject(*mutex, 0);
-	if (result == WAIT_OBJECT_0 || result == WAIT_ABANDONED)
-		return 0; // acquired (ToDo: check that abandoned is ok)
-	else if (result == WAIT_TIMEOUT)
-		return EBUSY;
-	else
-		return EINVAL; // don't know how this would happen
-			       //   so don't know proper error
-}
-
-int usbi_mutex_destroy(usbi_mutex_t *mutex)
-{
-	// It is not clear if CloseHandle failure is due to failure to unlock.
-	//   If so, this should be errno=EBUSY.
-	if (!mutex || !CloseHandle(*mutex))
-		return EINVAL;
-	*mutex = NULL;
-	return 0;
-}
-
-int usbi_cond_init(usbi_cond_t *cond)
-{
-	if (!cond)
-		return EINVAL;
-	list_init(&cond->waiters);
-	list_init(&cond->not_waiting);
-	return 0;
-}
-
-int usbi_cond_destroy(usbi_cond_t *cond)
-{
-	// This assumes no one is using this anymore.  The check MAY NOT BE safe.
-	struct usbi_cond_perthread *pos, *next_pos;
-
-	if(!cond)
-		return EINVAL;
-	if (!list_empty(&cond->waiters))
-		return EBUSY; // (!see above!)
-	list_for_each_entry_safe(pos, next_pos, &cond->not_waiting, list, struct usbi_cond_perthread) {
-		CloseHandle(pos->event);
-		list_del(&pos->list);
-		free(pos);
-	}
-	return 0;
-}
-
-int usbi_cond_broadcast(usbi_cond_t *cond)
-{
-	// Assumes mutex is locked; this is not in keeping with POSIX spec, but
-	//   libusb does this anyway, so we simplify by not adding more sync
-	//   primitives to the CV definition!
-	int fail = 0;
-	struct usbi_cond_perthread *pos;
-
-	if (!cond)
-		return EINVAL;
-	list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread) {
-		if (!SetEvent(pos->event))
-			fail = 1;
-	}
-	// The wait function will remove its respective item from the list.
-	return fail ? EINVAL : 0;
-}
-
-__inline static int usbi_cond_intwait(usbi_cond_t *cond,
-	usbi_mutex_t *mutex, DWORD timeout_ms)
-{
-	struct usbi_cond_perthread *pos;
-	int r, found = 0;
-	DWORD r2, tid = GetCurrentThreadId();
-
-	if (!cond || !mutex)
-		return EINVAL;
-	list_for_each_entry(pos, &cond->not_waiting, list, struct usbi_cond_perthread) {
-		if(tid == pos->tid) {
-			found = 1;
-			break;
-		}
-	}
-
-	if (!found) {
-		pos = calloc(1, sizeof(struct usbi_cond_perthread));
-		if (!pos)
-			return ENOMEM; // This errno is not POSIX-allowed.
-		pos->tid = tid;
-		pos->event = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset.
-		if (!pos->event) {
-			free(pos);
-			return ENOMEM;
-		}
-		list_add(&pos->list, &cond->not_waiting);
-	}
-
-	list_del(&pos->list); // remove from not_waiting list.
-	list_add(&pos->list, &cond->waiters);
-
-	r  = usbi_mutex_unlock(mutex);
-	if (r)
-		return r;
-
-	r2 = WaitForSingleObject(pos->event, timeout_ms);
-	r = usbi_mutex_lock(mutex);
-	if (r)
-		return r;
-
-	list_del(&pos->list);
-	list_add(&pos->list, &cond->not_waiting);
-
-	if (r2 == WAIT_OBJECT_0)
-		return 0;
-	else if (r2 == WAIT_TIMEOUT)
-		return ETIMEDOUT;
-	else
-		return EINVAL;
-}
-// N.B.: usbi_cond_*wait() can also return ENOMEM, even though pthread_cond_*wait cannot!
-int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex)
-{
-	return usbi_cond_intwait(cond, mutex, INFINITE);
-}
-
-int usbi_cond_timedwait(usbi_cond_t *cond,
-	usbi_mutex_t *mutex, const struct timeval *tv)
-{
-	DWORD millis;
-
-	millis = (DWORD)(tv->tv_sec * 1000) + (tv->tv_usec / 1000);
-	/* round up to next millisecond */
-	if (tv->tv_usec % 1000)
-		millis++;
-	return usbi_cond_intwait(cond, mutex, millis);
-}
-
-int usbi_tls_key_create(usbi_tls_key_t *key)
-{
-	if (!key)
-		return EINVAL;
-	*key = TlsAlloc();
-	if (*key == TLS_OUT_OF_INDEXES)
-		return ENOMEM;
-	else
-		return 0;
-}
-
-void *usbi_tls_key_get(usbi_tls_key_t key)
-{
-	return TlsGetValue(key);
-}
-
-int usbi_tls_key_set(usbi_tls_key_t key, void *value)
-{
-	if (TlsSetValue(key, value))
-		return 0;
-	else
-		return EINVAL;
-}
-
-int usbi_tls_key_delete(usbi_tls_key_t key)
-{
-	if (TlsFree(key))
-		return 0;
-	else
-		return EINVAL;
-}
-
-int usbi_get_tid(void)
-{
-	return (int)GetCurrentThreadId();
-}

+ 0 - 63
vendor/github.com/karalabe/hid/libusb/libusb/os/windows_nt_common.h

@@ -1,63 +0,0 @@
-/*
- * Windows backend common header for libusb 1.0
- *
- * This file brings together header code common between
- * the desktop Windows backends.
- * Copyright © 2012-2013 RealVNC Ltd.
- * Copyright © 2009-2012 Pete Batard <pete@akeo.ie>
- * With contributions from Michael Plante, Orin Eman et al.
- * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
- * Major code testing contribution by Xiaofan Chen
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#pragma once
-
-// Missing from MinGW
-#if !defined(FACILITY_SETUPAPI)
-#define FACILITY_SETUPAPI	15
-#endif
-
-typedef struct USB_CONFIGURATION_DESCRIPTOR {
-  UCHAR  bLength;
-  UCHAR  bDescriptorType;
-  USHORT wTotalLength;
-  UCHAR  bNumInterfaces;
-  UCHAR  bConfigurationValue;
-  UCHAR  iConfiguration;
-  UCHAR  bmAttributes;
-  UCHAR  MaxPower;
-} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR;
-
-typedef struct libusb_device_descriptor USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;
-
-int windows_common_init(struct libusb_context *ctx);
-void windows_common_exit(void);
-
-unsigned long htab_hash(const char *str);
-int windows_clock_gettime(int clk_id, struct timespec *tp);
-
-void windows_clear_transfer_priv(struct usbi_transfer *itransfer);
-int windows_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size);
-struct winfd *windows_get_fd(struct usbi_transfer *transfer);
-void windows_get_overlapped_result(struct usbi_transfer *transfer, struct winfd *pollable_fd, DWORD *io_result, DWORD *io_size);
-
-void windows_handle_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size);
-int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready);
-
-#if defined(ENABLE_LOGGING)
-const char *windows_error_str(DWORD error_code);
-#endif

+ 0 - 4290
vendor/github.com/karalabe/hid/libusb/libusb/os/windows_winusb.c

@@ -1,4290 +0,0 @@
-/*
- * windows backend for libusb 1.0
- * Copyright © 2009-2012 Pete Batard <pete@akeo.ie>
- * With contributions from Michael Plante, Orin Eman et al.
- * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
- * HID Reports IOCTLs inspired from HIDAPI by Alan Ott, Signal 11 Software
- * Hash table functions adapted from glibc, by Ulrich Drepper et al.
- * Major code testing contribution by Xiaofan Chen
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <config.h>
-
-#if !defined(USE_USBDK)
-
-#include <windows.h>
-#include <setupapi.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <process.h>
-#include <stdio.h>
-#include <inttypes.h>
-#include <objbase.h>
-#include <winioctl.h>
-
-#include "libusbi.h"
-#include "poll_windows.h"
-#include "windows_winusb.h"
-
-#define HANDLE_VALID(h) (((h) != 0) && ((h) != INVALID_HANDLE_VALUE))
-
-// The 2 macros below are used in conjunction with safe loops.
-#define LOOP_CHECK(fcall)			\
-	{					\
-		r = fcall;			\
-		if (r != LIBUSB_SUCCESS)	\
-			continue;		\
-	}
-#define LOOP_BREAK(err)				\
-	{					\
-		r = err;			\
-		continue;			\
-	}
-
-// WinUSB-like API prototypes
-static int winusbx_init(int sub_api, struct libusb_context *ctx);
-static int winusbx_exit(int sub_api);
-static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle);
-static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle);
-static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface);
-static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
-static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
-static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer);
-static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting);
-static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer);
-static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
-static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer);
-static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer);
-static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle);
-static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
-// HID API prototypes
-static int hid_init(int sub_api, struct libusb_context *ctx);
-static int hid_exit(int sub_api);
-static int hid_open(int sub_api, struct libusb_device_handle *dev_handle);
-static void hid_close(int sub_api, struct libusb_device_handle *dev_handle);
-static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
-static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
-static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting);
-static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer);
-static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer);
-static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
-static int hid_abort_transfers(int sub_api, struct usbi_transfer *itransfer);
-static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle);
-static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
-// Composite API prototypes
-static int composite_init(int sub_api, struct libusb_context *ctx);
-static int composite_exit(int sub_api);
-static int composite_open(int sub_api, struct libusb_device_handle *dev_handle);
-static void composite_close(int sub_api, struct libusb_device_handle *dev_handle);
-static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
-static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting);
-static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface);
-static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer);
-static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer);
-static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer);
-static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
-static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer);
-static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer);
-static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle);
-static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
-
-
-// Global variables
-int windows_version = WINDOWS_UNDEFINED;
-static char windows_version_str[128] = "Undefined";
-// Concurrency
-static int concurrent_usage = -1;
-static usbi_mutex_t autoclaim_lock;
-// API globals
-#define CHECK_WINUSBX_AVAILABLE(sub_api)		\
-	do {						\
-		if (sub_api == SUB_API_NOTSET)		\
-			sub_api = priv->sub_api;	\
-		if (!WinUSBX[sub_api].initialized) 	\
-			return LIBUSB_ERROR_ACCESS;	\
-	} while(0)
-
-static HMODULE WinUSBX_handle = NULL;
-static struct winusb_interface WinUSBX[SUB_API_MAX];
-static const char *sub_api_name[SUB_API_MAX] = WINUSBX_DRV_NAMES;
-
-static bool api_hid_available = false;
-#define CHECK_HID_AVAILABLE				\
-	do {						\
-		if (!api_hid_available)			\
-			return LIBUSB_ERROR_ACCESS;	\
-	} while (0)
-
-static inline BOOLEAN guid_eq(const GUID *guid1, const GUID *guid2)
-{
-	if ((guid1 != NULL) && (guid2 != NULL))
-		return (memcmp(guid1, guid2, sizeof(GUID)) == 0);
-
-	return false;
-}
-
-#if defined(ENABLE_LOGGING)
-static char *guid_to_string(const GUID *guid)
-{
-	static char guid_string[MAX_GUID_STRING_LENGTH];
-
-	if (guid == NULL)
-		return NULL;
-
-	sprintf(guid_string, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
-		(unsigned int)guid->Data1, guid->Data2, guid->Data3,
-		guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
-		guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
-
-	return guid_string;
-}
-#endif
-
-/*
- * Sanitize Microsoft's paths: convert to uppercase, add prefix and fix backslashes.
- * Return an allocated sanitized string or NULL on error.
- */
-static char *sanitize_path(const char *path)
-{
-	const char root_prefix[] = { '\\', '\\', '.', '\\' };
-	size_t j, size;
-	char *ret_path;
-	size_t add_root = 0;
-
-	if (path == NULL)
-		return NULL;
-
-	size = strlen(path) + 1;
-
-	// Microsoft indiscriminately uses '\\?\', '\\.\', '##?#" or "##.#" for root prefixes.
-	if (!((size > 3) && (((path[0] == '\\') && (path[1] == '\\') && (path[3] == '\\'))
-			|| ((path[0] == '#') && (path[1] == '#') && (path[3] == '#'))))) {
-		add_root = sizeof(root_prefix);
-		size += add_root;
-	}
-
-	ret_path = malloc(size);
-	if (ret_path == NULL)
-		return NULL;
-
-	strcpy(&ret_path[add_root], path);
-
-	// Ensure consistency with root prefix
-	memcpy(ret_path, root_prefix, sizeof(root_prefix));
-
-	// Same goes for '\' and '#' after the root prefix. Ensure '#' is used
-	for (j = sizeof(root_prefix); j < size; j++) {
-		ret_path[j] = (char)toupper((int)ret_path[j]); // Fix case too
-		if (ret_path[j] == '\\')
-			ret_path[j] = '#';
-	}
-
-	return ret_path;
-}
-
-/*
- * Cfgmgr32, OLE32 and SetupAPI DLL functions
- */
-static int init_dlls(void)
-{
-	DLL_GET_HANDLE(Cfgmgr32);
-	DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Parent, TRUE);
-	DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Child, TRUE);
-	DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Sibling, TRUE);
-	DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Device_IDA, TRUE);
-
-	// Prefixed to avoid conflict with header files
-	DLL_GET_HANDLE(AdvAPI32);
-	DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegQueryValueExW, TRUE);
-	DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegCloseKey, TRUE);
-
-	DLL_GET_HANDLE(Kernel32);
-	DLL_LOAD_FUNC_PREFIXED(Kernel32, p, IsWow64Process, FALSE);
-
-	DLL_GET_HANDLE(OLE32);
-	DLL_LOAD_FUNC_PREFIXED(OLE32, p, CLSIDFromString, TRUE);
-
-	DLL_GET_HANDLE(SetupAPI);
-	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetClassDevsA, TRUE);
-	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInfo, TRUE);
-	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInterfaces, TRUE);
-	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInterfaceDetailA, TRUE);
-	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiDestroyDeviceInfoList, TRUE);
-	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDevRegKey, TRUE);
-	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceRegistryPropertyA, TRUE);
-	DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDeviceInterfaceRegKey, TRUE);
-
-	return LIBUSB_SUCCESS;
-}
-
-static void exit_dlls(void)
-{
-	DLL_FREE_HANDLE(Cfgmgr32);
-	DLL_FREE_HANDLE(AdvAPI32);
-	DLL_FREE_HANDLE(Kernel32);
-	DLL_FREE_HANDLE(OLE32);
-	DLL_FREE_HANDLE(SetupAPI);
-}
-
-/*
- * enumerate interfaces for the whole USB class
- *
- * Parameters:
- * dev_info: a pointer to a dev_info list
- * dev_info_data: a pointer to an SP_DEVINFO_DATA to be filled (or NULL if not needed)
- * usb_class: the generic USB class for which to retrieve interface details
- * index: zero based index of the interface in the device info list
- *
- * Note: it is the responsibility of the caller to free the DEVICE_INTERFACE_DETAIL_DATA
- * structure returned and call this function repeatedly using the same guid (with an
- * incremented index starting at zero) until all interfaces have been returned.
- */
-static bool get_devinfo_data(struct libusb_context *ctx,
-	HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const char *usb_class, unsigned _index)
-{
-	if (_index <= 0) {
-		*dev_info = pSetupDiGetClassDevsA(NULL, usb_class, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES);
-		if (*dev_info == INVALID_HANDLE_VALUE)
-			return false;
-	}
-
-	dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA);
-	if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) {
-		if (GetLastError() != ERROR_NO_MORE_ITEMS)
-			usbi_err(ctx, "Could not obtain device info data for index %u: %s",
-				_index, windows_error_str(0));
-
-		pSetupDiDestroyDeviceInfoList(*dev_info);
-		*dev_info = INVALID_HANDLE_VALUE;
-		return false;
-	}
-	return true;
-}
-
-/*
- * enumerate interfaces for a specific GUID
- *
- * Parameters:
- * dev_info: a pointer to a dev_info list
- * dev_info_data: a pointer to an SP_DEVINFO_DATA to be filled (or NULL if not needed)
- * guid: the GUID for which to retrieve interface details
- * index: zero based index of the interface in the device info list
- *
- * Note: it is the responsibility of the caller to free the DEVICE_INTERFACE_DETAIL_DATA
- * structure returned and call this function repeatedly using the same guid (with an
- * incremented index starting at zero) until all interfaces have been returned.
- */
-static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details(struct libusb_context *ctx,
-	HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID *guid, unsigned _index)
-{
-	SP_DEVICE_INTERFACE_DATA dev_interface_data;
-	SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details;
-	DWORD size;
-
-	if (_index <= 0)
-		*dev_info = pSetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
-
-	if (dev_info_data != NULL) {
-		dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA);
-		if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) {
-			if (GetLastError() != ERROR_NO_MORE_ITEMS)
-				usbi_err(ctx, "Could not obtain device info data for index %u: %s",
-					_index, windows_error_str(0));
-
-			pSetupDiDestroyDeviceInfoList(*dev_info);
-			*dev_info = INVALID_HANDLE_VALUE;
-			return NULL;
-		}
-	}
-
-	dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
-	if (!pSetupDiEnumDeviceInterfaces(*dev_info, NULL, guid, _index, &dev_interface_data)) {
-		if (GetLastError() != ERROR_NO_MORE_ITEMS)
-			usbi_err(ctx, "Could not obtain interface data for index %u: %s",
-				_index, windows_error_str(0));
-
-		pSetupDiDestroyDeviceInfoList(*dev_info);
-		*dev_info = INVALID_HANDLE_VALUE;
-		return NULL;
-	}
-
-	// Read interface data (dummy + actual) to access the device path
-	if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, NULL, 0, &size, NULL)) {
-		// The dummy call should fail with ERROR_INSUFFICIENT_BUFFER
-		if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
-			usbi_err(ctx, "could not access interface data (dummy) for index %u: %s",
-				_index, windows_error_str(0));
-			goto err_exit;
-		}
-	} else {
-		usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong.");
-		goto err_exit;
-	}
-
-	dev_interface_details = calloc(1, size);
-	if (dev_interface_details == NULL) {
-		usbi_err(ctx, "could not allocate interface data for index %u.", _index);
-		goto err_exit;
-	}
-
-	dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
-	if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data,
-		dev_interface_details, size, &size, NULL)) {
-		usbi_err(ctx, "could not access interface data (actual) for index %u: %s",
-			_index, windows_error_str(0));
-	}
-
-	return dev_interface_details;
-
-err_exit:
-	pSetupDiDestroyDeviceInfoList(*dev_info);
-	*dev_info = INVALID_HANDLE_VALUE;
-	return NULL;
-}
-
-/* For libusb0 filter */
-static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details_filter(struct libusb_context *ctx,
-	HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID *guid, unsigned _index, char *filter_path)
-{
-	SP_DEVICE_INTERFACE_DATA dev_interface_data;
-	SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details;
-	DWORD size;
-
-	if (_index <= 0)
-		*dev_info = pSetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
-
-	if (dev_info_data != NULL) {
-		dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA);
-		if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) {
-			if (GetLastError() != ERROR_NO_MORE_ITEMS)
-				usbi_err(ctx, "Could not obtain device info data for index %u: %s",
-					_index, windows_error_str(0));
-
-			pSetupDiDestroyDeviceInfoList(*dev_info);
-			*dev_info = INVALID_HANDLE_VALUE;
-			return NULL;
-		}
-	}
-
-	dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
-	if (!pSetupDiEnumDeviceInterfaces(*dev_info, NULL, guid, _index, &dev_interface_data)) {
-		if (GetLastError() != ERROR_NO_MORE_ITEMS)
-			usbi_err(ctx, "Could not obtain interface data for index %u: %s",
-				_index, windows_error_str(0));
-
-		pSetupDiDestroyDeviceInfoList(*dev_info);
-		*dev_info = INVALID_HANDLE_VALUE;
-		return NULL;
-	}
-
-	// Read interface data (dummy + actual) to access the device path
-	if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, NULL, 0, &size, NULL)) {
-		// The dummy call should fail with ERROR_INSUFFICIENT_BUFFER
-		if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
-			usbi_err(ctx, "could not access interface data (dummy) for index %u: %s",
-				_index, windows_error_str(0));
-			goto err_exit;
-		}
-	} else {
-		usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong.");
-		goto err_exit;
-	}
-
-	dev_interface_details = calloc(1, size);
-	if (dev_interface_details == NULL) {
-		usbi_err(ctx, "could not allocate interface data for index %u.", _index);
-		goto err_exit;
-	}
-
-	dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
-	if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, dev_interface_details, size, &size, NULL))
-		usbi_err(ctx, "could not access interface data (actual) for index %u: %s",
-			_index, windows_error_str(0));
-
-	// [trobinso] lookup the libusb0 symbolic index.
-	if (dev_interface_details) {
-		HKEY hkey_device_interface = pSetupDiOpenDeviceInterfaceRegKey(*dev_info, &dev_interface_data, 0, KEY_READ);
-		if (hkey_device_interface != INVALID_HANDLE_VALUE) {
-			DWORD libusb0_symboliclink_index = 0;
-			DWORD value_length = sizeof(DWORD);
-			DWORD value_type = 0;
-			LONG status;
-
-			status = pRegQueryValueExW(hkey_device_interface, L"LUsb0", NULL, &value_type,
-				(LPBYTE)&libusb0_symboliclink_index, &value_length);
-			if (status == ERROR_SUCCESS) {
-				if (libusb0_symboliclink_index < 256) {
-					// libusb0.sys is connected to this device instance.
-					// If the the device interface guid is {F9F3FF14-AE21-48A0-8A25-8011A7A931D9} then it's a filter.
-					sprintf(filter_path, "\\\\.\\libusb0-%04u", (unsigned int)libusb0_symboliclink_index);
-					usbi_dbg("assigned libusb0 symbolic link %s", filter_path);
-				} else {
-					// libusb0.sys was connected to this device instance at one time; but not anymore.
-				}
-			}
-			pRegCloseKey(hkey_device_interface);
-		}
-	}
-
-	return dev_interface_details;
-
-err_exit:
-	pSetupDiDestroyDeviceInfoList(*dev_info);
-	*dev_info = INVALID_HANDLE_VALUE;
-	return NULL;
-}
-
-/*
- * Returns the session ID of a device's nth level ancestor
- * If there's no device at the nth level, return 0
- */
-static unsigned long get_ancestor_session_id(DWORD devinst, unsigned level)
-{
-	DWORD parent_devinst;
-	unsigned long session_id;
-	char *sanitized_path;
-	char path[MAX_PATH_LENGTH];
-	unsigned i;
-
-	if (level < 1)
-		return 0;
-
-	for (i = 0; i < level; i++) {
-		if (CM_Get_Parent(&parent_devinst, devinst, 0) != CR_SUCCESS)
-			return 0;
-		devinst = parent_devinst;
-	}
-
-	if (CM_Get_Device_IDA(devinst, path, MAX_PATH_LENGTH, 0) != CR_SUCCESS)
-		return 0;
-
-	// TODO: (post hotplug): try without sanitizing
-	sanitized_path = sanitize_path(path);
-	if (sanitized_path == NULL)
-		return 0;
-
-	session_id = htab_hash(sanitized_path);
-	free(sanitized_path);
-	return session_id;
-}
-
-/*
- * Determine which interface the given endpoint address belongs to
- */
-static int get_interface_by_endpoint(struct libusb_config_descriptor *conf_desc, uint8_t ep)
-{
-	const struct libusb_interface *intf;
-	const struct libusb_interface_descriptor *intf_desc;
-	int i, j, k;
-
-	for (i = 0; i < conf_desc->bNumInterfaces; i++) {
-		intf = &conf_desc->interface[i];
-		for (j = 0; j < intf->num_altsetting; j++) {
-			intf_desc = &intf->altsetting[j];
-			for (k = 0; k < intf_desc->bNumEndpoints; k++) {
-				if (intf_desc->endpoint[k].bEndpointAddress == ep) {
-					usbi_dbg("found endpoint %02X on interface %d", intf_desc->bInterfaceNumber, i);
-					return intf_desc->bInterfaceNumber;
-				}
-			}
-		}
-	}
-
-	usbi_dbg("endpoint %02X not found on any interface", ep);
-	return LIBUSB_ERROR_NOT_FOUND;
-}
-
-/*
- * Populate the endpoints addresses of the device_priv interface helper structs
- */
-static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int iface, int altsetting)
-{
-	int i, r;
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	struct libusb_config_descriptor *conf_desc;
-	const struct libusb_interface_descriptor *if_desc;
-	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
-
-	r = libusb_get_active_config_descriptor(dev_handle->dev, &conf_desc);
-	if (r != LIBUSB_SUCCESS) {
-		usbi_warn(ctx, "could not read config descriptor: error %d", r);
-		return r;
-	}
-
-	if_desc = &conf_desc->interface[iface].altsetting[altsetting];
-	safe_free(priv->usb_interface[iface].endpoint);
-
-	if (if_desc->bNumEndpoints == 0) {
-		usbi_dbg("no endpoints found for interface %d", iface);
-		libusb_free_config_descriptor(conf_desc);
-		return LIBUSB_SUCCESS;
-	}
-
-	priv->usb_interface[iface].endpoint = malloc(if_desc->bNumEndpoints);
-	if (priv->usb_interface[iface].endpoint == NULL) {
-		libusb_free_config_descriptor(conf_desc);
-		return LIBUSB_ERROR_NO_MEM;
-	}
-
-	priv->usb_interface[iface].nb_endpoints = if_desc->bNumEndpoints;
-	for (i = 0; i < if_desc->bNumEndpoints; i++) {
-		priv->usb_interface[iface].endpoint[i] = if_desc->endpoint[i].bEndpointAddress;
-		usbi_dbg("(re)assigned endpoint %02X to interface %d", priv->usb_interface[iface].endpoint[i], iface);
-	}
-	libusb_free_config_descriptor(conf_desc);
-
-	// Extra init may be required to configure endpoints
-	return priv->apib->configure_endpoints(SUB_API_NOTSET, dev_handle, iface);
-}
-
-// Lookup for a match in the list of API driver names
-// return -1 if not found, driver match number otherwise
-static int get_sub_api(char *driver, int api)
-{
-	int i;
-	const char sep_str[2] = {LIST_SEPARATOR, 0};
-	char *tok, *tmp_str;
-	size_t len = strlen(driver);
-
-	if (len == 0)
-		return SUB_API_NOTSET;
-
-	tmp_str = _strdup(driver);
-	if (tmp_str == NULL)
-		return SUB_API_NOTSET;
-
-	tok = strtok(tmp_str, sep_str);
-	while (tok != NULL) {
-		for (i = 0; i < usb_api_backend[api].nb_driver_names; i++) {
-			if (_stricmp(tok, usb_api_backend[api].driver_name_list[i]) == 0) {
-				free(tmp_str);
-				return i;
-			}
-		}
-		tok = strtok(NULL, sep_str);
-	}
-
-	free(tmp_str);
-	return SUB_API_NOTSET;
-}
-
-/*
- * auto-claiming and auto-release helper functions
- */
-static int auto_claim(struct libusb_transfer *transfer, int *interface_number, int api_type)
-{
-	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(
-		transfer->dev_handle);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
-	int current_interface = *interface_number;
-	int r = LIBUSB_SUCCESS;
-
-	switch(api_type) {
-	case USB_API_WINUSBX:
-	case USB_API_HID:
-		break;
-	default:
-		return LIBUSB_ERROR_INVALID_PARAM;
-	}
-
-	usbi_mutex_lock(&autoclaim_lock);
-	if (current_interface < 0) { // No serviceable interface was found
-		for (current_interface = 0; current_interface < USB_MAXINTERFACES; current_interface++) {
-			// Must claim an interface of the same API type
-			if ((priv->usb_interface[current_interface].apib->id == api_type)
-					&& (libusb_claim_interface(transfer->dev_handle, current_interface) == LIBUSB_SUCCESS)) {
-				usbi_dbg("auto-claimed interface %d for control request", current_interface);
-				if (handle_priv->autoclaim_count[current_interface] != 0)
-					usbi_warn(ctx, "program assertion failed - autoclaim_count was nonzero");
-				handle_priv->autoclaim_count[current_interface]++;
-				break;
-			}
-		}
-		if (current_interface == USB_MAXINTERFACES) {
-			usbi_err(ctx, "could not auto-claim any interface");
-			r = LIBUSB_ERROR_NOT_FOUND;
-		}
-	} else {
-		// If we have a valid interface that was autoclaimed, we must increment
-		// its autoclaim count so that we can prevent an early release.
-		if (handle_priv->autoclaim_count[current_interface] != 0)
-			handle_priv->autoclaim_count[current_interface]++;
-	}
-	usbi_mutex_unlock(&autoclaim_lock);
-
-	*interface_number = current_interface;
-	return r;
-}
-
-static void auto_release(struct usbi_transfer *itransfer)
-{
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	libusb_device_handle *dev_handle = transfer->dev_handle;
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	int r;
-
-	usbi_mutex_lock(&autoclaim_lock);
-	if (handle_priv->autoclaim_count[transfer_priv->interface_number] > 0) {
-		handle_priv->autoclaim_count[transfer_priv->interface_number]--;
-		if (handle_priv->autoclaim_count[transfer_priv->interface_number] == 0) {
-			r = libusb_release_interface(dev_handle, transfer_priv->interface_number);
-			if (r == LIBUSB_SUCCESS)
-				usbi_dbg("auto-released interface %d", transfer_priv->interface_number);
-			else
-				usbi_dbg("failed to auto-release interface %d (%s)",
-					transfer_priv->interface_number, libusb_error_name((enum libusb_error)r));
-		}
-	}
-	usbi_mutex_unlock(&autoclaim_lock);
-}
-
-/* Windows version dtection */
-static BOOL is_x64(void)
-{
-	BOOL ret = FALSE;
-
-	// Detect if we're running a 32 or 64 bit system
-	if (sizeof(uintptr_t) < 8) {
-		if (pIsWow64Process != NULL)
-			pIsWow64Process(GetCurrentProcess(), &ret);
-	} else {
-		ret = TRUE;
-	}
-
-	return ret;
-}
-
-static void get_windows_version(void)
-{
-	OSVERSIONINFOEXA vi, vi2;
-	const char *arch, *w = NULL;
-	unsigned major, minor;
-	ULONGLONG major_equal, minor_equal;
-	BOOL ws;
-
-	memset(&vi, 0, sizeof(vi));
-	vi.dwOSVersionInfoSize = sizeof(vi);
-	if (!GetVersionExA((OSVERSIONINFOA *)&vi)) {
-		memset(&vi, 0, sizeof(vi));
-		vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
-		if (!GetVersionExA((OSVERSIONINFOA *)&vi))
-			return;
-	}
-
-	if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
-		if (vi.dwMajorVersion > 6 || (vi.dwMajorVersion == 6 && vi.dwMinorVersion >= 2)) {
-			// Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version
-			// See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx
-
-			major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
-			for (major = vi.dwMajorVersion; major <= 9; major++) {
-				memset(&vi2, 0, sizeof(vi2));
-				vi2.dwOSVersionInfoSize = sizeof(vi2);
-				vi2.dwMajorVersion = major;
-				if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal))
-					continue;
-
-				if (vi.dwMajorVersion < major) {
-					vi.dwMajorVersion = major;
-					vi.dwMinorVersion = 0;
-				}
-
-				minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);
-				for (minor = vi.dwMinorVersion; minor <= 9; minor++) {
-					memset(&vi2, 0, sizeof(vi2));
-					vi2.dwOSVersionInfoSize = sizeof(vi2);
-					vi2.dwMinorVersion = minor;
-					if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal))
-						continue;
-
-					vi.dwMinorVersion = minor;
-					break;
-				}
-
-				break;
-			}
-		}
-
-		if (vi.dwMajorVersion <= 0xf && vi.dwMinorVersion <= 0xf) {
-			ws = (vi.wProductType <= VER_NT_WORKSTATION);
-			windows_version = vi.dwMajorVersion << 4 | vi.dwMinorVersion;
-			switch (windows_version) {
-			case 0x50: w = "2000"; break;
-			case 0x51: w = "XP"; break;
-			case 0x52: w = "2003"; break;
-			case 0x60: w = (ws ? "Vista" : "2008"); break;
-			case 0x61: w = (ws ? "7" : "2008_R2"); break;
-			case 0x62: w = (ws ? "8" : "2012"); break;
-			case 0x63: w = (ws ? "8.1" : "2012_R2"); break;
-			case 0x64: w = (ws ? "10" : "2015"); break;
-			default:
-				if (windows_version < 0x50)
-					windows_version = WINDOWS_UNSUPPORTED;
-				else
-					w = "11 or later";
-				break;
-			}
-		}
-	}
-
-	arch = is_x64() ? "64-bit" : "32-bit";
-
-	if (w == NULL)
-		snprintf(windows_version_str, sizeof(windows_version_str), "%s %u.%u %s",
-			(vi.dwPlatformId == VER_PLATFORM_WIN32_NT ? "NT" : "??"),
-			(unsigned int)vi.dwMajorVersion, (unsigned int)vi.dwMinorVersion, arch);
-	else if (vi.wServicePackMinor)
-		snprintf(windows_version_str, sizeof(windows_version_str), "%s SP%u.%u %s",
-			w, vi.wServicePackMajor, vi.wServicePackMinor, arch);
-	else if (vi.wServicePackMajor)
-		snprintf(windows_version_str, sizeof(windows_version_str), "%s SP%u %s",
-			w, vi.wServicePackMajor, arch);
-	else
-		snprintf(windows_version_str, sizeof(windows_version_str), "%s %s",
-			w, arch);
-}
-
-/*
- * init: libusb backend init function
- *
- * This function enumerates the HCDs (Host Controller Drivers) and populates our private HCD list
- * In our implementation, we equate Windows' "HCD" to libusb's "bus". Note that bus is zero indexed.
- * HCDs are not expected to change after init (might not hold true for hot pluggable USB PCI card?)
- */
-static int windows_init(struct libusb_context *ctx)
-{
-	int i, r = LIBUSB_ERROR_OTHER;
-	HANDLE semaphore;
-	char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
-
-	sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF));
-	semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name);
-	if (semaphore == NULL) {
-		usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0));
-		return LIBUSB_ERROR_NO_MEM;
-	}
-
-	// A successful wait brings our semaphore count to 0 (unsignaled)
-	// => any concurent wait stalls until the semaphore's release
-	if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) {
-		usbi_err(ctx, "failure to access semaphore: %s", windows_error_str(0));
-		CloseHandle(semaphore);
-		return LIBUSB_ERROR_NO_MEM;
-	}
-
-	// NB: concurrent usage supposes that init calls are equally balanced with
-	// exit calls. If init is called more than exit, we will not exit properly
-	if (++concurrent_usage == 0) { // First init?
-		get_windows_version();
-		usbi_dbg("Windows %s", windows_version_str);
-
-		if (windows_version == WINDOWS_UNSUPPORTED) {
-			usbi_err(ctx, "This version of Windows is NOT supported");
-			r = LIBUSB_ERROR_NOT_SUPPORTED;
-			goto init_exit;
-		}
-
-		// We need a lock for proper auto-release
-		usbi_mutex_init(&autoclaim_lock);
-
-		// Initialize pollable file descriptors
-		init_polling();
-
-		// Load DLL imports
-		if (init_dlls() != LIBUSB_SUCCESS) {
-			usbi_err(ctx, "could not resolve DLL functions");
-			goto init_exit;
-		}
-
-		// Initialize the low level APIs (we don't care about errors at this stage)
-		for (i = 0; i < USB_API_MAX; i++)
-			usb_api_backend[i].init(SUB_API_NOTSET, ctx);
-
-		r = windows_common_init(ctx);
-		if (r)
-			goto init_exit;
-	}
-	// At this stage, either we went through full init successfully, or didn't need to
-	r = LIBUSB_SUCCESS;
-
-init_exit: // Holds semaphore here.
-	if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed?
-		for (i = 0; i < USB_API_MAX; i++)
-			usb_api_backend[i].exit(SUB_API_NOTSET);
-		exit_dlls();
-		exit_polling();
-		windows_common_exit();
-		usbi_mutex_destroy(&autoclaim_lock);
-	}
-
-	if (r != LIBUSB_SUCCESS)
-		--concurrent_usage; // Not expected to call libusb_exit if we failed.
-
-	ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1
-	CloseHandle(semaphore);
-	return r;
-}
-
-/*
- * HCD (root) hubs need to have their device descriptor manually populated
- *
- * Note that, like Microsoft does in the device manager, we populate the
- * Vendor and Device ID for HCD hubs with the ones from the PCI HCD device.
- */
-static int force_hcd_device_descriptor(struct libusb_device *dev)
-{
-	struct windows_device_priv *parent_priv, *priv = _device_priv(dev);
-	struct libusb_context *ctx = DEVICE_CTX(dev);
-	int vid, pid;
-
-	dev->num_configurations = 1;
-	priv->dev_descriptor.bLength = sizeof(USB_DEVICE_DESCRIPTOR);
-	priv->dev_descriptor.bDescriptorType = USB_DEVICE_DESCRIPTOR_TYPE;
-	priv->dev_descriptor.bNumConfigurations = 1;
-	priv->active_config = 1;
-
-	if (dev->parent_dev == NULL) {
-		usbi_err(ctx, "program assertion failed - HCD hub has no parent");
-		return LIBUSB_ERROR_NO_DEVICE;
-	}
-
-	parent_priv = _device_priv(dev->parent_dev);
-	if (sscanf(parent_priv->path, "\\\\.\\PCI#VEN_%04x&DEV_%04x%*s", &vid, &pid) == 2) {
-		priv->dev_descriptor.idVendor = (uint16_t)vid;
-		priv->dev_descriptor.idProduct = (uint16_t)pid;
-	} else {
-		usbi_warn(ctx, "could not infer VID/PID of HCD hub from '%s'", parent_priv->path);
-		priv->dev_descriptor.idVendor = 0x1d6b; // Linux Foundation root hub
-		priv->dev_descriptor.idProduct = 1;
-	}
-
-	return LIBUSB_SUCCESS;
-}
-
-/*
- * fetch and cache all the config descriptors through I/O
- */
-static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle, char *device_id)
-{
-	DWORD size, ret_size;
-	struct libusb_context *ctx = DEVICE_CTX(dev);
-	struct windows_device_priv *priv = _device_priv(dev);
-	int r;
-	uint8_t i;
-
-	USB_CONFIGURATION_DESCRIPTOR_SHORT cd_buf_short; // dummy request
-	PUSB_DESCRIPTOR_REQUEST cd_buf_actual = NULL;    // actual request
-	PUSB_CONFIGURATION_DESCRIPTOR cd_data = NULL;
-
-	if (dev->num_configurations == 0)
-		return LIBUSB_ERROR_INVALID_PARAM;
-
-	priv->config_descriptor = calloc(dev->num_configurations, sizeof(unsigned char *));
-	if (priv->config_descriptor == NULL)
-		return LIBUSB_ERROR_NO_MEM;
-
-	for (i = 0; i < dev->num_configurations; i++)
-		priv->config_descriptor[i] = NULL;
-
-	for (i = 0, r = LIBUSB_SUCCESS; ; i++) {
-		// safe loop: release all dynamic resources
-		safe_free(cd_buf_actual);
-
-		// safe loop: end of loop condition
-		if ((i >= dev->num_configurations) || (r != LIBUSB_SUCCESS))
-			break;
-
-		size = sizeof(USB_CONFIGURATION_DESCRIPTOR_SHORT);
-		memset(&cd_buf_short, 0, size);
-
-		cd_buf_short.req.ConnectionIndex = (ULONG)priv->port;
-		cd_buf_short.req.SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN;
-		cd_buf_short.req.SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
-		cd_buf_short.req.SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) | i;
-		cd_buf_short.req.SetupPacket.wIndex = 0;
-		cd_buf_short.req.SetupPacket.wLength = (USHORT)(size - sizeof(USB_DESCRIPTOR_REQUEST));
-
-		// Dummy call to get the required data size. Initial failures are reported as info rather
-		// than error as they can occur for non-penalizing situations, such as with some hubs.
-		// coverity[tainted_data_argument]
-		if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, &cd_buf_short, size,
-			&cd_buf_short, size, &ret_size, NULL)) {
-			usbi_info(ctx, "could not access configuration descriptor (dummy) for '%s': %s", device_id, windows_error_str(0));
-			LOOP_BREAK(LIBUSB_ERROR_IO);
-		}
-
-		if ((ret_size != size) || (cd_buf_short.data.wTotalLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))) {
-			usbi_info(ctx, "unexpected configuration descriptor size (dummy) for '%s'.", device_id);
-			LOOP_BREAK(LIBUSB_ERROR_IO);
-		}
-
-		size = sizeof(USB_DESCRIPTOR_REQUEST) + cd_buf_short.data.wTotalLength;
-		cd_buf_actual = calloc(1, size);
-		if (cd_buf_actual == NULL) {
-			usbi_err(ctx, "could not allocate configuration descriptor buffer for '%s'.", device_id);
-			LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
-		}
-
-		// Actual call
-		cd_buf_actual->ConnectionIndex = (ULONG)priv->port;
-		cd_buf_actual->SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN;
-		cd_buf_actual->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
-		cd_buf_actual->SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) | i;
-		cd_buf_actual->SetupPacket.wIndex = 0;
-		cd_buf_actual->SetupPacket.wLength = (USHORT)(size - sizeof(USB_DESCRIPTOR_REQUEST));
-
-		if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, cd_buf_actual, size,
-			cd_buf_actual, size, &ret_size, NULL)) {
-			usbi_err(ctx, "could not access configuration descriptor (actual) for '%s': %s", device_id, windows_error_str(0));
-			LOOP_BREAK(LIBUSB_ERROR_IO);
-		}
-
-		cd_data = (PUSB_CONFIGURATION_DESCRIPTOR)((UCHAR *)cd_buf_actual + sizeof(USB_DESCRIPTOR_REQUEST));
-
-		if ((size != ret_size) || (cd_data->wTotalLength != cd_buf_short.data.wTotalLength)) {
-			usbi_err(ctx, "unexpected configuration descriptor size (actual) for '%s'.", device_id);
-			LOOP_BREAK(LIBUSB_ERROR_IO);
-		}
-
-		if (cd_data->bDescriptorType != USB_CONFIGURATION_DESCRIPTOR_TYPE) {
-			usbi_err(ctx, "not a configuration descriptor for '%s'", device_id);
-			LOOP_BREAK(LIBUSB_ERROR_IO);
-		}
-
-		usbi_dbg("cached config descriptor %d (bConfigurationValue=%u, %u bytes)",
-			i, cd_data->bConfigurationValue, cd_data->wTotalLength);
-
-		// Cache the descriptor
-		priv->config_descriptor[i] = malloc(cd_data->wTotalLength);
-		if (priv->config_descriptor[i] == NULL)
-			LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
-		memcpy(priv->config_descriptor[i], cd_data, cd_data->wTotalLength);
-	}
-	return LIBUSB_SUCCESS;
-}
-
-/*
- * Populate a libusb device structure
- */
-static int init_device(struct libusb_device *dev, struct libusb_device *parent_dev,
-	uint8_t port_number, char *device_id, DWORD devinst)
-{
-	HANDLE handle;
-	DWORD size;
-	USB_NODE_CONNECTION_INFORMATION_EX conn_info;
-	USB_NODE_CONNECTION_INFORMATION_EX_V2 conn_info_v2;
-	struct windows_device_priv *priv, *parent_priv;
-	struct libusb_context *ctx;
-	struct libusb_device *tmp_dev;
-	unsigned long tmp_id;
-	unsigned i;
-
-	if ((dev == NULL) || (parent_dev == NULL))
-		return LIBUSB_ERROR_NOT_FOUND;
-
-	ctx = DEVICE_CTX(dev);
-	priv = _device_priv(dev);
-	parent_priv = _device_priv(parent_dev);
-	if (parent_priv->apib->id != USB_API_HUB) {
-		usbi_warn(ctx, "parent for device '%s' is not a hub", device_id);
-		return LIBUSB_ERROR_NOT_FOUND;
-	}
-
-	// It is possible for the parent hub not to have been initialized yet
-	// If that's the case, lookup the ancestors to set the bus number
-	if (parent_dev->bus_number == 0) {
-		for (i = 2; ; i++) {
-			tmp_id = get_ancestor_session_id(devinst, i);
-			if (tmp_id == 0)
-				break;
-
-			tmp_dev = usbi_get_device_by_session_id(ctx, tmp_id);
-			if (tmp_dev == NULL)
-				continue;
-
-			if (tmp_dev->bus_number != 0) {
-				usbi_dbg("got bus number from ancestor #%u", i);
-				parent_dev->bus_number = tmp_dev->bus_number;
-				libusb_unref_device(tmp_dev);
-				break;
-			}
-
-			libusb_unref_device(tmp_dev);
-		}
-	}
-
-	if (parent_dev->bus_number == 0) {
-		usbi_err(ctx, "program assertion failed: unable to find ancestor bus number for '%s'", device_id);
-		return LIBUSB_ERROR_NOT_FOUND;
-	}
-
-	dev->bus_number = parent_dev->bus_number;
-	priv->port = port_number;
-	dev->port_number = port_number;
-	priv->depth = parent_priv->depth + 1;
-	dev->parent_dev = parent_dev;
-
-	// If the device address is already set, we can stop here
-	if (dev->device_address != 0)
-		return LIBUSB_SUCCESS;
-
-	memset(&conn_info, 0, sizeof(conn_info));
-	if (priv->depth != 0) { // Not a HCD hub
-		handle = CreateFileA(parent_priv->path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
-			FILE_FLAG_OVERLAPPED, NULL);
-		if (handle == INVALID_HANDLE_VALUE) {
-			usbi_warn(ctx, "could not open hub %s: %s", parent_priv->path, windows_error_str(0));
-			return LIBUSB_ERROR_ACCESS;
-		}
-
-		size = sizeof(conn_info);
-		conn_info.ConnectionIndex = (ULONG)port_number;
-		// coverity[tainted_data_argument]
-		if (!DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, &conn_info, size,
-			&conn_info, size, &size, NULL)) {
-			usbi_warn(ctx, "could not get node connection information for device '%s': %s",
-				device_id, windows_error_str(0));
-			CloseHandle(handle);
-			return LIBUSB_ERROR_NO_DEVICE;
-		}
-
-		if (conn_info.ConnectionStatus == NoDeviceConnected) {
-			usbi_err(ctx, "device '%s' is no longer connected!", device_id);
-			CloseHandle(handle);
-			return LIBUSB_ERROR_NO_DEVICE;
-		}
-
-		memcpy(&priv->dev_descriptor, &(conn_info.DeviceDescriptor), sizeof(USB_DEVICE_DESCRIPTOR));
-		dev->num_configurations = priv->dev_descriptor.bNumConfigurations;
-		priv->active_config = conn_info.CurrentConfigurationValue;
-		usbi_dbg("found %u configurations (active conf: %u)", dev->num_configurations, priv->active_config);
-
-		// If we can't read the config descriptors, just set the number of confs to zero
-		if (cache_config_descriptors(dev, handle, device_id) != LIBUSB_SUCCESS) {
-			dev->num_configurations = 0;
-			priv->dev_descriptor.bNumConfigurations = 0;
-		}
-
-		// In their great wisdom, Microsoft decided to BREAK the USB speed report between Windows 7 and Windows 8
-		if (windows_version >= WINDOWS_8) {
-			memset(&conn_info_v2, 0, sizeof(conn_info_v2));
-			size = sizeof(conn_info_v2);
-			conn_info_v2.ConnectionIndex = (ULONG)port_number;
-			conn_info_v2.Length = size;
-			conn_info_v2.SupportedUsbProtocols.Usb300 = 1;
-			if (!DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2,
-				&conn_info_v2, size, &conn_info_v2, size, &size, NULL)) {
-				usbi_warn(ctx, "could not get node connection information (V2) for device '%s': %s",
-					device_id,  windows_error_str(0));
-			} else if (conn_info_v2.Flags.DeviceIsOperatingAtSuperSpeedOrHigher) {
-				conn_info.Speed = 3;
-			}
-		}
-
-		CloseHandle(handle);
-
-		if (conn_info.DeviceAddress > UINT8_MAX)
-			usbi_err(ctx, "program assertion failed: device address overflow");
-
-		dev->device_address = (uint8_t)conn_info.DeviceAddress + 1;
-		if (dev->device_address == 1)
-			usbi_err(ctx, "program assertion failed: device address collision with root hub");
-
-		switch (conn_info.Speed) {
-		case 0: dev->speed = LIBUSB_SPEED_LOW; break;
-		case 1: dev->speed = LIBUSB_SPEED_FULL; break;
-		case 2: dev->speed = LIBUSB_SPEED_HIGH; break;
-		case 3: dev->speed = LIBUSB_SPEED_SUPER; break;
-		default:
-			usbi_warn(ctx, "Got unknown device speed %u", conn_info.Speed);
-			break;
-		}
-	} else {
-		dev->device_address = 1; // root hubs are set to use device number 1
-		force_hcd_device_descriptor(dev);
-	}
-
-	usbi_sanitize_device(dev);
-
-	usbi_dbg("(bus: %u, addr: %u, depth: %u, port: %u): '%s'",
-		dev->bus_number, dev->device_address, priv->depth, priv->port, device_id);
-
-	return LIBUSB_SUCCESS;
-}
-
-// Returns the api type, or 0 if not found/unsupported
-static void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info,
-	SP_DEVINFO_DATA *dev_info_data, int *api, int *sub_api)
-{
-	// Precedence for filter drivers vs driver is in the order of this array
-	struct driver_lookup lookup[3] = {
-		{"\0\0", SPDRP_SERVICE, "driver"},
-		{"\0\0", SPDRP_UPPERFILTERS, "upper filter driver"},
-		{"\0\0", SPDRP_LOWERFILTERS, "lower filter driver"}
-	};
-	DWORD size, reg_type;
-	unsigned k, l;
-	int i, j;
-
-	*api = USB_API_UNSUPPORTED;
-	*sub_api = SUB_API_NOTSET;
-
-	// Check the service & filter names to know the API we should use
-	for (k = 0; k < 3; k++) {
-		if (pSetupDiGetDeviceRegistryPropertyA(*dev_info, dev_info_data, lookup[k].reg_prop,
-			&reg_type, (BYTE *)lookup[k].list, MAX_KEY_LENGTH, &size)) {
-			// Turn the REG_SZ SPDRP_SERVICE into REG_MULTI_SZ
-			if (lookup[k].reg_prop == SPDRP_SERVICE)
-				// our buffers are MAX_KEY_LENGTH + 1 so we can overflow if needed
-				lookup[k].list[strlen(lookup[k].list) + 1] = 0;
-
-			// MULTI_SZ is a pain to work with. Turn it into something much more manageable
-			// NB: none of the driver names we check against contain LIST_SEPARATOR,
-			// (currently ';'), so even if an unsuported one does, it's not an issue
-			for (l = 0; (lookup[k].list[l] != 0) || (lookup[k].list[l + 1] != 0); l++) {
-				if (lookup[k].list[l] == 0)
-					lookup[k].list[l] = LIST_SEPARATOR;
-			}
-			usbi_dbg("%s(s): %s", lookup[k].designation, lookup[k].list);
-		} else {
-			if (GetLastError() != ERROR_INVALID_DATA)
-				usbi_dbg("could not access %s: %s", lookup[k].designation, windows_error_str(0));
-			lookup[k].list[0] = 0;
-		}
-	}
-
-	for (i = 1; i < USB_API_MAX; i++) {
-		for (k = 0; k < 3; k++) {
-			j = get_sub_api(lookup[k].list, i);
-			if (j >= 0) {
-				usbi_dbg("matched %s name against %s", lookup[k].designation,
-					(i != USB_API_WINUSBX) ? usb_api_backend[i].designation : sub_api_name[j]);
-				*api = i;
-				*sub_api = j;
-				return;
-			}
-		}
-	}
-}
-
-static int set_composite_interface(struct libusb_context *ctx, struct libusb_device *dev,
-	char *dev_interface_path, char *device_id, int api, int sub_api)
-{
-	unsigned i;
-	struct windows_device_priv *priv = _device_priv(dev);
-	int interface_number;
-
-	if (priv->apib->id != USB_API_COMPOSITE) {
-		usbi_err(ctx, "program assertion failed: '%s' is not composite", device_id);
-		return LIBUSB_ERROR_NO_DEVICE;
-	}
-
-	// Because MI_## are not necessarily in sequential order (some composite
-	// devices will have only MI_00 & MI_03 for instance), we retrieve the actual
-	// interface number from the path's MI value
-	interface_number = 0;
-	for (i = 0; device_id[i] != 0; ) {
-		if ((device_id[i++] == 'M') && (device_id[i++] == 'I')
-				&& (device_id[i++] == '_')) {
-			interface_number = (device_id[i++] - '0') * 10;
-			interface_number += device_id[i] - '0';
-			break;
-		}
-	}
-
-	if (device_id[i] == 0)
-		usbi_warn(ctx, "failure to read interface number for %s. Using default value %d",
-			device_id, interface_number);
-
-	if (priv->usb_interface[interface_number].path != NULL) {
-		if (api == USB_API_HID) {
-			// HID devices can have multiple collections (COL##) for each MI_## interface
-			usbi_dbg("interface[%d] already set - ignoring HID collection: %s",
-				interface_number, device_id);
-			return LIBUSB_ERROR_ACCESS;
-		}
-		// In other cases, just use the latest data
-		safe_free(priv->usb_interface[interface_number].path);
-	}
-
-	usbi_dbg("interface[%d] = %s", interface_number, dev_interface_path);
-	priv->usb_interface[interface_number].path = dev_interface_path;
-	priv->usb_interface[interface_number].apib = &usb_api_backend[api];
-	priv->usb_interface[interface_number].sub_api = sub_api;
-	if ((api == USB_API_HID) && (priv->hid == NULL)) {
-		priv->hid = calloc(1, sizeof(struct hid_device_priv));
-		if (priv->hid == NULL)
-			return LIBUSB_ERROR_NO_MEM;
-	}
-
-	return LIBUSB_SUCCESS;
-}
-
-static int set_hid_interface(struct libusb_context *ctx, struct libusb_device *dev,
-	char *dev_interface_path)
-{
-	int i;
-	struct windows_device_priv *priv = _device_priv(dev);
-
-	if (priv->hid == NULL) {
-		usbi_err(ctx, "program assertion failed: parent is not HID");
-		return LIBUSB_ERROR_NO_DEVICE;
-	} else if (priv->hid->nb_interfaces == USB_MAXINTERFACES) {
-		usbi_err(ctx, "program assertion failed: max USB interfaces reached for HID device");
-		return LIBUSB_ERROR_NO_DEVICE;
-	}
-
-	for (i = 0; i < priv->hid->nb_interfaces; i++) {
-		if ((priv->usb_interface[i].path != NULL) && strcmp(priv->usb_interface[i].path, dev_interface_path) == 0) {
-			usbi_dbg("interface[%d] already set to %s", i, dev_interface_path);
-			return LIBUSB_ERROR_ACCESS;
-		}
-	}
-
-	priv->usb_interface[priv->hid->nb_interfaces].path = dev_interface_path;
-	priv->usb_interface[priv->hid->nb_interfaces].apib = &usb_api_backend[USB_API_HID];
-	usbi_dbg("interface[%u] = %s", priv->hid->nb_interfaces, dev_interface_path);
-	priv->hid->nb_interfaces++;
-	return LIBUSB_SUCCESS;
-}
-
-/*
- * get_device_list: libusb backend device enumeration function
- */
-static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs)
-{
-	struct discovered_devs *discdevs;
-	HDEVINFO dev_info = { 0 };
-	const char *usb_class[] = {"USB", "NUSB3", "IUSB3", "IARUSB3"};
-	SP_DEVINFO_DATA dev_info_data = { 0 };
-	SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL;
-	GUID hid_guid;
-#define MAX_ENUM_GUIDS 64
-	const GUID *guid[MAX_ENUM_GUIDS];
-#define HCD_PASS 0
-#define HUB_PASS 1
-#define GEN_PASS 2
-#define DEV_PASS 3
-#define HID_PASS 4
-	int r = LIBUSB_SUCCESS;
-	int api, sub_api;
-	size_t class_index = 0;
-	unsigned int nb_guids, pass, i, j, ancestor;
-	char path[MAX_PATH_LENGTH];
-	char strbuf[MAX_PATH_LENGTH];
-	struct libusb_device *dev, *parent_dev;
-	struct windows_device_priv *priv, *parent_priv;
-	char *dev_interface_path = NULL;
-	char *dev_id_path = NULL;
-	unsigned long session_id;
-	DWORD size, reg_type, port_nr, install_state;
-	HKEY key;
-	WCHAR guid_string_w[MAX_GUID_STRING_LENGTH];
-	GUID *if_guid;
-	LONG s;
-	// Keep a list of newly allocated devs to unref
-	libusb_device **unref_list, **new_unref_list;
-	unsigned int unref_size = 64;
-	unsigned int unref_cur = 0;
-
-	// PASS 1 : (re)enumerate HCDs (allows for HCD hotplug)
-	// PASS 2 : (re)enumerate HUBS
-	// PASS 3 : (re)enumerate generic USB devices (including driverless)
-	//           and list additional USB device interface GUIDs to explore
-	// PASS 4 : (re)enumerate master USB devices that have a device interface
-	// PASS 5+: (re)enumerate device interfaced GUIDs (including HID) and
-	//           set the device interfaces.
-
-	// Init the GUID table
-	guid[HCD_PASS] = &GUID_DEVINTERFACE_USB_HOST_CONTROLLER;
-	guid[HUB_PASS] = &GUID_DEVINTERFACE_USB_HUB;
-	guid[GEN_PASS] = NULL;
-	guid[DEV_PASS] = &GUID_DEVINTERFACE_USB_DEVICE;
-	HidD_GetHidGuid(&hid_guid);
-	guid[HID_PASS] = &hid_guid;
-	nb_guids = HID_PASS + 1;
-
-	unref_list = calloc(unref_size, sizeof(libusb_device *));
-	if (unref_list == NULL)
-		return LIBUSB_ERROR_NO_MEM;
-
-	for (pass = 0; ((pass < nb_guids) && (r == LIBUSB_SUCCESS)); pass++) {
-//#define ENUM_DEBUG
-#if defined(ENABLE_LOGGING) && defined(ENUM_DEBUG)
-		const char *passname[] = { "HCD", "HUB", "GEN", "DEV", "HID", "EXT" };
-		usbi_dbg("#### PROCESSING %ss %s", passname[(pass <= HID_PASS) ? pass : (HID_PASS + 1)],
-			(pass != GEN_PASS) ? guid_to_string(guid[pass]) : "");
-#endif
-		for (i = 0; ; i++) {
-			// safe loop: free up any (unprotected) dynamic resource
-			// NB: this is always executed before breaking the loop
-			safe_free(dev_interface_details);
-			safe_free(dev_interface_path);
-			safe_free(dev_id_path);
-			priv = parent_priv = NULL;
-			dev = parent_dev = NULL;
-
-			// Safe loop: end of loop conditions
-			if (r != LIBUSB_SUCCESS)
-				break;
-
-			if ((pass == HCD_PASS) && (i == UINT8_MAX)) {
-				usbi_warn(ctx, "program assertion failed - found more than %d buses, skipping the rest.", UINT8_MAX);
-				break;
-			}
-
-			if (pass != GEN_PASS) {
-				// Except for GEN, all passes deal with device interfaces
-				dev_interface_details = get_interface_details(ctx, &dev_info, &dev_info_data, guid[pass], i);
-				if (dev_interface_details == NULL)
-					break;
-
-				dev_interface_path = sanitize_path(dev_interface_details->DevicePath);
-				if (dev_interface_path == NULL) {
-					usbi_warn(ctx, "could not sanitize device interface path for '%s'", dev_interface_details->DevicePath);
-					continue;
-				}
-			} else {
-				// Workaround for a Nec/Renesas USB 3.0 driver bug where root hubs are
-				// being listed under the "NUSB3" PnP Symbolic Name rather than "USB".
-				// The Intel USB 3.0 driver behaves similar, but uses "IUSB3"
-				// The Intel Alpine Ridge USB 3.1 driver uses "IARUSB3"
-				for (; class_index < ARRAYSIZE(usb_class); class_index++) {
-					if (get_devinfo_data(ctx, &dev_info, &dev_info_data, usb_class[class_index], i))
-						break;
-					i = 0;
-				}
-				if (class_index >= ARRAYSIZE(usb_class))
-					break;
-			}
-
-			// Read the Device ID path. This is what we'll use as UID
-			// Note that if the device is plugged in a different port or hub, the Device ID changes
-			if (CM_Get_Device_IDA(dev_info_data.DevInst, path, sizeof(path), 0) != CR_SUCCESS) {
-				usbi_warn(ctx, "could not read the device id path for devinst %X, skipping",
-					(unsigned int)dev_info_data.DevInst);
-				continue;
-			}
-
-			dev_id_path = sanitize_path(path);
-			if (dev_id_path == NULL) {
-				usbi_warn(ctx, "could not sanitize device id path for devinst %X, skipping",
-					(unsigned int)dev_info_data.DevInst);
-				continue;
-			}
-#ifdef ENUM_DEBUG
-			usbi_dbg("PRO: %s", dev_id_path);
-#endif
-
-			// The SPDRP_ADDRESS for USB devices is the device port number on the hub
-			port_nr = 0;
-			if ((pass >= HUB_PASS) && (pass <= GEN_PASS)) {
-				if ((!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_ADDRESS,
-					&reg_type, (BYTE *)&port_nr, 4, &size)) || (size != 4)) {
-					usbi_warn(ctx, "could not retrieve port number for device '%s', skipping: %s",
-						dev_id_path, windows_error_str(0));
-					continue;
-				}
-			}
-
-			// Set API to use or get additional data from generic pass
-			api = USB_API_UNSUPPORTED;
-			sub_api = SUB_API_NOTSET;
-			switch (pass) {
-			case HCD_PASS:
-				break;
-			case GEN_PASS:
-				// We use the GEN pass to detect driverless devices...
-				size = sizeof(strbuf);
-				if (!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_DRIVER,
-					&reg_type, (BYTE *)strbuf, size, &size)) {
-						usbi_info(ctx, "The following device has no driver: '%s'", dev_id_path);
-						usbi_info(ctx, "libusb will not be able to access it.");
-				}
-				// ...and to add the additional device interface GUIDs
-				key = pSetupDiOpenDevRegKey(dev_info, &dev_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
-				if (key != INVALID_HANDLE_VALUE) {
-					size = sizeof(guid_string_w);
-					s = pRegQueryValueExW(key, L"DeviceInterfaceGUIDs", NULL, &reg_type,
-						(BYTE *)guid_string_w, &size);
-					pRegCloseKey(key);
-					if (s == ERROR_SUCCESS) {
-						if (nb_guids >= MAX_ENUM_GUIDS) {
-							// If this assert is ever reported, grow a GUID table dynamically
-							usbi_err(ctx, "program assertion failed: too many GUIDs");
-							LOOP_BREAK(LIBUSB_ERROR_OVERFLOW);
-						}
-						if_guid = calloc(1, sizeof(GUID));
-						if (if_guid == NULL) {
-							usbi_err(ctx, "could not calloc for if_guid: not enough memory");
-							LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
-						}
-						pCLSIDFromString(guid_string_w, if_guid);
-						guid[nb_guids++] = if_guid;
-						usbi_dbg("extra GUID: %s", guid_to_string(if_guid));
-					}
-				}
-				break;
-			case HID_PASS:
-				api = USB_API_HID;
-				break;
-			default:
-				// Get the API type (after checking that the driver installation is OK)
-				if ((!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_INSTALL_STATE,
-					&reg_type, (BYTE *)&install_state, 4, &size)) || (size != 4)) {
-					usbi_warn(ctx, "could not detect installation state of driver for '%s': %s",
-						dev_id_path, windows_error_str(0));
-				} else if (install_state != 0) {
-					usbi_warn(ctx, "driver for device '%s' is reporting an issue (code: %u) - skipping",
-						dev_id_path, (unsigned int)install_state);
-					continue;
-				}
-				get_api_type(ctx, &dev_info, &dev_info_data, &api, &sub_api);
-				break;
-			}
-
-			// Find parent device (for the passes that need it)
-			switch (pass) {
-			case HCD_PASS:
-			case DEV_PASS:
-			case HUB_PASS:
-				break;
-			default:
-				// Go through the ancestors until we see a face we recognize
-				parent_dev = NULL;
-				for (ancestor = 1; parent_dev == NULL; ancestor++) {
-					session_id = get_ancestor_session_id(dev_info_data.DevInst, ancestor);
-					if (session_id == 0)
-						break;
-
-					parent_dev = usbi_get_device_by_session_id(ctx, session_id);
-				}
-
-				if (parent_dev == NULL) {
-					usbi_dbg("unlisted ancestor for '%s' (non USB HID, newly connected, etc.) - ignoring", dev_id_path);
-					continue;
-				}
-
-				parent_priv = _device_priv(parent_dev);
-				// virtual USB devices are also listed during GEN - don't process these yet
-				if ((pass == GEN_PASS) && (parent_priv->apib->id != USB_API_HUB)) {
-					libusb_unref_device(parent_dev);
-					continue;
-				}
-
-				break;
-			}
-
-			// Create new or match existing device, using the (hashed) device_id as session id
-			if (pass <= DEV_PASS) {	// For subsequent passes, we'll lookup the parent
-				// These are the passes that create "new" devices
-				session_id = htab_hash(dev_id_path);
-				dev = usbi_get_device_by_session_id(ctx, session_id);
-				if (dev == NULL) {
-					if (pass == DEV_PASS) {
-						// This can occur if the OS only reports a newly plugged device after we started enum
-						usbi_warn(ctx, "'%s' was only detected in late pass (newly connected device?)"
-							" - ignoring", dev_id_path);
-						continue;
-					}
-
-					usbi_dbg("allocating new device for session [%lX]", session_id);
-					dev = usbi_alloc_device(ctx, session_id);
-					if (dev == NULL)
-						LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
-
-					priv = windows_device_priv_init(dev);
-				} else {
-					usbi_dbg("found existing device for session [%lX] (%u.%u)",
-						session_id, dev->bus_number, dev->device_address);
-
-					priv = _device_priv(dev);
-					if ((parent_dev != NULL) && (dev->parent_dev != NULL)) {
-						if (dev->parent_dev != parent_dev) {
-							// It is possible for the actual parent device to not have existed at the
-							// time of enumeration, so the currently assigned parent may in fact be a
-							// grandparent.  If the devices differ, we assume the "new" parent device
-							// is in fact closer to the device.
-                                                        usbi_dbg("updating parent device [session %lX -> %lX]",
-                                                                dev->parent_dev->session_data, parent_dev->session_data);
-							libusb_unref_device(dev->parent_dev);
-							dev->parent_dev = parent_dev;
-						} else {
-							// We hold a reference to parent_dev instance, but this device already
-							// has a parent_dev reference (only one per child)
-							libusb_unref_device(parent_dev);
-						}
-					}
-				}
-
-				// Keep track of devices that need unref
-				unref_list[unref_cur++] = dev;
-				if (unref_cur >= unref_size) {
-					unref_size += 64;
-					new_unref_list = usbi_reallocf(unref_list, unref_size * sizeof(libusb_device *));
-					if (new_unref_list == NULL) {
-						usbi_err(ctx, "could not realloc list for unref - aborting.");
-						LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
-					} else {
-						unref_list = new_unref_list;
-					}
-				}
-			}
-
-			// Setup device
-			switch (pass) {
-			case HCD_PASS:
-				// If the hcd has already been setup, don't do it again
-				if (priv->path != NULL)
-					break;
-				dev->bus_number = (uint8_t)(i + 1); // bus 0 is reserved for disconnected
-				dev->device_address = 0;
-				dev->num_configurations = 0;
-				priv->apib = &usb_api_backend[USB_API_HUB];
-				priv->sub_api = SUB_API_NOTSET;
-				priv->depth = UINT8_MAX; // Overflow to 0 for HCD Hubs
-				priv->path = dev_interface_path;
-				dev_interface_path = NULL;
-				break;
-			case HUB_PASS:
-			case DEV_PASS:
-				// If the device has already been setup, don't do it again
-				if (priv->path != NULL)
-					break;
-				// Take care of API initialization
-				priv->path = dev_interface_path;
-				dev_interface_path = NULL;
-				priv->apib = &usb_api_backend[api];
-				priv->sub_api = sub_api;
-				switch(api) {
-				case USB_API_COMPOSITE:
-				case USB_API_HUB:
-					break;
-				case USB_API_HID:
-					priv->hid = calloc(1, sizeof(struct hid_device_priv));
-					if (priv->hid == NULL)
-						LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
-
-					priv->hid->nb_interfaces = 0;
-					break;
-				default:
-					// For other devices, the first interface is the same as the device
-					priv->usb_interface[0].path = _strdup(priv->path);
-					if (priv->usb_interface[0].path == NULL)
-						usbi_warn(ctx, "could not duplicate interface path '%s'", priv->path);
-					// The following is needed if we want API calls to work for both simple
-					// and composite devices.
-					for (j = 0; j < USB_MAXINTERFACES; j++)
-						priv->usb_interface[j].apib = &usb_api_backend[api];
-
-					break;
-				}
-				break;
-			case GEN_PASS:
-				r = init_device(dev, parent_dev, (uint8_t)port_nr, dev_id_path, dev_info_data.DevInst);
-				if (r == LIBUSB_SUCCESS) {
-					// Append device to the list of discovered devices
-					discdevs = discovered_devs_append(*_discdevs, dev);
-					if (!discdevs)
-						LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
-
-					*_discdevs = discdevs;
-				} else if (r == LIBUSB_ERROR_NO_DEVICE) {
-					// This can occur if the device was disconnected but Windows hasn't
-					// refreshed its enumeration yet - in that case, we ignore the device
-					r = LIBUSB_SUCCESS;
-				}
-				break;
-			default: // HID_PASS and later
-				if (parent_priv->apib->id == USB_API_HID || parent_priv->apib->id == USB_API_COMPOSITE) {
-					if (parent_priv->apib->id == USB_API_HID) {
-						usbi_dbg("setting HID interface for [%lX]:", parent_dev->session_data);
-						r = set_hid_interface(ctx, parent_dev, dev_interface_path);
-					} else {
-						usbi_dbg("setting composite interface for [%lX]:", parent_dev->session_data);
-						r = set_composite_interface(ctx, parent_dev, dev_interface_path, dev_id_path, api, sub_api);
-					}
-					switch (r) {
-					case LIBUSB_SUCCESS:
-						dev_interface_path = NULL;
-						break;
-					case LIBUSB_ERROR_ACCESS:
-						// interface has already been set => make sure dev_interface_path is freed then
-						r = LIBUSB_SUCCESS;
-						break;
-					default:
-						LOOP_BREAK(r);
-						break;
-					}
-				}
-				libusb_unref_device(parent_dev);
-				break;
-			}
-		}
-	}
-
-	// Free any additional GUIDs
-	for (pass = HID_PASS + 1; pass < nb_guids; pass++)
-		free((void *)guid[pass]);
-
-	// Unref newly allocated devs
-	for (i = 0; i < unref_cur; i++)
-		libusb_unref_device(unref_list[i]);
-	free(unref_list);
-
-	return r;
-}
-
-/*
- * exit: libusb backend deinitialization function
- */
-static void windows_exit(void)
-{
-	int i;
-	HANDLE semaphore;
-	char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
-
-	sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF));
-	semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name);
-	if (semaphore == NULL)
-		return;
-
-	// A successful wait brings our semaphore count to 0 (unsignaled)
-	// => any concurent wait stalls until the semaphore release
-	if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) {
-		CloseHandle(semaphore);
-		return;
-	}
-
-	// Only works if exits and inits are balanced exactly
-	if (--concurrent_usage < 0) { // Last exit
-		for (i = 0; i < USB_API_MAX; i++)
-			usb_api_backend[i].exit(SUB_API_NOTSET);
-		exit_dlls();
-		exit_polling();
-		windows_common_exit();
-		usbi_mutex_destroy(&autoclaim_lock);
-	}
-
-	ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1
-	CloseHandle(semaphore);
-}
-
-static int windows_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian)
-{
-	struct windows_device_priv *priv = _device_priv(dev);
-
-	memcpy(buffer, &priv->dev_descriptor, DEVICE_DESC_LENGTH);
-	*host_endian = 0;
-
-	return LIBUSB_SUCCESS;
-}
-
-static int windows_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian)
-{
-	struct windows_device_priv *priv = _device_priv(dev);
-	PUSB_CONFIGURATION_DESCRIPTOR config_header;
-	size_t size;
-
-	// config index is zero based
-	if (config_index >= dev->num_configurations)
-		return LIBUSB_ERROR_INVALID_PARAM;
-
-	if ((priv->config_descriptor == NULL) || (priv->config_descriptor[config_index] == NULL))
-		return LIBUSB_ERROR_NOT_FOUND;
-
-	config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptor[config_index];
-
-	size = MIN(config_header->wTotalLength, len);
-	memcpy(buffer, priv->config_descriptor[config_index], size);
-	*host_endian = 0;
-
-	return (int)size;
-}
-
-static int windows_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue,
-	unsigned char **buffer, int *host_endian)
-{
-	struct windows_device_priv *priv = _device_priv(dev);
-	PUSB_CONFIGURATION_DESCRIPTOR config_header;
-	uint8_t index;
-
-	*buffer = NULL;
-	*host_endian = 0;
-
-	if (priv->config_descriptor == NULL)
-		return LIBUSB_ERROR_NOT_FOUND;
-
-	for (index = 0; index < dev->num_configurations; index++) {
-		config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptor[index];
-		if (config_header->bConfigurationValue == bConfigurationValue) {
-			*buffer = priv->config_descriptor[index];
-			return (int)config_header->wTotalLength;
-		}
-	}
-
-	return LIBUSB_ERROR_NOT_FOUND;
-}
-
-/*
- * return the cached copy of the active config descriptor
- */
-static int windows_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian)
-{
-	struct windows_device_priv *priv = _device_priv(dev);
-	unsigned char *config_desc;
-	int r;
-
-	if (priv->active_config == 0)
-		return LIBUSB_ERROR_NOT_FOUND;
-
-	r = windows_get_config_descriptor_by_value(dev, priv->active_config, &config_desc, host_endian);
-	if (r < 0)
-		return r;
-
-	len = MIN((size_t)r, len);
-	memcpy(buffer, config_desc, len);
-	return (int)len;
-}
-
-static int windows_open(struct libusb_device_handle *dev_handle)
-{
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
-
-	if (priv->apib == NULL) {
-		usbi_err(ctx, "program assertion failed - device is not initialized");
-		return LIBUSB_ERROR_NO_DEVICE;
-	}
-
-	return priv->apib->open(SUB_API_NOTSET, dev_handle);
-}
-
-static void windows_close(struct libusb_device_handle *dev_handle)
-{
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-
-	priv->apib->close(SUB_API_NOTSET, dev_handle);
-}
-
-static int windows_get_configuration(struct libusb_device_handle *dev_handle, int *config)
-{
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-
-	if (priv->active_config == 0) {
-		*config = 0;
-		return LIBUSB_ERROR_NOT_FOUND;
-	}
-
-	*config = priv->active_config;
-	return LIBUSB_SUCCESS;
-}
-
-/*
- * from http://msdn.microsoft.com/en-us/library/ms793522.aspx: "The port driver
- * does not currently expose a service that allows higher-level drivers to set
- * the configuration."
- */
-static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config)
-{
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	int r = LIBUSB_SUCCESS;
-
-	if (config >= USB_MAXCONFIG)
-		return LIBUSB_ERROR_INVALID_PARAM;
-
-	r = libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_OUT |
-		LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE,
-		LIBUSB_REQUEST_SET_CONFIGURATION, (uint16_t)config,
-		0, NULL, 0, 1000);
-
-	if (r == LIBUSB_SUCCESS)
-		priv->active_config = (uint8_t)config;
-
-	return r;
-}
-
-static int windows_claim_interface(struct libusb_device_handle *dev_handle, int iface)
-{
-	int r = LIBUSB_SUCCESS;
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-
-	safe_free(priv->usb_interface[iface].endpoint);
-	priv->usb_interface[iface].nb_endpoints = 0;
-
-	r = priv->apib->claim_interface(SUB_API_NOTSET, dev_handle, iface);
-
-	if (r == LIBUSB_SUCCESS)
-		r = windows_assign_endpoints(dev_handle, iface, 0);
-
-	return r;
-}
-
-static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting)
-{
-	int r = LIBUSB_SUCCESS;
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-
-	safe_free(priv->usb_interface[iface].endpoint);
-	priv->usb_interface[iface].nb_endpoints = 0;
-
-	r = priv->apib->set_interface_altsetting(SUB_API_NOTSET, dev_handle, iface, altsetting);
-
-	if (r == LIBUSB_SUCCESS)
-		r = windows_assign_endpoints(dev_handle, iface, altsetting);
-
-	return r;
-}
-
-static int windows_release_interface(struct libusb_device_handle *dev_handle, int iface)
-{
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-
-	return priv->apib->release_interface(SUB_API_NOTSET, dev_handle, iface);
-}
-
-static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
-{
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	return priv->apib->clear_halt(SUB_API_NOTSET, dev_handle, endpoint);
-}
-
-static int windows_reset_device(struct libusb_device_handle *dev_handle)
-{
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	return priv->apib->reset_device(SUB_API_NOTSET, dev_handle);
-}
-
-// The 3 functions below are unlikely to ever get supported on Windows
-static int windows_kernel_driver_active(struct libusb_device_handle *dev_handle, int iface)
-{
-	return LIBUSB_ERROR_NOT_SUPPORTED;
-}
-
-static int windows_attach_kernel_driver(struct libusb_device_handle *dev_handle, int iface)
-{
-	return LIBUSB_ERROR_NOT_SUPPORTED;
-}
-
-static int windows_detach_kernel_driver(struct libusb_device_handle *dev_handle, int iface)
-{
-	return LIBUSB_ERROR_NOT_SUPPORTED;
-}
-
-static void windows_destroy_device(struct libusb_device *dev)
-{
-	windows_device_priv_release(dev);
-}
-
-void windows_clear_transfer_priv(struct usbi_transfer *itransfer)
-{
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-
-	usbi_free_fd(&transfer_priv->pollable_fd);
-	safe_free(transfer_priv->hid_buffer);
-	// When auto claim is in use, attempt to release the auto-claimed interface
-	auto_release(itransfer);
-}
-
-static int submit_bulk_transfer(struct usbi_transfer *itransfer)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
-	int r;
-
-	r = priv->apib->submit_bulk_transfer(SUB_API_NOTSET, itransfer);
-	if (r != LIBUSB_SUCCESS)
-		return r;
-
-	usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd,
-		(short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT));
-
-	return LIBUSB_SUCCESS;
-}
-
-static int submit_iso_transfer(struct usbi_transfer *itransfer)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
-	int r;
-
-	r = priv->apib->submit_iso_transfer(SUB_API_NOTSET, itransfer);
-	if (r != LIBUSB_SUCCESS)
-		return r;
-
-	usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd,
-		(short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT));
-
-	return LIBUSB_SUCCESS;
-}
-
-static int submit_control_transfer(struct usbi_transfer *itransfer)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
-	int r;
-
-	r = priv->apib->submit_control_transfer(SUB_API_NOTSET, itransfer);
-	if (r != LIBUSB_SUCCESS)
-		return r;
-
-	usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, POLLIN);
-
-	return LIBUSB_SUCCESS;
-}
-
-static int windows_submit_transfer(struct usbi_transfer *itransfer)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-
-	switch (transfer->type) {
-	case LIBUSB_TRANSFER_TYPE_CONTROL:
-		return submit_control_transfer(itransfer);
-	case LIBUSB_TRANSFER_TYPE_BULK:
-	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
-		if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET))
-			return LIBUSB_ERROR_NOT_SUPPORTED;
-		return submit_bulk_transfer(itransfer);
-	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
-		return submit_iso_transfer(itransfer);
-	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
-		return LIBUSB_ERROR_NOT_SUPPORTED;
-	default:
-		usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
-		return LIBUSB_ERROR_INVALID_PARAM;
-	}
-}
-
-static int windows_abort_control(struct usbi_transfer *itransfer)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
-
-	return priv->apib->abort_control(SUB_API_NOTSET, itransfer);
-}
-
-static int windows_abort_transfers(struct usbi_transfer *itransfer)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
-
-	return priv->apib->abort_transfers(SUB_API_NOTSET, itransfer);
-}
-
-static int windows_cancel_transfer(struct usbi_transfer *itransfer)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-
-	switch (transfer->type) {
-	case LIBUSB_TRANSFER_TYPE_CONTROL:
-		return windows_abort_control(itransfer);
-	case LIBUSB_TRANSFER_TYPE_BULK:
-	case LIBUSB_TRANSFER_TYPE_INTERRUPT:
-	case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
-		return windows_abort_transfers(itransfer);
-	case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
-		return LIBUSB_ERROR_NOT_SUPPORTED;
-	default:
-		usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
-		return LIBUSB_ERROR_INVALID_PARAM;
-	}
-}
-
-int windows_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
-	return priv->apib->copy_transfer_data(SUB_API_NOTSET, itransfer, io_size);
-}
-
-struct winfd *windows_get_fd(struct usbi_transfer *transfer)
-{
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(transfer);
-	return &transfer_priv->pollable_fd;
-}
-
-void windows_get_overlapped_result(struct usbi_transfer *transfer, struct winfd *pollable_fd, DWORD *io_result, DWORD *io_size)
-{
-	if (HasOverlappedIoCompletedSync(pollable_fd->overlapped)) {
-		*io_result = NO_ERROR;
-		*io_size = (DWORD)pollable_fd->overlapped->InternalHigh;
-	} else if (GetOverlappedResult(pollable_fd->handle, pollable_fd->overlapped, io_size, false)) {
-		// Regular async overlapped
-		*io_result = NO_ERROR;
-	} else {
-		*io_result = GetLastError();
-	}
-}
-
-// NB: MSVC6 does not support named initializers.
-const struct usbi_os_backend windows_backend = {
-	"Windows",
-	USBI_CAP_HAS_HID_ACCESS,
-	windows_init,
-	windows_exit,
-
-	windows_get_device_list,
-	NULL,				/* hotplug_poll */
-	windows_open,
-	windows_close,
-
-	windows_get_device_descriptor,
-	windows_get_active_config_descriptor,
-	windows_get_config_descriptor,
-	windows_get_config_descriptor_by_value,
-
-	windows_get_configuration,
-	windows_set_configuration,
-	windows_claim_interface,
-	windows_release_interface,
-
-	windows_set_interface_altsetting,
-	windows_clear_halt,
-	windows_reset_device,
-
-	NULL,				/* alloc_streams */
-	NULL,				/* free_streams */
-
-	NULL,				/* dev_mem_alloc */
-	NULL,				/* dev_mem_free */
-
-	windows_kernel_driver_active,
-	windows_detach_kernel_driver,
-	windows_attach_kernel_driver,
-
-	windows_destroy_device,
-
-	windows_submit_transfer,
-	windows_cancel_transfer,
-	windows_clear_transfer_priv,
-
-	windows_handle_events,
-	NULL,
-
-	windows_clock_gettime,
-#if defined(USBI_TIMERFD_AVAILABLE)
-	NULL,
-#endif
-	sizeof(struct windows_device_priv),
-	sizeof(struct windows_device_handle_priv),
-	sizeof(struct windows_transfer_priv),
-};
-
-
-/*
- * USB API backends
- */
-static int unsupported_init(int sub_api, struct libusb_context *ctx)
-{
-	return LIBUSB_SUCCESS;
-}
-
-static int unsupported_exit(int sub_api)
-{
-	return LIBUSB_SUCCESS;
-}
-
-static int unsupported_open(int sub_api, struct libusb_device_handle *dev_handle)
-{
-	PRINT_UNSUPPORTED_API(open);
-}
-
-static void unsupported_close(int sub_api, struct libusb_device_handle *dev_handle)
-{
-	usbi_dbg("unsupported API call for 'close'");
-}
-
-static int unsupported_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface)
-{
-	PRINT_UNSUPPORTED_API(configure_endpoints);
-}
-
-static int unsupported_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
-{
-	PRINT_UNSUPPORTED_API(claim_interface);
-}
-
-static int unsupported_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
-{
-	PRINT_UNSUPPORTED_API(set_interface_altsetting);
-}
-
-static int unsupported_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
-{
-	PRINT_UNSUPPORTED_API(release_interface);
-}
-
-static int unsupported_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
-{
-	PRINT_UNSUPPORTED_API(clear_halt);
-}
-
-static int unsupported_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
-{
-	PRINT_UNSUPPORTED_API(reset_device);
-}
-
-static int unsupported_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer)
-{
-	PRINT_UNSUPPORTED_API(submit_bulk_transfer);
-}
-
-static int unsupported_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer)
-{
-	PRINT_UNSUPPORTED_API(submit_iso_transfer);
-}
-
-static int unsupported_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer)
-{
-	PRINT_UNSUPPORTED_API(submit_control_transfer);
-}
-
-static int unsupported_abort_control(int sub_api, struct usbi_transfer *itransfer)
-{
-	PRINT_UNSUPPORTED_API(abort_control);
-}
-
-static int unsupported_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
-{
-	PRINT_UNSUPPORTED_API(abort_transfers);
-}
-
-static int unsupported_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
-{
-	PRINT_UNSUPPORTED_API(copy_transfer_data);
-}
-
-static int common_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface)
-{
-	return LIBUSB_SUCCESS;
-}
-
-// These names must be uppercase
-static const char *hub_driver_names[] = {"USBHUB", "USBHUB3", "USB3HUB", "NUSB3HUB", "RUSB3HUB", "FLXHCIH", "TIHUB3", "ETRONHUB3", "VIAHUB3", "ASMTHUB3", "IUSB3HUB", "VUSB3HUB", "AMDHUB30", "VHHUB", "AUSB3HUB"};
-static const char *composite_driver_names[] = {"USBCCGP"};
-static const char *winusbx_driver_names[] = WINUSBX_DRV_NAMES;
-static const char *hid_driver_names[] = {"HIDUSB", "MOUHID", "KBDHID"};
-const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = {
-	{
-		USB_API_UNSUPPORTED,
-		"Unsupported API",
-		NULL,
-		0,
-		unsupported_init,
-		unsupported_exit,
-		unsupported_open,
-		unsupported_close,
-		unsupported_configure_endpoints,
-		unsupported_claim_interface,
-		unsupported_set_interface_altsetting,
-		unsupported_release_interface,
-		unsupported_clear_halt,
-		unsupported_reset_device,
-		unsupported_submit_bulk_transfer,
-		unsupported_submit_iso_transfer,
-		unsupported_submit_control_transfer,
-		unsupported_abort_control,
-		unsupported_abort_transfers,
-		unsupported_copy_transfer_data,
-	},
-	{
-		USB_API_HUB,
-		"HUB API",
-		hub_driver_names,
-		ARRAYSIZE(hub_driver_names),
-		unsupported_init,
-		unsupported_exit,
-		unsupported_open,
-		unsupported_close,
-		unsupported_configure_endpoints,
-		unsupported_claim_interface,
-		unsupported_set_interface_altsetting,
-		unsupported_release_interface,
-		unsupported_clear_halt,
-		unsupported_reset_device,
-		unsupported_submit_bulk_transfer,
-		unsupported_submit_iso_transfer,
-		unsupported_submit_control_transfer,
-		unsupported_abort_control,
-		unsupported_abort_transfers,
-		unsupported_copy_transfer_data,
-	},
-	{
-		USB_API_COMPOSITE,
-		"Composite API",
-		composite_driver_names,
-		ARRAYSIZE(composite_driver_names),
-		composite_init,
-		composite_exit,
-		composite_open,
-		composite_close,
-		common_configure_endpoints,
-		composite_claim_interface,
-		composite_set_interface_altsetting,
-		composite_release_interface,
-		composite_clear_halt,
-		composite_reset_device,
-		composite_submit_bulk_transfer,
-		composite_submit_iso_transfer,
-		composite_submit_control_transfer,
-		composite_abort_control,
-		composite_abort_transfers,
-		composite_copy_transfer_data,
-	},
-	{
-		USB_API_WINUSBX,
-		"WinUSB-like APIs",
-		winusbx_driver_names,
-		ARRAYSIZE(winusbx_driver_names),
-		winusbx_init,
-		winusbx_exit,
-		winusbx_open,
-		winusbx_close,
-		winusbx_configure_endpoints,
-		winusbx_claim_interface,
-		winusbx_set_interface_altsetting,
-		winusbx_release_interface,
-		winusbx_clear_halt,
-		winusbx_reset_device,
-		winusbx_submit_bulk_transfer,
-		unsupported_submit_iso_transfer,
-		winusbx_submit_control_transfer,
-		winusbx_abort_control,
-		winusbx_abort_transfers,
-		winusbx_copy_transfer_data,
-	},
-	{
-		USB_API_HID,
-		"HID API",
-		hid_driver_names,
-		ARRAYSIZE(hid_driver_names),
-		hid_init,
-		hid_exit,
-		hid_open,
-		hid_close,
-		common_configure_endpoints,
-		hid_claim_interface,
-		hid_set_interface_altsetting,
-		hid_release_interface,
-		hid_clear_halt,
-		hid_reset_device,
-		hid_submit_bulk_transfer,
-		unsupported_submit_iso_transfer,
-		hid_submit_control_transfer,
-		hid_abort_transfers,
-		hid_abort_transfers,
-		hid_copy_transfer_data,
-	},
-};
-
-
-/*
- * WinUSB-like (WinUSB, libusb0/libusbK through libusbk DLL) API functions
- */
-#define WinUSBX_Set(fn)										\
-	do {											\
-		if (native_winusb)								\
-			WinUSBX[i].fn = (WinUsb_##fn##_t)GetProcAddress(h, "WinUsb_" #fn);	\
-		else										\
-			pLibK_GetProcAddress((PVOID *)&WinUSBX[i].fn, i, KUSB_FNID_##fn);	\
-	} while (0)
-
-static int winusbx_init(int sub_api, struct libusb_context *ctx)
-{
-	HMODULE h;
-	bool native_winusb;
-	int i;
-	KLIB_VERSION LibK_Version;
-	LibK_GetProcAddress_t pLibK_GetProcAddress = NULL;
-	LibK_GetVersion_t pLibK_GetVersion;
-
-	h = LoadLibraryA("libusbK");
-
-	if (h == NULL) {
-		usbi_info(ctx, "libusbK DLL is not available, will use native WinUSB");
-		h = LoadLibraryA("WinUSB");
-
-		if (h == NULL) {
-			usbi_warn(ctx, "WinUSB DLL is not available either, "
-				"you will not be able to access devices outside of enumeration");
-			return LIBUSB_ERROR_NOT_FOUND;
-		}
-	} else {
-		usbi_dbg("using libusbK DLL for universal access");
-		pLibK_GetVersion = (LibK_GetVersion_t)GetProcAddress(h, "LibK_GetVersion");
-		if (pLibK_GetVersion != NULL) {
-			pLibK_GetVersion(&LibK_Version);
-			usbi_dbg("libusbK version: %d.%d.%d.%d", LibK_Version.Major, LibK_Version.Minor,
-				LibK_Version.Micro, LibK_Version.Nano);
-		}
-		pLibK_GetProcAddress = (LibK_GetProcAddress_t)GetProcAddress(h, "LibK_GetProcAddress");
-		if (pLibK_GetProcAddress == NULL) {
-			usbi_err(ctx, "LibK_GetProcAddress() not found in libusbK DLL");
-			FreeLibrary(h);
-			return LIBUSB_ERROR_NOT_FOUND;
-		}
-	}
-
-	native_winusb = (pLibK_GetProcAddress == NULL);
-	for (i = SUB_API_LIBUSBK; i < SUB_API_MAX; i++) {
-		WinUSBX_Set(AbortPipe);
-		WinUSBX_Set(ControlTransfer);
-		WinUSBX_Set(FlushPipe);
-		WinUSBX_Set(Free);
-		WinUSBX_Set(GetAssociatedInterface);
-		WinUSBX_Set(GetCurrentAlternateSetting);
-		WinUSBX_Set(GetDescriptor);
-		WinUSBX_Set(GetOverlappedResult);
-		WinUSBX_Set(GetPipePolicy);
-		WinUSBX_Set(GetPowerPolicy);
-		WinUSBX_Set(Initialize);
-		WinUSBX_Set(QueryDeviceInformation);
-		WinUSBX_Set(QueryInterfaceSettings);
-		WinUSBX_Set(QueryPipe);
-		WinUSBX_Set(ReadPipe);
-		WinUSBX_Set(ResetPipe);
-		WinUSBX_Set(SetCurrentAlternateSetting);
-		WinUSBX_Set(SetPipePolicy);
-		WinUSBX_Set(SetPowerPolicy);
-		WinUSBX_Set(WritePipe);
-		if (!native_winusb)
-			WinUSBX_Set(ResetDevice);
-
-		if (WinUSBX[i].Initialize != NULL) {
-			WinUSBX[i].initialized = true;
-			usbi_dbg("initalized sub API %s", sub_api_name[i]);
-		} else {
-			usbi_warn(ctx, "Failed to initalize sub API %s", sub_api_name[i]);
-			WinUSBX[i].initialized = false;
-		}
-	}
-
-	WinUSBX_handle = h;
-	return LIBUSB_SUCCESS;
-}
-
-static int winusbx_exit(int sub_api)
-{
-	if (WinUSBX_handle != NULL) {
-		FreeLibrary(WinUSBX_handle);
-		WinUSBX_handle = NULL;
-
-		/* Reset the WinUSBX API structures */
-		memset(&WinUSBX, 0, sizeof(WinUSBX));
-	}
-
-	return LIBUSB_SUCCESS;
-}
-
-// NB: open and close must ensure that they only handle interface of
-// the right API type, as these functions can be called wholesale from
-// composite_open(), with interfaces belonging to different APIs
-static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle)
-{
-	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-
-	HANDLE file_handle;
-	int i;
-
-	CHECK_WINUSBX_AVAILABLE(sub_api);
-
-	// WinUSB requires a separate handle for each interface
-	for (i = 0; i < USB_MAXINTERFACES; i++) {
-		if ((priv->usb_interface[i].path != NULL)
-				&& (priv->usb_interface[i].apib->id == USB_API_WINUSBX)) {
-			file_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,
-				NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
-			if (file_handle == INVALID_HANDLE_VALUE) {
-				usbi_err(ctx, "could not open device %s (interface %d): %s", priv->usb_interface[i].path, i, windows_error_str(0));
-				switch(GetLastError()) {
-				case ERROR_FILE_NOT_FOUND: // The device was disconnected
-					return LIBUSB_ERROR_NO_DEVICE;
-				case ERROR_ACCESS_DENIED:
-					return LIBUSB_ERROR_ACCESS;
-				default:
-					return LIBUSB_ERROR_IO;
-				}
-			}
-			handle_priv->interface_handle[i].dev_handle = file_handle;
-		}
-	}
-
-	return LIBUSB_SUCCESS;
-}
-
-static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle)
-{
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	HANDLE handle;
-	int i;
-
-	if (sub_api == SUB_API_NOTSET)
-		sub_api = priv->sub_api;
-
-	if (!WinUSBX[sub_api].initialized)
-		return;
-
-	if (priv->apib->id == USB_API_COMPOSITE) {
-		// If this is a composite device, just free and close all WinUSB-like
-		// interfaces directly (each is independent and not associated with another)
-		for (i = 0; i < USB_MAXINTERFACES; i++) {
-			if (priv->usb_interface[i].apib->id == USB_API_WINUSBX) {
-				handle = handle_priv->interface_handle[i].api_handle;
-				if (HANDLE_VALID(handle))
-					WinUSBX[sub_api].Free(handle);
-
-				handle = handle_priv->interface_handle[i].dev_handle;
-				if (HANDLE_VALID(handle))
-					CloseHandle(handle);
-			}
-		}
-	} else {
-		// If this is a WinUSB device, free all interfaces above interface 0,
-		// then free and close interface 0 last
-		for (i = 1; i < USB_MAXINTERFACES; i++) {
-			handle = handle_priv->interface_handle[i].api_handle;
-			if (HANDLE_VALID(handle))
-				WinUSBX[sub_api].Free(handle);
-		}
-		handle = handle_priv->interface_handle[0].api_handle;
-		if (HANDLE_VALID(handle))
-			WinUSBX[sub_api].Free(handle);
-
-		handle = handle_priv->interface_handle[0].dev_handle;
-		if (HANDLE_VALID(handle))
-			CloseHandle(handle);
-	}
-}
-
-static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface)
-{
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	HANDLE winusb_handle = handle_priv->interface_handle[iface].api_handle;
-	UCHAR policy;
-	ULONG timeout = 0;
-	uint8_t endpoint_address;
-	int i;
-
-	CHECK_WINUSBX_AVAILABLE(sub_api);
-
-	// With handle and enpoints set (in parent), we can setup the default pipe properties
-	// see http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DVC-T705_DDC08.pptx
-	for (i = -1; i < priv->usb_interface[iface].nb_endpoints; i++) {
-		endpoint_address = (i == -1) ? 0 : priv->usb_interface[iface].endpoint[i];
-		if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
-			PIPE_TRANSFER_TIMEOUT, sizeof(ULONG), &timeout))
-			usbi_dbg("failed to set PIPE_TRANSFER_TIMEOUT for control endpoint %02X", endpoint_address);
-
-		if ((i == -1) || (sub_api == SUB_API_LIBUSB0))
-			continue; // Other policies don't apply to control endpoint or libusb0
-
-		policy = false;
-		if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
-			SHORT_PACKET_TERMINATE, sizeof(UCHAR), &policy))
-			usbi_dbg("failed to disable SHORT_PACKET_TERMINATE for endpoint %02X", endpoint_address);
-
-		if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
-			IGNORE_SHORT_PACKETS, sizeof(UCHAR), &policy))
-			usbi_dbg("failed to disable IGNORE_SHORT_PACKETS for endpoint %02X", endpoint_address);
-
-		policy = true;
-		/* ALLOW_PARTIAL_READS must be enabled due to likely libusbK bug. See:
-		   https://sourceforge.net/mailarchive/message.php?msg_id=29736015 */
-		if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
-			ALLOW_PARTIAL_READS, sizeof(UCHAR), &policy))
-			usbi_dbg("failed to enable ALLOW_PARTIAL_READS for endpoint %02X", endpoint_address);
-
-		if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address,
-			AUTO_CLEAR_STALL, sizeof(UCHAR), &policy))
-			usbi_dbg("failed to enable AUTO_CLEAR_STALL for endpoint %02X", endpoint_address);
-	}
-
-	return LIBUSB_SUCCESS;
-}
-
-static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
-{
-	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	bool is_using_usbccgp = (priv->apib->id == USB_API_COMPOSITE);
-	SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL;
-	HDEVINFO dev_info = INVALID_HANDLE_VALUE;
-	SP_DEVINFO_DATA dev_info_data;
-	char *dev_path_no_guid = NULL;
-	char filter_path[] = "\\\\.\\libusb0-0000";
-	bool found_filter = false;
-	HANDLE file_handle, winusb_handle;
-	DWORD err;
-	int i;
-
-	CHECK_WINUSBX_AVAILABLE(sub_api);
-
-	// If the device is composite, but using the default Windows composite parent driver (usbccgp)
-	// or if it's the first WinUSB-like interface, we get a handle through Initialize().
-	if ((is_using_usbccgp) || (iface == 0)) {
-		// composite device (independent interfaces) or interface 0
-		file_handle = handle_priv->interface_handle[iface].dev_handle;
-		if (!HANDLE_VALID(file_handle))
-			return LIBUSB_ERROR_NOT_FOUND;
-
-		if (!WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) {
-			handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE;
-			err = GetLastError();
-			switch(err) {
-			case ERROR_BAD_COMMAND:
-				// The device was disconnected
-				usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(0));
-				return LIBUSB_ERROR_NO_DEVICE;
-			default:
-				// it may be that we're using the libusb0 filter driver.
-				// TODO: can we move this whole business into the K/0 DLL?
-				for (i = 0; ; i++) {
-					safe_free(dev_interface_details);
-					safe_free(dev_path_no_guid);
-
-					dev_interface_details = get_interface_details_filter(ctx, &dev_info, &dev_info_data, &GUID_DEVINTERFACE_LIBUSB0_FILTER, i, filter_path);
-					if ((found_filter) || (dev_interface_details == NULL))
-						break;
-
-					// ignore GUID part
-					dev_path_no_guid = sanitize_path(strtok(dev_interface_details->DevicePath, "{"));
-					if (dev_path_no_guid == NULL)
-						continue;
-
-					if (strncmp(dev_path_no_guid, priv->usb_interface[iface].path, strlen(dev_path_no_guid)) == 0) {
-						file_handle = CreateFileA(filter_path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,
-							NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
-						if (file_handle != INVALID_HANDLE_VALUE) {
-							if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) {
-								// Replace the existing file handle with the working one
-								CloseHandle(handle_priv->interface_handle[iface].dev_handle);
-								handle_priv->interface_handle[iface].dev_handle = file_handle;
-								found_filter = true;
-							} else {
-								usbi_err(ctx, "could not initialize filter driver for %s", filter_path);
-								CloseHandle(file_handle);
-							}
-						} else {
-							usbi_err(ctx, "could not open device %s: %s", filter_path, windows_error_str(0));
-						}
-					}
-				}
-				free(dev_interface_details);
-				if (!found_filter) {
-					usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(err));
-					return LIBUSB_ERROR_ACCESS;
-				}
-			}
-		}
-		handle_priv->interface_handle[iface].api_handle = winusb_handle;
-	} else {
-		// For all other interfaces, use GetAssociatedInterface()
-		winusb_handle = handle_priv->interface_handle[0].api_handle;
-		// It is a requirement for multiple interface devices on Windows that, to you
-		// must first claim the first interface before you claim the others
-		if (!HANDLE_VALID(winusb_handle)) {
-			file_handle = handle_priv->interface_handle[0].dev_handle;
-			if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) {
-				handle_priv->interface_handle[0].api_handle = winusb_handle;
-				usbi_warn(ctx, "auto-claimed interface 0 (required to claim %d with WinUSB)", iface);
-			} else {
-				usbi_warn(ctx, "failed to auto-claim interface 0 (required to claim %d with WinUSB): %s", iface, windows_error_str(0));
-				return LIBUSB_ERROR_ACCESS;
-			}
-		}
-		if (!WinUSBX[sub_api].GetAssociatedInterface(winusb_handle, (UCHAR)(iface - 1),
-			&handle_priv->interface_handle[iface].api_handle)) {
-			handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE;
-			switch(GetLastError()) {
-			case ERROR_NO_MORE_ITEMS:   // invalid iface
-				return LIBUSB_ERROR_NOT_FOUND;
-			case ERROR_BAD_COMMAND:     // The device was disconnected
-				return LIBUSB_ERROR_NO_DEVICE;
-			case ERROR_ALREADY_EXISTS:  // already claimed
-				return LIBUSB_ERROR_BUSY;
-			default:
-				usbi_err(ctx, "could not claim interface %d: %s", iface, windows_error_str(0));
-				return LIBUSB_ERROR_ACCESS;
-			}
-		}
-	}
-	usbi_dbg("claimed interface %d", iface);
-	handle_priv->active_interface = iface;
-
-	return LIBUSB_SUCCESS;
-}
-
-static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
-{
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	HANDLE winusb_handle;
-
-	CHECK_WINUSBX_AVAILABLE(sub_api);
-
-	winusb_handle = handle_priv->interface_handle[iface].api_handle;
-	if (!HANDLE_VALID(winusb_handle))
-		return LIBUSB_ERROR_NOT_FOUND;
-
-	WinUSBX[sub_api].Free(winusb_handle);
-	handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE;
-
-	return LIBUSB_SUCCESS;
-}
-
-/*
- * Return the first valid interface (of the same API type), for control transfers
- */
-static int get_valid_interface(struct libusb_device_handle *dev_handle, int api_id)
-{
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	int i;
-
-	if ((api_id < USB_API_WINUSBX) || (api_id > USB_API_HID)) {
-		usbi_dbg("unsupported API ID");
-		return -1;
-	}
-
-	for (i = 0; i < USB_MAXINTERFACES; i++) {
-		if (HANDLE_VALID(handle_priv->interface_handle[i].dev_handle)
-				&& HANDLE_VALID(handle_priv->interface_handle[i].api_handle)
-				&& (priv->usb_interface[i].apib->id == api_id))
-			return i;
-	}
-
-	return -1;
-}
-
-/*
- * Lookup interface by endpoint address. -1 if not found
- */
-static int interface_by_endpoint(struct windows_device_priv *priv,
-	struct windows_device_handle_priv *handle_priv, uint8_t endpoint_address)
-{
-	int i, j;
-
-	for (i = 0; i < USB_MAXINTERFACES; i++) {
-		if (!HANDLE_VALID(handle_priv->interface_handle[i].api_handle))
-			continue;
-		if (priv->usb_interface[i].endpoint == NULL)
-			continue;
-		for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) {
-			if (priv->usb_interface[i].endpoint[j] == endpoint_address)
-				return i;
-		}
-	}
-
-	return -1;
-}
-
-static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
-	WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer;
-	ULONG size;
-	HANDLE winusb_handle;
-	int current_interface;
-	struct winfd wfd;
-
-	CHECK_WINUSBX_AVAILABLE(sub_api);
-
-	transfer_priv->pollable_fd = INVALID_WINFD;
-	size = transfer->length - LIBUSB_CONTROL_SETUP_SIZE;
-
-	// Windows places upper limits on the control transfer size
-	// See: https://msdn.microsoft.com/en-us/library/windows/hardware/ff538112.aspx
-	if (size > MAX_CTRL_BUFFER_LENGTH)
-		return LIBUSB_ERROR_INVALID_PARAM;
-
-	current_interface = get_valid_interface(transfer->dev_handle, USB_API_WINUSBX);
-	if (current_interface < 0) {
-		if (auto_claim(transfer, &current_interface, USB_API_WINUSBX) != LIBUSB_SUCCESS)
-			return LIBUSB_ERROR_NOT_FOUND;
-	}
-
-	usbi_dbg("will use interface %d", current_interface);
-	winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
-
-	wfd = usbi_create_fd(winusb_handle, RW_READ, NULL, NULL);
-	// Always use the handle returned from usbi_create_fd (wfd.handle)
-	if (wfd.fd < 0)
-		return LIBUSB_ERROR_NO_MEM;
-
-	// Sending of set configuration control requests from WinUSB creates issues
-	if (((setup->request_type & (0x03 << 5)) == LIBUSB_REQUEST_TYPE_STANDARD)
-			&& (setup->request == LIBUSB_REQUEST_SET_CONFIGURATION)) {
-		if (setup->value != priv->active_config) {
-			usbi_warn(ctx, "cannot set configuration other than the default one");
-			usbi_free_fd(&wfd);
-			return LIBUSB_ERROR_INVALID_PARAM;
-		}
-		wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
-		wfd.overlapped->InternalHigh = 0;
-	} else {
-		if (!WinUSBX[sub_api].ControlTransfer(wfd.handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, NULL, wfd.overlapped)) {
-			if (GetLastError() != ERROR_IO_PENDING) {
-				usbi_warn(ctx, "ControlTransfer failed: %s", windows_error_str(0));
-				usbi_free_fd(&wfd);
-				return LIBUSB_ERROR_IO;
-			}
-		} else {
-			wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
-			wfd.overlapped->InternalHigh = (DWORD)size;
-		}
-	}
-
-	// Use priv_transfer to store data needed for async polling
-	transfer_priv->pollable_fd = wfd;
-	transfer_priv->interface_number = (uint8_t)current_interface;
-
-	return LIBUSB_SUCCESS;
-}
-
-static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
-{
-	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	HANDLE winusb_handle;
-
-	CHECK_WINUSBX_AVAILABLE(sub_api);
-
-	if (altsetting > 255)
-		return LIBUSB_ERROR_INVALID_PARAM;
-
-	winusb_handle = handle_priv->interface_handle[iface].api_handle;
-	if (!HANDLE_VALID(winusb_handle)) {
-		usbi_err(ctx, "interface must be claimed first");
-		return LIBUSB_ERROR_NOT_FOUND;
-	}
-
-	if (!WinUSBX[sub_api].SetCurrentAlternateSetting(winusb_handle, (UCHAR)altsetting)) {
-		usbi_err(ctx, "SetCurrentAlternateSetting failed: %s", windows_error_str(0));
-		return LIBUSB_ERROR_IO;
-	}
-
-	return LIBUSB_SUCCESS;
-}
-
-static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
-	HANDLE winusb_handle;
-	bool ret;
-	int current_interface;
-	struct winfd wfd;
-
-	CHECK_WINUSBX_AVAILABLE(sub_api);
-
-	transfer_priv->pollable_fd = INVALID_WINFD;
-
-	current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
-	if (current_interface < 0) {
-		usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
-		return LIBUSB_ERROR_NOT_FOUND;
-	}
-
-	usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
-
-	winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
-
-	wfd = usbi_create_fd(winusb_handle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL);
-	// Always use the handle returned from usbi_create_fd (wfd.handle)
-	if (wfd.fd < 0)
-		return LIBUSB_ERROR_NO_MEM;
-
-	if (IS_XFERIN(transfer)) {
-		usbi_dbg("reading %d bytes", transfer->length);
-		ret = WinUSBX[sub_api].ReadPipe(wfd.handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped);
-	} else {
-		usbi_dbg("writing %d bytes", transfer->length);
-		ret = WinUSBX[sub_api].WritePipe(wfd.handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped);
-	}
-
-	if (!ret) {
-		if (GetLastError() != ERROR_IO_PENDING) {
-			usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0));
-			usbi_free_fd(&wfd);
-			return LIBUSB_ERROR_IO;
-		}
-	} else {
-		wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
-		wfd.overlapped->InternalHigh = (DWORD)transfer->length;
-	}
-
-	transfer_priv->pollable_fd = wfd;
-	transfer_priv->interface_number = (uint8_t)current_interface;
-
-	return LIBUSB_SUCCESS;
-}
-
-static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
-{
-	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	HANDLE winusb_handle;
-	int current_interface;
-
-	CHECK_WINUSBX_AVAILABLE(sub_api);
-
-	current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
-	if (current_interface < 0) {
-		usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear");
-		return LIBUSB_ERROR_NOT_FOUND;
-	}
-
-	usbi_dbg("matched endpoint %02X with interface %d", endpoint, current_interface);
-	winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
-
-	if (!WinUSBX[sub_api].ResetPipe(winusb_handle, endpoint)) {
-		usbi_err(ctx, "ResetPipe failed: %s", windows_error_str(0));
-		return LIBUSB_ERROR_NO_DEVICE;
-	}
-
-	return LIBUSB_SUCCESS;
-}
-
-/*
- * from http://www.winvistatips.com/winusb-bugchecks-t335323.html (confirmed
- * through testing as well):
- * "You can not call WinUsb_AbortPipe on control pipe. You can possibly cancel
- * the control transfer using CancelIo"
- */
-static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer)
-{
-	// Cancelling of the I/O is done in the parent
-	return LIBUSB_SUCCESS;
-}
-
-static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
-	HANDLE winusb_handle;
-	int current_interface;
-
-	CHECK_WINUSBX_AVAILABLE(sub_api);
-
-	current_interface = transfer_priv->interface_number;
-	if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) {
-		usbi_err(ctx, "program assertion failed: invalid interface_number");
-		return LIBUSB_ERROR_NOT_FOUND;
-	}
-	usbi_dbg("will use interface %d", current_interface);
-
-	winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
-
-	if (!WinUSBX[sub_api].AbortPipe(winusb_handle, transfer->endpoint)) {
-		usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0));
-		return LIBUSB_ERROR_NO_DEVICE;
-	}
-
-	return LIBUSB_SUCCESS;
-}
-
-/*
- * from the "How to Use WinUSB to Communicate with a USB Device" Microsoft white paper
- * (http://www.microsoft.com/whdc/connect/usb/winusb_howto.mspx):
- * "WinUSB does not support host-initiated reset port and cycle port operations" and
- * IOCTL_INTERNAL_USB_CYCLE_PORT is only available in kernel mode and the
- * IOCTL_USB_HUB_CYCLE_PORT ioctl was removed from Vista => the best we can do is
- * cycle the pipes (and even then, the control pipe can not be reset using WinUSB)
- */
-// TODO: (post hotplug): see if we can force eject the device and redetect it (reuse hotplug?)
-static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
-{
-	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	struct winfd wfd;
-	HANDLE winusb_handle;
-	int i, j;
-
-	CHECK_WINUSBX_AVAILABLE(sub_api);
-
-	// Reset any available pipe (except control)
-	for (i = 0; i < USB_MAXINTERFACES; i++) {
-		winusb_handle = handle_priv->interface_handle[i].api_handle;
-		for (wfd = handle_to_winfd(winusb_handle); wfd.fd > 0; ) {
-			// Cancel any pollable I/O
-			usbi_remove_pollfd(ctx, wfd.fd);
-			usbi_free_fd(&wfd);
-			wfd = handle_to_winfd(winusb_handle);
-		}
-
-		if (HANDLE_VALID(winusb_handle)) {
-			for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) {
-				usbi_dbg("resetting ep %02X", priv->usb_interface[i].endpoint[j]);
-				if (!WinUSBX[sub_api].AbortPipe(winusb_handle, priv->usb_interface[i].endpoint[j]))
-					usbi_err(ctx, "AbortPipe (pipe address %02X) failed: %s",
-						priv->usb_interface[i].endpoint[j], windows_error_str(0));
-
-				// FlushPipe seems to fail on OUT pipes
-				if (IS_EPIN(priv->usb_interface[i].endpoint[j])
-						&& (!WinUSBX[sub_api].FlushPipe(winusb_handle, priv->usb_interface[i].endpoint[j])))
-					usbi_err(ctx, "FlushPipe (pipe address %02X) failed: %s",
-						priv->usb_interface[i].endpoint[j], windows_error_str(0));
-
-				if (!WinUSBX[sub_api].ResetPipe(winusb_handle, priv->usb_interface[i].endpoint[j]))
-					usbi_err(ctx, "ResetPipe (pipe address %02X) failed: %s",
-						priv->usb_interface[i].endpoint[j], windows_error_str(0));
-			}
-		}
-	}
-
-	// libusbK & libusb0 have the ability to issue an actual device reset
-	if (WinUSBX[sub_api].ResetDevice != NULL) {
-		winusb_handle = handle_priv->interface_handle[0].api_handle;
-		if (HANDLE_VALID(winusb_handle))
-			WinUSBX[sub_api].ResetDevice(winusb_handle);
-	}
-
-	return LIBUSB_SUCCESS;
-}
-
-static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
-{
-	itransfer->transferred += io_size;
-	return LIBUSB_TRANSFER_COMPLETED;
-}
-
-/*
- * Internal HID Support functions (from libusb-win32)
- * Note that functions that complete data transfer synchronously must return
- * LIBUSB_COMPLETED instead of LIBUSB_SUCCESS
- */
-static int _hid_get_hid_descriptor(struct hid_device_priv *dev, void *data, size_t *size);
-static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, size_t *size);
-
-static int _hid_wcslen(WCHAR *str)
-{
-	int i = 0;
-
-	while (str[i] && (str[i] != 0x409))
-		i++;
-
-	return i;
-}
-
-static int _hid_get_device_descriptor(struct hid_device_priv *dev, void *data, size_t *size)
-{
-	struct libusb_device_descriptor d;
-
-	d.bLength = LIBUSB_DT_DEVICE_SIZE;
-	d.bDescriptorType = LIBUSB_DT_DEVICE;
-	d.bcdUSB = 0x0200; /* 2.00 */
-	d.bDeviceClass = 0;
-	d.bDeviceSubClass = 0;
-	d.bDeviceProtocol = 0;
-	d.bMaxPacketSize0 = 64; /* fix this! */
-	d.idVendor = (uint16_t)dev->vid;
-	d.idProduct = (uint16_t)dev->pid;
-	d.bcdDevice = 0x0100;
-	d.iManufacturer = dev->string_index[0];
-	d.iProduct = dev->string_index[1];
-	d.iSerialNumber = dev->string_index[2];
-	d.bNumConfigurations = 1;
-
-	if (*size > LIBUSB_DT_DEVICE_SIZE)
-		*size = LIBUSB_DT_DEVICE_SIZE;
-	memcpy(data, &d, *size);
-
-	return LIBUSB_COMPLETED;
-}
-
-static int _hid_get_config_descriptor(struct hid_device_priv *dev, void *data, size_t *size)
-{
-	char num_endpoints = 0;
-	size_t config_total_len = 0;
-	char tmp[HID_MAX_CONFIG_DESC_SIZE];
-	struct libusb_config_descriptor *cd;
-	struct libusb_interface_descriptor *id;
-	struct libusb_hid_descriptor *hd;
-	struct libusb_endpoint_descriptor *ed;
-	size_t tmp_size;
-
-	if (dev->input_report_size)
-		num_endpoints++;
-	if (dev->output_report_size)
-		num_endpoints++;
-
-	config_total_len = LIBUSB_DT_CONFIG_SIZE + LIBUSB_DT_INTERFACE_SIZE
-		+ LIBUSB_DT_HID_SIZE + num_endpoints * LIBUSB_DT_ENDPOINT_SIZE;
-
-	cd = (struct libusb_config_descriptor *)tmp;
-	id = (struct libusb_interface_descriptor *)(tmp + LIBUSB_DT_CONFIG_SIZE);
-	hd = (struct libusb_hid_descriptor *)(tmp + LIBUSB_DT_CONFIG_SIZE
-		+ LIBUSB_DT_INTERFACE_SIZE);
-	ed = (struct libusb_endpoint_descriptor *)(tmp + LIBUSB_DT_CONFIG_SIZE
-		+ LIBUSB_DT_INTERFACE_SIZE
-		+ LIBUSB_DT_HID_SIZE);
-
-	cd->bLength = LIBUSB_DT_CONFIG_SIZE;
-	cd->bDescriptorType = LIBUSB_DT_CONFIG;
-	cd->wTotalLength = (uint16_t)config_total_len;
-	cd->bNumInterfaces = 1;
-	cd->bConfigurationValue = 1;
-	cd->iConfiguration = 0;
-	cd->bmAttributes = 1 << 7; /* bus powered */
-	cd->MaxPower = 50;
-
-	id->bLength = LIBUSB_DT_INTERFACE_SIZE;
-	id->bDescriptorType = LIBUSB_DT_INTERFACE;
-	id->bInterfaceNumber = 0;
-	id->bAlternateSetting = 0;
-	id->bNumEndpoints = num_endpoints;
-	id->bInterfaceClass = 3;
-	id->bInterfaceSubClass = 0;
-	id->bInterfaceProtocol = 0;
-	id->iInterface = 0;
-
-	tmp_size = LIBUSB_DT_HID_SIZE;
-	_hid_get_hid_descriptor(dev, hd, &tmp_size);
-
-	if (dev->input_report_size) {
-		ed->bLength = LIBUSB_DT_ENDPOINT_SIZE;
-		ed->bDescriptorType = LIBUSB_DT_ENDPOINT;
-		ed->bEndpointAddress = HID_IN_EP;
-		ed->bmAttributes = 3;
-		ed->wMaxPacketSize = dev->input_report_size - 1;
-		ed->bInterval = 10;
-		ed = (struct libusb_endpoint_descriptor *)((char *)ed + LIBUSB_DT_ENDPOINT_SIZE);
-	}
-
-	if (dev->output_report_size) {
-		ed->bLength = LIBUSB_DT_ENDPOINT_SIZE;
-		ed->bDescriptorType = LIBUSB_DT_ENDPOINT;
-		ed->bEndpointAddress = HID_OUT_EP;
-		ed->bmAttributes = 3;
-		ed->wMaxPacketSize = dev->output_report_size - 1;
-		ed->bInterval = 10;
-	}
-
-	if (*size > config_total_len)
-		*size = config_total_len;
-	memcpy(data, tmp, *size);
-
-	return LIBUSB_COMPLETED;
-}
-
-static int _hid_get_string_descriptor(struct hid_device_priv *dev, int _index,
-	void *data, size_t *size)
-{
-	void *tmp = NULL;
-	size_t tmp_size = 0;
-	int i;
-
-	/* language ID, EN-US */
-	char string_langid[] = {0x09, 0x04};
-
-	if ((*size < 2) || (*size > 255))
-		return LIBUSB_ERROR_OVERFLOW;
-
-	if (_index == 0) {
-		tmp = string_langid;
-		tmp_size = sizeof(string_langid) + 2;
-	} else {
-		for (i = 0; i < 3; i++) {
-			if (_index == (dev->string_index[i])) {
-				tmp = dev->string[i];
-				tmp_size = (_hid_wcslen(dev->string[i]) + 1) * sizeof(WCHAR);
-				break;
-			}
-		}
-
-		if (i == 3) // not found
-			return LIBUSB_ERROR_INVALID_PARAM;
-	}
-
-	if (!tmp_size)
-		return LIBUSB_ERROR_INVALID_PARAM;
-
-	if (tmp_size < *size)
-		*size = tmp_size;
-
-	// 2 byte header
-	((uint8_t *)data)[0] = (uint8_t)*size;
-	((uint8_t *)data)[1] = LIBUSB_DT_STRING;
-	memcpy((uint8_t *)data + 2, tmp, *size - 2);
-
-	return LIBUSB_COMPLETED;
-}
-
-static int _hid_get_hid_descriptor(struct hid_device_priv *dev, void *data, size_t *size)
-{
-	struct libusb_hid_descriptor d;
-	uint8_t tmp[MAX_HID_DESCRIPTOR_SIZE];
-	size_t report_len = MAX_HID_DESCRIPTOR_SIZE;
-
-	_hid_get_report_descriptor(dev, tmp, &report_len);
-
-	d.bLength = LIBUSB_DT_HID_SIZE;
-	d.bDescriptorType = LIBUSB_DT_HID;
-	d.bcdHID = 0x0110; /* 1.10 */
-	d.bCountryCode = 0;
-	d.bNumDescriptors = 1;
-	d.bClassDescriptorType = LIBUSB_DT_REPORT;
-	d.wClassDescriptorLength = (uint16_t)report_len;
-
-	if (*size > LIBUSB_DT_HID_SIZE)
-		*size = LIBUSB_DT_HID_SIZE;
-	memcpy(data, &d, *size);
-
-	return LIBUSB_COMPLETED;
-}
-
-static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, size_t *size)
-{
-	uint8_t d[MAX_HID_DESCRIPTOR_SIZE];
-	size_t i = 0;
-
-	/* usage page (0xFFA0 == vendor defined) */
-	d[i++] = 0x06; d[i++] = 0xA0; d[i++] = 0xFF;
-	/* usage (vendor defined) */
-	d[i++] = 0x09; d[i++] = 0x01;
-	/* start collection (application) */
-	d[i++] = 0xA1; d[i++] = 0x01;
-	/* input report */
-	if (dev->input_report_size) {
-		/* usage (vendor defined) */
-		d[i++] = 0x09; d[i++] = 0x01;
-		/* logical minimum (0) */
-		d[i++] = 0x15; d[i++] = 0x00;
-		/* logical maximum (255) */
-		d[i++] = 0x25; d[i++] = 0xFF;
-		/* report size (8 bits) */
-		d[i++] = 0x75; d[i++] = 0x08;
-		/* report count */
-		d[i++] = 0x95; d[i++] = (uint8_t)dev->input_report_size - 1;
-		/* input (data, variable, absolute) */
-		d[i++] = 0x81; d[i++] = 0x00;
-	}
-	/* output report */
-	if (dev->output_report_size) {
-		/* usage (vendor defined) */
-		d[i++] = 0x09; d[i++] = 0x02;
-		/* logical minimum (0) */
-		d[i++] = 0x15; d[i++] = 0x00;
-		/* logical maximum (255) */
-		d[i++] = 0x25; d[i++] = 0xFF;
-		/* report size (8 bits) */
-		d[i++] = 0x75; d[i++] = 0x08;
-		/* report count */
-		d[i++] = 0x95; d[i++] = (uint8_t)dev->output_report_size - 1;
-		/* output (data, variable, absolute) */
-		d[i++] = 0x91; d[i++] = 0x00;
-	}
-	/* feature report */
-	if (dev->feature_report_size) {
-		/* usage (vendor defined) */
-		d[i++] = 0x09; d[i++] = 0x03;
-		/* logical minimum (0) */
-		d[i++] = 0x15; d[i++] = 0x00;
-		/* logical maximum (255) */
-		d[i++] = 0x25; d[i++] = 0xFF;
-		/* report size (8 bits) */
-		d[i++] = 0x75; d[i++] = 0x08;
-		/* report count */
-		d[i++] = 0x95; d[i++] = (uint8_t)dev->feature_report_size - 1;
-		/* feature (data, variable, absolute) */
-		d[i++] = 0xb2; d[i++] = 0x02; d[i++] = 0x01;
-	}
-
-	/* end collection */
-	d[i++] = 0xC0;
-
-	if (*size > i)
-		*size = i;
-	memcpy(data, d, *size);
-
-	return LIBUSB_COMPLETED;
-}
-
-static int _hid_get_descriptor(struct hid_device_priv *dev, HANDLE hid_handle, int recipient,
-	int type, int _index, void *data, size_t *size)
-{
-	switch(type) {
-	case LIBUSB_DT_DEVICE:
-		usbi_dbg("LIBUSB_DT_DEVICE");
-		return _hid_get_device_descriptor(dev, data, size);
-	case LIBUSB_DT_CONFIG:
-		usbi_dbg("LIBUSB_DT_CONFIG");
-		if (!_index)
-			return _hid_get_config_descriptor(dev, data, size);
-		return LIBUSB_ERROR_INVALID_PARAM;
-	case LIBUSB_DT_STRING:
-		usbi_dbg("LIBUSB_DT_STRING");
-		return _hid_get_string_descriptor(dev, _index, data, size);
-	case LIBUSB_DT_HID:
-		usbi_dbg("LIBUSB_DT_HID");
-		if (!_index)
-			return _hid_get_hid_descriptor(dev, data, size);
-		return LIBUSB_ERROR_INVALID_PARAM;
-	case LIBUSB_DT_REPORT:
-		usbi_dbg("LIBUSB_DT_REPORT");
-		if (!_index)
-			return _hid_get_report_descriptor(dev, data, size);
-		return LIBUSB_ERROR_INVALID_PARAM;
-	case LIBUSB_DT_PHYSICAL:
-		usbi_dbg("LIBUSB_DT_PHYSICAL");
-		if (HidD_GetPhysicalDescriptor(hid_handle, data, (ULONG)*size))
-			return LIBUSB_COMPLETED;
-		return LIBUSB_ERROR_OTHER;
-	}
-
-	usbi_dbg("unsupported");
-	return LIBUSB_ERROR_NOT_SUPPORTED;
-}
-
-static int _hid_get_report(struct hid_device_priv *dev, HANDLE hid_handle, int id, void *data,
-	struct windows_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type)
-{
-	uint8_t *buf;
-	DWORD ioctl_code, read_size, expected_size = (DWORD)*size;
-	int r = LIBUSB_SUCCESS;
-
-	if (tp->hid_buffer != NULL)
-		usbi_dbg("program assertion failed: hid_buffer is not NULL");
-
-	if ((*size == 0) || (*size > MAX_HID_REPORT_SIZE)) {
-		usbi_dbg("invalid size (%u)", *size);
-		return LIBUSB_ERROR_INVALID_PARAM;
-	}
-
-	switch (report_type) {
-	case HID_REPORT_TYPE_INPUT:
-		ioctl_code = IOCTL_HID_GET_INPUT_REPORT;
-		break;
-	case HID_REPORT_TYPE_FEATURE:
-		ioctl_code = IOCTL_HID_GET_FEATURE;
-		break;
-	default:
-		usbi_dbg("unknown HID report type %d", report_type);
-		return LIBUSB_ERROR_INVALID_PARAM;
-	}
-
-	// Add a trailing byte to detect overflows
-	buf = calloc(1, expected_size + 1);
-	if (buf == NULL)
-		return LIBUSB_ERROR_NO_MEM;
-
-	buf[0] = (uint8_t)id; // Must be set always
-	usbi_dbg("report ID: 0x%02X", buf[0]);
-
-	tp->hid_expected_size = expected_size;
-	read_size = expected_size;
-
-	// NB: The size returned by DeviceIoControl doesn't include report IDs when not in use (0)
-	if (!DeviceIoControl(hid_handle, ioctl_code, buf, expected_size + 1,
-		buf, expected_size + 1, &read_size, overlapped)) {
-		if (GetLastError() != ERROR_IO_PENDING) {
-			usbi_dbg("Failed to Read HID Report: %s", windows_error_str(0));
-			free(buf);
-			return LIBUSB_ERROR_IO;
-		}
-		// Asynchronous wait
-		tp->hid_buffer = buf;
-		tp->hid_dest = data; // copy dest, as not necessarily the start of the transfer buffer
-		return LIBUSB_SUCCESS;
-	}
-
-	// Transfer completed synchronously => copy and discard extra buffer
-	if (read_size == 0) {
-		usbi_warn(NULL, "program assertion failed - read completed synchronously, but no data was read");
-		*size = 0;
-	} else {
-		if (buf[0] != id)
-			usbi_warn(NULL, "mismatched report ID (data is %02X, parameter is %02X)", buf[0], id);
-
-		if ((size_t)read_size > expected_size) {
-			r = LIBUSB_ERROR_OVERFLOW;
-			usbi_dbg("OVERFLOW!");
-		} else {
-			r = LIBUSB_COMPLETED;
-		}
-
-		*size = MIN((size_t)read_size, *size);
-		if (id == 0)
-			memcpy(data, buf + 1, *size); // Discard report ID
-		else
-			memcpy(data, buf, *size);
-	}
-
-	free(buf);
-	return r;
-}
-
-static int _hid_set_report(struct hid_device_priv *dev, HANDLE hid_handle, int id, void *data,
-	struct windows_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type)
-{
-	uint8_t *buf = NULL;
-	DWORD ioctl_code, write_size = (DWORD)*size;
-
-	if (tp->hid_buffer != NULL)
-		usbi_dbg("program assertion failed: hid_buffer is not NULL");
-
-	if ((*size == 0) || (*size > MAX_HID_REPORT_SIZE)) {
-		usbi_dbg("invalid size (%u)", *size);
-		return LIBUSB_ERROR_INVALID_PARAM;
-	}
-
-	switch (report_type) {
-	case HID_REPORT_TYPE_OUTPUT:
-		ioctl_code = IOCTL_HID_SET_OUTPUT_REPORT;
-		break;
-	case HID_REPORT_TYPE_FEATURE:
-		ioctl_code = IOCTL_HID_SET_FEATURE;
-		break;
-	default:
-		usbi_dbg("unknown HID report type %d", report_type);
-		return LIBUSB_ERROR_INVALID_PARAM;
-	}
-
-	usbi_dbg("report ID: 0x%02X", id);
-	// When report IDs are not used (i.e. when id == 0), we must add
-	// a null report ID. Otherwise, we just use original data buffer
-	if (id == 0)
-		write_size++;
-
-	buf = malloc(write_size);
-	if (buf == NULL)
-		return LIBUSB_ERROR_NO_MEM;
-
-	if (id == 0) {
-		buf[0] = 0;
-		memcpy(buf + 1, data, *size);
-	} else {
-		// This seems like a waste, but if we don't duplicate the
-		// data, we'll get issues when freeing hid_buffer
-		memcpy(buf, data, *size);
-		if (buf[0] != id)
-			usbi_warn(NULL, "mismatched report ID (data is %02X, parameter is %02X)", buf[0], id);
-	}
-
-	// NB: The size returned by DeviceIoControl doesn't include report IDs when not in use (0)
-	if (!DeviceIoControl(hid_handle, ioctl_code, buf, write_size,
-		buf, write_size, &write_size, overlapped)) {
-		if (GetLastError() != ERROR_IO_PENDING) {
-			usbi_dbg("Failed to Write HID Output Report: %s", windows_error_str(0));
-			free(buf);
-			return LIBUSB_ERROR_IO;
-		}
-		tp->hid_buffer = buf;
-		tp->hid_dest = NULL;
-		return LIBUSB_SUCCESS;
-	}
-
-	// Transfer completed synchronously
-	*size = write_size;
-	if (write_size == 0)
-		usbi_dbg("program assertion failed - write completed synchronously, but no data was written");
-
-	free(buf);
-	return LIBUSB_COMPLETED;
-}
-
-static int _hid_class_request(struct hid_device_priv *dev, HANDLE hid_handle, int request_type,
-	int request, int value, int _index, void *data, struct windows_transfer_priv *tp,
-	size_t *size, OVERLAPPED *overlapped)
-{
-	int report_type = (value >> 8) & 0xFF;
-	int report_id = value & 0xFF;
-
-	if ((LIBUSB_REQ_RECIPIENT(request_type) != LIBUSB_RECIPIENT_INTERFACE)
-			&& (LIBUSB_REQ_RECIPIENT(request_type) != LIBUSB_RECIPIENT_DEVICE))
-		return LIBUSB_ERROR_INVALID_PARAM;
-
-	if (LIBUSB_REQ_OUT(request_type) && request == HID_REQ_SET_REPORT)
-		return _hid_set_report(dev, hid_handle, report_id, data, tp, size, overlapped, report_type);
-
-	if (LIBUSB_REQ_IN(request_type) && request == HID_REQ_GET_REPORT)
-		return _hid_get_report(dev, hid_handle, report_id, data, tp, size, overlapped, report_type);
-
-	return LIBUSB_ERROR_INVALID_PARAM;
-}
-
-
-/*
- * HID API functions
- */
-static int hid_init(int sub_api, struct libusb_context *ctx)
-{
-	DLL_GET_HANDLE(hid);
-	DLL_LOAD_FUNC(hid, HidD_GetAttributes, TRUE);
-	DLL_LOAD_FUNC(hid, HidD_GetHidGuid, TRUE);
-	DLL_LOAD_FUNC(hid, HidD_GetPreparsedData, TRUE);
-	DLL_LOAD_FUNC(hid, HidD_FreePreparsedData, TRUE);
-	DLL_LOAD_FUNC(hid, HidD_GetManufacturerString, TRUE);
-	DLL_LOAD_FUNC(hid, HidD_GetProductString, TRUE);
-	DLL_LOAD_FUNC(hid, HidD_GetSerialNumberString, TRUE);
-	DLL_LOAD_FUNC(hid, HidP_GetCaps, TRUE);
-	DLL_LOAD_FUNC(hid, HidD_SetNumInputBuffers, TRUE);
-	DLL_LOAD_FUNC(hid, HidD_SetFeature, TRUE);
-	DLL_LOAD_FUNC(hid, HidD_GetFeature, TRUE);
-	DLL_LOAD_FUNC(hid, HidD_GetPhysicalDescriptor, TRUE);
-	DLL_LOAD_FUNC(hid, HidD_GetInputReport, FALSE);
-	DLL_LOAD_FUNC(hid, HidD_SetOutputReport, FALSE);
-	DLL_LOAD_FUNC(hid, HidD_FlushQueue, TRUE);
-	DLL_LOAD_FUNC(hid, HidP_GetValueCaps, TRUE);
-
-	api_hid_available = true;
-	return LIBUSB_SUCCESS;
-}
-
-static int hid_exit(int sub_api)
-{
-	DLL_FREE_HANDLE(hid);
-
-	return LIBUSB_SUCCESS;
-}
-
-// NB: open and close must ensure that they only handle interface of
-// the right API type, as these functions can be called wholesale from
-// composite_open(), with interfaces belonging to different APIs
-static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
-{
-	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	HIDD_ATTRIBUTES hid_attributes;
-	PHIDP_PREPARSED_DATA preparsed_data = NULL;
-	HIDP_CAPS capabilities;
-	HIDP_VALUE_CAPS *value_caps;
-	HANDLE hid_handle = INVALID_HANDLE_VALUE;
-	int i, j;
-	// report IDs handling
-	ULONG size[3];
-	int nb_ids[2]; // zero and nonzero report IDs
-#if defined(ENABLE_LOGGING)
-	const char *type[3] = {"input", "output", "feature"};
-#endif
-
-	CHECK_HID_AVAILABLE;
-
-	if (priv->hid == NULL) {
-		usbi_err(ctx, "program assertion failed - private HID structure is unitialized");
-		return LIBUSB_ERROR_NOT_FOUND;
-	}
-
-	for (i = 0; i < USB_MAXINTERFACES; i++) {
-		if ((priv->usb_interface[i].path != NULL)
-				&& (priv->usb_interface[i].apib->id == USB_API_HID)) {
-			hid_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,
-				NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
-			/*
-			 * http://www.lvr.com/hidfaq.htm: Why do I receive "Access denied" when attempting to access my HID?
-			 * "Windows 2000 and later have exclusive read/write access to HIDs that are configured as a system
-			 * keyboards or mice. An application can obtain a handle to a system keyboard or mouse by not
-			 * requesting READ or WRITE access with CreateFile. Applications can then use HidD_SetFeature and
-			 * HidD_GetFeature (if the device supports Feature reports)."
-			 */
-			if (hid_handle == INVALID_HANDLE_VALUE) {
-				usbi_warn(ctx, "could not open HID device in R/W mode (keyboard or mouse?) - trying without");
-				hid_handle = CreateFileA(priv->usb_interface[i].path, 0, FILE_SHARE_WRITE | FILE_SHARE_READ,
-					NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
-				if (hid_handle == INVALID_HANDLE_VALUE) {
-					usbi_err(ctx, "could not open device %s (interface %d): %s", priv->path, i, windows_error_str(0));
-					switch(GetLastError()) {
-					case ERROR_FILE_NOT_FOUND: // The device was disconnected
-						return LIBUSB_ERROR_NO_DEVICE;
-					case ERROR_ACCESS_DENIED:
-						return LIBUSB_ERROR_ACCESS;
-					default:
-						return LIBUSB_ERROR_IO;
-					}
-				}
-				priv->usb_interface[i].restricted_functionality = true;
-			}
-			handle_priv->interface_handle[i].api_handle = hid_handle;
-		}
-	}
-
-	hid_attributes.Size = sizeof(hid_attributes);
-	do {
-		if (!HidD_GetAttributes(hid_handle, &hid_attributes)) {
-			usbi_err(ctx, "could not gain access to HID top collection (HidD_GetAttributes)");
-			break;
-		}
-
-		priv->hid->vid = hid_attributes.VendorID;
-		priv->hid->pid = hid_attributes.ProductID;
-
-		// Set the maximum available input buffer size
-		for (i = 32; HidD_SetNumInputBuffers(hid_handle, i); i *= 2);
-		usbi_dbg("set maximum input buffer size to %d", i / 2);
-
-		// Get the maximum input and output report size
-		if (!HidD_GetPreparsedData(hid_handle, &preparsed_data) || !preparsed_data) {
-			usbi_err(ctx, "could not read HID preparsed data (HidD_GetPreparsedData)");
-			break;
-		}
-		if (HidP_GetCaps(preparsed_data, &capabilities) != HIDP_STATUS_SUCCESS) {
-			usbi_err(ctx, "could not parse HID capabilities (HidP_GetCaps)");
-			break;
-		}
-
-		// Find out if interrupt will need report IDs
-		size[0] = capabilities.NumberInputValueCaps;
-		size[1] = capabilities.NumberOutputValueCaps;
-		size[2] = capabilities.NumberFeatureValueCaps;
-		for (j = HidP_Input; j <= HidP_Feature; j++) {
-			usbi_dbg("%u HID %s report value(s) found", (unsigned int)size[j], type[j]);
-			priv->hid->uses_report_ids[j] = false;
-			if (size[j] > 0) {
-				value_caps = calloc(size[j], sizeof(HIDP_VALUE_CAPS));
-				if ((value_caps != NULL)
-						&& (HidP_GetValueCaps((HIDP_REPORT_TYPE)j, value_caps, &size[j], preparsed_data) == HIDP_STATUS_SUCCESS)
-						&& (size[j] >= 1)) {
-					nb_ids[0] = 0;
-					nb_ids[1] = 0;
-					for (i = 0; i < (int)size[j]; i++) {
-						usbi_dbg("  Report ID: 0x%02X", value_caps[i].ReportID);
-						if (value_caps[i].ReportID != 0)
-							nb_ids[1]++;
-						else
-							nb_ids[0]++;
-					}
-					if (nb_ids[1] != 0) {
-						if (nb_ids[0] != 0)
-							usbi_warn(ctx, "program assertion failed: zero and nonzero report IDs used for %s",
-								type[j]);
-						priv->hid->uses_report_ids[j] = true;
-					}
-				} else {
-					usbi_warn(ctx, "  could not process %s report IDs", type[j]);
-				}
-				free(value_caps);
-			}
-		}
-
-		// Set the report sizes
-		priv->hid->input_report_size = capabilities.InputReportByteLength;
-		priv->hid->output_report_size = capabilities.OutputReportByteLength;
-		priv->hid->feature_report_size = capabilities.FeatureReportByteLength;
-
-		// Fetch string descriptors
-		priv->hid->string_index[0] = priv->dev_descriptor.iManufacturer;
-		if (priv->hid->string_index[0] != 0)
-			HidD_GetManufacturerString(hid_handle, priv->hid->string[0], sizeof(priv->hid->string[0]));
-		else
-			priv->hid->string[0][0] = 0;
-
-		priv->hid->string_index[1] = priv->dev_descriptor.iProduct;
-		if (priv->hid->string_index[1] != 0)
-			HidD_GetProductString(hid_handle, priv->hid->string[1], sizeof(priv->hid->string[1]));
-		else
-			priv->hid->string[1][0] = 0;
-
-		priv->hid->string_index[2] = priv->dev_descriptor.iSerialNumber;
-		if (priv->hid->string_index[2] != 0)
-			HidD_GetSerialNumberString(hid_handle, priv->hid->string[2], sizeof(priv->hid->string[2]));
-		else
-			priv->hid->string[2][0] = 0;
-	} while(0);
-
-	if (preparsed_data)
-		HidD_FreePreparsedData(preparsed_data);
-
-	return LIBUSB_SUCCESS;
-}
-
-static void hid_close(int sub_api, struct libusb_device_handle *dev_handle)
-{
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	HANDLE file_handle;
-	int i;
-
-	if (!api_hid_available)
-		return;
-
-	for (i = 0; i < USB_MAXINTERFACES; i++) {
-		if (priv->usb_interface[i].apib->id == USB_API_HID) {
-			file_handle = handle_priv->interface_handle[i].api_handle;
-			if (HANDLE_VALID(file_handle))
-				CloseHandle(file_handle);
-		}
-	}
-}
-
-static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
-{
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-
-	CHECK_HID_AVAILABLE;
-
-	// NB: Disconnection detection is not possible in this function
-	if (priv->usb_interface[iface].path == NULL)
-		return LIBUSB_ERROR_NOT_FOUND; // invalid iface
-
-	// We use dev_handle as a flag for interface claimed
-	if (handle_priv->interface_handle[iface].dev_handle == INTERFACE_CLAIMED)
-		return LIBUSB_ERROR_BUSY; // already claimed
-
-
-	handle_priv->interface_handle[iface].dev_handle = INTERFACE_CLAIMED;
-
-	usbi_dbg("claimed interface %d", iface);
-	handle_priv->active_interface = iface;
-
-	return LIBUSB_SUCCESS;
-}
-
-static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
-{
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-
-	CHECK_HID_AVAILABLE;
-
-	if (priv->usb_interface[iface].path == NULL)
-		return LIBUSB_ERROR_NOT_FOUND; // invalid iface
-
-	if (handle_priv->interface_handle[iface].dev_handle != INTERFACE_CLAIMED)
-		return LIBUSB_ERROR_NOT_FOUND; // invalid iface
-
-	handle_priv->interface_handle[iface].dev_handle = INVALID_HANDLE_VALUE;
-
-	return LIBUSB_SUCCESS;
-}
-
-static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
-{
-	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
-
-	CHECK_HID_AVAILABLE;
-
-	if (altsetting > 255)
-		return LIBUSB_ERROR_INVALID_PARAM;
-
-	if (altsetting != 0) {
-		usbi_err(ctx, "set interface altsetting not supported for altsetting >0");
-		return LIBUSB_ERROR_NOT_SUPPORTED;
-	}
-
-	return LIBUSB_SUCCESS;
-}
-
-static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
-	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer;
-	HANDLE hid_handle;
-	struct winfd wfd;
-	int current_interface, config;
-	size_t size;
-	int r = LIBUSB_ERROR_INVALID_PARAM;
-
-	CHECK_HID_AVAILABLE;
-
-	transfer_priv->pollable_fd = INVALID_WINFD;
-	safe_free(transfer_priv->hid_buffer);
-	transfer_priv->hid_dest = NULL;
-	size = transfer->length - LIBUSB_CONTROL_SETUP_SIZE;
-
-	if (size > MAX_CTRL_BUFFER_LENGTH)
-		return LIBUSB_ERROR_INVALID_PARAM;
-
-	current_interface = get_valid_interface(transfer->dev_handle, USB_API_HID);
-	if (current_interface < 0) {
-		if (auto_claim(transfer, &current_interface, USB_API_HID) != LIBUSB_SUCCESS)
-			return LIBUSB_ERROR_NOT_FOUND;
-	}
-
-	usbi_dbg("will use interface %d", current_interface);
-	hid_handle = handle_priv->interface_handle[current_interface].api_handle;
-	// Always use the handle returned from usbi_create_fd (wfd.handle)
-	wfd = usbi_create_fd(hid_handle, RW_READ, NULL, NULL);
-	if (wfd.fd < 0)
-		return LIBUSB_ERROR_NOT_FOUND;
-
-	switch(LIBUSB_REQ_TYPE(setup->request_type)) {
-	case LIBUSB_REQUEST_TYPE_STANDARD:
-		switch(setup->request) {
-		case LIBUSB_REQUEST_GET_DESCRIPTOR:
-			r = _hid_get_descriptor(priv->hid, wfd.handle, LIBUSB_REQ_RECIPIENT(setup->request_type),
-				(setup->value >> 8) & 0xFF, setup->value & 0xFF, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, &size);
-			break;
-		case LIBUSB_REQUEST_GET_CONFIGURATION:
-			r = windows_get_configuration(transfer->dev_handle, &config);
-			if (r == LIBUSB_SUCCESS) {
-				size = 1;
-				((uint8_t *)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = (uint8_t)config;
-				r = LIBUSB_COMPLETED;
-			}
-			break;
-		case LIBUSB_REQUEST_SET_CONFIGURATION:
-			if (setup->value == priv->active_config) {
-				r = LIBUSB_COMPLETED;
-			} else {
-				usbi_warn(ctx, "cannot set configuration other than the default one");
-				r = LIBUSB_ERROR_NOT_SUPPORTED;
-			}
-			break;
-		case LIBUSB_REQUEST_GET_INTERFACE:
-			size = 1;
-			((uint8_t *)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = 0;
-			r = LIBUSB_COMPLETED;
-			break;
-		case LIBUSB_REQUEST_SET_INTERFACE:
-			r = hid_set_interface_altsetting(0, transfer->dev_handle, setup->index, setup->value);
-			if (r == LIBUSB_SUCCESS)
-				r = LIBUSB_COMPLETED;
-			break;
-		default:
-			usbi_warn(ctx, "unsupported HID control request");
-			r = LIBUSB_ERROR_NOT_SUPPORTED;
-			break;
-		}
-		break;
-	case LIBUSB_REQUEST_TYPE_CLASS:
-		r = _hid_class_request(priv->hid, wfd.handle, setup->request_type, setup->request, setup->value,
-			setup->index, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, transfer_priv,
-			&size, wfd.overlapped);
-		break;
-	default:
-		usbi_warn(ctx, "unsupported HID control request");
-		r = LIBUSB_ERROR_NOT_SUPPORTED;
-		break;
-	}
-
-	if (r == LIBUSB_COMPLETED) {
-		// Force request to be completed synchronously. Transferred size has been set by previous call
-		wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
-		// http://msdn.microsoft.com/en-us/library/ms684342%28VS.85%29.aspx
-		// set InternalHigh to the number of bytes transferred
-		wfd.overlapped->InternalHigh = (DWORD)size;
-		r = LIBUSB_SUCCESS;
-	}
-
-	if (r == LIBUSB_SUCCESS) {
-		// Use priv_transfer to store data needed for async polling
-		transfer_priv->pollable_fd = wfd;
-		transfer_priv->interface_number = (uint8_t)current_interface;
-	} else {
-		usbi_free_fd(&wfd);
-	}
-
-	return r;
-}
-
-static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
-	struct winfd wfd;
-	HANDLE hid_handle;
-	bool direction_in, ret;
-	int current_interface, length;
-	DWORD size;
-	int r = LIBUSB_SUCCESS;
-
-	CHECK_HID_AVAILABLE;
-
-	transfer_priv->pollable_fd = INVALID_WINFD;
-	transfer_priv->hid_dest = NULL;
-	safe_free(transfer_priv->hid_buffer);
-
-	current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
-	if (current_interface < 0) {
-		usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
-		return LIBUSB_ERROR_NOT_FOUND;
-	}
-
-	usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
-
-	hid_handle = handle_priv->interface_handle[current_interface].api_handle;
-	direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN;
-
-	wfd = usbi_create_fd(hid_handle, direction_in?RW_READ:RW_WRITE, NULL, NULL);
-	// Always use the handle returned from usbi_create_fd (wfd.handle)
-	if (wfd.fd < 0)
-		return LIBUSB_ERROR_NO_MEM;
-
-	// If report IDs are not in use, an extra prefix byte must be added
-	if (((direction_in) && (!priv->hid->uses_report_ids[0]))
-			|| ((!direction_in) && (!priv->hid->uses_report_ids[1])))
-		length = transfer->length + 1;
-	else
-		length = transfer->length;
-
-	// Add a trailing byte to detect overflows on input
-	transfer_priv->hid_buffer = calloc(1, length + 1);
-	if (transfer_priv->hid_buffer == NULL)
-		return LIBUSB_ERROR_NO_MEM;
-
-	transfer_priv->hid_expected_size = length;
-
-	if (direction_in) {
-		transfer_priv->hid_dest = transfer->buffer;
-		usbi_dbg("reading %d bytes (report ID: 0x00)", length);
-		ret = ReadFile(wfd.handle, transfer_priv->hid_buffer, length + 1, &size, wfd.overlapped);
-	} else {
-		if (!priv->hid->uses_report_ids[1])
-			memcpy(transfer_priv->hid_buffer + 1, transfer->buffer, transfer->length);
-		else
-			// We could actually do without the calloc and memcpy in this case
-			memcpy(transfer_priv->hid_buffer, transfer->buffer, transfer->length);
-
-		usbi_dbg("writing %d bytes (report ID: 0x%02X)", length, transfer_priv->hid_buffer[0]);
-		ret = WriteFile(wfd.handle, transfer_priv->hid_buffer, length, &size, wfd.overlapped);
-	}
-
-	if (!ret) {
-		if (GetLastError() != ERROR_IO_PENDING) {
-			usbi_err(ctx, "HID transfer failed: %s", windows_error_str(0));
-			usbi_free_fd(&wfd);
-			safe_free(transfer_priv->hid_buffer);
-			return LIBUSB_ERROR_IO;
-		}
-	} else {
-		// Only write operations that completed synchronously need to free up
-		// hid_buffer. For reads, copy_transfer_data() handles that process.
-		if (!direction_in)
-			safe_free(transfer_priv->hid_buffer);
-
-		if (size == 0) {
-			usbi_err(ctx, "program assertion failed - no data was transferred");
-			size = 1;
-		}
-		if (size > (size_t)length) {
-			usbi_err(ctx, "OVERFLOW!");
-			r = LIBUSB_ERROR_OVERFLOW;
-		}
-		wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
-		wfd.overlapped->InternalHigh = size;
-	}
-
-	transfer_priv->pollable_fd = wfd;
-	transfer_priv->interface_number = (uint8_t)current_interface;
-
-	return r;
-}
-
-static int hid_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
-	HANDLE hid_handle;
-	int current_interface;
-
-	CHECK_HID_AVAILABLE;
-
-	current_interface = transfer_priv->interface_number;
-	hid_handle = handle_priv->interface_handle[current_interface].api_handle;
-	CancelIo(hid_handle);
-
-	return LIBUSB_SUCCESS;
-}
-
-static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
-{
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	HANDLE hid_handle;
-	int current_interface;
-
-	CHECK_HID_AVAILABLE;
-
-	// Flushing the queues on all interfaces is the best we can achieve
-	for (current_interface = 0; current_interface < USB_MAXINTERFACES; current_interface++) {
-		hid_handle = handle_priv->interface_handle[current_interface].api_handle;
-		if (HANDLE_VALID(hid_handle))
-			HidD_FlushQueue(hid_handle);
-	}
-
-	return LIBUSB_SUCCESS;
-}
-
-static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
-{
-	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	HANDLE hid_handle;
-	int current_interface;
-
-	CHECK_HID_AVAILABLE;
-
-	current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
-	if (current_interface < 0) {
-		usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear");
-		return LIBUSB_ERROR_NOT_FOUND;
-	}
-
-	usbi_dbg("matched endpoint %02X with interface %d", endpoint, current_interface);
-	hid_handle = handle_priv->interface_handle[current_interface].api_handle;
-
-	// No endpoint selection with Microsoft's implementation, so we try to flush the
-	// whole interface. Should be OK for most case scenarios
-	if (!HidD_FlushQueue(hid_handle)) {
-		usbi_err(ctx, "Flushing of HID queue failed: %s", windows_error_str(0));
-		// Device was probably disconnected
-		return LIBUSB_ERROR_NO_DEVICE;
-	}
-
-	return LIBUSB_SUCCESS;
-}
-
-// This extra function is only needed for HID
-static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	int r = LIBUSB_TRANSFER_COMPLETED;
-	uint32_t corrected_size = io_size;
-
-	if (transfer_priv->hid_buffer != NULL) {
-		// If we have a valid hid_buffer, it means the transfer was async
-		if (transfer_priv->hid_dest != NULL) { // Data readout
-			if (corrected_size > 0) {
-				// First, check for overflow
-				if (corrected_size > transfer_priv->hid_expected_size) {
-					usbi_err(ctx, "OVERFLOW!");
-					corrected_size = (uint32_t)transfer_priv->hid_expected_size;
-					r = LIBUSB_TRANSFER_OVERFLOW;
-				}
-
-				if (transfer_priv->hid_buffer[0] == 0) {
-					// Discard the 1 byte report ID prefix
-					corrected_size--;
-					memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer + 1, corrected_size);
-				} else {
-					memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer, corrected_size);
-				}
-			}
-			transfer_priv->hid_dest = NULL;
-		}
-		// For write, we just need to free the hid buffer
-		safe_free(transfer_priv->hid_buffer);
-	}
-
-	itransfer->transferred += corrected_size;
-	return r;
-}
-
-
-/*
- * Composite API functions
- */
-static int composite_init(int sub_api, struct libusb_context *ctx)
-{
-	return LIBUSB_SUCCESS;
-}
-
-static int composite_exit(int sub_api)
-{
-	return LIBUSB_SUCCESS;
-}
-
-static int composite_open(int sub_api, struct libusb_device_handle *dev_handle)
-{
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	int r = LIBUSB_ERROR_NOT_FOUND;
-	uint8_t i;
-	// SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID
-	bool available[SUB_API_MAX + 1] = { 0 };
-
-	for (i = 0; i < USB_MAXINTERFACES; i++) {
-		switch (priv->usb_interface[i].apib->id) {
-		case USB_API_WINUSBX:
-			if (priv->usb_interface[i].sub_api != SUB_API_NOTSET)
-				available[priv->usb_interface[i].sub_api] = true;
-			break;
-		case USB_API_HID:
-			available[SUB_API_MAX] = true;
-			break;
-		default:
-			break;
-		}
-	}
-
-	for (i = 0; i < SUB_API_MAX; i++) { // WinUSB-like drivers
-		if (available[i]) {
-			r = usb_api_backend[USB_API_WINUSBX].open(i, dev_handle);
-			if (r != LIBUSB_SUCCESS)
-				return r;
-		}
-	}
-
-	if (available[SUB_API_MAX]) // HID driver
-		r = hid_open(SUB_API_NOTSET, dev_handle);
-
-	return r;
-}
-
-static void composite_close(int sub_api, struct libusb_device_handle *dev_handle)
-{
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	uint8_t i;
-	// SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID
-	bool available[SUB_API_MAX + 1] = { 0 };
-
-	for (i = 0; i < USB_MAXINTERFACES; i++) {
-		switch (priv->usb_interface[i].apib->id) {
-		case USB_API_WINUSBX:
-			if (priv->usb_interface[i].sub_api != SUB_API_NOTSET)
-				available[priv->usb_interface[i].sub_api] = true;
-			break;
-		case USB_API_HID:
-			available[SUB_API_MAX] = true;
-			break;
-		default:
-			break;
-		}
-	}
-
-	for (i = 0; i < SUB_API_MAX; i++) { // WinUSB-like drivers
-		if (available[i])
-			usb_api_backend[USB_API_WINUSBX].close(i, dev_handle);
-	}
-
-	if (available[SUB_API_MAX]) // HID driver
-		hid_close(SUB_API_NOTSET, dev_handle);
-}
-
-static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
-{
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-
-	return priv->usb_interface[iface].apib->
-		claim_interface(priv->usb_interface[iface].sub_api, dev_handle, iface);
-}
-
-static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
-{
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-
-	return priv->usb_interface[iface].apib->
-		set_interface_altsetting(priv->usb_interface[iface].sub_api, dev_handle, iface, altsetting);
-}
-
-static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
-{
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-
-	return priv->usb_interface[iface].apib->
-		release_interface(priv->usb_interface[iface].sub_api, dev_handle, iface);
-}
-
-static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
-	struct libusb_config_descriptor *conf_desc;
-	WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer;
-	int iface, pass, r;
-
-	// Interface shouldn't matter for control, but it does in practice, with Windows'
-	// restrictions with regards to accessing HID keyboards and mice. Try to target
-	// a specific interface first, if possible.
-	switch (LIBUSB_REQ_RECIPIENT(setup->request_type)) {
-	case LIBUSB_RECIPIENT_INTERFACE:
-		iface = setup->index & 0xFF;
-		break;
-	case LIBUSB_RECIPIENT_ENDPOINT:
-		r = libusb_get_active_config_descriptor(transfer->dev_handle->dev, &conf_desc);
-		if (r == LIBUSB_SUCCESS) {
-			iface = get_interface_by_endpoint(conf_desc, (setup->index & 0xFF));
-			libusb_free_config_descriptor(conf_desc);
-			break;
-		}
-		// Fall through if not able to determine interface
-	default:
-		iface = -1;
-		break;
-	}
-
-	// Try and target a specific interface if the control setup indicates such
-	if ((iface >= 0) && (iface < USB_MAXINTERFACES)) {
-		usbi_dbg("attempting control transfer targeted to interface %d", iface);
-		if (priv->usb_interface[iface].path != NULL) {
-			r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer);
-			if (r == LIBUSB_SUCCESS)
-				return r;
-		}
-	}
-
-	// Either not targeted to a specific interface or no luck in doing so.
-	// Try a 2 pass approach with all interfaces.
-	for (pass = 0; pass < 2; pass++) {
-		for (iface = 0; iface < USB_MAXINTERFACES; iface++) {
-			if (priv->usb_interface[iface].path != NULL) {
-				if ((pass == 0) && (priv->usb_interface[iface].restricted_functionality)) {
-					usbi_dbg("trying to skip restricted interface #%d (HID keyboard or mouse?)", iface);
-					continue;
-				}
-				usbi_dbg("using interface %d", iface);
-				r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer);
-				// If not supported on this API, it may be supported on another, so don't give up yet!!
-				if (r == LIBUSB_ERROR_NOT_SUPPORTED)
-					continue;
-				return r;
-			}
-		}
-	}
-
-	usbi_err(ctx, "no libusb supported interfaces to complete request");
-	return LIBUSB_ERROR_NOT_FOUND;
-}
-
-static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) {
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
-	int current_interface;
-
-	current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
-	if (current_interface < 0) {
-		usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
-		return LIBUSB_ERROR_NOT_FOUND;
-	}
-
-	return priv->usb_interface[current_interface].apib->
-		submit_bulk_transfer(priv->usb_interface[current_interface].sub_api, itransfer);
-}
-
-static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) {
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
-	int current_interface;
-
-	current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
-	if (current_interface < 0) {
-		usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
-		return LIBUSB_ERROR_NOT_FOUND;
-	}
-
-	return priv->usb_interface[current_interface].apib->
-		submit_iso_transfer(priv->usb_interface[current_interface].sub_api, itransfer);
-}
-
-static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
-{
-	struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
-	struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	int current_interface;
-
-	current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
-	if (current_interface < 0) {
-		usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear");
-		return LIBUSB_ERROR_NOT_FOUND;
-	}
-
-	return priv->usb_interface[current_interface].apib->
-		clear_halt(priv->usb_interface[current_interface].sub_api, dev_handle, endpoint);
-}
-
-static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
-
-	return priv->usb_interface[transfer_priv->interface_number].apib->
-		abort_control(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer);
-}
-
-static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
-
-	return priv->usb_interface[transfer_priv->interface_number].apib->
-		abort_transfers(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer);
-}
-
-static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
-{
-	struct windows_device_priv *priv = _device_priv(dev_handle->dev);
-	int r;
-	uint8_t i;
-	bool available[SUB_API_MAX];
-
-	for (i = 0; i < SUB_API_MAX; i++)
-		available[i] = false;
-
-	for (i = 0; i < USB_MAXINTERFACES; i++) {
-		if ((priv->usb_interface[i].apib->id == USB_API_WINUSBX)
-				&& (priv->usb_interface[i].sub_api != SUB_API_NOTSET))
-			available[priv->usb_interface[i].sub_api] = true;
-	}
-
-	for (i = 0; i < SUB_API_MAX; i++) {
-		if (available[i]) {
-			r = usb_api_backend[USB_API_WINUSBX].reset_device(i, dev_handle);
-			if (r != LIBUSB_SUCCESS)
-				return r;
-		}
-	}
-
-	return LIBUSB_SUCCESS;
-}
-
-static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
-{
-	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-	struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
-	struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
-
-	return priv->usb_interface[transfer_priv->interface_number].apib->
-		copy_transfer_data(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer, io_size);
-}
-
-#endif /* !USE_USBDK */

+ 0 - 1
vendor/github.com/karalabe/hid/libusb/libusb/version_nano.h

@@ -1 +0,0 @@
-#define LIBUSB_NANO 11182

+ 6 - 0
vendor/github.com/karalabe/usb/AUTHORS

@@ -0,0 +1,6 @@
+Felix Lange <fjl@twurst.com>
+Guillaume Ballet <gballet@gmail.com>
+Jakob Weisblat <jakobw@yubico.com>
+Mateusz Mikołajczyk <mikolajczyk.mateusz@gmail.com>
+Péter Szilágyi <peterke@gmail.com>
+Rosen Penev <rosenp@gmail.com>

+ 165 - 0
vendor/github.com/karalabe/usb/LICENSE

@@ -0,0 +1,165 @@
+                   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.

+ 47 - 0
vendor/github.com/karalabe/usb/README.md

@@ -0,0 +1,47 @@
+[![Travis][travisimg]][travisurl]
+[![AppVeyor][appveyorimg]][appveyorurl]
+[![GoDoc][docimg]][docurl]
+
+[travisimg]:   https://travis-ci.org/karalabe/usb.svg?branch=master
+[travisurl]:   https://travis-ci.org/karalabe/usb
+[appveyorimg]: https://ci.appveyor.com/api/projects/status/u96eq262bj2itprh/branch/master?svg=true
+[appveyorurl]: https://ci.appveyor.com/project/karalabe/usb
+[docimg]:      https://godoc.org/github.com/karalabe/usb?status.svg
+[docurl]:      https://godoc.org/github.com/karalabe/usb
+
+# Yet another USB library for Go
+
+The `usb` package is a cross platform, fully self-contained library for accessing and communicating with USB devices **either via HID or low level interrupts**. The goal of the library was to create a simple way to find-, attach to- and read/write form USB devices.
+
+There are multiple already existing USB libraries:
+
+ * The original `gousb` package [created by @kylelemons](https://github.com/kylelemons/gousb) and nowadays [maintained by @google](https://github.com/google/gousb) is a CGO wrapper around `libusb`. It is the most advanced USB library for Go out there.
+   * Unfortunately, `gousb` requires the `libusb` C library to be installed both during build as well as during runtime on the host operating system. This breaks binary portability and also adds unnecessary hurdles on Windows.
+   * Furthermore, whilst HID devices are supported by `libusb`, the OS on Macos and Windows explicitly takes over these devices, so only native system calls can be used on recent versions (i.e. you **cannot** use `libusb` for HID).
+ * There is a fork of `gousb` [created by @karalabe](https://github.com/karalabe/gousb) that statically linked `libusb` during build, but with the lack of HID access, that work was abandoned.
+ * For HID-only devices, a previous self-contained package was created at [`github.com/karalabe/hid`](https://github.com/karalabe/hid), which worked well for hardware wallet uses cases in [`go-ethereum`](https://github.com/ethereum/go-ethereum). It's a simple package that does it's thing well.
+   * Unfortunately, `hid` is not capable of talking to generic USB devices. When multiple different devices are needed, eventually some will not support the HID spec (e.g. WebUSB). Pulling in both `hid` and `gousb` will break down due to both depending internally on different versions of `libusb` on Linux.
+
+This `usb` package is a proper integration of `hidapi` and `libusb` so that communication with HID devices is done via system calls, whereas communication with lower level USB devices is done via interrupts. All this detail is hidden away behind a tiny interface.
+
+The package supports Linux, macOS, Windows and FreeBSD. Exclude constraints are also specified for Android and iOS to allow smoother vendoring into cross platform projects.
+
+## Cross-compiling
+
+Using `go get`, the embedded C library is compiled into the binary format of your host OS. Cross compiling to a different platform or architecture entails disabling CGO by default in Go, causing device enumeration `hid.Enumerate()` to yield no results.
+
+To cross compile a functional version of this library, you'll need to enable CGO during cross compilation via `CGO_ENABLED=1` and you'll need to install and set a cross compilation enabled C toolkit via `CC=your-cross-gcc`.
+
+## Acknowledgements
+
+Although the `usb` package is an implementation from scratch, HID support was heavily inspired by the existing [`go.hid`](https://github.com/GeertJohan/go.hid) library, which seems abandoned since 2015; is incompatible with Go 1.6+; and has various external dependencies.
+
+Wide character support in the HID support is done via the [`gowchar`](https://github.com/orofarne/gowchar) library, unmaintained since 2013; non buildable with a modern Go release and failing `go vet` checks. As such, `gowchar` was also vendored in inline.
+
+Error handling for the `libusb` integration originates from the [`gousb`](https://github.com/google/gousb) library.
+
+## License
+
+This USB library is licensed under the [GNU Lesser General Public License v3.0](https://www.gnu.org/licenses/lgpl-3.0.en.html) (dictated by libusb).
+
+If you are only interested in Human Interface devices, a less restrictive package can be found at [`github.com/karalabe/hid`](https://github.com/karalabe/hid).

+ 3 - 3
vendor/github.com/karalabe/hid/appveyor.yml → vendor/github.com/karalabe/usb/appveyor.yml

@@ -1,7 +1,7 @@
 os: Visual Studio 2015
 
 # Clone directly into GOPATH.
-clone_folder: C:\gopath\src\github.com\karalabe\hid
+clone_folder: C:\gopath\src\github.com\karalabe\usb
 clone_depth: 1
 version: "{branch}.{build}"
 environment:
@@ -22,8 +22,8 @@ environment:
 
 install:
   - rmdir C:\go /s /q
-  - appveyor DownloadFile https://storage.googleapis.com/golang/go1.10.1.windows-%GOARCH%.zip
-  - 7z x go1.10.1.windows-%GOARCH%.zip -y -oC:\ > NUL
+  - appveyor DownloadFile https://storage.googleapis.com/golang/go1.12.5.windows-%GOARCH%.zip
+  - 7z x go1.12.5.windows-%GOARCH%.zip -y -oC:\ > NUL
   - go version
   - gcc --version
 

+ 76 - 0
vendor/github.com/karalabe/usb/demo.go

@@ -0,0 +1,76 @@
+// usb - Self contained USB and HID library for Go
+// Copyright 2019 The library Authors
+//
+// This library is free software: you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation, either version 3 of the License, or (at your option) any
+// later version.
+//
+// The library is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+// A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along
+// with the library. If not, see <http://www.gnu.org/licenses/>.
+
+// +build none
+
+package main
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/karalabe/usb"
+)
+
+func main() {
+	// Enumerate all the HID devices in alphabetical path order
+	hids, err := usb.EnumerateHid(0, 0)
+	if err != nil {
+		panic(err)
+	}
+	for i := 0; i < len(hids); i++ {
+		for j := i + 1; j < len(hids); j++ {
+			if hids[i].Path > hids[j].Path {
+				hids[i], hids[j] = hids[j], hids[i]
+			}
+		}
+	}
+	for i, hid := range hids {
+		fmt.Println(strings.Repeat("-", 128))
+		fmt.Printf("HID #%d\n", i)
+		fmt.Printf("  OS Path:      %s\n", hid.Path)
+		fmt.Printf("  Vendor ID:    %#04x\n", hid.VendorID)
+		fmt.Printf("  Product ID:   %#04x\n", hid.ProductID)
+		fmt.Printf("  Release:      %d\n", hid.Release)
+		fmt.Printf("  Serial:       %s\n", hid.Serial)
+		fmt.Printf("  Manufacturer: %s\n", hid.Manufacturer)
+		fmt.Printf("  Product:      %s\n", hid.Product)
+		fmt.Printf("  Usage Page:   %d\n", hid.UsagePage)
+		fmt.Printf("  Usage:        %d\n", hid.Usage)
+		fmt.Printf("  Interface:    %d\n", hid.Interface)
+	}
+	fmt.Println(strings.Repeat("=", 128))
+
+	// Enumerate all the non-HID devices in alphabetical path order
+	raws, err := usb.EnumerateRaw(0, 0)
+	if err != nil {
+		panic(err)
+	}
+	for i := 0; i < len(raws); i++ {
+		for j := i + 1; j < len(raws); j++ {
+			if raws[i].Path > raws[j].Path {
+				raws[i], raws[j] = raws[j], raws[i]
+			}
+		}
+	}
+	for i, raw := range raws {
+		fmt.Printf("RAW #%d\n", i)
+		fmt.Printf("  OS Path:    %s\n", raw.Path)
+		fmt.Printf("  Vendor ID:  %#04x\n", raw.VendorID)
+		fmt.Printf("  Product ID: %#04x\n", raw.ProductID)
+		fmt.Printf("  Interface:  %d\n", raw.Interface)
+		fmt.Println(strings.Repeat("-", 128))
+	}
+}

+ 3 - 0
vendor/github.com/karalabe/usb/go.mod

@@ -0,0 +1,3 @@
+module github.com/karalabe/usb
+
+go 1.12

+ 42 - 0
vendor/github.com/karalabe/usb/hid_disabled.go

@@ -0,0 +1,42 @@
+// usb - Self contained USB and HID library for Go
+// Copyright 2017 The library Authors
+//
+// This library is free software: you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation, either version 3 of the License, or (at your option) any
+// later version.
+//
+// The library is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+// A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along
+// with the library. If not, see <http://www.gnu.org/licenses/>.
+
+// +build !freebsd,!linux,!darwin,!windows ios !cgo
+
+package usb
+
+// HidDevice is a live HID USB connected device handle. On platforms that this file
+// implements, the type lacks the actual HID device and all methods are noop.
+type HidDevice struct {
+	DeviceInfo // Embed the infos for easier access
+}
+
+// Close releases the HID USB device handle. On platforms that this file implements,
+// the method is just a noop.
+func (dev *HidDevice) Close() error {
+	return ErrUnsupportedPlatform
+}
+
+// Write sends an output report to a HID device. On platforms that this file
+// implements, the method just returns an error.
+func (dev *HidDevice) Write(b []byte) (int, error) {
+	return 0, ErrUnsupportedPlatform
+}
+
+// Read retrieves an input report from a HID device. On platforms that this file
+// implements, the method just returns an error.
+func (dev *HidDevice) Read(b []byte) (int, error) {
+	return 0, ErrUnsupportedPlatform
+}

+ 29 - 70
vendor/github.com/karalabe/hid/hid_enabled.go → vendor/github.com/karalabe/usb/hid_enabled.go

@@ -1,44 +1,25 @@
-// hid - Gopher Interface Devices (USB HID)
-// Copyright (c) 2017 Péter Szilágyi. All rights reserved.
+// usb - Self contained USB and HID library for Go
+// Copyright 2017 The library Authors
 //
-// This file is released under the 3-clause BSD license. Note however that Linux
-// support depends on libusb, released under LGNU GPL 2.1 or later.
+// This library is free software: you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation, either version 3 of the License, or (at your option) any
+// later version.
+//
+// The library is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+// A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along
+// with the library. If not, see <http://www.gnu.org/licenses/>.
 
-// +build linux,cgo darwin,!ios,cgo windows,cgo
+// +build freebsd,cgo linux,cgo darwin,!ios,cgo windows,cgo
 
-package hid
+package usb
 
 /*
-#cgo CFLAGS: -I./hidapi/hidapi
-
-#cgo linux CFLAGS: -I./libusb/libusb -DDEFAULT_VISIBILITY="" -DOS_LINUX -D_GNU_SOURCE -DPOLL_NFDS_TYPE=int
-#cgo linux,!android LDFLAGS: -lrt
-#cgo darwin CFLAGS: -DOS_DARWIN
-#cgo darwin LDFLAGS: -framework CoreFoundation -framework IOKit
-#cgo windows CFLAGS: -DOS_WINDOWS
-#cgo windows LDFLAGS: -lsetupapi
-
-#ifdef OS_LINUX
-	#include <sys/poll.h>
-	#include "os/threads_posix.c"
-	#include "os/poll_posix.c"
-
-	#include "os/linux_usbfs.c"
-	#include "os/linux_netlink.c"
-
-	#include "core.c"
-	#include "descriptor.c"
-	#include "hotplug.c"
-	#include "io.c"
-	#include "strerror.c"
-	#include "sync.c"
-
-	#include "hidapi/libusb/hid.c"
-#elif OS_DARWIN
-	#include "hidapi/mac/hid.c"
-#elif OS_WINDOWS
-	#include "hidapi/windows/hid.c"
-#endif
+#include <stdlib.h>
+#include "./hidapi/hidapi/hidapi.h"
 */
 import "C"
 
@@ -49,35 +30,16 @@ import (
 	"unsafe"
 )
 
-// enumerateLock is a mutex serializing access to USB device enumeration needed
-// by the macOS USB HID system calls, which require 2 consecutive method calls
-// for enumeration, causing crashes if called concurrently.
-//
-// For more details, see:
-//   https://developer.apple.com/documentation/iokit/1438371-iohidmanagersetdevicematching
-//   > "subsequent calls will cause the hid manager to release previously enumerated devices"
-var enumerateLock sync.Mutex
-
-// Supported returns whether this platform is supported by the HID library or not.
-// The goal of this method is to allow programatically handling platforms that do
-// not support USB HID and not having to fall back to build constraints.
-func Supported() bool {
-	return true
-}
-
-// Enumerate returns a list of all the HID devices attached to the system which
+// enumerateHid returns a list of all the HID devices attached to the system which
 // match the vendor and product id:
 //  - If the vendor id is set to 0 then any vendor matches.
 //  - If the product id is set to 0 then any product matches.
 //  - If the vendor and product id are both 0, all HID devices are returned.
-func Enumerate(vendorID uint16, productID uint16) []DeviceInfo {
-	enumerateLock.Lock()
-	defer enumerateLock.Unlock()
-
+func enumerateHid(vendorID uint16, productID uint16) ([]DeviceInfo, error) {
 	// Gather all device infos and ensure they are freed before returning
 	head := C.hid_enumerate(C.ushort(vendorID), C.ushort(productID))
 	if head == nil {
-		return nil
+		return nil, nil
 	}
 	defer C.hid_free_enumeration(head)
 
@@ -104,14 +66,11 @@ func Enumerate(vendorID uint16, productID uint16) []DeviceInfo {
 		}
 		infos = append(infos, info)
 	}
-	return infos
+	return infos, nil
 }
 
-// Open connects to an HID device by its path name.
-func (info DeviceInfo) Open() (*Device, error) {
-	enumerateLock.Lock()
-	defer enumerateLock.Unlock()
-
+// openHid connects to an HID device by its path name.
+func openHid(info DeviceInfo) (*hidDevice, error) {
 	path := C.CString(info.Path)
 	defer C.free(unsafe.Pointer(path))
 
@@ -119,14 +78,14 @@ func (info DeviceInfo) Open() (*Device, error) {
 	if device == nil {
 		return nil, errors.New("hidapi: failed to open device")
 	}
-	return &Device{
+	return &hidDevice{
 		DeviceInfo: info,
 		device:     device,
 	}, nil
 }
 
-// Device is a live HID USB connected device handle.
-type Device struct {
+// hidDevice is a live HID USB connected device handle.
+type hidDevice struct {
 	DeviceInfo // Embed the infos for easier access
 
 	device *C.hid_device // Low level HID device to communicate through
@@ -134,7 +93,7 @@ type Device struct {
 }
 
 // Close releases the HID USB device handle.
-func (dev *Device) Close() error {
+func (dev *hidDevice) Close() error {
 	dev.lock.Lock()
 	defer dev.lock.Unlock()
 
@@ -149,7 +108,7 @@ func (dev *Device) Close() error {
 //
 // Write will send the data on the first OUT endpoint, if one exists. If it does
 // not, it will send the data through the Control Endpoint (Endpoint 0).
-func (dev *Device) Write(b []byte) (int, error) {
+func (dev *hidDevice) Write(b []byte) (int, error) {
 	// Abort if nothing to write
 	if len(b) == 0 {
 		return 0, nil
@@ -192,7 +151,7 @@ func (dev *Device) Write(b []byte) (int, error) {
 }
 
 // Read retrieves an input report from a HID device.
-func (dev *Device) Read(b []byte) (int, error) {
+func (dev *hidDevice) Read(b []byte) (int, error) {
 	// Aborth if nothing to read
 	if len(b) == 0 {
 		return 0, nil

+ 0 - 0
vendor/github.com/karalabe/hid/hidapi/AUTHORS.txt → vendor/github.com/karalabe/usb/hidapi/AUTHORS.txt


+ 0 - 0
vendor/github.com/karalabe/hid/hidapi/LICENSE-bsd.txt → vendor/github.com/karalabe/usb/hidapi/LICENSE-bsd.txt


+ 0 - 0
vendor/github.com/karalabe/hid/hidapi/LICENSE-gpl3.txt → vendor/github.com/karalabe/usb/hidapi/LICENSE-gpl3.txt


+ 0 - 0
vendor/github.com/karalabe/hid/hidapi/LICENSE-orig.txt → vendor/github.com/karalabe/usb/hidapi/LICENSE-orig.txt


+ 0 - 0
vendor/github.com/karalabe/hid/hidapi/LICENSE.txt → vendor/github.com/karalabe/usb/hidapi/LICENSE.txt


+ 0 - 0
vendor/github.com/karalabe/hid/hidapi/README.txt → vendor/github.com/karalabe/usb/hidapi/README.txt


+ 0 - 0
vendor/github.com/karalabe/hid/hidapi/hidapi/hidapi.h → vendor/github.com/karalabe/usb/hidapi/hidapi/hidapi.h


+ 0 - 0
vendor/github.com/karalabe/hid/hidapi/libusb/hid.c → vendor/github.com/karalabe/usb/hidapi/libusb/hid.c


+ 0 - 0
vendor/github.com/karalabe/hid/hidapi/mac/hid.c → vendor/github.com/karalabe/usb/hidapi/mac/hid.c


+ 0 - 0
vendor/github.com/karalabe/hid/hidapi/windows/hid.c → vendor/github.com/karalabe/usb/hidapi/windows/hid.c


+ 74 - 0
vendor/github.com/karalabe/usb/libs.go

@@ -0,0 +1,74 @@
+// usb - Self contained USB and HID library for Go
+// Copyright 2019 The library Authors
+//
+// This library is free software: you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation, either version 3 of the License, or (at your option) any
+// later version.
+//
+// The library is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+// A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along
+// with the library. If not, see <http://www.gnu.org/licenses/>.
+
+// +build freebsd,cgo linux,cgo darwin,!ios,cgo windows,cgo
+
+package usb
+
+/*
+#cgo CFLAGS: -I./hidapi/hidapi
+#cgo CFLAGS: -I./libusb/libusb
+#cgo CFLAGS: -DDEFAULT_VISIBILITY=""
+#cgo CFLAGS: -DPOLL_NFDS_TYPE=int
+
+#cgo linux CFLAGS: -DOS_LINUX -D_GNU_SOURCE
+#cgo linux,!android LDFLAGS: -lrt
+#cgo darwin CFLAGS: -DOS_DARWIN -DHAVE_SYS_TIME_H
+#cgo darwin LDFLAGS: -framework CoreFoundation -framework IOKit -lobjc
+#cgo windows CFLAGS: -DOS_WINDOWS
+#cgo windows LDFLAGS: -lsetupapi
+#cgo freebsd CFLAGS: -DOS_FREEBSD
+#cgo freebsd LDFLAGS: -lusb
+#cgo openbsd CFLAGS: -DOS_OPENBSD
+
+#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(DOS_FREEBSD) || defined(OS_OPENBSD)
+	#include <poll.h>
+	#include "os/threads_posix.c"
+	#include "os/poll_posix.c"
+#elif defined(OS_WINDOWS)
+	#include "os/poll_windows.c"
+	#include "os/threads_windows.c"
+#endif
+
+#ifdef OS_LINUX
+	#include "os/linux_usbfs.c"
+	#include "os/linux_netlink.c"
+	#include "hidapi/libusb/hid.c"
+#elif OS_DARWIN
+	#include "os/darwin_usb.c"
+	#include "hidapi/mac/hid.c"
+#elif OS_WINDOWS
+	#include "os/windows_nt_common.c"
+	#include "os/windows_usbdk.c"
+	#include "os/windows_winusb.c"
+	#include "hidapi/windows/hid.c"
+#elif OS_FREEBSD
+	#include <libusb.h>
+	#include "hidapi/libusb/hid.c"
+#elif DOS_OPENBSD
+	#include "os/openbsd_usb.c"
+	#include "hidapi/libusb/hid.c"
+#endif
+
+#ifndef OS_FREEBSD
+	#include "core.c"
+	#include "descriptor.c"
+	#include "hotplug.c"
+	#include "io.c"
+	#include "strerror.c"
+	#include "sync.c"
+#endif
+*/
+import "C"

+ 32 - 2
vendor/github.com/karalabe/hid/libusb/AUTHORS → vendor/github.com/karalabe/usb/libusb/AUTHORS

@@ -8,14 +8,19 @@ Copyright © 2010-2012 Michael Plante <michael.plante@gmail.com>
 Copyright © 2011-2013 Hans de Goede <hdegoede@redhat.com>
 Copyright © 2012-2013 Martin Pieuchot <mpi@openbsd.org>
 Copyright © 2012-2013 Toby Gray <toby.gray@realvnc.com>
-Copyright © 2013-2015 Chris Dickens <christopher.a.dickens@gmail.com>
+Copyright © 2013-2018 Chris Dickens <christopher.a.dickens@gmail.com>
 
 Other contributors:
+Adrian Bunk
 Akshay Jaggi
 Alan Ott
 Alan Stern
 Alex Vatchenko
 Andrew Fernandes
+Andy Chunyu
+Andy McFadden
+Angus Gratton
+Anil Nair
 Anthony Clay
 Antonio Ospite
 Artem Egorkine
@@ -23,12 +28,17 @@ Aurelien Jarno
 Bastien Nocera
 Bei Zhang
 Benjamin Dobell
+Brent Rector
 Carl Karsten
+Christophe Zeitouny
 Colin Walters
 Dave Camarillo
 David Engraf
 David Moore
 Davidlohr Bueso
+Dmitry Fleytman
+Doug Johnston
+Evan Hunter
 Federico Manzan
 Felipe Balbi
 Florian Albrechtskirchinger
@@ -41,23 +51,34 @@ Hans Ulrich Niedermann
 Hector Martin
 Hoi-Ho Chan
 Ilya Konstantinov
+Jakub Klama
 James Hanko
+Jeffrey Nichols
+Johann Richard
 John Sheu
+Jonathon Jongsma
+Joost Muller
+Josh Gao
 Joshua Blake
 Justin Bischoff
+KIMURA Masaru
 Karsten Koenig
 Konrad Rzepecki
 Kuangye Guo
 Lars Kanis
 Lars Wirzenius
+Lei Chen
 Luca Longinotti
 Marcus Meissner
 Markus Heidelberg
 Martin Ettl
 Martin Koegler
+Matthew Stapleton
 Matthias Bolte
+Michel Zou
 Mike Frysinger
 Mikhail Gusarov
+Morgan Leborgne
 Moritz Fischer
 Ларионов Даниил
 Nicholas Corgan
@@ -66,10 +87,17 @@ Orin Eman
 Paul Fertser
 Pekka Nikander
 Rob Walker
+Romain Vimont
+Roman Kalashnikov
+Sameeh Jubran
 Sean McBride
 Sebastian Pipping
+Sergey Serb
 Simon Haggett
 Simon Newton
+Stefan Agner
+Stefan Tauner
+Steinar H. Gunderson
 Thomas Röfer
 Tim Hutt
 Tim Roberts
@@ -81,9 +109,11 @@ Uri Lublin
 Vasily Khoruzhick
 Vegard Storheil Eriksen
 Venkatesh Shukla
+Vianney le Clément de Saint-Marcq
+Victor Toso
 Vitali Lovich
+William Skellenger
 Xiaofan Chen
 Zoltán Kovács
 Роман Донченко
 parafin
-xantares

+ 0 - 0
vendor/github.com/karalabe/hid/libusb/COPYING → vendor/github.com/karalabe/usb/libusb/COPYING


+ 0 - 0
vendor/github.com/karalabe/hid/libusb/libusb/config.h → vendor/github.com/karalabe/usb/libusb/libusb/config.h


+ 201 - 145
vendor/github.com/karalabe/hid/libusb/libusb/core.c → vendor/github.com/karalabe/usb/libusb/libusb/core.c

@@ -44,32 +44,6 @@
 #include "libusbi.h"
 #include "hotplug.h"
 
-#if defined(OS_LINUX)
-const struct usbi_os_backend * const usbi_backend = &linux_usbfs_backend;
-#elif defined(OS_DARWIN)
-const struct usbi_os_backend * const usbi_backend = &darwin_backend;
-#elif defined(OS_OPENBSD)
-const struct usbi_os_backend * const usbi_backend = &openbsd_backend;
-#elif defined(OS_NETBSD)
-const struct usbi_os_backend * const usbi_backend = &netbsd_backend;
-#elif defined(OS_WINDOWS)
-
-#if defined(USE_USBDK)
-const struct usbi_os_backend * const usbi_backend = &usbdk_backend;
-#else
-const struct usbi_os_backend * const usbi_backend = &windows_backend;
-#endif
-
-#elif defined(OS_WINCE)
-const struct usbi_os_backend * const usbi_backend = &wince_backend;
-#elif defined(OS_HAIKU)
-const struct usbi_os_backend * const usbi_backend = &haiku_usb_raw_backend;
-#elif defined (OS_SUNOS)
-const struct usbi_os_backend * const usbi_backend = &sunos_backend;
-#else
-#error "Unsupported OS"
-#endif
-
 struct libusb_context *usbi_default_context = NULL;
 static const struct libusb_version libusb_version_internal =
 	{ LIBUSB_MAJOR, LIBUSB_MINOR, LIBUSB_MICRO, LIBUSB_NANO,
@@ -142,15 +116,17 @@ struct list_head active_contexts_list;
  * libusb uses stderr for all logging. By default, logging is set to NONE,
  * which means that no output will be produced. However, unless the library
  * has been compiled with logging disabled, then any application calls to
- * libusb_set_debug(), or the setting of the environmental variable
- * LIBUSB_DEBUG outside of the application, can result in logging being
- * produced. Your application should therefore not close stderr, but instead
- * direct it to the null device if its output is undesirable.
- *
- * The libusb_set_debug() function can be used to enable logging of certain
- * messages. Under standard configuration, libusb doesn't really log much
- * so you are advised to use this function to enable all error/warning/
- * informational messages. It will help debug problems with your software.
+ * libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level), or the setting of the
+ * environmental variable LIBUSB_DEBUG outside of the application, can result
+ * in logging being produced. Your application should therefore not close
+ * stderr, but instead direct it to the null device if its output is
+ * undesirable.
+ *
+ * The libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) function can be
+ * used to enable logging of certain messages. Under standard configuration,
+ * libusb doesn't really log much so you are advised to use this function
+ * to enable all error/warning/ informational messages. It will help debug
+ * problems with your software.
  *
  * The logged messages are unstructured. There is no one-to-one correspondence
  * between messages being logged and success or failure return codes from
@@ -165,18 +141,20 @@ struct list_head active_contexts_list;
  *
  * The LIBUSB_DEBUG environment variable can be used to enable message logging
  * at run-time. This environment variable should be set to a log level number,
- * which is interpreted the same as the libusb_set_debug() parameter. When this
+ * which is interpreted the same as the
+ * libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) parameter. When this
  * environment variable is set, the message logging verbosity level is fixed
- * and libusb_set_debug() effectively does nothing.
+ * and libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) effectively does
+ * nothing.
  *
  * libusb can be compiled without any logging functions, useful for embedded
- * systems. In this case, libusb_set_debug() and the LIBUSB_DEBUG environment
- * variable have no effects.
+ * systems. In this case, libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level)
+ * and the LIBUSB_DEBUG environment variable have no effects.
  *
  * libusb can also be compiled with verbose debugging messages always. When
  * the library is compiled in this way, all messages of all verbosities are
- * always logged. libusb_set_debug() and the LIBUSB_DEBUG environment variable
- * have no effects.
+ * always logged. libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) and
+ * the LIBUSB_DEBUG environment variable have no effects.
  *
  * \section remarks Other remarks
  *
@@ -187,6 +165,20 @@ struct list_head active_contexts_list;
 /**
  * \page libusb_caveats Caveats
  *
+ * \section fork Fork considerations
+ *
+ * libusb is <em>not</em> designed to work across fork() calls. Depending on
+ * the platform, there may be resources in the parent process that are not
+ * available to the child (e.g. the hotplug monitor thread on Linux). In
+ * addition, since the parent and child will share libusb's internal file
+ * descriptors, using libusb in any way from the child could cause the parent
+ * process's \ref libusb_context to get into an inconsistent state.
+ *
+ * On Linux, libusb's file descriptors will be marked as CLOEXEC, which means
+ * that it is safe to fork() and exec() without worrying about the child
+ * process needing to clean up state or having access to these file descriptors.
+ * Other platforms may not be so forgiving, so consider yourself warned!
+ *
  * \section devresets Device resets
  *
  * The libusb_reset_device() function allows you to reset a device. If your
@@ -291,7 +283,6 @@ if (cfg != desired)
  * information about the end of the short packet, and the user probably wanted
  * that surplus data to arrive in the next logical transfer.
  *
- *
  * \section zlp Zero length packets
  *
  * - libusb is able to send a packet of zero length to an endpoint simply by
@@ -310,7 +301,7 @@ if (cfg != desired)
  * developed modules may both use libusb.
  *
  * libusb is written to allow for these multiple user scenarios. The two
- * "instances" of libusb will not interfere: libusb_set_debug() calls
+ * "instances" of libusb will not interfere: libusb_set_option() calls
  * from one user will not affect the same settings for other users, other
  * users can continue using libusb after one of them calls libusb_exit(), etc.
  *
@@ -435,6 +426,7 @@ if (cfg != desired)
   * - libusb_set_debug()
   * - libusb_set_interface_alt_setting()
   * - libusb_set_iso_packet_lengths()
+  * - libusb_set_option()
   * - libusb_setlocale()
   * - libusb_set_pollfd_notifiers()
   * - libusb_strerror()
@@ -478,6 +470,7 @@ if (cfg != desired)
   * - \ref libusb_iso_sync_type
   * - \ref libusb_iso_usage_type
   * - \ref libusb_log_level
+  * - \ref libusb_option
   * - \ref libusb_request_recipient
   * - \ref libusb_request_type
   * - \ref libusb_speed
@@ -680,7 +673,7 @@ struct discovered_devs *discovered_devs_append(
 struct libusb_device *usbi_alloc_device(struct libusb_context *ctx,
 	unsigned long session_id)
 {
-	size_t priv_size = usbi_backend->device_priv_size;
+	size_t priv_size = usbi_backend.device_priv_size;
 	struct libusb_device *dev = calloc(1, sizeof(*dev) + priv_size);
 	int r;
 
@@ -824,8 +817,8 @@ ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx,
 		/* backend provides hotplug support */
 		struct libusb_device *dev;
 
-		if (usbi_backend->hotplug_poll)
-			usbi_backend->hotplug_poll();
+		if (usbi_backend.hotplug_poll)
+			usbi_backend.hotplug_poll();
 
 		usbi_mutex_lock(&ctx->usb_devs_lock);
 		list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) {
@@ -839,7 +832,7 @@ ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx,
 		usbi_mutex_unlock(&ctx->usb_devs_lock);
 	} else {
 		/* backend does not provide hotplug support */
-		r = usbi_backend->get_device_list(ctx, &discdevs);
+		r = usbi_backend.get_device_list(ctx, &discdevs);
 	}
 
 	if (r < 0) {
@@ -1167,8 +1160,8 @@ void API_EXPORTED libusb_unref_device(libusb_device *dev)
 
 		libusb_unref_device(dev->parent_dev);
 
-		if (usbi_backend->destroy_device)
-			usbi_backend->destroy_device(dev);
+		if (usbi_backend.destroy_device)
+			usbi_backend.destroy_device(dev);
 
 		if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
 			/* backend does not support hotplug */
@@ -1242,7 +1235,7 @@ int API_EXPORTED libusb_open(libusb_device *dev,
 {
 	struct libusb_context *ctx = DEVICE_CTX(dev);
 	struct libusb_device_handle *_dev_handle;
-	size_t priv_size = usbi_backend->device_handle_priv_size;
+	size_t priv_size = usbi_backend.device_handle_priv_size;
 	int r;
 	usbi_dbg("open %d.%d", dev->bus_number, dev->device_address);
 
@@ -1265,7 +1258,7 @@ int API_EXPORTED libusb_open(libusb_device *dev,
 	_dev_handle->claimed_interfaces = 0;
 	memset(&_dev_handle->os_priv, 0, priv_size);
 
-	r = usbi_backend->open(_dev_handle);
+	r = usbi_backend.open(_dev_handle);
 	if (r < 0) {
 		usbi_dbg("open %d.%d returns %d", dev->bus_number, dev->device_address, r);
 		libusb_unref_device(dev);
@@ -1382,7 +1375,7 @@ static void do_close(struct libusb_context *ctx,
 	list_del(&dev_handle->list);
 	usbi_mutex_unlock(&ctx->open_devs_lock);
 
-	usbi_backend->close(dev_handle);
+	usbi_backend.close(dev_handle);
 	libusb_unref_device(dev_handle->dev);
 	usbi_mutex_destroy(&dev_handle->lock);
 	free(dev_handle);
@@ -1491,8 +1484,8 @@ int API_EXPORTED libusb_get_configuration(libusb_device_handle *dev_handle,
 	int r = LIBUSB_ERROR_NOT_SUPPORTED;
 
 	usbi_dbg("");
-	if (usbi_backend->get_configuration)
-		r = usbi_backend->get_configuration(dev_handle, config);
+	if (usbi_backend.get_configuration)
+		r = usbi_backend.get_configuration(dev_handle, config);
 
 	if (r == LIBUSB_ERROR_NOT_SUPPORTED) {
 		uint8_t tmp = 0;
@@ -1567,7 +1560,7 @@ int API_EXPORTED libusb_set_configuration(libusb_device_handle *dev_handle,
 	int configuration)
 {
 	usbi_dbg("configuration %d", configuration);
-	return usbi_backend->set_configuration(dev_handle, configuration);
+	return usbi_backend.set_configuration(dev_handle, configuration);
 }
 
 /** \ingroup libusb_dev
@@ -1614,7 +1607,7 @@ int API_EXPORTED libusb_claim_interface(libusb_device_handle *dev_handle,
 	if (dev_handle->claimed_interfaces & (1 << interface_number))
 		goto out;
 
-	r = usbi_backend->claim_interface(dev_handle, interface_number);
+	r = usbi_backend.claim_interface(dev_handle, interface_number);
 	if (r == 0)
 		dev_handle->claimed_interfaces |= 1 << interface_number;
 
@@ -1657,7 +1650,7 @@ int API_EXPORTED libusb_release_interface(libusb_device_handle *dev_handle,
 		goto out;
 	}
 
-	r = usbi_backend->release_interface(dev_handle, interface_number);
+	r = usbi_backend.release_interface(dev_handle, interface_number);
 	if (r == 0)
 		dev_handle->claimed_interfaces &= ~(1 << interface_number);
 
@@ -1707,7 +1700,7 @@ int API_EXPORTED libusb_set_interface_alt_setting(libusb_device_handle *dev_hand
 	}
 	usbi_mutex_unlock(&dev_handle->lock);
 
-	return usbi_backend->set_interface_altsetting(dev_handle, interface_number,
+	return usbi_backend.set_interface_altsetting(dev_handle, interface_number,
 		alternate_setting);
 }
 
@@ -1734,7 +1727,7 @@ int API_EXPORTED libusb_clear_halt(libusb_device_handle *dev_handle,
 	if (!dev_handle->dev->attached)
 		return LIBUSB_ERROR_NO_DEVICE;
 
-	return usbi_backend->clear_halt(dev_handle, endpoint);
+	return usbi_backend.clear_halt(dev_handle, endpoint);
 }
 
 /** \ingroup libusb_dev
@@ -1762,7 +1755,7 @@ int API_EXPORTED libusb_reset_device(libusb_device_handle *dev_handle)
 	if (!dev_handle->dev->attached)
 		return LIBUSB_ERROR_NO_DEVICE;
 
-	return usbi_backend->reset_device(dev_handle);
+	return usbi_backend.reset_device(dev_handle);
 }
 
 /** \ingroup libusb_asyncio
@@ -1794,8 +1787,8 @@ int API_EXPORTED libusb_alloc_streams(libusb_device_handle *dev_handle,
 	if (!dev_handle->dev->attached)
 		return LIBUSB_ERROR_NO_DEVICE;
 
-	if (usbi_backend->alloc_streams)
-		return usbi_backend->alloc_streams(dev_handle, num_streams, endpoints,
+	if (usbi_backend.alloc_streams)
+		return usbi_backend.alloc_streams(dev_handle, num_streams, endpoints,
 						   num_endpoints);
 	else
 		return LIBUSB_ERROR_NOT_SUPPORTED;
@@ -1821,8 +1814,8 @@ int API_EXPORTED libusb_free_streams(libusb_device_handle *dev_handle,
 	if (!dev_handle->dev->attached)
 		return LIBUSB_ERROR_NO_DEVICE;
 
-	if (usbi_backend->free_streams)
-		return usbi_backend->free_streams(dev_handle, endpoints,
+	if (usbi_backend.free_streams)
+		return usbi_backend.free_streams(dev_handle, endpoints,
 						  num_endpoints);
 	else
 		return LIBUSB_ERROR_NOT_SUPPORTED;
@@ -1859,8 +1852,8 @@ unsigned char * LIBUSB_CALL libusb_dev_mem_alloc(libusb_device_handle *dev_handl
 	if (!dev_handle->dev->attached)
 		return NULL;
 
-	if (usbi_backend->dev_mem_alloc)
-		return usbi_backend->dev_mem_alloc(dev_handle, length);
+	if (usbi_backend.dev_mem_alloc)
+		return usbi_backend.dev_mem_alloc(dev_handle, length);
 	else
 		return NULL;
 }
@@ -1876,8 +1869,8 @@ unsigned char * LIBUSB_CALL libusb_dev_mem_alloc(libusb_device_handle *dev_handl
 int API_EXPORTED libusb_dev_mem_free(libusb_device_handle *dev_handle,
 	unsigned char *buffer, size_t length)
 {
-	if (usbi_backend->dev_mem_free)
-		return usbi_backend->dev_mem_free(dev_handle, buffer, length);
+	if (usbi_backend.dev_mem_free)
+		return usbi_backend.dev_mem_free(dev_handle, buffer, length);
 	else
 		return LIBUSB_ERROR_NOT_SUPPORTED;
 }
@@ -1907,8 +1900,8 @@ int API_EXPORTED libusb_kernel_driver_active(libusb_device_handle *dev_handle,
 	if (!dev_handle->dev->attached)
 		return LIBUSB_ERROR_NO_DEVICE;
 
-	if (usbi_backend->kernel_driver_active)
-		return usbi_backend->kernel_driver_active(dev_handle, interface_number);
+	if (usbi_backend.kernel_driver_active)
+		return usbi_backend.kernel_driver_active(dev_handle, interface_number);
 	else
 		return LIBUSB_ERROR_NOT_SUPPORTED;
 }
@@ -1942,8 +1935,8 @@ int API_EXPORTED libusb_detach_kernel_driver(libusb_device_handle *dev_handle,
 	if (!dev_handle->dev->attached)
 		return LIBUSB_ERROR_NO_DEVICE;
 
-	if (usbi_backend->detach_kernel_driver)
-		return usbi_backend->detach_kernel_driver(dev_handle, interface_number);
+	if (usbi_backend.detach_kernel_driver)
+		return usbi_backend.detach_kernel_driver(dev_handle, interface_number);
 	else
 		return LIBUSB_ERROR_NOT_SUPPORTED;
 }
@@ -1976,8 +1969,8 @@ int API_EXPORTED libusb_attach_kernel_driver(libusb_device_handle *dev_handle,
 	if (!dev_handle->dev->attached)
 		return LIBUSB_ERROR_NO_DEVICE;
 
-	if (usbi_backend->attach_kernel_driver)
-		return usbi_backend->attach_kernel_driver(dev_handle, interface_number);
+	if (usbi_backend.attach_kernel_driver)
+		return usbi_backend.attach_kernel_driver(dev_handle, interface_number);
 	else
 		return LIBUSB_ERROR_NOT_SUPPORTED;
 }
@@ -2007,7 +2000,7 @@ int API_EXPORTED libusb_attach_kernel_driver(libusb_device_handle *dev_handle,
 int API_EXPORTED libusb_set_auto_detach_kernel_driver(
 	libusb_device_handle *dev_handle, int enable)
 {
-	if (!(usbi_backend->caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER))
+	if (!(usbi_backend.caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER))
 		return LIBUSB_ERROR_NOT_SUPPORTED;
 
 	dev_handle->auto_detach_kernel_driver = enable;
@@ -2015,37 +2008,100 @@ int API_EXPORTED libusb_set_auto_detach_kernel_driver(
 }
 
 /** \ingroup libusb_lib
- * Set log message verbosity.
- *
- * The default level is LIBUSB_LOG_LEVEL_NONE, which means no messages are ever
- * printed. If you choose to increase the message verbosity level, ensure
- * that your application does not close the stdout/stderr file descriptors.
+ * \deprecated Use libusb_set_option() instead using the
+ * \ref LIBUSB_OPTION_LOG_LEVEL option.
+ */
+void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level)
+{
+#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
+	USBI_GET_CONTEXT(ctx);
+	if (!ctx->debug_fixed) {
+		level = CLAMP(level, LIBUSB_LOG_LEVEL_NONE, LIBUSB_LOG_LEVEL_DEBUG);
+		ctx->debug = (enum libusb_log_level)level;
+	}
+#else
+	UNUSED(ctx);
+	UNUSED(level);
+#endif
+}
+
+/** \ingroup libusb_lib
+ * Set an option in the library.
  *
- * You are advised to use level LIBUSB_LOG_LEVEL_WARNING. libusb is conservative
- * with its message logging and most of the time, will only log messages that
- * explain error conditions and other oddities. This will help you debug
- * your software.
+ * Use this function to configure a specific option within the library.
  *
- * If the LIBUSB_DEBUG environment variable was set when libusb was
- * initialized, this function does nothing: the message verbosity is fixed
- * to the value in the environment variable.
+ * Some options require one or more arguments to be provided. Consult each
+ * option's documentation for specific requirements.
  *
- * If libusb was compiled without any message logging, this function does
- * nothing: you'll never get any messages.
+ * Since version 1.0.22, \ref LIBUSB_API_VERSION >= 0x01000106
  *
- * If libusb was compiled with verbose debug message logging, this function
- * does nothing: you'll always get messages from all levels.
+ * \param ctx context on which to operate
+ * \param option which option to set
+ * \param ... any required arguments for the specified option
  *
- * \param ctx the context to operate on, or NULL for the default context
- * \param level debug level to set
+ * \returns LIBUSB_SUCCESS on success
+ * \returns LIBUSB_ERROR_INVALID_PARAM if the option or arguments are invalid
+ * \returns LIBUSB_ERROR_NOT_SUPPORTED if the option is valid but not supported
+ * on this platform
  */
-void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level)
+int API_EXPORTED libusb_set_option(libusb_context *ctx,
+	enum libusb_option option, ...)
 {
+	int arg, r = LIBUSB_SUCCESS;
+	va_list ap;
+
 	USBI_GET_CONTEXT(ctx);
-	if (!ctx->debug_fixed)
-		ctx->debug = level;
+
+	va_start(ap, option);
+	switch (option) {
+	case LIBUSB_OPTION_LOG_LEVEL:
+		arg = va_arg(ap, int);
+		if (arg < LIBUSB_LOG_LEVEL_NONE || arg > LIBUSB_LOG_LEVEL_DEBUG) {
+			r = LIBUSB_ERROR_INVALID_PARAM;
+			break;
+		}
+#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
+		if (!ctx->debug_fixed)
+			ctx->debug = (enum libusb_log_level)arg;
+#endif
+		break;
+
+	/* Handle all backend-specific options here */
+	case LIBUSB_OPTION_USE_USBDK:
+		if (usbi_backend.set_option)
+			r = usbi_backend.set_option(ctx, option, ap);
+		else
+			r = LIBUSB_ERROR_NOT_SUPPORTED;
+		break;
+
+	default:
+		r = LIBUSB_ERROR_INVALID_PARAM;
+	}
+	va_end(ap);
+
+	return r;
 }
 
+#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
+/* returns the log level as defined in the LIBUSB_DEBUG environment variable.
+ * if LIBUSB_DEBUG is not present or not a number, returns LIBUSB_LOG_LEVEL_NONE.
+ * value is clamped to ensure it is within the valid range of possibilities.
+ */
+static enum libusb_log_level get_env_debug_level(void)
+{
+	const char *dbg = getenv("LIBUSB_DEBUG");
+	enum libusb_log_level level;
+	if (dbg) {
+		int dbg_level = atoi(dbg);
+		dbg_level = CLAMP(dbg_level, LIBUSB_LOG_LEVEL_NONE, LIBUSB_LOG_LEVEL_DEBUG);
+		level = (enum libusb_log_level)dbg_level;
+	} else {
+		level = LIBUSB_LOG_LEVEL_NONE;
+	}
+	return level;
+}
+#endif
+
 /** \ingroup libusb_lib
  * Initialize libusb. This function must be called before calling any other
  * libusb function.
@@ -2062,7 +2118,7 @@ void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level)
 int API_EXPORTED libusb_init(libusb_context **context)
 {
 	struct libusb_device *dev, *next;
-	char *dbg = getenv("LIBUSB_DEBUG");
+	size_t priv_size = usbi_backend.context_priv_size;
 	struct libusb_context *ctx;
 	static int first_init = 1;
 	int r = 0;
@@ -2070,7 +2126,7 @@ int API_EXPORTED libusb_init(libusb_context **context)
 	usbi_mutex_static_lock(&default_context_lock);
 
 	if (!timestamp_origin.tv_sec) {
-		usbi_backend->clock_gettime(USBI_CLOCK_REALTIME, &timestamp_origin);
+		usbi_backend.clock_gettime(USBI_CLOCK_REALTIME, &timestamp_origin);
 	}
 
 	if (!context && usbi_default_context) {
@@ -2080,22 +2136,18 @@ int API_EXPORTED libusb_init(libusb_context **context)
 		return 0;
 	}
 
-	ctx = calloc(1, sizeof(*ctx));
+	ctx = calloc(1, sizeof(*ctx) + priv_size);
 	if (!ctx) {
 		r = LIBUSB_ERROR_NO_MEM;
 		goto err_unlock;
 	}
 
-#ifdef ENABLE_DEBUG_LOGGING
-	ctx->debug = LIBUSB_LOG_LEVEL_DEBUG;
+#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
+	ctx->debug = get_env_debug_level();
+	if (ctx->debug != LIBUSB_LOG_LEVEL_NONE)
+		ctx->debug_fixed = 1;
 #endif
 
-	if (dbg) {
-		ctx->debug = atoi(dbg);
-		if (ctx->debug)
-			ctx->debug_fixed = 1;
-	}
-
 	/* default context should be initialized before calling usbi_dbg */
 	if (!usbi_default_context) {
 		usbi_default_context = ctx;
@@ -2112,6 +2164,7 @@ int API_EXPORTED libusb_init(libusb_context **context)
 	list_init(&ctx->usb_devs);
 	list_init(&ctx->open_devs);
 	list_init(&ctx->hotplug_cbs);
+	ctx->next_hotplug_cb_handle = 1;
 
 	usbi_mutex_static_lock(&active_contexts_lock);
 	if (first_init) {
@@ -2121,8 +2174,8 @@ int API_EXPORTED libusb_init(libusb_context **context)
 	list_add (&ctx->list, &active_contexts_list);
 	usbi_mutex_static_unlock(&active_contexts_lock);
 
-	if (usbi_backend->init) {
-		r = usbi_backend->init(ctx);
+	if (usbi_backend.init) {
+		r = usbi_backend.init(ctx);
 		if (r)
 			goto err_free_ctx;
 	}
@@ -2139,8 +2192,8 @@ int API_EXPORTED libusb_init(libusb_context **context)
 	return 0;
 
 err_backend_exit:
-	if (usbi_backend->exit)
-		usbi_backend->exit();
+	if (usbi_backend.exit)
+		usbi_backend.exit(ctx);
 err_free_ctx:
 	if (ctx == usbi_default_context) {
 		usbi_default_context = NULL;
@@ -2200,7 +2253,7 @@ void API_EXPORTED libusb_exit(struct libusb_context *ctx)
 	usbi_mutex_static_unlock(&active_contexts_lock);
 
 	if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
-		usbi_hotplug_deregister_all(ctx);
+		usbi_hotplug_deregister(ctx, 1);
 
 		/*
 		 * Ensure any pending unplug events are read from the hotplug
@@ -2230,8 +2283,8 @@ void API_EXPORTED libusb_exit(struct libusb_context *ctx)
 		usbi_warn(ctx, "application left some devices open");
 
 	usbi_io_exit(ctx);
-	if (usbi_backend->exit)
-		usbi_backend->exit();
+	if (usbi_backend.exit)
+		usbi_backend.exit(ctx);
 
 	usbi_mutex_destroy(&ctx->open_devs_lock);
 	usbi_mutex_destroy(&ctx->usb_devs_lock);
@@ -2253,15 +2306,17 @@ int API_EXPORTED libusb_has_capability(uint32_t capability)
 	case LIBUSB_CAP_HAS_CAPABILITY:
 		return 1;
 	case LIBUSB_CAP_HAS_HOTPLUG:
-		return !(usbi_backend->get_device_list);
+		return !(usbi_backend.get_device_list);
 	case LIBUSB_CAP_HAS_HID_ACCESS:
-		return (usbi_backend->caps & USBI_CAP_HAS_HID_ACCESS);
+		return (usbi_backend.caps & USBI_CAP_HAS_HID_ACCESS);
 	case LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER:
-		return (usbi_backend->caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER);
+		return (usbi_backend.caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER);
 	}
 	return 0;
 }
 
+#ifdef ENABLE_LOGGING
+
 /* this is defined in libusbi.h if needed */
 #ifdef LIBUSB_PRINTF_WIN32
 /*
@@ -2301,10 +2356,9 @@ int usbi_vsnprintf(char *str, size_t size, const char *format, va_list ap)
 
 	return ret;
 }
-#endif
+#endif /* LIBUSB_PRINTF_WIN32 */
 
-static void usbi_log_str(struct libusb_context *ctx,
-	enum libusb_log_level level, const char * str)
+static void usbi_log_str(enum libusb_log_level level, const char *str)
 {
 #if defined(USE_SYSTEM_LOGGING_FACILITY)
 #if defined(OS_WINDOWS)
@@ -2317,18 +2371,20 @@ static void usbi_log_str(struct libusb_context *ctx,
 #elif defined(__ANDROID__)
 	int priority = ANDROID_LOG_UNKNOWN;
 	switch (level) {
-	case LIBUSB_LOG_LEVEL_INFO: priority = ANDROID_LOG_INFO; break;
-	case LIBUSB_LOG_LEVEL_WARNING: priority = ANDROID_LOG_WARN; break;
+	case LIBUSB_LOG_LEVEL_NONE: return;
 	case LIBUSB_LOG_LEVEL_ERROR: priority = ANDROID_LOG_ERROR; break;
+	case LIBUSB_LOG_LEVEL_WARNING: priority = ANDROID_LOG_WARN; break;
+	case LIBUSB_LOG_LEVEL_INFO: priority = ANDROID_LOG_INFO; break;
 	case LIBUSB_LOG_LEVEL_DEBUG: priority = ANDROID_LOG_DEBUG; break;
 	}
 	__android_log_write(priority, "libusb", str);
 #elif defined(HAVE_SYSLOG_FUNC)
 	int syslog_level = LOG_INFO;
 	switch (level) {
-	case LIBUSB_LOG_LEVEL_INFO: syslog_level = LOG_INFO; break;
-	case LIBUSB_LOG_LEVEL_WARNING: syslog_level = LOG_WARNING; break;
+	case LIBUSB_LOG_LEVEL_NONE: return;
 	case LIBUSB_LOG_LEVEL_ERROR: syslog_level = LOG_ERR; break;
+	case LIBUSB_LOG_LEVEL_WARNING: syslog_level = LOG_WARNING; break;
+	case LIBUSB_LOG_LEVEL_INFO: syslog_level = LOG_INFO; break;
 	case LIBUSB_LOG_LEVEL_DEBUG: syslog_level = LOG_DEBUG; break;
 	}
 	syslog(syslog_level, "%s", str);
@@ -2339,14 +2395,13 @@ static void usbi_log_str(struct libusb_context *ctx,
 #else
 	fputs(str, stderr);
 #endif /* USE_SYSTEM_LOGGING_FACILITY */
-	UNUSED(ctx);
 	UNUSED(level);
 }
 
 void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level,
 	const char *function, const char *format, va_list args)
 {
-	const char *prefix = "";
+	const char *prefix;
 	char buf[USBI_MAX_LOG_LEN];
 	struct timespec now;
 	int global_debug, header_len, text_len;
@@ -2356,18 +2411,15 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level,
 	global_debug = 1;
 	UNUSED(ctx);
 #else
-	int ctx_level = 0;
+	enum libusb_log_level ctx_level = LIBUSB_LOG_LEVEL_NONE;
 
 	USBI_GET_CONTEXT(ctx);
-	if (ctx) {
+	if (ctx)
 		ctx_level = ctx->debug;
-	} else {
-		char *dbg = getenv("LIBUSB_DEBUG");
-		if (dbg)
-			ctx_level = atoi(dbg);
-	}
-	global_debug = (ctx_level == LIBUSB_LOG_LEVEL_DEBUG);
-	if (!ctx_level)
+	else
+		ctx_level = get_env_debug_level();
+
+	if (ctx_level == LIBUSB_LOG_LEVEL_NONE)
 		return;
 	if (level == LIBUSB_LOG_LEVEL_WARNING && ctx_level < LIBUSB_LOG_LEVEL_WARNING)
 		return;
@@ -2375,13 +2427,15 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level,
 		return;
 	if (level == LIBUSB_LOG_LEVEL_DEBUG && ctx_level < LIBUSB_LOG_LEVEL_DEBUG)
 		return;
+
+	global_debug = (ctx_level == LIBUSB_LOG_LEVEL_DEBUG);
 #endif
 
-	usbi_backend->clock_gettime(USBI_CLOCK_REALTIME, &now);
+	usbi_backend.clock_gettime(USBI_CLOCK_REALTIME, &now);
 	if ((global_debug) && (!has_debug_header_been_displayed)) {
 		has_debug_header_been_displayed = 1;
-		usbi_log_str(ctx, LIBUSB_LOG_LEVEL_DEBUG, "[timestamp] [threadID] facility level [function call] <message>" USBI_LOG_LINE_END);
-		usbi_log_str(ctx, LIBUSB_LOG_LEVEL_DEBUG, "--------------------------------------------------------------------------------" USBI_LOG_LINE_END);
+		usbi_log_str(LIBUSB_LOG_LEVEL_DEBUG, "[timestamp] [threadID] facility level [function call] <message>" USBI_LOG_LINE_END);
+		usbi_log_str(LIBUSB_LOG_LEVEL_DEBUG, "--------------------------------------------------------------------------------" USBI_LOG_LINE_END);
 	}
 	if (now.tv_nsec < timestamp_origin.tv_nsec) {
 		now.tv_sec--;
@@ -2391,20 +2445,20 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level,
 	now.tv_nsec -= timestamp_origin.tv_nsec;
 
 	switch (level) {
-	case LIBUSB_LOG_LEVEL_INFO:
-		prefix = "info";
+	case LIBUSB_LOG_LEVEL_NONE:
+		return;
+	case LIBUSB_LOG_LEVEL_ERROR:
+		prefix = "error";
 		break;
 	case LIBUSB_LOG_LEVEL_WARNING:
 		prefix = "warning";
 		break;
-	case LIBUSB_LOG_LEVEL_ERROR:
-		prefix = "error";
+	case LIBUSB_LOG_LEVEL_INFO:
+		prefix = "info";
 		break;
 	case LIBUSB_LOG_LEVEL_DEBUG:
 		prefix = "debug";
 		break;
-	case LIBUSB_LOG_LEVEL_NONE:
-		return;
 	default:
 		prefix = "unknown";
 		break;
@@ -2439,7 +2493,7 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level,
 	}
 	strcpy(buf + header_len + text_len, USBI_LOG_LINE_END);
 
-	usbi_log_str(ctx, level, buf);
+	usbi_log_str(level, buf);
 }
 
 void usbi_log(struct libusb_context *ctx, enum libusb_log_level level,
@@ -2452,6 +2506,8 @@ void usbi_log(struct libusb_context *ctx, enum libusb_log_level level,
 	va_end (args);
 }
 
+#endif /* ENABLE_LOGGING */
+
 /** \ingroup libusb_misc
  * Returns a constant NULL-terminated string with the ASCII name of a libusb
  * error or transfer status code. The caller must not free() the returned

+ 11 - 10
vendor/github.com/karalabe/hid/libusb/libusb/descriptor.c → vendor/github.com/karalabe/usb/libusb/libusb/descriptor.c

@@ -333,7 +333,7 @@ static int parse_interface(libusb_context *ctx,
 					goto err;
 				if (r == 0) {
 					ifp->bNumEndpoints = (uint8_t)i;
-					break;;
+					break;
 				}
 
 				buffer += r;
@@ -513,7 +513,7 @@ int usbi_device_cache_descriptor(libusb_device *dev)
 {
 	int r, host_endian = 0;
 
-	r = usbi_backend->get_device_descriptor(dev, (unsigned char *) &dev->device_descriptor,
+	r = usbi_backend.get_device_descriptor(dev, (unsigned char *) &dev->device_descriptor,
 						&host_endian);
 	if (r < 0)
 		return r;
@@ -572,7 +572,7 @@ int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev,
 	int host_endian = 0;
 	int r;
 
-	r = usbi_backend->get_active_config_descriptor(dev, tmp,
+	r = usbi_backend.get_active_config_descriptor(dev, tmp,
 		LIBUSB_DT_CONFIG_SIZE, &host_endian);
 	if (r < 0)
 		return r;
@@ -587,7 +587,7 @@ int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev,
 	if (!buf)
 		return LIBUSB_ERROR_NO_MEM;
 
-	r = usbi_backend->get_active_config_descriptor(dev, buf,
+	r = usbi_backend.get_active_config_descriptor(dev, buf,
 		_config.wTotalLength, &host_endian);
 	if (r >= 0)
 		r = raw_desc_to_config(dev->ctx, buf, r, host_endian, config);
@@ -625,7 +625,7 @@ int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev,
 	if (config_index >= dev->num_configurations)
 		return LIBUSB_ERROR_NOT_FOUND;
 
-	r = usbi_backend->get_config_descriptor(dev, config_index, tmp,
+	r = usbi_backend.get_config_descriptor(dev, config_index, tmp,
 		LIBUSB_DT_CONFIG_SIZE, &host_endian);
 	if (r < 0)
 		return r;
@@ -640,7 +640,7 @@ int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev,
 	if (!buf)
 		return LIBUSB_ERROR_NO_MEM;
 
-	r = usbi_backend->get_config_descriptor(dev, config_index, buf,
+	r = usbi_backend.get_config_descriptor(dev, config_index, buf,
 		_config.wTotalLength, &host_endian);
 	if (r >= 0)
 		r = raw_desc_to_config(dev->ctx, buf, r, host_endian, config);
@@ -663,7 +663,7 @@ int usbi_get_config_index_by_value(struct libusb_device *dev,
 	for (i = 0; i < dev->num_configurations; i++) {
 		unsigned char tmp[6];
 		int host_endian;
-		int r = usbi_backend->get_config_descriptor(dev, i, tmp, sizeof(tmp),
+		int r = usbi_backend.get_config_descriptor(dev, i, tmp, sizeof(tmp),
 			&host_endian);
 		if (r < 0) {
 			*idx = -1;
@@ -702,8 +702,8 @@ int API_EXPORTED libusb_get_config_descriptor_by_value(libusb_device *dev,
 	int r, idx, host_endian;
 	unsigned char *buf = NULL;
 
-	if (usbi_backend->get_config_descriptor_by_value) {
-		r = usbi_backend->get_config_descriptor_by_value(dev,
+	if (usbi_backend.get_config_descriptor_by_value) {
+		r = usbi_backend.get_config_descriptor_by_value(dev,
 			bConfigurationValue, &buf, &host_endian);
 		if (r < 0)
 			return r;
@@ -1176,7 +1176,8 @@ int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_ha
 	if (tbuf[0] > r)
 		return LIBUSB_ERROR_IO;
 
-	for (di = 0, si = 2; si < tbuf[0]; si += 2) {
+	di = 0;
+	for (si = 2; si < tbuf[0]; si += 2) {
 		if (di >= (length - 1))
 			break;
 

+ 73 - 50
vendor/github.com/karalabe/hid/libusb/libusb/hotplug.c → vendor/github.com/karalabe/usb/libusb/libusb/hotplug.c

@@ -154,36 +154,30 @@ int main (void) {
 \endcode
  */
 
-static int usbi_hotplug_match_cb (struct libusb_context *ctx,
+static int usbi_hotplug_match_cb(struct libusb_context *ctx,
 	struct libusb_device *dev, libusb_hotplug_event event,
 	struct libusb_hotplug_callback *hotplug_cb)
 {
-	/* Handle lazy deregistration of callback */
-	if (hotplug_cb->needs_free) {
-		/* Free callback */
-		return 1;
-	}
-
-	if (!(hotplug_cb->events & event)) {
+	if (!(hotplug_cb->flags & event)) {
 		return 0;
 	}
 
-	if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->vendor_id &&
+	if ((hotplug_cb->flags & USBI_HOTPLUG_VENDOR_ID_VALID) &&
 	    hotplug_cb->vendor_id != dev->device_descriptor.idVendor) {
 		return 0;
 	}
 
-	if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->product_id &&
+	if ((hotplug_cb->flags & USBI_HOTPLUG_PRODUCT_ID_VALID) &&
 	    hotplug_cb->product_id != dev->device_descriptor.idProduct) {
 		return 0;
 	}
 
-	if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->dev_class &&
+	if ((hotplug_cb->flags & USBI_HOTPLUG_DEV_CLASS_VALID) &&
 	    hotplug_cb->dev_class != dev->device_descriptor.bDeviceClass) {
 		return 0;
 	}
 
-	return hotplug_cb->cb (ctx, dev, event, hotplug_cb->user_data);
+	return hotplug_cb->cb(ctx, dev, event, hotplug_cb->user_data);
 }
 
 void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
@@ -195,8 +189,13 @@ void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
 	usbi_mutex_lock(&ctx->hotplug_cbs_lock);
 
 	list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) {
+		if (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE) {
+			/* process deregistration in usbi_hotplug_deregister() */
+			continue;
+		}
+
 		usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
-		ret = usbi_hotplug_match_cb (ctx, dev, event, hotplug_cb);
+		ret = usbi_hotplug_match_cb(ctx, dev, event, hotplug_cb);
 		usbi_mutex_lock(&ctx->hotplug_cbs_lock);
 
 		if (ret) {
@@ -206,15 +205,13 @@ void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
 	}
 
 	usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
-
-	/* the backend is expected to call the callback for each active transfer */
 }
 
 void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev,
 	libusb_hotplug_event event)
 {
 	int pending_events;
-	libusb_hotplug_message *message = calloc(1, sizeof(*message));
+	struct libusb_hotplug_message *message = calloc(1, sizeof(*message));
 
 	if (!message) {
 		usbi_err(ctx, "error allocating hotplug message");
@@ -240,59 +237,70 @@ int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx,
 	libusb_hotplug_callback_fn cb_fn, void *user_data,
 	libusb_hotplug_callback_handle *callback_handle)
 {
-	libusb_hotplug_callback *new_callback;
-	static int handle_id = 1;
-
-	/* check for hotplug support */
-	if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
-		return LIBUSB_ERROR_NOT_SUPPORTED;
-	}
+	struct libusb_hotplug_callback *new_callback;
 
 	/* check for sane values */
-	if ((LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) ||
+	if ((!events || (~(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) & events)) ||
+	    (flags && (~LIBUSB_HOTPLUG_ENUMERATE & flags)) ||
+	    (LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) ||
 	    (LIBUSB_HOTPLUG_MATCH_ANY != product_id && (~0xffff & product_id)) ||
 	    (LIBUSB_HOTPLUG_MATCH_ANY != dev_class && (~0xff & dev_class)) ||
 	    !cb_fn) {
 		return LIBUSB_ERROR_INVALID_PARAM;
 	}
 
+	/* check for hotplug support */
+	if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
+		return LIBUSB_ERROR_NOT_SUPPORTED;
+	}
+
 	USBI_GET_CONTEXT(ctx);
 
-	new_callback = (libusb_hotplug_callback *)calloc(1, sizeof (*new_callback));
+	new_callback = calloc(1, sizeof(*new_callback));
 	if (!new_callback) {
 		return LIBUSB_ERROR_NO_MEM;
 	}
 
-	new_callback->ctx = ctx;
-	new_callback->vendor_id = vendor_id;
-	new_callback->product_id = product_id;
-	new_callback->dev_class = dev_class;
-	new_callback->flags = flags;
-	new_callback->events = events;
+	new_callback->flags = (uint8_t)events;
+	if (LIBUSB_HOTPLUG_MATCH_ANY != vendor_id) {
+		new_callback->flags |= USBI_HOTPLUG_VENDOR_ID_VALID;
+		new_callback->vendor_id = (uint16_t)vendor_id;
+	}
+	if (LIBUSB_HOTPLUG_MATCH_ANY != product_id) {
+		new_callback->flags |= USBI_HOTPLUG_PRODUCT_ID_VALID;
+		new_callback->product_id = (uint16_t)product_id;
+	}
+	if (LIBUSB_HOTPLUG_MATCH_ANY != dev_class) {
+		new_callback->flags |= USBI_HOTPLUG_DEV_CLASS_VALID;
+		new_callback->dev_class = (uint8_t)dev_class;
+	}
 	new_callback->cb = cb_fn;
 	new_callback->user_data = user_data;
-	new_callback->needs_free = 0;
 
 	usbi_mutex_lock(&ctx->hotplug_cbs_lock);
 
-	/* protect the handle by the context hotplug lock. it doesn't matter if the same handle
-	 * is used for different contexts only that the handle is unique for this context */
-	new_callback->handle = handle_id++;
+	/* protect the handle by the context hotplug lock */
+	new_callback->handle = ctx->next_hotplug_cb_handle++;
+
+	/* handle the unlikely case of overflow */
+	if (ctx->next_hotplug_cb_handle < 0)
+		ctx->next_hotplug_cb_handle = 1;
 
 	list_add(&new_callback->list, &ctx->hotplug_cbs);
 
 	usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
 
+	usbi_dbg("new hotplug cb %p with handle %d", new_callback, new_callback->handle);
 
-	if (flags & LIBUSB_HOTPLUG_ENUMERATE) {
-		int i, len;
+	if ((flags & LIBUSB_HOTPLUG_ENUMERATE) && (events & LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)) {
+		ssize_t i, len;
 		struct libusb_device **devs;
 
-		len = (int) libusb_get_device_list(ctx, &devs);
+		len = libusb_get_device_list(ctx, &devs);
 		if (len < 0) {
 			libusb_hotplug_deregister_callback(ctx,
 							new_callback->handle);
-			return len;
+			return (int)len;
 		}
 
 		for (i = 0; i < len; i++) {
@@ -311,10 +319,11 @@ int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx,
 	return LIBUSB_SUCCESS;
 }
 
-void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx,
+void API_EXPORTED libusb_hotplug_deregister_callback(struct libusb_context *ctx,
 	libusb_hotplug_callback_handle callback_handle)
 {
 	struct libusb_hotplug_callback *hotplug_cb;
+	int deregistered = 0;
 
 	/* check for hotplug support */
 	if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
@@ -323,28 +332,42 @@ void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx
 
 	USBI_GET_CONTEXT(ctx);
 
+	usbi_dbg("deregister hotplug cb %d", callback_handle);
+
 	usbi_mutex_lock(&ctx->hotplug_cbs_lock);
-	list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list,
-			    struct libusb_hotplug_callback) {
+	list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) {
 		if (callback_handle == hotplug_cb->handle) {
 			/* Mark this callback for deregistration */
-			hotplug_cb->needs_free = 1;
+			hotplug_cb->flags |= USBI_HOTPLUG_NEEDS_FREE;
+			deregistered = 1;
 		}
 	}
 	usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
 
-	usbi_hotplug_notification(ctx, NULL, 0);
+	if (deregistered) {
+		int pending_events;
+
+		usbi_mutex_lock(&ctx->event_data_lock);
+		pending_events = usbi_pending_events(ctx);
+		ctx->event_flags |= USBI_EVENT_HOTPLUG_CB_DEREGISTERED;
+		if (!pending_events)
+			usbi_signal_event(ctx);
+		usbi_mutex_unlock(&ctx->event_data_lock);
+	}
 }
 
-void usbi_hotplug_deregister_all(struct libusb_context *ctx) {
+void usbi_hotplug_deregister(struct libusb_context *ctx, int forced)
+{
 	struct libusb_hotplug_callback *hotplug_cb, *next;
 
 	usbi_mutex_lock(&ctx->hotplug_cbs_lock);
-	list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list,
-				 struct libusb_hotplug_callback) {
-		list_del(&hotplug_cb->list);
-		free(hotplug_cb);
+	list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) {
+		if (forced || (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE)) {
+			usbi_dbg("freeing hotplug cb %p with handle %d", hotplug_cb,
+				 hotplug_cb->handle);
+			list_del(&hotplug_cb->list);
+			free(hotplug_cb);
+		}
 	}
-
 	usbi_mutex_unlock(&ctx->hotplug_cbs_lock);
 }

+ 34 - 25
vendor/github.com/karalabe/hid/libusb/libusb/hotplug.h → vendor/github.com/karalabe/usb/libusb/libusb/hotplug.h

@@ -19,12 +19,34 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#if !defined(USBI_HOTPLUG_H)
+#ifndef USBI_HOTPLUG_H
 #define USBI_HOTPLUG_H
 
-#ifndef LIBUSBI_H
 #include "libusbi.h"
-#endif
+
+enum usbi_hotplug_flags {
+	/* This callback is interested in device arrivals */
+	USBI_HOTPLUG_DEVICE_ARRIVED = LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED,
+
+	/* This callback is interested in device removals */
+	USBI_HOTPLUG_DEVICE_LEFT = LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
+
+	/* IMPORTANT: The values for the below entries must start *after*
+	 * the highest value of the above entries!!!
+	 */
+
+	/* The vendor_id field is valid for matching */
+	USBI_HOTPLUG_VENDOR_ID_VALID = (1 << 3),
+
+	/* The product_id field is valid for matching */
+	USBI_HOTPLUG_PRODUCT_ID_VALID = (1 << 4),
+
+	/* The dev_class field is valid for matching */
+	USBI_HOTPLUG_DEV_CLASS_VALID = (1 << 5),
+
+	/* This callback has been unregistered and needs to be freed */
+	USBI_HOTPLUG_NEEDS_FREE = (1 << 6),
+};
 
 /** \ingroup hotplug
  * The hotplug callback structure. The user populates this structure with
@@ -32,23 +54,17 @@
  * to receive notification of hotplug events.
  */
 struct libusb_hotplug_callback {
-	/** Context this callback is associated with */
-	struct libusb_context *ctx;
-
-	/** Vendor ID to match or LIBUSB_HOTPLUG_MATCH_ANY */
-	int vendor_id;
-
-	/** Product ID to match or LIBUSB_HOTPLUG_MATCH_ANY */
-	int product_id;
+	/** Flags that control how this callback behaves */
+	uint8_t flags;
 
-	/** Device class to match or LIBUSB_HOTPLUG_MATCH_ANY */
-	int dev_class;
+	/** Vendor ID to match (if flags says this is valid) */
+	uint16_t vendor_id;
 
-	/** Hotplug callback flags */
-	libusb_hotplug_flag flags;
+	/** Product ID to match (if flags says this is valid) */
+	uint16_t product_id;
 
-	/** Event(s) that will trigger this callback */
-	libusb_hotplug_event events;
+	/** Device class to match (if flags says this is valid) */
+	uint8_t dev_class;
 
 	/** Callback function to invoke for matching event/device */
 	libusb_hotplug_callback_fn cb;
@@ -59,15 +75,10 @@ struct libusb_hotplug_callback {
 	/** User data that will be passed to the callback function */
 	void *user_data;
 
-	/** Callback is marked for deletion */
-	int needs_free;
-
 	/** List this callback is registered in (ctx->hotplug_cbs) */
 	struct list_head list;
 };
 
-typedef struct libusb_hotplug_callback libusb_hotplug_callback;
-
 struct libusb_hotplug_message {
 	/** The hotplug event that occurred */
 	libusb_hotplug_event event;
@@ -79,9 +90,7 @@ struct libusb_hotplug_message {
 	struct list_head list;
 };
 
-typedef struct libusb_hotplug_message libusb_hotplug_message;
-
-void usbi_hotplug_deregister_all(struct libusb_context *ctx);
+void usbi_hotplug_deregister(struct libusb_context *ctx, int forced);
 void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
 			libusb_hotplug_event event);
 void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev,

+ 38 - 35
vendor/github.com/karalabe/hid/libusb/libusb/io.c → vendor/github.com/karalabe/usb/libusb/libusb/io.c

@@ -1144,8 +1144,8 @@ int usbi_io_init(struct libusb_context *ctx)
 		goto err_close_pipe;
 
 #ifdef USBI_TIMERFD_AVAILABLE
-	ctx->timerfd = timerfd_create(usbi_backend->get_timerfd_clockid(),
-		TFD_NONBLOCK);
+	ctx->timerfd = timerfd_create(usbi_backend.get_timerfd_clockid(),
+		TFD_NONBLOCK | TFD_CLOEXEC);
 	if (ctx->timerfd >= 0) {
 		usbi_dbg("using timerfd for timeouts");
 		r = usbi_add_pollfd(ctx, ctx->timerfd, POLLIN);
@@ -1205,10 +1205,12 @@ static int calculate_timeout(struct usbi_transfer *transfer)
 	unsigned int timeout =
 		USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout;
 
-	if (!timeout)
+	if (!timeout) {
+		timerclear(&transfer->timeout);
 		return 0;
+	}
 
-	r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, &current_time);
+	r = usbi_backend.clock_gettime(USBI_CLOCK_MONOTONIC, &current_time);
 	if (r < 0) {
 		usbi_err(ITRANSFER_CTX(transfer),
 			"failed to read monotonic clock, errno=%d", errno);
@@ -1255,7 +1257,7 @@ struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(
 	int iso_packets)
 {
 	struct libusb_transfer *transfer;
-	size_t os_alloc_size = usbi_backend->transfer_priv_size;
+	size_t os_alloc_size = usbi_backend.transfer_priv_size;
 	size_t alloc_size = sizeof(struct usbi_transfer)
 		+ sizeof(struct libusb_transfer)
 		+ (sizeof(struct libusb_iso_packet_descriptor) * iso_packets)
@@ -1526,7 +1528,7 @@ int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer)
 	 */
 	usbi_mutex_unlock(&ctx->flying_transfers_lock);
 
-	r = usbi_backend->submit_transfer(itransfer);
+	r = usbi_backend.submit_transfer(itransfer);
 	if (r == LIBUSB_SUCCESS) {
 		itransfer->state_flags |= USBI_TRANSFER_IN_FLIGHT;
 		/* keep a reference to this device */
@@ -1567,7 +1569,7 @@ int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer)
 		r = LIBUSB_ERROR_NOT_FOUND;
 		goto out;
 	}
-	r = usbi_backend->cancel_transfer(itransfer);
+	r = usbi_backend.cancel_transfer(itransfer);
 	if (r < 0) {
 		if (r != LIBUSB_ERROR_NOT_FOUND &&
 		    r != LIBUSB_ERROR_NO_DEVICE)
@@ -2004,7 +2006,7 @@ static int handle_timeouts_locked(struct libusb_context *ctx)
 		return 0;
 
 	/* get current time */
-	r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, &systime_ts);
+	r = usbi_backend.clock_gettime(USBI_CLOCK_MONOTONIC, &systime_ts);
 	if (r < 0)
 		return r;
 
@@ -2077,7 +2079,6 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv)
 	struct pollfd *fds = NULL;
 	int i = -1;
 	int timeout_ms;
-	int special_event;
 
 	/* prevent attempts to recursively handle events (e.g. calling into
 	 * libusb_handle_events() from within a hotplug or transfer callback) */
@@ -2146,32 +2147,30 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv)
 	if (tv->tv_usec % 1000)
 		timeout_ms++;
 
-redo_poll:
 	usbi_dbg("poll() %d fds with timeout in %dms", nfds, timeout_ms);
 	r = usbi_poll(fds, nfds, timeout_ms);
 	usbi_dbg("poll() returned %d", r);
 	if (r == 0) {
 		r = handle_timeouts(ctx);
 		goto done;
-	}
-	else if (r == -1 && errno == EINTR) {
+	} else if (r == -1 && errno == EINTR) {
 		r = LIBUSB_ERROR_INTERRUPTED;
 		goto done;
-	}
-	else if (r < 0) {
+	} else if (r < 0) {
 		usbi_err(ctx, "poll failed %d err=%d", r, errno);
 		r = LIBUSB_ERROR_IO;
 		goto done;
 	}
 
-	special_event = 0;
-
 	/* fds[0] is always the event pipe */
 	if (fds[0].revents) {
-		libusb_hotplug_message *message = NULL;
+		struct list_head hotplug_msgs;
 		struct usbi_transfer *itransfer;
+		int hotplug_cb_deregistered = 0;
 		int ret = 0;
 
+		list_init(&hotplug_msgs);
+
 		usbi_dbg("caught a fish on the event pipe");
 
 		/* take the the event data lock while processing events */
@@ -2186,6 +2185,12 @@ redo_poll:
 			ctx->event_flags &= ~USBI_EVENT_USER_INTERRUPT;
 		}
 
+		if (ctx->event_flags & USBI_EVENT_HOTPLUG_CB_DEREGISTERED) {
+			usbi_dbg("someone unregistered a hotplug cb");
+			ctx->event_flags &= ~USBI_EVENT_HOTPLUG_CB_DEREGISTERED;
+			hotplug_cb_deregistered = 1;
+		}
+
 		/* check if someone is closing a device */
 		if (ctx->device_close)
 			usbi_dbg("someone is closing a device");
@@ -2193,9 +2198,7 @@ redo_poll:
 		/* check for any pending hotplug messages */
 		if (!list_empty(&ctx->hotplug_msgs)) {
 			usbi_dbg("hotplug message received");
-			special_event = 1;
-			message = list_first_entry(&ctx->hotplug_msgs, libusb_hotplug_message, list);
-			list_del(&message->list);
+			list_cut(&hotplug_msgs, &ctx->hotplug_msgs);
 		}
 
 		/* complete any pending transfers */
@@ -2203,7 +2206,7 @@ redo_poll:
 			itransfer = list_first_entry(&ctx->completed_transfers, struct usbi_transfer, completed_list);
 			list_del(&itransfer->completed_list);
 			usbi_mutex_unlock(&ctx->event_data_lock);
-			ret = usbi_backend->handle_transfer_completion(itransfer);
+			ret = usbi_backend.handle_transfer_completion(itransfer);
 			if (ret)
 				usbi_err(ctx, "backend handle_transfer_completion failed with error %d", ret);
 			usbi_mutex_lock(&ctx->event_data_lock);
@@ -2215,14 +2218,21 @@ redo_poll:
 
 		usbi_mutex_unlock(&ctx->event_data_lock);
 
-		/* process the hotplug message, if any */
-		if (message) {
+		if (hotplug_cb_deregistered)
+			usbi_hotplug_deregister(ctx, 0);
+
+		/* process the hotplug messages, if any */
+		while (!list_empty(&hotplug_msgs)) {
+			struct libusb_hotplug_message *message =
+				list_first_entry(&hotplug_msgs, struct libusb_hotplug_message, list);
+
 			usbi_hotplug_match(ctx, message->device, message->event);
 
 			/* the device left, dereference the device */
 			if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == message->event)
 				libusb_unref_device(message->device);
 
+			list_del(&message->list);
 			free(message);
 		}
 
@@ -2233,7 +2243,7 @@ redo_poll:
 		}
 
 		if (0 == --r)
-			goto handled;
+			goto done;
 	}
 
 #ifdef USBI_TIMERFD_AVAILABLE
@@ -2242,7 +2252,6 @@ redo_poll:
 		/* timerfd indicates that a timeout has expired */
 		int ret;
 		usbi_dbg("timerfd triggered");
-		special_event = 1;
 
 		ret = handle_timerfd_trigger(ctx);
 		if (ret < 0) {
@@ -2252,20 +2261,14 @@ redo_poll:
 		}
 
 		if (0 == --r)
-			goto handled;
+			goto done;
 	}
 #endif
 
-	r = usbi_backend->handle_events(ctx, fds + internal_nfds, nfds - internal_nfds, r);
+	r = usbi_backend.handle_events(ctx, fds + internal_nfds, nfds - internal_nfds, r);
 	if (r)
 		usbi_err(ctx, "backend handle_events failed with error %d", r);
 
-handled:
-	if (r == 0 && special_event) {
-		timeout_ms = 0;
-		goto redo_poll;
-	}
-
 done:
 	usbi_end_event_handling(ctx);
 	return r;
@@ -2583,7 +2586,7 @@ int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx,
 		return 0;
 	}
 
-	r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, &cur_ts);
+	r = usbi_backend.clock_gettime(USBI_CLOCK_MONOTONIC, &cur_ts);
 	if (r < 0) {
 		usbi_err(ctx, "failed to read monotonic clock, errno=%d", errno);
 		return 0;
@@ -2811,7 +2814,7 @@ void usbi_handle_disconnect(struct libusb_device_handle *dev_handle)
 			 USBI_TRANSFER_TO_LIBUSB_TRANSFER(to_cancel));
 
 		usbi_mutex_lock(&to_cancel->lock);
-		usbi_backend->clear_transfer_priv(to_cancel);
+		usbi_backend.clear_transfer_priv(to_cancel);
 		usbi_mutex_unlock(&to_cancel->lock);
 		usbi_handle_transfer_completion(to_cancel, LIBUSB_TRANSFER_NO_DEVICE);
 	}

+ 63 - 32
vendor/github.com/karalabe/hid/libusb/libusb/libusb.h → vendor/github.com/karalabe/usb/libusb/libusb/libusb.h

@@ -54,13 +54,19 @@ typedef unsigned __int32  uint32_t;
 #include <sys/types.h>
 #endif
 
-#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__HAIKU__)
+#if defined(__linux__) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__HAIKU__)
 #include <sys/time.h>
 #endif
 
 #include <time.h>
 #include <limits.h>
 
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#define ZERO_SIZED_ARRAY		/* [] - valid C99 code */
+#else
+#define ZERO_SIZED_ARRAY	0	/* [0] - non-standard, but usually working code */
+#endif
+
 /* 'interface' might be defined as a macro on Windows, so we need to
  * undefine it so as not to break the current libusb API, because
  * libusb_config_descriptor has an 'interface' member
@@ -79,6 +85,8 @@ typedef unsigned __int32  uint32_t;
 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
 #define LIBUSB_DEPRECATED_FOR(f) \
   __attribute__((deprecated("Use " #f " instead")))
+#elif __GNUC__ >= 3
+#define LIBUSB_DEPRECATED_FOR(f) __attribute__((deprecated))
 #else
 #define LIBUSB_DEPRECATED_FOR(f)
 #endif /* __GNUC__ */
@@ -141,7 +149,7 @@ typedef unsigned __int32  uint32_t;
  * Internally, LIBUSB_API_VERSION is defined as follows:
  * (libusb major << 24) | (libusb minor << 16) | (16 bit incremental)
  */
-#define LIBUSB_API_VERSION 0x01000105
+#define LIBUSB_API_VERSION 0x01000106
 
 /* The following is kept for compatibility, but will be deprecated in the future */
 #define LIBUSBX_API_VERSION LIBUSB_API_VERSION
@@ -729,13 +737,7 @@ struct libusb_bos_dev_capability_descriptor {
 	/** Device Capability type */
 	uint8_t bDevCapabilityType;
 	/** Device Capability data (bLength - 3 bytes) */
-	uint8_t dev_capability_data
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-	[] /* valid C99 code */
-#else
-	[0] /* non-standard, but usually working code */
-#endif
-	;
+	uint8_t dev_capability_data[ZERO_SIZED_ARRAY];
 };
 
 /** \ingroup libusb_desc
@@ -760,13 +762,7 @@ struct libusb_bos_descriptor {
 	uint8_t  bNumDeviceCaps;
 
 	/** bNumDeviceCap Device Capability Descriptors */
-	struct libusb_bos_dev_capability_descriptor *dev_capability
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-	[] /* valid C99 code */
-#else
-	[0] /* non-standard, but usually working code */
-#endif
-	;
+	struct libusb_bos_dev_capability_descriptor *dev_capability[ZERO_SIZED_ARRAY];
 };
 
 /** \ingroup libusb_desc
@@ -927,7 +923,7 @@ struct libusb_version {
  * sessions allows for your program to use two libraries (or dynamically
  * load two modules) which both independently use libusb. This will prevent
  * interference between the individual libusb users - for example
- * libusb_set_debug() will not affect the other user of the library, and
+ * libusb_set_option() will not affect the other user of the library, and
  * libusb_exit() will not destroy resources that the other user is still
  * using.
  *
@@ -987,6 +983,9 @@ enum libusb_speed {
 
 	/** The device is operating at super speed (5000MBit/s). */
 	LIBUSB_SPEED_SUPER = 4,
+
+	/** The device is operating at super speed plus (10000MBit/s). */
+	LIBUSB_SPEED_SUPER_PLUS = 5,
 };
 
 /** \ingroup libusb_dev
@@ -1256,13 +1255,7 @@ struct libusb_transfer {
 	int num_iso_packets;
 
 	/** Isochronous packet descriptors, for isochronous transfers only. */
-	struct libusb_iso_packet_descriptor iso_packet_desc
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-	[] /* valid C99 code */
-#else
-	[0] /* non-standard, but usually working code */
-#endif
-	;
+	struct libusb_iso_packet_descriptor iso_packet_desc[ZERO_SIZED_ARRAY];
 };
 
 /** \ingroup libusb_misc
@@ -1290,21 +1283,20 @@ enum libusb_capability {
  *  - LIBUSB_LOG_LEVEL_NONE (0)    : no messages ever printed by the library (default)
  *  - LIBUSB_LOG_LEVEL_ERROR (1)   : error messages are printed to stderr
  *  - LIBUSB_LOG_LEVEL_WARNING (2) : warning and error messages are printed to stderr
- *  - LIBUSB_LOG_LEVEL_INFO (3)    : informational messages are printed to stdout, warning
- *    and error messages are printed to stderr
- *  - LIBUSB_LOG_LEVEL_DEBUG (4)   : debug and informational messages are printed to stdout,
- *    warnings and errors to stderr
+ *  - LIBUSB_LOG_LEVEL_INFO (3)    : informational messages are printed to stderr
+ *  - LIBUSB_LOG_LEVEL_DEBUG (4)   : debug and informational messages are printed to stderr
  */
 enum libusb_log_level {
 	LIBUSB_LOG_LEVEL_NONE = 0,
-	LIBUSB_LOG_LEVEL_ERROR,
-	LIBUSB_LOG_LEVEL_WARNING,
-	LIBUSB_LOG_LEVEL_INFO,
-	LIBUSB_LOG_LEVEL_DEBUG,
+	LIBUSB_LOG_LEVEL_ERROR = 1,
+	LIBUSB_LOG_LEVEL_WARNING = 2,
+	LIBUSB_LOG_LEVEL_INFO = 3,
+	LIBUSB_LOG_LEVEL_DEBUG = 4,
 };
 
 int LIBUSB_CALL libusb_init(libusb_context **ctx);
 void LIBUSB_CALL libusb_exit(libusb_context *ctx);
+LIBUSB_DEPRECATED_FOR(libusb_set_option)
 void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level);
 const struct libusb_version * LIBUSB_CALL libusb_get_version(void);
 int LIBUSB_CALL libusb_has_capability(uint32_t capability);
@@ -2001,6 +1993,45 @@ int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx,
 void LIBUSB_CALL libusb_hotplug_deregister_callback(libusb_context *ctx,
 						libusb_hotplug_callback_handle callback_handle);
 
+/** \ingroup libusb_lib
+ * Available option values for libusb_set_option().
+ */
+enum libusb_option {
+	/** Set the log message verbosity.
+	 *
+	 * The default level is LIBUSB_LOG_LEVEL_NONE, which means no messages are ever
+	 * printed. If you choose to increase the message verbosity level, ensure
+	 * that your application does not close the stderr file descriptor.
+	 *
+	 * You are advised to use level LIBUSB_LOG_LEVEL_WARNING. libusb is conservative
+	 * with its message logging and most of the time, will only log messages that
+	 * explain error conditions and other oddities. This will help you debug
+	 * your software.
+	 *
+	 * If the LIBUSB_DEBUG environment variable was set when libusb was
+	 * initialized, this function does nothing: the message verbosity is fixed
+	 * to the value in the environment variable.
+	 *
+	 * If libusb was compiled without any message logging, this function does
+	 * nothing: you'll never get any messages.
+	 *
+	 * If libusb was compiled with verbose debug message logging, this function
+	 * does nothing: you'll always get messages from all levels.
+	 */
+	LIBUSB_OPTION_LOG_LEVEL,
+
+	/** Use the UsbDk backend for a specific context, if available.
+	 *
+	 * This option should be set immediately after calling libusb_init(), otherwise
+	 * unspecified behavior may occur.
+	 *
+	 * Only valid on Windows.
+	 */
+	LIBUSB_OPTION_USE_USBDK,
+};
+
+int LIBUSB_CALL libusb_set_option(libusb_context *ctx, enum libusb_option option, ...);
+
 #ifdef __cplusplus
 }
 #endif

+ 89 - 73
vendor/github.com/karalabe/hid/libusb/libusb/libusbi.h → vendor/github.com/karalabe/usb/libusb/libusb/libusbi.h

@@ -39,6 +39,20 @@
 #include "libusb.h"
 #include "version.h"
 
+/* Attribute to ensure that a structure member is aligned to a natural
+ * pointer alignment. Used for os_priv member. */
+#if defined(_MSC_VER)
+#if defined(_WIN64)
+#define PTR_ALIGNED __declspec(align(8))
+#else
+#define PTR_ALIGNED __declspec(align(4))
+#endif
+#elif defined(__GNUC__)
+#define PTR_ALIGNED __attribute__((aligned(sizeof(void *))))
+#else
+#define PTR_ALIGNED
+#endif
+
 /* Inside the libusb code, mark all public functions as follows:
  *   return_type API_EXPORTED function_name(params) { ... }
  * But if the function returns a pointer, mark it as follows:
@@ -139,6 +153,19 @@ static inline void list_del(struct list_head *entry)
 	entry->next = entry->prev = NULL;
 }
 
+static inline void list_cut(struct list_head *list, struct list_head *head)
+{
+	if (list_empty(head))
+		return;
+
+	list->next = head->next;
+	list->next->prev = list;
+	list->prev = head->prev;
+	list->prev->next = list;
+
+	list_init(head);
+}
+
 static inline void *usbi_reallocf(void *ptr, size_t size)
 {
 	void *ret = realloc(ptr, size);
@@ -151,6 +178,9 @@ static inline void *usbi_reallocf(void *ptr, size_t size)
 	const typeof( ((type *)0)->member ) *mptr = (ptr);	\
 	(type *)( (char *)mptr - offsetof(type,member) );})
 
+#ifndef CLAMP
+#define CLAMP(val, min, max) ((val) < (min) ? (min) : ((val) > (max) ? (max) : (val)))
+#endif
 #ifndef MIN
 #define MIN(a, b)	((a) < (b) ? (a) : (b))
 #endif
@@ -175,29 +205,33 @@ static inline void *usbi_reallocf(void *ptr, size_t size)
 	} while (0)
 #endif
 
+#ifdef ENABLE_LOGGING
+
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+#define snprintf usbi_snprintf
+#define vsnprintf usbi_vsnprintf
+int usbi_snprintf(char *dst, size_t size, const char *format, ...);
+int usbi_vsnprintf(char *dst, size_t size, const char *format, va_list ap);
+#define LIBUSB_PRINTF_WIN32
+#endif /* defined(_MSC_VER) && (_MSC_VER < 1900) */
+
 void usbi_log(struct libusb_context *ctx, enum libusb_log_level level,
 	const char *function, const char *format, ...);
 
 void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level,
 	const char *function, const char *format, va_list args);
 
-#if !defined(_MSC_VER) || _MSC_VER >= 1400
+#if !defined(_MSC_VER) || (_MSC_VER >= 1400)
 
-#ifdef ENABLE_LOGGING
 #define _usbi_log(ctx, level, ...) usbi_log(ctx, level, __FUNCTION__, __VA_ARGS__)
-#define usbi_dbg(...) _usbi_log(NULL, LIBUSB_LOG_LEVEL_DEBUG, __VA_ARGS__)
-#else
-#define _usbi_log(ctx, level, ...) do { (void)(ctx); } while(0)
-#define usbi_dbg(...) do {} while(0)
-#endif
 
-#define usbi_info(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_INFO, __VA_ARGS__)
-#define usbi_warn(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_WARNING, __VA_ARGS__)
 #define usbi_err(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_ERROR, __VA_ARGS__)
+#define usbi_warn(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_WARNING, __VA_ARGS__)
+#define usbi_info(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_INFO, __VA_ARGS__)
+#define usbi_dbg(...) _usbi_log(NULL, LIBUSB_LOG_LEVEL_DEBUG, __VA_ARGS__)
 
-#else /* !defined(_MSC_VER) || _MSC_VER >= 1400 */
+#else /* !defined(_MSC_VER) || (_MSC_VER >= 1400) */
 
-#ifdef ENABLE_LOGGING
 #define LOG_BODY(ctxt, level)				\
 {							\
 	va_list args;					\
@@ -205,24 +239,26 @@ void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level,
 	usbi_log_v(ctxt, level, "", format, args);	\
 	va_end(args);					\
 }
-#else
-#define LOG_BODY(ctxt, level)				\
-{							\
-	(void)(ctxt);					\
-}
-#endif
 
-static inline void usbi_info(struct libusb_context *ctx, const char *format, ...)
-	LOG_BODY(ctx, LIBUSB_LOG_LEVEL_INFO)
-static inline void usbi_warn(struct libusb_context *ctx, const char *format, ...)
-	LOG_BODY(ctx, LIBUSB_LOG_LEVEL_WARNING)
 static inline void usbi_err(struct libusb_context *ctx, const char *format, ...)
 	LOG_BODY(ctx, LIBUSB_LOG_LEVEL_ERROR)
-
+static inline void usbi_warn(struct libusb_context *ctx, const char *format, ...)
+	LOG_BODY(ctx, LIBUSB_LOG_LEVEL_WARNING)
+static inline void usbi_info(struct libusb_context *ctx, const char *format, ...)
+	LOG_BODY(ctx, LIBUSB_LOG_LEVEL_INFO)
 static inline void usbi_dbg(const char *format, ...)
 	LOG_BODY(NULL, LIBUSB_LOG_LEVEL_DEBUG)
 
-#endif /* !defined(_MSC_VER) || _MSC_VER >= 1400 */
+#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1400) */
+
+#else /* ENABLE_LOGGING */
+
+#define usbi_err(ctx, ...) do { (void)ctx; } while (0)
+#define usbi_warn(ctx, ...) do { (void)ctx; } while (0)
+#define usbi_info(ctx, ...) do { (void)ctx; } while (0)
+#define usbi_dbg(...) do {} while (0)
+
+#endif /* ENABLE_LOGGING */
 
 #define USBI_GET_CONTEXT(ctx)				\
 	do {						\
@@ -254,8 +290,10 @@ extern struct libusb_context *usbi_default_context;
 struct pollfd;
 
 struct libusb_context {
-	int debug;
+#if defined(ENABLE_LOGGING) && !defined(ENABLE_DEBUG_LOGGING)
+	enum libusb_log_level debug;
 	int debug_fixed;
+#endif
 
 	/* internal event pipe, used for signalling occurrence of an internal event. */
 	int event_pipe[2];
@@ -270,6 +308,7 @@ struct libusb_context {
 
 	/* A list of registered hotplug callbacks */
 	struct list_head hotplug_cbs;
+	libusb_hotplug_callback_handle next_hotplug_cb_handle;
 	usbi_mutex_t hotplug_cbs_lock;
 
 	/* this is a list of in-flight transfer handles, sorted by timeout
@@ -331,6 +370,8 @@ struct libusb_context {
 #endif
 
 	struct list_head list;
+
+	PTR_ALIGNED unsigned char os_priv[ZERO_SIZED_ARRAY];
 };
 
 enum usbi_event_flags {
@@ -339,6 +380,9 @@ enum usbi_event_flags {
 
 	/* The user has interrupted the event handler */
 	USBI_EVENT_USER_INTERRUPT = 1 << 1,
+
+	/* A hotplug callback deregistration is pending */
+	USBI_EVENT_HOTPLUG_CB_DEREGISTERED = 1 << 2,
 };
 
 /* Macros for managing event handling state */
@@ -383,17 +427,7 @@ struct libusb_device {
 	struct libusb_device_descriptor device_descriptor;
 	int attached;
 
-	unsigned char os_priv
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-	[] /* valid C99 code */
-#else
-	[0] /* non-standard, but usually working code */
-#endif
-#if defined(OS_SUNOS)
-	__attribute__ ((aligned (8)));
-#else
-	;
-#endif
+	PTR_ALIGNED unsigned char os_priv[ZERO_SIZED_ARRAY];
 };
 
 struct libusb_device_handle {
@@ -404,17 +438,8 @@ struct libusb_device_handle {
 	struct list_head list;
 	struct libusb_device *dev;
 	int auto_detach_kernel_driver;
-	unsigned char os_priv
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-	[] /* valid C99 code */
-#else
-	[0] /* non-standard, but usually working code */
-#endif
-#if defined(OS_SUNOS)
-	__attribute__ ((aligned (8)));
-#else
-	;
-#endif
+
+	PTR_ALIGNED unsigned char os_priv[ZERO_SIZED_ARRAY];
 };
 
 enum {
@@ -540,14 +565,6 @@ int usbi_clear_event(struct libusb_context *ctx);
 #include "os/poll_windows.h"
 #endif
 
-#if defined(_MSC_VER) && (_MSC_VER < 1900)
-#define snprintf usbi_snprintf
-#define vsnprintf usbi_vsnprintf
-int usbi_snprintf(char *dst, size_t size, const char *format, ...);
-int usbi_vsnprintf(char *dst, size_t size, const char *format, va_list ap);
-#define LIBUSB_PRINTF_WIN32
-#endif
-
 struct usbi_pollfd {
 	/* must come first */
 	struct libusb_pollfd pollfd;
@@ -568,13 +585,7 @@ void usbi_remove_pollfd(struct libusb_context *ctx, int fd);
 struct discovered_devs {
 	size_t len;
 	size_t capacity;
-	struct libusb_device *devices
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-	[] /* valid C99 code */
-#else
-	[0] /* non-standard, but usually working code */
-#endif
-	;
+	struct libusb_device *devices[ZERO_SIZED_ARRAY];
 };
 
 struct discovered_devs *discovered_devs_append(
@@ -607,7 +618,17 @@ struct usbi_os_backend {
 	 *
 	 * This function is called when the user deinitializes the library.
 	 */
-	void (*exit)(void);
+	void (*exit)(struct libusb_context *ctx);
+
+	/* Set a backend-specific option. Optional.
+	 *
+	 * This function is called when the user calls libusb_set_option() and
+	 * the option is not handled by the core library.
+	 *
+	 * Return 0 on success, or a LIBUSB_ERROR code on failure.
+	 */
+	int (*set_option)(struct libusb_context *ctx, enum libusb_option option,
+		va_list args);
 
 	/* Enumerate all the USB devices on the system, returning them in a list
 	 * of discovered devices.
@@ -1110,6 +1131,11 @@ struct usbi_os_backend {
 	clockid_t (*get_timerfd_clockid)(void);
 #endif
 
+	/* Number of bytes to reserve for per-context private backend data.
+	 * This private data area is accessible through the "os_priv" field of
+	 * struct libusb_context. */
+	size_t context_priv_size;
+
 	/* Number of bytes to reserve for per-device private backend data.
 	 * This private data area is accessible through the "os_priv" field of
 	 * struct libusb_device. */
@@ -1127,17 +1153,7 @@ struct usbi_os_backend {
 	size_t transfer_priv_size;
 };
 
-extern const struct usbi_os_backend * const usbi_backend;
-
-extern const struct usbi_os_backend linux_usbfs_backend;
-extern const struct usbi_os_backend darwin_backend;
-extern const struct usbi_os_backend openbsd_backend;
-extern const struct usbi_os_backend netbsd_backend;
-extern const struct usbi_os_backend windows_backend;
-extern const struct usbi_os_backend usbdk_backend;
-extern const struct usbi_os_backend wince_backend;
-extern const struct usbi_os_backend haiku_usb_raw_backend;
-extern const struct usbi_os_backend sunos_backend;
+extern const struct usbi_os_backend usbi_backend;
 
 extern struct list_head active_contexts_list;
 extern usbi_mutex_static_t active_contexts_lock;

+ 75 - 27
vendor/github.com/karalabe/hid/libusb/libusb/os/darwin_usb.c → vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.c

@@ -1,7 +1,7 @@
 /* -*- Mode: C; indent-tabs-mode:nil -*- */
 /*
  * darwin backend for libusb 1.0
- * Copyright © 2008-2016 Nathan Hjelm <hjelmn@users.sourceforge.net>
+ * Copyright © 2008-2017 Nathan Hjelm <hjelmn@users.sourceforge.net>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -36,6 +36,10 @@
 #include <mach/mach_host.h>
 #include <mach/mach_port.h>
 
+/* Suppress warnings about the use of the deprecated objc_registerThreadWithCollector
+ * function. Its use is also conditionalized to only older deployment targets. */
+#define OBJC_SILENCE_GC_DEPRECATIONS 1
+
 #include <AvailabilityMacros.h>
 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200
   #include <objc/objc-auto.h>
@@ -55,6 +59,14 @@ _Atomic int32_t initCount = ATOMIC_VAR_INIT(0);
 #define libusb_darwin_atomic_fetch_add(x, y) (OSAtomicAdd32Barrier(y, x) - y)
 
 static volatile int32_t initCount = 0;
+
+#endif
+
+/* On 10.12 and later, use newly available clock_*() functions */
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
+#define OSX_USE_CLOCK_GETTIME 1
+#else
+#define OSX_USE_CLOCK_GETTIME 0
 #endif
 
 #include "darwin_usb.h"
@@ -65,15 +77,17 @@ static pthread_cond_t  libusb_darwin_at_cond = PTHREAD_COND_INITIALIZER;
 
 static pthread_once_t darwin_init_once = PTHREAD_ONCE_INIT;
 
+#if !OSX_USE_CLOCK_GETTIME
 static clock_serv_t clock_realtime;
 static clock_serv_t clock_monotonic;
+#endif
 
 static CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */
 static CFRunLoopSourceRef libusb_darwin_acfls = NULL; /* shutdown signal for event cf loop */
 
 static usbi_mutex_t darwin_cached_devices_lock = PTHREAD_MUTEX_INITIALIZER;
 static struct list_head darwin_cached_devices = {&darwin_cached_devices, &darwin_cached_devices};
-static char *darwin_device_class = kIOUSBDeviceClassName;
+static const char *darwin_device_class = kIOUSBDeviceClassName;
 
 #define DARWIN_CACHED_DEVICE(a) ((struct darwin_cached_device *) (((struct darwin_device_priv *)((a)->os_priv))->dev))
 
@@ -219,20 +233,21 @@ static int usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32 loca
                                                                          &kCFTypeDictionaryKeyCallBacks,
                                                                          &kCFTypeDictionaryValueCallBacks);
 
-    if (propertyMatchDict) {
-      /* there are no unsigned CFNumber types so treat the value as signed. the os seems to do this
-         internally (CFNumberType of locationID is 3) */
-      CFTypeRef locationCF = CFNumberCreate (NULL, kCFNumberSInt32Type, &location);
+    /* there are no unsigned CFNumber types so treat the value as signed. the OS seems to do this
+         internally (CFNumberType of locationID is kCFNumberSInt32Type) */
+    CFTypeRef locationCF = CFNumberCreate (NULL, kCFNumberSInt32Type, &location);
 
+    if (propertyMatchDict && locationCF) {
       CFDictionarySetValue (propertyMatchDict, CFSTR(kUSBDevicePropertyLocationID), locationCF);
-      /* release our reference to the CFNumber (CFDictionarySetValue retains it) */
-      CFRelease (locationCF);
-
       CFDictionarySetValue (matchingDict, CFSTR(kIOPropertyMatchKey), propertyMatchDict);
-      /* release out reference to the CFMutableDictionaryRef (CFDictionarySetValue retains it) */
-      CFRelease (propertyMatchDict);
     }
     /* else we can still proceed as long as the caller accounts for the possibility of other devices in the iterator */
+
+    /* release our references as per the Create Rule */
+    if (propertyMatchDict)
+      CFRelease (propertyMatchDict);
+    if (locationCF)
+      CFRelease (locationCF);
   }
 
   return IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, deviceIterator);
@@ -300,6 +315,7 @@ static usb_device_t **darwin_device_from_service (io_service_t service)
 }
 
 static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) {
+  UNUSED(ptr);
   struct libusb_context *ctx;
   io_service_t service;
 
@@ -308,7 +324,7 @@ static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) {
   while ((service = IOIteratorNext(add_devices))) {
     /* add this device to each active context's device list */
     list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
-      process_new_device (ctx, service);;
+      process_new_device (ctx, service);
     }
 
     IOObjectRelease(service);
@@ -318,6 +334,7 @@ static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) {
 }
 
 static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
+  UNUSED(ptr);
   struct libusb_device *dev = NULL;
   struct libusb_context *ctx;
   struct darwin_cached_device *old_device;
@@ -516,7 +533,6 @@ static void darwin_check_version (void) {
 }
 
 static int darwin_init(struct libusb_context *ctx) {
-  host_name_port_t host_self;
   int rc;
 
   rc = pthread_once (&darwin_init_once, darwin_check_version);
@@ -530,12 +546,15 @@ static int darwin_init(struct libusb_context *ctx) {
   }
 
   if (libusb_darwin_atomic_fetch_add (&initCount, 1) == 0) {
-    /* create the clocks that will be used */
+#if !OSX_USE_CLOCK_GETTIME
+    /* create the clocks that will be used if clock_gettime() is not available */
+    host_name_port_t host_self;
 
     host_self = mach_host_self();
     host_get_clock_service(host_self, CALENDAR_CLOCK, &clock_realtime);
     host_get_clock_service(host_self, SYSTEM_CLOCK, &clock_monotonic);
     mach_port_deallocate(mach_task_self(), host_self);
+#endif
 
     pthread_create (&libusb_darwin_at, NULL, darwin_event_thread_main, ctx);
 
@@ -548,10 +567,13 @@ static int darwin_init(struct libusb_context *ctx) {
   return rc;
 }
 
-static void darwin_exit (void) {
+static void darwin_exit (struct libusb_context *ctx) {
+  UNUSED(ctx);
   if (libusb_darwin_atomic_fetch_add (&initCount, -1) == 1) {
+#if !OSX_USE_CLOCK_GETTIME
     mach_port_deallocate(mach_task_self(), clock_realtime);
     mach_port_deallocate(mach_task_self(), clock_monotonic);
+#endif
 
     /* stop the event runloop and wait for the thread to terminate. */
     CFRunLoopSourceSignal(libusb_darwin_acfls);
@@ -866,14 +888,29 @@ static int get_device_port (io_service_t service, UInt8 *port) {
   return ret;
 }
 
+static int get_device_parent_sessionID(io_service_t service, UInt64 *parent_sessionID) {
+  kern_return_t result;
+  io_service_t parent;
+
+  /* Walk up the tree in the IOService plane until we find a parent that has a sessionID */
+  parent = service;
+  while((result = IORegistryEntryGetParentEntry (parent, kIOServicePlane, &parent)) == kIOReturnSuccess) {
+    if (get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, parent_sessionID)) {
+        /* Success */
+        return 1;
+    }
+  }
+
+  /* We ran out of parents */
+  return 0;
+}
+
 static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t service,
                                     struct darwin_cached_device **cached_out) {
   struct darwin_cached_device *new_device;
   UInt64 sessionID = 0, parent_sessionID = 0;
   int ret = LIBUSB_SUCCESS;
   usb_device_t **device;
-  io_service_t parent;
-  kern_return_t result;
   UInt8 port = 0;
 
   /* get some info from the io registry */
@@ -884,11 +921,8 @@ static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t ser
 
   usbi_dbg("finding cached device for sessionID 0x%" PRIx64, sessionID);
 
-  result = IORegistryEntryGetParentEntry (service, kIOUSBPlane, &parent);
-
-  if (kIOReturnSuccess == result) {
-    (void) get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, &parent_sessionID);
-    IOObjectRelease(parent);
+  if (get_device_parent_sessionID(service, &parent_sessionID)) {
+    usbi_dbg("parent sessionID: 0x%" PRIx64, parent_sessionID);
   }
 
   usbi_mutex_lock(&darwin_cached_devices_lock);
@@ -1005,8 +1039,11 @@ static int process_new_device (struct libusb_context *ctx, io_service_t service)
     case kUSBDeviceSpeedLow: dev->speed = LIBUSB_SPEED_LOW; break;
     case kUSBDeviceSpeedFull: dev->speed = LIBUSB_SPEED_FULL; break;
     case kUSBDeviceSpeedHigh: dev->speed = LIBUSB_SPEED_HIGH; break;
-#if DeviceVersion >= 500
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
     case kUSBDeviceSpeedSuper: dev->speed = LIBUSB_SPEED_SUPER; break;
+#endif
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
+    case kUSBDeviceSpeedSuperPlus: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break;
 #endif
     default:
       usbi_warn (ctx, "Got unknown device speed %d", devSpeed);
@@ -1216,9 +1253,9 @@ static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) {
 
   kern_return_t kresult;
 
-  u_int8_t numep, direction, number;
-  u_int8_t dont_care1, dont_care3;
-  u_int16_t dont_care2;
+  UInt8 numep, direction, number;
+  UInt8 dont_care1, dont_care3;
+  UInt16 dont_care2;
   int rc;
 
   usbi_dbg ("building table of endpoints.");
@@ -1965,6 +2002,7 @@ static int darwin_handle_transfer_completion (struct usbi_transfer *itransfer) {
 }
 
 static int darwin_clock_gettime(int clk_id, struct timespec *tp) {
+#if !OSX_USE_CLOCK_GETTIME
   mach_timespec_t sys_time;
   clock_serv_t clock_ref;
 
@@ -1987,6 +2025,16 @@ static int darwin_clock_gettime(int clk_id, struct timespec *tp) {
   tp->tv_nsec = sys_time.tv_nsec;
 
   return 0;
+#else
+  switch (clk_id) {
+  case USBI_CLOCK_MONOTONIC:
+    return clock_gettime(CLOCK_MONOTONIC, tp);
+  case USBI_CLOCK_REALTIME:
+    return clock_gettime(CLOCK_REALTIME, tp);
+  default:
+    return LIBUSB_ERROR_INVALID_PARAM;
+  }
+#endif
 }
 
 #if InterfaceVersion >= 550
@@ -2047,7 +2095,7 @@ static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigne
 }
 #endif
 
-const struct usbi_os_backend darwin_backend = {
+const struct usbi_os_backend usbi_backend = {
         .name = "Darwin",
         .caps = 0,
         .init = darwin_init,

+ 48 - 13
vendor/github.com/karalabe/hid/libusb/libusb/os/darwin_usb.h → vendor/github.com/karalabe/usb/libusb/libusb/os/darwin_usb.h

@@ -28,37 +28,58 @@
 #include <IOKit/IOCFPlugIn.h>
 
 /* IOUSBInterfaceInferface */
-#if defined (kIOUSBInterfaceInterfaceID700) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9
+
+/* New in OS 10.12.0. */
+#if defined (kIOUSBInterfaceInterfaceID800) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)
+
+#define usb_interface_t IOUSBInterfaceInterface800
+#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID800
+#define InterfaceVersion 800
+
+/* New in OS 10.10.0. */
+#elif defined (kIOUSBInterfaceInterfaceID700) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 101000)
 
 #define usb_interface_t IOUSBInterfaceInterface700
 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID700
 #define InterfaceVersion 700
 
-#elif defined (kIOUSBInterfaceInterfaceID550) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9
+/* New in OS 10.9.0. */
+#elif defined (kIOUSBInterfaceInterfaceID650) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090)
+
+#define usb_interface_t IOUSBInterfaceInterface650
+#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID650
+#define InterfaceVersion 650
+
+/* New in OS 10.8.2 but can't test deployment target to that granularity, so round up. */
+#elif defined (kIOUSBInterfaceInterfaceID550) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090)
 
 #define usb_interface_t IOUSBInterfaceInterface550
 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID550
 #define InterfaceVersion 550
 
-#elif defined (kIOUSBInterfaceInterfaceID500)
+/* New in OS 10.7.3 but can't test deployment target to that granularity, so round up. */
+#elif defined (kIOUSBInterfaceInterfaceID500) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1080)
 
 #define usb_interface_t IOUSBInterfaceInterface500
 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID500
 #define InterfaceVersion 500
 
-#elif defined (kIOUSBInterfaceInterfaceID300)
+/* New in OS 10.5.0. */
+#elif defined (kIOUSBInterfaceInterfaceID300) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
 
 #define usb_interface_t IOUSBInterfaceInterface300
 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID300
 #define InterfaceVersion 300
 
-#elif defined (kIOUSBInterfaceInterfaceID245)
+/* New in OS 10.4.5 (or 10.4.6?) but can't test deployment target to that granularity, so round up. */
+#elif defined (kIOUSBInterfaceInterfaceID245) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
 
 #define usb_interface_t IOUSBInterfaceInterface245
 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID245
 #define InterfaceVersion 245
 
-#elif defined (kIOUSBInterfaceInterfaceID220)
+/* New in OS 10.4.0. */
+#elif defined (kIOUSBInterfaceInterfaceID220) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1040)
 
 #define usb_interface_t IOUSBInterfaceInterface220
 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220
@@ -66,43 +87,57 @@
 
 #else
 
-#error "IOUSBFamily is too old. Please upgrade your OS"
+#error "IOUSBFamily is too old. Please upgrade your SDK and/or deployment target"
 
 #endif
 
 /* IOUSBDeviceInterface */
-#if defined (kIOUSBDeviceInterfaceID500) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9
+
+/* New in OS 10.9.0. */
+#if defined (kIOUSBDeviceInterfaceID650) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1090)
+
+#define usb_device_t    IOUSBDeviceInterface650
+#define DeviceInterfaceID kIOUSBDeviceInterfaceID650
+#define DeviceVersion 650
+
+/* New in OS 10.7.3 but can't test deployment target to that granularity, so round up. */
+#elif defined (kIOUSBDeviceInterfaceID500) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1080)
 
 #define usb_device_t    IOUSBDeviceInterface500
 #define DeviceInterfaceID kIOUSBDeviceInterfaceID500
 #define DeviceVersion 500
 
-#elif defined (kIOUSBDeviceInterfaceID320)
+/* New in OS 10.5.4 but can't test deployment target to that granularity, so round up. */
+#elif defined (kIOUSBDeviceInterfaceID320) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)
 
 #define usb_device_t    IOUSBDeviceInterface320
 #define DeviceInterfaceID kIOUSBDeviceInterfaceID320
 #define DeviceVersion 320
 
-#elif defined (kIOUSBDeviceInterfaceID300)
+/* New in OS 10.5.0. */
+#elif defined (kIOUSBDeviceInterfaceID300) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
 
 #define usb_device_t    IOUSBDeviceInterface300
 #define DeviceInterfaceID kIOUSBDeviceInterfaceID300
 #define DeviceVersion 300
 
-#elif defined (kIOUSBDeviceInterfaceID245)
+/* New in OS 10.4.5 (or 10.4.6?) but can't test deployment target to that granularity, so round up. */
+#elif defined (kIOUSBDeviceInterfaceID245) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)
 
 #define usb_device_t    IOUSBDeviceInterface245
 #define DeviceInterfaceID kIOUSBDeviceInterfaceID245
 #define DeviceVersion 245
 
-#elif defined (kIOUSBDeviceInterfaceID220)
+/* New in OS 10.2.3 but can't test deployment target to that granularity, so round up. */
+#elif defined (kIOUSBDeviceInterfaceID197) && (MAC_OS_X_VERSION_MIN_REQUIRED >= 1030)
+
 #define usb_device_t    IOUSBDeviceInterface197
 #define DeviceInterfaceID kIOUSBDeviceInterfaceID197
 #define DeviceVersion 197
 
 #else
 
-#error "IOUSBFamily is too old. Please upgrade your OS"
+#error "IOUSBFamily is too old. Please upgrade your SDK and/or deployment target"
 
 #endif
 

+ 0 - 0
vendor/github.com/karalabe/hid/libusb/libusb/os/haiku_pollfs.cpp → vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_pollfs.cpp


+ 0 - 0
vendor/github.com/karalabe/hid/libusb/libusb/os/haiku_usb.h → vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb.h


+ 0 - 0
vendor/github.com/karalabe/hid/libusb/libusb/os/haiku_usb_backend.cpp → vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_backend.cpp


+ 5 - 2
vendor/github.com/karalabe/hid/libusb/libusb/os/haiku_usb_raw.cpp → vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.cpp

@@ -38,8 +38,9 @@ haiku_init(struct libusb_context *ctx)
 }
 
 static void
-haiku_exit(void)
+haiku_exit(struct libusb_context *ctx)
 {
+	UNUSED(ctx);
 	if (atomic_add(&gInitCount, -1) == 1)
 		gUsbRoster.Stop();
 }
@@ -195,11 +196,12 @@ haiku_clock_gettime(int clkid, struct timespec *tp)
 	return LIBUSB_ERROR_INVALID_PARAM;
 }
 
-const struct usbi_os_backend haiku_usb_raw_backend = {
+const struct usbi_os_backend usbi_backend = {
 	/*.name =*/ "Haiku usbfs",
 	/*.caps =*/ 0,
 	/*.init =*/ haiku_init,
 	/*.exit =*/ haiku_exit,
+	/*.set_option =*/ NULL,
 	/*.get_device_list =*/ NULL,
 	/*.hotplug_poll =*/ NULL,
 	/*.open =*/ haiku_open,
@@ -244,6 +246,7 @@ const struct usbi_os_backend haiku_usb_raw_backend = {
 	/*.get_timerfd_clockid =*/ NULL,
 #endif
 
+	/*.context_priv_size=*/ 0,
 	/*.device_priv_size =*/ sizeof(USBDevice *),
 	/*.device_handle_priv_size =*/ sizeof(USBDeviceHandle *),
 	/*.transfer_priv_size =*/ sizeof(USBTransfer *),

+ 0 - 0
vendor/github.com/karalabe/hid/libusb/libusb/os/haiku_usb_raw.h → vendor/github.com/karalabe/usb/libusb/libusb/os/haiku_usb_raw.h


+ 37 - 28
vendor/github.com/karalabe/hid/libusb/libusb/os/linux_netlink.c → vendor/github.com/karalabe/usb/libusb/libusb/os/linux_netlink.c

@@ -45,24 +45,33 @@
 
 #define NL_GROUP_KERNEL 1
 
+#ifndef SOCK_CLOEXEC
+#define SOCK_CLOEXEC	0
+#endif
+
+#ifndef SOCK_NONBLOCK
+#define SOCK_NONBLOCK	0
+#endif
+
 static int linux_netlink_socket = -1;
 static int netlink_control_pipe[2] = { -1, -1 };
 static pthread_t libusb_linux_event_thread;
 
 static void *linux_netlink_event_thread_main(void *arg);
 
-static int set_fd_cloexec_nb(int fd)
+static int set_fd_cloexec_nb(int fd, int socktype)
 {
 	int flags;
 
 #if defined(FD_CLOEXEC)
-	flags = fcntl(fd, F_GETFD);
-	if (flags == -1) {
-		usbi_err(NULL, "failed to get netlink fd flags (%d)", errno);
-		return -1;
-	}
+	/* Make sure the netlink socket file descriptor is marked as CLOEXEC */
+	if (!(socktype & SOCK_CLOEXEC)) {
+		flags = fcntl(fd, F_GETFD);
+		if (flags == -1) {
+			usbi_err(NULL, "failed to get netlink fd flags (%d)", errno);
+			return -1;
+		}
 
-	if (!(flags & FD_CLOEXEC)) {
 		if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {
 			usbi_err(NULL, "failed to set netlink fd flags (%d)", errno);
 			return -1;
@@ -70,13 +79,14 @@ static int set_fd_cloexec_nb(int fd)
 	}
 #endif
 
-	flags = fcntl(fd, F_GETFL);
-	if (flags == -1) {
-		usbi_err(NULL, "failed to get netlink fd status flags (%d)", errno);
-		return -1;
-	}
+	/* Make sure the netlink socket is non-blocking */
+	if (!(socktype & SOCK_NONBLOCK)) {
+		flags = fcntl(fd, F_GETFL);
+		if (flags == -1) {
+			usbi_err(NULL, "failed to get netlink fd status flags (%d)", errno);
+			return -1;
+		}
 
-	if (!(flags & O_NONBLOCK)) {
 		if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
 			usbi_err(NULL, "failed to set netlink fd status flags (%d)", errno);
 			return -1;
@@ -89,21 +99,15 @@ static int set_fd_cloexec_nb(int fd)
 int linux_netlink_start_event_monitor(void)
 {
 	struct sockaddr_nl sa_nl = { .nl_family = AF_NETLINK, .nl_groups = NL_GROUP_KERNEL };
-	int socktype = SOCK_RAW;
+	int socktype = SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC;
 	int opt = 1;
 	int ret;
 
-#if defined(SOCK_CLOEXEC)
-	socktype |= SOCK_CLOEXEC;
-#endif
-#if defined(SOCK_NONBLOCK)
-	socktype |= SOCK_NONBLOCK;
-#endif
-
 	linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT);
 	if (linux_netlink_socket == -1 && errno == EINVAL) {
 		usbi_dbg("failed to create netlink socket of type %d, attempting SOCK_RAW", socktype);
-		linux_netlink_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
+		socktype = SOCK_RAW;
+		linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT);
 	}
 
 	if (linux_netlink_socket == -1) {
@@ -111,7 +115,7 @@ int linux_netlink_start_event_monitor(void)
 		goto err;
 	}
 
-	ret = set_fd_cloexec_nb(linux_netlink_socket);
+	ret = set_fd_cloexec_nb(linux_netlink_socket, socktype);
 	if (ret == -1)
 		goto err_close_socket;
 
@@ -162,7 +166,7 @@ int linux_netlink_stop_event_monitor(void)
 
 	/* Write some dummy data to the control pipe and
 	 * wait for the thread to exit */
-	r = usbi_write(netlink_control_pipe[1], &dummy, sizeof(dummy));
+	r = write(netlink_control_pipe[1], &dummy, sizeof(dummy));
 	if (r <= 0)
 		usbi_warn(NULL, "netlink control pipe signal failed");
 
@@ -356,7 +360,8 @@ static int linux_netlink_read_message(void)
 static void *linux_netlink_event_thread_main(void *arg)
 {
 	char dummy;
-	ssize_t r;
+	int r;
+	ssize_t nb;
 	struct pollfd fds[] = {
 		{ .fd = netlink_control_pipe[0],
 		  .events = POLLIN },
@@ -368,11 +373,15 @@ static void *linux_netlink_event_thread_main(void *arg)
 
 	usbi_dbg("netlink event thread entering");
 
-	while (poll(fds, 2, -1) >= 0) {
+	while ((r = poll(fds, 2, -1)) >= 0 || errno == EINTR) {
+		if (r < 0) {
+			/* temporary failure */
+			continue;
+		}
 		if (fds[0].revents & POLLIN) {
 			/* activity on control pipe, read the byte and exit */
-			r = usbi_read(netlink_control_pipe[0], &dummy, sizeof(dummy));
-			if (r <= 0)
+			nb = read(netlink_control_pipe[0], &dummy, sizeof(dummy));
+			if (nb <= 0)
 				usbi_warn(NULL, "netlink control pipe read failed");
 			break;
 		}

+ 26 - 8
vendor/github.com/karalabe/hid/libusb/libusb/os/linux_udev.c → vendor/github.com/karalabe/usb/libusb/libusb/os/linux_udev.c

@@ -82,17 +82,33 @@ int linux_udev_start_event_monitor(void)
 
 	udev_monitor_fd = udev_monitor_get_fd(udev_monitor);
 
+#if defined(FD_CLOEXEC)
+	/* Make sure the udev file descriptor is marked as CLOEXEC */
+	r = fcntl(udev_monitor_fd, F_GETFD);
+	if (r == -1) {
+		usbi_err(NULL, "geting udev monitor fd flags (%d)", errno);
+		goto err_free_monitor;
+	}
+	if (!(r & FD_CLOEXEC)) {
+		if (fcntl(udev_monitor_fd, F_SETFD, r | FD_CLOEXEC) == -1) {
+			usbi_err(NULL, "setting udev monitor fd flags (%d)", errno);
+			goto err_free_monitor;
+		}
+	}
+#endif
+
 	/* Some older versions of udev are not non-blocking by default,
 	 * so make sure this is set */
 	r = fcntl(udev_monitor_fd, F_GETFL);
 	if (r == -1) {
-		usbi_err(NULL, "getting udev monitor fd flags (%d)", errno);
+		usbi_err(NULL, "getting udev monitor fd status flags (%d)", errno);
 		goto err_free_monitor;
 	}
-	r = fcntl(udev_monitor_fd, F_SETFL, r | O_NONBLOCK);
-	if (r) {
-		usbi_err(NULL, "setting udev monitor fd flags (%d)", errno);
-		goto err_free_monitor;
+	if (!(r & O_NONBLOCK)) {
+		if (fcntl(udev_monitor_fd, F_SETFL, r | O_NONBLOCK) == -1) {
+			usbi_err(NULL, "setting udev monitor fd status flags (%d)", errno);
+			goto err_free_monitor;
+		}
 	}
 
 	r = usbi_pipe(udev_control_pipe);
@@ -134,7 +150,7 @@ int linux_udev_stop_event_monitor(void)
 
 	/* Write some dummy data to the control pipe and
 	 * wait for the thread to exit */
-	r = usbi_write(udev_control_pipe[1], &dummy, sizeof(dummy));
+	r = write(udev_control_pipe[1], &dummy, sizeof(dummy));
 	if (r <= 0) {
 		usbi_warn(NULL, "udev control pipe signal failed");
 	}
@@ -162,6 +178,7 @@ static void *linux_udev_event_thread_main(void *arg)
 {
 	char dummy;
 	int r;
+	ssize_t nb;
 	struct udev_device* udev_dev;
 	struct pollfd fds[] = {
 		{.fd = udev_control_pipe[0],
@@ -179,8 +196,8 @@ static void *linux_udev_event_thread_main(void *arg)
 		}
 		if (fds[0].revents & POLLIN) {
 			/* activity on control pipe, read the byte and exit */
-			r = usbi_read(udev_control_pipe[0], &dummy, sizeof(dummy));
-			if (r <= 0) {
+			nb = read(udev_control_pipe[0], &dummy, sizeof(dummy));
+			if (nb <= 0) {
 				usbi_warn(NULL, "udev control pipe read failed");
 			}
 			break;
@@ -274,6 +291,7 @@ int linux_udev_scan_devices(struct libusb_context *ctx)
 	udev_enumerate_scan_devices(enumerator);
 	devices = udev_enumerate_get_list_entry(enumerator);
 
+	entry = NULL;
 	udev_list_entry_foreach(entry, devices) {
 		const char *path = udev_list_entry_get_name(entry);
 		uint8_t busnum = 0, devaddr = 0;

+ 162 - 100
vendor/github.com/karalabe/hid/libusb/libusb/os/linux_usbfs.c → vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.c

@@ -81,6 +81,19 @@ static const char *usbfs_path = NULL;
 /* use usbdev*.* device names in /dev instead of the usbfs bus directories */
 static int usbdev_names = 0;
 
+/* Linux has changed the maximum length of an individual isochronous packet
+ * over time.  Initially this limit was 1,023 bytes, but Linux 2.6.18
+ * (commit 3612242e527eb47ee4756b5350f8bdf791aa5ede) increased this value to
+ * 8,192 bytes to support higher bandwidth devices.  Linux 3.10
+ * (commit e2e2f0ea1c935edcf53feb4c4c8fdb4f86d57dd9) further increased this
+ * value to 49,152 bytes to support super speed devices.
+ */
+static unsigned int max_iso_packet_len = 0;
+
+/* Linux 2.6.23 adds support for O_CLOEXEC when opening files, which marks the
+ * close-on-exec flag in the underlying file descriptor. */
+static int supports_flag_cloexec = -1;
+
 /* Linux 2.6.32 adds support for a bulk continuation URB flag. this basically
  * allows us to mark URBs as being part of a specific logical transfer when
  * we submit them to the kernel. then, on any error except a cancellation, all
@@ -136,6 +149,12 @@ static int detach_kernel_driver_and_claim(struct libusb_device_handle *, int);
 static int linux_default_scan_devices (struct libusb_context *ctx);
 #endif
 
+struct kernel_version {
+	int major;
+	int minor;
+	int sublevel;
+};
+
 struct linux_device_priv {
 	char *sysfs_dir;
 	unsigned char *descriptors;
@@ -180,6 +199,16 @@ struct linux_transfer_priv {
 	int iso_packet_offset;
 };
 
+static int _open(const char *path, int flags)
+{
+#if defined(O_CLOEXEC)
+	if (supports_flag_cloexec)
+		return open(path, flags | O_CLOEXEC);
+	else
+#endif
+		return open(path, flags);
+}
+
 static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
 {
 	struct libusb_context *ctx = DEVICE_CTX(dev);
@@ -194,7 +223,7 @@ static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
 		snprintf(path, PATH_MAX, "%s/%03d/%03d",
 			usbfs_path, dev->bus_number, dev->device_address);
 
-	fd = open(path, mode);
+	fd = _open(path, mode);
 	if (fd != -1)
 		return fd; /* Success */
 
@@ -205,7 +234,7 @@ static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
 		/* Wait 10ms for USB device path creation.*/
 		nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000UL}, NULL);
 
-		fd = open(path, mode);
+		fd = _open(path, mode);
 		if (fd != -1)
 			return fd; /* Success */
 	}
@@ -342,39 +371,59 @@ static clockid_t find_monotonic_clock(void)
 	return CLOCK_REALTIME;
 }
 
-static int kernel_version_ge(int major, int minor, int sublevel)
+static int get_kernel_version(struct libusb_context *ctx,
+	struct kernel_version *ver)
 {
 	struct utsname uts;
-	int atoms, kmajor, kminor, ksublevel;
+	int atoms;
 
-	if (uname(&uts) < 0)
+	if (uname(&uts) < 0) {
+		usbi_err(ctx, "uname failed, errno %d", errno);
 		return -1;
-	atoms = sscanf(uts.release, "%d.%d.%d", &kmajor, &kminor, &ksublevel);
-	if (atoms < 1)
+	}
+
+	atoms = sscanf(uts.release, "%d.%d.%d", &ver->major, &ver->minor, &ver->sublevel);
+	if (atoms < 1) {
+		usbi_err(ctx, "failed to parse uname release '%s'", uts.release);
 		return -1;
+	}
+
+	if (atoms < 2)
+		ver->minor = -1;
+	if (atoms < 3)
+		ver->sublevel = -1;
 
-	if (kmajor > major)
+	usbi_dbg("reported kernel version is %s", uts.release);
+
+	return 0;
+}
+
+static int kernel_version_ge(const struct kernel_version *ver,
+	int major, int minor, int sublevel)
+{
+	if (ver->major > major)
 		return 1;
-	if (kmajor < major)
+	else if (ver->major < major)
 		return 0;
 
 	/* kmajor == major */
-	if (atoms < 2)
+	if (ver->minor == -1 && ver->sublevel == -1)
 		return 0 == minor && 0 == sublevel;
-	if (kminor > minor)
+	else if (ver->minor > minor)
 		return 1;
-	if (kminor < minor)
+	else if (ver->minor < minor)
 		return 0;
 
 	/* kminor == minor */
-	if (atoms < 3)
+	if (ver->sublevel == -1)
 		return 0 == sublevel;
 
-	return ksublevel >= sublevel;
+	return ver->sublevel >= sublevel;
 }
 
 static int op_init(struct libusb_context *ctx)
 {
+	struct kernel_version kversion;
 	struct stat statbuf;
 	int r;
 
@@ -387,13 +436,17 @@ static int op_init(struct libusb_context *ctx)
 	if (monotonic_clkid == -1)
 		monotonic_clkid = find_monotonic_clock();
 
+	if (get_kernel_version(ctx, &kversion) < 0)
+		return LIBUSB_ERROR_OTHER;
+
+	if (supports_flag_cloexec == -1) {
+		/* O_CLOEXEC flag available from Linux 2.6.23 */
+		supports_flag_cloexec = kernel_version_ge(&kversion,2,6,23);
+	}
+
 	if (supports_flag_bulk_continuation == -1) {
 		/* bulk continuation URB flag available from Linux 2.6.32 */
-		supports_flag_bulk_continuation = kernel_version_ge(2,6,32);
-		if (supports_flag_bulk_continuation == -1) {
-			usbi_err(ctx, "error checking for bulk continuation support");
-			return LIBUSB_ERROR_OTHER;
-		}
+		supports_flag_bulk_continuation = kernel_version_ge(&kversion,2,6,32);
 	}
 
 	if (supports_flag_bulk_continuation)
@@ -401,32 +454,31 @@ static int op_init(struct libusb_context *ctx)
 
 	if (-1 == supports_flag_zero_packet) {
 		/* zero length packet URB flag fixed since Linux 2.6.31 */
-		supports_flag_zero_packet = kernel_version_ge(2,6,31);
-		if (-1 == supports_flag_zero_packet) {
-			usbi_err(ctx, "error checking for zero length packet support");
-			return LIBUSB_ERROR_OTHER;
-		}
+		supports_flag_zero_packet = kernel_version_ge(&kversion,2,6,31);
 	}
 
 	if (supports_flag_zero_packet)
 		usbi_dbg("zero length packet flag supported");
 
+	if (!max_iso_packet_len) {
+		if (kernel_version_ge(&kversion,3,10,0))
+			max_iso_packet_len = 49152;
+		else if (kernel_version_ge(&kversion,2,6,18))
+			max_iso_packet_len = 8192;
+		else
+			max_iso_packet_len = 1023;
+	}
+
+	usbi_dbg("max iso packet length is (likely) %u bytes", max_iso_packet_len);
+
 	if (-1 == sysfs_has_descriptors) {
 		/* sysfs descriptors has all descriptors since Linux 2.6.26 */
-		sysfs_has_descriptors = kernel_version_ge(2,6,26);
-		if (-1 == sysfs_has_descriptors) {
-			usbi_err(ctx, "error checking for sysfs descriptors");
-			return LIBUSB_ERROR_OTHER;
-		}
+		sysfs_has_descriptors = kernel_version_ge(&kversion,2,6,26);
 	}
 
 	if (-1 == sysfs_can_relate_devices) {
 		/* sysfs has busnum since Linux 2.6.22 */
-		sysfs_can_relate_devices = kernel_version_ge(2,6,22);
-		if (-1 == sysfs_can_relate_devices) {
-			usbi_err(ctx, "error checking for sysfs busnum");
-			return LIBUSB_ERROR_OTHER;
-		}
+		sysfs_can_relate_devices = kernel_version_ge(&kversion,2,6,22);
 	}
 
 	if (sysfs_can_relate_devices || sysfs_has_descriptors) {
@@ -463,8 +515,9 @@ static int op_init(struct libusb_context *ctx)
 	return r;
 }
 
-static void op_exit(void)
+static void op_exit(struct libusb_context *ctx)
 {
+	UNUSED(ctx);
 	usbi_mutex_static_lock(&linux_hotplug_startstop_lock);
 	assert(init_count != 0);
 	if (!--init_count) {
@@ -526,7 +579,7 @@ static int _open_sysfs_attr(struct libusb_device *dev, const char *attr)
 
 	snprintf(filename, PATH_MAX, "%s/%s/%s",
 		SYSFS_DEVICE_PATH, priv->sysfs_dir, attr);
-	fd = open(filename, O_RDONLY);
+	fd = _open(filename, O_RDONLY);
 	if (fd < 0) {
 		usbi_err(DEVICE_CTX(dev),
 			"open %s failed ret=%d errno=%d", filename, fd, errno);
@@ -542,12 +595,12 @@ static int __read_sysfs_attr(struct libusb_context *ctx,
 {
 	char filename[PATH_MAX];
 	FILE *f;
-	int r, value;
+	int fd, r, value;
 
 	snprintf(filename, PATH_MAX, "%s/%s/%s", SYSFS_DEVICE_PATH,
 		 devname, attr);
-	f = fopen(filename, "r");
-	if (f == NULL) {
+	fd = _open(filename, O_RDONLY);
+	if (fd == -1) {
 		if (errno == ENOENT) {
 			/* File doesn't exist. Assume the device has been
 			   disconnected (see trac ticket #70). */
@@ -557,6 +610,13 @@ static int __read_sysfs_attr(struct libusb_context *ctx,
 		return LIBUSB_ERROR_IO;
 	}
 
+	f = fdopen(fd, "r");
+	if (f == NULL) {
+		usbi_err(ctx, "fdopen %s failed errno=%d", filename, errno);
+		close(fd);
+		return LIBUSB_ERROR_OTHER;
+	}
+
 	r = fscanf(f, "%d", &value);
 	fclose(f);
 	if (r != 1) {
@@ -806,7 +866,7 @@ static int op_get_active_config_descriptor(struct libusb_device *dev,
 	if (r < 0)
 		return r;
 
-	len = MIN(len, r);
+	len = MIN(len, (size_t)r);
 	memcpy(buffer, config_desc, len);
 	return len;
 }
@@ -836,7 +896,7 @@ static int op_get_config_descriptor(struct libusb_device *dev,
 		descriptors += r;
 	}
 
-	len = MIN(len, r);
+	len = MIN(len, (size_t)r);
 	memcpy(buffer, descriptors, len);
 	return len;
 }
@@ -911,6 +971,7 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum,
 			case    12: dev->speed = LIBUSB_SPEED_FULL; break;
 			case   480: dev->speed = LIBUSB_SPEED_HIGH; break;
 			case  5000: dev->speed = LIBUSB_SPEED_SUPER; break;
+			case 10000: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break;
 			default:
 				usbi_warn(DEVICE_CTX(dev), "Unknown device speed: %d Mbps", speed);
 			}
@@ -1239,11 +1300,12 @@ static int sysfs_get_device_list(struct libusb_context *ctx)
 {
 	DIR *devices = opendir(SYSFS_DEVICE_PATH);
 	struct dirent *entry;
-	int r = LIBUSB_ERROR_IO;
+	int num_devices = 0;
+	int num_enumerated = 0;
 
 	if (!devices) {
 		usbi_err(ctx, "opendir devices failed errno=%d", errno);
-		return r;
+		return LIBUSB_ERROR_IO;
 	}
 
 	while ((entry = readdir(devices))) {
@@ -1251,16 +1313,23 @@ static int sysfs_get_device_list(struct libusb_context *ctx)
 				|| strchr(entry->d_name, ':'))
 			continue;
 
+		num_devices++;
+
 		if (sysfs_scan_device(ctx, entry->d_name)) {
 			usbi_dbg("failed to enumerate dir entry %s", entry->d_name);
 			continue;
 		}
 
-		r = 0;
+		num_enumerated++;
 	}
 
 	closedir(devices);
-	return r;
+
+	/* successful if at least one device was enumerated or no devices were found */
+	if (num_enumerated || !num_devices)
+		return LIBUSB_SUCCESS;
+	else
+		return LIBUSB_ERROR_IO;
 }
 
 static int linux_default_scan_devices (struct libusb_context *ctx)
@@ -1685,10 +1754,7 @@ static int detach_kernel_driver_and_claim(struct libusb_device_handle *handle,
 	strcpy(dc.driver, "usbfs");
 	dc.flags = USBFS_DISCONNECT_CLAIM_EXCEPT_DRIVER;
 	r = ioctl(fd, IOCTL_USBFS_DISCONNECT_CLAIM, &dc);
-	if (r == 0 || (r != 0 && errno != ENOTTY)) {
-		if (r == 0)
-			return 0;
-
+	if (r != 0 && errno != ENOTTY) {
 		switch (errno) {
 		case EBUSY:
 			return LIBUSB_ERROR_BUSY;
@@ -1700,7 +1766,8 @@ static int detach_kernel_driver_and_claim(struct libusb_device_handle *handle,
 		usbi_err(HANDLE_CTX(handle),
 			"disconnect-and-claim failed errno %d", errno);
 		return LIBUSB_ERROR_OTHER;
-	}
+	} else if (r == 0)
+		return 0;
 
 	/* Fallback code for kernels which don't support the
 	   disconnect-and-claim ioctl */
@@ -1973,38 +2040,43 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
 	struct linux_device_handle_priv *dpriv =
 		_device_handle_priv(transfer->dev_handle);
 	struct usbfs_urb **urbs;
-	size_t alloc_size;
 	int num_packets = transfer->num_iso_packets;
-	int i;
-	int this_urb_len = 0;
-	int num_urbs = 1;
-	int packet_offset = 0;
+	int num_packets_remaining;
+	int i, j;
+	int num_urbs;
 	unsigned int packet_len;
+	unsigned int total_len = 0;
 	unsigned char *urb_buffer = transfer->buffer;
 
+	if (num_packets < 1)
+		return LIBUSB_ERROR_INVALID_PARAM;
+
 	/* usbfs places arbitrary limits on iso URBs. this limit has changed
-	 * at least three times, and it's difficult to accurately detect which
-	 * limit this running kernel might impose. so we attempt to submit
-	 * whatever the user has provided. if the kernel rejects the request
-	 * due to its size, we return an error indicating such to the user.
+	 * at least three times, but we attempt to detect this limit during
+	 * init and check it here. if the kernel rejects the request due to
+	 * its size, we return an error indicating such to the user.
 	 */
-
-	/* calculate how many URBs we need */
 	for (i = 0; i < num_packets; i++) {
-		unsigned int space_remaining = MAX_ISO_BUFFER_LENGTH - this_urb_len;
 		packet_len = transfer->iso_packet_desc[i].length;
 
-		if (packet_len > space_remaining) {
-			num_urbs++;
-			this_urb_len = packet_len;
-			/* check that we can actually support this packet length */
-			if (this_urb_len > MAX_ISO_BUFFER_LENGTH)
-				return LIBUSB_ERROR_INVALID_PARAM;
-		} else {
-			this_urb_len += packet_len;
+		if (packet_len > max_iso_packet_len) {
+			usbi_warn(TRANSFER_CTX(transfer),
+				"iso packet length of %u bytes exceeds maximum of %u bytes",
+				packet_len, max_iso_packet_len);
+			return LIBUSB_ERROR_INVALID_PARAM;
 		}
+
+		total_len += packet_len;
 	}
-	usbi_dbg("need %d %dk URBs for transfer", num_urbs, MAX_ISO_BUFFER_LENGTH / 1024);
+
+	if (transfer->length < (int)total_len)
+		return LIBUSB_ERROR_INVALID_PARAM;
+
+	/* usbfs limits the number of iso packets per URB */
+	num_urbs = (num_packets + (MAX_ISO_PACKETS_PER_URB - 1)) / MAX_ISO_PACKETS_PER_URB;
+
+	usbi_dbg("need %d urbs for new transfer with length %d", num_urbs,
+		transfer->length);
 
 	urbs = calloc(num_urbs, sizeof(*urbs));
 	if (!urbs)
@@ -2017,31 +2089,15 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
 	tpriv->iso_packet_offset = 0;
 
 	/* allocate + initialize each URB with the correct number of packets */
-	for (i = 0; i < num_urbs; i++) {
+	num_packets_remaining = num_packets;
+	for (i = 0, j = 0; i < num_urbs; i++) {
+		int num_packets_in_urb = MIN(num_packets_remaining, MAX_ISO_PACKETS_PER_URB);
 		struct usbfs_urb *urb;
-		unsigned int space_remaining_in_urb = MAX_ISO_BUFFER_LENGTH;
-		int urb_packet_offset = 0;
-		unsigned char *urb_buffer_orig = urb_buffer;
-		int j;
+		size_t alloc_size;
 		int k;
 
-		/* swallow up all the packets we can fit into this URB */
-		while (packet_offset < transfer->num_iso_packets) {
-			packet_len = transfer->iso_packet_desc[packet_offset].length;
-			if (packet_len <= space_remaining_in_urb) {
-				/* throw it in */
-				urb_packet_offset++;
-				packet_offset++;
-				space_remaining_in_urb -= packet_len;
-				urb_buffer += packet_len;
-			} else {
-				/* it can't fit, save it for the next URB */
-				break;
-			}
-		}
-
 		alloc_size = sizeof(*urb)
-			+ (urb_packet_offset * sizeof(struct usbfs_iso_packet_desc));
+			+ (num_packets_in_urb * sizeof(struct usbfs_iso_packet_desc));
 		urb = calloc(1, alloc_size);
 		if (!urb) {
 			free_iso_urbs(tpriv);
@@ -2050,10 +2106,10 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
 		urbs[i] = urb;
 
 		/* populate packet lengths */
-		for (j = 0, k = packet_offset - urb_packet_offset;
-				k < packet_offset; k++, j++) {
-			packet_len = transfer->iso_packet_desc[k].length;
-			urb->iso_frame_desc[j].length = packet_len;
+		for (k = 0; k < num_packets_in_urb; j++, k++) {
+			packet_len = transfer->iso_packet_desc[j].length;
+			urb->buffer_length += packet_len;
+			urb->iso_frame_desc[k].length = packet_len;
 		}
 
 		urb->usercontext = itransfer;
@@ -2061,8 +2117,11 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
 		/* FIXME: interface for non-ASAP data? */
 		urb->flags = USBFS_URB_ISO_ASAP;
 		urb->endpoint = transfer->endpoint;
-		urb->number_of_packets = urb_packet_offset;
-		urb->buffer = urb_buffer_orig;
+		urb->number_of_packets = num_packets_in_urb;
+		urb->buffer = urb_buffer;
+
+		urb_buffer += urb->buffer_length;
+		num_packets_remaining -= num_packets_in_urb;
 	}
 
 	/* submit URBs */
@@ -2075,6 +2134,10 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
 				usbi_warn(TRANSFER_CTX(transfer),
 					"submiturb failed, transfer too large");
 				r = LIBUSB_ERROR_INVALID_PARAM;
+			} else if (errno == EMSGSIZE) {
+				usbi_warn(TRANSFER_CTX(transfer),
+					"submiturb failed, iso packet length too large");
+				r = LIBUSB_ERROR_INVALID_PARAM;
 			} else {
 				usbi_err(TRANSFER_CTX(transfer),
 					"submiturb failed error %d errno=%d", r, errno);
@@ -2213,7 +2276,6 @@ static void op_clear_transfer_priv(struct usbi_transfer *itransfer)
 		USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
 	struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
 
-	/* urbs can be freed also in submit_transfer so lock mutex first */
 	switch (transfer->type) {
 	case LIBUSB_TRANSFER_TYPE_CONTROL:
 	case LIBUSB_TRANSFER_TYPE_BULK:
@@ -2685,7 +2747,7 @@ static clockid_t op_get_timerfd_clockid(void)
 }
 #endif
 
-const struct usbi_os_backend linux_usbfs_backend = {
+const struct usbi_os_backend usbi_backend = {
 	.name = "Linux usbfs",
 	.caps = USBI_CAP_HAS_HID_ACCESS|USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER,
 	.init = op_init,

+ 2 - 1
vendor/github.com/karalabe/hid/libusb/libusb/os/linux_usbfs.h → vendor/github.com/karalabe/usb/libusb/libusb/os/linux_usbfs.h

@@ -81,10 +81,11 @@ struct usbfs_iso_packet_desc {
 	unsigned int status;
 };
 
-#define MAX_ISO_BUFFER_LENGTH		49152 * 128
 #define MAX_BULK_BUFFER_LENGTH		16384
 #define MAX_CTRL_BUFFER_LENGTH		4096
 
+#define MAX_ISO_PACKETS_PER_URB		128
+
 struct usbfs_urb {
 	unsigned char type;
 	unsigned char endpoint;

+ 3 - 3
vendor/github.com/karalabe/hid/libusb/libusb/os/netbsd_usb.c → vendor/github.com/karalabe/usb/libusb/libusb/os/netbsd_usb.c

@@ -86,11 +86,12 @@ static int _sync_control_transfer(struct usbi_transfer *);
 static int _sync_gen_transfer(struct usbi_transfer *);
 static int _access_endpoint(struct libusb_transfer *);
 
-const struct usbi_os_backend netbsd_backend = {
+const struct usbi_os_backend usbi_backend = {
 	"Synchronous NetBSD backend",
 	0,
 	NULL,				/* init() */
 	NULL,				/* exit() */
+	NULL,				/* set_option() */
 	netbsd_get_device_list,
 	NULL,				/* hotplug_poll */
 	netbsd_open,
@@ -131,6 +132,7 @@ const struct usbi_os_backend netbsd_backend = {
 	netbsd_handle_transfer_completion,
 
 	netbsd_clock_gettime,
+	0,				/* context_priv_size */
 	sizeof(struct device_priv),
 	sizeof(struct handle_priv),
 	0,				/* transfer_priv_size */
@@ -212,7 +214,6 @@ error:
 int
 netbsd_open(struct libusb_device_handle *handle)
 {
-	struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
 	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
 
 	dpriv->fd = open(dpriv->devnode, O_RDWR);
@@ -230,7 +231,6 @@ netbsd_open(struct libusb_device_handle *handle)
 void
 netbsd_close(struct libusb_device_handle *handle)
 {
-	struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
 	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
 
 	usbi_dbg("close: fd %d", dpriv->fd);

+ 3 - 3
vendor/github.com/karalabe/hid/libusb/libusb/os/openbsd_usb.c → vendor/github.com/karalabe/usb/libusb/libusb/os/openbsd_usb.c

@@ -89,11 +89,12 @@ static int _access_endpoint(struct libusb_transfer *);
 static int _bus_open(int);
 
 
-const struct usbi_os_backend openbsd_backend = {
+const struct usbi_os_backend usbi_backend = {
 	"Synchronous OpenBSD backend",
 	0,
 	NULL,				/* init() */
 	NULL,				/* exit() */
+	NULL,				/* set_option() */
 	obsd_get_device_list,
 	NULL,				/* hotplug_poll */
 	obsd_open,
@@ -134,6 +135,7 @@ const struct usbi_os_backend openbsd_backend = {
 	obsd_handle_transfer_completion,
 
 	obsd_clock_gettime,
+	0,				/* context_priv_size */
 	sizeof(struct device_priv),
 	sizeof(struct handle_priv),
 	0,				/* transfer_priv_size */
@@ -246,7 +248,6 @@ obsd_get_device_list(struct libusb_context * ctx,
 int
 obsd_open(struct libusb_device_handle *handle)
 {
-	struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
 	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
 	char devnode[16];
 
@@ -270,7 +271,6 @@ obsd_open(struct libusb_device_handle *handle)
 void
 obsd_close(struct libusb_device_handle *handle)
 {
-	struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
 	struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
 
 	if (dpriv->devname) {

+ 36 - 5
vendor/github.com/karalabe/hid/libusb/libusb/os/poll_posix.c → vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.c

@@ -29,25 +29,56 @@
 
 int usbi_pipe(int pipefd[2])
 {
+#if defined(HAVE_PIPE2)
+	int ret = pipe2(pipefd, O_CLOEXEC);
+#else
 	int ret = pipe(pipefd);
+#endif
+
 	if (ret != 0) {
+		usbi_err(NULL, "failed to create pipe (%d)", errno);
 		return ret;
 	}
+
+#if !defined(HAVE_PIPE2) && defined(FD_CLOEXEC)
+	ret = fcntl(pipefd[0], F_GETFD);
+	if (ret == -1) {
+		usbi_err(NULL, "failed to get pipe fd flags (%d)", errno);
+		goto err_close_pipe;
+	}
+	ret = fcntl(pipefd[0], F_SETFD, ret | FD_CLOEXEC);
+	if (ret == -1) {
+		usbi_err(NULL, "failed to set pipe fd flags (%d)", errno);
+		goto err_close_pipe;
+	}
+
+	ret = fcntl(pipefd[1], F_GETFD);
+	if (ret == -1) {
+		usbi_err(NULL, "failed to get pipe fd flags (%d)", errno);
+		goto err_close_pipe;
+	}
+	ret = fcntl(pipefd[1], F_SETFD, ret | FD_CLOEXEC);
+	if (ret == -1) {
+		usbi_err(NULL, "failed to set pipe fd flags (%d)", errno);
+		goto err_close_pipe;
+	}
+#endif
+
 	ret = fcntl(pipefd[1], F_GETFL);
 	if (ret == -1) {
-		usbi_dbg("Failed to get pipe fd flags: %d", errno);
+		usbi_err(NULL, "failed to get pipe fd status flags (%d)", errno);
 		goto err_close_pipe;
 	}
 	ret = fcntl(pipefd[1], F_SETFL, ret | O_NONBLOCK);
-	if (ret != 0) {
-		usbi_dbg("Failed to set non-blocking on new pipe: %d", errno);
+	if (ret == -1) {
+		usbi_err(NULL, "failed to set pipe fd status flags (%d)", errno);
 		goto err_close_pipe;
 	}
 
 	return 0;
 
 err_close_pipe:
-	usbi_close(pipefd[0]);
-	usbi_close(pipefd[1]);
+	close(pipefd[0]);
+	close(pipefd[1]);
 	return ret;
 }

+ 0 - 0
vendor/github.com/karalabe/hid/libusb/libusb/os/poll_posix.h → vendor/github.com/karalabe/usb/libusb/libusb/os/poll_posix.h


+ 364 - 0
vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.c

@@ -0,0 +1,364 @@
+/*
+ * poll_windows: poll compatibility wrapper for Windows
+ * Copyright © 2017 Chris Dickens <christopher.a.dickens@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+/*
+ * poll() and pipe() Windows compatibility layer for libusb 1.0
+ *
+ * The way this layer works is by using OVERLAPPED with async I/O transfers, as
+ * OVERLAPPED have an associated event which is flagged for I/O completion.
+ *
+ * For USB pollable async I/O, you would typically:
+ * - obtain a Windows HANDLE to a file or device that has been opened in
+ *   OVERLAPPED mode
+ * - call usbi_create_fd with this handle to obtain a custom fd.
+ * - leave the core functions call the poll routine and flag POLLIN/POLLOUT
+ *
+ * The pipe pollable synchronous I/O works using the overlapped event associated
+ * with a fake pipe. The read/write functions are only meant to be used in that
+ * context.
+ */
+#include <config.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "libusbi.h"
+#include "windows_common.h"
+
+// public fd data
+const struct winfd INVALID_WINFD = { -1, NULL };
+
+// private data
+struct file_descriptor {
+	enum fd_type { FD_TYPE_PIPE, FD_TYPE_TRANSFER } type;
+	OVERLAPPED overlapped;
+};
+
+static usbi_mutex_static_t fd_table_lock = USBI_MUTEX_INITIALIZER;
+static struct file_descriptor *fd_table[MAX_FDS];
+
+static struct file_descriptor *create_fd(enum fd_type type)
+{
+	struct file_descriptor *fd = calloc(1, sizeof(*fd));
+	if (fd == NULL)
+		return NULL;
+	fd->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+	if (fd->overlapped.hEvent == NULL) {
+		free(fd);
+		return NULL;
+	}
+	fd->type = type;
+	return fd;
+}
+
+static void free_fd(struct file_descriptor *fd)
+{
+	CloseHandle(fd->overlapped.hEvent);
+	free(fd);
+}
+
+/*
+ * Create both an fd and an OVERLAPPED, so that it can be used with our
+ * polling function
+ * The handle MUST support overlapped transfers (usually requires CreateFile
+ * with FILE_FLAG_OVERLAPPED)
+ * Return a pollable file descriptor struct, or INVALID_WINFD on error
+ *
+ * Note that the fd returned by this function is a per-transfer fd, rather
+ * than a per-session fd and cannot be used for anything else but our
+ * custom functions.
+ * if you plan to do R/W on the same handle, you MUST create 2 fds: one for
+ * read and one for write. Using a single R/W fd is unsupported and will
+ * produce unexpected results
+ */
+struct winfd usbi_create_fd(void)
+{
+	struct file_descriptor *fd;
+	struct winfd wfd;
+
+	fd = create_fd(FD_TYPE_TRANSFER);
+	if (fd == NULL)
+		return INVALID_WINFD;
+
+	usbi_mutex_static_lock(&fd_table_lock);
+	for (wfd.fd = 0; wfd.fd < MAX_FDS; wfd.fd++) {
+		if (fd_table[wfd.fd] != NULL)
+			continue;
+		fd_table[wfd.fd] = fd;
+		break;
+	}
+	usbi_mutex_static_unlock(&fd_table_lock);
+
+	if (wfd.fd == MAX_FDS) {
+		free_fd(fd);
+		return INVALID_WINFD;
+	}
+
+	wfd.overlapped = &fd->overlapped;
+
+	return wfd;
+}
+
+static int check_pollfds(struct pollfd *fds, unsigned int nfds,
+	HANDLE *wait_handles, DWORD *nb_wait_handles)
+{
+	struct file_descriptor *fd;
+	unsigned int n;
+	int nready = 0;
+
+	usbi_mutex_static_lock(&fd_table_lock);
+
+	for (n = 0; n < nfds; ++n) {
+		fds[n].revents = 0;
+
+		// Keep it simple - only allow either POLLIN *or* POLLOUT
+		assert((fds[n].events == POLLIN) || (fds[n].events == POLLOUT));
+		if ((fds[n].events != POLLIN) && (fds[n].events != POLLOUT)) {
+			fds[n].revents = POLLNVAL;
+			nready++;
+			continue;
+		}
+
+		if ((fds[n].fd >= 0) && (fds[n].fd < MAX_FDS))
+			fd = fd_table[fds[n].fd];
+		else
+			fd = NULL;
+
+		assert(fd != NULL);
+		if (fd == NULL) {
+			fds[n].revents = POLLNVAL;
+			nready++;
+			continue;
+		}
+
+		if (HasOverlappedIoCompleted(&fd->overlapped)
+				&& (WaitForSingleObject(fd->overlapped.hEvent, 0) == WAIT_OBJECT_0)) {
+			fds[n].revents = fds[n].events;
+			nready++;
+		} else if (wait_handles != NULL) {
+			if (*nb_wait_handles == MAXIMUM_WAIT_OBJECTS) {
+				usbi_warn(NULL, "too many HANDLEs to wait on");
+				continue;
+			}
+			wait_handles[*nb_wait_handles] = fd->overlapped.hEvent;
+			(*nb_wait_handles)++;
+		}
+	}
+
+	usbi_mutex_static_unlock(&fd_table_lock);
+
+	return nready;
+}
+/*
+ * POSIX poll equivalent, using Windows OVERLAPPED
+ * Currently, this function only accepts one of POLLIN or POLLOUT per fd
+ * (but you can create multiple fds from the same handle for read and write)
+ */
+int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
+{
+	HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS];
+	DWORD nb_wait_handles = 0;
+	DWORD ret;
+	int nready;
+
+	nready = check_pollfds(fds, nfds, wait_handles, &nb_wait_handles);
+
+	// If nothing was triggered, wait on all fds that require it
+	if ((nready == 0) && (nb_wait_handles != 0) && (timeout != 0)) {
+		ret = WaitForMultipleObjects(nb_wait_handles, wait_handles,
+			FALSE, (timeout < 0) ? INFINITE : (DWORD)timeout);
+		if (ret < (WAIT_OBJECT_0 + nb_wait_handles)) {
+			nready = check_pollfds(fds, nfds, NULL, NULL);
+		} else if (ret != WAIT_TIMEOUT) {
+			if (ret == WAIT_FAILED)
+				usbi_err(NULL, "WaitForMultipleObjects failed: %u", (unsigned int)GetLastError());
+			nready = -1;
+		}
+	}
+
+	return nready;
+}
+
+/*
+ * close a fake file descriptor
+ */
+int usbi_close(int _fd)
+{
+	struct file_descriptor *fd;
+
+	if (_fd < 0 || _fd >= MAX_FDS)
+		goto err_badfd;
+
+	usbi_mutex_static_lock(&fd_table_lock);
+	fd = fd_table[_fd];
+	fd_table[_fd] = NULL;
+	usbi_mutex_static_unlock(&fd_table_lock);
+
+	if (fd == NULL)
+		goto err_badfd;
+
+	if (fd->type == FD_TYPE_PIPE) {
+		// InternalHigh is our reference count
+		fd->overlapped.InternalHigh--;
+		if (fd->overlapped.InternalHigh == 0)
+			free_fd(fd);
+	} else {
+		free_fd(fd);
+	}
+
+	return 0;
+
+err_badfd:
+	errno = EBADF;
+	return -1;
+}
+
+/*
+* Create a fake pipe.
+* As libusb only uses pipes for signaling, all we need from a pipe is an
+* event. To that extent, we create a single wfd and overlapped as a means
+* to access that event.
+*/
+int usbi_pipe(int filedes[2])
+{
+	struct file_descriptor *fd;
+	int r_fd = -1, w_fd = -1;
+	int i;
+
+	fd = create_fd(FD_TYPE_PIPE);
+	if (fd == NULL) {
+		errno = ENOMEM;
+		return -1;
+	}
+
+	// Use InternalHigh as a reference count
+	fd->overlapped.Internal = STATUS_PENDING;
+	fd->overlapped.InternalHigh = 2;
+
+	usbi_mutex_static_lock(&fd_table_lock);
+	do {
+		for (i = 0; i < MAX_FDS; i++) {
+			if (fd_table[i] != NULL)
+				continue;
+			if (r_fd == -1) {
+				r_fd = i;
+			} else if (w_fd == -1) {
+				w_fd = i;
+				break;
+			}
+		}
+
+		if (i == MAX_FDS)
+			break;
+
+		fd_table[r_fd] = fd;
+		fd_table[w_fd] = fd;
+
+	} while (0);
+	usbi_mutex_static_unlock(&fd_table_lock);
+
+	if (i == MAX_FDS) {
+		free_fd(fd);
+		errno = EMFILE;
+		return -1;
+	}
+
+	filedes[0] = r_fd;
+	filedes[1] = w_fd;
+
+	return 0;
+}
+
+/*
+ * synchronous write for fake "pipe" signaling
+ */
+ssize_t usbi_write(int fd, const void *buf, size_t count)
+{
+	int error = EBADF;
+
+	UNUSED(buf);
+
+	if (fd < 0 || fd >= MAX_FDS)
+		goto err_out;
+
+	if (count != sizeof(unsigned char)) {
+		usbi_err(NULL, "this function should only used for signaling");
+		error = EINVAL;
+		goto err_out;
+	}
+
+	usbi_mutex_static_lock(&fd_table_lock);
+	if ((fd_table[fd] != NULL) && (fd_table[fd]->type == FD_TYPE_PIPE)) {
+		assert(fd_table[fd]->overlapped.Internal == STATUS_PENDING);
+		assert(fd_table[fd]->overlapped.InternalHigh == 2);
+		fd_table[fd]->overlapped.Internal = STATUS_WAIT_0;
+		SetEvent(fd_table[fd]->overlapped.hEvent);
+		error = 0;
+	}
+	usbi_mutex_static_unlock(&fd_table_lock);
+
+	if (error)
+		goto err_out;
+
+	return sizeof(unsigned char);
+
+err_out:
+	errno = error;
+	return -1;
+}
+
+/*
+ * synchronous read for fake "pipe" signaling
+ */
+ssize_t usbi_read(int fd, void *buf, size_t count)
+{
+	int error = EBADF;
+
+	UNUSED(buf);
+
+	if (fd < 0 || fd >= MAX_FDS)
+		goto err_out;
+
+	if (count != sizeof(unsigned char)) {
+		usbi_err(NULL, "this function should only used for signaling");
+		error = EINVAL;
+		goto err_out;
+	}
+
+	usbi_mutex_static_lock(&fd_table_lock);
+	if ((fd_table[fd] != NULL) && (fd_table[fd]->type == FD_TYPE_PIPE)) {
+		assert(fd_table[fd]->overlapped.Internal == STATUS_WAIT_0);
+		assert(fd_table[fd]->overlapped.InternalHigh == 2);
+		fd_table[fd]->overlapped.Internal = STATUS_PENDING;
+		ResetEvent(fd_table[fd]->overlapped.hEvent);
+		error = 0;
+	}
+	usbi_mutex_static_unlock(&fd_table_lock);
+
+	if (error)
+		goto err_out;
+
+	return sizeof(unsigned char);
+
+err_out:
+	errno = error;
+	return -1;
+}

+ 9 - 43
vendor/github.com/karalabe/hid/libusb/libusb/os/poll_windows.h → vendor/github.com/karalabe/usb/libusb/libusb/os/poll_windows.h

@@ -2,6 +2,7 @@
  * Windows compat: POSIX compatibility wrapper
  * Copyright © 2012-2013 RealVNC Ltd.
  * Copyright © 2009-2010 Pete Batard <pete@akeo.ie>
+ * Copyright © 2016-2018 Chris Dickens <christopher.a.dickens@gmail.com>
  * With contributions from Michael Plante, Orin Eman et al.
  * Parts of poll implementation from libusb-win32, by Stephan Meyer et al.
  *
@@ -40,21 +41,6 @@
 
 #define DUMMY_HANDLE ((HANDLE)(LONG_PTR)-2)
 
-/* Windows versions */
-enum windows_version {
-	WINDOWS_CE = -2,
-	WINDOWS_UNDEFINED = -1,
-	WINDOWS_UNSUPPORTED = 0,
-	WINDOWS_XP = 0x51,
-	WINDOWS_2003 = 0x52,	// Also XP x64
-	WINDOWS_VISTA = 0x60,
-	WINDOWS_7 = 0x61,
-	WINDOWS_8 = 0x62,
-	WINDOWS_8_1_OR_LATER = 0x63,
-	WINDOWS_MAX
-};
-extern int windows_version;
-
 #define MAX_FDS     256
 
 #define POLLIN      0x0001    /* There is data to read */
@@ -65,46 +51,26 @@ extern int windows_version;
 #define POLLNVAL    0x0020    /* Invalid request: fd not open */
 
 struct pollfd {
-    int fd;           /* file descriptor */
-    short events;     /* requested events */
-    short revents;    /* returned events */
-};
-
-// access modes
-enum rw_type {
-	RW_NONE,
-	RW_READ,
-	RW_WRITE,
+	int fd;		/* file descriptor */
+	short events;	/* requested events */
+	short revents;	/* returned events */
 };
 
-// fd struct that can be used for polling on Windows
-typedef int cancel_transfer(struct usbi_transfer *itransfer);
-
 struct winfd {
-	int fd;							// what's exposed to libusb core
-	HANDLE handle;					// what we need to attach overlapped to the I/O op, so we can poll it
-	OVERLAPPED* overlapped;			// what will report our I/O status
-	struct usbi_transfer *itransfer;		// Associated transfer, or NULL if completed
-	cancel_transfer *cancel_fn;		// Function pointer to cancel transfer API
-	enum rw_type rw;				// I/O transfer direction: read *XOR* write (NOT BOTH)
+	int fd;				// what's exposed to libusb core
+	OVERLAPPED *overlapped;		// what will report our I/O status
 };
+
 extern const struct winfd INVALID_WINFD;
 
+struct winfd usbi_create_fd(void);
+
 int usbi_pipe(int pipefd[2]);
 int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout);
 ssize_t usbi_write(int fd, const void *buf, size_t count);
 ssize_t usbi_read(int fd, void *buf, size_t count);
 int usbi_close(int fd);
 
-void init_polling(void);
-void exit_polling(void);
-struct winfd usbi_create_fd(HANDLE handle, int access_mode, 
-	struct usbi_transfer *transfer, cancel_transfer *cancel_fn);
-void usbi_free_fd(struct winfd* winfd);
-struct winfd fd_to_winfd(int fd);
-struct winfd handle_to_winfd(HANDLE handle);
-struct winfd overlapped_to_winfd(OVERLAPPED* overlapped);
-
 /*
  * Timeval operations
  */

+ 475 - 92
vendor/github.com/karalabe/hid/libusb/libusb/os/sunos_usb.c → vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.c

@@ -21,6 +21,7 @@
 
 #include <sys/time.h>
 #include <sys/types.h>
+#include <sys/list.h>
 #include <sys/stat.h>
 #include <strings.h>
 #include <errno.h>
@@ -28,21 +29,34 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <wait.h>
 #include <unistd.h>
 #include <aio.h>
 #include <libdevinfo.h>
+#include <sys/nvpair.h>
+#include <sys/devctl.h>
 #include <sys/usb/clients/ugen/usb_ugen.h>
+#include <errno.h>
 #include <sys/usb/usba.h>
 #include <sys/pci.h>
 
 #include "libusbi.h"
 #include "sunos_usb.h"
 
+#define UPDATEDRV_PATH	"/usr/sbin/update_drv"
+#define UPDATEDRV	"update_drv"
+
+typedef list_t string_list_t;
+typedef struct string_node {
+	char		*string;
+	list_node_t	link;
+} string_node_t;
+
 /*
  * Backend functions
  */
 static int sunos_init(struct libusb_context *);
-static void sunos_exit(void);
+static void sunos_exit(struct libusb_context *);
 static int sunos_get_device_list(struct libusb_context *,
     struct discovered_devs **);
 static int sunos_open(struct libusb_device_handle *);
@@ -67,6 +81,162 @@ static int sunos_cancel_transfer(struct usbi_transfer *);
 static void sunos_clear_transfer_priv(struct usbi_transfer *);
 static int sunos_handle_transfer_completion(struct usbi_transfer *);
 static int sunos_clock_gettime(int, struct timespec *);
+static int sunos_kernel_driver_active(struct libusb_device_handle *, int interface);
+static int sunos_detach_kernel_driver (struct libusb_device_handle *dev, int interface_number);
+static int sunos_attach_kernel_driver (struct libusb_device_handle *dev, int interface_number);
+static int sunos_usb_open_ep0(sunos_dev_handle_priv_t *hpriv, sunos_dev_priv_t *dpriv);
+static int sunos_usb_ioctl(struct libusb_device *dev, int cmd);
+
+static struct devctl_iocdata iocdata;
+static int sunos_get_link(di_devlink_t devlink, void *arg)
+{
+	walk_link_t *larg = (walk_link_t *)arg;
+	const char *p;
+	const char *q;
+
+	if (larg->path) {
+		char *content = (char *)di_devlink_content(devlink);
+		char *start = strstr(content, "/devices/");
+		start += strlen("/devices");
+		usbi_dbg("%s", start);
+
+		/* line content must have minor node */
+		if (start == NULL ||
+		    strncmp(start, larg->path, larg->len) != 0 ||
+		    start[larg->len] != ':')
+			return (DI_WALK_CONTINUE);
+	}
+
+	p = di_devlink_path(devlink);
+	q = strrchr(p, '/');
+	usbi_dbg("%s", q);
+
+	*(larg->linkpp) = strndup(p, strlen(p) - strlen(q));
+
+	return (DI_WALK_TERMINATE);
+}
+
+
+static int sunos_physpath_to_devlink(
+	const char *node_path, const char *match, char **link_path)
+{
+	walk_link_t larg;
+	di_devlink_handle_t hdl;
+
+	*link_path = NULL;
+	larg.linkpp = link_path;
+	if ((hdl = di_devlink_init(NULL, 0)) == NULL) {
+		usbi_dbg("di_devlink_init failure");
+		return (-1);
+	}
+
+	larg.len = strlen(node_path);
+	larg.path = (char *)node_path;
+
+	(void) di_devlink_walk(hdl, match, NULL, DI_PRIMARY_LINK,
+	    (void *)&larg, sunos_get_link);
+
+	(void) di_devlink_fini(&hdl);
+
+	if (*link_path == NULL) {
+		usbi_dbg("there is no devlink for this path");
+		return (-1);
+	}
+
+	return 0;
+}
+
+static int
+sunos_usb_ioctl(struct libusb_device *dev, int cmd)
+{
+	int fd;
+	nvlist_t *nvlist;
+	char *end;
+	char *phypath;
+	char *hubpath;
+	char path_arg[PATH_MAX];
+	sunos_dev_priv_t *dpriv;
+	devctl_ap_state_t devctl_ap_state;
+
+	dpriv = (sunos_dev_priv_t *)dev->os_priv;
+	phypath = dpriv->phypath;
+
+	end = strrchr(phypath, '/');
+	if (end == NULL)
+		return (-1);
+	hubpath = strndup(phypath, end - phypath);
+	if (hubpath == NULL)
+		return (-1);
+
+	end = strrchr(hubpath, '@');
+	if (end == NULL) {
+		free(hubpath);
+		return (-1);
+	}
+	end++;
+	usbi_dbg("unitaddr: %s", end);
+
+	nvlist_alloc(&nvlist, NV_UNIQUE_NAME_TYPE, KM_NOSLEEP);
+	nvlist_add_int32(nvlist, "port", dev->port_number);
+	//find the hub path
+	snprintf(path_arg, sizeof(path_arg), "/devices%s:hubd", hubpath);
+	usbi_dbg("ioctl hub path: %s", path_arg);
+
+	fd = open(path_arg, O_RDONLY);
+	if (fd < 0) {
+		usbi_err(DEVICE_CTX(dev), "open failed: %d (%s)", errno, strerror(errno));
+		nvlist_free(nvlist);
+		free(hubpath);
+		return (-1);
+	}
+
+	memset(&iocdata, 0, sizeof(iocdata));
+	memset(&devctl_ap_state, 0, sizeof(devctl_ap_state));
+
+	nvlist_pack(nvlist, (char **)&iocdata.nvl_user, &iocdata.nvl_usersz, NV_ENCODE_NATIVE, 0);
+
+	iocdata.cmd = DEVCTL_AP_GETSTATE;
+	iocdata.flags = 0;
+	iocdata.c_nodename = "hub";
+	iocdata.c_unitaddr = end;
+	iocdata.cpyout_buf = &devctl_ap_state;
+	usbi_dbg("%p, %d", iocdata.nvl_user, iocdata.nvl_usersz);
+
+	errno = 0;
+	if (ioctl(fd, DEVCTL_AP_GETSTATE, &iocdata) == -1) {
+		usbi_err(DEVICE_CTX(dev), "ioctl failed: fd %d, cmd %x, errno %d (%s)",
+			 fd, DEVCTL_AP_GETSTATE, errno, strerror(errno));
+	} else {
+		usbi_dbg("dev rstate: %d", devctl_ap_state.ap_rstate);
+		usbi_dbg("dev ostate: %d", devctl_ap_state.ap_ostate);
+	}
+
+	errno = 0;
+	iocdata.cmd = cmd;
+	if (ioctl(fd, (int)cmd, &iocdata) != 0) {
+		usbi_err(DEVICE_CTX(dev), "ioctl failed: fd %d, cmd %x, errno %d (%s)",
+			 fd, cmd, errno, strerror(errno));
+		sleep(2);
+	}
+
+	close(fd);
+	free(iocdata.nvl_user);
+	nvlist_free(nvlist);
+	free(hubpath);
+
+	return (-errno);
+}
+
+static int
+sunos_kernel_driver_active(struct libusb_device_handle *dev, int interface)
+{
+	sunos_dev_priv_t *dpriv;
+	dpriv = (sunos_dev_priv_t *)dev->dev->os_priv;
+
+	usbi_dbg("%s", dpriv->ugenpath);
+
+	return (dpriv->ugenpath == NULL);
+}
 
 /*
  * Private functions
@@ -79,11 +249,229 @@ static int sunos_init(struct libusb_context *ctx)
 	return (LIBUSB_SUCCESS);
 }
 
-static void sunos_exit(void)
+static void sunos_exit(struct libusb_context *ctx)
 {
 	usbi_dbg("");
 }
 
+static string_list_t *
+sunos_new_string_list(void)
+{
+	string_list_t *list;
+
+	list = calloc(1, sizeof(*list));
+	if (list != NULL)
+		list_create(list, sizeof(string_node_t),
+			    offsetof(string_node_t, link));
+
+	return (list);
+}
+
+static int
+sunos_append_to_string_list(string_list_t *list, const char *arg)
+{
+	string_node_t *np;
+
+	np = calloc(1, sizeof(*np));
+	if (!np)
+		return (-1);
+
+	np->string = strdup(arg);
+	if (!np->string) {
+		free(np);
+		return (-1);
+	}
+
+	list_insert_tail(list, np);
+
+	return (0);
+}
+
+static void
+sunos_free_string_list(string_list_t *list)
+{
+	string_node_t *np;
+
+	while ((np = list_remove_head(list)) != NULL) {
+		free(np->string);
+		free(np);
+	}
+
+	free(list);
+}
+
+static char **
+sunos_build_argv_list(string_list_t *list)
+{
+	char **argv_list;
+	string_node_t *np;
+	int n;
+
+	n = 1; /* Start at 1 for NULL terminator */
+	for (np = list_head(list); np != NULL; np = list_next(list, np))
+		n++;
+
+	argv_list = calloc(n, sizeof(char *));
+	if (argv_list == NULL)
+		return NULL;
+
+	n = 0;
+	for (np = list_head(list); np != NULL; np = list_next(list, np))
+		argv_list[n++] = np->string;
+
+	return (argv_list);
+}
+
+
+static int
+sunos_exec_command(struct libusb_context *ctx, const char *path,
+	string_list_t *list)
+{
+	pid_t pid;
+	int status;
+	int waitstat;
+	int exit_status;
+	char **argv_list;
+
+	argv_list = sunos_build_argv_list(list);
+	if (argv_list == NULL)
+		return (-1);
+
+	pid = fork();
+	if (pid == 0) {
+		/* child */
+		execv(path, argv_list);
+		_exit(127);
+	} else if (pid > 0) {
+		/* parent */
+		do {
+			waitstat = waitpid(pid, &status, 0);
+		} while ((waitstat == -1 && errno == EINTR) ||
+			 (waitstat == 0 && !WIFEXITED(status) && !WIFSIGNALED(status)));
+
+		if (waitstat == 0) {
+			if (WIFEXITED(status))
+				exit_status = WEXITSTATUS(status);
+			else
+				exit_status = WTERMSIG(status);
+		} else {
+			usbi_err(ctx, "waitpid failed: errno %d (%s)", errno, strerror(errno));
+			exit_status = -1;
+		}
+	} else {
+		/* fork failed */
+		usbi_err(ctx, "fork failed: errno %d (%s)", errno, strerror(errno));
+		exit_status = -1;
+	}
+
+	free(argv_list);
+
+	return (exit_status);
+}
+
+static int
+sunos_detach_kernel_driver(struct libusb_device_handle *dev_handle,
+	int interface_number)
+{
+	struct libusb_context *ctx = HANDLE_CTX(dev_handle);
+	string_list_t *list;
+	char path_arg[PATH_MAX];
+	sunos_dev_priv_t *dpriv;
+	int r;
+
+	dpriv = (sunos_dev_priv_t *)dev_handle->dev->os_priv;
+	snprintf(path_arg, sizeof(path_arg), "\'\"%s\"\'", dpriv->phypath);
+	usbi_dbg("%s", path_arg);
+
+	list = sunos_new_string_list();
+	if (list == NULL)
+		return (LIBUSB_ERROR_NO_MEM);
+
+	/* attach ugen driver */
+	r = 0;
+	r |= sunos_append_to_string_list(list, UPDATEDRV);
+	r |= sunos_append_to_string_list(list, "-a"); /* add rule */
+	r |= sunos_append_to_string_list(list, "-i"); /* specific device */
+	r |= sunos_append_to_string_list(list, path_arg); /* physical path */
+	r |= sunos_append_to_string_list(list, "ugen");
+	if (r) {
+		sunos_free_string_list(list);
+		return (LIBUSB_ERROR_NO_MEM);
+	}
+
+	r = sunos_exec_command(ctx, UPDATEDRV_PATH, list);
+	sunos_free_string_list(list);
+	if (r < 0)
+		return (LIBUSB_ERROR_OTHER);
+
+	/* reconfigure the driver node */
+	r = 0;
+	r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_DISCONNECT);
+	r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE);
+	if (r)
+		usbi_warn(HANDLE_CTX(dev_handle), "one or more ioctls failed");
+
+	snprintf(path_arg, sizeof(path_arg), "^usb/%x.%x", dpriv->dev_descr.idVendor,
+	    dpriv->dev_descr.idProduct);
+	sunos_physpath_to_devlink(dpriv->phypath, path_arg, &dpriv->ugenpath);
+
+	if (access(dpriv->ugenpath, F_OK) == -1) {
+		usbi_err(HANDLE_CTX(dev_handle), "fail to detach kernel driver");
+		return (LIBUSB_ERROR_IO);
+	}
+
+	return sunos_usb_open_ep0((sunos_dev_handle_priv_t *)dev_handle->os_priv, dpriv);
+}
+
+static int
+sunos_attach_kernel_driver(struct libusb_device_handle *dev_handle,
+	int interface_number)
+{
+	struct libusb_context *ctx = HANDLE_CTX(dev_handle);
+	string_list_t *list;
+	char path_arg[PATH_MAX];
+	sunos_dev_priv_t *dpriv;
+	int r;
+
+	/* we open the dev in detach driver, so we need close it first. */
+	sunos_close(dev_handle);
+
+	dpriv = (sunos_dev_priv_t *)dev_handle->dev->os_priv;
+	snprintf(path_arg, sizeof(path_arg), "\'\"%s\"\'", dpriv->phypath);
+	usbi_dbg("%s", path_arg);
+
+	list = sunos_new_string_list();
+	if (list == NULL)
+		return (LIBUSB_ERROR_NO_MEM);
+
+	/* detach ugen driver */
+	r = 0;
+	r |= sunos_append_to_string_list(list, UPDATEDRV);
+	r |= sunos_append_to_string_list(list, "-d"); /* add rule */
+	r |= sunos_append_to_string_list(list, "-i"); /* specific device */
+	r |= sunos_append_to_string_list(list, path_arg); /* physical path */
+	r |= sunos_append_to_string_list(list, "ugen");
+	if (r) {
+		sunos_free_string_list(list);
+		return (LIBUSB_ERROR_NO_MEM);
+	}
+
+	r = sunos_exec_command(ctx, UPDATEDRV_PATH, list);
+	sunos_free_string_list(list);
+	if (r < 0)
+		return (LIBUSB_ERROR_OTHER);
+
+	/* reconfigure the driver node */
+	r = 0;
+	r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE);
+	r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_DISCONNECT);
+	r |= sunos_usb_ioctl(dev_handle->dev, DEVCTL_AP_CONFIGURE);
+	if (r)
+		usbi_warn(HANDLE_CTX(dev_handle), "one or more ioctls failed");
+
+	return 0;
+}
+
 static int
 sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev)
 {
@@ -93,6 +481,7 @@ sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev)
 	uint8_t	*rdata;
 	struct libusb_device_descriptor	*descr;
 	sunos_dev_priv_t	*dpriv = (sunos_dev_priv_t *)dev->os_priv;
+	char	match_str[PATH_MAX];
 
 	/* Device descriptors */
 	proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node,
@@ -137,7 +526,11 @@ sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev)
 	phypath = di_devfs_path(node);
 	if (phypath) {
 		dpriv->phypath = strdup(phypath);
+		snprintf(match_str, sizeof(match_str), "^usb/%x.%x", dpriv->dev_descr.idVendor, dpriv->dev_descr.idProduct);
+		usbi_dbg("match is %s", match_str);
+		sunos_physpath_to_devlink(dpriv->phypath, match_str,  &dpriv->ugenpath);
 		di_devfs_path_free(phypath);
+
 	} else {
 		free(dpriv->raw_cfgdescr);
 
@@ -170,111 +563,98 @@ sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev)
 	return (LIBUSB_SUCCESS);
 }
 
-
 static int
 sunos_add_devices(di_devlink_t link, void *arg)
 {
 	struct devlink_cbarg	*largs = (struct devlink_cbarg *)arg;
 	struct node_args	*nargs;
-	di_node_t		myself, pnode;
+	di_node_t		myself, dn;
 	uint64_t		session_id = 0;
-	uint16_t		bdf = 0;
+	uint64_t		sid = 0;
+	uint64_t		bdf = 0;
 	struct libusb_device	*dev;
 	sunos_dev_priv_t	*devpriv;
-	const char		*path, *newpath;
-	int			 n, i;
+	int			n;
+	int			i = 0;
 	int			*addr_prop;
 	uint8_t			bus_number = 0;
+	uint32_t * 		regbuf = NULL;
+	uint32_t		reg;
 
 	nargs = (struct node_args *)largs->nargs;
 	myself = largs->myself;
-	if (nargs->last_ugenpath) {
-		/* the same node's links */
-		return (DI_WALK_CONTINUE);
-	}
 
 	/*
 	 * Construct session ID.
-	 * session ID = ...parent hub addr|hub addr|dev addr.
+	 * session ID = dev_addr | hub addr |parent hub addr|...|root hub bdf
+	 * 		8 bits       8bits          8 bits               16bits
 	 */
-	pnode = myself;
-	i = 0;
-	while (pnode != DI_NODE_NIL) {
-		if (di_prop_exists(DDI_DEV_T_ANY, pnode, "root-hub") == 1) {
-			/* walk to root */
-			uint32_t *regbuf = NULL;
-			uint32_t reg;
-
-			n = di_prop_lookup_ints(DDI_DEV_T_ANY, pnode, "reg",
-			    (int **)&regbuf);
-			reg = regbuf[0];
-			bdf = (PCI_REG_BUS_G(reg) << 8) |
-			    (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg);
-			session_id |= (bdf << i * 8);
-
-			/* same as 'unit-address' property */
-			bus_number =
-			    (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg);
-
-			usbi_dbg("device bus address=%s:%x",
-			    di_bus_addr(pnode), bus_number);
+	if (myself == DI_NODE_NIL)
+		return (DI_WALK_CONTINUE);
 
-			break;
-		}
+	dn = myself;
+	/* find the root hub */
+	while (di_prop_exists(DDI_DEV_T_ANY, dn, "root-hub") != 1) {
+		usbi_dbg("find_root_hub:%s", di_devfs_path(dn));
+		n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn,
+				"assigned-address", &addr_prop);
+		session_id |= ((addr_prop[0] & 0xff) << i++ * 8);
+		dn = di_parent_node(dn);
+	}
 
+	/* dn is the root hub node */
+	n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "reg", (int **)&regbuf);
+	reg = regbuf[0];
+	bdf = (PCI_REG_BUS_G(reg) << 8) | (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg);
+	/* bdf must larger than i*8 bits */
+	session_id |= (bdf << i * 8);
+	bus_number = (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg);
+
+	usbi_dbg("device bus address=%s:%x, name:%s",
+	    di_bus_addr(myself), bus_number, di_node_name(dn));
+	usbi_dbg("session id org:%lx", session_id);
+
+	/* dn is the usb device */
+	for (dn = di_child_node(myself); dn != DI_NODE_NIL; dn = di_sibling_node(dn)) {
+		usbi_dbg("device path:%s", di_devfs_path(dn));
+		/* skip hub devices, because its driver can not been unload */
+		if (di_prop_lookup_ints(DDI_DEV_T_ANY, dn, "usb-port-count", &addr_prop) != -1)
+			continue;
 		/* usb_addr */
-		n = di_prop_lookup_ints(DDI_DEV_T_ANY, pnode,
+		n = di_prop_lookup_ints(DDI_DEV_T_ANY, dn,
 		    "assigned-address", &addr_prop);
 		if ((n != 1) || (addr_prop[0] == 0)) {
 			usbi_dbg("cannot get valid usb_addr");
-
-			return (DI_WALK_CONTINUE);
+			continue;
 		}
 
-		session_id |= ((addr_prop[0] & 0xff) << i * 8);
-		if (++i > 7)
-			break;
+		sid = (session_id << 8) | (addr_prop[0] & 0xff) ;
+		usbi_dbg("session id %lx", sid);
 
-		pnode = di_parent_node(pnode);
-	}
-
-	path = di_devlink_path(link);
-	dev = usbi_get_device_by_session_id(nargs->ctx, session_id);
-	if (dev == NULL) {
-		dev = usbi_alloc_device(nargs->ctx, session_id);
+		dev = usbi_get_device_by_session_id(nargs->ctx, sid);
 		if (dev == NULL) {
-			usbi_dbg("can't alloc device");
-
-			return (DI_WALK_TERMINATE);
-		}
-		devpriv = (sunos_dev_priv_t *)dev->os_priv;
-		if ((newpath = strrchr(path, '/')) == NULL) {
-			libusb_unref_device(dev);
-
-			return (DI_WALK_TERMINATE);
-		}
-		devpriv->ugenpath = strndup(path, strlen(path) -
-		    strlen(newpath));
-		dev->bus_number = bus_number;
-
-		if (sunos_fill_in_dev_info(myself, dev) != LIBUSB_SUCCESS) {
-			libusb_unref_device(dev);
+			dev = usbi_alloc_device(nargs->ctx, sid);
+			if (dev == NULL) {
+				usbi_dbg("can't alloc device");
+				continue;
+			}
+			devpriv = (sunos_dev_priv_t *)dev->os_priv;
+			dev->bus_number = bus_number;
 
-			return (DI_WALK_TERMINATE);
-		}
-		if (usbi_sanitize_device(dev) < 0) {
-			libusb_unref_device(dev);
-			usbi_dbg("sanatize failed: ");
-			return (DI_WALK_TERMINATE);
+			if (sunos_fill_in_dev_info(dn, dev) != LIBUSB_SUCCESS) {
+				libusb_unref_device(dev);
+				usbi_dbg("get infomation fail");
+				continue;
+			}
+			if (usbi_sanitize_device(dev) < 0) {
+				libusb_unref_device(dev);
+				usbi_dbg("sanatize failed: ");
+				return (DI_WALK_TERMINATE);
+			}
+		} else {
+			devpriv = (sunos_dev_priv_t *)dev->os_priv;
+			usbi_dbg("Dev %s exists", devpriv->ugenpath);
 		}
-	} else {
-		usbi_dbg("Dev %s exists", path);
-	}
-
-	devpriv = (sunos_dev_priv_t *)dev->os_priv;
-	if (nargs->last_ugenpath == NULL) {
-		/* first device */
-		nargs->last_ugenpath = devpriv->ugenpath;
 
 		if (discovered_devs_append(*(nargs->discdevs), dev) == NULL) {
 			usbi_dbg("cannot append device");
@@ -285,11 +665,11 @@ sunos_add_devices(di_devlink_t link, void *arg)
 		 * hereafter. Front end or app should take care of their ref.
 		 */
 		libusb_unref_device(dev);
-	}
 
-	usbi_dbg("Device %s %s id=0x%llx, devcount:%d, bdf=%x",
-	    devpriv->ugenpath, path, (uint64_t)session_id,
-	    (*nargs->discdevs)->len, bdf);
+		usbi_dbg("Device %s %s id=0x%llx, devcount:%d, bdf=%x",
+		    devpriv->ugenpath, di_devfs_path(dn), (uint64_t)sid,
+		    (*nargs->discdevs)->len, bdf);
+	}
 
 	return (DI_WALK_CONTINUE);
 }
@@ -303,14 +683,14 @@ sunos_walk_minor_node_link(di_node_t node, void *args)
 	struct node_args *nargs = (struct node_args *)args;
 	di_devlink_handle_t devlink_hdl = nargs->dlink_hdl;
 
-	/* walk each minor to find ugen devices */
+	/* walk each minor to find usb devices */
         while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
                 minor_path = di_devfs_minor_path(minor);
                 arg.nargs = args;
 		arg.myself = node;
                 arg.minor = minor;
                 (void) di_devlink_walk(devlink_hdl,
-		    "^usb/[0-9a-f]+[.][0-9a-f]+", minor_path,
+		    "^usb/hub[0-9]+", minor_path,
 		    DI_PRIMARY_LINK, (void *)&arg, sunos_add_devices);
                 di_devfs_path_free(minor_path);
         }
@@ -496,7 +876,7 @@ sunos_check_device_and_status_open(struct libusb_device_handle *hdl,
 		usbi_dbg("can't find interface for endpoint 0x%02x",
 		    ep_addr);
 
-		return (LIBUSB_ERROR_ACCESS);
+		return (EACCES);
 	}
 
 	/* create filename */
@@ -603,6 +983,11 @@ sunos_open(struct libusb_device_handle *handle)
 		hpriv->eps[i].statfd = -1;
 	}
 
+	if (sunos_kernel_driver_active(handle, 0)) {
+		/* pretend we can open the device */
+		return (LIBUSB_SUCCESS);
+	}
+
 	if ((ret = sunos_usb_open_ep0(hpriv, dpriv)) != LIBUSB_SUCCESS) {
 		usbi_dbg("fail: %d", ret);
 		return (ret);
@@ -1010,9 +1395,7 @@ void
 sunos_destroy_device(struct libusb_device *dev)
 {
 	sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv;
-
-	usbi_dbg("");
-
+	usbi_dbg("destroy everyting");
 	free(dpriv->raw_cfgdescr);
 	free(dpriv->ugenpath);
 	free(dpriv->phypath);
@@ -1254,7 +1637,7 @@ sunos_usb_get_status(int fd)
 	return (status);
 }
 
-const struct usbi_os_backend sunos_backend = {
+const struct usbi_os_backend usbi_backend = {
         .name = "Solaris",
         .caps = 0,
         .init = sunos_init,
@@ -1276,9 +1659,9 @@ const struct usbi_os_backend sunos_backend = {
         .reset_device = sunos_reset_device, /* TODO */
         .alloc_streams = NULL,
         .free_streams = NULL,
-        .kernel_driver_active = NULL,
-        .detach_kernel_driver = NULL,
-        .attach_kernel_driver = NULL,
+        .kernel_driver_active = sunos_kernel_driver_active,
+        .detach_kernel_driver = sunos_detach_kernel_driver,
+        .attach_kernel_driver = sunos_attach_kernel_driver,
         .destroy_device = sunos_destroy_device,
         .submit_transfer = sunos_submit_transfer,
         .cancel_transfer = sunos_cancel_transfer,

+ 6 - 0
vendor/github.com/karalabe/hid/libusb/libusb/os/sunos_usb.h → vendor/github.com/karalabe/usb/libusb/libusb/os/sunos_usb.h

@@ -65,6 +65,12 @@ struct devlink_cbarg {
 	di_minor_t		minor;
 };
 
+typedef struct walk_link {
+	char *path;
+	int len;
+	char **linkpp;
+} walk_link_t;
+
 /* AIO callback args */
 struct aio_callback_args{
 	struct libusb_transfer *transfer;

+ 6 - 5
vendor/github.com/karalabe/hid/libusb/libusb/os/threads_posix.c → vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.c

@@ -29,7 +29,7 @@
 # include <unistd.h>
 # include <sys/syscall.h>
 #elif defined(__APPLE__)
-# include <mach/mach.h>
+# include <pthread.h>
 #elif defined(__CYGWIN__)
 # include <windows.h>
 #endif
@@ -43,7 +43,7 @@ int usbi_cond_timedwait(pthread_cond_t *cond,
 	struct timespec timeout;
 	int r;
 
-	r = usbi_backend->clock_gettime(USBI_CLOCK_REALTIME, &timeout);
+	r = usbi_backend.clock_gettime(USBI_CLOCK_REALTIME, &timeout);
 	if (r < 0)
 		return r;
 
@@ -59,7 +59,7 @@ int usbi_cond_timedwait(pthread_cond_t *cond,
 
 int usbi_get_tid(void)
 {
-	int ret = -1;
+	int ret;
 #if defined(__ANDROID__)
 	ret = gettid();
 #elif defined(__linux__)
@@ -69,10 +69,11 @@ int usbi_get_tid(void)
 	   real thread support. For 5.1 and earlier, -1 is returned. */
 	ret = syscall(SYS_getthrid);
 #elif defined(__APPLE__)
-	ret = mach_thread_self();
-	mach_port_deallocate(mach_task_self(), ret);
+	ret = (int)pthread_mach_thread_np(pthread_self());
 #elif defined(__CYGWIN__)
 	ret = GetCurrentThreadId();
+#else
+	ret = -1;
 #endif
 /* TODO: NetBSD thread ID support */
 	return ret;

+ 102 - 0
vendor/github.com/karalabe/usb/libusb/libusb/os/threads_posix.h

@@ -0,0 +1,102 @@
+/*
+ * libusb synchronization using POSIX Threads
+ *
+ * Copyright © 2010 Peter Stuge <peter@stuge.se>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LIBUSB_THREADS_POSIX_H
+#define LIBUSB_THREADS_POSIX_H
+
+#include <pthread.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#define USBI_MUTEX_INITIALIZER	PTHREAD_MUTEX_INITIALIZER
+typedef pthread_mutex_t usbi_mutex_static_t;
+static inline void usbi_mutex_static_lock(usbi_mutex_static_t *mutex)
+{
+	(void)pthread_mutex_lock(mutex);
+}
+static inline void usbi_mutex_static_unlock(usbi_mutex_static_t *mutex)
+{
+	(void)pthread_mutex_unlock(mutex);
+}
+
+typedef pthread_mutex_t usbi_mutex_t;
+static inline int usbi_mutex_init(usbi_mutex_t *mutex)
+{
+	return pthread_mutex_init(mutex, NULL);
+}
+static inline void usbi_mutex_lock(usbi_mutex_t *mutex)
+{
+	(void)pthread_mutex_lock(mutex);
+}
+static inline void usbi_mutex_unlock(usbi_mutex_t *mutex)
+{
+	(void)pthread_mutex_unlock(mutex);
+}
+static inline int usbi_mutex_trylock(usbi_mutex_t *mutex)
+{
+	return pthread_mutex_trylock(mutex);
+}
+static inline void usbi_mutex_destroy(usbi_mutex_t *mutex)
+{
+	(void)pthread_mutex_destroy(mutex);
+}
+
+typedef pthread_cond_t usbi_cond_t;
+static inline void usbi_cond_init(pthread_cond_t *cond)
+{
+	(void)pthread_cond_init(cond, NULL);
+}
+static inline int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex)
+{
+	return pthread_cond_wait(cond, mutex);
+}
+int usbi_cond_timedwait(usbi_cond_t *cond,
+	usbi_mutex_t *mutex, const struct timeval *tv);
+static inline void usbi_cond_broadcast(usbi_cond_t *cond)
+{
+	(void)pthread_cond_broadcast(cond);
+}
+static inline void usbi_cond_destroy(usbi_cond_t *cond)
+{
+	(void)pthread_cond_destroy(cond);
+}
+
+typedef pthread_key_t usbi_tls_key_t;
+static inline void usbi_tls_key_create(usbi_tls_key_t *key)
+{
+	(void)pthread_key_create(key, NULL);
+}
+static inline void *usbi_tls_key_get(usbi_tls_key_t key)
+{
+	return pthread_getspecific(key);
+}
+static inline void usbi_tls_key_set(usbi_tls_key_t key, void *ptr)
+{
+	(void)pthread_setspecific(key, ptr);
+}
+static inline void usbi_tls_key_delete(usbi_tls_key_t key)
+{
+	(void)pthread_key_delete(key);
+}
+
+int usbi_get_tid(void);
+
+#endif /* LIBUSB_THREADS_POSIX_H */

+ 126 - 0
vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.c

@@ -0,0 +1,126 @@
+/*
+ * libusb synchronization on Microsoft Windows
+ *
+ * Copyright © 2010 Michael Plante <michael.plante@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+
+#include <errno.h>
+
+#include "libusbi.h"
+
+struct usbi_cond_perthread {
+	struct list_head list;
+	HANDLE event;
+};
+
+void usbi_mutex_static_lock(usbi_mutex_static_t *mutex)
+{
+	while (InterlockedExchange(mutex, 1L) == 1L)
+		SleepEx(0, TRUE);
+}
+
+void usbi_cond_init(usbi_cond_t *cond)
+{
+	list_init(&cond->waiters);
+	list_init(&cond->not_waiting);
+}
+
+static int usbi_cond_intwait(usbi_cond_t *cond,
+	usbi_mutex_t *mutex, DWORD timeout_ms)
+{
+	struct usbi_cond_perthread *pos;
+	DWORD r;
+
+	// Same assumption as usbi_cond_broadcast() holds
+	if (list_empty(&cond->not_waiting)) {
+		pos = malloc(sizeof(*pos));
+		if (pos == NULL)
+			return ENOMEM; // This errno is not POSIX-allowed.
+		pos->event = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset.
+		if (pos->event == NULL) {
+			free(pos);
+			return ENOMEM;
+		}
+	} else {
+		pos = list_first_entry(&cond->not_waiting, struct usbi_cond_perthread, list);
+		list_del(&pos->list); // remove from not_waiting list.
+		// Ensure the event is clear before waiting
+		WaitForSingleObject(pos->event, 0);
+	}
+
+	list_add(&pos->list, &cond->waiters);
+
+	LeaveCriticalSection(mutex);
+	r = WaitForSingleObject(pos->event, timeout_ms);
+	EnterCriticalSection(mutex);
+
+	list_del(&pos->list);
+	list_add(&pos->list, &cond->not_waiting);
+
+	if (r == WAIT_OBJECT_0)
+		return 0;
+	else if (r == WAIT_TIMEOUT)
+		return ETIMEDOUT;
+	else
+		return EINVAL;
+}
+
+// N.B.: usbi_cond_*wait() can also return ENOMEM, even though pthread_cond_*wait cannot!
+int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex)
+{
+	return usbi_cond_intwait(cond, mutex, INFINITE);
+}
+
+int usbi_cond_timedwait(usbi_cond_t *cond,
+	usbi_mutex_t *mutex, const struct timeval *tv)
+{
+	DWORD millis;
+
+	millis = (DWORD)(tv->tv_sec * 1000) + (tv->tv_usec / 1000);
+	/* round up to next millisecond */
+	if (tv->tv_usec % 1000)
+		millis++;
+	return usbi_cond_intwait(cond, mutex, millis);
+}
+
+void usbi_cond_broadcast(usbi_cond_t *cond)
+{
+	// Assumes mutex is locked; this is not in keeping with POSIX spec, but
+	//   libusb does this anyway, so we simplify by not adding more sync
+	//   primitives to the CV definition!
+	struct usbi_cond_perthread *pos;
+
+	list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread)
+		SetEvent(pos->event);
+	// The wait function will remove its respective item from the list.
+}
+
+void usbi_cond_destroy(usbi_cond_t *cond)
+{
+	// This assumes no one is using this anymore.  The check MAY NOT BE safe.
+	struct usbi_cond_perthread *pos, *next;
+
+	if (!list_empty(&cond->waiters))
+		return; // (!see above!)
+	list_for_each_entry_safe(pos, next, &cond->not_waiting, list, struct usbi_cond_perthread) {
+		CloseHandle(pos->event);
+		list_del(&pos->list);
+		free(pos);
+	}
+}

+ 64 - 29
vendor/github.com/karalabe/hid/libusb/libusb/os/threads_windows.h → vendor/github.com/karalabe/usb/libusb/libusb/os/threads_windows.h

@@ -21,17 +21,40 @@
 #ifndef LIBUSB_THREADS_WINDOWS_H
 #define LIBUSB_THREADS_WINDOWS_H
 
-#define usbi_mutex_static_t	volatile LONG
-#define USBI_MUTEX_INITIALIZER	0
-
-#define usbi_mutex_t		HANDLE
+#define USBI_MUTEX_INITIALIZER	0L
+#ifdef _WIN32_WCE
+typedef LONG usbi_mutex_static_t;
+#else
+typedef volatile LONG usbi_mutex_static_t;
+#endif
+void usbi_mutex_static_lock(usbi_mutex_static_t *mutex);
+static inline void usbi_mutex_static_unlock(usbi_mutex_static_t *mutex)
+{
+	InterlockedExchange(mutex, 0L);
+}
 
-typedef struct usbi_cond {
-	// Every time a thread touches the CV, it winds up in one of these lists.
-	//   It stays there until the CV is destroyed, even if the thread terminates.
-	struct list_head waiters;
-	struct list_head not_waiting;
-} usbi_cond_t;
+typedef CRITICAL_SECTION usbi_mutex_t;
+static inline int usbi_mutex_init(usbi_mutex_t *mutex)
+{
+	InitializeCriticalSection(mutex);
+	return 0;
+}
+static inline void usbi_mutex_lock(usbi_mutex_t *mutex)
+{
+	EnterCriticalSection(mutex);
+}
+static inline void usbi_mutex_unlock(usbi_mutex_t *mutex)
+{
+	LeaveCriticalSection(mutex);
+}
+static inline int usbi_mutex_trylock(usbi_mutex_t *mutex)
+{
+	return !TryEnterCriticalSection(mutex);
+}
+static inline void usbi_mutex_destroy(usbi_mutex_t *mutex)
+{
+	DeleteCriticalSection(mutex);
+}
 
 // We *were* getting timespec from pthread.h:
 #if (!defined(HAVE_STRUCT_TIMESPEC) && !defined(_TIMESPEC_DEFINED))
@@ -45,32 +68,44 @@ struct timespec {
 
 // We *were* getting ETIMEDOUT from pthread.h:
 #ifndef ETIMEDOUT
-#  define ETIMEDOUT 10060     /* This is the value in winsock.h. */
+#define ETIMEDOUT	10060	/* This is the value in winsock.h. */
 #endif
 
-#define usbi_tls_key_t		DWORD
-
-int usbi_mutex_static_lock(usbi_mutex_static_t *mutex);
-int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex);
-
-int usbi_mutex_init(usbi_mutex_t *mutex);
-int usbi_mutex_lock(usbi_mutex_t *mutex);
-int usbi_mutex_unlock(usbi_mutex_t *mutex);
-int usbi_mutex_trylock(usbi_mutex_t *mutex);
-int usbi_mutex_destroy(usbi_mutex_t *mutex);
+typedef struct usbi_cond {
+	// Every time a thread touches the CV, it winds up in one of these lists.
+	//   It stays there until the CV is destroyed, even if the thread terminates.
+	struct list_head waiters;
+	struct list_head not_waiting;
+} usbi_cond_t;
 
-int usbi_cond_init(usbi_cond_t *cond);
+void usbi_cond_init(usbi_cond_t *cond);
 int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex);
 int usbi_cond_timedwait(usbi_cond_t *cond,
 	usbi_mutex_t *mutex, const struct timeval *tv);
-int usbi_cond_broadcast(usbi_cond_t *cond);
-int usbi_cond_destroy(usbi_cond_t *cond);
+void usbi_cond_broadcast(usbi_cond_t *cond);
+void usbi_cond_destroy(usbi_cond_t *cond);
 
-int usbi_tls_key_create(usbi_tls_key_t *key);
-void *usbi_tls_key_get(usbi_tls_key_t key);
-int usbi_tls_key_set(usbi_tls_key_t key, void *value);
-int usbi_tls_key_delete(usbi_tls_key_t key);
+typedef DWORD usbi_tls_key_t;
+static inline void usbi_tls_key_create(usbi_tls_key_t *key)
+{
+	*key = TlsAlloc();
+}
+static inline void *usbi_tls_key_get(usbi_tls_key_t key)
+{
+	return TlsGetValue(key);
+}
+static inline void usbi_tls_key_set(usbi_tls_key_t key, void *ptr)
+{
+	(void)TlsSetValue(key, ptr);
+}
+static inline void usbi_tls_key_delete(usbi_tls_key_t key)
+{
+	(void)TlsFree(key);
+}
 
-int usbi_get_tid(void);
+static inline int usbi_get_tid(void)
+{
+	return (int)GetCurrentThreadId();
+}
 
 #endif /* LIBUSB_THREADS_WINDOWS_H */

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.