@@ -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 , nil , err
156156 }
157157
158158 if len (response ) < 4 {
159- return nil , "" , false , errp .New ("unexpected response" )
159+ return nil , "" , false , nil , 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 , nil , err
166166 }
167167 platformByte , response := response [0 ], response [1 :]
168168 editionByte , response := response [0 ], response [1 :]
@@ -175,24 +175,41 @@ 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 , nil , 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 , nil , 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 , nil , errp .New ("unexpected reply" )
194194 }
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
196213}
197214
198215// Version returns the firmware version.
@@ -206,14 +223,9 @@ func (device *Device) Version() *semver.SemVer {
206223// inferVersionAndProduct either sets the version and product by using OP_INFO if they were not
207224// provided. In this case, the firmware is assumed to be >=v4.3.0, before that OP_INFO was not
208225// available.
209- func (device * Device ) inferVersionAndProduct () error {
226+ func (device * Device ) inferVersionAndProduct (version * semver. SemVer , product common. Product ) error {
210227 // The version has not been provided, so we try to get it from OP_INFO.
211228 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- }
217229 device .log .Info (fmt .Sprintf ("OP_INFO: version=%s, product=%s" , version , product ))
218230
219231 // sanity check
@@ -241,11 +253,25 @@ func (device *Device) Init() error {
241253 device .channelHashDeviceVerified = false
242254 device .sendCipher = nil
243255 device .receiveCipher = nil
244- device .changeStatus (StatusConnected )
245256
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" )
248261 }
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+
249275 if device .version .AtLeast (lowestNonSupportedFirmwareVersion ) {
250276 device .changeStatus (StatusRequireAppUpgrade )
251277 return nil
@@ -261,7 +287,7 @@ func (device *Device) Init() error {
261287
262288 // Before 2.0.0, unlock was invoked automatically by the device before USB communication
263289 // started.
264- if device .version .AtLeast (semver .NewSemVer (2 , 0 , 0 )) {
290+ if device .version .AtLeast (semver .NewSemVer (2 , 0 , 0 )) && ( device . status != StatusInitialized ) {
265291 _ , err := device .rawQuery ([]byte (opUnlock ))
266292 if err != nil {
267293 // Most likely the device has been unplugged.
0 commit comments