43 |
#define SCARD_AUTOALLOCATE -1 |
#define SCARD_AUTOALLOCATE -1 |
44 |
#define OUT_STREAM_SIZE 4096 |
#define OUT_STREAM_SIZE 4096 |
45 |
|
|
46 |
|
#ifdef B_ENDIAN |
47 |
|
#define swap32(x) ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) | \ |
48 |
|
(((x) & 0xff0000) >> 8) | (((x) & 0xff000000) >> 24)) |
49 |
|
|
50 |
|
#define swap16(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8)) |
51 |
|
#else |
52 |
|
#define swap32(x) (x) |
53 |
|
#define swap16(x) (x) |
54 |
|
#endif |
55 |
|
|
56 |
static pthread_mutex_t **scard_mutex = NULL; |
static pthread_mutex_t **scard_mutex = NULL; |
57 |
|
|
58 |
static uint32 curDevice = 0, curId = 0, curBytesOut = 0; |
static uint32 curDevice = 0, curId = 0, curBytesOut = 0; |
61 |
|
|
62 |
static pthread_t queueHandler; |
static pthread_t queueHandler; |
63 |
static pthread_mutex_t queueAccess; |
static pthread_mutex_t queueAccess; |
64 |
static pthread_mutex_t queueEmpty; |
static pthread_cond_t queueEmpty; |
65 |
static pthread_mutex_t hcardAccess; |
static pthread_mutex_t hcardAccess; |
66 |
|
|
67 |
static PMEM_HANDLE threadListHandle = NULL; |
static PMEM_HANDLE threadListHandle = NULL; |
148 |
return 0; |
return 0; |
149 |
} |
} |
150 |
|
|
151 |
if (0 != pthread_mutex_init(&queueEmpty, NULL)) |
if (0 != pthread_cond_init(&queueEmpty, NULL)) |
152 |
{ |
{ |
153 |
error("scard_enum_devices: Can't initialize queue control mutex\n"); |
error("scard_enum_devices: Can't initialize queue control cv\n"); |
154 |
return 0; |
return 0; |
155 |
} |
} |
156 |
|
|
620 |
} |
} |
621 |
else |
else |
622 |
{ |
{ |
623 |
DEBUG_SCARD(("SCARD: -> Success (context: 0x%08x)\n", (unsigned) hContext)); |
DEBUG_SCARD(("SCARD: -> Success (context: 0x%08lx)\n", hContext)); |
624 |
} |
} |
625 |
|
|
626 |
out_uint32_le(out, 0x00000004); |
out_uint32_le(out, 0x00000004); |
1063 |
{ |
{ |
1064 |
SERVER_DWORD dataLength; |
SERVER_DWORD dataLength; |
1065 |
|
|
1066 |
|
/* Do endian swaps... */ |
1067 |
|
cur->dwCurrentState = swap32(cur->dwCurrentState); |
1068 |
|
cur->dwEventState = swap32(cur->dwEventState); |
1069 |
|
cur->cbAtr = swap32(cur->cbAtr); |
1070 |
|
|
1071 |
/* reset Current state hign bytes; */ |
/* reset Current state hign bytes; */ |
1072 |
*curState = cur->dwCurrentState; |
*curState = cur->dwCurrentState; |
1073 |
cur->dwCurrentState &= 0x0000FFFF; |
cur->dwCurrentState &= 0x0000FFFF; |
1175 |
(unsigned) cur->pvUserData, (unsigned) cur->dwCurrentState, |
(unsigned) cur->pvUserData, (unsigned) cur->dwCurrentState, |
1176 |
(unsigned) cur->dwEventState)); |
(unsigned) cur->dwEventState)); |
1177 |
|
|
1178 |
|
/* Do endian swaps... */ |
1179 |
|
cur->dwCurrentState = swap32(cur->dwCurrentState); |
1180 |
|
cur->dwEventState = swap32(cur->dwEventState); |
1181 |
|
cur->cbAtr = swap32(cur->cbAtr); |
1182 |
|
|
1183 |
out_uint8p(out, (void *) ((unsigned char **) cur + 2), |
out_uint8p(out, (void *) ((unsigned char **) cur + 2), |
1184 |
sizeof(SERVER_SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *)); |
sizeof(SERVER_SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *)); |
1185 |
} |
} |
1245 |
|
|
1246 |
for (i = 0, cur = pAtrMasks; i < atrMaskCount; i++, cur++) |
for (i = 0, cur = pAtrMasks; i < atrMaskCount; i++, cur++) |
1247 |
{ |
{ |
1248 |
|
cur->cbAtr = swap32(cur->cbAtr); |
1249 |
|
|
1250 |
DEBUG_SCARD(("SCARD: ATR: ")); |
DEBUG_SCARD(("SCARD: ATR: ")); |
1251 |
for (j = 0; j < pAtrMasks->cbAtr; j++) |
for (j = 0; j < pAtrMasks->cbAtr; j++) |
1252 |
{ |
{ |
1273 |
ResArray = SC_xmalloc(&lcHandle, readerCount * sizeof(SERVER_SCARD_READERSTATE_A)); |
ResArray = SC_xmalloc(&lcHandle, readerCount * sizeof(SERVER_SCARD_READERSTATE_A)); |
1274 |
if (!ResArray) |
if (!ResArray) |
1275 |
return SC_returnNoMemoryError(&lcHandle, in, out); |
return SC_returnNoMemoryError(&lcHandle, in, out); |
|
memcpy(ResArray, rsArray, readerCount * sizeof(SERVER_SCARD_READERSTATE_A)); |
|
1276 |
|
|
1277 |
for (i = 0, rsCur = rsArray; i < readerCount; i++, rsCur++) |
for (i = 0, rsCur = rsArray; i < readerCount; i++, rsCur++) |
1278 |
{ |
{ |
1279 |
|
/* Do endian swaps... */ |
1280 |
|
rsCur->dwCurrentState = swap32(rsCur->dwCurrentState); |
1281 |
|
rsCur->dwEventState = swap32(rsCur->dwEventState); |
1282 |
|
rsCur->cbAtr = swap32(rsCur->cbAtr); |
1283 |
|
|
1284 |
inReaderName(&lcHandle, in, (char **) &rsCur->szReader, wide); |
inReaderName(&lcHandle, in, (char **) &rsCur->szReader, wide); |
1285 |
DEBUG_SCARD(("SCARD: \"%s\"\n", rsCur->szReader ? rsCur->szReader : "NULL")); |
DEBUG_SCARD(("SCARD: \"%s\"\n", rsCur->szReader ? rsCur->szReader : "NULL")); |
1286 |
DEBUG_SCARD(("SCARD: user: 0x%08x, state: 0x%08x, event: 0x%08x\n", |
DEBUG_SCARD(("SCARD: user: 0x%08x, state: 0x%08x, event: 0x%08x\n", |
1287 |
(unsigned) rsCur->pvUserData, (unsigned) rsCur->dwCurrentState, |
(unsigned) rsCur->pvUserData, (unsigned) rsCur->dwCurrentState, |
1288 |
(unsigned) rsCur->dwEventState)); |
(unsigned) rsCur->dwEventState)); |
1289 |
} |
} |
1290 |
|
memcpy(ResArray, rsArray, readerCount * sizeof(SERVER_SCARD_READERSTATE_A)); |
1291 |
|
|
1292 |
/* FIXME segfault here. */ |
/* FIXME segfault here. */ |
1293 |
myRsArray = SC_xmalloc(&lcHandle, readerCount * sizeof(MYPCSC_SCARD_READERSTATE_A)); |
myRsArray = SC_xmalloc(&lcHandle, readerCount * sizeof(MYPCSC_SCARD_READERSTATE_A)); |
1336 |
out_uint32_le(out, 0x00084dd8); |
out_uint32_le(out, 0x00084dd8); |
1337 |
out_uint32_le(out, readerCount); |
out_uint32_le(out, readerCount); |
1338 |
|
|
1339 |
for (i = 0, rsCur = rsArray; i < readerCount; i++, rsCur++) |
for (i = 0, rsCur = ResArray; i < readerCount; i++, rsCur++) |
1340 |
{ |
{ |
1341 |
|
/* Do endian swaps... */ |
1342 |
|
rsCur->dwCurrentState = swap32(rsCur->dwCurrentState); |
1343 |
|
rsCur->dwEventState = swap32(rsCur->dwEventState); |
1344 |
|
rsCur->cbAtr = swap32(rsCur->cbAtr); |
1345 |
|
|
1346 |
out_uint8p(out, (void *) ((unsigned char **) rsCur + 2), |
out_uint8p(out, (void *) ((unsigned char **) rsCur + 2), |
1347 |
sizeof(SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *)); |
sizeof(SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *)); |
1348 |
} |
} |
1420 |
size_t bytesToCopy = src->cbPciLength - sizeof(MYPCSC_SCARD_IO_REQUEST); |
size_t bytesToCopy = src->cbPciLength - sizeof(MYPCSC_SCARD_IO_REQUEST); |
1421 |
srcBytes = ((unsigned char *) src + sizeof(MYPCSC_SCARD_IO_REQUEST)); |
srcBytes = ((unsigned char *) src + sizeof(MYPCSC_SCARD_IO_REQUEST)); |
1422 |
dstBytes = ((unsigned char *) dst + sizeof(SERVER_SCARD_IO_REQUEST)); |
dstBytes = ((unsigned char *) dst + sizeof(SERVER_SCARD_IO_REQUEST)); |
1423 |
dst->dwProtocol = src->dwProtocol; |
dst->dwProtocol = swap32((uint32_t)src->dwProtocol); |
1424 |
dst->cbPciLength = src->cbPciLength |
dst->cbPciLength = swap32((uint32_t)src->cbPciLength |
1425 |
- sizeof(MYPCSC_SCARD_IO_REQUEST) + sizeof(SERVER_SCARD_IO_REQUEST); |
- sizeof(MYPCSC_SCARD_IO_REQUEST) + sizeof(SERVER_SCARD_IO_REQUEST)); |
1426 |
memcpy(dstBytes, srcBytes, bytesToCopy); |
memcpy(dstBytes, srcBytes, bytesToCopy); |
1427 |
} |
} |
1428 |
|
|
1433 |
size_t bytesToCopy = src->cbPciLength - sizeof(SERVER_SCARD_IO_REQUEST); |
size_t bytesToCopy = src->cbPciLength - sizeof(SERVER_SCARD_IO_REQUEST); |
1434 |
srcBytes = ((unsigned char *) src + sizeof(SERVER_SCARD_IO_REQUEST)); |
srcBytes = ((unsigned char *) src + sizeof(SERVER_SCARD_IO_REQUEST)); |
1435 |
dstBytes = ((unsigned char *) dst + sizeof(MYPCSC_SCARD_IO_REQUEST)); |
dstBytes = ((unsigned char *) dst + sizeof(MYPCSC_SCARD_IO_REQUEST)); |
1436 |
dst->dwProtocol = src->dwProtocol; |
dst->dwProtocol = swap32(src->dwProtocol); |
1437 |
dst->cbPciLength = src->cbPciLength |
dst->cbPciLength = src->cbPciLength /* already correct endian */ |
1438 |
- sizeof(SERVER_SCARD_IO_REQUEST) + sizeof(MYPCSC_SCARD_IO_REQUEST); |
- sizeof(SERVER_SCARD_IO_REQUEST) + sizeof(MYPCSC_SCARD_IO_REQUEST); |
1439 |
memcpy(dstBytes, srcBytes, bytesToCopy); |
memcpy(dstBytes, srcBytes, bytesToCopy); |
1440 |
} |
} |
1595 |
{ |
{ |
1596 |
DEBUG_SCARD(("SCARD: -> Success (%d bytes)\n", (int) cbRecvLength)); |
DEBUG_SCARD(("SCARD: -> Success (%d bytes)\n", (int) cbRecvLength)); |
1597 |
#if 0 |
#if 0 |
1598 |
if ((pioRecvPci != NULL) && (pioRecvPci->cbPciLength > 0)) |
if ((pioRecvPci != NULL) && (mypioRecvPci->cbPciLength > 0)) |
1599 |
{ |
{ |
1600 |
out_uint32_le(out, (DWORD) pioRecvPci); /* if not NULL, this 4 bytes indicates that pioRecvPci is present */ |
out_uint32_le(out, (DWORD) pioRecvPci); /* if not NULL, this 4 bytes indicates that pioRecvPci is present */ |
1601 |
} |
} |
1606 |
outBufferStart(out, cbRecvLength); /* start of recvBuf output */ |
outBufferStart(out, cbRecvLength); /* start of recvBuf output */ |
1607 |
|
|
1608 |
#if 0 |
#if 0 |
1609 |
if ((pioRecvPci) && (pioRecvPci->cbPciLength > 0)) |
if ((pioRecvPci) && (mypioRecvPci->cbPciLength > 0)) |
1610 |
{ |
{ |
1611 |
out_uint32_le(out, pioRecvPci->dwProtocol); |
out_uint32_le(out, mypioRecvPci->dwProtocol); |
1612 |
int len = pioRecvPci->cbPciLength - sizeof(pioRecvPci); |
int len = mypioRecvPci->cbPciLength - sizeof(mypioRecvPci); |
1613 |
outBufferStartWithLimit(out, len, 12); |
outBufferStartWithLimit(out, len, 12); |
1614 |
outBufferFinishWithLimit(out, |
outBufferFinishWithLimit(out, |
1615 |
(char *) ((DWORD) pioRecvPci + sizeof(pioRecvPci)), |
(char *) ((DWORD) pioRecvPci + sizeof(pioRecvPci)), |
1652 |
if (dwAtrLen <= 0 || dwAtrLen == SCARD_AUTOALLOCATE || dwAtrLen > SCARD_MAX_MEM) |
if (dwAtrLen <= 0 || dwAtrLen == SCARD_AUTOALLOCATE || dwAtrLen > SCARD_MAX_MEM) |
1653 |
dwAtrLen = SCARD_MAX_MEM; |
dwAtrLen = SCARD_MAX_MEM; |
1654 |
|
|
1655 |
|
#if 1 |
1656 |
|
/* |
1657 |
|
* Active client sometimes sends a readerlen *just* big enough |
1658 |
|
* SCardStatus doesn't seem to like this. This is a workaround, |
1659 |
|
* aka hack! |
1660 |
|
*/ |
1661 |
|
dwReaderLen = 200; |
1662 |
|
#endif |
1663 |
|
|
1664 |
readerName = SC_xmalloc(&lcHandle, dwReaderLen + 2); |
readerName = SC_xmalloc(&lcHandle, dwReaderLen + 2); |
1665 |
if (!readerName) |
if (!readerName) |
1666 |
return SC_returnNoMemoryError(&lcHandle, in, out); |
return SC_returnNoMemoryError(&lcHandle, in, out); |
2423 |
if (!queueFirst) |
if (!queueFirst) |
2424 |
queueFirst = data; |
queueFirst = data; |
2425 |
|
|
2426 |
pthread_mutex_unlock(&queueEmpty); |
pthread_cond_broadcast(&queueEmpty); |
2427 |
pthread_mutex_unlock(&queueAccess); |
pthread_mutex_unlock(&queueAccess); |
2428 |
} |
} |
2429 |
return data; |
return data; |
2443 |
SC_getNextInQueue() |
SC_getNextInQueue() |
2444 |
{ |
{ |
2445 |
PSCThreadData Result = NULL; |
PSCThreadData Result = NULL; |
2446 |
|
|
2447 |
pthread_mutex_lock(&queueAccess); |
pthread_mutex_lock(&queueAccess); |
2448 |
if (queueFirst != NULL) |
|
2449 |
|
while (queueFirst == NULL) |
2450 |
|
pthread_cond_wait(&queueEmpty, &queueAccess); |
2451 |
|
|
2452 |
|
Result = queueFirst; |
2453 |
|
queueFirst = queueFirst->next; |
2454 |
|
if (!queueFirst) |
2455 |
{ |
{ |
2456 |
Result = queueFirst; |
queueLast = NULL; |
|
queueFirst = queueFirst->next; |
|
|
if (!queueFirst) |
|
|
{ |
|
|
queueLast = NULL; |
|
|
pthread_mutex_trylock(&queueEmpty); |
|
|
} |
|
|
Result->next = NULL; |
|
2457 |
} |
} |
2458 |
|
Result->next = NULL; |
2459 |
|
|
2460 |
pthread_mutex_unlock(&queueAccess); |
pthread_mutex_unlock(&queueAccess); |
2461 |
|
|
2462 |
return Result; |
return Result; |
2463 |
} |
} |
2464 |
|
|
2476 |
static void * |
static void * |
2477 |
thread_function(PThreadListElement listElement) |
thread_function(PThreadListElement listElement) |
2478 |
{ |
{ |
2479 |
if ((listElement != NULL) && (listElement->data != NULL)) |
pthread_mutex_lock(&listElement->busy); |
2480 |
|
while (1) |
2481 |
{ |
{ |
2482 |
while (1) |
while (listElement->data == NULL) |
2483 |
{ |
pthread_cond_wait(&listElement->nodata, |
2484 |
pthread_mutex_lock(&listElement->nodata); |
&listElement->busy); |
2485 |
SC_deviceControl(listElement->data); |
|
2486 |
listElement->data = NULL; |
SC_deviceControl(listElement->data); |
2487 |
pthread_mutex_unlock(&listElement->busy); |
listElement->data = NULL; |
|
} |
|
2488 |
} |
} |
2489 |
|
pthread_mutex_unlock(&listElement->busy); |
2490 |
|
|
2491 |
pthread_exit(NULL); |
pthread_exit(NULL); |
2492 |
return NULL; |
return NULL; |
2493 |
} |
} |
2496 |
SC_handleRequest(PSCThreadData data) |
SC_handleRequest(PSCThreadData data) |
2497 |
{ |
{ |
2498 |
int Result = 0; |
int Result = 0; |
2499 |
PThreadListElement cur = threadList, last = threadList; |
PThreadListElement cur; |
2500 |
|
|
2501 |
while (cur) |
for (cur = threadList; cur != NULL; cur = cur->next) { |
2502 |
{ |
if (cur->data == NULL) { |
2503 |
if (0 == pthread_mutex_trylock(&cur->busy)) |
pthread_mutex_lock(&cur->busy); |
2504 |
{ |
/* double check with lock held.... */ |
2505 |
|
if (cur->data != NULL) { |
2506 |
|
pthread_mutex_unlock(&cur->busy); |
2507 |
|
continue; |
2508 |
|
} |
2509 |
|
|
2510 |
|
/* Wake up thread */ |
2511 |
cur->data = data; |
cur->data = data; |
2512 |
pthread_mutex_unlock(&cur->nodata); |
pthread_cond_broadcast(&cur->nodata); |
2513 |
|
pthread_mutex_unlock(&cur->busy); |
2514 |
return; |
return; |
2515 |
} |
} |
|
else |
|
|
{ |
|
|
last = cur; |
|
|
cur = cur->next; |
|
|
} |
|
2516 |
} |
} |
2517 |
|
|
2518 |
cur = SC_xmalloc(&threadListHandle, sizeof(TThreadListElement)); |
cur = SC_xmalloc(&threadListHandle, sizeof(TThreadListElement)); |
2521 |
|
|
2522 |
threadCount++; |
threadCount++; |
2523 |
|
|
|
cur->next = NULL; |
|
2524 |
pthread_mutex_init(&cur->busy, NULL); |
pthread_mutex_init(&cur->busy, NULL); |
2525 |
pthread_mutex_init(&cur->nodata, NULL); |
pthread_cond_init(&cur->nodata, NULL); |
|
pthread_mutex_trylock(&cur->busy); |
|
2526 |
cur->data = data; |
cur->data = data; |
|
pthread_mutex_unlock(&cur->nodata); |
|
2527 |
|
|
2528 |
Result = pthread_create(&cur->thread, NULL, (void *(*)(void *)) thread_function, cur); |
Result = pthread_create(&cur->thread, NULL, (void *(*)(void *)) thread_function, cur); |
2529 |
if (0 != Result) |
if (0 != Result) |
2533 |
SC_destroyThreadData(data); |
SC_destroyThreadData(data); |
2534 |
data = NULL; |
data = NULL; |
2535 |
} |
} |
2536 |
else if (last) |
cur->next = threadList; |
2537 |
last->next = cur; |
threadList = cur; |
|
else |
|
|
threadList = cur; |
|
2538 |
} |
} |
2539 |
|
|
2540 |
static void * |
static void * |
2544 |
while (1) |
while (1) |
2545 |
{ |
{ |
2546 |
cur_data = SC_getNextInQueue(); |
cur_data = SC_getNextInQueue(); |
2547 |
if (cur_data != NULL) |
switch (cur_data->request) |
2548 |
{ |
{ |
2549 |
switch (cur_data->request) |
case SC_ESTABLISH_CONTEXT: |
2550 |
{ |
case SC_RELEASE_CONTEXT: |
2551 |
case SC_ESTABLISH_CONTEXT: |
{ |
2552 |
case SC_RELEASE_CONTEXT: |
SC_deviceControl(cur_data); |
2553 |
{ |
break; |
2554 |
SC_deviceControl(cur_data); |
} |
2555 |
break; |
default: |
2556 |
} |
{ |
2557 |
default: |
SC_handleRequest(cur_data); |
2558 |
{ |
break; |
2559 |
SC_handleRequest(cur_data); |
} |
|
break; |
|
|
} |
|
|
} |
|
|
cur_data = NULL; |
|
2560 |
} |
} |
|
else |
|
|
pthread_mutex_lock(&queueEmpty); |
|
2561 |
} |
} |
2562 |
return NULL; |
return NULL; |
2563 |
} |
} |