Monday, December 27, 2021

Windows PC/SC and SCARD_E_SERVICE_STOPPED (part 2)

In a previous blog article " Windows PC/SC and SCARD_E_SERVICE_STOPPED " I presented a problem on Windows when the last reader is disconnected.

After a discussion on the pcsclite-muscle mailing list I got nice feedback.Thanks.

Diego de Felice gave a reference to a Microsoft documentation from 2016 "What's New in Smart Cards"

Smart Card Service start and stop behavior

Smart card reader detection logic has been added so that the Smart Card Service runs only when appropriate. On Windows Server 2012 and Windows 8, the Smart Card Service (scardsvr) automatically starts when the user connects a smart card reader and automatically stops when a user removes a smart card reader and no other smart card reader is connected to the computer. On startup, the Smart Card Service automatically starts if a reader was previously connected to the computer but a reader is not currently connected to the system. If no smart card readers are connected to the computer, the service will automatically shut down one minute after the last API call into the Smart Card Service. If a reader was never previously connected to the computer, the service will not start automatically.

So the (strange) behavior is documented by Microsoft.

Stephan Brunner then gave a solution: establish a new context.


Source code

I wanted to test the hack proposed by Stephan.

#! /usr/bin/env python3

from smartcard.scard import *
from smartcard.pcsc.PCSCExceptions import *
import time

hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
if hresult != SCARD_S_SUCCESS:
    raise EstablishContextException(hresult)

i = 0
while True:
    hresult, readers = SCardListReaders(hcontext, [])
    exc = BaseSCardException(message="", hresult=hresult)
    print('(%d) %s:' % (i, str(exc)), readers)
    if not hresult in [SCARD_S_SUCCESS, SCARD_E_NO_READERS_AVAILABLE]:
        hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
        if hresult != SCARD_S_SUCCESS:
            raise EstablishContextException(hresult)

    time.sleep(1)
    i += 1

Output

(base) C:\Users\ludovic\Documents>python SCardListReaders.py
(0) : Impossible de trouver un lecteur de carte ŕ puce.  (0x8010002E): []
(1) : Impossible de trouver un lecteur de carte ŕ puce.  (0x8010002E): []
(2) : Impossible de trouver un lecteur de carte ŕ puce.  (0x8010002E): []
(3) : Impossible de trouver un lecteur de carte ŕ puce.  (0x8010002E): []
(4) : L’opération a réussi.  (0x00000000): ['Generic EMV Smartcard Reader 0']
(5) : L’opération a réussi.  (0x00000000): ['Generic EMV Smartcard Reader 0']
(6) : L’opération a réussi.  (0x00000000): ['Generic EMV Smartcard Reader 0']
(7) : L’opération a réussi.  (0x00000000): ['Generic EMV Smartcard Reader 0']
(8) : L’opération a réussi.  (0x00000000): ['Generic EMV Smartcard Reader 0']
(9) : Le gestionnaire de ressources des cartes ŕ puce s’est arręté.  (0x8010001E): []
(10) : Impossible de trouver un lecteur de carte ŕ puce.  (0x8010002E): []
(11) : Impossible de trouver un lecteur de carte ŕ puce.  (0x8010002E): []
(12) : Impossible de trouver un lecteur de carte ŕ puce.  (0x8010002E): []
(13) : L’opération a réussi.  (0x00000000): ['Generic EMV Smartcard Reader 0']
(14) : L’opération a réussi.  (0x00000000): ['Generic EMV Smartcard Reader 0']
(15) : L’opération a réussi.  (0x00000000): ['Generic EMV Smartcard Reader 0']
(16) : L’opération a réussi.  (0x00000000): ['Generic EMV Smartcard Reader 0']
(17) : Le gestionnaire de ressources des cartes ŕ puce s’est arręté.  (0x8010001E): []
(18) : Impossible de trouver un lecteur de carte ŕ puce.  (0x8010002E): []
(19) : Impossible de trouver un lecteur de carte ŕ puce.  (0x8010002E): []

Description

Step 0, I start the script with no smart card reader connected. So SCardListReaders() returns the expected 0x8010002E which is SCARD_E_NO_READERS_AVAILABLE.

Step 4, Then I connect a smart card reader.

Step 9, Then I disconnect the smart card reader and SCardListReaders() returns the unexpected error 0x8010001E i.e. SCARD_E_SERVICE_STOPPED.

The program then calls SCardEstablishContext() again, with success, and continue.

Step 10, The next call to CardListReaders() returns the expected 0x8010002E. So I guess the PC/SC resource manager has been  re-started. 

Step 13, Connecting a new smart card reader works fine and the reader is detected.

Step 17, I disconnect the reader and I get again the SCARD_E_SERVICE_STOPPED error.

Without the hack

If the code does not establish a new context then CardListReaders() will return SCARD_E_SERVICE_STOPPED for ever. And if I connect a new reader it is not detected.

I think this behavior explains the bug reported in CardRequest waitforcard ATR can't see reconnected readers on Windows (regression) #123.


Conclusion

Ignoring SCARD_E_SERVICE_STOPPED, as I did in commit 5b43ef5, is not a correct solution. I have to work on a better solution (just for Windows).

Sunday, December 26, 2021

Windows PC/SC and SCARD_E_SERVICE_STOPPED

It looks like Windows introduced a new behavior when the last smart card reader is disconnected. The PC/SC layer (WinSCard library) will return the error SCARD_E_SERVICE_STOPPED.

According to MSDN "Smart Card Return Values":

SCARD_E_SERVICE_STOPPED
0x8010001E
The smart card resource manager has shut down. 

 

Demonstration

The idea is to wait for a smart card reader if none is already present.

Then wait for the card reader to be disconnected.

Once disconnected SCardListReaders() will return SCARD_E_SERVICE_STOPPED (0x8010001E) instead of the expected SCARD_E_NO_READERS_AVAILABLE (0x8010002E).


Source code

#! /usr/bin/env python3

from smartcard.scard import *
from smartcard.pcsc.PCSCExceptions import *
import time

hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
if hresult != SCARD_S_SUCCESS:
    raise EstablishContextException(hresult)

hresult, readers = SCardListReaders(hcontext, [])
if not hresult in [SCARD_S_SUCCESS, SCARD_E_NO_READERS_AVAILABLE]:
    raise ListReadersException(hresult)
print('PC/SC Readers:', readers)

if not len(readers):
    print("Wait for the first reader")
    while not len(readers):
        hresult, readers = SCardListReaders(hcontext, [])
        if not hresult in [SCARD_S_SUCCESS, SCARD_E_NO_READERS_AVAILABLE]:
            raise ListReadersException(hresult)
        time.sleep(1)
    print('PC/SC Readers:', readers)

print("wait for the last reader removal")
while len(readers):
    hresult, readers = SCardListReaders(hcontext, [])
    if not hresult in [SCARD_S_SUCCESS, SCARD_E_NO_READERS_AVAILABLE]:
        raise ListReadersException(hresult)
    time.sleep(1)
print('PC/SC Readers:', readers)

hresult = SCardReleaseContext(hcontext)
if hresult != SCARD_S_SUCCESS:
    raise ReleaseContextException(hresult)

GNU/Linux result

rousseau@debian:~ $ ./SCardListReaders.py
PC/SC Readers: []
Wait for the first reader
PC/SC Readers: ['Alcor Micro AU9540 00 00']
wait for the last reader removal
PC/SC Readers: []

Windows result

(base) C:\Users\ludovic\Documents>python SCardListReaders.py
PC/SC Readers: []
Wait for the first reader
PC/SC Readers: ['Generic EMV Smartcard Reader 0']
wait for the last reader removal
Traceback (most recent call last):
  File "C:\Users\ludovic\Documents\SCardListReaders.py", line 29, in <module>
    raise ListReadersException(hresult)
smartcard.pcsc.PCSCExceptions.ListReadersException: Failed to list readers:
 Le gestionnaire de ressources des cartes ŕ puce s’est arręté. (0x8010001E)

Sorry for the error message in French. I don't know an equivalent of "LANG=C program" to have program run and use the default language (English).

You can also note the strange display of accented letters. Windows is not yet Unicode ready? :-)


Problems

The problem is that this new behavior broke code in PySCard, my PC/SC Python wrapper.

For example see

Yes, it is an old issue. I tried to fix it many times but the fixes has some other side effects and the problem is still present somewhere.

Windows is NOT my preferred platform (far from it) so fixing Windows issue is a P.I.T.A. for me. Help is really welcome here.

 

But Why?

What problem Microsoft is trying to solve with this behavior?

Why killing the resource manager and returning an error while there is still PC/SC clients connected to the resource manager?

If you have an idea of the answers please tell me.
If you know a way to change the behavior please tell me.

Use the pcsclite-muscle mailing list to discuss this issue.

Saturday, December 4, 2021

New version of pcsc-lite: 1.9.5

I just released a new version of pcsc-lite 1.9.5.
pcsc-lite is a Free Software implementation of the PC/SC (or WinSCard) API for Unix systems.


Changes:

1.9.5: Ludovic Rousseau
4 December 2021

  • pcscd: autoexit even if no client connects
  • Fix variable substitution in systemd units
  • fix potential race conditions with powerState handling
  • Add and use tag TAG_IFD_DEVICE_REMOVED
  • UnitaryTests: port code to Python 3

 

This version includes some user visible changes (if the user looks very carefully).

pcscd: autoexit even if no client connects

Since pcsc-lite version 1.8.0 (November 2010) pcscd can be started by systemd when a PC/SC application is started. See pcscd auto start using systemd.

After the last client releases the last PC/SC resource the pcscd daemon is waiting for 30 seconds (in case a new client connects again) and then exits. This mechanism works great and will continue to work.

When pcscd is NOT started by a PC/SC application then the autoexit mechanism is not triggered (the alarm clock is not started) and the pcscd process can run forever if no client connects and disconnects.

This happens when pcscd is manually started (or restarted) using something like:

sudo service pcscd restart

This is used to relaunch pcscd after a pcscd upgrade or after a driver installation or upgrade. I implemented this to fix Debian bug #995814.


Add and use tag TAG_IFD_DEVICE_REMOVED

pcscd knows when a USB reader is removed. The hotplug mechanism, by default, uses libudev.

pcscd will now notify the driver that the USB device has been removed and that it is not a good idea to try to send USB packets to a now inexistent device. This will prevent the driver to log USB communication errors (because the device is no more present).

I implemented this to (partly) fix "Reader disconnects are noisy in journal/logs #110"

The driver needs to handle this tag. It is the case for my CCID driver since the patch "Avoid logging errors when a reader is removed". The next stable CCID driver version will include this change.

Thursday, November 11, 2021

macOS Monterey and smart cards status

Monterey (macOS 12.0 or 12.0.1 in fact) is now available since October, 2021.

I compare this version to the previous one in Big Sur I presented in macOS Big Sur and smart cards status.



PC/SC

Since Yosemite (macOS 10.10 in 2014) the PC/SC layer is no more a fork of pcsc-lite. So comparing versions with pcsc-lite is useless.

$ cat /System/Library/Frameworks/PCSC.framework/Versions/A/Resources/version.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>BuildAliasOf</key>
	<string>CryptoTokenKit</string>
	<key>BuildVersion</key>
	<string>13</string>
	<key>CFBundleShortVersionString</key>
	<string>8.0</string>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>ProjectName</key>
	<string>SmartCardServices</string>
	<key>SourceVersion</key>
	<string>554040005000000</string>
</dict>
</plist>

The BuildVersion changed from 25 to 13. No idea what that means.

The SourceVersion changed from 487040010000000 to 554040005000000. Again, no idea what that means. Except that Apple made changes to the code.

I have not yet made many tests of the PC/SC layer. So far it works fine.


Crypto Token Kit

CryptoTokenKit is the native smart card API since the complete rewrite in macOS Yosemite 10.10 (OS X Yosemite BETA and smart cards status).

The framework directory changed again. There is no more a /System/Library/Frameworks/CryptoTokenKit.framework/CryptoTokenKit/ directory.

But you can of course still use the CryptoTokenKit framework. My Objective-C sample "PC/SC" sample in Objective-C (synchronous) still builds and works fine.


CCID

$ grep -A 1 CFBundleShortVersionString /usr/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist
17:    <key>CFBundleShortVersionString</key>
18-    <string>1.4.34</string>
The CCID driver has been upgraded from version 1.4.32 as in Big Sur to version 1.4.34.
 
I released version 1.4.34 in  January 2021. The latest CCID version (at the time of writing this blog) is 1.4.36 from August 2021.

Apple Open Source

Apple has not yet added macOS Monterey to the Apple Open Source web site. So we can't say much about what Apple provides in Monterey.

macOS Monterey 12.0.1 Release Notes

CryptoTokenKit is not mentioned in the macOS Monterey 12.0.1 Release Notes. So I imagine only minor changes were made.

Conclusion

No big changes in Monterey for the smart card world.

Saturday, October 23, 2021

PCSC sample in Flutter/Dart

Here is a new PC/SC sample in Dart language I promised in PC/SC sample in different languages.

Fabien Rousseau wrote a PC/SC wrapper for Dart (the language) and Flutter (the UI toolkit).

The library is at https://pub.dev/packages/flutter_pcsc. It is available for GNU/Linux, macOS and Windows.

The source code is at https://github.com/fabienrousseau/flutter_pcsc and uses the MIT license. The current version is 0.0.4.

Fabien also provides an sample code at https://github.com/fabienrousseau/flutter_pcsc/blob/main/flutter_pcsc/example/lib/main.dart. I reused this code for my example bellow.

 

Installation

I just cloned the flutter_pcsc git repository.

You also need to install the flutter SDK to build and run the application. But if you use Flutter I imagine your already have the SDK installed.


Source code

You can use flutter create test to create a sample application with the correct structure and configuration files.

Then edit the pubspec.yaml file to add in the dependencies: section something like:

dependencies:
  flutter_pcsc:
    path: /home/rousseau/Documents/github/flutter_pcsc/flutter_pcsc

Of course you adapt the path to the location of your flutter_pcsc directory.

The source code of the sample application lib/main.dart is:

import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';

import 'package:flutter_pcsc/flutter_pcsc.dart';

void main() {
  MyApp? myApp;

  runZonedGuarded(() async {
    WidgetsFlutterBinding.ensureInitialized();
    FlutterError.onError = (FlutterErrorDetails details) {
      FlutterError.dumpErrorToConsole(details);
      myApp?.addError(details.toString());
    };

    runApp(myApp = MyApp());
  }, (Object error, StackTrace stack) {
    myApp?.addError(error.toString());
  });
}

class MyApp extends StatelessWidget {
  final GlobalKey<_MyAppBodyState> _myAppKey = GlobalKey();

  MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar(
            title: const Text('PCSC example app'),
          ),
          body: MyAppBody(key: _myAppKey)),
    );
  }

  void addError(String msg) {
    _myAppKey.currentState?.messages.add(Message.error(msg));
  }
}

class MyAppBody extends StatefulWidget {
  const MyAppBody({required Key key}) : super(key: key);

  @override
  _MyAppBodyState createState() {
    return _MyAppBodyState();
  }
}

enum MessageType { info, error }

class Message {
  final String content;
  final MessageType type;
  Message(this.type, this.content);

  static info(String content) {
    return Message(MessageType.info, content);
  }

  static error(String content) {
    return Message(MessageType.error, content);
  }
}

class _MyAppBodyState extends State<MyAppBody> {
  static const List<int> selectAppletCommand = [
    0x00, 0xA4, 0x04, 0x00, 0x0A, 0xA0, 0x00, 0x00, 0x00, 0x62,
    0x03, 0x01, 0x0C, 0x06, 0x01
  ];
  static const List<int> appCommand = [
    0x00, 0x00, 0x00, 0x00
  ];
  final ScrollController _scrollController = ScrollController();

  final List<Message> messages = [];

  @override
  void initState() {
    super.initState();
    helloWorld();
  }

  Future<void> helloWorld() async {
    /* establish PCSC context */
    int ctx = await Pcsc.establishContext(PcscSCope.user);
    CardStruct? card;
    try {
      /* get the reader list */
      List<String> readers = await Pcsc.listReaders(ctx);

      if (readers.isEmpty) {
        messages.add(Message.error('Could not detect any reader'));
      } else {
        /* use the first reader */
        String reader = readers[0];
        setState(() {
          messages.add(Message.info('Using reader: $reader'));
        });

        /* connect to the card */
        card = await Pcsc.cardConnect(
            ctx, reader, PcscShare.shared, PcscProtocol.any);

        /* send select applet APDU */
        var response = await Pcsc.transmit(card, selectAppletCommand);
            messages.add(Message.info('Card returned: ${hexDump(response)}'));

        /* send applet test command */
        response = await Pcsc.transmit(card, appCommand);
        var sw = response.sublist(response.length - 2);
        var bytes = response.sublist(0, response.length - 2);
        var text = utf8.decode(bytes);

        messages.add(Message.info('Card returned: ${hexDump(response)}'));

        if (sw[0] != 0x90 || sw[1] != 0x00) {
          setState(() {
            messages
                .add(Message.error('Card returned an error: ${hexDump(sw)}'));
          });
        } else {
          setState(() {
            messages.add(Message.info('text is: ${text}'));
          });
        }
      }
    } finally {
      if (card != null) {
        try {
          /* disconnect from the card */
          await Pcsc.cardDisconnect(card.hCard, PcscDisposition.resetCard);
        } on Exception catch (e) {
          messages.add(Message.error(e.toString()));
        }
      }
      try {
        /* release PCSC context */
        await Pcsc.releaseContext(ctx);
      } on Exception catch (e) {
        messages.add(Message.error(e.toString()));
      }
    }
  }

  static String hexDump(List<int> csn) {
    return csn
        .map((i) => i.toRadixString(16).padLeft(2, '0').toUpperCase())
        .join(' ');
  }

  _scrollToBottom() {
    _scrollController.jumpTo(_scrollController.position.maxScrollExtent);
  }

  @override
  Widget build(BuildContext context) {
    TextStyle errorStyle = const TextStyle(color: Colors.red);
    WidgetsBinding.instance?.addPostFrameCallback((_) => _scrollToBottom());
    return Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
      Expanded(
          child: Column(children: [
        Expanded(
            child: ListView(
                controller: _scrollController,
                children: messages
                    .map((e) => Text(e.content,
                        style: e.type == MessageType.error ? errorStyle : null))
                    .toList())),
        Container(
            margin: const EdgeInsets.all(10),
            child: ElevatedButton(
                onPressed: () async {
                  await tryAgain();
                },
                child: const Text("Try again")))
      ]))
    ]);
  }

  tryAgain() async {
    messages.clear();
    await helloWorld();
  }
}

Output

$ flutter run
hanging current working directory to: /home/rousseau/Documents/flutter/blog
Launching lib/main.dart on Linux in debug mode...
Building Linux application...                                           
Syncing files to device Linux...                                    55ms

Flutter run key commands.
r Hot reload. 🔥🔥🔥
R Hot restart.
h List all available interactive commands.
d Detach (terminate "flutter run" but leave application running).
c Clear the screen
q Quit (terminate the application on the device).

💪 Running with sound null safety 💪

An Observatory debugger and profiler on Linux is available at:
http://127.0.0.1:34019/ORqpNzBQLEQ=/
The Flutter DevTools debugger and profiler on Linux is available at:
http://127.0.0.1:9100?uri=http://127.0.0.1:34019/ORqpNzBQLEQ=/

Flutter is a framework to create graphical applications. So when you run the sample code you get a new window.

Remarks

The code is long because it is a complete Flutter application so you have to handle the graphical interface.

I asked Fabien for a Dart only interface but flutter_pcsc depends on some Flutter mechanisms to handle asynchronism. So it is not possible to write a PC/SC application for the console just using Dart. But if you use Dart I guess you also use flutter.

Despite of his (nice) name Fabien Rousseau is not part of my direct family. So I do not have a potential conflict of interest here 😜.


Conclusion

Thanks to Fabien for telling about his Dart/Flutter project.

If you work on a Free Software PC/SC wrapper that is not yet in my list please let me know.

Friday, October 15, 2021

What happened 20 years ago?

The 14th of October 2001 I became a Debian Developer (or DD).

You can get some more details from https://nm.debian.org/person/rousseau/

History of my Debian packages

Unsurprisingly I mostly maintain smart card related packages.

2001

  • pcsc-perl Perl interface to the PC/SC smart card library
  • pcsc-tools Some tools to use with smart cards and PC/SC

2002

  • ifd-gempc
    • libgempc410 - PC/SC driver for the GemPC 410, 412, 413 and 415 smart card readers
    • libgempc430 - PC/SC driver for the GemPC 430, 432, 435 smart card readers
  • pcsc-lite
    • pcscd - Middleware to access a smart card using PC/SC (daemon side) 
    • libpcsclite1 - Middleware to access a smart card using PC/SC (library) 
    • libpcsclite-dev - Middleware to access a smart card using PC/SC (development files)

2003

  • ccid PC/SC driver for USB CCID smart card readers
  • pilot-link
    • libpisock9 - library for communicating with a PalmOS PDA
    • libpisync1 - synchronization library for PalmOS devices
    • pilot-link - tools to communicate with a PalmOS PDA
    • python-pisock - Python module to communicate with PalmOS PDA
    • libpisock-dev - development files for communicating with a PalmOS PDA
    • python-pisock-dbg - Python module to communicate with PalmOS PDA (debug extension)

    • I will stoped maintaining pilot-link in 2019 because I do not have a Palm pilot any more.

2004

  • jpilot 
    • jpilot - graphical app. to modify the contents of your Palm Pilot's DBs
    • jpilot-plugins - plugins for jpilot (Palm Pilot desktop)
       
    • I will stoped maintaining jpilot in 2019 for the same reason I stopped maintaining pilot-link

2005

  • asedriveiiie
    • libasedrive-serial - PC/SC driver for the Athena ASEDrive IIIe serial smart card reader
    • libasedrive-usb - PC/SC driver for the Athena ASEDrive IIIe USB smart card reader  

2007

  • coolkey
    • coolkey - Smart Card PKCS #11 cryptographic module
    • libckyapplet1 - Smart Card Coolkey applet
    • libckyapplet1-dev - Smart Card Coolkey applet development files 

2008

  • pykcs11 - PKCS#11 wrapper for Python
  • pyscard - Python3 wrapper above PC/SC API

2009

  • pam-pkcs11 - Fully featured PAM module for using PKCS#11 smart cards
  • colormake - simple wrapper around make to colorize output

2013

  • vgrabbj - grabs an image from a camera and puts it in jpg/png format
  • acsccid - PC/SC driver for ACS USB CCID smart card readers
    • I just sponsor this package because the package maintainer is not a Debian Developer

2016

  • grisbi - personal finance management program

2017

  • 0ad - Real-time strategy game of ancient warfare
  • 0ad-data - Real-time strategy game of ancient warfare (data files)

2020

  • libnfc
    • libnfc-bin - Near Field Communication (NFC) binaries
    • libnfc-dev - Near Field Communication (NFC) library (development files)
    • libnfc-examples - Near Field Communication (NFC) examples
    • libnfc-pn53x-examples - Near Field Communication (NFC) examples for PN53x chips only
    • libnfc6 - Near Field Communication (NFC) library 

You can have a list of my packages and their status at my Debian QA page.


Why?

I maintain Debian packages for different reasons.

  • I maintain the package upstream.
    • For example I am the author and maintainer of the CCID driver. And I also maintain the Debian package for this software.
  • I use the package and it has been orphaned. It may have been orphaned in Debian or also orphaned upstream.
    • For example I am not the original author of pcsc-lite. I first started providing bug reports, then patches. I got a write access on the source code repository. I made new releases. And eventually I am on the only maintainer of pcsc-lite.


Conclusion

I think Debian is a very nice project. I do plan to continue maintaining my packages for the next 10 or 20 years. Maybe more :-)

Tuesday, October 12, 2021

No more error logs when a USB reader is removed

When a USB reader was removed you got error logs from the CCID driver. Something like:

00000000 [140295925790464] ccid_usb.c:871:WriteUSB() write failed (1/22): -4 LIBUSB_ERROR_NO_DEVICE
00000506 [140295934183168] ccid_usb.c:871:WriteUSB() write failed (1/22): -4 LIBUSB_ERROR_NO_DEVICE

 

Why?

The first error is because IFDHICCPresence() sends the CCID command PC_to_RDR_GetSlotStatus to know if a card is present.

The second error is because IFDHCloseChannel() sends the CCID command PC_to_RDR_IccPowerOff to power off the card.

But since the USB device has been removed these 2 CCID commands fails and logs the error.  

 

Solution

I had to modify both pcsc-lite (the middleware) and libccid (the smart card reader driver) so they both cooperate to fix the problem.

Now when pcscd detects that a reader has been removed it uses IFDHSetCapabilities() with the new tag TAG_IFD_DEVICE_REMOVED to indicate to the driver that the reader has been removed and that there is no point in trying to send commands to a no more connected reader.

 

Bug reports

The problem has been initially reported by a Fedora user at "Bug 2011128 - pcscd spam syslog when the laptop is undocked and the reader is connected through the dock".

Then Jakub Jelen from RedHat forwarded the bug upstream (to me) at "Reader disconnects are noisy in journal/logs #110" so I am aware of the problem.

The problem was then fixed 5 days later in "Use TAG_IFD_DEVICE_REMOVED when the reader is removed" for pcsc-lite and "Avoid logging errors when a reader is removed" for libccid.

Report upstream

The important point here is that users must reports bugs to their distribution. And distributions must report the problems upstream. It works well (in general).

What does not work is if you know of a problem and the problem does not come to me. For example this bug "Memory leak in pcscd" has been reported to pfSense 3 months ago and no one from pfSense took the time to report the bug upstream (to me). They just discussed about how to remove/disable pcsc-lite from pfSense instead.

I don't have a pfSense account so I can't comment on their bug tracker. I can't create an account on the bug trackers of every project that use my software. That is not how it is supposed to work. Distributors should forward bugs to the upstream projects.

I don't know if the problem is because pfSense is a commercial product or if it is because it uses FreeBSD. (be careful, a troll may be hidden in the previous sentence).


Conclusion

Don't be shy, report bugs.

Don't be shy, forward bugs upstream.

Friday, October 1, 2021

New version of pcsc-lite: 1.9.4

I just released a new version of pcsc-lite 1.9.4.
pcsc-lite is a Free Software implementation of the PC/SC (or WinSCard) API for Unix systems.

This version fixes a memory leak when libusb is used for the hotplug mechanism. GNU/Linux systems should use libudev instead of libusb for hotplug so they should not be concerned. FreeBSD systems and other non-Linux systems had the problem.

The memory leak problem was also reported on the pfSense project at https://redmine.pfsense.org/issues/12095.

Changes:

1.9.4: Ludovic Rousseau
1 October 2021

  •  fix a memory leak when libusb is used for hotplug (i.e. non-Linux systems)

Wednesday, September 22, 2021

PySCard 2.0.2 released

I just released a new version 2.0.2 of pyscard. PySCard is a python module adding smart cards support (PC/SC) to Python.

The PySCard project is available at:

This version is a bug fix release.

Changes:

  • Fix an issue in ReaderMonitor() that failed to enumerate readers on macOS
  • getReaderNames(): handle SCARD_E_SERVICE_STOPPED on Windows generated on last reader removal
  • Restrict MAX_BUFFER_SIZE_EXTENDED to 65535 and fix an issue on Lenovo laptops with NXP NFC readers
  • SmartcardException: display a positive PCSC error code

Monday, August 30, 2021

New version of libccid: 1.4.36

I just released version 1.4.36 of libccid the Free Software CCID class smart card reader driver.

Changes:

1.4.36 - 30 August 2021, Ludovic Rousseau

  • Add support of
    • Lenovo Lenovo Smartcard Wired Keyboard II
    • REINER SCT tanJack USB
    • SafeNet eToken 5110+ FIPS
    • SafeNet eToken 5300 C
    • jSolutions s.r.o. Multi SIM card reader 4/8
  • parse: fix check when bNumDataRatesSupported = 0

Friday, August 6, 2021

New version of pcsc-lite: 1.9.3

I just released a new version of pcsc-lite 1.9.3.
pcsc-lite is a Free Software implementation of the PC/SC (or WinSCard) API for Unix systems.

Please do not use or deploy version 1.9.2 (the previous and bogus version) if you depend on systemd to start the pcscd process.


Changes:

1.9.3: Ludovic Rousseau
6 August 2021

  •  fix a stupid regression with systemd introduced in the previous version

Wednesday, August 4, 2021

pcsc-lite: configuration using /etc/default/pcscd

Version 1.9.2 of pcsc-lite adds a new configuration possibility: systemd EnvironmentFile

 

systemd EnvironmentFile

With systemd it is possible to configure a file that will contain definitions for the process started by systemd. In our case the started process is the daemon pcscd.

The file name is defined in pcscd.service and is, by default, /etc/default/pcscd. You can change the path using --sysconfdir= argument for ./configure.


pcscd environment variables

A first use case is to define environment variables to change the behaviour of pcscd.

For example you can add in this file:

PCSCLITE_FILTER_IGNORE_READER_NAMES="Twin"

so that readers with "Twin" in the name will be ignored.

See "Remove and/or customize PC/SC reader names" for more details and use cases.

You can also define other variables like:

 

pcscd arguments

pcscd is started with the extra parameter $PCSCD_ARGS. By default this variable is empty. But you can define PCSCD_ARGS in /etc/default/pcscd to add more arguments to pcscd.

For example you can use:

PCSCD_ARGS=--debug

to get debug messages in the systemd journal.

To see the pcscd logs in live use:

$ journalctl --unit pcscd --follow


Conclusion

/etc/default/pcscd is a user file so you can edit it as you like. It should not prevent a package upgrade for example.

It is also much simpler and safer than editing systemd files directly.

Tuesday, August 3, 2021

New version of pcsc-lite: 1.9.2

I just released a new version of pcsc-lite 1.9.2.
pcsc-lite is a Free Software implementation of the PC/SC (or WinSCard) API for Unix systems.

Changes:

1.9.2: Ludovic Rousseau
3 August 2021

  • improve NetBSD support
  • pcsc-spy: version 1.1
    • add option -t|--thread
    • x10 speed increase
    • correctly exit at end-of-file
    • remove, now useless, support of macOS
  • systemd:
    • use /etc/default/pcscd as EnvironmentFile
    • use $PCSCD_ARGS to specify more arguments
  • SetProtocol: Handle IFD_NOT_SUPPORTED from the driver
  • hotplug_libudev.c: sanitize interface name
  • pcsc_demo: change licence from GPLv3 to BSD
  • use Python 3 for Python scripts (psc-spy, UnitaryTests)
  • Some other minor improvements

Sunday, July 25, 2021

New version of libccid: 1.4.35

I just released version 1.4.35 of libccid the Free Software CCID class smart card reader driver. 

Changes:

1.4.35 - 25 July 2021, Ludovic Rousseau

  • Add support of
    • ArkSigner Connect2Sign
    • Circle CCR7115 ICC
    • Circle CCR7315
    • Circle CIR215 CL
    • Circle CIR215 PICC
    • Circle CIR315
    • Circle CIR315 (idProduct: 0x3100)
    • Circle CIR315 CL
    • Circle CIR315 Dual & 1S
    • Circle CIR415 CL & 1S
    • Circle Idaxis SecurePIV
    • DUALi DE-ABCM6 RFRW
    • Feitian R701
    • Generic EMV Smartcard Reader (0x058C:0x9590)
    • INMAX DWR18 HC
    • INMAX DWR18 HPC
    • Identiv Identiv uTrust 4711 F CL + SAM Reader
    • Identiv uTrust 3721 Contactless Reader
    • Infocrypt HWDSSL DEVICE
    • Infocrypt Token++ lite
    • MK Technology KeyPass D1
    • SONY Felica RC-S300/P
    • SONY Felica RC-S300/S
    • SONY Felica RC-S660/U
    • SYNNIX CL-2100R
    • SoloKeys Solo 2
    • Spyrus Inc PocketVault P-3X (idProduct: 0x3203)
  • parse: use "ICCD token" for ICCD tokens
  • Support 4 card slots with Feitian R502 C9
  • ccid_usb: ask for bNumDataRatesSupported data rates
  • Solve a performance issue with T=1 and CCID_CLASS_AUTO_PPS_PROP
  • Fix a possible buffer overflow in T0ProcACK
  • IFDHSetProtocolParameters: set IFSC/IFSD only for TPDU readers
  • CCID serial: Reset buffers on failed read
  • Fix yylex missing symbol
  • Gemalto pinpad: fix incorrect bEntryValidationCondition for SecurePINVerify and SecurePINModify
  • Fix bit4id miniLector-EVO pinpad support
  • The Kobil TriBank reader does NOT support extended APDU

Thursday, June 17, 2021

PySCard 2.0.1 released

I just released a new version 2.0.1 of pyscard. PySCard is a python module adding smart cards support (PC/SC) to Python.

The PySCard project is available at:

 

Changes:

 2.0.1 (June 2021)

  • Add .reconnect() method to high-level API
  • Handle removal of the last reader on Windows
  • Fix support of macOS Big Sur
  • Use Python3 by default
  • Handle bogus ACS ACR122U PICC reader

Friday, June 4, 2021

A reader for 96 smart cards? sysmoSIMBANK

In a previous article "Accessing a lot of smart cards?" I presented a reader with 8 slots.

The same company, sysmocom, was also working or a reader with 96 slots. The reader is now available.

sysmoSIMBANK

The product web page contains technical details and documentation.

The sysmoSIMBANK familly has two members:

  • 96 slots in 2U 19” rack mount form-factor

  • 192 slots in 4U 19” rack mount form-factor

The 96 slots reader is composed of 12 sysmoOCTSIM readers of 8 slots each so a total of 12 x 8 = 96 slots.

 On the USB bus the reader looks like 12 sysmoOCTSIM CCID devices connected by some USB hubs.

