Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions polling/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -636,11 +636,8 @@ func (s *Session) handlePollingError(err error) {
return
}

// For serious device errors, trigger immediate card removal
// This handles cases like device disconnection
s.handleCardRemoval()

// If this is a fatal error (device disconnected), notify via callback
// but do NOT trigger card removal - the card wasn't removed, the reader was
if pn532.IsFatal(err) {
s.stateMutex.RLock()
onDisconnected := s.OnDeviceDisconnected
Expand All @@ -649,7 +646,11 @@ func (s *Session) handlePollingError(err error) {
if onDisconnected != nil {
onDisconnected(err)
}
return
}

// For non-fatal errors, trigger card removal (transient comm issues)
s.handleCardRemoval()
}

// handleCardRemoval handles card removal state changes
Expand Down
36 changes: 36 additions & 0 deletions polling/session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1281,6 +1281,42 @@ func TestSession_OnDeviceDisconnected(t *testing.T) {
})
}

// TestSession_FatalErrorDoesNotTriggerCardRemoved verifies that fatal errors
// (device disconnection) don't incorrectly fire OnCardRemoved before OnDeviceDisconnected.
func TestSession_FatalErrorDoesNotTriggerCardRemoved(t *testing.T) {
t.Parallel()
device, _ := createMockDeviceWithTransport(t)
session := NewSession(device, nil)

// Simulate card was present
session.stateMutex.Lock()
session.state.Present = true
session.state.LastUID = "04123456789ABC"
session.stateMutex.Unlock()

var cardRemovedCalled bool
var disconnectedCalled bool
session.SetOnCardRemoved(func() {
cardRemovedCalled = true
})
session.SetOnDeviceDisconnected(func(_ error) {
disconnectedCalled = true
})

// Create a fatal error (device disconnected)
fatalErr := &pn532.TransportError{
Op: "test",
Port: "test",
Err: pn532.ErrDeviceNotFound,
Type: pn532.ErrorTypePermanent,
}

session.handlePollingError(fatalErr)

assert.True(t, disconnectedCalled, "OnDeviceDisconnected should be called")
assert.False(t, cardRemovedCalled, "OnCardRemoved should NOT be called for fatal errors")
}

func TestSession_HandleCardRemoval(t *testing.T) {
t.Parallel()

Expand Down