Q256161: HOWTO: Get PCMCIA Socket Information
Article: Q256161
Product(s): Microsoft Windows NT
Version(s):
Operating System(s):
Keyword(s): kbDDK kbOSWin2000 kbPlugPlay kbDSupport kbGrpDSNTDDK kbWDM
Last Modified: 13-MAR-2002
-------------------------------------------------------------------------------
The information in this article applies to:
- Microsoft Windows XP Driver Development Kit (DDK)
- Microsoft Windows 2000 Driver Development Kit (DDK)
-------------------------------------------------------------------------------
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.
Additional query words: Pcmcia
======================================================================
Keywords : kbDDK kbOSWin2000 kbPlugPlay kbDSupport kbGrpDSNTDDK kbWDM
Technology : kbwin2000Search kbwin2000DDK kbAudDeveloper kbWinDDKSearch kbWinDDK kbWinXPDDKSearch
Version : :
Issue type : kbhowto
=============================================================================
THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.
Copyright Microsoft Corporation 1986-2002.