# lsusb -t
/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 5000M
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 480M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/2p, 480M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M
        |__ Port 1: Dev 3, If 0, Class=Hub, Driver=hub/4p, 480M
            |__ Port 1: Dev 4, If 0, Class=Hub, Driver=hub/4p, 480M
                |__ Port 3: Dev 12, If 2, Class=CDC Data, Driver=cdc_acm, 12M
                |__ Port 3: Dev 12, If 0, Class=Chip/SmartCard, Driver=, 12M
                |__ Port 3: Dev 12, If 3, Class=Application Specific Interface, Driver=, 12M
                |__ Port 3: Dev 12, If 1, Class=Communications, Driver=cdc_acm, 12M
                |__ Port 1: Dev 7, If 1, Class=Communications, Driver=cdc_acm, 12M
                |__ Port 1: Dev 7, If 2, Class=CDC Data, Driver=cdc_acm, 12M
                |__ Port 1: Dev 7, If 0, Class=Chip/SmartCard, Driver=, 12M
                |__ Port 1: Dev 7, If 3, Class=Application Specific Interface, Driver=, 12M
                |__ Port 4: Dev 15, If 2, Class=CDC Data, Driver=cdc_acm, 12M
                |__ Port 4: Dev 15, If 0, Class=Chip/SmartCard, Driver=, 12M
                |__ Port 4: Dev 15, If 3, Class=Application Specific Interface, Driver=, 12M
                |__ Port 4: Dev 15, If 1, Class=Communications, Driver=cdc_acm, 12M
                |__ Port 2: Dev 9, If 3, Class=Application Specific Interface, Driver=, 12M
                |__ Port 2: Dev 9, If 1, Class=Communications, Driver=cdc_acm, 12M
                |__ Port 2: Dev 9, If 2, Class=CDC Data, Driver=cdc_acm, 12M
                |__ Port 2: Dev 9, If 0, Class=Chip/SmartCard, Driver=, 12M
            |__ Port 2: Dev 5, If 0, Class=Hub, Driver=hub/4p, 480M
                |__ Port 1: Dev 8, If 3, Class=Application Specific Interface, Driver=, 12M
                |__ Port 1: Dev 8, If 1, Class=Communications, Driver=cdc_acm, 12M
                |__ Port 1: Dev 8, If 2, Class=CDC Data, Driver=cdc_acm, 12M
                |__ Port 1: Dev 8, If 0, Class=Chip/SmartCard, Driver=, 12M
                |__ Port 2: Dev 11, If 2, Class=CDC Data, Driver=cdc_acm, 12M
                |__ Port 2: Dev 11, If 0, Class=Chip/SmartCard, Driver=, 12M
                |__ Port 2: Dev 11, If 3, Class=Application Specific Interface, Driver=, 12M
                |__ Port 2: Dev 11, If 1, Class=Communications, Driver=cdc_acm, 12M
                |__ Port 3: Dev 14, If 2, Class=CDC Data, Driver=cdc_acm, 12M
                |__ Port 3: Dev 14, If 0, Class=Chip/SmartCard, Driver=, 12M
                |__ Port 3: Dev 14, If 3, Class=Application Specific Interface, Driver=, 12M
                |__ Port 3: Dev 14, If 1, Class=Communications, Driver=cdc_acm, 12M
                |__ Port 4: Dev 17, If 0, Class=Chip/SmartCard, Driver=, 12M
                |__ Port 4: Dev 17, If 1, Class=Communications, Driver=cdc_acm, 12M
                |__ Port 4: Dev 17, If 2, Class=CDC Data, Driver=cdc_acm, 12M
                |__ Port 4: Dev 17, If 3, Class=Application Specific Interface, Driver=, 12M
            |__ Port 3: Dev 6, If 0, Class=Hub, Driver=hub/4p, 480M
                |__ Port 2: Dev 13, If 2, Class=CDC Data, Driver=cdc_acm, 12M
                |__ Port 2: Dev 13, If 0, Class=Chip/SmartCard, Driver=, 12M
                |__ Port 2: Dev 13, If 3, Class=Application Specific Interface, Driver=, 12M
                |__ Port 2: Dev 13, If 1, Class=Communications, Driver=cdc_acm, 12M
                |__ Port 3: Dev 16, If 3, Class=Application Specific Interface, Driver=, 12M
                |__ Port 3: Dev 16, If 1, Class=Communications, Driver=cdc_acm, 12M
                |__ Port 3: Dev 16, If 2, Class=CDC Data, Driver=cdc_acm, 12M
                |__ Port 3: Dev 16, If 0, Class=Chip/SmartCard, Driver=, 12M
                |__ Port 1: Dev 10, If 2, Class=CDC Data, Driver=cdc_acm, 12M
                |__ Port 1: Dev 10, If 0, Class=Chip/SmartCard, Driver=, 12M
                |__ Port 1: Dev 10, If 3, Class=Application Specific Interface, Driver=, 12M
                |__ Port 1: Dev 10, If 1, Class=Communications, Driver=cdc_acm, 12M
                |__ Port 4: Dev 18, If 3, Class=Application Specific Interface, Driver=, 12M
                |__ Port 4: Dev 18, If 1, Class=Communications, Driver=cdc_acm, 12M
                |__ Port 4: Dev 18, If 2, Class=CDC Data, Driver=cdc_acm, 12M
                |__ Port 4: Dev 18, If 0, Class=Chip/SmartCard, Driver=, 12M

Each sysmoOCTSIM is composed of 4 interfaces and one interface is the CCID reader (Class=Chip/SmartCard). Here we see 3 USB hubs each connected to 4 sysmoOCTSIM. So a total of 12 sysmoOCTSIM readers.


pcsc_scan output

With 96 readers the output of the pcsc_scan command is impressive.

Using reader plug'n play mechanism
Scanning present readers...
0: sysmocom sysmoOCTSIM [CCID] (835a971733353553202020341b1f15ff) 00 00
1: sysmocom sysmoOCTSIM [CCID] (835a971733353553202020341b1f15ff) 00 01
2: sysmocom sysmoOCTSIM [CCID] (835a971733353553202020341b1f15ff) 00 02
3: sysmocom sysmoOCTSIM [CCID] (835a971733353553202020341b1f15ff) 00 03
4: sysmocom sysmoOCTSIM [CCID] (835a971733353553202020341b1f15ff) 00 04
5: sysmocom sysmoOCTSIM [CCID] (835a971733353553202020341b1f15ff) 00 05
6: sysmocom sysmoOCTSIM [CCID] (835a971733353553202020341b1f15ff) 00 06
7: sysmocom sysmoOCTSIM [CCID] (835a971733353553202020341b1f15ff) 00 07
8: sysmocom sysmoOCTSIM [CCID] (6b44014933353553202020341b3815ff) 01 00
9: sysmocom sysmoOCTSIM [CCID] (6b44014933353553202020341b3815ff) 01 01
10: sysmocom sysmoOCTSIM [CCID] (6b44014933353553202020341b3815ff) 01 02
11: sysmocom sysmoOCTSIM [CCID] (6b44014933353553202020341b3815ff) 01 03
12: sysmocom sysmoOCTSIM [CCID] (6b44014933353553202020341b3815ff) 01 04
13: sysmocom sysmoOCTSIM [CCID] (6b44014933353553202020341b3815ff) 01 05
14: sysmocom sysmoOCTSIM [CCID] (6b44014933353553202020341b3815ff) 01 06
15: sysmocom sysmoOCTSIM [CCID] (6b44014933353553202020341b3815ff) 01 07
16: sysmocom sysmoOCTSIM [CCID] (9582a74433353553202020341b3315ff) 02 00
17: sysmocom sysmoOCTSIM [CCID] (9582a74433353553202020341b3315ff) 02 01
18: sysmocom sysmoOCTSIM [CCID] (9582a74433353553202020341b3315ff) 02 02
19: sysmocom sysmoOCTSIM [CCID] (9582a74433353553202020341b3315ff) 02 03
20: sysmocom sysmoOCTSIM [CCID] (9582a74433353553202020341b3315ff) 02 04
21: sysmocom sysmoOCTSIM [CCID] (9582a74433353553202020341b3315ff) 02 05
22: sysmocom sysmoOCTSIM [CCID] (9582a74433353553202020341b3315ff) 02 06
23: sysmocom sysmoOCTSIM [CCID] (9582a74433353553202020341b3315ff) 02 07
24: sysmocom sysmoOCTSIM [CCID] (11850ae933353553202020341b3415ff) 03 00
25: sysmocom sysmoOCTSIM [CCID] (11850ae933353553202020341b3415ff) 03 01
26: sysmocom sysmoOCTSIM [CCID] (11850ae933353553202020341b3415ff) 03 02
27: sysmocom sysmoOCTSIM [CCID] (11850ae933353553202020341b3415ff) 03 03
28: sysmocom sysmoOCTSIM [CCID] (11850ae933353553202020341b3415ff) 03 04
29: sysmocom sysmoOCTSIM [CCID] (11850ae933353553202020341b3415ff) 03 05
30: sysmocom sysmoOCTSIM [CCID] (11850ae933353553202020341b3415ff) 03 06
31: sysmocom sysmoOCTSIM [CCID] (11850ae933353553202020341b3415ff) 03 07
32: sysmocom sysmoOCTSIM [CCID] (b4360eaa3335355320202034433215ff) 04 00
33: sysmocom sysmoOCTSIM [CCID] (b4360eaa3335355320202034433215ff) 04 01
34: sysmocom sysmoOCTSIM [CCID] (b4360eaa3335355320202034433215ff) 04 02
35: sysmocom sysmoOCTSIM [CCID] (b4360eaa3335355320202034433215ff) 04 03
36: sysmocom sysmoOCTSIM [CCID] (b4360eaa3335355320202034433215ff) 04 04
37: sysmocom sysmoOCTSIM [CCID] (b4360eaa3335355320202034433215ff) 04 05
38: sysmocom sysmoOCTSIM [CCID] (b4360eaa3335355320202034433215ff) 04 06
39: sysmocom sysmoOCTSIM [CCID] (b4360eaa3335355320202034433215ff) 04 07
40: sysmocom sysmoOCTSIM [CCID] (f9604bd73335355320202034122c15ff) 05 00
41: sysmocom sysmoOCTSIM [CCID] (f9604bd73335355320202034122c15ff) 05 01
42: sysmocom sysmoOCTSIM [CCID] (f9604bd73335355320202034122c15ff) 05 02
43: sysmocom sysmoOCTSIM [CCID] (f9604bd73335355320202034122c15ff) 05 03
44: sysmocom sysmoOCTSIM [CCID] (f9604bd73335355320202034122c15ff) 05 04
45: sysmocom sysmoOCTSIM [CCID] (f9604bd73335355320202034122c15ff) 05 05
46: sysmocom sysmoOCTSIM [CCID] (f9604bd73335355320202034122c15ff) 05 06
47: sysmocom sysmoOCTSIM [CCID] (f9604bd73335355320202034122c15ff) 05 07
48: sysmocom sysmoOCTSIM [CCID] (67c6627c33353553202020341a0515ff) 06 00
49: sysmocom sysmoOCTSIM [CCID] (67c6627c33353553202020341a0515ff) 06 01
50: sysmocom sysmoOCTSIM [CCID] (67c6627c33353553202020341a0515ff) 06 02
51: sysmocom sysmoOCTSIM [CCID] (67c6627c33353553202020341a0515ff) 06 03
52: sysmocom sysmoOCTSIM [CCID] (67c6627c33353553202020341a0515ff) 06 04
53: sysmocom sysmoOCTSIM [CCID] (67c6627c33353553202020341a0515ff) 06 05
54: sysmocom sysmoOCTSIM [CCID] (67c6627c33353553202020341a0515ff) 06 06
55: sysmocom sysmoOCTSIM [CCID] (67c6627c33353553202020341a0515ff) 06 07
56: sysmocom sysmoOCTSIM [CCID] (c8bf40c433353553202020341b1215ff) 07 00
57: sysmocom sysmoOCTSIM [CCID] (c8bf40c433353553202020341b1215ff) 07 01
58: sysmocom sysmoOCTSIM [CCID] (c8bf40c433353553202020341b1215ff) 07 02
59: sysmocom sysmoOCTSIM [CCID] (c8bf40c433353553202020341b1215ff) 07 03
60: sysmocom sysmoOCTSIM [CCID] (c8bf40c433353553202020341b1215ff) 07 04
61: sysmocom sysmoOCTSIM [CCID] (c8bf40c433353553202020341b1215ff) 07 05
62: sysmocom sysmoOCTSIM [CCID] (c8bf40c433353553202020341b1215ff) 07 06
63: sysmocom sysmoOCTSIM [CCID] (c8bf40c433353553202020341b1215ff) 07 07
64: sysmocom sysmoOCTSIM [CCID] (183c363033353553202020341b2b15ff) 08 00
65: sysmocom sysmoOCTSIM [CCID] (183c363033353553202020341b2b15ff) 08 01
66: sysmocom sysmoOCTSIM [CCID] (183c363033353553202020341b2b15ff) 08 02
67: sysmocom sysmoOCTSIM [CCID] (183c363033353553202020341b2b15ff) 08 03
68: sysmocom sysmoOCTSIM [CCID] (183c363033353553202020341b2b15ff) 08 04
69: sysmocom sysmoOCTSIM [CCID] (183c363033353553202020341b2b15ff) 08 05
70: sysmocom sysmoOCTSIM [CCID] (183c363033353553202020341b2b15ff) 08 06
71: sysmocom sysmoOCTSIM [CCID] (183c363033353553202020341b2b15ff) 08 07
72: sysmocom sysmoOCTSIM [CCID] (5dea892433353553202020341b0f15ff) 09 00
73: sysmocom sysmoOCTSIM [CCID] (5dea892433353553202020341b0f15ff) 09 01
74: sysmocom sysmoOCTSIM [CCID] (5dea892433353553202020341b0f15ff) 09 02
75: sysmocom sysmoOCTSIM [CCID] (5dea892433353553202020341b0f15ff) 09 03
76: sysmocom sysmoOCTSIM [CCID] (5dea892433353553202020341b0f15ff) 09 04
77: sysmocom sysmoOCTSIM [CCID] (5dea892433353553202020341b0f15ff) 09 05
78: sysmocom sysmoOCTSIM [CCID] (5dea892433353553202020341b0f15ff) 09 06
79: sysmocom sysmoOCTSIM [CCID] (5dea892433353553202020341b0f15ff) 09 07
80: sysmocom sysmoOCTSIM [CCID] (9a5f16b433353553202020341b4115ff) 0A 00
81: sysmocom sysmoOCTSIM [CCID] (9a5f16b433353553202020341b4115ff) 0A 01
82: sysmocom sysmoOCTSIM [CCID] (9a5f16b433353553202020341b4115ff) 0A 02
83: sysmocom sysmoOCTSIM [CCID] (9a5f16b433353553202020341b4115ff) 0A 03
84: sysmocom sysmoOCTSIM [CCID] (9a5f16b433353553202020341b4115ff) 0A 04
85: sysmocom sysmoOCTSIM [CCID] (9a5f16b433353553202020341b4115ff) 0A 05
86: sysmocom sysmoOCTSIM [CCID] (9a5f16b433353553202020341b4115ff) 0A 06
87: sysmocom sysmoOCTSIM [CCID] (9a5f16b433353553202020341b4115ff) 0A 07
88: sysmocom sysmoOCTSIM [CCID] (196a76f633353553202020341b3b15ff) 0B 00
89: sysmocom sysmoOCTSIM [CCID] (196a76f633353553202020341b3b15ff) 0B 01
90: sysmocom sysmoOCTSIM [CCID] (196a76f633353553202020341b3b15ff) 0B 02
91: sysmocom sysmoOCTSIM [CCID] (196a76f633353553202020341b3b15ff) 0B 03
92: sysmocom sysmoOCTSIM [CCID] (196a76f633353553202020341b3b15ff) 0B 04
93: sysmocom sysmoOCTSIM [CCID] (196a76f633353553202020341b3b15ff) 0B 05
94: sysmocom sysmoOCTSIM [CCID] (196a76f633353553202020341b3b15ff) 0B 06
95: sysmocom sysmoOCTSIM [CCID] (196a76f633353553202020341b3b15ff) 0B 07
 
Fri Jun  4 18:13:48 2021
  Reader 0: sysmocom sysmoOCTSIM [CCID] (835a971733353553202020341b1f15ff) 00 00
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 30 34 05 4B A9
  Reader 1: sysmocom sysmoOCTSIM [CCID] (835a971733353553202020341b1f15ff) 00 01
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B FF 95 00 FF C0 0A 1F 43 80 31 E0 73 36 21 13 57 4A 33 20 07 33 41 41 1F
  Reader 2: sysmocom sysmoOCTSIM [CCID] (835a971733353553202020341b1f15ff) 00 02
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F C7 80 31 E0 73 FE 21 13 67 98 07 02 01 01 01 01 45
  Reader 3: sysmocom sysmoOCTSIM [CCID] (835a971733353553202020341b1f15ff) 00 03
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9A 94 00 92 02 75 93 11 00 01 02 02 19
  Reader 4: sysmocom sysmoOCTSIM [CCID] (835a971733353553202020341b1f15ff) 00 04
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9D 94 80 1F C3 80 63 AF 03 A0 73 1A 21 1B 83 0F 90 00 F5
  Reader 5: sysmocom sysmoOCTSIM [CCID] (835a971733353553202020341b1f15ff) 00 05
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 94 80 1F C7 80 31 E0 73 FE 21 1B 64 07 07 31 00 82 90 00 F2
  Reader 6: sysmocom sysmoOCTSIM [CCID] (835a971733353553202020341b1f15ff) 00 06
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F C7 80 31 E0 73 FE 21 1B 65 24 01 09 01 00 81 05 7B
  Reader 7: sysmocom sysmoOCTSIM [CCID] (835a971733353553202020341b1f15ff) 00 07
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F C7 80 31 A0 73 BE 21 13 67 43 20 07 18 00 00 01 A5
  Reader 8: sysmocom sysmoOCTSIM [CCID] (6b44014933353553202020341b3815ff) 01 00
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 30 34 05 4B A9
  Reader 9: sysmocom sysmoOCTSIM [CCID] (6b44014933353553202020341b3815ff) 01 01
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 99 18 00 11 88 22 33 44 55 66 77 60
  Reader 10: sysmocom sysmoOCTSIM [CCID] (6b44014933353553202020341b3815ff) 01 02
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 99 18 00 11 88 22 33 44 55 66 77 60
  Reader 11: sysmocom sysmoOCTSIM [CCID] (6b44014933353553202020341b3815ff) 01 03
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 99 18 00 11 88 22 33 44 55 66 77 60
  Reader 12: sysmocom sysmoOCTSIM [CCID] (6b44014933353553202020341b3815ff) 01 04
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 99 18 00 11 88 22 33 44 55 66 77 60
  Reader 13: sysmocom sysmoOCTSIM [CCID] (6b44014933353553202020341b3815ff) 01 05
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 99 18 00 11 88 22 33 44 55 66 77 60
  Reader 14: sysmocom sysmoOCTSIM [CCID] (6b44014933353553202020341b3815ff) 01 06
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 99 18 00 11 88 22 33 44 55 66 77 60
  Reader 15: sysmocom sysmoOCTSIM [CCID] (6b44014933353553202020341b3815ff) 01 07
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 99 18 00 11 88 22 33 44 55 66 77 60
  Reader 16: sysmocom sysmoOCTSIM [CCID] (9582a74433353553202020341b3315ff) 02 00
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 30 34 05 4B A9
  Reader 17: sysmocom sysmoOCTSIM [CCID] (9582a74433353553202020341b3315ff) 02 01
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 99 18 00 11 88 22 33 44 55 66 77 60
  Reader 18: sysmocom sysmoOCTSIM [CCID] (9582a74433353553202020341b3315ff) 02 02
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 99 18 00 11 88 22 33 44 55 66 77 60
  Reader 19: sysmocom sysmoOCTSIM [CCID] (9582a74433353553202020341b3315ff) 02 03
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9A 94 00 92 02 75 93 11 00 01 02 02 10
  Reader 20: sysmocom sysmoOCTSIM [CCID] (9582a74433353553202020341b3315ff) 02 04
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9A 94 00 92 02 75 93 11 00 01 02 02 10
  Reader 21: sysmocom sysmoOCTSIM [CCID] (9582a74433353553202020341b3315ff) 02 05
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9A 94 00 92 02 75 93 11 00 01 02 02 19
  Reader 22: sysmocom sysmoOCTSIM [CCID] (9582a74433353553202020341b3315ff) 02 06
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9A 94 00 92 02 75 93 11 00 01 02 02 19
  Reader 23: sysmocom sysmoOCTSIM [CCID] (9582a74433353553202020341b3315ff) 02 07
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 3D 94 00 2B 04 02 56 00 00 86 60 54 A0 80 00 07
  Reader 24: sysmocom sysmoOCTSIM [CCID] (11850ae933353553202020341b3415ff) 03 00
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 30 34 05 4B A9
  Reader 25: sysmocom sysmoOCTSIM [CCID] (11850ae933353553202020341b3415ff) 03 01
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 1C 94 47 44 23 01 00 01 00 00 03 01 00 00
  Reader 26: sysmocom sysmoOCTSIM [CCID] (11850ae933353553202020341b3415ff) 03 02
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 1C 94 47 44 23 01 00 01 00 00 03 01 00 00
  Reader 27: sysmocom sysmoOCTSIM [CCID] (11850ae933353553202020341b3415ff) 03 03
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 1C 94 47 44 23 01 00 01 00 00 03 01 00 00
  Reader 28: sysmocom sysmoOCTSIM [CCID] (11850ae933353553202020341b3415ff) 03 04
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 1C 94 47 44 23 01 00 01 00 00 03 01 00 00
  Reader 29: sysmocom sysmoOCTSIM [CCID] (11850ae933353553202020341b3415ff) 03 05
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 16 94 D0 00 2B 06 F0 00
  Reader 30: sysmocom sysmoOCTSIM [CCID] (11850ae933353553202020341b3415ff) 03 06
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 3D 94 00 2B 04 02 56 00 00 86 60 54 A0 80 00 07
  Reader 31: sysmocom sysmoOCTSIM [CCID] (11850ae933353553202020341b3415ff) 03 07
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 1C 94 47 44 23 01 00 01 00 00 03 01 00 00
  Reader 32: sysmocom sysmoOCTSIM [CCID] (b4360eaa3335355320202034433215ff) 04 00
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 30 34 05 4B A9
  Reader 33: sysmocom sysmoOCTSIM [CCID] (b4360eaa3335355320202034433215ff) 04 01
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 3F 94 00 80 69 AF 03 45 00 CD 00 00 00 0E 83 18 9F 16
  Reader 34: sysmocom sysmoOCTSIM [CCID] (b4360eaa3335355320202034433215ff) 04 02
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 16 94 D0 00 2B 06 F0 00
  Reader 35: sysmocom sysmoOCTSIM [CCID] (b4360eaa3335355320202034433215ff) 04 03
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 1C 94 47 44 23 01 00 01 00 00 03 01 00 00
  Reader 36: sysmocom sysmoOCTSIM [CCID] (b4360eaa3335355320202034433215ff) 04 04
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 1C 94 47 44 23 01 00 01 00 00 03 01 00 00
  Reader 37: sysmocom sysmoOCTSIM [CCID] (b4360eaa3335355320202034433215ff) 04 05
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 16 94 D0 00 2B 06 F0 00
  Reader 38: sysmocom sysmoOCTSIM [CCID] (b4360eaa3335355320202034433215ff) 04 06
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 1C 94 47 44 23 01 00 01 00 00 03 01 00 00
  Reader 39: sysmocom sysmoOCTSIM [CCID] (b4360eaa3335355320202034433215ff) 04 07
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 3D 94 00 2B 04 02 56 00 00 86 60 54 A0 80 00 07
  Reader 40: sysmocom sysmoOCTSIM [CCID] (f9604bd73335355320202034122c15ff) 05 00
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 30 34 05 4B A9
  Reader 41: sysmocom sysmoOCTSIM [CCID] (f9604bd73335355320202034122c15ff) 05 01
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 3F 94 00 80 69 AF 03 45 00 CD 00 00 00 0E 83 18 9F 16
  Reader 42: sysmocom sysmoOCTSIM [CCID] (f9604bd73335355320202034122c15ff) 05 02
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 1C 94 47 44 23 01 00 01 00 00 03 01 00 00
  Reader 43: sysmocom sysmoOCTSIM [CCID] (f9604bd73335355320202034122c15ff) 05 03
  Event number: 0
  Card state: Card removed, 
  Reader 44: sysmocom sysmoOCTSIM [CCID] (f9604bd73335355320202034122c15ff) 05 04
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 1C 94 47 44 23 01 00 01 00 00 03 01 00 00
  Reader 45: sysmocom sysmoOCTSIM [CCID] (f9604bd73335355320202034122c15ff) 05 05
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 16 94 D0 00 2B 06 F0 00
  Reader 46: sysmocom sysmoOCTSIM [CCID] (f9604bd73335355320202034122c15ff) 05 06
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 3D 94 00 2B 04 02 56 00 00 86 60 54 A0 80 00 07
  Reader 47: sysmocom sysmoOCTSIM [CCID] (f9604bd73335355320202034122c15ff) 05 07
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 3F 94 00 80 69 AF 03 45 00 CD 00 00 00 0E 83 18 9F 16
  Reader 48: sysmocom sysmoOCTSIM [CCID] (67c6627c33353553202020341a0515ff) 06 00
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 30 34 05 4B A9
  Reader 49: sysmocom sysmoOCTSIM [CCID] (67c6627c33353553202020341a0515ff) 06 01
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9E 94 80 1F C3 80 31 E0 73 FE 21 1B 66 D0 00 2B 18 02 00 37
  Reader 50: sysmocom sysmoOCTSIM [CCID] (67c6627c33353553202020341a0515ff) 06 02
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 1C 94 47 44 23 01 00 01 00 00 03 01 00 00
  Reader 51: sysmocom sysmoOCTSIM [CCID] (67c6627c33353553202020341a0515ff) 06 03
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 3D 94 00 2B 04 02 56 00 00 86 60 54 A0 80 00 07
  Reader 52: sysmocom sysmoOCTSIM [CCID] (67c6627c33353553202020341a0515ff) 06 04
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9E 94 80 1F C3 80 31 E0 73 FE 21 1B 66 D0 00 2B 18 02 00 37
  Reader 53: sysmocom sysmoOCTSIM [CCID] (67c6627c33353553202020341a0515ff) 06 05
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9E 94 80 1F C3 80 31 E0 73 FE 21 1B 66 D0 00 2B 18 02 00 37
  Reader 54: sysmocom sysmoOCTSIM [CCID] (67c6627c33353553202020341a0515ff) 06 06
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 3D 94 00 2B 04 02 56 00 00 86 60 54 A0 80 00 07
  Reader 55: sysmocom sysmoOCTSIM [CCID] (67c6627c33353553202020341a0515ff) 06 07
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9E 94 80 10 C3 80 31 E0 73 FE 21 1B 66 D0 00 2B 18 02 00
  Reader 56: sysmocom sysmoOCTSIM [CCID] (c8bf40c433353553202020341b1215ff) 07 00
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 30 34 05 4B A9
  Reader 57: sysmocom sysmoOCTSIM [CCID] (c8bf40c433353553202020341b1215ff) 07 01
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9E 94 80 1F C3 80 31 E0 73 FE 21 1B 66 D0 00 2B 18 02 00 37
  Reader 58: sysmocom sysmoOCTSIM [CCID] (c8bf40c433353553202020341b1215ff) 07 02
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 3D 94 00 2B 04 02 56 00 00 86 60 54 A0 80 00 07
  Reader 59: sysmocom sysmoOCTSIM [CCID] (c8bf40c433353553202020341b1215ff) 07 03
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F C3 80 31 E0 73 FE 21 1B B3 E2 02 7E 83 0F 90 00 82
  Reader 60: sysmocom sysmoOCTSIM [CCID] (c8bf40c433353553202020341b1215ff) 07 04
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9E 95 80 1F C7 80 31 E0 73 FE 21 1B 66 D0 01 7B 91 0D 00 E5
  Reader 61: sysmocom sysmoOCTSIM [CCID] (c8bf40c433353553202020341b1215ff) 07 05
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 95 80 1F C7 80 31 A0 73 BE 21 13 67 D0 02 04 09 01 00 00 05
  Reader 62: sysmocom sysmoOCTSIM [CCID] (c8bf40c433353553202020341b1215ff) 07 06
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 16 96 41 73 74 72 69 64
  Reader 63: sysmocom sysmoOCTSIM [CCID] (c8bf40c433353553202020341b1215ff) 07 07
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 7D 94 00 00 55 55 53 0A 74 86 93 0B 24 7C 4D 54 68
  Reader 64: sysmocom sysmoOCTSIM [CCID] (183c363033353553202020341b2b15ff) 08 00
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 30 34 05 4B A9
  Reader 65: sysmocom sysmoOCTSIM [CCID] (183c363033353553202020341b2b15ff) 08 01
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 1C 94 47 44 23 01 00 01 00 00 03 01 00 00
  Reader 66: sysmocom sysmoOCTSIM [CCID] (183c363033353553202020341b2b15ff) 08 02
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F C7 80 31 E0 73 FE 21 1B 65 7E 01 09 01 02 81 05 23
  Reader 67: sysmocom sysmoOCTSIM [CCID] (183c363033353553202020341b2b15ff) 08 03
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B AA 00 40 14 47 47 32 45 54 35 53 34 38 30
  Reader 68: sysmocom sysmoOCTSIM [CCID] (183c363033353553202020341b2b15ff) 08 04
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F C7 80 31 A0 73 BE 21 13 67 43 20 07 18 00 00 01 A5
  Reader 69: sysmocom sysmoOCTSIM [CCID] (183c363033353553202020341b2b15ff) 08 05
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9E 95 80 1F C7 80 31 E0 73 FE 21 1B 66 D0 01 6C 04 0D 00 67
  Reader 70: sysmocom sysmoOCTSIM [CCID] (183c363033353553202020341b2b15ff) 08 06
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9E 94 80 10 C3 80 31 E0 73 FE 21 1B 66 D0 00 2B 18 02 00
  Reader 71: sysmocom sysmoOCTSIM [CCID] (183c363033353553202020341b2b15ff) 08 07
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 99 18 00 11 88 22 33 44 55 66 77 60
  Reader 72: sysmocom sysmoOCTSIM [CCID] (5dea892433353553202020341b0f15ff) 09 00
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 30 34 05 4B A9
  Reader 73: sysmocom sysmoOCTSIM [CCID] (5dea892433353553202020341b0f15ff) 09 01
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9E 96 80 1F C3 80 31 E0 73 FE 21 1B 66 D0 01 6C 04 0D 00 60
  Reader 74: sysmocom sysmoOCTSIM [CCID] (5dea892433353553202020341b0f15ff) 09 02
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F C7 80 31 E0 73 FE 21 13 67 93 30 01 07 02 01 03 7D
  Reader 75: sysmocom sysmoOCTSIM [CCID] (5dea892433353553202020341b0f15ff) 09 03
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9E 95 80 1F C7 80 31 E0 73 FE 21 1B 66 D0 01 6C 04 0D 00 67
  Reader 76: sysmocom sysmoOCTSIM [CCID] (5dea892433353553202020341b0f15ff) 09 04
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 95 80 1F C7 80 31 E0 73 FE 21 1B 63 E2 0A AA 83 0F 90 00 89
  Reader 77: sysmocom sysmoOCTSIM [CCID] (5dea892433353553202020341b0f15ff) 09 05
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B FF 95 00 00 C0 0A 1F 43 80 31 E0 73 36 21 13 57 4A 33 0E 02 31 41 00 88
  Reader 78: sysmocom sysmoOCTSIM [CCID] (5dea892433353553202020341b0f15ff) 09 06
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 3F 94 00 80 69 AF 03 07 06 68 00 7F 0A 0E 83 3E 9F 16
  Reader 79: sysmocom sysmoOCTSIM [CCID] (5dea892433353553202020341b0f15ff) 09 07
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 99 94 00 91 16 91 08 00 01 25 01 00
  Reader 80: sysmocom sysmoOCTSIM [CCID] (9a5f16b433353553202020341b4115ff) 0A 00
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 30 34 05 4B A9
  Reader 81: sysmocom sysmoOCTSIM [CCID] (9a5f16b433353553202020341b4115ff) 0A 01
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9E 96 80 1F C7 80 31 E0 73 FE 21 1B 66 D0 01 7B 5C 0E 00 28
  Reader 82: sysmocom sysmoOCTSIM [CCID] (9a5f16b433353553202020341b4115ff) 0A 02
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F 43 80 31 E0 73 36 21 13 57 4A 33 0E 0C 31 41 00 AF
  Reader 83: sysmocom sysmoOCTSIM [CCID] (9a5f16b433353553202020341b4115ff) 0A 03
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B FF 95 00 00 C0 0A 1F 43 80 31 E0 73 36 21 13 57 4A 33 0E 02 31 41 00 88
  Reader 84: sysmocom sysmoOCTSIM [CCID] (9a5f16b433353553202020341b4115ff) 0A 04
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 3F 95 00 80 69 AF 03 0F 02 80 FF FF 06 0E 83 3E 9F 16
  Reader 85: sysmocom sysmoOCTSIM [CCID] (9a5f16b433353553202020341b4115ff) 0A 05
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F C7 80 31 E0 73 FE 21 11 63 07 52 12 83 07 90 00 8D
  Reader 86: sysmocom sysmoOCTSIM [CCID] (9a5f16b433353553202020341b4115ff) 0A 06
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B BC 94 00 40 14 47 47 33 53 30 35 31 53 31 30 31 30
  Reader 87: sysmocom sysmoOCTSIM [CCID] (9a5f16b433353553202020341b4115ff) 0A 07
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 95 80 1F C7 80 31 E0 73 FE 21 13 57 4A 33 05 2D 32 34 00 BC
  Reader 88: sysmocom sysmoOCTSIM [CCID] (196a76f633353553202020341b3b15ff) 0B 00
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 30 34 05 4B A9
  Reader 89: sysmocom sysmoOCTSIM [CCID] (196a76f633353553202020341b3b15ff) 0B 01
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9F 96 80 1F C7 80 31 E0 73 F6 21 13 67 4D 45 01 00 32 01 01 EB
  Reader 90: sysmocom sysmoOCTSIM [CCID] (196a76f633353553202020341b3b15ff) 0B 02
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 3D 95 00 80 67 AF 03 0F 01 7C 06 0E 83 3E 9F 16
  Reader 91: sysmocom sysmoOCTSIM [CCID] (196a76f633353553202020341b3b15ff) 0B 03
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 9E 95 80 1F C7 80 31 E0 73 FE 21 1B 66 D0 01 6C 04 0D 00 67
  Reader 92: sysmocom sysmoOCTSIM [CCID] (196a76f633353553202020341b3b15ff) 0B 04
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 99 18 00 11 88 22 33 44 55 66 77 60
  Reader 93: sysmocom sysmoOCTSIM [CCID] (196a76f633353553202020341b3b15ff) 0B 05
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 7D 94 00 00 55 55 53 0A 74 86 93 0B 24 7C 4D 54 68
  Reader 94: sysmocom sysmoOCTSIM [CCID] (196a76f633353553202020341b3b15ff) 0B 06
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 99 18 00 11 88 22 33 44 55 66 77 60
  Reader 95: sysmocom sysmoOCTSIM [CCID] (196a76f633353553202020341b3b15ff) 0B 07
  Event number: 0
  Card state: Card inserted, 
  ATR: 3B 7D 94 00 00 55 55 53 0A 74 86 93 0B 24 7C 4D 54 68

