AusweisApp2/src/card/bluetooth/BluetoothReader.cpp

164 lines
4.6 KiB
C++

/*!
* BluetoothReader.cpp
*
* \copyright Copyright (c) 2015 Governikus GmbH & Co. KG
*/
#include "BluetoothCard.h"
#include "BluetoothDebug.h"
#include "BluetoothReader.h"
#include "DeviceError.h"
#include "messages/BluetoothMessageCreator.h"
#include "messages/BluetoothMessageParser.h"
#include "messages/BluetoothMessageSetTransportProtocolResponse.h"
#include "messages/BluetoothMessageStatusInd.h"
#include "SynchronousBtCall.h"
#include <QDebug>
#include <QLoggingCategory>
#include <QSignalBlocker>
Q_DECLARE_LOGGING_CATEGORY(bluetooth)
using namespace governikus;
BluetoothReader::BluetoothReader(const QSharedPointer<CyberJackWaveDevice>& pDevice)
: ConnectableReader(ReaderManagerPlugInType::BLUETOOTH, pDevice->getName(), ReaderType::REINER_cyberJack_wave)
, mDevice(pDevice)
, mLastCardEvent(CardEvent::NONE)
, mCard()
{
mReaderInfo.setBasicReader(false);
mReaderInfo.setConnected(false);
connect(mDevice.data(), &CyberJackWaveDevice::fireInitialized, this, &BluetoothReader::onInitialized);
connect(mDevice.data(), &CyberJackWaveDevice::fireDisconnected, this, &BluetoothReader::onDisconnected);
connect(mDevice.data(), &CyberJackWaveDevice::fireError, this, &BluetoothReader::onError);
connect(mDevice.data(), &CyberJackWaveDevice::fireStatusCharacteristicChanged, this, &BluetoothReader::onStatusCharacteristicChanged);
}
Card* BluetoothReader::getCard() const
{
return mCard.data();
}
void BluetoothReader::connectReader()
{
mDevice->initialize();
}
void BluetoothReader::onInitialized(const QBluetoothDeviceInfo&)
{
qCDebug(bluetooth) << "Connected reader" << getName() << "is valid:" << mDevice->isValid();
/*
* Attention: This also triggers the pairing!
* (Pairing is initiated by the device on the first write request with WriteMode::WriteWithResponse.)
*/
auto request = BluetoothMessageCreator::createSetTransportProtocolRequest(BluetoothTransportProtocol::T1);
auto response = SynchronousBtCall(mDevice).send(request, BluetoothMsgId::SetTransportProtocolResponse);
if (response.isNull())
{
qCCritical(bluetooth) << "Response is empty";
return;
}
auto protocolResponse = response.staticCast<const BluetoothMessageSetTransportProtocolResponse>();
if (protocolResponse->getResultCode() != BluetoothResultCode::Ok)
{
qCCritical(bluetooth) << "Error setting transport protocol";
return;
}
Q_EMIT fireReaderConnected(mReaderInfo.getName());
mReaderInfo.setConnected(mDevice->isValid());
mLastCardEvent = CardEvent::CARD_REMOVED;
mTimerId = startTimer(500);
}
void BluetoothReader::disconnectReader()
{
mDevice->disconnectFromDevice();
}
void BluetoothReader::onDisconnected(const QBluetoothDeviceInfo&)
{
qCDebug(bluetooth) << "Disconnected reader" << getName();
killTimer(mTimerId);
mTimerId = 0;
mReaderInfo.setConnected(false);
/*
* We remove the card, because the user may remove it either when the reader is disconnected.
* Finally we perform one update manually, because the timer is already stopped.
*/
onCardRemoved();
update();
}
void BluetoothReader::onError(QLowEnergyController::Error pError)
{
if (pError == QLowEnergyController::ConnectionError)
{
Q_EMIT fireReaderDeviceError(DeviceError::DEVICE_CONNECTION_ERROR);
}
}
Reader::CardEvent BluetoothReader::updateCard()
{
CardEvent tmpEvent = mLastCardEvent;
mLastCardEvent = CardEvent::NONE;
return tmpEvent;
}
void BluetoothReader::onStatusCharacteristicChanged(const QByteArray& pValue)
{
auto messages = BluetoothMessageParser(pValue).getMessages();
if (messages.size() != 1 || messages.at(0)->getBluetoothMsgId() != BluetoothMsgId::StatusInd)
{
qCCritical(card) << "Cannot handle Bluetooth message";
return;
}
auto statusChange = messages.at(0).staticCast<const BluetoothMessageStatusInd>()->getStatusChange();
if (mCard.isNull() && (statusChange == BluetoothStatusChange::CardInserted || statusChange == BluetoothStatusChange::CardReset))
{
qCDebug(card) << "Card inserted" << getName();
mCard.reset(new BluetoothCard(mDevice));
QSharedPointer<CardConnectionWorker> cardConnection = createCardConnectionWorker();
CardInfoFactory::create(cardConnection, mReaderInfo);
const QSignalBlocker blocker(this);
updateRetryCounter(cardConnection);
mLastCardEvent = CardEvent::CARD_INSERTED;
}
else if (!mCard.isNull() && statusChange == BluetoothStatusChange::CardRemoved)
{
onCardRemoved();
}
else
{
qCWarning(card) << "Got unhandled card reader status" << statusChange;
}
}
void BluetoothReader::onCardRemoved()
{
qCDebug(card) << "Card removed" << getName();
mLastCardEvent = CardEvent::CARD_REMOVED;
mUpdateRetryCounter = false;
mReaderInfo.setCardInfo(CardInfo(CardType::NONE));
mCard.reset();
}