⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tlp3nt.c

📁 SmardCard Windows驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
   SmartcardDebug(
      DEBUG_INFO,
      ( "%s!TLP3RemoveDevice: Exit\n",
        DRIVER_NAME)
      );
}

VOID
TLP3DriverUnload(
    IN PDRIVER_OBJECT DriverObject
    )
/*++

Routine Description:
    The driver unload routine.  This is called by the I/O system
    when the device is unloaded from memory.

Arguments:
    DriverObject - Pointer to driver object created by system.

Return Value:
    STATUS_SUCCESS.

--*/
{
    PAGED_CODE();

    SmartcardDebug(
        DEBUG_INFO,
        ("%s!TLP3DriverUnload\n",
        DRIVER_NAME)
        );
}

NTSTATUS
TLP3ConfigureSerialPort(
    PSMARTCARD_EXTENSION SmartcardExtension
    )

/*++

Routine Description:

    This routine will appropriately configure the serial port.
    It makes synchronous calls to the serial port.

Arguments:

    SmartcardExtension - Pointer to smart card struct

Return Value:

    NTSTATUS

--*/

{
    PSERIAL_READER_CONFIG configData = &SmartcardExtension->ReaderExtension->SerialConfigData;
    NTSTATUS status = STATUS_SUCCESS;
    USHORT i;
   PUCHAR request = SmartcardExtension->SmartcardRequest.Buffer;

   SmartcardExtension->SmartcardRequest.BufferLength = 0;
   SmartcardExtension->SmartcardReply.BufferLength =
      SmartcardExtension->SmartcardReply.BufferSize;

   for (i = 0; status == STATUS_SUCCESS; i++) {

        switch (i) {

         case 0:
             //
             // Set up baudrate for the TLP3 reader
             //
            SmartcardExtension->ReaderExtension->SerialIoControlCode =
               IOCTL_SERIAL_SET_BAUD_RATE;

             SmartcardExtension->SmartcardRequest.Buffer =
               (PUCHAR) &configData->BaudRate;

            SmartcardExtension->SmartcardRequest.BufferLength =
               sizeof(SERIAL_BAUD_RATE);

            break;

           case 1:
               //
               // Set up line control parameters
               //
            SmartcardExtension->ReaderExtension->SerialIoControlCode =
                 IOCTL_SERIAL_SET_LINE_CONTROL;

             SmartcardExtension->SmartcardRequest.Buffer =
                  (PUCHAR) &configData->LineControl;

            SmartcardExtension->SmartcardRequest.BufferLength =
                  sizeof(SERIAL_LINE_CONTROL);
               break;

           case 2:
               //
               // Set serial special characters
               //
            SmartcardExtension->ReaderExtension->SerialIoControlCode =
                 IOCTL_SERIAL_SET_CHARS;

            SmartcardExtension->SmartcardRequest.Buffer =
                  (PUCHAR) &configData->SerialChars;

            SmartcardExtension->SmartcardRequest.BufferLength =
                  sizeof(SERIAL_CHARS);
               break;

           case 3:
               //
               // Set up timeouts
               //
            SmartcardExtension->ReaderExtension->SerialIoControlCode =
               IOCTL_SERIAL_SET_TIMEOUTS;

             SmartcardExtension->SmartcardRequest.Buffer =
                  (PUCHAR) &configData->Timeouts;

            SmartcardExtension->SmartcardRequest.BufferLength =
                  sizeof(SERIAL_TIMEOUTS);
               break;

           case 4:
               // Set flowcontrol and handshaking
            SmartcardExtension->ReaderExtension->SerialIoControlCode =
                 IOCTL_SERIAL_SET_HANDFLOW;

             SmartcardExtension->SmartcardRequest.Buffer =
                  (PUCHAR) &configData->HandFlow;

            SmartcardExtension->SmartcardRequest.BufferLength =
                  sizeof(SERIAL_HANDFLOW);
               break;

           case 5:
               // Set break off
            SmartcardExtension->ReaderExtension->SerialIoControlCode =
                 IOCTL_SERIAL_SET_BREAK_OFF;
               break;

         case 6:
                // set DTR for the reader
              SmartcardExtension->ReaderExtension->SerialIoControlCode =
               IOCTL_SERIAL_SET_DTR;
            break;

         case 7:
              SmartcardExtension->ReaderExtension->SerialIoControlCode =
               IOCTL_SERIAL_SET_RTS;
            break;

         case 8:
             return STATUS_SUCCESS;
        }

       status = TLP3SerialIo(SmartcardExtension);
       

      // restore pointer to original request buffer
      SmartcardExtension->SmartcardRequest.Buffer = request;
    }
    
    return status;
}

NTSTATUS
TLP3StartSerialEventTracking(
    PSMARTCARD_EXTENSION SmartcardExtension
   )
/*++

Routine Description:

    This routine initializes serial event tracking.
    It calls the serial driver to set a wait mask for CTS and DSR tracking.

--*/
{
    NTSTATUS status;
    PREADER_EXTENSION readerExtension = SmartcardExtension->ReaderExtension;
   IO_STATUS_BLOCK ioStatus;
   KEVENT event;

    PAGED_CODE();

    readerExtension->SerialConfigData.SerialWaitMask =
        SERIAL_EV_CTS | SERIAL_EV_DSR;

    KeInitializeEvent(
        &event,
        NotificationEvent,
        FALSE
        );

   //
   // Send a wait mask to the serial driver. This call only sets the
    // wait mask. We want to be informed when CTS or DSR changes its state
   //
    readerExtension->SerialStatusIrp = IoBuildDeviceIoControlRequest(
      IOCTL_SERIAL_SET_WAIT_MASK,
      readerExtension->AttachedDeviceObject,
        &readerExtension->SerialConfigData.SerialWaitMask,
        sizeof(readerExtension->SerialConfigData.SerialWaitMask),
        NULL,
      0,
        FALSE,
        &event,
        &ioStatus
        );

    if (readerExtension->SerialStatusIrp == NULL) {

        return STATUS_INSUFFICIENT_RESOURCES;
    }

    status = IoCallDriver(
      readerExtension->AttachedDeviceObject,
      readerExtension->SerialStatusIrp,
      );

   if (status == STATUS_PENDING) {

        status = KeWaitForSingleObject(
            &event,
            Executive,
            KernelMode,
            FALSE,
            NULL
            );
        ASSERT(status == STATUS_SUCCESS);

      status = ioStatus.Status;
   }

   if (status == STATUS_SUCCESS) {

      KIRQL oldIrql;
      LARGE_INTEGER delayPeriod;
      PIO_STACK_LOCATION irpSp;

      //
      // Now tell the serial driver that we want to be informed
      // when CTS or DSR changes its state.
      //
      readerExtension->SerialStatusIrp = IoAllocateIrp(
         (CCHAR) (SmartcardExtension->OsData->DeviceObject->StackSize + 1),
         FALSE
         );

       if (readerExtension->SerialStatusIrp == NULL) {

           return STATUS_INSUFFICIENT_RESOURCES;
       }

       irpSp = IoGetNextIrpStackLocation( readerExtension->SerialStatusIrp );
      irpSp->MajorFunction = IRP_MJ_DEVICE_CONTROL;

      irpSp->Parameters.DeviceIoControl.InputBufferLength = 0;
      irpSp->Parameters.DeviceIoControl.OutputBufferLength =
         sizeof(readerExtension->SerialConfigData.SerialWaitMask);
      irpSp->Parameters.DeviceIoControl.IoControlCode =
         IOCTL_SERIAL_WAIT_ON_MASK;

      readerExtension->SerialStatusIrp->AssociatedIrp.SystemBuffer =
         &readerExtension->SerialConfigData.SerialWaitMask;

      //
      // this artificial delay is necessary to make this driver work
      // with digi board cards
      //
      delayPeriod.HighPart = -1;
      delayPeriod.LowPart = 100l * 1000 * (-10);

        KeDelayExecutionThread(
            KernelMode,
            FALSE,
            &delayPeriod
            );

        // We simulate a callback now that triggers the card supervision
        TLP3SerialEvent(
            SmartcardExtension->OsData->DeviceObject,
            readerExtension->SerialStatusIrp,
            SmartcardExtension
            );

      status = STATUS_SUCCESS;
   }

    return status;
}

