FeitianSmartcardReader/FEITIAN_MOBILE_READERS

Disconnecting Bluetooth reader after use on iOS

tperfitt opened this issue · 10 comments

My App uses the Feitian SDK to communicate with the Feitian Bluetooth reader. It has a CryptoTokenKit (CTK) extensions which does not have direct access to the container app. Both the extension and the container app communicate with the SDK. Here is how it is supposed to work:

  1. App readers certs off of the PIV card via the Feitian Bluetooth reader.
  2. App disconnects from reader
  3. User goes to a system process (like Safari) and connects to a client certificate protected web service. The CTK extension connects to the reader and does the signing operation.

The issue I am having is the disconnect after #1. It doesn't seem consistent. When I disconnect:

        SCardDisconnect(gContxtHandle, DWORD(SCARD_UNPOWER_CARD))
        SCardReleaseContext(gContxtHandle)
        readerInterface.disConnectCurrentPeripheralReader()

It sometimes turns the reader off and works fine. Other times it remains connected and other apps trying to access it via the reader are denied until I either force quit the containing app or toggle bluetooth.

Here is the steps I am doing:

         //setup the connection
         guard SCardEstablishContext(DWORD(SCARD_SCOPE_SYSTEM), nil, nil, &gContxtHandle)==0 else {
                Logging.printLog(log: "Error establishing context")

                return false
         }
        var dwActiveProtocol: DWORD  = 0;
        readerInterface.setAutoPair(true)
        let s = SCardConnect(gContxtHandle, LPCSTR(readerName?.cString(using: .utf8)), DWORD(SCARD_SHARE_SHARED),DWORD(SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1), &gContxtHandle, &dwActiveProtocol)
        readerInterface.setDelegate(self)

        ... APDU commands and communication to read from the reader ...

        // Disconnect

        SCardDisconnect(gContxtHandle, DWORD(SCARD_UNPOWER_CARD))
        SCardReleaseContext(gContxtHandle)
        readerInterface.disConnectCurrentPeripheralReader()

When I use the sample app and tap "power off", the lights stay on for the reader. I am not sure if the power off is to just power off the card or disconnect from bluetooth.

Is there a way I can disconnect from the reader so other apps can access it?

We have a public beta now with the reader integrated if you want to try it:

https://testflight.apple.com/join/eMO0PY8T

@tperfitt
SCardDisconnect only use to disconnect the smartcard.
And SCardReleaseContext will release the context, and close the session.

With Bluetooth 3.0 and lightning reader: it just close the session, and don't disconnect the reader, our bR301 with C18 and iR301 reader will go this way.

With Bluetooth 4.0 (BLE): it will close the session and disconnect the reader, our BLE reader have bR301BLE with C45 casing and bR500

which bluetooth reader are you using? from your report, I guess you are using bR301 C18 casing which is Bluetooth 3.0

With bR301 C18(Bluetooth 3.0): it called External Accessory Framework, and we only can control the disconnect event in EASession, the reader will always paired until you disconnect manually. without data communication, the reader will enter to standby mode and enable the power consumption.

WIth bR301BLE C45: with the BLE technology, it uses CoreBluetooth Framework, and can easily control in CoreBluetooth
And in our SDK, when you call SCardReleaseContext API, the reader will turn off.

I am using the bR301BLE C45 with the SDK. It doesn't always turn off or release. I do this:

    SCardDisconnect(gContxtHandle, DWORD(SCARD_UNPOWER_CARD))
    SCardReleaseContext(gContxtHandle)
    readerInterface.disConnectCurrentPeripheralReader()

and the lights sometimes go off, and sometimes they do not. I have to cycle bluetooth or force quit the app to get it to release the reader.

tim

Let me know which light?
From left to right
LED1: Low battery notification
LED2: Card slot status
LED3: Bluetooth connection
LED4: Battery Charging

@tperfitt BTW. if the BLE reader receive the disconnect event of Bluetooth, then the reader will turn off to save battery.

the reader will turn off with below condition:

  1. Bluetooth disconnect

  2. User press the power off button manually

  3. Without any data communicate with reader in 3 mins, but with this feature, it can be controled by user with API, in our SDK, the API named FT_AutoTurnOffReader, if user call this API, the reader will disable this feature, which means without any data communicate in 3mins, the reader still keep on.
    ` RESPONSECODE cmdAutoTurnOffReader60(bool isOpen)
    {
    unsigned char cmd[10+4]={0};
    unsigned char tmp[10+6]={0};
    status_t res;
    unsigned int length = sizeof(tmp);
    RESPONSECODE return_value = IFD_SUCCESS;
    _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(0);

    cmd[0] = 0x6B; /* feitian private cmd /
    cmd[1] = 0x04;
    cmd[2] = cmd[3] = cmd[4] = 0; /
    dwLength /
    cmd[5] = ccid_descriptor->bCurrentSlotIndex; /
    slot number /
    cmd[6] = ccid_descriptor->real_bSeq++;
    cmd[7] = cmd[8] = cmd[9] = 0; /
    RFU */

     cmd[10] = 0xA5;
     cmd[11] = 0x5A;
     cmd[12] = 0x39;
     if (isOpen) {
         cmd[13] = 0x01;
     }else{
         cmd[13] = 0x02;
     }
    

    res = WritePort(0, 10+4, cmd);
    if (res != STATUS_SUCCESS)
    {
    return IFD_COMMUNICATION_ERROR;
    }

    res = ReadPort(0, &length, tmp);

    if (res != STATUS_SUCCESS)
    return IFD_COMMUNICATION_ERROR;

    if (length < STATUS_OFFSET+1)
    {
    return IFD_COMMUNICATION_ERROR;
    }

    if (tmp[STATUS_OFFSET] & CCID_COMMAND_FAILED)
    {
    ccid_error(tmp[ERROR_OFFSET], FILE, LINE, FUNCTION);
    return IFD_COMMUNICATION_ERROR;
    }

    if(length < 12)
    {
    return IFD_COMMUNICATION_ERROR;
    }

    if (tmp[SIZE_GET_SLOT_STATUS] != 0x90 || tmp[SIZE_GET_SLOT_STATUS +1] != 0x00) {
    return IFD_COMMUNICATION_ERROR;
    }
    return return_value;
    }/cmdAutoTurnOffReader/`

The lights (from L to R):
off, solid yellow, solid blue, off

If I force quit the app that is connected to it, seems to release it and I can use it in another app. How do i get one app to release it via the SDK so I can connect via another app?

We developed power consumption feature, the bluetooth disconnect, then the reader goes off to save battery. so will need change the bluetooth firmware, remove this feature, after the disconnect the reader, and the reader still goes on, then the other App can re-scan and using it directly. keep the BT ON, is that will work for you?

I think i found a way to make it work, though I am not sure why. After I am done with the reader, if I call this twice:

    SCardReleaseContext(gContxtHandle)
    SCardReleaseContext(gContxtHandle)

Then the reader seems to consistently turn off. I then tell the user to turn the reader back on and open the other app.

A firmware update would be much better to not have to do this, but this works in the meantime. Any ideas of why I have to call SCardReleaseContext twice?

Did you call SCardEstablishContext twice? BTW, I remember you are working on write your API based on BLE, and on other hand, our engineer also write a very basic demo based on swift, and follow the CCID spec, so you can have review if you plan to write your own API, will share to you next week, thanks

That was it! Thanks.