How To Get PCMCIA Socket Information (256161)



The information in this article applies to:

  • Microsoft Windows XP Driver Development Kit (DDK)
  • Microsoft Windows 2000 Driver Development Kit (DDK)

This article was previously published under Q256161

SUMMARY

This article describes how to get PCMCIA socket information, such as the number of slots on the reader or the slot number of the currently inserted card device.

MORE INFORMATION

The following sample code uses the PCMCIA_SOCKET_INFORMATION structure that is defined in the Ntddpcm.h header file:

typedef struct _PCMCIA_SOCKET_INFORMATION {
   USHORT  Socket;
   USHORT  TupleCrc;
   UCHAR   Manufacturer[MANUFACTURER_NAME_LENGTH];
   UCHAR   Identifier[DEVICE_IDENTIFIER_LENGTH];
   UCHAR   DriverName[DRIVER_NAME_LENGTH];
   UCHAR   DeviceFunctionId;
   UCHAR   Reserved;
   UCHAR   CardInSocket;
   UCHAR   CardEnabled;
   ULONG   ControllerType;
} PCMCIA_SOCKET_INFORMATION, *PPCMCIA_SOCKET_INFORMATION;
				

The sample code performs the following steps:
  1. Uses the IoGetDeviceObjectPointer function to obtain the device object and corresponding file object.
  2. Initializes the PCMCIA_SOCKET_INFORMATION structure for the socket for which the information is sought.
  3. Uses the IoBuildDeviceIoControlRequest function to allocate and set up an I/O request packet (IRP) for a device control request (the IOCTL_SOCKET_INFORMATION structure). This request should be sent at PASSIVE_LEVEL to the PCMCIA bus driver.
  4. Passes the IRP down and waits for the result.
If the return status is success, the information in the PCMCIA_SOCKET_INFORMATION structure is valid and can be used in your driver. Repeat steps 1 to 4 for all the controllers present on your computer.

Here is the sample code:
{
    ANSI_STRING ntString;
    UNICODE_STRING ntUnicodeString;
    KEVENT event;
    PDEVICE_OBJECT PcmciaDeviceObject = NULL;
    NTSTATUS istatus = 0;
    PFILE_OBJECT fileObject = NULL;
    PIRP irp = NULL;
    LONG SktNo = 0;
    LONG ValidSkts = 0;
    PCMCIA_SOCKET_INFORMATION PcmciaSkt;
    IO_STATUS_BLOCK ioStatusBlock;
    CCHAR deviceNameBuffer[64];
    LONG portNumber = 0;
    LONG MorePorts = TRUE;
    LONG MoreSkts = TRUE;

    //Loop for all the controllers.
    do{
        sprintf(deviceNameBuffer,"\\Device\\Pcmcia%d",portNumber);
	RtlInitAnsiString(
                          &ntString,
                          deviceNameBuffer
                         ); //Initialize the string
        istatus = RtlAnsiStringToUnicodeString(
                                             &ntUnicodeString,
                                             &ntString,
                                             TRUE
                                            );
        if (!NT_SUCCESS(istatus)){
            //Handle this error properly.
            return STATUS_UNSUCCESSFUL; //Error
        }//ENDIF
        status = IoGetDeviceObjectPointer(
                                          &ntUnicodeString,
                                          FILE_READ_ATTRIBUTES,
                                          &fileObject,
                                          &PcmciaDeviceObject
                                         );
        if (!NT_SUCCESS(istatus)){
            return STATUS_UNSUCCESSFUL; //Error
        }//ENDIF
        do{
            RtlZeroMemory(
                          &PcmciaSkt,
                          sizeof(PCMCIA_SOCKET_INFORMATION)
                         );
            PcmciaSkt.Socket = (USHORT) SktNo;
            KeInitializeEvent(&event, NotificationEvent, FALSE);
            irp = IoBuildDeviceIoControlRequest
                        (
                         IOCTL_SOCKET_INFORMATION,
                         PcmciaDeviceObject,
                         &PcmciaSkt,
                         sizeof(PCMCIA_SOCKET_INFORMATION),
                         &PcmciaSkt,
                         sizeof (PCMCIA_SOCKET_INFORMATION),
                         FALSE,
                         &event,
                         &ioStatusBlock
                        );

            if (!irp){
                //Handle the error properly.
                MoreSkts = FALSE;
                break; //Error
            }//ENDIF

            ioStatusBlock.Status = STATUS_NOT_SUPPORTED;
            ioStatusBlock.Information = 0;

            // Send the request down.
            istatus = IoCallDriver(
                                  PcmciaDeviceObject,
                                  irp
                                 );
            if (istatus == STATUS_PENDING){
            // If pending then wait for done.
                KeWaitForSingleObject(
                                      &event,
                                      Executive,
                                      KernelMode,
                                      FALSE,
                                      NULL
                                     );
                istatus = ioStatusBlock.Status;
            }//ENDIF
            if (!NT_SUCCESS(istatus)){
                //The error can occur for many reasons including the
                //STATUS_INVALID_PARAMETER,STATUS_BUFFER_TOO_SMALL 
                //if the parameters in the IoBuildDevice.... function
                //are not valid.

                //If the error is because of invalid parameter then, 
                //it could be because there may not be more valid socket 
                //on this controller. In this case just break see if 
                //any other controller exists.
                //Otherwise handle the error carefully.    

                MoreSkts = FALSE;
                break;
            }//ENDIF
            //You have the socket information now to handle in your driver.
            SktNo++;
        }while (MoreSkts)//END FOR
        //Dereference the file object on this controller.
        ObDereferenceObject(fileObject);
        portNumber++;
        //Here before reinitializing the flag you can insert your code.
        MoreSkts = TRUE;
    }while(MorePorts)//END WHILE
    MorePorts = TRUE;
}
				
The PcmciaSkt.CardInSocket value is TRUE when a card is present in the socket, and the PcmciaSkt.Socket value provides the socket number. For all invalid parameters, including SktNo, the underlying driver returns STATUS_INVALID_PARAMETER.

REFERENCES

The Ntddpcm.h file is located under the Ddk\Inc folder.

Modification Type:MinorLast Reviewed:7/1/2004
Keywords:kbhowto kbPlugPlay kbWDM KB256161