VOID
TLP3CompleteCardTracking(
    IN PSMARTCARD_EXTENSION SmartcardExtension
    )
{
    KIRQL ioIrql, keIrql;
    PIRP notificationIrp;

    IoAcquireCancelSpinLock(&ioIrql);
    KeAcquireSpinLock(
        &SmartcardExtension->OsData->SpinLock,
        &keIrql
        );

    notificationIrp = SmartcardExtension->OsData->NotificationIrp;
    SmartcardExtension->OsData->NotificationIrp = NULL;

    KeReleaseSpinLock(
        &SmartcardExtension->OsData->SpinLock,
        keIrql
        );

    if (notificationIrp) {

        IoSetCancelRoutine(
            notificationIrp,
            NULL
            );
    }

    IoReleaseCancelSpinLock(ioIrql);

    if (notificationIrp) {

      SmartcardDebug(
         DEBUG_INFO,
         ("%s!TLP3CompleteCardTracking: Completing NotificationIrp %lxh\n",
            DRIVER_NAME,
            notificationIrp)
         );

       //   finish the request
        if (notificationIrp->Cancel) {

           notificationIrp->IoStatus.Status = STATUS_CANCELLED;

        } else {

           notificationIrp->IoStatus.Status = STATUS_SUCCESS;
        }
       notificationIrp->IoStatus.Information = 0;

       IoCompleteRequest(
            notificationIrp,
            IO_NO_INCREMENT
            );
    }
}

NTSTATUS
TLP3SerialEvent(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PSMARTCARD_EXTENSION SmartcardExtension
    )
/*++

Routine Description:

    This routine is called in two cases:
    a) CTS changed (card inserted or removed) or
    b) DSR changed (reader has been removed)

    For a) we update the card status and complete outstanding
    card tracking requests.
    For b) we start to unload the driver

    NOTE: This function calls itself using IoCompletion. In the 'first'
    callback the serial driver only tells us that something has changed.
    We set up a call for 'what has changed' (GetModemStatus) which then
    call this function again.
    When we updated everything and we don't unload the driver card
    tracking is started again.

--*/
{
   NTSTATUS status;
    KIRQL irql;

    KeAcquireSpinLock(
        &SmartcardExtension->OsData->SpinLock,
        &irql
        );

   if (SmartcardExtension->ReaderExtension->GetModemStatus) {

      //
      // This function requested the modem status previously.
        // As part of the io-completion, this function is then
        // called again. When we're here we can read the actual
        // modem-status to figure out if the card is in the reader
      //
      if ((SmartcardExtension->ReaderExtension->ModemStatus & SERIAL_DSR_STATE) == 0) {

         SmartcardDebug(
            DEBUG_INFO,
            ("%s!TLP3SerialEvent: Reader removed\n",
                DRIVER_NAME)
            );

            //
            // We set the mask to zero to signal that we can
            // release the irp that we use for the serial events
            //
            SmartcardExtension->ReaderExtension->SerialConfigData.SerialWaitMask = 0;
         SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_UNKNOWN;

        } else {

          if (SmartcardExtension->ReaderExtension->ModemStatus & SERIAL_CTS_STATE) {

             // Card is inserted
               SmartcardExtension->ReaderCapabilities.CurrentState =
                    SCARD_SWALLOWED;

             SmartcardExtension->CardCapabilities.Protocol.Selected =
                SCARD_PROTOCOL_UNDEFINED;

             SmartcardDebug(
                DEBUG_INFO,
                ("%s!TLP3SerialEvent: Smart card inserted\n",
                    DRIVER_NAME)
                );

          } else {

             // Card is removed
                SmartcardExtension->CardCapabilities.ATR.Length = 0;

               SmartcardExtension->ReaderCapabilities.CurrentState =
                SCARD_ABSENT;

             SmartcardExtension->CardCapabilities.Protocol.Selected =
                SCARD_PROTOCOL_UNDEFINED;

             SmartcardDebug(
                DEBUG_INFO,
                ("%s!TLP3SerialEvent: Smart card removed\n",
                    DRIVER_NAME)
                );
          }
        }
    }

   KeReleaseSpinLock(
      &SmartcardExtension->OsData->SpinLock,
      irql
      );

   //
   // Only inform the user of a card insertion/removal event
   // if this function isn't called due to a power down - power up cycle
   //
   if (SmartcardExtension->ReaderExtension->PowerRequest == FALSE) {

        TLP3CompleteCardTracking(SmartcardExtension);
   }

    // The wait mask is set to 0 when the driver unloads
   if (SmartcardExtension->ReaderExtension->SerialConfigData.SerialWaitMask == 0) {

        // The reader has been unplugged.
        PDEVICE_EXTENSION deviceExtension =
            SmartcardExtension->OsData->DeviceObject->DeviceExtension;

        // schedule our remove thread
      IoQueueWorkItem(
         deviceExtension->CloseSerial,
            (PIO_WORKITEM_ROUTINE) TLP3CloseSerialPort,
         DelayedWorkQueue,
            NULL
         );

        SmartcardDebug(
            DEBUG_TRAC

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -