Skip to content

Commit 68e1951

Browse files
committed
api/firmware/device: info use device status fields
Return initialized status from info() and use unlocked and initialized to set the device status appropriately.
1 parent fa7f932 commit 68e1951

File tree

1 file changed

+41
-19
lines changed

1 file changed

+41
-19
lines changed

api/firmware/device.go

+41-19
Original file line numberDiff line numberDiff line change
@@ -145,24 +145,24 @@ func NewDevice(
145145

146146
// info uses the opInfo api endpoint to learn about the version, platform/edition, and unlock
147147
// status (true if unlocked).
148-
func (device *Device) info() (*semver.SemVer, common.Product, bool, error) {
148+
func (device *Device) info() (*semver.SemVer, common.Product, bool, bool, error) {
149149

150150
// CAREFUL: hwwInfo is called on the raw transport, not on device.rawQuery, which behaves
151151
// differently depending on the firmware version. Reason: the version is not
152152
// available (this call is used to get the version), so it must work for all firmware versions.
153153
response, err := device.communication.Query([]byte(hwwInfo))
154154
if err != nil {
155-
return nil, "", false, err
155+
return nil, "", false, false, err
156156
}
157157

158158
if len(response) < 4 {
159-
return nil, "", false, errp.New("unexpected response")
159+
return nil, "", false, false, errp.New("unexpected response")
160160
}
161161
versionStrLen, response := int(response[0]), response[1:]
162162
versionBytes, response := response[:versionStrLen], response[versionStrLen:]
163163
version, err := semver.NewSemVerFromString(string(versionBytes))
164164
if err != nil {
165-
return nil, "", false, err
165+
return nil, "", false, false, err
166166
}
167167
platformByte, response := response[0], response[1:]
168168
editionByte, response := response[0], response[1:]
@@ -175,24 +175,36 @@ func (device *Device) info() (*semver.SemVer, common.Product, bool, error) {
175175
}
176176
editions, ok := products[platformByte]
177177
if !ok {
178-
return nil, "", false, errp.Newf("unrecognized platform: %v", platformByte)
178+
return nil, "", false, false, errp.Newf("unrecognized platform: %v", platformByte)
179179
}
180180
product, ok := editions[editionByte]
181181
if !ok {
182-
return nil, "", false, errp.Newf("unrecognized platform/edition: %v/%v", platformByte, editionByte)
182+
return nil, "", false, false, errp.Newf("unrecognized platform/edition: %v/%v", platformByte, editionByte)
183183
}
184184

185185
var unlocked bool
186-
unlockedByte := response[0]
186+
unlockedByte, response := response[0], response[1:]
187187
switch unlockedByte {
188188
case 0x00:
189189
unlocked = false
190190
case 0x01:
191191
unlocked = true
192192
default:
193-
return nil, "", false, errp.New("unexpected reply")
193+
return nil, "", false, false, errp.New("unexpected reply")
194194
}
195-
return version, product, unlocked, nil
195+
196+
var initialized bool
197+
initializedByte := response[0]
198+
switch initializedByte {
199+
case 0x00:
200+
initialized = false
201+
case 0x01:
202+
initialized = true
203+
default:
204+
return nil, "", false, false, errp.New("unexpected reply")
205+
}
206+
207+
return version, product, unlocked, initialized, nil
196208
}
197209

198210
// Version returns the firmware version.
@@ -203,17 +215,13 @@ func (device *Device) Version() *semver.SemVer {
203215
return device.version
204216
}
205217

218+
206219
// inferVersionAndProduct either sets the version and product by using OP_INFO if they were not
207220
// provided. In this case, the firmware is assumed to be >=v4.3.0, before that OP_INFO was not
208221
// available.
209-
func (device *Device) inferVersionAndProduct() error {
222+
func (device *Device) inferVersionAndProduct(version *semver.SemVer, product common.Product) error {
210223
// The version has not been provided, so we try to get it from OP_INFO.
211224
if device.version == nil {
212-
version, product, _, err := device.info()
213-
if err != nil {
214-
return errp.New(
215-
"OP_INFO unavailable; need to provide version and product via the USB HID descriptor")
216-
}
217225
device.log.Info(fmt.Sprintf("OP_INFO: version=%s, product=%s", version, product))
218226

219227
// sanity check
@@ -241,11 +249,25 @@ func (device *Device) Init() error {
241249
device.channelHashDeviceVerified = false
242250
device.sendCipher = nil
243251
device.receiveCipher = nil
244-
device.changeStatus(StatusConnected)
245252

246-
if err := device.inferVersionAndProduct(); err != nil {
247-
return err
253+
version, product, unlocked, initialized, err := device.info()
254+
if err != nil {
255+
return errp.New(
256+
"OP_INFO unavailable; need to provide version and product via the USB HID descriptor")
257+
}
258+
// The semantics of the firmware and status.Status are not the same.
259+
// status.Status StatusInitialized means the device is unlocked.
260+
// The firmware initialized = true means the device can be unlocked.
261+
if unlocked {
262+
device.changeStatus(StatusInitialized)
263+
} else if initialized {
264+
device.changeStatus(StatusConnected)
265+
} else {
266+
device.changeStatus(StatusUninitialized)
248267
}
268+
269+
device.inferVersionAndProduct(version, product)
270+
249271
if device.version.AtLeast(lowestNonSupportedFirmwareVersion) {
250272
device.changeStatus(StatusRequireAppUpgrade)
251273
return nil
@@ -261,7 +283,7 @@ func (device *Device) Init() error {
261283

262284
// Before 2.0.0, unlock was invoked automatically by the device before USB communication
263285
// started.
264-
if device.version.AtLeast(semver.NewSemVer(2, 0, 0)) {
286+
if (device.version.AtLeast(semver.NewSemVer(2, 0, 0)) && (device.status != StatusInitialized)) {
265287
_, err := device.rawQuery([]byte(opUnlock))
266288
if err != nil {
267289
// Most likely the device has been unplugged.

0 commit comments

Comments
 (0)