Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1698 lines
48 KiB

  1. /*++
  2. Copyright (C) 1997, 98 Microsoft Corporation
  3. Module Name:
  4. tlp3cb.c
  5. Abstract:
  6. Callback functions for smart card library
  7. Author:
  8. Klaus U. Schutz
  9. Environment:
  10. Kernel mode
  11. --*/
  12. #include <stdio.h>
  13. #include "bulltlp3.h"
  14. #pragma alloc_text(PAGEABLE, TLP3SetProtocol)
  15. #pragma alloc_text(PAGEABLE, TLP3SetParameters)
  16. #pragma alloc_text(PAGEABLE, TLP3TransmitT0)
  17. #pragma alloc_text(PAGEABLE, TLP3Transmit)
  18. #pragma alloc_text(PAGEABLE, TLP3VendorIoctl)
  19. NTSTATUS
  20. TLP3ReaderPower(
  21. PSMARTCARD_EXTENSION SmartcardExtension
  22. )
  23. /*++
  24. Routine Description:
  25. The smart card lib requires to have this function. It is called
  26. for certain power requests to the card. We do nothing here, because
  27. this action is performed in the StartIo function.
  28. --*/
  29. {
  30. ULONG step, waitTime, TdIndex, numTry = 0, minWaitTime;
  31. NTSTATUS status = STATUS_SUCCESS;
  32. PSERIAL_STATUS serialStatus;
  33. KIRQL oldIrql;
  34. PUCHAR requestBuffer;
  35. PSERIAL_READER_CONFIG serialConfigData =
  36. &SmartcardExtension->ReaderExtension->SerialConfigData;
  37. SmartcardDebug(
  38. DEBUG_TRACE,
  39. ("%s!TLP3ReaderPower: Enter (%lx)\n",
  40. DRIVER_NAME,
  41. SmartcardExtension->MinorIoControlCode)
  42. );
  43. _try {
  44. #if defined (DEBUG) && defined (DETECT_SERIAL_OVERRUNS)
  45. // we have to call GetCommStatus to reset the error condition
  46. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  47. IOCTL_SERIAL_GET_COMMSTATUS;
  48. SmartcardExtension->SmartcardRequest.BufferLength = 0;
  49. SmartcardExtension->SmartcardReply.BufferLength =
  50. sizeof(SERIAL_STATUS);
  51. status = TLP3SerialIo(SmartcardExtension);
  52. ASSERT(status == STATUS_SUCCESS);
  53. #endif
  54. //
  55. // Set standard parameters for serial port
  56. //
  57. serialConfigData->LineControl.Parity = EVEN_PARITY;
  58. serialConfigData->LineControl.StopBits = STOP_BITS_2;
  59. serialConfigData->BaudRate.BaudRate =
  60. SmartcardExtension->ReaderCapabilities.DataRate.Default;
  61. // we set very short timeouts to get the ATR as fast as possible
  62. serialConfigData->Timeouts.ReadIntervalTimeout =
  63. READ_INTERVAL_TIMEOUT_ATR;
  64. serialConfigData->Timeouts.ReadTotalTimeoutConstant =
  65. READ_TOTAL_TIMEOUT_CONSTANT_ATR;
  66. status = TLP3ConfigureSerialPort(SmartcardExtension);
  67. ASSERT(status == STATUS_SUCCESS);
  68. if (status != STATUS_SUCCESS) {
  69. leave;
  70. }
  71. // We don't send data to the reader, so set Number of bytes to send = 0
  72. SmartcardExtension->SmartcardRequest.BufferLength = 0;
  73. // Default number of bytes we expect to get back
  74. SmartcardExtension->SmartcardReply.BufferLength = 0;
  75. //
  76. // Since power down triggers the UpdateSerialStatus function, we have
  77. // to inform it that we forced the change of the status and not the user
  78. // (who might have removed and inserted a card)
  79. //
  80. // SmartcardExtension->ReaderExtension->PowerRequest = TRUE;
  81. // purge the serial buffer (it can contain the pnp id of the reader)
  82. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  83. IOCTL_SERIAL_PURGE;
  84. *(PULONG) SmartcardExtension->SmartcardRequest.Buffer =
  85. SERIAL_PURGE_RXCLEAR | SERIAL_PURGE_TXCLEAR;;
  86. SmartcardExtension->SmartcardRequest.BufferLength =
  87. sizeof(ULONG);
  88. status = TLP3SerialIo(SmartcardExtension);
  89. ASSERT(status == STATUS_SUCCESS);
  90. if (status != STATUS_SUCCESS) {
  91. leave;
  92. }
  93. SmartcardExtension->CardCapabilities.ATR.Length = 0;
  94. for (step = 0; NT_SUCCESS(status); step++) {
  95. if (SmartcardExtension->MinorIoControlCode ==
  96. SCARD_WARM_RESET &&
  97. step == 0) {
  98. step = 4;
  99. }
  100. switch (step) {
  101. case 0:
  102. // RTS = 0 means reader is in command mode
  103. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  104. IOCTL_SERIAL_CLR_RTS;
  105. //
  106. // This is the minimum wait time we have to wait before
  107. // we can send commands to the microcontroller.
  108. //
  109. waitTime = 1000;
  110. break;
  111. case 1:
  112. // write power down command to the reader
  113. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  114. SMARTCARD_WRITE;
  115. SmartcardExtension->SmartcardRequest.BufferLength = 1;
  116. SmartcardExtension->SmartcardRequest.Buffer[0] =
  117. READER_CMD_POWER_DOWN;
  118. waitTime = 100;
  119. break;
  120. case 2:
  121. // Read back the echo of the reader
  122. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  123. SMARTCARD_READ;
  124. SmartcardExtension->SmartcardReply.BufferLength = 1;
  125. // Wait the recovery time for the microcontroller
  126. waitTime = 1000;
  127. break;
  128. case 3:
  129. // set RTS again so the microcontroller can execute the command
  130. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  131. IOCTL_SERIAL_SET_RTS;
  132. waitTime = 10000;
  133. break;
  134. case 4:
  135. if (SmartcardExtension->MinorIoControlCode == SCARD_POWER_DOWN) {
  136. if (SmartcardExtension->ReaderCapabilities.CurrentState >
  137. SCARD_PRESENT) {
  138. SmartcardExtension->ReaderCapabilities.CurrentState =
  139. SCARD_PRESENT;
  140. }
  141. SmartcardExtension->CardCapabilities.Protocol.Selected =
  142. SCARD_PROTOCOL_UNDEFINED;
  143. status = STATUS_SUCCESS;
  144. leave;
  145. }
  146. // clear RTS to switch to command mode
  147. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  148. IOCTL_SERIAL_CLR_RTS;
  149. // Wait the recovery time for the microcontroller
  150. waitTime = 1000;
  151. break;
  152. case 5:
  153. // write the appropriate reset command to the reader
  154. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  155. SMARTCARD_WRITE;
  156. SmartcardExtension->SmartcardRequest.BufferLength = 1;
  157. switch (SmartcardExtension->MinorIoControlCode) {
  158. case SCARD_COLD_RESET:
  159. SmartcardExtension->SmartcardRequest.Buffer[0] =
  160. READER_CMD_COLD_RESET;
  161. break;
  162. case SCARD_WARM_RESET:
  163. SmartcardExtension->SmartcardRequest.Buffer[0] =
  164. READER_CMD_WARM_RESET;
  165. break;
  166. }
  167. waitTime = 100;
  168. break;
  169. case 6:
  170. // Read back the echo of the reader
  171. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  172. SMARTCARD_READ;
  173. SmartcardExtension->SmartcardReply.BufferLength = 1;
  174. //
  175. // This is the time we need to wait for the microcontroller
  176. // to recover before we can set RTS again
  177. //
  178. waitTime = 1000;
  179. break;
  180. case 7:
  181. // set RTS again so the microcontroller can execute the command
  182. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  183. IOCTL_SERIAL_SET_RTS;
  184. waitTime = 10000;
  185. break;
  186. case 8:
  187. //
  188. // We now try to get the ATR as fast as possible.
  189. // Therefor we prev. set a very short read timeout and
  190. // 'hope' that the card delivered its ATR within this
  191. // short time. To verify the correctness of the ATR we call
  192. // SmartcardUpdateCardCapabilities(). If this call returns
  193. // with STATUS_SUCCESS we know that the ATR is complete.
  194. // Otherwise we read again and append the new data to the
  195. // ATR buffer in the CardCapabilities and try again.
  196. //
  197. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  198. SMARTCARD_READ;
  199. SmartcardExtension->SmartcardReply.BufferLength =
  200. MAXIMUM_ATR_LENGTH -
  201. SmartcardExtension->CardCapabilities.ATR.Length;
  202. waitTime = 0;
  203. break;
  204. case 9:
  205. if (SmartcardExtension->SmartcardReply.BufferLength != 0) {
  206. ASSERT(
  207. SmartcardExtension->CardCapabilities.ATR.Length +
  208. SmartcardExtension->SmartcardReply.BufferLength <
  209. MAXIMUM_ATR_LENGTH
  210. );
  211. if( SmartcardExtension->CardCapabilities.ATR.Length +
  212. SmartcardExtension->SmartcardReply.BufferLength >=
  213. MAXIMUM_ATR_LENGTH) {
  214. status = STATUS_UNRECOGNIZED_MEDIA;
  215. leave;
  216. }
  217. // we got some ATR bytes.
  218. RtlCopyMemory(
  219. SmartcardExtension->CardCapabilities.ATR.Buffer +
  220. SmartcardExtension->CardCapabilities.ATR.Length,
  221. SmartcardExtension->SmartcardReply.Buffer,
  222. SmartcardExtension->SmartcardReply.BufferLength
  223. );
  224. SmartcardExtension->CardCapabilities.ATR.Length +=
  225. (UCHAR) SmartcardExtension->SmartcardReply.BufferLength;
  226. status = SmartcardUpdateCardCapabilities(
  227. SmartcardExtension
  228. );
  229. }
  230. if (status != STATUS_SUCCESS && numTry < 25) {
  231. if (SmartcardExtension->SmartcardReply.BufferLength != 0) {
  232. // Because we received some data, we reset our counter
  233. numTry = 0;
  234. } else {
  235. // ATR is incomplete. Try again to get ATR bytes.
  236. numTry += 1;
  237. }
  238. // continue with step 8
  239. step = 7;
  240. status = STATUS_TIMEOUT;
  241. continue;
  242. }
  243. if (status != STATUS_SUCCESS) {
  244. leave;
  245. }
  246. // No break
  247. case 10:
  248. KeAcquireSpinLock(
  249. &SmartcardExtension->OsData->SpinLock,
  250. &oldIrql
  251. );
  252. if (SmartcardExtension->ReaderCapabilities.CurrentState <=
  253. SCARD_ABSENT) {
  254. status = STATUS_MEDIA_CHANGED;
  255. }
  256. KeReleaseSpinLock(
  257. &SmartcardExtension->OsData->SpinLock,
  258. oldIrql
  259. );
  260. if (status != STATUS_SUCCESS) {
  261. leave;
  262. }
  263. #ifdef SIMULATION
  264. if (SmartcardExtension->ReaderExtension->SimulationLevel &
  265. SIM_ATR_TRASH) {
  266. ULONG index;
  267. LARGE_INTEGER tickCount;
  268. KeQueryTickCount(
  269. &tickCount
  270. );
  271. SmartcardExtension->CardCapabilities.ATR.Length =
  272. (UCHAR) tickCount.LowPart % MAXIMUM_ATR_LENGTH;
  273. for (index = 0;
  274. index < SmartcardExtension->CardCapabilities.ATR.Length;
  275. index++) {
  276. SmartcardExtension->CardCapabilities.ATR.Buffer[index] *=
  277. (UCHAR) tickCount.LowPart;
  278. }
  279. SmartcardDebug(
  280. DEBUG_SIMULATION,
  281. ("%s!TLP3ReaderPower: SIM ATR trash\n",
  282. DRIVER_NAME)
  283. );
  284. }
  285. #endif
  286. // Copy ATR to user space
  287. if (SmartcardExtension->IoRequest.ReplyBuffer) {
  288. RtlCopyMemory(
  289. SmartcardExtension->IoRequest.ReplyBuffer,
  290. SmartcardExtension->CardCapabilities.ATR.Buffer,
  291. SmartcardExtension->CardCapabilities.ATR.Length
  292. );
  293. // Tell user length of ATR
  294. *SmartcardExtension->IoRequest.Information =
  295. SmartcardExtension->CardCapabilities.ATR.Length;
  296. }
  297. //
  298. // If the card uses invers convention we need to switch
  299. // the serial driver to odd paritiy
  300. //
  301. if (SmartcardExtension->CardCapabilities.InversConvention) {
  302. serialConfigData->LineControl.Parity = ODD_PARITY;
  303. }
  304. //
  305. // If the extra guard time is 255 it means that our
  306. // frame we have to expect from the card has only
  307. // 1 instead of 2 stop bits
  308. // 1start bit + 8data bits + 1parity + 1stop == 11 etu
  309. // see iso 7816-3 6.1.4.4 Extra Guard Time N
  310. //
  311. if (SmartcardExtension->CardCapabilities.PtsData.StopBits == 1) {
  312. serialConfigData->LineControl.StopBits = STOP_BIT_1;
  313. }
  314. // Change data rate according to the new settings
  315. serialConfigData->BaudRate.BaudRate =
  316. SmartcardExtension->CardCapabilities.PtsData.DataRate;
  317. // depending on the protocol set the timeout values
  318. if (SmartcardExtension->CardCapabilities.Protocol.Selected &
  319. SCARD_PROTOCOL_T1) {
  320. // set timeouts
  321. serialConfigData->Timeouts.ReadTotalTimeoutConstant =
  322. SmartcardExtension->CardCapabilities.T1.BWT / 1000;
  323. serialConfigData->Timeouts.ReadIntervalTimeout =
  324. SmartcardExtension->CardCapabilities.T1.CWT / 1000;
  325. } else if (SmartcardExtension->CardCapabilities.Protocol.Selected &
  326. SCARD_PROTOCOL_T0) {
  327. // set timeouts
  328. serialConfigData->Timeouts.ReadTotalTimeoutConstant =
  329. serialConfigData->Timeouts.ReadIntervalTimeout =
  330. SmartcardExtension->CardCapabilities.T0.WT / 1000;
  331. }
  332. // Now make some adjustments depending on the system speed
  333. minWaitTime = (KeQueryTimeIncrement() / 10000) * 5;
  334. if (serialConfigData->Timeouts.ReadTotalTimeoutConstant <
  335. minWaitTime) {
  336. serialConfigData->Timeouts.ReadTotalTimeoutConstant =
  337. minWaitTime;
  338. }
  339. if (serialConfigData->Timeouts.ReadIntervalTimeout <
  340. minWaitTime) {
  341. serialConfigData->Timeouts.ReadIntervalTimeout =
  342. minWaitTime;
  343. }
  344. status = TLP3ConfigureSerialPort(SmartcardExtension);
  345. ASSERT(status == STATUS_SUCCESS);
  346. // We're done anyway, so leave
  347. leave;
  348. }
  349. status = TLP3SerialIo(SmartcardExtension);
  350. if (!NT_SUCCESS(status)) {
  351. leave;
  352. }
  353. if (waitTime) {
  354. LARGE_INTEGER delayPeriod;
  355. delayPeriod.HighPart = -1;
  356. delayPeriod.LowPart = waitTime * (-10);
  357. KeDelayExecutionThread(
  358. KernelMode,
  359. FALSE,
  360. &delayPeriod
  361. );
  362. }
  363. }
  364. }
  365. _finally {
  366. if (status == STATUS_TIMEOUT) {
  367. status = STATUS_UNRECOGNIZED_MEDIA;
  368. }
  369. SmartcardExtension->ReaderExtension->PowerRequest = FALSE;
  370. #ifdef SIMULATION
  371. if (SmartcardExtension->ReaderExtension->SimulationLevel &
  372. SIM_WRONG_STATE) {
  373. // inject a wrong state after warm/cold reset
  374. SmartcardExtension->ReaderCapabilities.CurrentState =
  375. SCARD_PRESENT;
  376. SmartcardDebug(
  377. DEBUG_SIMULATION,
  378. ("%s!TLP3ReaderPower: SIM wrong state\n",
  379. DRIVER_NAME)
  380. );
  381. } else if (SmartcardExtension->ReaderExtension->SimulationLevel &
  382. SIM_INVALID_STATE) {
  383. // inject completely invalid state after reset.
  384. LARGE_INTEGER tickCount;
  385. KeQueryTickCount(
  386. &tickCount
  387. );
  388. SmartcardExtension->ReaderCapabilities.CurrentState =
  389. (UCHAR) tickCount.LowPart;
  390. SmartcardDebug(
  391. DEBUG_SIMULATION,
  392. ("%s!TLP3ReaderPower: SIM invalid state %ls\n",
  393. DRIVER_NAME,
  394. SmartcardExtension->ReaderCapabilities.CurrentState)
  395. );
  396. }
  397. if (SmartcardExtension->ReaderExtension->SimulationLevel &
  398. SIM_LONG_RESET_TIMEOUT) {
  399. // inject a random timeout of max 60 sec.
  400. LARGE_INTEGER tickCount;
  401. KeQueryTickCount(
  402. &tickCount
  403. );
  404. tickCount.LowPart %= 60;
  405. SmartcardDebug(
  406. DEBUG_SIMULATION,
  407. ("%s!TLP3ReaderPower: SIM reset wait %ld\n",
  408. DRIVER_NAME,
  409. tickCount.LowPart)
  410. );
  411. tickCount.QuadPart *= -10000000;
  412. KeDelayExecutionThread(
  413. KernelMode,
  414. FALSE,
  415. &tickCount
  416. );
  417. }
  418. #endif
  419. }
  420. SmartcardDebug(
  421. DEBUG_TRACE,
  422. ("%s!TLP3ReaderPower: Exit (%lx)\n",
  423. DRIVER_NAME,
  424. status)
  425. );
  426. return status;
  427. }
  428. NTSTATUS
  429. TLP3SetProtocol(
  430. PSMARTCARD_EXTENSION SmartcardExtension
  431. )
  432. /*++
  433. Routine Description:
  434. The smart card lib requires to have this function. It is called
  435. to set a the transmission protocol and parameters. If this function
  436. is called with a protocol mask (which means the caller doesn't card
  437. about a particular protocol to be set) we first look if we can
  438. set T=1 and the T=0
  439. Arguments:
  440. SmartcardExtension - Pointer to smart card data struct.
  441. Return Value:
  442. NTSTATUS
  443. --*/
  444. {
  445. NTSTATUS status;
  446. PAGED_CODE();
  447. SmartcardDebug(
  448. DEBUG_TRACE,
  449. ("%s!TLP3SetProtocol: Enter\n",
  450. DRIVER_NAME)
  451. );
  452. try {
  453. PUCHAR ptsRequest = SmartcardExtension->SmartcardRequest.Buffer;
  454. PUCHAR ptsReply = SmartcardExtension->SmartcardReply.Buffer;
  455. PSERIAL_READER_CONFIG serialConfigData =
  456. &SmartcardExtension->ReaderExtension->SerialConfigData;
  457. ULONG minWaitTime, newProtocol;
  458. //
  459. // Check if the card is already in specific state
  460. // and if the caller wants to have the already selected protocol.
  461. // We return success if this is the case.
  462. //
  463. if (SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_SPECIFIC &&
  464. (SmartcardExtension->CardCapabilities.Protocol.Selected &
  465. SmartcardExtension->MinorIoControlCode)) {
  466. status = STATUS_SUCCESS;
  467. leave;
  468. }
  469. // set normal timeout
  470. serialConfigData->Timeouts.ReadIntervalTimeout =
  471. READ_INTERVAL_TIMEOUT_DEFAULT;
  472. serialConfigData->Timeouts.ReadTotalTimeoutConstant =
  473. READ_TOTAL_TIMEOUT_CONSTANT_DEFAULT;
  474. status = TLP3ConfigureSerialPort(SmartcardExtension);
  475. ASSERT(status == STATUS_SUCCESS);
  476. if (status != STATUS_SUCCESS) {
  477. leave;
  478. }
  479. //
  480. // Assemble and send a pts selection
  481. //
  482. newProtocol = SmartcardExtension->MinorIoControlCode;
  483. while(TRUE) {
  484. // set initial character of PTS
  485. ptsRequest[0] = 0xff;
  486. // set the format character
  487. if (SmartcardExtension->CardCapabilities.Protocol.Supported &
  488. newProtocol &
  489. SCARD_PROTOCOL_T1) {
  490. // select T=1 and indicate that pts1 follows
  491. ptsRequest[1] = 0x11;
  492. SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T1;
  493. } else if (SmartcardExtension->CardCapabilities.Protocol.Supported &
  494. newProtocol &
  495. SCARD_PROTOCOL_T0) {
  496. // select T=0 and indicate that pts1 follows
  497. ptsRequest[1] = 0x10;
  498. SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T0;
  499. } else {
  500. status = STATUS_INVALID_DEVICE_REQUEST;
  501. leave;
  502. }
  503. // set pts1 which codes Fl and Dl
  504. ptsRequest[2] =
  505. SmartcardExtension->CardCapabilities.PtsData.Fl << 4 |
  506. SmartcardExtension->CardCapabilities.PtsData.Dl;
  507. // set pck (check character)
  508. ptsRequest[3] = ptsRequest[0] ^ ptsRequest[1] ^ ptsRequest[2];
  509. SmartcardExtension->SmartcardRequest.BufferLength = 4;
  510. SmartcardExtension->ReaderExtension->SerialIoControlCode = SMARTCARD_WRITE;
  511. status = TLP3SerialIo(SmartcardExtension);
  512. if (status != STATUS_SUCCESS) {
  513. leave;
  514. }
  515. // read back the echo of the reader
  516. SmartcardExtension->SmartcardReply.BufferLength = 4;
  517. SmartcardExtension->ReaderExtension->SerialIoControlCode = SMARTCARD_READ;
  518. status = TLP3SerialIo(SmartcardExtension);
  519. if (status != STATUS_SUCCESS) {
  520. leave;
  521. }
  522. // read back the pts data
  523. status = TLP3SerialIo(SmartcardExtension);
  524. if (status != STATUS_SUCCESS &&
  525. status != STATUS_TIMEOUT) {
  526. leave;
  527. }
  528. if (status != STATUS_TIMEOUT &&
  529. memcmp(ptsRequest, ptsReply, 4) == 0) {
  530. // the card replied correctly to our pts-request
  531. break;
  532. }
  533. if (SmartcardExtension->CardCapabilities.PtsData.Type !=
  534. PTS_TYPE_DEFAULT) {
  535. SmartcardDebug(
  536. DEBUG_TRACE,
  537. ("%s!TLP3SetProtocol: PTS failed. Trying default parameters...\n",
  538. DRIVER_NAME,
  539. status)
  540. );
  541. //
  542. // The card did either NOT reply or it replied incorrectly
  543. // so try default values
  544. //
  545. SmartcardExtension->CardCapabilities.PtsData.Type =
  546. PTS_TYPE_DEFAULT;
  547. SmartcardExtension->MinorIoControlCode = SCARD_COLD_RESET;
  548. status = TLP3ReaderPower(SmartcardExtension);
  549. continue;
  550. }
  551. // the card failed the pts-request
  552. status = STATUS_DEVICE_PROTOCOL_ERROR;
  553. leave;
  554. }
  555. //
  556. // The card replied correctly to the pts request
  557. // Set the appropriate parameters for the port
  558. //
  559. if (SmartcardExtension->CardCapabilities.Protocol.Selected &
  560. SCARD_PROTOCOL_T1) {
  561. // set timeouts
  562. serialConfigData->Timeouts.ReadTotalTimeoutConstant =
  563. SmartcardExtension->CardCapabilities.T1.BWT / 1000;
  564. serialConfigData->Timeouts.ReadIntervalTimeout =
  565. SmartcardExtension->CardCapabilities.T1.CWT / 1000;
  566. } else if (SmartcardExtension->CardCapabilities.Protocol.Selected &
  567. SCARD_PROTOCOL_T0) {
  568. // set timeouts
  569. serialConfigData->Timeouts.ReadTotalTimeoutConstant =
  570. serialConfigData->Timeouts.ReadIntervalTimeout =
  571. SmartcardExtension->CardCapabilities.T0.WT / 1000;
  572. }
  573. // Now make some adjustments depending on the system speed
  574. minWaitTime = (KeQueryTimeIncrement() / 10000) * 5;
  575. if (serialConfigData->Timeouts.ReadTotalTimeoutConstant < minWaitTime) {
  576. serialConfigData->Timeouts.ReadTotalTimeoutConstant = minWaitTime;
  577. }
  578. if (serialConfigData->Timeouts.ReadIntervalTimeout < minWaitTime) {
  579. serialConfigData->Timeouts.ReadIntervalTimeout = minWaitTime;
  580. }
  581. // Change data rate according to the new settings
  582. serialConfigData->BaudRate.BaudRate =
  583. SmartcardExtension->CardCapabilities.PtsData.DataRate;
  584. status = TLP3ConfigureSerialPort(SmartcardExtension);
  585. ASSERT(status == STATUS_SUCCESS);
  586. // now indicate that we're in specific mode
  587. SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC;
  588. // return the selected protocol to the caller
  589. *(PULONG) SmartcardExtension->IoRequest.ReplyBuffer =
  590. SmartcardExtension->CardCapabilities.Protocol.Selected;
  591. *SmartcardExtension->IoRequest.Information =
  592. sizeof(SmartcardExtension->CardCapabilities.Protocol.Selected);
  593. }
  594. finally {
  595. if (status == STATUS_TIMEOUT) {
  596. // STATUS_TIMEOUT is not mapped to a Win32 error code
  597. status = STATUS_IO_TIMEOUT;
  598. *SmartcardExtension->IoRequest.Information = 0;
  599. } else if (status != STATUS_SUCCESS) {
  600. SmartcardExtension->CardCapabilities.Protocol.Selected =
  601. SCARD_PROTOCOL_UNDEFINED;
  602. *SmartcardExtension->IoRequest.Information = 0;
  603. }
  604. }
  605. SmartcardDebug(
  606. DEBUG_TRACE,
  607. ("%s!TLP3SetProtocol: Exit(%lx)\n",
  608. DRIVER_NAME,
  609. status)
  610. );
  611. return status;
  612. }
  613. NTSTATUS
  614. TLP3TransmitT0(
  615. PSMARTCARD_EXTENSION SmartcardExtension
  616. )
  617. /*++
  618. Routine Description:
  619. This function performs a T=0 transmission.
  620. Arguments:
  621. SmartcardExtension - Pointer to smart card data struct.
  622. Return Value:
  623. NTSTATUS
  624. --*/
  625. {
  626. PUCHAR requestBuffer = SmartcardExtension->SmartcardRequest.Buffer;
  627. PUCHAR replyBuffer = SmartcardExtension->SmartcardReply.Buffer;
  628. PULONG requestLength = &SmartcardExtension->SmartcardRequest.BufferLength;
  629. PULONG replyLength = &SmartcardExtension->SmartcardReply.BufferLength;
  630. PULONG serialIoControlCode = &SmartcardExtension->ReaderExtension->SerialIoControlCode;
  631. ULONG bytesToSend, bytesToRead, currentByte = 0;
  632. BOOLEAN restartWorkWaitingTime = FALSE;
  633. NTSTATUS status;
  634. PAGED_CODE();
  635. SmartcardDebug(
  636. DEBUG_TRACE,
  637. ("%s!TLP3TransmitT0: Enter\n",
  638. DRIVER_NAME)
  639. );
  640. try {
  641. // Let the lib build a T=0 packet
  642. status = SmartcardT0Request(SmartcardExtension);
  643. if (status != STATUS_SUCCESS)
  644. leave;
  645. //
  646. // The number of bytes we expect from the card
  647. // is Le + 2 status bytes
  648. //
  649. bytesToSend = *requestLength;
  650. bytesToRead = SmartcardExtension->T0.Le + 2;
  651. //
  652. // Send the first 5 bytes to the card
  653. //
  654. *requestLength = 5;
  655. do {
  656. UCHAR procByte;
  657. //
  658. // According to ISO 7816 a procedure byte of
  659. // 60 should be treated as a request for a one time wait.
  660. // In this case we do not write anything to the card
  661. //
  662. if (restartWorkWaitingTime == FALSE) {
  663. SmartcardDebug(
  664. DEBUG_PROTOCOL,
  665. ("%s!TLP3TransmitT0: -> Sending %s (%ld bytes)\n",
  666. DRIVER_NAME,
  667. (currentByte == 0 ? "header" : "data"),
  668. *requestLength)
  669. );
  670. //
  671. // Write to the card
  672. //
  673. *serialIoControlCode = SMARTCARD_WRITE;
  674. SmartcardExtension->SmartcardRequest.Buffer = &requestBuffer[currentByte];
  675. status = TLP3SerialIo(SmartcardExtension);
  676. if (status != STATUS_SUCCESS) {
  677. SmartcardDebug(
  678. DEBUG_ERROR,
  679. ("%s!TLP3TransmitT0: TLP3SerialIo(SMARTCARD_WRITE) returned %lx\n",
  680. DRIVER_NAME,
  681. status)
  682. );
  683. leave;
  684. }
  685. //
  686. // The TLP3 echos all sent bytes. We read the echo
  687. // back into our send buffer
  688. //
  689. *serialIoControlCode = SMARTCARD_READ;
  690. *replyLength = *requestLength;
  691. SmartcardExtension->SmartcardReply.Buffer = &requestBuffer[currentByte];
  692. status = TLP3SerialIo(SmartcardExtension);
  693. if (status != STATUS_SUCCESS) {
  694. SmartcardDebug(
  695. DEBUG_ERROR,
  696. ("%s!TLP3TransmitT0: TLP3SerialIo(SMARTCARD_READ) returned %lx\n",
  697. DRIVER_NAME,
  698. status)
  699. );
  700. leave;
  701. }
  702. currentByte += *requestLength;
  703. bytesToSend -= *requestLength;
  704. }
  705. // Read the 'Procedure byte'.
  706. SmartcardExtension->SmartcardReply.Buffer = &procByte;
  707. *serialIoControlCode = SMARTCARD_READ;
  708. *replyLength = 1;
  709. status = TLP3SerialIo(SmartcardExtension);
  710. if (status != STATUS_SUCCESS) {
  711. SmartcardDebug(
  712. DEBUG_ERROR,
  713. ("%s!TLP3TransmitT0: TLP3SerialIo(SMARTCARD_READ) returned %lx\n",
  714. DRIVER_NAME,
  715. status)
  716. );
  717. leave;
  718. }
  719. restartWorkWaitingTime = FALSE;
  720. //
  721. // Check the procedure byte.
  722. // Please take a look at ISO 7816 Part 3 Section 8.2.2
  723. //
  724. if (procByte == requestBuffer[1] ||
  725. procByte == requestBuffer[1] + 1) {
  726. SmartcardDebug(
  727. DEBUG_PROTOCOL,
  728. ("%s!TLP3TransmitT0: <- ACK (send all)\n",
  729. DRIVER_NAME)
  730. );
  731. // All remaining data bytes can be sent at once
  732. *requestLength = bytesToSend;
  733. } else if (procByte == (UCHAR) ~requestBuffer[1] ||
  734. procByte == (UCHAR) ~(requestBuffer[1] + 1)) {
  735. SmartcardDebug(
  736. DEBUG_PROTOCOL,
  737. ("%s!TLP3TransmitT0: <- ACK (send single)\n",
  738. DRIVER_NAME)
  739. );
  740. // We can send only one byte
  741. *requestLength = 1;
  742. } else if (procByte == 0x60 ||
  743. SmartcardExtension->CardCapabilities.InversConvention &&
  744. procByte == 0xf9) {
  745. //
  746. // We have to reset the wait time and try again to read
  747. //
  748. ULONG TimeRes;
  749. LARGE_INTEGER delayTime;
  750. SmartcardDebug(
  751. DEBUG_PROTOCOL,
  752. ("%s!TLP3TransmitT0: <- NULL (%ldms)\n",
  753. DRIVER_NAME,
  754. SmartcardExtension->CardCapabilities.T0.WT / 1000)
  755. );
  756. TimeRes = KeQueryTimeIncrement();
  757. delayTime.HighPart = -1;
  758. delayTime.LowPart =
  759. (-1) *
  760. TimeRes *
  761. ((SmartcardExtension->CardCapabilities.T0.WT * 10l / TimeRes) + 1);
  762. KeDelayExecutionThread(
  763. KernelMode,
  764. FALSE,
  765. &delayTime
  766. );
  767. //
  768. // Set flag that we only should read the proc byte
  769. // without writing data to the card
  770. //
  771. restartWorkWaitingTime = TRUE;
  772. } else {
  773. //
  774. // The card returned a status byte.
  775. // Status bytes are always two bytes long.
  776. // Store this byte first and then read the next
  777. //
  778. replyBuffer[0] = procByte;
  779. *serialIoControlCode = SMARTCARD_READ;
  780. *replyLength = 1;
  781. bytesToSend = 0;
  782. bytesToRead = 0;
  783. //
  784. // Read in the second status byte
  785. //
  786. SmartcardExtension->SmartcardReply.Buffer =
  787. &replyBuffer[1];
  788. status = TLP3SerialIo(SmartcardExtension);
  789. SmartcardExtension->SmartcardReply.BufferLength = 2;
  790. SmartcardDebug(
  791. (status == STATUS_SUCCESS ? DEBUG_PROTOCOL : DEBUG_ERROR),
  792. ("%s!TLP3TransmitT0: <- SW1=%02x SW2=%02x (%lx)\n",
  793. DRIVER_NAME,
  794. replyBuffer[0],
  795. replyBuffer[1],
  796. status)
  797. );
  798. }
  799. } while(bytesToSend || restartWorkWaitingTime);
  800. if (status != STATUS_SUCCESS)
  801. leave;
  802. if (bytesToRead != 0) {
  803. *serialIoControlCode = SMARTCARD_READ;
  804. *replyLength = bytesToRead;
  805. SmartcardExtension->SmartcardReply.Buffer =
  806. replyBuffer;
  807. status = TLP3SerialIo(SmartcardExtension);
  808. SmartcardDebug(
  809. (status == STATUS_SUCCESS ? DEBUG_PROTOCOL : DEBUG_ERROR),
  810. ("%s!TLP3TransmitT0: <- Data %ld bytes, SW1=%02x SW2=%02x (%lx)\n",
  811. DRIVER_NAME,
  812. bytesToRead,
  813. replyBuffer[bytesToRead - 2],
  814. replyBuffer[bytesToRead - 1],
  815. status)
  816. );
  817. }
  818. }
  819. finally {
  820. // Restore pointers to their original location
  821. SmartcardExtension->SmartcardRequest.Buffer =
  822. requestBuffer;
  823. SmartcardExtension->SmartcardReply.Buffer =
  824. replyBuffer;
  825. if (status == STATUS_TIMEOUT) {
  826. // STATUS_TIMEOUT is not mapped to a Win32 error code
  827. status = STATUS_IO_TIMEOUT;
  828. }
  829. if (status == STATUS_SUCCESS) {
  830. status = SmartcardT0Reply(SmartcardExtension);
  831. }
  832. }
  833. SmartcardDebug(
  834. (status == STATUS_SUCCESS ? DEBUG_TRACE : DEBUG_ERROR),
  835. ("%s!TLP3TransmitT0: Exit(%lx)\n",
  836. DRIVER_NAME,
  837. status)
  838. );
  839. return status;
  840. }
  841. NTSTATUS
  842. TLP3Transmit(
  843. PSMARTCARD_EXTENSION SmartcardExtension
  844. )
  845. /*++
  846. Routine Description:
  847. This function is called by the smart card library whenever a transmission
  848. is required.
  849. Arguments:
  850. SmartcardExtension - Pointer to smart card data struct.
  851. Return Value:
  852. NTSTATUS
  853. --*/
  854. {
  855. NTSTATUS status;
  856. PAGED_CODE();
  857. SmartcardDebug(
  858. DEBUG_TRACE,
  859. ("%s!TLP3Transmit: Enter\n",
  860. DRIVER_NAME)
  861. );
  862. _try {
  863. do {
  864. PUCHAR requestBuffer = SmartcardExtension->SmartcardRequest.Buffer;
  865. PUCHAR replyBuffer = SmartcardExtension->SmartcardReply.Buffer;
  866. PULONG requestLength = &SmartcardExtension->SmartcardRequest.BufferLength;
  867. PULONG replyLength = &SmartcardExtension->SmartcardReply.BufferLength;
  868. PULONG serialIoControlCode = &SmartcardExtension->ReaderExtension->SerialIoControlCode;
  869. //
  870. // Tell the lib function how many bytes I need for the prologue
  871. //
  872. *requestLength = 0;
  873. switch (SmartcardExtension->CardCapabilities.Protocol.Selected) {
  874. case SCARD_PROTOCOL_RAW:
  875. status = SmartcardRawRequest(SmartcardExtension);
  876. break;
  877. case SCARD_PROTOCOL_T0:
  878. //
  879. // T=0 requires a bit more work.
  880. // So we do this in a seperate function.
  881. //
  882. status = TLP3TransmitT0(SmartcardExtension);
  883. leave;
  884. case SCARD_PROTOCOL_T1:
  885. status = SmartcardT1Request(SmartcardExtension);
  886. break;
  887. default:
  888. status = STATUS_INVALID_DEVICE_REQUEST;
  889. leave;
  890. }
  891. if (status != STATUS_SUCCESS) {
  892. leave;
  893. }
  894. //
  895. // Write the command to the card
  896. //
  897. *replyLength = 0;
  898. *serialIoControlCode = SMARTCARD_WRITE;
  899. status = TLP3SerialIo(SmartcardExtension);
  900. if (status != STATUS_SUCCESS) {
  901. leave;
  902. }
  903. //
  904. // The Bull reader always echos the bytes sent, so read that echo back
  905. //
  906. *serialIoControlCode = SMARTCARD_READ;
  907. *replyLength = *requestLength;
  908. status = TLP3SerialIo(SmartcardExtension);
  909. if (status != STATUS_SUCCESS) {
  910. leave;
  911. }
  912. switch (SmartcardExtension->CardCapabilities.Protocol.Selected) {
  913. case SCARD_PROTOCOL_RAW:
  914. status = SmartcardRawReply(SmartcardExtension);
  915. break;
  916. case SCARD_PROTOCOL_T1:
  917. //
  918. // Check if the card requested a waiting time extension
  919. //
  920. if (SmartcardExtension->T1.Wtx) {
  921. LARGE_INTEGER waitTime;
  922. waitTime.HighPart = -1;
  923. waitTime.LowPart =
  924. SmartcardExtension->T1.Wtx *
  925. SmartcardExtension->CardCapabilities.T1.BWT *
  926. (-10);
  927. KeDelayExecutionThread(
  928. KernelMode,
  929. FALSE,
  930. &waitTime
  931. );
  932. }
  933. //
  934. // Read NAD, PCB and LEN fields
  935. //
  936. *replyLength = 3;
  937. status = TLP3SerialIo(SmartcardExtension);
  938. //
  939. // Check for timeout first. If the card did not reply
  940. // we need to send a resend request
  941. //
  942. if (status != STATUS_TIMEOUT) {
  943. if (status != STATUS_SUCCESS) {
  944. leave;
  945. }
  946. //
  947. // The third byte contains the length of the data in the packet
  948. // and we additinally want to have the EDC bytes which
  949. // is one for LRC and 2 for CRC
  950. //
  951. *replyLength =
  952. replyBuffer[2] +
  953. (SmartcardExtension->CardCapabilities.T1.EDC & 0x01 ? 2 : 1);
  954. // We want to have the remaining bytes just after the first 3
  955. SmartcardExtension->SmartcardReply.Buffer += 3;
  956. status = TLP3SerialIo(SmartcardExtension);
  957. SmartcardExtension->SmartcardReply.Buffer -= 3;
  958. SmartcardExtension->SmartcardReply.BufferLength += 3;
  959. if (status != STATUS_SUCCESS && status != STATUS_TIMEOUT) {
  960. leave;
  961. }
  962. }
  963. if (status == STATUS_TIMEOUT) {
  964. //
  965. // Since the card did not reply we set the number of
  966. // bytes received to 0. This will trigger a resend
  967. // request
  968. //
  969. SmartcardDebug(
  970. DEBUG_PROTOCOL,
  971. ("%s!TLP3TransmitT1: Timeout\n",
  972. DRIVER_NAME)
  973. );
  974. SmartcardExtension->SmartcardReply.BufferLength = 0;
  975. }
  976. status = SmartcardT1Reply(SmartcardExtension);
  977. break;
  978. default:
  979. status = STATUS_INVALID_DEVICE_REQUEST;
  980. leave;
  981. }
  982. } while (status == STATUS_MORE_PROCESSING_REQUIRED);
  983. }
  984. _finally {
  985. if (status == STATUS_TIMEOUT) {
  986. // STATUS_TIMEOUT is not mapped to a Win32 error code
  987. status = STATUS_IO_TIMEOUT;
  988. }
  989. }
  990. #if defined (DEBUG) && defined (DETECT_SERIAL_OVERRUNS)
  991. if (status != STATUS_SUCCESS) {
  992. NTSTATUS status;
  993. PSERIALPERF_STATS perfData =
  994. (PSERIALPERF_STATS) SmartcardExtension->SmartcardReply.Buffer;
  995. // we have to call GetCommStatus to reset the error condition
  996. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  997. IOCTL_SERIAL_GET_COMMSTATUS;
  998. SmartcardExtension->SmartcardRequest.BufferLength = 0;
  999. SmartcardExtension->SmartcardReply.BufferLength =
  1000. sizeof(SERIAL_STATUS);
  1001. status = TLP3SerialIo(SmartcardExtension);
  1002. ASSERT(status == STATUS_SUCCESS);
  1003. // now get the reason for the transmission error
  1004. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  1005. IOCTL_SERIAL_GET_STATS;
  1006. SmartcardExtension->SmartcardRequest.BufferLength = 0;
  1007. SmartcardExtension->SmartcardReply.BufferLength =
  1008. sizeof(SERIALPERF_STATS);
  1009. status = TLP3SerialIo(SmartcardExtension);
  1010. ASSERT(status == STATUS_SUCCESS);
  1011. SmartcardDebug(
  1012. DEBUG_ERROR,
  1013. ("%s!TLP3Transmit: Serial error statistics:\n FrameErrors: %ld\n SerialOverrunErrors: %ld\n BufferOverrunErrors: %ld\n ParityErrors: %ld\n",
  1014. DRIVER_NAME,
  1015. perfData->FrameErrorCount,
  1016. perfData->SerialOverrunErrorCount,
  1017. perfData->BufferOverrunErrorCount,
  1018. perfData->ParityErrorCount)
  1019. );
  1020. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  1021. IOCTL_SERIAL_CLEAR_STATS;
  1022. SmartcardExtension->SmartcardRequest.BufferLength = 0;
  1023. SmartcardExtension->SmartcardReply.BufferLength = 0;
  1024. status = TLP3SerialIo(SmartcardExtension);
  1025. ASSERT(status == STATUS_SUCCESS);
  1026. }
  1027. #if DEBUG && TIMEOUT_TEST
  1028. else {
  1029. // inject some timeout errors
  1030. LARGE_INTEGER Ticks;
  1031. UCHAR RandomVal;
  1032. KeQueryTickCount(&Ticks);
  1033. RandomVal = (UCHAR) Ticks.LowPart % 4;
  1034. if (RandomVal == 0) {
  1035. status = STATUS_IO_TIMEOUT;
  1036. SmartcardDebug(
  1037. DEBUG_ERROR,
  1038. ("%s!TLP3Transmit: Simulating timeout\n",
  1039. DRIVER_NAME)
  1040. );
  1041. }
  1042. }
  1043. #endif
  1044. #endif
  1045. #ifdef SIMULATION
  1046. if (SmartcardExtension->ReaderExtension->SimulationLevel &
  1047. SIM_IO_TIMEOUT) {
  1048. status = STATUS_IO_TIMEOUT;
  1049. SmartcardDebug(
  1050. DEBUG_SIMULATION,
  1051. ("%s!TLP3Transmit: SIM STATUS_IO_TIMEOUT\n",
  1052. DRIVER_NAME)
  1053. );
  1054. }
  1055. #endif
  1056. SmartcardDebug(
  1057. DEBUG_TRACE,
  1058. ("%s!TLP3Transmit: Exit(%lx)\n",
  1059. DRIVER_NAME,
  1060. status)
  1061. );
  1062. return status;
  1063. }
  1064. NTSTATUS
  1065. TLP3CardTracking(
  1066. PSMARTCARD_EXTENSION SmartcardExtension
  1067. )
  1068. /*++
  1069. Routine Description:
  1070. The smart card lib requires to have this function. It is called
  1071. to setup event tracking for card insertion and removal events.
  1072. Arguments:
  1073. SmartcardExtension - pointer to the smart card data struct.
  1074. Return Value:
  1075. NTSTATUS
  1076. --*/
  1077. {
  1078. KIRQL ioIrql, keIrql;
  1079. //
  1080. // Set cancel routine for the notification irp
  1081. //
  1082. KeAcquireSpinLock(
  1083. &SmartcardExtension->OsData->SpinLock,
  1084. &keIrql
  1085. );
  1086. IoAcquireCancelSpinLock(&ioIrql);
  1087. if (SmartcardExtension->OsData->NotificationIrp) {
  1088. IoSetCancelRoutine(
  1089. SmartcardExtension->OsData->NotificationIrp,
  1090. TLP3Cancel
  1091. );
  1092. }
  1093. IoReleaseCancelSpinLock(ioIrql);
  1094. KeReleaseSpinLock(
  1095. &SmartcardExtension->OsData->SpinLock,
  1096. keIrql
  1097. );
  1098. return STATUS_PENDING;
  1099. }
  1100. NTSTATUS
  1101. TLP3VendorIoctl(
  1102. PSMARTCARD_EXTENSION SmartcardExtension
  1103. )
  1104. {
  1105. NTSTATUS status;
  1106. static char answer[] = "Vendor IOCTL";
  1107. PAGED_CODE();
  1108. SmartcardDebug(
  1109. DEBUG_PROTOCOL,
  1110. ("%s!TLP3VendorIoctl: Enter\n",
  1111. DRIVER_NAME)
  1112. );
  1113. if (SmartcardExtension->IoRequest.ReplyBuffer != NULL &&
  1114. SmartcardExtension->IoRequest.ReplyBufferLength >= strlen(answer) + 1) {
  1115. strcpy(SmartcardExtension->IoRequest.ReplyBuffer, answer);
  1116. *SmartcardExtension->IoRequest.Information = strlen(answer);
  1117. status = STATUS_SUCCESS;
  1118. } else {
  1119. status = STATUS_BUFFER_TOO_SMALL;
  1120. }
  1121. SmartcardDebug(
  1122. DEBUG_PROTOCOL,
  1123. ("%s!TLP3VendorIoctl: Exit(%lx)\n",
  1124. DRIVER_NAME,
  1125. status)
  1126. );
  1127. return status;
  1128. }
  1129. NTSTATUS
  1130. TLP3SerialIo(
  1131. PSMARTCARD_EXTENSION SmartcardExtension
  1132. )
  1133. /*++
  1134. Routine Description:
  1135. This routine sends IOCTL's to the serial driver. It waits on for their
  1136. completion, and then returns.
  1137. Arguments:
  1138. Return Value:
  1139. NTSTATUS
  1140. --*/
  1141. {
  1142. NTSTATUS status;
  1143. ULONG currentByte = 0;
  1144. if (KeReadStateEvent(&READER_EXTENSION(SerialCloseDone))) {
  1145. //
  1146. // we have no connection to serial, fail the call
  1147. // this could be the case if the reader was removed
  1148. // during stand by / hibernation
  1149. //
  1150. return STATUS_UNSUCCESSFUL;
  1151. }
  1152. // Check if the buffers are large enough
  1153. ASSERT(SmartcardExtension->SmartcardReply.BufferLength <=
  1154. SmartcardExtension->SmartcardReply.BufferSize);
  1155. ASSERT(SmartcardExtension->SmartcardRequest.BufferLength <=
  1156. SmartcardExtension->SmartcardRequest.BufferSize);
  1157. if (SmartcardExtension->SmartcardReply.BufferLength >
  1158. SmartcardExtension->SmartcardReply.BufferSize ||
  1159. SmartcardExtension->SmartcardRequest.BufferLength >
  1160. SmartcardExtension->SmartcardRequest.BufferSize) {
  1161. SmartcardLogError(
  1162. SmartcardExtension->OsData->DeviceObject,
  1163. TLP3_BUFFER_TOO_SMALL,
  1164. NULL,
  1165. 0
  1166. );
  1167. return STATUS_BUFFER_TOO_SMALL;
  1168. }
  1169. do {
  1170. IO_STATUS_BLOCK ioStatus;
  1171. KEVENT event;
  1172. PIRP irp;
  1173. PIO_STACK_LOCATION irpNextStack;
  1174. PUCHAR requestBuffer = NULL;
  1175. PUCHAR replyBuffer = SmartcardExtension->SmartcardReply.Buffer;
  1176. ULONG requestBufferLength = SmartcardExtension->SmartcardRequest.BufferLength;
  1177. ULONG replyBufferLength = SmartcardExtension->SmartcardReply.BufferLength;
  1178. KeInitializeEvent(
  1179. &event,
  1180. NotificationEvent,
  1181. FALSE
  1182. );
  1183. if (READER_EXTENSION(SerialIoControlCode) == SMARTCARD_WRITE) {
  1184. if (SmartcardExtension->CardCapabilities.GT != 0) {
  1185. //
  1186. // If the guardtime isn't 0 and we write data to the smart card
  1187. // we only write byte by byte, because we have to insert a delay
  1188. // between every sent byte
  1189. //
  1190. requestBufferLength = 1;
  1191. }
  1192. requestBuffer =
  1193. &SmartcardExtension->SmartcardRequest.Buffer[currentByte++];
  1194. replyBuffer = NULL;
  1195. replyBufferLength = 0;
  1196. } else {
  1197. requestBuffer =
  1198. (requestBufferLength ?
  1199. SmartcardExtension->SmartcardRequest.Buffer : NULL);
  1200. }
  1201. // Build irp to be sent to serial driver
  1202. irp = IoBuildDeviceIoControlRequest(
  1203. READER_EXTENSION(SerialIoControlCode),
  1204. SmartcardExtension->ReaderExtension->AttachedDeviceObject,
  1205. requestBuffer,
  1206. requestBufferLength,
  1207. replyBuffer,
  1208. replyBufferLength,
  1209. FALSE,
  1210. &event,
  1211. &ioStatus
  1212. );
  1213. ASSERT(irp != NULL);
  1214. if (irp == NULL) {
  1215. return STATUS_INSUFFICIENT_RESOURCES;
  1216. }
  1217. irpNextStack = IoGetNextIrpStackLocation(irp);
  1218. switch (SmartcardExtension->ReaderExtension->SerialIoControlCode) {
  1219. //
  1220. // The serial driver trasfers data from/to irp->AssociatedIrp.SystemBuffer
  1221. //
  1222. case SMARTCARD_WRITE:
  1223. //
  1224. // Since we 'manually' change parameters, the io-manager
  1225. // does not really know if this is an input or an ouput operation
  1226. // unless the reply buffer is 0. We do the assertion here, because
  1227. // if the reply buffer is not NULL, the io-manager will copy
  1228. // data back to the reply buffer.
  1229. //
  1230. ASSERT(replyBuffer == NULL);
  1231. irpNextStack->MajorFunction = IRP_MJ_WRITE;
  1232. irpNextStack->Parameters.Write.Length = requestBufferLength;
  1233. irpNextStack->Parameters.Write.ByteOffset.QuadPart = 0;
  1234. break;
  1235. case SMARTCARD_READ:
  1236. irpNextStack->MajorFunction = IRP_MJ_READ;
  1237. irpNextStack->Parameters.Read.Length = replyBufferLength;
  1238. irpNextStack->Parameters.Read.ByteOffset.QuadPart = 0;
  1239. break;
  1240. default:
  1241. ASSERT(irpNextStack->MajorFunction = IRP_MJ_DEVICE_CONTROL);
  1242. ASSERT(
  1243. DEVICE_TYPE_FROM_CTL_CODE(READER_EXTENSION(SerialIoControlCode)) ==
  1244. FILE_DEVICE_SERIAL_PORT
  1245. );
  1246. }
  1247. status = IoCallDriver(
  1248. SmartcardExtension->ReaderExtension->AttachedDeviceObject,
  1249. irp
  1250. );
  1251. if (status == STATUS_PENDING) {
  1252. KeWaitForSingleObject(
  1253. &event,
  1254. Executive,
  1255. KernelMode,
  1256. FALSE,
  1257. NULL
  1258. );
  1259. status = ioStatus.Status;
  1260. // save the number of bytes received
  1261. SmartcardExtension->SmartcardReply.BufferLength =
  1262. (ULONG) ioStatus.Information;
  1263. }
  1264. // Check if we have to write more bytes to the reader
  1265. if (SmartcardExtension->ReaderExtension->SerialIoControlCode ==
  1266. SMARTCARD_WRITE &&
  1267. SmartcardExtension->CardCapabilities.GT != 0 &&
  1268. currentByte <
  1269. SmartcardExtension->SmartcardRequest.BufferLength) {
  1270. // Now wait the required guard time
  1271. KeStallExecutionProcessor(SmartcardExtension->CardCapabilities.GT);
  1272. status = STATUS_MORE_PROCESSING_REQUIRED;
  1273. }
  1274. } while (status == STATUS_MORE_PROCESSING_REQUIRED);
  1275. return status;
  1276. }