Skip to content

Commit 0008efa

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 0008efa

File tree

1 file changed

+40
-19
lines changed

1 file changed

+40
-19
lines changed

api/firmware/device.go

+40-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.
@@ -206,14 +218,9 @@ func (device *Device) Version() *semver.SemVer {
206218
// inferVersionAndProduct either sets the version and product by using OP_INFO if they were not
207219
// provided. In this case, the firmware is assumed to be >=v4.3.0, before that OP_INFO was not
208220
// available.
209-
func (device *Device) inferVersionAndProduct() error {
221+
func (device *Device) inferVersionAndProduct(version *semver.SemVer, product common.Product) error {
210222
// The version has not been provided, so we try to get it from OP_INFO.
211223
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-
}
217224
device.log.Info(fmt.Sprintf("OP_INFO: version=%s, product=%s", version, product))
218225

219226
// sanity check
@@ -241,11 +248,25 @@ func (device *Device) Init() error {
241248
device.channelHashDeviceVerified = false
242249
device.sendCipher = nil
243250
device.receiveCipher = nil
244-
device.changeStatus(StatusConnected)
245251

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

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

0 commit comments

Comments
 (0)