UsbCardReader.cpp revision 636ffa46f2d7dc5fe152170b891ad5cbcbbc9cf5
/* $Id$ */
/** @file
* UsbCardReader - Driver Interface to USB Smart Card Reader emulation.
*/
/*
* Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#define LOG_GROUP LOG_GROUP_USB_CARDREADER
#include "UsbCardReader.h"
#include "ConsoleImpl.h"
#include "ConsoleVRDPServer.h"
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
typedef struct USBCARDREADER USBCARDREADER;
typedef struct USBCARDREADER *PUSBCARDREADER;
struct USBCARDREADER
{
/* Thread handling Cmd to card reader */
/* Queue handling requests to cardreader */
};
/*
* Command queue's callbacks.
*/
void *pvUser,
{
LogFlowFunc(("ENTER: pvUser:%p, u32Timeout:%d\n",
pvUser, u32Timeout));
if (!pUsbCardReader)
{
}
else
{
}
}
{
LogFlowFunc(("\n"));
if (!pUsbCardReader)
{
}
else
{
}
}
void *pvUser)
{
LogFlowFunc(("ENTER: pvUser:%p\n",
pvUser));
if (!pUsbCardReader)
{
/* Do nothing. */
}
else
{
}
}
void *pvUser)
{
LogFlowFunc(("ENTER: pvUser:%p\n",
pvUser));
if (!pUsbCardReader)
{
/* pszReaderName */ NULL,
/* cchReaderName */ 0,
/* u32CardState */ 0,
/* u32Protocol */ 0,
/* pu8Atr */ 0,
/* cbAtr */ 0);
}
else
{
}
}
void *pvUser,
const char *pcszCardReaderName,
{
LogFlowFunc(("ENTER: pvUser:%p, pcszCardReaderName:%s, u32ShareMode:%RX32, u32PreferredProtocols:%RX32\n",
if (!pUsbCardReader)
{
0);
}
else
{
}
}
void *pvUser,
{
LogFlowFunc(("ENTER: pvUser:%p, u32Disposition:%RX32\n",
pvUser, u32Disposition));
if (!pUsbCardReader)
{
}
else
{
}
}
void *pvUser,
{
LogFlowFunc(("ENTER: pvUser:%p, pioSendRequest:%p, pu8SendBuffer:%p, cbSendBuffer:%d, cbRecvBuffer:%d\n",
if (!pUsbCardReader)
{
/* pioRecvPci */ NULL,
/* pu8RecvBuffer */ NULL,
/* cbRecvBuffer*/ 0);
}
else
{
}
/* Clean up buffers allocated by driver */
}
void *pvUser,
{
LogFlowFunc(("ENTER: pvUser:%p, u32AttrId:%RX32, cbAttrib:%d\n",
if (!pUsbCardReader)
{
/* pvAttrib */ NULL,
/* cbAttrib */ 0);
}
else
{
}
}
void *pvUser,
void *pvAttrib,
{
LogFlowFunc(("ENTER: pvUser:%p, u32AttrId:%RX32, pvAttrib:%p, cbAttrib:%d\n",
if (!pUsbCardReader)
{
}
else
{
}
/* Clean up buffers allocated by driver */
}
void *pvUser,
void *pvInBuffer,
{
LogFlowFunc(("ENTER: pvUser:%p, u32ControlCode:%RX32, pvInBuffer:%p, cbInBuffer:%d, cbOutBuffer:%d\n",
if (!pUsbCardReader)
{
/* pvOutBuffer */ NULL,
/* cbOutBuffer */ 0);
}
else
{
}
/* Clean up buffers allocated by driver */
}
/*
* PDMICARDREADERDOWN - interface
*/
void *pvUser,
const char *pcszCardReaderName,
{
LogFlowFunc(("ENTER: pcszCardReaderName:%s, pvUser:%p, u32ShareMode:%RX32, u32PreferredProtocols:%RX32\n",
return rc;
}
void *pvUser,
{
LogFlowFunc(("ENTER: pvUser:%p, u32Disposition:%RX32\n",
pvUser, u32Disposition));
return rc;
}
{
LogFlowFunc(("ENTER:\n"));
pThis);
return rc;
}
void *pvUser)
{
LogFlowFunc(("ENTER: pvUser:%p\n",
pvUser));
/* @todo Device calls this when the driver already destroyed. */
{
LogFlowFunc(("LEAVE: device already deleted.\n"));
return VINF_SUCCESS;
}
return rc;
}
void *pvUser,
{
LogFlowFunc(("ENTER: pvUser:%p, cchReaderName:%d, cbAtrLen:%d\n",
return rc;
}
void *pvUser,
{
LogFlowFunc(("ENTER: pvUser:%p, u32Timeout:%d, cReaderStats:%d\n",
return rc;
}
void *pvUser)
{
LogFlowFunc(("ENTER: pvUser:%p\n",
pvUser));
int rc = VERR_NOT_SUPPORTED;
return rc;
}
void *pvUser,
{
LogFlowFunc(("ENTER: pvUser:%p, u32Disposition:%RX32\n",
pvUser, u32Disposition));
int rc = VERR_NOT_SUPPORTED;
return rc;
}
void *pvUser,
const uint8_t *pu8SendBuffer,
{
LogFlowFunc(("ENTER: pvUser:%p, pioSendRequest:%p, pu8SendBuffer:%p, cbSendBuffer:%d, cbRecvBuffer:%d\n",
if ( pu8SendBuffer
&& cbSendBuffer)
{
if (!pu8SendBufferCopy)
{
return VERR_NO_MEMORY;
}
}
if (pioSendRequest)
{
pioSendRequestCopy = (PDMICARDREADER_IO_REQUEST *)RTMemDup(pioSendRequest, pioSendRequest->cbPciLength);
if (!pioSendRequestCopy)
{
return VERR_NO_MEMORY;
}
}
return rc;
}
void *pvUser,
{
LogFlowFunc(("ENTER: pvUser:%p, u32AttribId:%RX32, cbAttrib:%d\n",
return rc;
}
void *pvUser,
const void *pvAttrib,
{
LogFlowFunc(("ENTER: pvUser:%p, u32AttribId:%RX32, pvAttrib:%p, cbAttrib:%d\n",
void *pvAttribCopy = NULL;
if ( pvAttrib
&& cbAttrib)
{
}
return rc;
}
void *pvUser,
const void *pvInBuffer,
{
LogFlowFunc(("ENTER: pvUser:%p, u32ControlCode:%RX32 pvInBuffer:%p, cbInBuffer:%d, cbOutBuffer:%d\n",
void *pvInBufferCopy = NULL;
if ( pvInBuffer
&& cbInBuffer)
{
}
return rc;
}
/*
* Cardreader driver thread routines
*/
{
int rc = VINF_SUCCESS;
{
LogFlowFunc(("LEAVE: INITIALIZING: VINF_SUCCESS\n"));
return VINF_SUCCESS;
}
{
("Left RTReqProcess and error code is not VWRN_STATE_CHANGED rc=%Rrc\n",
rc));
}
return rc;
}
{
/* Returning a VINF_* will cause RTReqQueueProcess return. */
return VWRN_STATE_CHANGED;
}
{
int rc = RTReqQueueCall(pThis->hReqQCardReaderCmd, &pReq, 10000, (PFNRT)drvCardReaderWakeupFunc, 1, pThis);
if (RT_SUCCESS(rc))
/* @todo handle VERR_TIMEOUT */
return rc;
}
/*
* USB Card reader driver implementation.
*/
:
{
LogFlowFunc(("\n"));
}
{
if (mpDrv)
{
}
}
typedef struct UCRREMOTEREADER
{
bool fAvailable;
char szReaderName[1024];
bool fHandle;
struct UCRREMOTE
{
/* The remote identifiers. */
bool fContext;
/* Possible a few readers. Currently only one. */
};
typedef struct UCRREQCTX
{
void *pvUser;
union
{
struct
{
struct
{
} GetAttrib;
struct
{
} SetAttrib;
struct
{
} Control;
} u;
} UCRREQCTX;
int UsbCardReader::vrdeSCardRequest(void *pvUser, uint32_t u32Function, const void *pvData, uint32_t cbData)
{
return rc;
}
{
int rc = VINF_SUCCESS;
switch (u32Id)
{
case VRDE_SCARD_NOTIFY_ATTACH:
{
/* Add this remote instance, which allow access to card readers attached to the client, to the list.
* @todo currently only one device is allowed.
*/
if (m_pRemote)
{
AssertFailed();
break;
}
{
rc = VERR_NO_MEMORY;
break;
}
pRemote->pUsbCardReader = this;
/* Try to establish a context. */
LogFlowFunc(("sent ESTABLISHCONTEXT\n"));
} break;
case VRDE_SCARD_NOTIFY_DETACH:
{
/* @todo Just free. There should be no pending requests, because VRDP cancels them. */
} break;
default:
AssertFailed();
break;
}
return rc;
}
int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Function, void *pvData, uint32_t cbData)
{
int rc = VINF_SUCCESS;
LogFlowFunc(("%Rrc %p %u %p %u\n",
switch (u32Function)
{
{
/* Check if the context was created. */
if ( RT_SUCCESS(rcRequest)
{
LogFlowFunc(("ESTABLISHCONTEXT success\n"));
/* Now list readers attached to the remote client. */
}
} break;
{
if ( RT_SUCCESS(rcRequest)
{
LogFlowFunc(("LISTREADERS: cReaders %d\n",
uint32_t i;
{
LogFlowFunc(("LISTREADERS: [%d] [%s]\n",
/* @todo only the first reader is supported. */
if (i != 0)
{
continue;
}
}
}
} break;
{
LogFlowFunc(("RELEASECONTEXT completed\n"));
/* No notification is expected here by the caller. */
} break;
{
LogFlowFunc(("GETSTATUSCHANGE\n"));
if (RT_FAILURE(rcRequest))
{
}
else
{
{
uint32_t i;
{
LogFlowFunc(("GETSTATUSCHANGE: [%d] %RX32\n",
/* @todo only the first reader is supported. */
if (i != 0)
{
continue;
}
{
continue;
}
36:
}
}
}
} break;
case VRDE_SCARD_FN_CANCEL:
{
LogFlowFunc(("CANCEL\n"));
} break;
case VRDE_SCARD_FN_CONNECT:
{
LogFlowFunc(("CONNECT\n"));
if (RT_FAILURE(rcRequest))
{
}
else
{
{
}
}
} break;
case VRDE_SCARD_FN_RECONNECT:
{
LogFlowFunc(("RECONNECT\n"));
} break;
case VRDE_SCARD_FN_DISCONNECT:
{
LogFlowFunc(("DISCONNECT\n"));
if (RT_FAILURE(rcRequest))
{
}
else
{
}
rcCard);
} break;
{
LogFlowFunc(("BEGINTRANSACTION\n"));
} break;
{
LogFlowFunc(("ENDTRANSACTION\n"));
} break;
case VRDE_SCARD_FN_STATE:
{
LogFlowFunc(("STATE\n"));
} break;
case VRDE_SCARD_FN_STATUS:
{
LogFlowFunc(("STATUS\n"));
char *pszReaderName = NULL;
uint32_t cchReaderName = 0;
uint32_t u32CardState = 0;
uint32_t u32Protocol = 0;
uint32_t u32AtrLength = 0;
if (RT_FAILURE(rcRequest))
{
}
else
{
{
}
}
} break;
case VRDE_SCARD_FN_TRANSMIT:
{
LogFlowFunc(("TRANSMIT\n"));
uint32_t cbRecvBuffer = 0;
if (RT_FAILURE(rcRequest))
{
}
else
{
{
/* @todo pioRecvPci */
}
}
} break;
case VRDE_SCARD_FN_CONTROL:
{
LogFlowFunc(("CONTROL\n"));
uint32_t cbOutBuffer = 0;
if (RT_FAILURE(rcRequest))
{
}
else
{
{
}
}
} break;
case VRDE_SCARD_FN_GETATTRIB:
{
LogFlowFunc(("GETATTRIB\n"));
if (RT_FAILURE(rcRequest))
{
}
else
{
{
}
}
cbAttrib);
} break;
case VRDE_SCARD_FN_SETATTRIB:
{
LogFlowFunc(("SETATTRIB\n"));
if (RT_FAILURE(rcRequest))
{
}
else
{
}
} break;
default:
AssertFailed();
break;
}
return rc;
}
{
/* The context here is a not a real device context.
* The device can be detached at the moment, for example the VRDP client did not connect yet.
*/
}
{
int rc = VINF_SUCCESS;
if ( !m_pRemote
{
/* Do nothing. */
}
else
{
if (!pCtx)
{
/* Do nothing. */
}
else
{
if (RT_FAILURE(rc))
{
}
else
{
}
}
}
return rc;
}
void *pvUser,
{
int rc = VINF_SUCCESS;
if ( !m_pRemote
{
}
else
{
if (!pCtx)
{
}
else
{
if (RT_FAILURE(rc))
{
}
}
}
return rc;
}
void *pvUser,
const char *pszReaderName,
{
int rc = VINF_SUCCESS;
if ( !m_pRemote
{
}
else
{
if (!pCtx)
{
}
else
{
if (RT_FAILURE(rc))
{
}
}
}
return rc;
}
void *pvUser,
{
int rc = VINF_SUCCESS;
if ( !m_pRemote
{
}
else
{
if (!pCtx)
{
}
else
{
if (RT_FAILURE(rc))
{
}
else
{
}
}
}
return rc;
}
void *pvUser)
{
int rc = VINF_SUCCESS;
if ( !m_pRemote
{
/* pszReaderName */ NULL,
/* cchReaderName */ 0,
/* u32CardState */ 0,
/* u32Protocol */ 0,
/* pu8Atr */ 0,
/* cbAtr */ 0);
}
else
{
if (!pCtx)
{
/* pszReaderName */ NULL,
/* cchReaderName */ 0,
/* u32CardState */ 0,
/* u32Protocol */ 0,
/* pu8Atr */ 0,
/* cbAtr */ 0);
}
else
{
if (RT_FAILURE(rc))
{
}
}
}
return rc;
}
void *pvUser,
{
int rc = VINF_SUCCESS;
if ( !m_pRemote
{
}
if (rcSCard == VRDE_SCARD_S_SUCCESS)
{
if ( !pioSendRequest
)
{
AssertFailed();
}
}
if (rcSCard == VRDE_SCARD_S_SUCCESS)
{
if (!pCtx)
{
}
}
if (rcSCard != VRDE_SCARD_S_SUCCESS)
{
/* pioRecvPci */ NULL,
/* pu8RecvBuffer */ NULL,
/* cbRecvBuffer*/ 0);
}
else
{
2 * sizeof(uint32_t):
if (RT_FAILURE(rc))
{
}
}
return rc;
}
void *pvUser,
{
int rc = VINF_SUCCESS;
if ( !m_pRemote
{
}
if (rcSCard == VRDE_SCARD_S_SUCCESS)
{
if ( cbInBuffer > _128K
|| cbOutBuffer > _128K)
{
AssertFailed();
}
}
if (rcSCard == VRDE_SCARD_S_SUCCESS)
{
if (!pCtx)
{
}
}
if (rcSCard != VRDE_SCARD_S_SUCCESS)
{
/* pvOutBuffer */ NULL,
/* cbOutBuffer*/ 0);
}
else
{
if (RT_FAILURE(rc))
{
}
}
return rc;
}
void *pvUser,
{
int rc = VINF_SUCCESS;
if ( !m_pRemote
{
}
if (rcSCard == VRDE_SCARD_S_SUCCESS)
{
{
AssertFailed();
}
}
if (rcSCard == VRDE_SCARD_S_SUCCESS)
{
if (!pCtx)
{
}
}
if (rcSCard != VRDE_SCARD_S_SUCCESS)
{
/* pvAttrib */ NULL,
/* cbAttrib */ 0);
}
else
{
if (RT_FAILURE(rc))
{
}
}
return rc;
}
void *pvUser,
{
int rc = VINF_SUCCESS;
if ( !m_pRemote
{
}
if (rcSCard == VRDE_SCARD_S_SUCCESS)
{
{
AssertFailed();
}
}
if (rcSCard == VRDE_SCARD_S_SUCCESS)
{
if (!pCtx)
{
}
}
if (rcSCard != VRDE_SCARD_S_SUCCESS)
{
}
else
{
if (RT_FAILURE(rc))
{
}
}
return rc;
}
/*
* PDMDRVINS
*/
/* static */ DECLCALLBACK(void *) UsbCardReader::drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
{
return NULL;
}
{
/** @todo The driver is destroyed before the device.
* So device calls ReleaseContext when there is no more driver.
* Notify the device here so it can do cleanup or
* do a cleanup now in the driver.
*/
{
}
/** @todo r=bird: why doesn't this set pThis->pUsbCardReader->mpDrv to NULL like
* everyone else? */
}
/* static */ DECLCALLBACK(int) UsbCardReader::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
{
("Configuration error: Not possible to attach anything to this driver!\n"),
void *pv;
/* Command Thread Synchronization primitives */
drvCardReaderThreadCmd /* worker routine */,
drvCardReaderThreadCmdWakeup /* wakeup routine */,
if (RT_FAILURE(rc))
{
}
return rc;
}
{
/* u32Version */
/* szName[32] */
"UsbCardReader",
/* szRCMod[32] */
"",
/* szR0Mod[32] */
"",
/* pszDescription */
"Main Driver communicating with VRDE",
/* fFlags */
/* fClass */
/* cMaxInstances */
1,
/* cbInstance */
sizeof(USBCARDREADER),
/* pfnConstruct */
/* pfnDestruct */
/* pfnRelocate */
NULL,
/* pfnIOCtl */
NULL,
/* pfnPowerOn */
NULL,
/* pfnReset */
NULL,
/* pfnSuspend */
NULL,
/* pfnResume */
NULL,
/* pfnAttach */
NULL,
/* pfnDetach */
NULL,
/* pfnPowerOff */
NULL,
/* pfnSoftReset */
NULL,
/* u32VersionEnd */
};
/* vi: set tabstop=4 shiftwidth=4 expandtab: */