Microsoft KB Archive/256161

= How To Get PCMCIA Socket Information =

Article ID: 256161

Article Last Modified on 2/12/2007

-

APPLIES TO


 * Microsoft Windows XP Driver Development Kit
 * Microsoft Win32 Device Driver Kit for Windows 2000

-



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.

