📄 tuple.c
字号:
pParms->uLinkOffset /= 2;
DEBUGMSG(ZONE_TUPLE,
(TEXT("I_CheckNextLink: processing CISTPL_LONGLINK_TO_A\r\n")));
} else {
return CERR_NO_MORE_ITEMS;
}
pParms->fFlags &= ~(TUPLE_FLAG_LINK_TO_A|TUPLE_FLAG_LINK_TO_C);
DEBUGMSG(ZONE_TUPLE,
(TEXT("I_CheckNextLink: CISOffset changing from 0x%x to 0x%x\r\n"),
pParms->uCISOffset, pParms->uLinkOffset));
//
// Point to correct memory space on PC card (attribute vs common)
//
DEBUGMSG(ZONE_TUPLE,
(TEXT("I_CheckNextLink: *pAttr changing from 0x%x"), *pAttr));
*pAttr = I_TupleGetWindow(pParms);
DEBUGMSG(ZONE_TUPLE,(TEXT(" to 0x%x\r\n"), *pAttr));
//
// Check that the link destination looks correct.
//
pParms->uCISOffset = pParms->uLinkOffset;
if (pParms->uCISOffset > TUPLE_WINDOW_SIZE/2) {
DEBUGMSG(ZONE_TUPLE|ZONE_WARNING,
(TEXT("I_CheckNextLink: Link target larger than window!\r\n")));
return CERR_NO_MORE_ITEMS;
}
status = I_ReadAttrByte(pAttr, pParms, 0, &tuple);
if (status != CERR_SUCCESS) {
DEBUGMSG(ZONE_TUPLE|ZONE_WARNING,
(TEXT("I_CheckNextLink: Read tuple code failed %d\r\n"), status));
return status;
}
if (tuple != CISTPL_LINKTARGET) {
DEBUGMSG(ZONE_TUPLE|ZONE_WARNING,
(TEXT("I_CheckNextLink: Invalid link target tuple!(0x%x s/b 0x%x)\r\n"),
tuple, CISTPL_LINKTARGET));
return CERR_NO_MORE_ITEMS;
}
status = I_ReadAttrWord(pAttr, pParms, 1, &uSig);
if (status != CERR_SUCCESS) {
DEBUGMSG(ZONE_TUPLE|ZONE_WARNING,
(TEXT("I_CheckNextLink: Read signature failed %d\r\n"), status));
return status;
}
uSig >>= 8; // ignore the link byte.
if (uSig != LINK_TARGET_SIG) {
DEBUGMSG(ZONE_TUPLE|ZONE_WARNING,
(TEXT("I_CheckNextLink: Invalid link target signature!(0x%x s/b 0x%x)\r\n"),
uSig, LINK_TARGET_SIG));
return CERR_NO_MORE_ITEMS;
}
pParms->fFlags &= TUPLE_FLAG_COMMON; // Clear all but mem mode.
return CERR_SUCCESS;
} // I_CheckNextLink
//
// Get the next tuple's code and link info.
//
// pAttr may get changed to a pointer to common memory if the CIS is in common
// memory.
//
STATUS
I_GetNextTuple(
PCHAR * pAttr,
PCARD_TUPLE_PARMS pParms
)
{
STATUS status;
if (I_CheckNextTuple(pAttr, pParms)) {
status = I_CheckNextLink(pAttr, pParms);
if (status) {
return status;
}
}
pParms->uTupleLink = 0;
status = I_ReadAttrByte(pAttr, pParms, 0, &(pParms->uTupleCode));
if ((status == CERR_SUCCESS) && (pParms->uTupleCode != CISTPL_END)) {
status = I_ReadAttrByte(pAttr, pParms, 1, &(pParms->uTupleLink));
}
if (status != CERR_SUCCESS) {
return status;
}
I_ReadLink(pAttr, pParms); // Remember info from link tuples.
return CERR_SUCCESS;
} // I_GetNextTuple
//
// Find the next requested tuple
//
STATUS
I_GetDesiredTuple(
PCHAR * pAttr,
PCARD_TUPLE_PARMS pParms
)
{
STATUS status;
int iMisses;
//
// Continue down this tuple chain until we find a match or hit the end.
//
for (iMisses = 0; iMisses < MAX_TUPLE_MISSES; iMisses++) {
//
// Only CISTPL_END and CISTPL_NO_LINK can have a 0 link field.
//
if (pParms->uTupleLink == 0) {
if ((pParms->uTupleCode != CISTPL_END) &&
(pParms->uTupleCode != CISTPL_NO_LINK)) {
goto igdt_next;
}
}
//
// See if this tuple matches what the caller requested.
//
if ((pParms->uDesiredTuple == pParms->uTupleCode) ||
(pParms->uDesiredTuple == 0xff)) {
if (pParms->fAttributes & TUPLE_RETURN_LINKS) {
return CERR_SUCCESS;
}
if ((pParms->uTupleCode != CISTPL_LONGLINK_A) &&
(pParms->uTupleCode != CISTPL_LONGLINK_C) &&
(pParms->uTupleCode != CISTPL_LONGLINK_MFC) &&
(pParms->uTupleCode != CISTPL_LINKTARGET) &&
(pParms->uTupleCode != CISTPL_NO_LINK)) {
return CERR_SUCCESS;
}
}
igdt_next:
status = I_GetNextTuple(pAttr, pParms);
if (status) {
return status;
}
}
return CERR_NO_MORE_ITEMS;
} // I_GetDesiredTuple
//
// CardGetNextTuple
//
// @doc DRIVERS
//
// @func STATUS | CardGetNextTuple | Finds the next desired tuple in the CIS.
// @rdesc Returns one of CERR_SUCCESS, CERR_BAD_ARGS, CERR_BAD_SOCKET, CERR_READ_FAILURE,
// CERR_OUT_OF_RESOURCE or CERR_NO_MORE_ITEMS.
//
// @comm Follows the CIS tuple chain specified by the uLinkOffset, uCISOffset and
// fFlags fields of the <t CARD_TUPLE_PARMS> structure. These fields were set
// by a previous call to <f CardGetFirstTuple> or CardGetNextTuple.
// The result fields, uTupleCode and uTupleLink, should be ignored when
// the return code is not CERR_SUCCESS.
// @xref <t CARD_DATA_PARMS>
//
STATUS
CardGetNextTuple(
PCARD_TUPLE_PARMS pParms // @parm Pointer to a <t CARD_TUPLE_PARMS> structure.
)
{
PLOG_SOCKET pSock;
PCHAR pAttr;
STATUS status;
DEBUGMSG(ZONE_FUNCTION|ZONE_TUPLE,
(TEXT("CardGetNextTuple entered\r\n")));
if (pParms == NULL) {
status = CERR_BAD_ARGS;
goto next_exit;
}
pSock = I_FindSocket(pParms->hSocket);
if (pSock == NULL) {
status = CERR_BAD_SOCKET;
goto next_exit;
}
if (!IsCardInserted(pParms->hSocket.uSocket)) {
status = CERR_READ_FAILURE;
goto next_exit;
}
pAttr = (PCHAR)I_TupleGetWindow(pParms);
if (pAttr == NULL) {
status = CERR_OUT_OF_RESOURCE;
goto next_exit;
}
status = I_GetNextTuple(&pAttr, pParms);
if (status) {
goto next_exit;
}
status = I_GetDesiredTuple(&pAttr, pParms);
next_exit:
#ifdef DEBUG
if (status) {
DEBUGMSG(ZONE_FUNCTION|ZONE_ERROR|ZONE_TUPLE,
(TEXT("CardGetNextTuple failed %d\r\n"), status));
} else {
DEBUGMSG(ZONE_FUNCTION|ZONE_TUPLE,
(TEXT("CardGetNextTuple succeeded\r\n")));
}
#endif
return status;
} // CardGetNextTuple
//
// CardGetFirstTuple
//
// @func STATUS | CardGetFirstTuple | Finds the desired tuple in the CIS.
// @rdesc Returns one of CERR_SUCCESS, CERR_BAD_ARGS, CERR_BAD_SOCKET, CERR_READ_FAILURE,
// CERR_OUT_OF_RESOURCE or CERR_NO_MORE_ITEMS.
//
// @comm Follows the CIS tuple chain searching for the desired tuple.
// On return, the uLinkOffset, uCISOffset and fFlags fields of the
// <t CARD_TUPLE_PARMS> structure are set so that subsequent calls to
// <f CardGetNextTuple> or <f CardGetTupleData> can follow the tuple chain.
// The result fields, uTupleCode and uTupleLink, should be ignored when
// the return code is not CERR_SUCCESS.
// @xref <t CARD_DATA_PARMS>
//
STATUS
CardGetFirstTuple(
PCARD_TUPLE_PARMS pParms // @parm Pointer to a <t CARD_TUPLE_PARMS> structure.
)
{
PLOG_SOCKET pSock;
PCHAR pAttr;
UINT8 uByte;
STATUS status;
DEBUGMSG(ZONE_FUNCTION|ZONE_TUPLE,
(TEXT("CardGetFirstTuple entered %d\r\n"), pParms->uDesiredTuple));
if (pParms == NULL) {
status = CERR_BAD_ARGS;
goto first_exit;
}
pSock = I_FindSocket(pParms->hSocket);
if (pSock == NULL) {
status = CERR_BAD_SOCKET;
goto first_exit;
}
if (!IsCardInserted(pParms->hSocket.uSocket)) {
status = CERR_READ_FAILURE;
goto first_exit;
}
//
// Check if a window has already been mapped to attribute space on this
// socket. Map a window if not and set it to attribute space mode.
//
pParms->fFlags = 0;
pAttr = (PCHAR)I_TupleGetWindow(pParms);
if (pAttr == NULL) {
status = CERR_OUT_OF_RESOURCE;
goto first_exit;
}
PcmciaPowerOn(pParms->hSocket.uSocket);
//
// Fill in where to start the tuple search
//
pParms->uLinkOffset = 0;
pParms->uCISOffset = 0;
pParms->fFlags = 0;
status = I_ReadAttrByte(&pAttr, pParms, 0, &uByte);
if (status) {
goto first_exit;
}
if (uByte == 0xFF) {
DEBUGMSG(ZONE_TUPLE|ZONE_WARNING,
(TEXT("CardGetFirstTuple: CIS is in common memory\r\n")));
// The CIS is in common memory.
pParms->fFlags = TUPLE_FLAG_COMMON;
pAttr = (PCHAR)I_TupleGetWindow(pParms);
if (pAttr == NULL) {
status = CERR_OUT_OF_RESOURCE;
goto first_exit;
}
}
status = I_ReadAttrByte(&pAttr, pParms, 0, &(pParms->uTupleCode));
if (status == CERR_SUCCESS) {
status = I_ReadAttrByte(&pAttr, pParms, 1, &(pParms->uTupleLink));
}
if (status) {
goto first_exit;
}
//
// Find the requested tuple type
//
status = I_GetDesiredTuple(&pAttr, pParms);
first_exit:
#ifdef DEBUG
if (status) {
DEBUGMSG(ZONE_FUNCTION|ZONE_ERROR|ZONE_TUPLE,
(TEXT("CardGetFirstTuple failed %d\r\n"), status));
} else {
DEBUGMSG(ZONE_FUNCTION|ZONE_TUPLE,
(TEXT("CardGetFirstTuple succeeded\r\n")));
}
#endif
return status;
} // CardGetFirstTuple
//
// CardGetTupleData
//
// @func STATUS | CardGetTupleData | Reads the data from the current tuple.
// @rdesc Returns one of CERR_SUCCESS, CERR_BAD_ARGS, CERR_BAD_SOCKET, CERR_READ_FAILURE,
// CERR_OUT_OF_RESOURCE, CERR_NO_MORE_ITEMS or CERR_BAD_ARG_LENGTH.
//
// @comm Reads the CIS data from the specified PC card at the location specified by
// the uCISOffset and uTupleOffset fields. The uCISOffset field should be the
// value set by a previous call to <f CardGetFirstTuple> or <f CardGetNextTuple>.
// @xref <t CARD_TUPLE_PARMS>
//
STATUS
CardGetTupleData(
PCARD_DATA_PARMS pData // @parm Pointer to a <t CARD_DATA_PARMS> structure.
)
{
PLOG_SOCKET pSock;
PCHAR pAttr;
PCHAR pBuf;
UINT uNumBytes, uOffset;
STATUS status;
UINT8 tuple;
DEBUGMSG(ZONE_FUNCTION|ZONE_TUPLE,
(TEXT("CardGetTupleData entered\r\n")));
if (pData == NULL) {
status = CERR_BAD_ARGS;
goto data_exit;
}
pSock = I_FindSocket(pData->hSocket);
if (pSock == NULL) {
status = CERR_BAD_SOCKET;
goto data_exit;
}
if (!IsCardInserted(pData->hSocket.uSocket)) {
status = CERR_READ_FAILURE;
goto data_exit;
}
pAttr = (PCHAR)I_TupleGetWindow((PCARD_TUPLE_PARMS)pData);
if (pAttr == NULL) {
status = CERR_OUT_OF_RESOURCE;
goto data_exit;
}
DEBUGMSG(ZONE_TUPLE,
(TEXT("CardGetTupleData: uCISOffset = 0x%x\r\n"), pData->uCISOffset));
//
// There is no data for CISTPL_END
//
pData->uDataLen = 0;
status = I_ReadAttrByte(
&pAttr,
(PCARD_TUPLE_PARMS)pData,
0,
&tuple);
if ((status != CERR_SUCCESS) || (tuple == CISTPL_END)) {
goto data_exit;
}
//
// Get length from link field.
//
status = I_ReadAttrByte(
&pAttr,
(PCARD_TUPLE_PARMS)pData,
1,
(PCHAR)(&(pData->uDataLen)));
if (status) {
goto data_exit;
}
//
// Check if they want more than is there.
//
if (pData->uDataLen < pData->uTupleOffset) {
status = CERR_NO_MORE_ITEMS;
goto data_exit;
}
//
// See if user buffer has enough room
//
pData->uDataLen -= pData->uTupleOffset;
if (pData->uDataLen > pData->uBufLen) {
status = CERR_BAD_ARG_LENGTH;
goto data_exit;
}
pBuf = (PCHAR)pData;
pBuf += sizeof(CARD_DATA_PARMS); // point to user's buffer.
uNumBytes = pData->uDataLen;
uOffset = pData->uTupleOffset + 2; // skip code and link
while (uNumBytes) {
status = I_ReadAttrByte(
&pAttr,
(PCARD_TUPLE_PARMS)pData,
uOffset,
pBuf);
if (status != CERR_SUCCESS) {
goto data_exit;
}
pBuf++;
uNumBytes--;
uOffset++;
}
data_exit:
#ifdef DEBUG
if (status) {
DEBUGMSG(ZONE_FUNCTION|ZONE_ERROR|ZONE_TUPLE,
(TEXT("CardGetTupleData failed %d\r\n"), status));
} else {
DEBUGMSG(ZONE_FUNCTION|ZONE_TUPLE,
(TEXT("CardGetTupleData succeeded\r\n")));
}
#endif
return status;
} // CardGetTupleData
//
// VarToFixed - convert the bytes of a variable length field into a UINT32
// and return fixed length value.
//
UINT32
VarToFixed(
UINT32 VarSize,
PUCHAR pBytes
)
{
UINT32 Fixed = 0;
//
// Parse the bytes starting from the MSB and shift them into place.
//
while (VarSize) {
VarSize--;
Fixed <<= 8;
Fixed |= (UINT32) pBytes[VarSize];
}
return Fixed;
}
//
// ParseConfig - Read the CISTPL_CONFIG tuple from the CIS and format it into a
// PARSED_CONFIG structure.
//
STATUS
ParseConfig(
CARD_SOCKET_HANDLE hSocket,
PVOID pBuf,
PUINT pnItems
)
{
STATUS status;
PPARSED_CONFIG pCfg = (PPARSED_CONFIG)pBuf;
UCHAR buf[BUFFER_SIZE + sizeof(CARD_DATA_PARMS)];
PCARD_DATA_PARMS pData;
PCARD_TUPLE_PARMS pTuple;
PUCHAR pCIS;
UINT AddrSz;
//
// Find and read the second CISTPL_CONFIG tuple if possible.
// (Some MFC cards contain a CISTPL_CONFIG in the CISTPL_LONGLINK_MFC chain)
//
pTuple = (PCARD_TUPLE_PARMS)buf;
pTuple->hSocket = hSocket;
pTuple->uDesiredTuple = CISTPL_CONFIG;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -