Skip to content

Commit bc9176b

Browse files
committed
Devices/Security: UsbCardReader: simplified ReadData callback. bugref:11114
svn:sync-xref-src-repo-rev: r174537
1 parent 1c53c51 commit bc9176b

2 files changed

Lines changed: 49 additions & 30 deletions

File tree

src/VBox/Devices/Security/Makefile.kup

Whitespace-only changes.

src/VBox/Devices/Security/UsbCardReader.cpp

Lines changed: 49 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $Id: UsbCardReader.cpp 112403 2026-01-11 19:29:08Z knut.osmundsen@oracle.com $ */
1+
/* $Id: UsbCardReader.cpp 114701 2026-07-14 13:09:24Z vitali.pelenjow@oracle.com $ */
22
/** @file
33
* UsbCardReader - Usb Smart Card Reader implementation.
44
*/
@@ -26,6 +26,7 @@
2626
*/
2727

2828
#define LOG_GROUP LOG_GROUP_USB_CARDREADER
29+
#include <VBox/AssertGuest.h>
2930
#include <VBox/param.h>
3031
#include <VBox/vmm/pdmusb.h>
3132
#include <VBox/log.h>
@@ -933,9 +934,10 @@ static int uscrResponseOK(PUSBCARDREADER pThis,
933934
}
934935

935936

936-
static uint32_t uscrResponseRead(PUSBCARDREADER pThis,
937-
uint8_t *pu8Data,
938-
uint32_t cbData)
937+
static int uscrResponseRead(PUSBCARDREADER pThis,
938+
uint8_t *pu8Data,
939+
uint32_t cbData,
940+
uint32_t *pcbOut)
939941
{
940942
USCRRSP *pRsp = pThis->pRspCurrent;
941943

@@ -945,7 +947,7 @@ static uint32_t uscrResponseRead(PUSBCARDREADER pThis,
945947

946948
if (!pRsp)
947949
{
948-
return 0;
950+
return VERR_NO_DATA;
949951
}
950952

951953
RTListNodeRemove(&pRsp->nodeRsp);
@@ -983,7 +985,8 @@ static uint32_t uscrResponseRead(PUSBCARDREADER pThis,
983985
/* Save the current response pointer for next invocation. */
984986
pThis->pRspCurrent = pRsp;
985987

986-
return cbToCopy;
988+
*pcbOut = cbToCopy;
989+
return VINF_SUCCESS;
987990
}
988991

989992
static void uscrResponseCleanup(PUSBCARDREADER pThis)
@@ -1013,21 +1016,29 @@ static void uscrResponseCleanup(PUSBCARDREADER pThis)
10131016
}
10141017

10151018

1016-
typedef uint32_t FNREADDATA(PUSBCARDREADER pThis, uint8_t *pu8Data, uint32_t cbData);
1019+
/* Callback to read data into a bulk-in or interrupt URB. Returns VERR_NO_DATA if data is currently not available. */
1020+
typedef int FNREADDATA(PUSBCARDREADER pThis, uint8_t *pu8Data, uint32_t cbData, uint32_t *pcbOut);
10171021
typedef FNREADDATA *PFNREADDATA;
10181022

1019-
static void urbQueueComplete(PUSBCARDREADER pThis, URBQUEUE *pQueue, PFNREADDATA pfnReadData, bool fDataOnly)
1023+
static void urbQueueComplete(PUSBCARDREADER pThis, URBQUEUE *pQueue, PFNREADDATA pfnReadData)
10201024
{
10211025
PVUSBURB pUrb = pQueue->pUrbHead;
10221026
while (pUrb)
10231027
{
1024-
uint32_t cbDataReturned = pfnReadData?
1025-
pfnReadData(pThis, &pUrb->pbData[0], pUrb->cbData):
1026-
0;
1028+
uint32_t cbDataReturned = 0;
10271029

1028-
if (fDataOnly && cbDataReturned == 0)
1030+
/* 'pfnReadData == NULL' means that all queued URBs must be completed with no data. */
1031+
if (pfnReadData)
10291032
{
1030-
break;
1033+
int rc = pfnReadData(pThis, &pUrb->pbData[0], pUrb->cbData, &cbDataReturned);
1034+
if (rc == VERR_NO_DATA)
1035+
{
1036+
/* If the caller wants data and data is not available, then keep the URB in the queue for future data. */
1037+
break;
1038+
}
1039+
1040+
if (RT_FAILURE(rc))
1041+
cbDataReturned = 0; /* Complete URB with zero data size. */
10311042
}
10321043

10331044
bool fRemoved = urbQueueRemove(pQueue, pUrb);
@@ -2388,17 +2399,17 @@ static int usbCardReaderBulkInPipe(PUSBCARDREADER pThis, PUSBCARDREADEREP pEp, P
23882399
* Add the URB to the BulkIn queue and complete URBs from the queue.
23892400
*/
23902401
urbQueueAddTail(&pThis->urbQueues.BulkIn, pUrb);
2391-
urbQueueComplete(pThis, &pThis->urbQueues.BulkIn, uscrResponseRead, true /* fDataOnly */);
2402+
urbQueueComplete(pThis, &pThis->urbQueues.BulkIn, uscrResponseRead);
23922403

23932404
return VINF_SUCCESS;
23942405
}
23952406

23962407

2397-
static uint32_t uscrEventRead(PUSBCARDREADER pThis, uint8_t *pu8Data, uint32_t cbData)
2408+
static int uscrEventRead(PUSBCARDREADER pThis, uint8_t *pu8Data, uint32_t cbData, uint32_t *pcbOut)
23982409
{
2399-
RT_NOREF1(cbData);
2400-
uint32_t cbReturned = 0;
2410+
ASSERT_GUEST_RETURN(cbData >= sizeof(VUSBCARDREADERNOTIFYSLOTCHANGE), VERR_BUFFER_OVERFLOW);
24012411

2412+
int rc = VINF_SUCCESS;
24022413
if (pThis->fICCStateChanged)
24032414
{
24042415
pThis->fICCStateChanged = false;
@@ -2413,12 +2424,14 @@ static uint32_t uscrEventRead(PUSBCARDREADER pThis, uint8_t *pu8Data, uint32_t c
24132424
pNotify->bmSlotICCState |= 0x01; /* ICC present */
24142425
}
24152426

2416-
cbReturned = sizeof(VUSBCARDREADERNOTIFYSLOTCHANGE);
2427+
*pcbOut = sizeof(VUSBCARDREADERNOTIFYSLOTCHANGE);
24172428

2418-
UCRLOG(("Reporting a slot change\n%.*Rhxs\n", cbReturned, pu8Data));
2429+
UCRLOG(("Reporting a slot change\n%.*Rhxs\n", *pcbOut, pu8Data));
24192430
}
2431+
else
2432+
rc = VERR_NO_DATA;
24202433

2421-
return cbReturned;
2434+
return rc;
24222435
}
24232436

24242437

@@ -2433,13 +2446,13 @@ static int usbCardReaderIntPipe(PUSBCARDREADER pThis, PUSBCARDREADEREP pEp, PVUS
24332446

24342447
/* If there is a pending URB, complete it without data. It is most likely cancelled.
24352448
*
2436-
* The webcam does not complete URB if there is no data. Therefore if a new intr-in URB is submitted,
2449+
* The card reader does not complete URB if there is no data. Therefore if a new intr-in URB is submitted,
24372450
* it means that the old URB is not ok anymore and returned data in it may be lost.
24382451
*/
2439-
urbQueueComplete(pThis, &pThis->urbQueues.IntrIn, NULL /* no data */, false /* fDataOnly */);
2452+
urbQueueComplete(pThis, &pThis->urbQueues.IntrIn, NULL /* no data */);
24402453

24412454
urbQueueAddTail(&pThis->urbQueues.IntrIn, pUrb);
2442-
urbQueueComplete(pThis, &pThis->urbQueues.IntrIn, uscrEventRead, true /* fDataOnly */);
2455+
urbQueueComplete(pThis, &pThis->urbQueues.IntrIn, uscrEventRead);
24432456

24442457
return VINF_SUCCESS;
24452458
}
@@ -2593,8 +2606,14 @@ static void uscrStatusMonitorProcess(PUSBCARDREADER pThis)
25932606
* because exclusive access is used. The disconnect request is sent if
25942607
* the card is connected: usbCardReaderSendDisconnect checks this condition.
25952608
*/
2596-
usbCardReaderSendDisconnect(pThis, pSlot, DISCONNECT_ONSTATUSCHANGE);
2597-
pThis->enmICCConnState = ICCNOCONNECTION;
2609+
if ((pThis->u32EventStateBackend & VBOX_SCARD_STATE_EMPTY) != 0)
2610+
{
2611+
/* Some clients send status change notifications even if PRESENT/EMPTY has not chnaged.
2612+
* Try to reconnect only if there is no card.
2613+
*/
2614+
usbCardReaderSendDisconnect(pThis, pSlot, DISCONNECT_ONSTATUSCHANGE);
2615+
pThis->enmICCConnState = ICCNOCONNECTION;
2616+
}
25982617

25992618
bool fForceChanged = (pThis->u32EventStateBackend & VBOX_SCARD_STATE_CHANGED) != 0;
26002619

@@ -2661,7 +2680,7 @@ static DECLCALLBACK(int) uscrStatusMonitor(PPDMUSBINS pUsbIns, PPDMTHREAD pThrea
26612680
{
26622681
uscrStatusMonitorProcess(pThis);
26632682

2664-
urbQueueComplete(pThis, &pThis->urbQueues.IntrIn, uscrEventRead, true /* fDataOnly */);
2683+
urbQueueComplete(pThis, &pThis->urbQueues.IntrIn, uscrEventRead);
26652684
uscrUnlock(pThis);
26662685
}
26672686

@@ -2819,7 +2838,7 @@ static DECLCALLBACK(int) usbSCardReaderConnect(PPDMICARDREADERUP pInterface,
28192838
pThis->fu8Cmd &= ~VUSBCARDREADER_F_CMD_BUSY;
28202839

28212840
/* Process possibly pending bulk-in URBs. */
2822-
urbQueueComplete(pThis, &pThis->urbQueues.BulkIn, uscrResponseRead, true /* fDataOnly */);
2841+
urbQueueComplete(pThis, &pThis->urbQueues.BulkIn, uscrResponseRead);
28232842

28242843
uscrUnlock(pThis);
28252844

@@ -2905,7 +2924,7 @@ static DECLCALLBACK(int) usbSCardReaderDisconnect(PPDMICARDREADERUP pInterface,
29052924
pThis->enmDisconnectReason = DISCONNECT_VOID;
29062925

29072926
/* Process possibly pending bulk-in URBs. */
2908-
urbQueueComplete(pThis, &pThis->urbQueues.BulkIn, uscrResponseRead, true /* fDataOnly */);
2927+
urbQueueComplete(pThis, &pThis->urbQueues.BulkIn, uscrResponseRead);
29092928

29102929
uscrUnlock(pThis);
29112930

@@ -3102,7 +3121,7 @@ static DECLCALLBACK(int) usbSCardReaderTransmit(PPDMICARDREADERUP pInterface,
31023121
}
31033122

31043123
/* Process possibly pending bulk-in URBs. */
3105-
urbQueueComplete(pThis, &pThis->urbQueues.BulkIn, uscrResponseRead, true /* fDataOnly */);
3124+
urbQueueComplete(pThis, &pThis->urbQueues.BulkIn, uscrResponseRead);
31063125

31073126
uscrUnlock(pThis);
31083127

@@ -3258,7 +3277,7 @@ static DECLCALLBACK(int) usbSCardReaderConstruct(PPDMUSBINS pUsbIns, int iInstan
32583277
pThis->hEvtDoneQueue = NIL_RTSEMEVENT;
32593278
rc = RTSemEventCreate(&pThis->hEvtDoneQueue);
32603279
if (RT_FAILURE(rc))
3261-
return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("USBWEBCAM: Failed to create event semaphore"));
3280+
return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("USBSCARDREADER: Failed to create event semaphore"));
32623281

32633282
rc = PDMUsbHlpThreadCreate(pUsbIns, &pThis->pStatusMonitorThread, pThis,
32643283
uscrStatusMonitor, uscrStatusMonitorWakeUp,

0 commit comments

Comments
 (0)