@@ -145,24 +145,24 @@ func NewDevice(
145
145
146
146
// info uses the opInfo api endpoint to learn about the version, platform/edition, and unlock
147
147
// 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 ) {
149
149
150
150
// CAREFUL: hwwInfo is called on the raw transport, not on device.rawQuery, which behaves
151
151
// differently depending on the firmware version. Reason: the version is not
152
152
// available (this call is used to get the version), so it must work for all firmware versions.
153
153
response , err := device .communication .Query ([]byte (hwwInfo ))
154
154
if err != nil {
155
- return nil , "" , false , err
155
+ return nil , "" , false , nil , err
156
156
}
157
157
158
158
if len (response ) < 4 {
159
- return nil , "" , false , errp .New ("unexpected response" )
159
+ return nil , "" , false , nil , errp .New ("unexpected response" )
160
160
}
161
161
versionStrLen , response := int (response [0 ]), response [1 :]
162
162
versionBytes , response := response [:versionStrLen ], response [versionStrLen :]
163
163
version , err := semver .NewSemVerFromString (string (versionBytes ))
164
164
if err != nil {
165
- return nil , "" , false , err
165
+ return nil , "" , false , nil , err
166
166
}
167
167
platformByte , response := response [0 ], response [1 :]
168
168
editionByte , response := response [0 ], response [1 :]
@@ -175,24 +175,41 @@ func (device *Device) info() (*semver.SemVer, common.Product, bool, error) {
175
175
}
176
176
editions , ok := products [platformByte ]
177
177
if ! ok {
178
- return nil , "" , false , errp .Newf ("unrecognized platform: %v" , platformByte )
178
+ return nil , "" , false , nil , errp .Newf ("unrecognized platform: %v" , platformByte )
179
179
}
180
180
product , ok := editions [editionByte ]
181
181
if ! ok {
182
- return nil , "" , false , errp .Newf ("unrecognized platform/edition: %v/%v" , platformByte , editionByte )
182
+ return nil , "" , false , nil , errp .Newf ("unrecognized platform/edition: %v/%v" , platformByte , editionByte )
183
183
}
184
184
185
185
var unlocked bool
186
- unlockedByte := response [0 ]
186
+ unlockedByte , response := response [0 ], response [ 1 : ]
187
187
switch unlockedByte {
188
188
case 0x00 :
189
189
unlocked = false
190
190
case 0x01 :
191
191
unlocked = true
192
192
default :
193
- return nil , "" , false , errp .New ("unexpected reply" )
193
+ return nil , "" , false , nil , errp .New ("unexpected reply" )
194
194
}
195
- return version , product , unlocked , nil
195
+
196
+ // Before 9.20.0 REQ_INFO does not respond with a byte for the initialized status.
197
+ if ! version .AtLeast (semver .NewSemVer (9 , 20 , 0 )) {
198
+ return version , product , unlocked , nil , nil
199
+ }
200
+
201
+ var initialized bool
202
+ initializedByte := response [0 ]
203
+ switch initializedByte {
204
+ case 0x00 :
205
+ initialized = false
206
+ case 0x01 :
207
+ initialized = true
208
+ default :
209
+ return nil , "" , false , nil , errp .New ("unexpected reply" )
210
+ }
211
+
212
+ return version , product , unlocked , & initialized , nil
196
213
}
197
214
198
215
// Version returns the firmware version.
@@ -206,14 +223,9 @@ func (device *Device) Version() *semver.SemVer {
206
223
// inferVersionAndProduct either sets the version and product by using OP_INFO if they were not
207
224
// provided. In this case, the firmware is assumed to be >=v4.3.0, before that OP_INFO was not
208
225
// available.
209
- func (device * Device ) inferVersionAndProduct () error {
226
+ func (device * Device ) inferVersionAndProduct (version * semver. SemVer , product common. Product ) error {
210
227
// The version has not been provided, so we try to get it from OP_INFO.
211
228
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
- }
217
229
device .log .Info (fmt .Sprintf ("OP_INFO: version=%s, product=%s" , version , product ))
218
230
219
231
// sanity check
@@ -241,11 +253,25 @@ func (device *Device) Init() error {
241
253
device .channelHashDeviceVerified = false
242
254
device .sendCipher = nil
243
255
device .receiveCipher = nil
244
- device .changeStatus (StatusConnected )
245
256
246
- if err := device .inferVersionAndProduct (); err != nil {
247
- return err
257
+ version , product , unlocked , initialized , err := device .info ()
258
+ if err != nil {
259
+ return errp .New (
260
+ "OP_INFO unavailable; need to provide version and product via the USB HID descriptor" )
248
261
}
262
+ // The semantics of the firmware and status.Status are not the same.
263
+ // status.Status StatusInitialized means the device is unlocked.
264
+ // The firmware initialized = true means the device can be unlocked.
265
+ if unlocked {
266
+ device .changeStatus (StatusInitialized )
267
+ } else if initialized {
268
+ device .changeStatus (StatusConnected )
269
+ } else {
270
+ device .changeStatus (StatusUninitialized )
271
+ }
272
+
273
+ device .inferVersionAndProduct (version , product )
274
+
249
275
if device .version .AtLeast (lowestNonSupportedFirmwareVersion ) {
250
276
device .changeStatus (StatusRequireAppUpgrade )
251
277
return nil
@@ -261,7 +287,7 @@ func (device *Device) Init() error {
261
287
262
288
// Before 2.0.0, unlock was invoked automatically by the device before USB communication
263
289
// started.
264
- if device .version .AtLeast (semver .NewSemVer (2 , 0 , 0 )) {
290
+ if device .version .AtLeast (semver .NewSemVer (2 , 0 , 0 )) && ( device . status != StatusInitialized ) {
265
291
_ , err := device .rawQuery ([]byte (opUnlock ))
266
292
if err != nil {
267
293
// Most likely the device has been unplugged.
0 commit comments