//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*++

Module Name:

pctuple.cpp

Abstract:

This file implements the CPCCard model device driver tuple 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:


Notes:


--*/
#include <windows.h>
#include <types.h>
#include "cardsv2.h"
#include <ceddk.h>
#include <tuple.h>
#include <PcTuple.h>
#include "debug.h"

STATUS CPCTuple::CardGetFirstTuple( PCARD_TUPLE_PARMS pGetTupleParms )
{
    if( pGetTupleParms == NULL )
    {
        return CERR_BAD_ARGS;
    }
    //
    // Fill in where to start the tuple search
    //
    pGetTupleParms->uLinkOffset = 0;
    pGetTupleParms->uCISOffset = 0;
    pGetTupleParms->fFlags = 0;
    return GetDesiredTupe( pGetTupleParms );
}
STATUS CPCTuple::CardGetNextTuple( PCARD_TUPLE_PARMS pGetTupleParms )
{
    if( pGetTupleParms == NULL )
    {
        return CERR_BAD_ARGS;
    }
    return GetDesiredTupe( pGetTupleParms );
}
#define MAX_TUPLE_SIZE 0x400
STATUS CPCTuple::CardGetTupleData( PCARD_DATA_PARMS pGetTupleData )
{
    if( pGetTupleData == NULL )
    {
        return CERR_BAD_ARGS;
    }
    UINT16 uLength = ( UINT16 )
                     ( pGetTupleData->uCISOffset - pGetTupleData->uLinkOffset );
    if( pGetTupleData->uTupleOffset >=
        uLength ||
        pGetTupleData->uCISOffset -
        pGetTupleData->uLinkOffset >
        MAX_TUPLE_SIZE )
    {
        return CERR_BAD_ARGS;
    }
    PBYTE uBuffer = ( PBYTE ) ( pGetTupleData + 1 );
    uLength = min( uLength - pGetTupleData->uTupleOffset,
                   pGetTupleData->uBufLen );
    //
    for( UINT16 uIndex = 0; uIndex < uLength; uIndex++ )
    {
        uBuffer[uIndex] = GetTupleByte( pGetTupleData->uLinkOffset +
                                        pGetTupleData->uTupleOffset +
                                        uIndex );
    }
    pGetTupleData->uDataLen = uLength;
    DEBUGMSG( ZONE_TUPLE,
              ( TEXT( "CPCTuple::GetTupleData return uDesiredTuple=%x, uLinkOffset=%x, uCISOffset=%x\r\n" ),
                pGetTupleData->uDesiredTuple,
                pGetTupleData->uLinkOffset,
                pGetTupleData->uCISOffset ) );
#ifdef DEBUG
    {
        extern void DumpHex( DWORD dwLength, PBYTE pBuffer );
        if( ZONE_TUPLE )
        {
            DumpHex( pGetTupleData->uDataLen, uBuffer );
        }
    }
#endif
    return CERR_SUCCESS;
}
#define  MAX_TUPLE_MISSES 500
STATUS CPCTuple::GetDesiredTupe( PCARD_TUPLE_PARMS pGetTupleParms )
{
    PREFAST_DEBUGCHK( pGetTupleParms );
    STATUS status = CERR_NO_MORE_ITEMS;
    for( DWORD dwIndex = 0; dwIndex < MAX_TUPLE_MISSES; dwIndex ++ )
    {
#if 1
      // Paul, Chao @ 2006/11/17 for SII-AH-S405C CF Wireless Modem Card
      Sleep(1);
#endif
        // Prevent infinite loop.
        if( GetTupleByte( pGetTupleParms->uCISOffset ) != 0xff )
        {
            pGetTupleParms->uTupleCode = GetTupleByte( pGetTupleParms->uCISOffset++ );
            if( pGetTupleParms->uTupleCode == CISTPL_NULL )
            {
                // This is one byte tuple.
                continue;
            }
            pGetTupleParms->uTupleLink = GetTupleByte( pGetTupleParms->uCISOffset++ );
            if( pGetTupleParms->uTupleLink == 0 )
            {
                if( ( pGetTupleParms->uTupleCode != CISTPL_END ) &&
                    ( pGetTupleParms->uTupleCode != CISTPL_NO_LINK ) )
                {
                    pGetTupleParms->uLinkOffset = pGetTupleParms->uCISOffset;// Offset to Tuple Data.
                    pGetTupleParms->uCISOffset += pGetTupleParms->uTupleLink; // Offset to Next Tuple.
                    continue;
                }
            }

            if( ( pGetTupleParms->uDesiredTuple == pGetTupleParms->uTupleCode ) ||
                ( pGetTupleParms->uDesiredTuple == 0xff ) )
            {
                status = CERR_SUCCESS;
            }
            else if( ( pGetTupleParms->uTupleCode == CISTPL_LONGLINK_A ) ||
                     ( pGetTupleParms->uTupleCode == CISTPL_LONGLINK_C ) ||
                     ( pGetTupleParms->uTupleCode == CISTPL_LONGLINK_MFC ) ||
                     ( pGetTupleParms->uTupleCode == CISTPL_LINKTARGET ) ||
                     ( pGetTupleParms->uTupleCode == CISTPL_NO_LINK ) )
            {
                status = CERR_SUCCESS;
            }
            pGetTupleParms->uLinkOffset = pGetTupleParms->uCISOffset;// Offset to Tuple Data.
            pGetTupleParms->uCISOffset += pGetTupleParms->uTupleLink; // Offset to Next Tuple.
        }
        else
            break;
        DEBUGMSG( ZONE_TUPLE,
                  ( TEXT( "CPCTuple::GetDesiredTuple return succues with uTupleCode=0x%x,uDesiredTuple=%x, uLinkOffset=%x,uCISOffset=%x\r\n" ),
                    pGetTupleParms->uTupleCode,
                    pGetTupleParms->uDesiredTuple,
                    pGetTupleParms->uLinkOffset,
                    pGetTupleParms->uCISOffset ) );                    
        if( status == CERR_SUCCESS )
        {
            // Found
            return CERR_SUCCESS;
        }
    }
    // Out of luck
    return status;
}