You can see that not all the cards are identical. Some are faster (TA1=96) than other (TA1=95 or TA1=94).

The PC/SC reader name is composed of the constant part "sysmocom sysmoOCTSIM [CCID]", then the USB serial number of the sysmoOCTSIM (like "(196a76f633353553202020341b3b15ff)"), followed by the reader number and slot number.

We have 12 readers so from number 00 to 0B (0x0B = 11). Each sysmoOCTSIM has 8 slots so the slot number is from 00 to 07.

The maximum would be 256 readers with 256 slots each so a total of 65536 cards.

See "What is in a PC/SC reader name?" for more details about PC/SC reader names.


Performances

The 12 internal sysmoOCTSIM readers are independant readers so can be accessed simultaneously. Because of a limitation of my CCID driver with multi-slots readers I discussed in "Accessing a lot of smart cards?" it is not possible to access 2 slots of the same reader at the same time. The accesses to slots of a same reader are serialized even if the reader could allow simultaneous accesses.

I used the same code as in "Accessing a lot of smart cards?" to test the performances. I used only the first slot of each of the 12 sysmoOCTSIM reader

Results

I used the time(1) command to measure the time. Example with 1 card:
$ time make -j 0.test > /dev/null 

real    0m1.203s
user    0m0.249s
sys 0m0.053s
The measures are:
# of cards real user sys
11s 203ms0s 249ms0s 53ms
21s 246ms0s 578ms0s 95ms
31s 274ms0s 904ms0s 191ms
41s 332ms1s 372ms0s 219ms
51s 455ms1s 691ms0s 293ms
61s 549ms1s 951ms0s 510ms
71s 646ms2s 551ms0s 424ms
81s 832ms3s 14ms0s 538ms
91s 906ms3s 390ms0s 645ms
102s 79ms3s 676ms0s 883ms
112s 232ms4s 269ms0s 830ms
122s 419ms4s 599ms1s 73ms

We get the graph:


The system has a 4-core CPU so it is expected that the "real" time is/can be lower than the "user" time.

What is important is that the "real" time grows much slower than the number of readers. The time should even be constant in all cases since the 12 readers can work in parallel, but I guess we have a contention on the USB bus since all the accesses are using the same USB connection. So some serialization has to be done at the USB level.

You can note that to handle 12 cards is it only 2.01 times slower than to handle 1 card. We have a speedup of 6 here.

The reader also has 3 Gigabit Ethernet interfaces (RJ45) so the USB limitation may not be a problem. Note that my CCID driver does not know how to talk to this reader using a network protocol.


Conclusion

Both pcsc-lite and my CCID driver work fine with 96 slots/cards. That is good to know because that is not a setup I used to test and debug the software. I guess it is not a very common setup 😀.

I have no problem making "advertising" for sysmocom products because the company is on the Free Software side of the force. All the software they provide, including the sysmoSIMBANK reader firmware, is Free Software (GNU GPL v2+) and I am happy to give them some visibility.

Thanks to sysmocom for giving me access to the reader.