📄 deviceid.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Module Name:
deviceid.c
Abstract:
This file implements the PCMCIA card unique identifier (PNP id) functions.
This is provided as a sample to platform writers and is
expected to be able to be used without modification on most (if not
all) hardware platforms.
Functions:
GetCardCRC()
CisToChar()
itoah()
CreateDeviceID()
Notes:
--*/
#include <windows.h>
#include <types.h>
#include <cardserv.h>
#include <sockserv.h>
#include <pcmcia.h>
#include <tuple.h>
#include <tchar.h>
#include <extern.h>
#define BUFFER_SIZE 300
// Defines for deviceID generation
#define PROD_LEN 64
#define MANFNAME_END (DEVID_LEN - 12)
#define PRODNAME_END (DEVID_LEN - 8)
#define MAX_INSTANCE 10
#define MAX_TUPLES 2048
#define STR_UNKNOWN_MANID (TEXT("UNKNOWN_MANUFACTURER"))
//
// List of tuples used to generate a card's CRC
//
const UCHAR TplList[] = {
CISTPL_DEVICE,
CISTPL_VERS_1,
CISTPL_CONFIG,
CISTPL_CFTABLE_ENTRY,
CISTPL_MANFID,
CISTPL_END
};
const unsigned short crc16a[] = {
0000000, 0140301, 0140601, 0000500,
0141401, 0001700, 0001200, 0141101,
0143001, 0003300, 0003600, 0143501,
0002400, 0142701, 0142201, 0002100,
};
const unsigned short crc16b[] = {
0000000, 0146001, 0154001, 0012000,
0170001, 0036000, 0024000, 0162001,
0120001, 0066000, 0074000, 0132001,
0050000, 0116001, 0104001, 0043000,
};
//
// Using the same algorithm as Windows 95, calculate the CRC value
// to be appended with the manufacturer name and device name to
// obtain the unique identifier for the PCCARD.
//
// Return: USHORT CRC.
//
USHORT
GetCardCRC(
UINT uSocket,
PUCHAR buffer
)
{
int i;
USHORT crc = 0;
USHORT index;
USHORT length;
PUCHAR tupleData;
PUCHAR cp;
UCHAR tupleCode;
UCHAR tmp;
PCARD_TUPLE_PARMS pTuple;
PCARD_DATA_PARMS pData;
STATUS status;
//
// Calculate CRC
//
DEBUGMSG(ZONE_TUPLE, (TEXT("GetCardCRC: Calculating CRC\r\n")));
pTuple = (PCARD_TUPLE_PARMS) buffer;
pData = (PCARD_DATA_PARMS) buffer;
tupleData = (PUCHAR)pData;
tupleData += sizeof(CARD_DATA_PARMS);
pTuple->hSocket.uSocket = (UINT8)uSocket;
pTuple->hSocket.uFunction = 0;
pTuple->fAttributes = 0; // Not interested in links
pTuple->uDesiredTuple = 0xff; // Interested in all tuples.
status = CardGetFirstTuple(pTuple);
if (status) {
DEBUGMSG(ZONE_TUPLE|ZONE_WARNING,
(TEXT("GetCardCRC: CardGetFirstTuple returned %d\r\n"), status));
goto crc_done;
}
//
// Walk the whole CIS, processing only those tuples that are used in CRC
// generation.
//
for (i = 0; i < MAX_TUPLES; i++) {
tupleCode = pTuple->uTupleCode;
for (index = 0; TplList[index] != CISTPL_END; index++) {
if (tupleCode != TplList[index]) {
continue;
}
pData->uBufLen = BUFFER_SIZE;
pData->uTupleOffset = 0;
status = CardGetTupleData(pData);
if (status) {
DEBUGMSG(ZONE_TUPLE|ZONE_WARNING,
(TEXT("GetCardCRC: CardGetTupleData returned %d\r\n"), status));
goto crc_done;
}
length = (USHORT)pData->uDataLen;
//
// This one is included in the CRC calculation
//
if (tupleCode == CISTPL_VERS_1) {
cp = tupleData + 2;
//
// Include all of the manufacturer name.
//
while (*cp) {
cp++;
}
cp++; // Include the product string
while (*cp) {
cp++;
}
cp++;
length = cp - tupleData;
}
for (cp = tupleData; length; length--, cp++) {
tmp = *cp ^ (UCHAR)crc;
crc = (crc >> 8) ^ crc16a[tmp & 0x0f] ^ crc16b[tmp >> 4];
}
break;
} // for (all CRC tuples)
status = CardGetNextTuple(pTuple);
if (status) {
DEBUGMSG(ZONE_TUPLE|ZONE_WARNING,
(TEXT("GetCardCRC: CardGetNextTuple returned %d\r\n"), status));
break;
}
} // for MAX_TUPLES
crc_done:
DEBUGMSG(ZONE_TUPLE,(TEXT("GetCardCRC: CRC = %x\r\n"), crc));
return crc;
} // GetCardCRC
//
// Convert a single byte character string from a PCMCIA CIS tuple to
// a TCHAR string limiting the range to 0x20-0x7F and changing space and
// comma to underscore.
//
// Returns number of bytes of source that where used.
//
UINT
CisToChar(
LPCSTR pcstr, // source
LPTSTR ptstr // destination
)
{
UCHAR c;
UINT i = 0;
while (c = *pcstr) {
if ((c > 0x20) && (c < 0x7f)) {
*ptstr = (TCHAR) c;
ptstr++;
} else if ((c == ' ') || (c == ',')) {
*ptstr = (TCHAR) '_';
ptstr++;
}
pcstr++;
i++;
}
*ptstr = (TCHAR) *pcstr; // NULL terminator
return i;
}
const TCHAR HexDigit[] = {
(TCHAR) '0', (TCHAR) '1', (TCHAR) '2', (TCHAR) '3', (TCHAR) '4',
(TCHAR) '5', (TCHAR) '6', (TCHAR) '7', (TCHAR) '8', (TCHAR) '9',
(TCHAR) 'A', (TCHAR) 'B', (TCHAR) 'C', (TCHAR) 'D', (TCHAR) 'E',
(TCHAR) 'F'};
//
// Convert USHORT value to ascii using hex radix
//
// Returns pointer to end of converted string.
//
TCHAR *
itoah(TCHAR * ptr, USHORT val)
{
int i;
for (i = 0; i < 4; i++) {
*ptr = HexDigit[val >> 12];
ptr++;
val <<= 4;
}
*ptr = (TCHAR) 0;
return ptr;
} // itoah
/********************************************************************
*
* CreateDeviceID - Create the DeviceID for the PC Card.
*
* The device ID is created from tuple information on the PC Card and saved
* in the CIC socket data. The goal is to create a unique ID for each
* card. The device ID is created from the manufacturer name string,
* the product name string, and a 16-bit CRC of a set of tuples.
*
* The ID is created by concatenating the PCMCIA" prefix, the manufacturer
* name string, the product name string, a 16-bit CRC, and the instance
* value for the card.
*
* PCMCIA\<manuf_name>-<prod_name>-<crc>\<instance>
*
* If the CISTPL_VERS_1 tuple is not available or the manufacturer name is
* NULL, the string "UNKNOWN_MANUFACTURER" will be included in its place.
*
* PCMCIA\UNKNOWN_MANUFACTURER-<crc>\<instance>
*
* The CRC will be created from the following tuple data.
*
* CISTPL_DEVICE
* CISTPL_VERS_1
* CISTPL_CONFIG
* CISTPL_CFTABLE_ENTRY
* CISTPL_MANFID
*
* The total length of the device ID string is limited to 128 characters,
* including the null terminator. The manufacturer and product name will
* be truncated to maintain this length restriction in the ID string.
*
* The characters in the manufacturer and product name strings that are
* greater than or equal to a space (0x20) or less than (0x7F) will be
* copied into the name string. Any other characters outside this range
* will be skipped. This makes it easier to include these characters in
* the .INF files for the device.
*
* Note the Configuration Manager converts spaces (' ') and commas (',')
* in the device ID that is passed during devnode creation to
* underscores ('_') and converts all characters to upper case.
*
********************************************************************/
STATUS
CreateDeviceID(
UINT uSocket,
BOOL instance
)
{
int i;
TCHAR *ps;
TCHAR *pd;
TCHAR product_name[PROD_LEN];
TCHAR manf_name[MANFNAME_END];
TCHAR dev_id[DEVID_LEN+1];
UCHAR buffer[BUFFER_SIZE+sizeof(CARD_DATA_PARMS)];
PCARD_TUPLE_PARMS pTuple;
PCARD_DATA_PARMS pData;
STATUS status;
PUCHAR tupleData;
DEBUGMSG(ZONE_TUPLE,(TEXT("CreateDeviceID entered\r\n")));
product_name[0] = 0; // Initialize product name string
pd = dev_id;
ps = STR_UNKNOWN_MANID; // UNKNOWN_MANUFACTURER string
//
// Try to get the manufacturer name and product name strings from
// the Level 1 Version tuple
//
pTuple = (PCARD_TUPLE_PARMS) buffer;
pTuple->hSocket.uSocket = uSocket;
pTuple->hSocket.uFunction = 0;
pTuple->fAttributes = 0; // Not interested in links
pTuple->uDesiredTuple = CISTPL_VERS_1;
if ((status = CardGetFirstTuple(pTuple)) == CERR_SUCCESS) {
pData = (PCARD_DATA_PARMS) buffer;
pData->uBufLen = BUFFER_SIZE;
pData->uTupleOffset = 0;
if ((status = CardGetTupleData(pData)) == CERR_SUCCESS) {
tupleData = (PUCHAR)pData;
tupleData += sizeof(CARD_DATA_PARMS); // point at returned data
if ((pData->uDataLen > 4) &&
(tupleData[2] != 0)) {
//
// Have a valid manufacturer name string.
//
// Force a null terminator at the end of the data, just in case
// the string is not properly terminated.
//
tupleData[pData->uDataLen] = 0;
tupleData = &tupleData[2];
i = CisToChar(tupleData, manf_name) + 1;
ps = manf_name;
tupleData += i;
DEBUGMSG(ZONE_TUPLE,(TEXT("Manufacturer = %s\r\n"), manf_name));
//
// Copy product name if manufacturer name is not too long
//
if (i < pData->uDataLen-2) {
CisToChar(tupleData, product_name);
DEBUGMSG(ZONE_TUPLE,(TEXT("Product Name = %s\r\n"), product_name));
} else {
product_name[0] = (TCHAR)0;
}
}
#ifdef DEBUG
else {
if (pData->uDataLen > 2) {
for (i = 0; i < pData->uDataLen; i++) {
if ((i) && ((i & 0x0F) == 0)) {
DEBUGMSG(ZONE_TUPLE,(TEXT("\r\n")));
}
DEBUGMSG(ZONE_TUPLE,(TEXT(" %2x"), tupleData[i]));
}
DEBUGMSG(ZONE_TUPLE,(TEXT("\r\n")));
}
}
#endif
}
}
//
// Copy manufacturer name into the device ID.
//
i = _tcslen(ps);
if (i > MANFNAME_END) {
i = MANFNAME_END;
}
_tcsncpy(pd, ps, i);
pd[i] = 0;
pd += i; // advance destination pointer
*pd++ = (TCHAR)'-'; // Append '-' to device ID
//
// If product name is valid, copy it into the device ID.
//
if (product_name[0] != (TCHAR)0) {
// Append product name to device ID.
_tcsncpy(pd, product_name, PROD_LEN);
i = _tcslen(pd);
if (i > PROD_LEN) {
i = PROD_LEN;
}
pd += i; // advance destination pointer
*pd++ = (TCHAR)'-'; // Append '-' to device ID
}
//
// Compute CRC for desired tuples and
// convert to ascii and append to device ID.
//
pd = itoah(pd, GetCardCRC(uSocket, buffer));
if (instance) {
*pd++ = (TCHAR)'\\'; // Append '\' to device ID
pd[1] = (TCHAR)0; // Null terminate device ID string
}
//
// Install the device id string for the current card
//
i = _tcslen(dev_id) + 1;
v_Sockets[uSocket].pDevId = alloc(i*sizeof(TCHAR));
if (v_Sockets[uSocket].pDevId == NULL) {
DEBUGMSG(ZONE_TUPLE,(TEXT("CreateDeviceID failed\r\n")));
return CERR_OUT_OF_RESOURCE;
}
#ifdef MYMEMTRACKING
v_TrackPNPId++;
v_TrackPNPIdBytes += i*sizeof(TCHAR);
#endif
#ifdef MEMTRACKING
AddTrackedItem( v_TrackPNPId, v_Sockets[uSocket].pDevId, NULL,
GetCurrentProcessId(), i*sizeof(TCHAR), 0, 0);
#endif
_tcscpy(v_Sockets[uSocket].pDevId, dev_id);
DEBUGMSG(ZONE_TUPLE,(TEXT("CreateDeviceID done\r\n")));
return CERR_SUCCESS;
} // CreateDeviceID
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -