947 lines
20 KiB
C
947 lines
20 KiB
C
/*++
|
|
Copyright (c) 1998 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
STRING.C
|
|
|
|
Abstract:
|
|
|
|
This module contains the functions used to parse the PNP COM ID
|
|
and save it in the appropriate UNICODE STRINGS. The main function
|
|
that is called is Serenum_ParseData. All other functions are called
|
|
by this main function.
|
|
|
|
@@BEGIN_DDKSPLIT
|
|
|
|
Author:
|
|
|
|
Jay Senior
|
|
|
|
@@END_DDKSPLIT
|
|
|
|
Environment:
|
|
|
|
kernel mode only
|
|
|
|
Notes:
|
|
|
|
|
|
@@BEGIN_DDKSPLIT
|
|
|
|
Revision History:
|
|
Louis J. Giliberto, Jr. 22-Mar-1998 Cleanup
|
|
|
|
@@END_DDKSPLIT
|
|
|
|
|
|
--*/
|
|
|
|
#include "pch.h"
|
|
|
|
|
|
#define MAX_DEVNODE_NAME 256 // Total size of Device ID
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text (PAGE, Serenum_ParseData)
|
|
|
|
// Called by ParseData:
|
|
#pragma alloc_text (PAGE, Serenum_GetDevDesc)
|
|
#pragma alloc_text (PAGE, Serenum_GetDevCompId)
|
|
#pragma alloc_text (PAGE, Serenum_GetDevClass)
|
|
#pragma alloc_text (PAGE, Serenum_GetDevSerialNo)
|
|
#pragma alloc_text (PAGE, Serenum_GetDevName)
|
|
#pragma alloc_text (PAGE, Serenum_GetDevPnPRev)
|
|
#pragma alloc_text (PAGE, Serenum_GetDevOtherID)
|
|
|
|
#pragma alloc_text (PAGE, Serenum_InitMultiString)
|
|
#pragma alloc_text (PAGE, Serenum_SzCopy)
|
|
#pragma alloc_text (PAGE, Serenum_StrLen)
|
|
|
|
// Called by the above functions:
|
|
#pragma alloc_text (PAGE, Serenum_FixptToAscii)
|
|
#pragma alloc_text (PAGE, Serenum_HToI)
|
|
|
|
#endif
|
|
|
|
NTSTATUS
|
|
Serenum_ParseData(PFDO_DEVICE_DATA FdoData, PCHAR ReadBuffer, ULONG BufferLen,
|
|
PUNICODE_STRING hardwareIDs, PUNICODE_STRING compIDs,
|
|
PUNICODE_STRING deviceIDs, PUNICODE_STRING PDeviceDesc,
|
|
PUNICODE_STRING serialNo, PUNICODE_STRING pnpRev)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Parses the PNP COM ID out of the buffer which is passed as the
|
|
first parameter and then saves the appropriate IDs as
|
|
UNICODE_STRINGS in the other passed parameters.
|
|
|
|
Return value:
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
PCHAR pOtherId;
|
|
PCHAR pPnpRev;
|
|
PCHAR pDevNodeName;
|
|
PCHAR pSerNo;
|
|
PCHAR pClass;
|
|
PCHAR pCompIdStar;
|
|
PCHAR pDesc;
|
|
PCHAR pStrBuffer = NULL;
|
|
|
|
NTSTATUS status;
|
|
|
|
PCHAR pDevName;
|
|
PCHAR pCompId;
|
|
|
|
int OtherIDLen;
|
|
int start;
|
|
|
|
BOOLEAN isMouse = FALSE;
|
|
PCHAR pMouseID = NULL;
|
|
|
|
UNREFERENCED_PARAMETER(BufferLen);
|
|
|
|
//
|
|
// Allocate the string buffers
|
|
//
|
|
|
|
pStrBuffer = ExAllocatePool(PagedPool, MAX_DEVNODE_NAME * 7 + 1);
|
|
|
|
if (pStrBuffer == NULL) {
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto DoneParsingErr;
|
|
} else {
|
|
PCHAR pCurBuffer = pStrBuffer;
|
|
|
|
pOtherId = pCurBuffer;
|
|
*pOtherId = '\0';
|
|
pCurBuffer += MAX_DEVNODE_NAME;
|
|
|
|
pPnpRev = pCurBuffer;
|
|
*pPnpRev = '\0';
|
|
pCurBuffer += MAX_DEVNODE_NAME;
|
|
|
|
pDevNodeName = pCurBuffer;
|
|
*pDevNodeName = '\0';
|
|
pCurBuffer += MAX_DEVNODE_NAME;
|
|
|
|
pSerNo = pCurBuffer;
|
|
*pSerNo = '\0';
|
|
pCurBuffer += MAX_DEVNODE_NAME;
|
|
|
|
pClass = pCurBuffer;
|
|
*pClass = '\0';
|
|
pCurBuffer += MAX_DEVNODE_NAME;
|
|
|
|
pCompIdStar = pCurBuffer;
|
|
pCompId = pCompIdStar + 1;
|
|
*pCompIdStar = '\0';
|
|
pCurBuffer += MAX_DEVNODE_NAME + 1;
|
|
|
|
pDesc = pCurBuffer;
|
|
*pDesc = '\0';
|
|
pCurBuffer += MAX_DEVNODE_NAME;
|
|
}
|
|
|
|
start = Serenum_SzCopy ("SERENUM\\", pDevNodeName);
|
|
pDevName = pDevNodeName + start;
|
|
|
|
start = 0;
|
|
|
|
RtlInitUnicodeString(hardwareIDs, NULL);
|
|
RtlInitUnicodeString(compIDs, NULL);
|
|
RtlInitUnicodeString(deviceIDs, NULL);
|
|
RtlInitUnicodeString(pnpRev, NULL);
|
|
RtlInitUnicodeString(serialNo, NULL);
|
|
|
|
|
|
//
|
|
// OtherID
|
|
//
|
|
|
|
start = Serenum_GetDevOtherID(ReadBuffer, pOtherId);
|
|
|
|
if (start > 16) {
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR,
|
|
("Other ID string too long\n"));
|
|
status = STATUS_UNSUCCESSFUL;
|
|
goto DoneParsingErr;
|
|
}
|
|
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Other ID: %s\n", pOtherId));
|
|
|
|
//
|
|
// See if this is a mouse
|
|
//
|
|
|
|
SerenumScanOtherIdForMouse(ReadBuffer, BufferLen, &pMouseID);
|
|
|
|
if (pMouseID != NULL && (*pMouseID == 'M' || *pMouseID == 'B')) {
|
|
isMouse = TRUE;
|
|
}
|
|
|
|
//
|
|
// PNP revision number
|
|
//
|
|
|
|
status = Serenum_GetDevPnPRev(FdoData, ReadBuffer, pPnpRev, &start);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR, ("PNP ID string bad\n"));
|
|
goto DoneParsingErr;
|
|
}
|
|
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("PNP Revision: %s\n", pPnpRev));
|
|
|
|
//
|
|
// PNP device node name
|
|
// EISA ID followed by Product ID
|
|
//
|
|
|
|
Serenum_GetDevName(ReadBuffer, pDevName, &start);
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Device Node name: %s\n",
|
|
pDevNodeName));
|
|
|
|
//
|
|
// Device serial number
|
|
//
|
|
|
|
Serenum_GetDevSerialNo(ReadBuffer, pSerNo, &start);
|
|
|
|
if (Serenum_StrLen(pSerNo)) {
|
|
//
|
|
// This field exists - Make sure it is correct length.
|
|
//
|
|
|
|
if (Serenum_StrLen(pSerNo) != 8) {
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR, ("Serial number wrong"
|
|
" length\n"));
|
|
*pSerNo = '\0';
|
|
status = STATUS_UNSUCCESSFUL;
|
|
goto DoneParsingErr;
|
|
}
|
|
}
|
|
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Serial Number: %s\n", pSerNo));
|
|
|
|
//
|
|
// PNP class identifier
|
|
//
|
|
|
|
Serenum_GetDevClass(ReadBuffer, pClass, &start);
|
|
|
|
if (Serenum_StrLen(pClass) > 32) {
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR, ("Class ID string too long\n"
|
|
));
|
|
status = STATUS_UNSUCCESSFUL;
|
|
goto DoneParsingErr;
|
|
}
|
|
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Class: %s\n", pClass));
|
|
|
|
if (_stricmp(pClass, "MOUSE") == 0) {
|
|
strcpy(pClass, "SERIAL_MOUSE");
|
|
}
|
|
|
|
//
|
|
// Compatible device ID
|
|
//
|
|
*pCompIdStar = '*';
|
|
|
|
Serenum_GetDevCompId(ReadBuffer, pCompId, &start);
|
|
|
|
if (Serenum_StrLen(pCompId) > 40) {
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR, ("Compatible driver ID"
|
|
" string too long\n"));
|
|
status = STATUS_UNSUCCESSFUL;
|
|
goto DoneParsingErr;
|
|
}
|
|
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Compatible driver ID: %s\n",
|
|
pCompId));
|
|
|
|
//
|
|
// End-user legible Product Description
|
|
//
|
|
|
|
Serenum_GetDevDesc (ReadBuffer, pDesc, &start);
|
|
|
|
if (Serenum_StrLen(pDesc) > 40) {
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR, ("Device Description too"
|
|
" long\n"));
|
|
status = STATUS_UNSUCCESSFUL;
|
|
goto DoneParsingErr;
|
|
}
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Device Description: %s\n",
|
|
pDesc));
|
|
|
|
DoneParsingErr:
|
|
if (pStrBuffer != NULL) {
|
|
//
|
|
// send back the good bits so that routine knows what driver to load
|
|
//
|
|
|
|
Serenum_InitMultiString (FdoData, hardwareIDs, pDevNodeName, pDevName,
|
|
NULL);
|
|
|
|
if (Serenum_StrLen(pCompId) > 0) {
|
|
if (!isMouse) {
|
|
Serenum_InitMultiString(FdoData, compIDs, pCompIdStar, pClass,
|
|
NULL);
|
|
} else {
|
|
Serenum_InitMultiString(FdoData, compIDs, pCompIdStar, pClass,
|
|
"SERIAL_MOUSE", NULL);
|
|
}
|
|
} else {
|
|
if (isMouse) {
|
|
Serenum_InitMultiString(FdoData, compIDs, "SERIAL_MOUSE", NULL);
|
|
}
|
|
}
|
|
|
|
Serenum_InitMultiString(FdoData, deviceIDs, pDevNodeName, NULL);
|
|
|
|
Serenum_InitMultiString(FdoData, PDeviceDesc, pDesc, NULL);
|
|
|
|
if (Serenum_StrLen(pSerNo)) {
|
|
Serenum_InitMultiString(FdoData, serialNo, pSerNo, NULL);
|
|
}
|
|
if (Serenum_StrLen(pPnpRev)) {
|
|
Serenum_InitMultiString(FdoData, pnpRev, pPnpRev, NULL);
|
|
}
|
|
|
|
ExFreePool(pStrBuffer);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
Serenum_InitMultiString(PFDO_DEVICE_DATA FdoData, PUNICODE_STRING MultiString,
|
|
...)
|
|
/*++
|
|
|
|
This routine will take a null terminated list of ascii strings and combine
|
|
them together to generate a unicode multi-string block
|
|
|
|
Arguments:
|
|
|
|
MultiString - a unicode structure in which a multi-string will be built
|
|
... - a null terminated list of narrow strings which will be
|
|
combined together. This list must contain at least a
|
|
trailing NULL
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
{
|
|
ANSI_STRING ansiString;
|
|
NTSTATUS status;
|
|
PCSTR rawString;
|
|
PWSTR unicodeLocation;
|
|
ULONG multiLength = 0;
|
|
UNICODE_STRING unicodeString;
|
|
va_list ap;
|
|
ULONG i;
|
|
|
|
PAGED_CODE();
|
|
|
|
#if !DBG
|
|
UNREFERENCED_PARAMETER(FdoData);
|
|
#endif
|
|
|
|
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE,
|
|
("Entering Serenum_InitMultiString\n"));
|
|
|
|
va_start(ap,MultiString);
|
|
|
|
//
|
|
// Make sure that we won't leak memory
|
|
//
|
|
|
|
ASSERT(MultiString->Buffer == NULL);
|
|
|
|
rawString = va_arg(ap, PCSTR);
|
|
|
|
while (rawString != NULL) {
|
|
RtlInitAnsiString(&ansiString, rawString);
|
|
multiLength += RtlAnsiStringToUnicodeSize(&(ansiString));
|
|
rawString = va_arg(ap, PCSTR);
|
|
}
|
|
|
|
va_end( ap );
|
|
|
|
if (multiLength == 0) {
|
|
//
|
|
// Done
|
|
//
|
|
RtlInitUnicodeString(MultiString, NULL);
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE,
|
|
("Leaving Serenum_InitMultiString (1)\n"));
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// We need an extra null
|
|
//
|
|
multiLength += sizeof(WCHAR);
|
|
|
|
MultiString->MaximumLength = (USHORT)multiLength;
|
|
MultiString->Buffer = ExAllocatePool(PagedPool, multiLength);
|
|
MultiString->Length = 0;
|
|
|
|
if (MultiString->Buffer == NULL) {
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE,
|
|
("Leaving Serenum_InitMultiString (2)\n"));
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE,
|
|
("Allocated %lu bytes for buffer\n", multiLength));
|
|
|
|
#if DBG
|
|
RtlFillMemory(MultiString->Buffer, multiLength, 0xff);
|
|
#endif
|
|
|
|
unicodeString.Buffer = MultiString->Buffer;
|
|
unicodeString.MaximumLength = (USHORT) multiLength;
|
|
|
|
va_start(ap, MultiString);
|
|
rawString = va_arg(ap, PCSTR);
|
|
|
|
while (rawString != NULL) {
|
|
|
|
RtlInitAnsiString(&ansiString,rawString);
|
|
status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, FALSE);
|
|
|
|
//
|
|
// We don't allocate memory, so if something goes wrong here,
|
|
// its the function that's at fault
|
|
//
|
|
ASSERT(NT_SUCCESS(status));
|
|
|
|
//
|
|
// Check for any commas and replace them with NULLs
|
|
//
|
|
|
|
ASSERT(unicodeString.Length % sizeof(WCHAR) == 0);
|
|
|
|
for (i = 0; i < (unicodeString.Length / sizeof(WCHAR)); i++) {
|
|
if (unicodeString.Buffer[i] == L'\x2C' ||
|
|
unicodeString.Buffer[i] == L'\x0C' ) {
|
|
unicodeString.Buffer[i] = L'\0';
|
|
}
|
|
}
|
|
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("unicode buffer: %ws\n",
|
|
unicodeString.Buffer));
|
|
|
|
//
|
|
// Move the buffers along
|
|
//
|
|
unicodeString.Buffer += ((unicodeString.Length / sizeof(WCHAR)) + 1);
|
|
unicodeString.MaximumLength -= (unicodeString.Length + sizeof(WCHAR));
|
|
unicodeString.Length = 0;
|
|
|
|
//
|
|
// Next
|
|
//
|
|
|
|
rawString = va_arg(ap, PCSTR);
|
|
} // while
|
|
|
|
va_end(ap);
|
|
|
|
ASSERT(unicodeString.MaximumLength == sizeof(WCHAR));
|
|
|
|
//
|
|
// Stick the final null there
|
|
//
|
|
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("unicode buffer last addr: "
|
|
"%x\n", unicodeString.Buffer));
|
|
|
|
unicodeString.Buffer[0] = L'\0';
|
|
|
|
//
|
|
// Include the nulls in the length of the string
|
|
//
|
|
|
|
MultiString->Length = (USHORT)multiLength;
|
|
MultiString->MaximumLength = MultiString->Length;
|
|
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE,
|
|
("Leaving Serenum_InitMultiString (3)\n"));
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
int
|
|
Serenum_StrLen (
|
|
PCHAR string)
|
|
// Measures the length of a string
|
|
{
|
|
int i;
|
|
if (string == NULL) {
|
|
return 0;
|
|
}
|
|
for (i=0; string[i] != '\0'; i++) {
|
|
}
|
|
return i;
|
|
}
|
|
|
|
int
|
|
Serenum_SzCopy (
|
|
PCHAR source,
|
|
PCHAR dest)
|
|
// Copies a string
|
|
// Assumes the buffer is already allocated to be copied into
|
|
{
|
|
int i;
|
|
|
|
ASSERT (source);
|
|
ASSERT (dest);
|
|
|
|
for (i=0; source[i] != '\0'; i++) {
|
|
*dest++ = source[i];
|
|
}
|
|
return i;
|
|
}
|
|
|
|
//
|
|
// String extraction functions:
|
|
//
|
|
int
|
|
Serenum_GetDevOtherID(
|
|
PCHAR input,
|
|
PCHAR output)
|
|
{
|
|
|
|
int tail;
|
|
CHAR c;
|
|
|
|
tail = 0;
|
|
|
|
c = input[tail++];
|
|
|
|
while((tail < 17 ) && (c != '(') && (c != '(' - 0x20)) {
|
|
*output++ = c;
|
|
c = input[tail++];
|
|
}
|
|
|
|
*output = '\0';
|
|
return(tail-1);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
*
|
|
***************************************************************************/
|
|
int
|
|
Serenum_HToI(char c) {
|
|
|
|
if('0' <= c && c <= '9')
|
|
return(c - '0');
|
|
|
|
if('A' <= c && c <= 'F')
|
|
return(c - 'A' + 10);
|
|
|
|
if('a' <= c && c <= 'f')
|
|
return(c - 'a' + 10);
|
|
|
|
return(-1);
|
|
}
|
|
|
|
void
|
|
Serenum_FixptToAscii(
|
|
int n,
|
|
PCHAR output)
|
|
/****************************************************************************
|
|
*
|
|
*
|
|
***************************************************************************/
|
|
{
|
|
int tmp;
|
|
|
|
tmp = n / 100;
|
|
|
|
if(tmp >= 10)
|
|
*output++ = (CHAR)('0' + (tmp / 10));
|
|
|
|
*output++ = (CHAR)('0' + (tmp % 10));
|
|
*output++ = '.';
|
|
|
|
tmp = n % 100;
|
|
|
|
*output++ = (CHAR)('0' + (tmp / 10));
|
|
*output++ = (CHAR)('0' + (tmp % 10));
|
|
|
|
*output = '\0';
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
*
|
|
***************************************************************************/
|
|
NTSTATUS
|
|
Serenum_GetDevPnPRev(PFDO_DEVICE_DATA FdoData, PCHAR input, PCHAR output,
|
|
int *start)
|
|
{
|
|
int tail;
|
|
int i;
|
|
char delta;
|
|
char c, begin_PnP, end_PnP_pos;
|
|
int sum, chk_sum, msd, lsd;
|
|
|
|
UNREFERENCED_PARAMETER(FdoData);
|
|
|
|
if (output == NULL || input == NULL) {
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR,
|
|
("GetDevPnPRev Failed, NULL pointer!\n"));
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
*output = '\0';
|
|
|
|
tail = *start;
|
|
|
|
if (input[tail] == 0) {
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR,
|
|
("GetDevPnPRev Failed, input buffer empty!\n"));
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
c = input[tail++];
|
|
|
|
while ((tail < 256) && (c != '(') && (c != '(' - 0x20)) {
|
|
c = input[tail++];
|
|
}
|
|
|
|
if (c != '(' && c != '(' - 0x20) {
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR,
|
|
("GetDevPnPRev Failed, no Begin PnP char!\n"));
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
begin_PnP = c;
|
|
delta = '(' - begin_PnP;
|
|
|
|
if (input[tail + 9] != ')' - delta) {
|
|
|
|
//
|
|
// compute checksum
|
|
//
|
|
|
|
sum = c;
|
|
i = tail;
|
|
while ( (i < 256) && (c != ( ')' - delta)) ) {
|
|
c = input[i++];
|
|
sum += c;
|
|
}
|
|
|
|
msd = input[i-3];
|
|
lsd = input[i-2];
|
|
|
|
sum -= msd;
|
|
sum -= lsd;
|
|
|
|
msd += delta;
|
|
lsd += delta;
|
|
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE,
|
|
("checksum from device (chars) = %c%c\n", (char)msd,
|
|
(char)lsd));
|
|
|
|
msd = Serenum_HToI((char)msd);
|
|
if (msd < 0) {
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR,
|
|
("Bad msd checksum digit\n"));
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
lsd = Serenum_HToI((char)lsd);
|
|
if (lsd < 0) {
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR,
|
|
("Bad lsd checksum digit\n"));
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
chk_sum = (msd << 4) + lsd;
|
|
|
|
sum &= 0xff;
|
|
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE,
|
|
("checksum read from device = %0x\n", chk_sum));
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE,
|
|
("Computed checksum = %0x\n", sum));
|
|
|
|
end_PnP_pos = (char)i;
|
|
|
|
if ( c - begin_PnP != ')' - '(' ) {
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR,
|
|
("GetDevPnPRev Failed,BeginPnP didn't match "
|
|
"EndPnP\n"));
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR,
|
|
("begin_PnP = %02x end_PnP = %02x\n", begin_PnP, c));
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// check the checksum
|
|
//
|
|
|
|
if (chk_sum != sum) {
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR,
|
|
("checksum Failed! Continuing...\n"));
|
|
// return STATUS_UNSUCCESSFUL; // Commented out in Memphis
|
|
}
|
|
|
|
i = end_PnP_pos;
|
|
|
|
input[i-3] = ')' - delta; // trash the checksum
|
|
input[i-2] = '\0'; // since we are done with it
|
|
}
|
|
|
|
if (input[tail] > 0x3f ||
|
|
input[tail+1] > 0x3f) {
|
|
|
|
Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Bad PnP Rev digits\n"));
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
i = (input[tail++] & 0x3f) << 6;
|
|
i |= (input[tail++]) & 0x3f;
|
|
|
|
Serenum_FixptToAscii(i, output);
|
|
|
|
i = tail;
|
|
|
|
//
|
|
// get ride of Mouse'output 0x20 bias in the string
|
|
//
|
|
while ( (i < 256) && delta ) {
|
|
input[i] += delta;
|
|
c = input[i++];
|
|
if ( c == ')' ) {
|
|
delta = 0; // indicate we are done
|
|
}
|
|
}
|
|
|
|
*start = tail;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
*
|
|
***************************************************************************/
|
|
void Serenum_GetDevName(
|
|
PCHAR input,
|
|
PCHAR output,
|
|
int *start)
|
|
{
|
|
|
|
int tail;
|
|
char c;
|
|
|
|
if(output == NULL || input == NULL)
|
|
return;
|
|
|
|
tail = *start;
|
|
|
|
// EISA ID
|
|
*output++ = input[tail++];
|
|
*output++ = input[tail++];
|
|
*output++ = input[tail++];
|
|
|
|
// Product ID
|
|
|
|
c = input[tail++];
|
|
if(Serenum_HToI(c) >= 0)
|
|
*output++ = c;
|
|
|
|
c = input[tail++];
|
|
if(Serenum_HToI(c) >= 0)
|
|
*output++ = c;
|
|
|
|
c = input[tail++];
|
|
if(Serenum_HToI(c) >= 0)
|
|
*output++ = c;
|
|
|
|
c = input[tail++];
|
|
if(Serenum_HToI(c) >= 0)
|
|
*output++ = c;
|
|
|
|
*output = '\0';
|
|
|
|
*start = tail;
|
|
|
|
return;
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
*
|
|
***************************************************************************/
|
|
void Serenum_GetDevSerialNo(
|
|
PCHAR input,
|
|
PCHAR output,
|
|
int *start)
|
|
{
|
|
|
|
int tail, cnt;
|
|
char c;
|
|
|
|
if(output == NULL || input == NULL)
|
|
return;
|
|
|
|
*output = '\0';
|
|
|
|
tail = *start;
|
|
|
|
if( input[tail++] != '\\')
|
|
return;
|
|
|
|
c = input[tail++];
|
|
|
|
cnt = 0;
|
|
|
|
while(cnt < 8 && tail < 256 && ( c != '\\') && ( c != ')') ) {
|
|
cnt++;
|
|
if(Serenum_HToI(c) < 0)
|
|
break;
|
|
|
|
*output++ = c;
|
|
c = input[tail++];
|
|
}
|
|
|
|
*output = '\0';
|
|
|
|
*start = tail - 1;
|
|
|
|
return;
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
*
|
|
***************************************************************************/
|
|
void Serenum_GetDevClass(
|
|
PCHAR input,
|
|
PCHAR output,
|
|
int *start)
|
|
{
|
|
|
|
int tail;
|
|
char c;
|
|
|
|
if(output == NULL || input == NULL)
|
|
return;
|
|
|
|
*output = '\0';
|
|
|
|
tail = *start;
|
|
|
|
if( input[tail++] != '\\')
|
|
return;
|
|
|
|
c = input[tail++];
|
|
|
|
while(tail < 256 && ( c != '\\') && ( c != ')') ) {
|
|
*output++ = c;
|
|
c = input[tail++];
|
|
}
|
|
*output = '\0';
|
|
|
|
*start = tail - 1;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void Serenum_GetDevCompId(
|
|
PCHAR input,
|
|
PCHAR output,
|
|
int *start)
|
|
/****************************************************************************
|
|
*
|
|
*
|
|
***************************************************************************/
|
|
{
|
|
|
|
int tail;
|
|
char c;
|
|
|
|
if(output == NULL || input == NULL)
|
|
return;
|
|
|
|
*output = '\0';
|
|
|
|
tail = *start;
|
|
|
|
if( input[tail++] != '\\')
|
|
return;
|
|
|
|
c = input[tail++];
|
|
|
|
while(tail < 256 && ( c != '\\') && ( c != ')') ) {
|
|
*output++ = c;
|
|
//
|
|
// Put a * after every comma
|
|
//
|
|
if ('\x0C' == c || '\x2C' == c) {
|
|
*output++ = '*';
|
|
}
|
|
c = input[tail++];
|
|
}
|
|
|
|
*output = '\0';
|
|
|
|
*start = tail - 1;
|
|
}
|
|
|
|
void
|
|
Serenum_GetDevDesc(
|
|
PCHAR input,
|
|
PCHAR output,
|
|
int *start)
|
|
/****************************************************************************
|
|
*
|
|
*
|
|
***************************************************************************/
|
|
{
|
|
|
|
int tail;
|
|
char c;
|
|
|
|
if(output == NULL || input == NULL)
|
|
return;
|
|
|
|
*output = '\0';
|
|
|
|
tail = *start;
|
|
|
|
if( input[tail++] != '\\')
|
|
return;
|
|
|
|
c = input[tail++];
|
|
|
|
while(tail < 256 && ( c != '\\') && ( c != ')') ) {
|
|
*output++ = c;
|
|
c = input[tail++];
|
|
}
|
|
|
|
*output = '\0';
|
|
|
|
*start = tail - 1;
|
|
}
|