William Kane / Generic

Dependents:   LaserioLib

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ad_obj.c Source File

ad_obj.c

00001 /*******************************************************************************
00002 ********************************************************************************
00003 **                                                                            **
00004 ** ABCC Starter Kit version 2.01.01 (2015-12-14)                              **
00005 **                                                                            **
00006 ** Delivered with:                                                            **
00007 **    ABCC Driver 4.01.01 (2015-12-14)                                        **
00008 **    ABP         7.16.01 (2015-10-14)                                        **
00009 **                                                                            */
00010 /*******************************************************************************
00011 ********************************************************************************
00012 ** COPYRIGHT NOTIFICATION (c) 2015 HMS Industrial Networks AB                 **
00013 **                                                                            **
00014 ** This code is the property of HMS Industrial Networks AB.                   **
00015 ** The source code may not be reproduced, distributed, or used without        **
00016 ** permission. When used together with a product from HMS, permission is      **
00017 ** granted to modify, reproduce and distribute the code in binary form        **
00018 ** without any restrictions.                                                  **
00019 **                                                                            **
00020 ** THE CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. HMS DOES NOT    **
00021 ** WARRANT THAT THE FUNCTIONS OF THE CODE WILL MEET YOUR REQUIREMENTS, OR     **
00022 ** THAT THE OPERATION OF THE CODE WILL BE UNINTERRUPTED OR ERROR-FREE, OR     **
00023 ** THAT DEFECTS IN IT CAN BE CORRECTED.                                       **
00024 ********************************************************************************
00025 ********************************************************************************
00026 ** Implementation of the AD object.
00027 ********************************************************************************
00028 ********************************************************************************
00029 */
00030 #include "abcc_td.h"
00031 #include "abcc_sw_port.h"
00032 #include "abcc_drv_cfg.h"
00033 #include "abcc_obj_cfg.h"
00034 #include "abp.h"
00035 #include "abcc_ad_if.h"
00036 #include "abcc.h"
00037 #include "appl_abcc_handler.h"
00038 #include "abcc_sys_adapt.h"
00039 #include "ad_obj.h"
00040 
00041 /*******************************************************************************
00042 ** Constants
00043 ********************************************************************************
00044 */
00045 
00046 #if( ABCC_CFG_REMAP_SUPPORT_ENABLED )
00047 #if( AD_MAX_NUM_WRITE_ADI_TO_MAP > AD_MAX_NUM_READ_ADI_TO_MAP )
00048 #define AD_MAX_OF_READ_WRITE_TO_MAP AD_MAX_NUM_WRITE_ADI_TO_MAP
00049 #else
00050 #define AD_MAX_OF_READ_WRITE_TO_MAP AD_MAX_NUM_READ_ADI_TO_MAP
00051 #endif
00052 #endif
00053 
00054 /*
00055 ** Value used in ad_MapType as ADI index when ADI 0 is mapped.
00056 */
00057 #define AD_MAP_PAD_INDEX                     ( 0xfffe )
00058 
00059 /*
00060 ** Invalid ADI index.
00061 */
00062 #define AD_INVALID_ADI_INDEX                 ( 0xffff )
00063 
00064 /*
00065 ** Default number of sub-elements
00066 */
00067 #define AD_DEFAULT_NUM_SUB_ELEMS             ( 1 )
00068 
00069 /*******************************************************************************
00070 ** Typedefs
00071 ********************************************************************************
00072 */
00073 
00074 /*------------------------------------------------------------------------------
00075 ** Type with mapping information for a single ADI
00076 **------------------------------------------------------------------------------
00077 ** iAdiIndex      - Index to ADI entry table.
00078 ** bNumElements   - Number of mapped elements.
00079 ** bStartIndex    - Element start index for the mapping
00080 **------------------------------------------------------------------------------
00081 */
00082 typedef struct ad_Map
00083 {
00084   UINT16           iAdiIndex;
00085   UINT8            bNumElements;
00086   UINT8            bStartIndex;
00087 }
00088 ad_MapType;
00089 
00090 /*------------------------------------------------------------------------------
00091 ** Type with mapping information for a specific direction (read/write).
00092 **------------------------------------------------------------------------------
00093 ** paiMappedAdiList    - Pointer to list of all mapped items.
00094 ** iNumMappedAdi       - Number of mapped ADI:s
00095 ** iMaxNumMappedAdi    - Maximum number of mapped ADI:s.
00096 ** iPdSize             - Current process data size in octets.
00097 **------------------------------------------------------------------------------
00098 */
00099 typedef struct ad_MapInfo
00100 {
00101    ad_MapType*   paiMappedAdiList;
00102    UINT16        iNumMappedAdi;
00103    UINT16        iMaxNumMappedAdi;
00104    UINT16        iPdSize;
00105 }
00106 ad_MapInfoType;
00107 
00108 /*******************************************************************************
00109 ** Private Globals
00110 ********************************************************************************
00111 */
00112 static BOOL ad_fDoNetworkEndianSwap = FALSE;
00113 static const AD_DefaultMapType* ad_asDefaultMap = NULL;
00114 static const AD_AdiEntryType* ad_asADIEntryList = NULL;
00115 static UINT16  ad_iNumOfADIs;
00116 static UINT16  ad_iHighestInstanceNumber;
00117 static ad_MapType ad_PdReadMapping[ AD_MAX_NUM_READ_ADI_TO_MAP ];
00118 static ad_MapType ad_PdWriteMapping[ AD_MAX_NUM_WRITE_ADI_TO_MAP ];
00119 static ad_MapInfoType ad_ReadMapInfo;
00120 static ad_MapInfoType ad_WriteMapInfo;
00121 
00122 /*******************************************************************************
00123 ** Private Services
00124 ********************************************************************************
00125 */
00126 
00127 /*------------------------------------------------------------------------------
00128 ** Converts number of octet offset to byte offset.
00129 **------------------------------------------------------------------------------
00130 */
00131 #ifdef ABCC_SYS_16_BIT_CHAR
00132 #define OctetToByteOffset( x )  ( ( x ) >> 1 )
00133 #else
00134 #define OctetToByteOffset( x )  ( x )
00135 #endif
00136 
00137 /*------------------------------------------------------------------------------
00138 ** Checks if a ABP data type is either a bit or pad type.
00139 **------------------------------------------------------------------------------
00140 */
00141 #define Is_BITx_Or_PADx( type ) ( ABP_Is_PADx( type ) || ABP_Is_BITx( type ) )
00142 
00143 /*------------------------------------------------------------------------------
00144 ** The bit variable is converted to whole octets and added to the octet variable.
00145 ** The remaining bits are saved to the bit variable.
00146 ** For a 16 bit char system the number of octets are kept even.
00147 ** Note that both input variables are updated.
00148 **------------------------------------------------------------------------------
00149 */
00150 #ifdef ABCC_SYS_16_BIT_CHAR
00151 #define AddBitsToOctetSize( octet, bits ) \
00152 do                                        \
00153 {                                         \
00154    (octet) += (bits >> 4 ) << 1;          \
00155    (bits) %= 16;                          \
00156 }                                         \
00157 while( 0 )
00158 #else
00159 #define AddBitsToOctetSize( octet, bits ) \
00160 do                                        \
00161 {                                         \
00162    (octet) += (bits) >> 3;                \
00163    (bits) %= 8;                           \
00164 }                                         \
00165 while( 0 )
00166 #endif
00167 
00168 /*------------------------------------------------------------------------------
00169 ** Calculates the bit offset to the startindex element in the ADI.
00170 **------------------------------------------------------------------------------
00171 */
00172 #define CalcStartindexBitOffset( bDataType, iStartIndex )      \
00173    ABCC_GetDataTypeSizeInBits( bDataType ) * ( iStartIndex )
00174 
00175 
00176 /*------------------------------------------------------------------------------
00177 ** Add octet variable and bit variable and round up to nearest octet.
00178 **------------------------------------------------------------------------------
00179 */
00180 #define SizeInOctets( octet, bits ) ( (octet) + ( (bits) + 7 ) / 8 )
00181 
00182 /*------------------------------------------------------------------------------
00183 ** Convert bit offset to octet offset.
00184 **------------------------------------------------------------------------------
00185 */
00186 #define BitToOctetOffset( bitOffset ) ( (bitOffset) >> 3 )
00187 
00188 /*------------------------------------------------------------------------------
00189 ** Copies a 16 bit values from a source to a destination. Each value will be
00190 ** endian swapped. The function support octet alignment.
00191 **------------------------------------------------------------------------------
00192 ** Arguments:
00193 **    pxDest            - Base pointer to the destination.
00194 **    iDestOctetOffset  - Octet offset to the destination where the copy will
00195 **                        begin.
00196 **    pxSrc             - Bsse pointer to source data.
00197 **    iSrcOctetOffset   - Octet offset to the source where the copy will begin.
00198 **    iNumElem          - Number of 16 bit values to copy.
00199 **
00200 ** Returns:
00201 **    None
00202 **------------------------------------------------------------------------------
00203 */
00204 static void Copy16WithEndianSwap( void* pxDest, UINT16 iDestOctetOffset,
00205                                   void* pxSrc,  UINT16 iSrcOctetOffset,
00206                                   UINT16 iNumElem )
00207 {
00208    UINT16 i;
00209    UINT16 iConv;
00210 
00211    for( i = 0; i < iNumElem; i++ )
00212    {
00213       ABCC_PORT_Copy16( &iConv, 0, pxSrc, iSrcOctetOffset + ( i << 1 ) );
00214       iConv = ABCC_iEndianSwap( iConv );
00215       ABCC_PORT_Copy16( pxDest, iDestOctetOffset + ( i << 1 ), &iConv, 0 );
00216    }
00217 }
00218 
00219 /*------------------------------------------------------------------------------
00220 ** Copies a 32 bit values from a source to a destination. Each value will be
00221 ** endian swapped. The function support octet alignment.
00222 **------------------------------------------------------------------------------
00223 ** Arguments:
00224 **    pxDest            - Base pointer to the destination.
00225 **    iDestOctetOffset  - Octet offset to the destination where the copy will
00226 **                        begin.
00227 **    pxSrc             - Bsse pointer to source data.
00228 **    iSrcOctetOffset   - Octet offset to the source where the copy will begin.
00229 **    iNumElem          - Number of 32 bit values to copy.
00230 **
00231 ** Returns:
00232 **    None
00233 **------------------------------------------------------------------------------
00234 */
00235 static void Copy32WithEndianSwap( void* pxDest, UINT16 iDestOctetOffset,
00236                                   void* pxSrc,  UINT16 iSrcOctetOffset,
00237                                   UINT16 iNumElem )
00238 {
00239    UINT16 i;
00240    UINT32 lConv;
00241 
00242    for( i = 0; i < iNumElem; i++ )
00243    {
00244       ABCC_PORT_Copy32( &lConv, 0, pxSrc, iSrcOctetOffset + ( i << 2 ) );
00245       lConv = ABCC_lEndianSwap( lConv );
00246       ABCC_PORT_Copy32( pxDest, iDestOctetOffset + ( i << 2 ), &lConv, 0 );
00247    }
00248 }
00249 
00250 
00251 /*------------------------------------------------------------------------------
00252 ** Copies a 64 bit values from a source to a destination. Each value will be
00253 ** endian swapped. The function support octet alignment.
00254 **------------------------------------------------------------------------------
00255 ** Arguments:
00256 **    pxDest            - Base pointer to the destination.
00257 **    iDestOctetOffset  - Octet offset to the destination where the copy will
00258 **                        begin.
00259 **    pxSrc             - Bsse pointer to source data.
00260 **    iSrcOctetOffset   - Octet offset to the source where the copy will begin.
00261 **    iNumElem          - Number of 64 bit values to copy.
00262 **
00263 ** Returns:
00264 **    None
00265 **------------------------------------------------------------------------------
00266 */
00267 #if( ABCC_CFG_64BIT_ADI_SUPPORT )
00268 static void Copy64WithEndianSwap( void* pxDest, UINT16 iDestOctetOffset,
00269                                   void* pxSrc,  UINT16 iSrcOctetOffset,
00270                                   UINT16 iNumElem )
00271 {
00272    UINT16 i;
00273    UINT64 lConv;
00274 
00275    for( i = 0; i < iNumElem; i++ )
00276    {
00277       ABCC_PORT_Copy64( &lConv, 0, pxSrc, iSrcOctetOffset + ( i << 3 ) );
00278       lConv = ABCC_lEndianSwap64( lConv );
00279       ABCC_PORT_Copy64( pxDest, iDestOctetOffset + ( i << 3 ), &lConv, 0 );
00280    }
00281 }
00282 #endif
00283 
00284 /*------------------------------------------------------------------------------
00285 ** Calculates size of ADI rounded up to nearest octet.
00286 **------------------------------------------------------------------------------
00287 ** Arguments:
00288 **    psAdiEntry  -  Pointer to ADI entry.
00289 **
00290 ** Returns:
00291 **    Size in octets.
00292 **------------------------------------------------------------------------------
00293 */
00294 static UINT16 GetAdiSizeInOctets( const AD_AdiEntryType* psAdiEntry )
00295 {
00296    UINT16 iSize;
00297 #if( ABCC_CFG_STRUCT_DATA_TYPE )
00298    UINT16 i;
00299 
00300    if( psAdiEntry->psStruct != NULL )
00301    {
00302       iSize = 0;
00303       for( i = 0; i < psAdiEntry->bNumOfElements; i++ )
00304       {
00305          iSize +=
00306             ABCC_GetDataTypeSizeInBits( psAdiEntry->psStruct[ i ].bDataType );
00307       }
00308    }
00309    else
00310 #endif
00311    {
00312       iSize = ABCC_GetDataTypeSizeInBits( psAdiEntry->bDataType ) *
00313                                           psAdiEntry->bNumOfElements ;
00314    }
00315    iSize = ( iSize + 7 ) / 8;
00316    return( iSize );
00317 }
00318 
00319 /*------------------------------------------------------------------------------
00320 ** Calculates map size of of an ADI mapping item, in bits.
00321 **------------------------------------------------------------------------------
00322 ** Arguments:
00323 **    psAdiEntry         -  Pointer to ADI entry.
00324 **    bNumElem           -  Number of elements
00325 **    bElemStartIndex    -  First element index.
00326 **
00327 ** Returns:
00328 **    Size in bits.
00329 **------------------------------------------------------------------------------
00330 */
00331 static UINT16 GetAdiMapSizeInBits( const AD_AdiEntryType* psAdiEntry,
00332                                    UINT8 bNumElem,
00333                                    UINT8 bElemStartIndex )
00334 {
00335    UINT16 iSize;
00336 #if( ABCC_CFG_STRUCT_DATA_TYPE )
00337    UINT16 i;
00338    if( psAdiEntry->psStruct != NULL )
00339    {
00340       iSize = 0;
00341       for( i = bElemStartIndex; i < ( bNumElem + bElemStartIndex ) ; i++ )
00342       {
00343          iSize +=
00344             ABCC_GetDataTypeSizeInBits( psAdiEntry->psStruct[ i ].bDataType );
00345       }
00346    }
00347    else
00348    {
00349       iSize = ABCC_GetDataTypeSizeInBits( psAdiEntry->bDataType ) * bNumElem ;
00350    }
00351 #else
00352       (void)bElemStartIndex;
00353       iSize = ABCC_GetDataTypeSizeInBits( psAdiEntry->bDataType ) * bNumElem ;
00354 #endif
00355 
00356    return( iSize );
00357 }
00358 
00359 /*------------------------------------------------------------------------------
00360 ** Calculates total map size in octets.
00361 **------------------------------------------------------------------------------
00362 ** Arguments:
00363 **    psMap         -  Pointer to mapping information. The size is
00364 **                     calculated based on the on the mapping list provided
00365 **                     in the structure. The iPdSize member is updated with
00366 **                     the new size.
00367 **
00368 ** Returns:
00369 **    None.
00370 **------------------------------------------------------------------------------
00371 */
00372 static void UpdateMapSize( ad_MapInfoType* psMap )
00373 {
00374    UINT16 iMapIndex;
00375    UINT16 iAdiIndex;
00376 
00377    psMap->iPdSize = 0;
00378    for( iMapIndex = 0; iMapIndex < psMap->iNumMappedAdi; iMapIndex++ )
00379    {
00380       iAdiIndex = psMap->paiMappedAdiList[ iMapIndex ].iAdiIndex;
00381       if( iAdiIndex != AD_MAP_PAD_INDEX )
00382       {
00383          psMap->iPdSize +=
00384             GetAdiMapSizeInBits( &ad_asADIEntryList[ iAdiIndex ],
00385                                  psMap->paiMappedAdiList[ iMapIndex ].bNumElements,
00386                                  psMap->paiMappedAdiList[ iMapIndex ].bStartIndex );
00387       }
00388       else
00389       {
00390          psMap->iPdSize += psMap->paiMappedAdiList[ iMapIndex ].bNumElements;
00391       }
00392    }
00393    psMap->iPdSize = SizeInOctets( 0, psMap->iPdSize );
00394 }
00395 
00396 /*------------------------------------------------------------------------------
00397 ** Find ADI entry table index for the specified instance number.
00398 **------------------------------------------------------------------------------
00399 ** Arguments:
00400 **    iInstance         -  Instance number.
00401 **
00402 ** Returns:
00403 **    0 - 0xfffe                - Index in ADI entry table.
00404 **    AD_INVALID_ADI_INDEX      - Instance was not found.
00405 **------------------------------------------------------------------------------
00406 */
00407 static UINT16 GetAdiIndex( UINT16 iInstance )
00408 {
00409    UINT16 i;
00410    UINT16  iIndex;
00411 
00412    iIndex = AD_INVALID_ADI_INDEX;
00413 
00414    if( iInstance == 0 )
00415    {
00416       return( AD_MAP_PAD_INDEX );
00417    }
00418 
00419    for( i = 0; i < ad_iNumOfADIs; i++ )
00420    {
00421       if( ad_asADIEntryList[ i ].iInstance == iInstance )
00422       {
00423          iIndex = i;
00424          break;
00425       }
00426    }
00427 
00428    return( iIndex );
00429 }
00430 
00431 #if( ABCC_CFG_REMAP_SUPPORT_ENABLED )
00432 /*------------------------------------------------------------------------------
00433 ** Process of remap command.
00434 **------------------------------------------------------------------------------
00435 ** Arguments:
00436 **    ABP_MsgType         - Pointer to remap command.
00437 **    psCurrMap           - Pointer to current mapping. Will hold the new
00438 **                          mapping when processing is done.
00439 **
00440 ** Returns:
00441 **    None.
00442 **------------------------------------------------------------------------------
00443 */
00444 static void RemapProcessDataCommand( ABP_MsgType* psMsg,
00445                                      ad_MapInfoType* psCurrMap )
00446 {
00447 
00448    UINT16 iAdi;
00449    UINT16 iMsgIndex;
00450    UINT16 iAddItemIndex;
00451    UINT16 iMapIndex;
00452    UINT16 bStartOfRemap;
00453    UINT8  bErrCode;
00454    UINT16 iItemsToRemove;
00455    UINT16 iItemsToAdd;
00456    UINT16 iDataSize;
00457    ad_MapType sMap;
00458 
00459    iDataSize = 1;
00460    bStartOfRemap = ABCC_GetMsgCmdExt( psMsg );
00461 
00462    ABCC_GetMsgData16( psMsg, &iItemsToRemove, 0);
00463    ABCC_GetMsgData16( psMsg, &iItemsToAdd, 2);
00464 
00465    /*
00466    ** A lot of sanity checks first since all actions of the command shall
00467    ** either be carried out or rejected.
00468    */
00469    if( ABCC_GetMsgDataSize( psMsg ) < 4 )
00470    {
00471       /*
00472       ** Not enough data provided
00473       */
00474       bErrCode = ABP_ERR_NOT_ENOUGH_DATA;
00475    }
00476    else if( bStartOfRemap > psCurrMap->iNumMappedAdi )
00477    {
00478       /*
00479       ** Not an allowed mapping number
00480       */
00481       bErrCode = ABP_ERR_INV_CMD_EXT_0;
00482    }
00483    else if( ( bStartOfRemap + iItemsToRemove ) > psCurrMap->iNumMappedAdi )
00484    {
00485       /*
00486       ** Cannot remove more than currently is mapped
00487       */
00488       bErrCode = ABP_ERR_OUT_OF_RANGE;
00489    }
00490    else if( ( psCurrMap->iNumMappedAdi + iItemsToAdd - iItemsToRemove )  >
00491               psCurrMap->iMaxNumMappedAdi )
00492    {
00493       /*
00494       ** This will result in more maps than we can handle
00495       */
00496       bErrCode = ABP_ERR_NO_RESOURCES;
00497    }
00498    else if( ABCC_GetMsgDataSize( psMsg ) < 4 + ( iItemsToAdd * 4 ) )
00499    {
00500       bErrCode = ABP_ERR_NOT_ENOUGH_DATA;
00501    }
00502    else if( ABCC_GetMsgDataSize( psMsg ) > 4 + ( iItemsToAdd * 4 ) )
00503    {
00504       bErrCode = ABP_ERR_TOO_MUCH_DATA;
00505    }
00506    else
00507    {
00508       bErrCode = ABP_ERR_NO_ERROR;
00509    }
00510 
00511    /*
00512    ** Check New ADI:s
00513    */
00514    if( bErrCode == ABP_ERR_NO_ERROR )
00515    {
00516       iAddItemIndex = 0;
00517       iMsgIndex = 4;
00518       while( ( bErrCode == ABP_ERR_NO_ERROR ) && ( iAddItemIndex < iItemsToAdd ) )
00519       {
00520          ABCC_GetMsgData16( psMsg, &iAdi, iMsgIndex );
00521          sMap.iAdiIndex = GetAdiIndex( iAdi );
00522          iMsgIndex += 2;
00523          ABCC_GetMsgData8( psMsg, &sMap.bStartIndex, iMsgIndex++ );
00524          ABCC_GetMsgData8( psMsg, &sMap.bNumElements, iMsgIndex++ );
00525 
00526          if( sMap.iAdiIndex != AD_MAP_PAD_INDEX )
00527          {
00528             if( ( sMap.bStartIndex + sMap.bNumElements ) >
00529                    ad_asADIEntryList[ sMap.iAdiIndex ].bNumOfElements )
00530             {
00531                bErrCode = ABP_ERR_OBJ_SPECIFIC;
00532                /*
00533                ** ABP_APPD_ERR_INVALID_NUM_ELEMENTS
00534                */
00535                ABCC_SetMsgData8( psMsg, 0x02, 1 );
00536                iDataSize = 2;
00537             }
00538          }
00539          iAddItemIndex++;
00540       }
00541    }
00542 
00543    if( bErrCode == ABP_ERR_NO_ERROR )
00544    {
00545       /*
00546       ** Move ADI if required
00547       */
00548       if( ( iItemsToRemove != iItemsToAdd ) &&
00549           ( iItemsToRemove  <  ( psCurrMap->iNumMappedAdi - bStartOfRemap  ) ) )
00550       {
00551          INT16  iItemsToMove;
00552          UINT16 iMoveFrom;
00553          UINT16 iMoveTo;
00554          UINT16 iIndex;
00555 
00556          /*
00557          ** Data needs to be moved
00558          */
00559          iMoveFrom = bStartOfRemap + iItemsToRemove;
00560          iMoveTo = bStartOfRemap  + iItemsToAdd;
00561          iItemsToMove = psCurrMap->iNumMappedAdi - bStartOfRemap - iItemsToRemove;
00562 
00563          if( iItemsToRemove > iItemsToAdd )
00564          {
00565             for( iIndex = 0; iIndex < iItemsToMove; iIndex++ )
00566             {
00567                psCurrMap->paiMappedAdiList[ iMoveTo + iIndex ] =
00568                   psCurrMap->paiMappedAdiList[ iMoveFrom + iIndex ];
00569             }
00570          }
00571          else
00572          {
00573             for( iIndex = iItemsToMove ; iIndex > 0 ; iIndex-- )
00574             {
00575                psCurrMap->paiMappedAdiList[ iMoveTo + iIndex - 1 ] =
00576                   psCurrMap->paiMappedAdiList[ iMoveFrom + iIndex - 1 ];
00577             }
00578          }
00579       }
00580 
00581       iMapIndex = bStartOfRemap;
00582       psCurrMap->iNumMappedAdi -= iItemsToRemove;
00583       psCurrMap->iNumMappedAdi += iItemsToAdd;
00584 
00585       iMsgIndex = 4;
00586       for( iAddItemIndex = 0; iAddItemIndex < iItemsToAdd; iAddItemIndex++ )
00587       {
00588          ABCC_GetMsgData16( psMsg, &iAdi, iMsgIndex );
00589          psCurrMap->paiMappedAdiList[ iMapIndex ].iAdiIndex = GetAdiIndex( iAdi );
00590          iMsgIndex += 2;
00591          ABCC_GetMsgData8( psMsg, &psCurrMap->paiMappedAdiList[ iMapIndex ].bStartIndex, iMsgIndex++ );
00592          ABCC_GetMsgData8( psMsg, &psCurrMap->paiMappedAdiList[ iMapIndex ].bNumElements, iMsgIndex++ );
00593          iMapIndex++;
00594       }
00595 
00596       UpdateMapSize( psCurrMap );
00597 
00598       ABCC_SetMsgData16(psMsg, psCurrMap->iPdSize, 0);
00599       ABP_SetMsgResponse( psMsg, 2 );
00600       ABCC_SendRemapRespMsg( psMsg, ad_ReadMapInfo.iPdSize,
00601                              ad_WriteMapInfo.iPdSize);
00602    }
00603    else
00604    {
00605       ABP_SetMsgErrorResponse( psMsg, iDataSize, bErrCode );
00606       ABCC_SendRespMsg(psMsg );
00607    }
00608 }
00609 #endif
00610 
00611 
00612 /*------------------------------------------------------------------------------
00613 ** Copy bit data. Any alignment is allowed.
00614 **------------------------------------------------------------------------------
00615 ** Arguments:
00616 **    pxDest            - Destination base pointer.
00617 **    iDestBitOffset    - Bit offset relative destination pointer.
00618 **    pxSrc             - Source base pointer.
00619 **    iSrcBitOffset     - Bit offset relative source pointer.
00620 **    bDataType         - Data type according to ABP_<X> types in abp.h
00621 **    iNumElem          - Number of elements to copy.
00622 **
00623 ** Returns:
00624 **    Size of copied data in bits.
00625 **------------------------------------------------------------------------------
00626 */
00627 static UINT16 CopyBitData( void* pxDest,
00628                            UINT16 iDestBitOffset,
00629                            void* pxSrc,
00630                            UINT16 iSrcBitOffset,
00631                            UINT8 bDataType,
00632                            UINT16 iNumElem )
00633 {
00634    UINT8  bCopySize;
00635    UINT16 i;
00636    UINT16 iSetBitSize = 0;
00637    UINT32 lBitMask;
00638    UINT32 lSrc;
00639    UINT32 lDest;
00640    UINT16 iSrcOctetOffset;
00641    UINT16 iDestOctetOffset;
00642 
00643    iSrcOctetOffset = 0;
00644    iDestOctetOffset = 0;
00645 
00646    if( ABP_Is_PADx( bDataType ) )
00647    {
00648       /*
00649       ** This is only a pad. No copy is done.
00650       */
00651       iSetBitSize += bDataType - ABP_PAD0;
00652    }
00653    else
00654    {
00655       /*
00656       ** Separate offsets into octets and bits.
00657       */
00658       AddBitsToOctetSize( iSrcOctetOffset, iSrcBitOffset );
00659       AddBitsToOctetSize( iDestOctetOffset, iDestBitOffset );
00660 
00661       /*
00662       ** Calculate number of bits to be set.
00663       */
00664       iSetBitSize += ( ( bDataType - ABP_BIT1 ) + 1 );
00665 
00666       for( i = 0; i < iNumElem; i++ )
00667       {
00668          /*
00669          ** Calculate the number of octets that has to be copied
00670          ** to include both destination bit offset and bit size.
00671          */
00672          bCopySize = ( iSetBitSize + iDestBitOffset + 7 ) / 8;
00673 
00674          /*
00675          ** Copy parts to be manipulated into local 32 bit variables to
00676          ** guarantee correct alignment.
00677          */
00678          ABCC_PORT_CopyOctets( &lSrc, 0, pxSrc, iSrcOctetOffset ,
00679                                ABP_UINT32_SIZEOF );
00680          ABCC_PORT_CopyOctets( &lDest, 0, pxDest, iDestOctetOffset, bCopySize );
00681 
00682          /*
00683          ** Bit data types crossing octet boundaries are always little endian.
00684          */
00685          lSrc = lLeTOl( lSrc );
00686          lDest = lLeTOl( lDest );
00687 
00688          /*
00689          ** Calculate bit mask and align it with destination bit offset.
00690          */
00691          lBitMask = ( (UINT32)1 << iSetBitSize ) - 1;
00692          lBitMask <<= iDestBitOffset;
00693 
00694          /*
00695          ** Align source bits with destination bits
00696          */
00697          if( iSrcBitOffset <  iDestBitOffset )
00698          {
00699             lSrc <<= iDestBitOffset - iSrcBitOffset;
00700          }
00701          else
00702          {
00703             lSrc >>= iSrcBitOffset - iDestBitOffset;
00704          }
00705 
00706          /*
00707          ** Clear destinations bits and mask source bits an insert source bits
00708          ** into destination bit position.
00709          */
00710          lDest &=  ~lBitMask;
00711          lSrc &=  lBitMask;
00712          lDest |= lSrc;
00713 
00714          /*
00715          ** Restore endian.
00716          */
00717          lDest = lTOlLe( lDest );
00718 
00719          /*
00720          ** Copy local updated data into final destination.
00721          */
00722          ABCC_PORT_CopyOctets( pxDest, iDestOctetOffset, &lDest, 0, bCopySize );
00723 
00724          /*
00725          ** Update bit offsets to next bit field.
00726          */
00727          iSrcBitOffset += iSetBitSize;
00728          AddBitsToOctetSize( iSrcOctetOffset, iSrcBitOffset );
00729          iDestBitOffset += iSetBitSize;
00730          AddBitsToOctetSize( iDestOctetOffset, iDestBitOffset );
00731       }
00732       iSetBitSize *= iNumElem;
00733    }
00734    return( iSetBitSize );
00735 }
00736 
00737 /*------------------------------------------------------------------------------
00738 **  Copy value (single element or parts of an array) of a specific type
00739 **  from a specified source to a destination. If the host platform endian
00740 **  differs from network endian a swap will be done.
00741 **  NOTE!! For all non-bit data types the source and destination must be octet
00742 **  aligned.
00743 **------------------------------------------------------------------------------
00744 ** Arguments:
00745 **    pxDst             - Destination base pointer.
00746 **    iDestBitOffset    - Bit offset relative destination pointer.
00747 **    pxSrc             - Source base pointer.
00748 **    iSrcBitOffset     - Bit offset relative source pointer.
00749 **    bDataType         - Data type according to ABP_<X> types in abp.h
00750 **    iNumElem          - Number of elements to copy.
00751 **
00752 ** Returns:
00753 **    Size of copied data in bits.
00754 **------------------------------------------------------------------------------
00755 */
00756 static UINT16 CopyValue( void* pxDst,
00757                          UINT16 iDestBitOffset,
00758                          void* pxSrc ,
00759                          UINT16 iSrcBitOffset,
00760                          UINT8 bDataType,
00761                          UINT16 iNumElem )
00762 {
00763    UINT8 bDataTypeSizeInOctets;
00764    UINT16 iBitSetSize;
00765 
00766    if( Is_BITx_Or_PADx( bDataType ) )
00767    {
00768       iBitSetSize = CopyBitData( pxDst,
00769                                  iDestBitOffset,
00770                                  pxSrc,
00771                                  iSrcBitOffset,
00772                                  bDataType,
00773                                  iNumElem );
00774    }
00775    else
00776    {
00777       bDataTypeSizeInOctets = ABCC_GetDataTypeSize( bDataType );
00778 
00779       if( ad_fDoNetworkEndianSwap )
00780       {
00781          switch( bDataTypeSizeInOctets )
00782          {
00783          case 1:
00784             ABCC_PORT_CopyOctets( pxDst, BitToOctetOffset( iDestBitOffset ),
00785                                   pxSrc, BitToOctetOffset( iSrcBitOffset ),
00786                                   iNumElem );
00787             break;
00788 
00789          case 2:
00790             Copy16WithEndianSwap( pxDst, BitToOctetOffset( iDestBitOffset ),
00791                                   pxSrc, BitToOctetOffset( iSrcBitOffset ),
00792                                   iNumElem );
00793             break;
00794 
00795          case 4:
00796             Copy32WithEndianSwap( pxDst, BitToOctetOffset( iDestBitOffset ),
00797                                   pxSrc, BitToOctetOffset( iSrcBitOffset ),
00798                                   iNumElem );
00799             break;
00800 
00801    #if( ABCC_CFG_64BIT_ADI_SUPPORT )
00802          case 8:
00803             Copy64WithEndianSwapImpl( pxDst, BitToOctetOffset( iDestBitOffset ),
00804                                       pxSrc, BitToOctetOffset( iSrcBitOffset ),
00805                                       iNumElem );
00806             break;
00807    #endif
00808          default:
00809             break;
00810          }
00811       }
00812       else
00813       {
00814          ABCC_PORT_CopyOctets( pxDst, BitToOctetOffset( iDestBitOffset ),
00815                                pxSrc, BitToOctetOffset( iSrcBitOffset ),
00816                                bDataTypeSizeInOctets * iNumElem );
00817       }
00818 
00819       iBitSetSize = ( iNumElem * bDataTypeSizeInOctets ) << 3;
00820    }
00821 
00822    return( iBitSetSize );
00823 }
00824 
00825 
00826 
00827 /*------------------------------------------------------------------------------
00828 **  Get min, max or default value(s) for an ADI. If the ADI is a structured ADI
00829 **  all default values will have the same format as the structure describes.
00830 **  The result is in network endian format.
00831 **------------------------------------------------------------------------------
00832 ** Arguments:
00833 **    psAdiEntry        - Pointer to ADI entry
00834 **    pxDest            - Destination pointer
00835 **    eMinMaxDefault    - Get min, max or default value described by
00836 **                        AD_MinMaxDefaultIndexType
00837 **    piOctetSize       - Size in octets of the written default values
00838 **
00839 ** Returns:
00840 **    ABP error code.
00841 **------------------------------------------------------------------------------
00842 */
00843 #if( AD_IA_MIN_MAX_DEFAULT_ENABLE )
00844 static UINT8 GetMinMaxDefault( const AD_AdiEntryType* psAdiEntry,
00845                                void* pxDest,
00846                                AD_MinMaxDefaultIndexType eMinMaxDefault,
00847                                UINT16* piBitSize)
00848 {
00849    UINT16 iSrcBitOffset;
00850 
00851    *piBitSize = 0;
00852 
00853 #if( ABCC_CFG_STRUCT_DATA_TYPE )
00854    if( psAdiEntry->psStruct != NULL )
00855    {
00856       UINT16 i;
00857 
00858       for(i = 0; i < psAdiEntry->bNumOfElements; i++ )
00859       {
00860          if( psAdiEntry->psStruct[ i ].uData.sVOID.pxValueProps != NULL )
00861          {
00862             iSrcBitOffset = CalcStartindexBitOffset( psAdiEntry->psStruct[ i ].bDataType, (UINT16)eMinMaxDefault );
00863 
00864             *piBitSize += CopyValue( pxDest,
00865                                      *piBitSize,
00866                                      psAdiEntry->psStruct[ i ].uData.sVOID.pxValueProps,
00867                                      iSrcBitOffset,
00868                                      psAdiEntry->psStruct[ i ].bDataType,
00869                                      1 );
00870          }
00871          else
00872          {
00873             *piBitSize = 0;
00874             return( ABP_ERR_INV_CMD_EXT_0 );
00875          }
00876       }
00877    }
00878    else
00879 #endif
00880    {
00881       if( psAdiEntry->uData.sVOID.pxValueProps != NULL )
00882       {
00883          iSrcBitOffset = CalcStartindexBitOffset( psAdiEntry->bDataType,
00884                                                   (UINT16)eMinMaxDefault );
00885 
00886          *piBitSize += CopyValue( pxDest,
00887                                   *piBitSize,
00888                                   psAdiEntry->uData.sVOID.pxValueProps,
00889                                   iSrcBitOffset,
00890                                   psAdiEntry->bDataType,
00891                                   1 );
00892       }
00893       else
00894       {
00895          *piBitSize = 0;
00896          return( ABP_ERR_INV_CMD_EXT_0 );
00897       }
00898    }
00899    return( ABP_ERR_NO_ERROR );
00900 }
00901 #endif
00902 
00903 /*------------------------------------------------------------------------------
00904 **  Get ADI of any data type. The read ADI will have network endian format.
00905 **------------------------------------------------------------------------------
00906 ** Arguments:
00907 **    psAdiEntry        - Pointer to ADI entry
00908 **    pxDest            - Destination base pointer.
00909 **    bNumElements      - Number of elements to read.
00910 **    bStartIndex       - Index to first element to read.
00911 **    piDestBitOffset   - Pointer to destination bit offset.
00912 **                        This offset will be incremented according to the size
00913 **                        of the read.
00914 ** Returns:
00915 **    None
00916 **------------------------------------------------------------------------------
00917 */
00918 static void GetAdiValue( const AD_AdiEntryType* psAdiEntry,
00919                          void* pxDest,
00920                          UINT8 bNumElements,
00921                          UINT8 bStartIndex,
00922                          UINT16* piDestBitOffset )
00923 {
00924    UINT16 iSrcBitOffset;
00925 
00926 #if( ABCC_CFG_ADI_GET_SET_CALLBACK )
00927    /*
00928    ** If a get callback is registered the user is notified that the ADI shall be
00929    ** updated.
00930    */
00931    if( psAdiEntry->pnGetAdiValue != NULL )
00932    {
00933       psAdiEntry->pnGetAdiValue( psAdiEntry,
00934                                  bNumElements,
00935                                  bStartIndex );
00936    }
00937 #endif
00938 
00939 #if( ABCC_CFG_STRUCT_DATA_TYPE )
00940    if( psAdiEntry->psStruct != NULL )
00941    {
00942       UINT16 i;
00943 
00944       i = 0;
00945 
00946       /*
00947       ** For structures each element is handled separately.
00948       */
00949       for( i = bStartIndex; i < bNumElements + bStartIndex; i++ )
00950       {
00951          iSrcBitOffset = psAdiEntry->psStruct[ i ].bBitOffset;
00952 
00953          *piDestBitOffset += CopyValue( pxDest,
00954                                         *piDestBitOffset,
00955                                         psAdiEntry->psStruct[ i ].uData.sVOID.pxValuePtr,
00956                                         iSrcBitOffset,
00957                                         psAdiEntry->psStruct[ i ].bDataType,
00958                                         psAdiEntry->psStruct[ i ].iNumSubElem );
00959       }
00960    }
00961    else
00962 #endif
00963    {
00964       iSrcBitOffset = CalcStartindexBitOffset( psAdiEntry->bDataType, bStartIndex );
00965       *piDestBitOffset += CopyValue( pxDest,
00966                                      *piDestBitOffset,
00967                                      psAdiEntry->uData.sVOID.pxValuePtr,
00968                                      iSrcBitOffset,
00969                                      psAdiEntry->bDataType,
00970                                      bNumElements );
00971    }
00972 }
00973 
00974 /*------------------------------------------------------------------------------
00975 **  Set ADI of any data type. The provided data must have network endian format.
00976 **------------------------------------------------------------------------------
00977 ** Arguments:
00978 **    psAdiEntry        - Pointer to ADI entry.
00979 **    pxData            - Source base pointer.
00980 **    bNumElements      - Number of elements to write.
00981 **    bStartIndex       - Index to first element to write.
00982 **    piSrcBitOffset    - Pointer to source bit offset.
00983 **                        This offset will be incremented according to the size
00984 **                        written.
00985 ** Returns:
00986 **    None
00987 **------------------------------------------------------------------------------
00988 */
00989 static void SetAdiValue( const AD_AdiEntryType* psAdiEntry,
00990                          void* pxData,
00991                          UINT8 bNumElements,
00992                          UINT8 bStartIndex,
00993                          UINT16* piSrcBitOffset )
00994 {
00995    UINT16 iDestBitOffset;
00996 
00997 #if( ABCC_CFG_STRUCT_DATA_TYPE )
00998    if( psAdiEntry->psStruct != NULL )
00999    {
01000       UINT16 i;
01001 
01002       /*
01003       ** For structures each element is handled separately.
01004       */
01005       for( i = bStartIndex; i < bNumElements + bStartIndex; i++ )
01006       {
01007          iDestBitOffset = psAdiEntry->psStruct[ i ].bBitOffset;
01008          *piSrcBitOffset += CopyValue( psAdiEntry->psStruct[ i ].uData.sVOID.pxValuePtr,
01009                                        iDestBitOffset,
01010                                        pxData,
01011                                        *piSrcBitOffset,
01012                                        psAdiEntry->psStruct[ i ].bDataType,
01013                                        psAdiEntry->psStruct[ i ].iNumSubElem );
01014       }
01015    }
01016    else
01017 #endif
01018    {
01019       iDestBitOffset = CalcStartindexBitOffset( psAdiEntry->bDataType, bStartIndex );
01020       *piSrcBitOffset += CopyValue( psAdiEntry->uData.sVOID.pxValuePtr,
01021                                     iDestBitOffset,
01022                                     pxData,
01023                                     *piSrcBitOffset,
01024                                     psAdiEntry->bDataType,
01025                                     bNumElements );
01026    }
01027 #if( ABCC_CFG_ADI_GET_SET_CALLBACK )
01028    if( psAdiEntry->pnSetAdiValue != NULL )
01029    {
01030       /*
01031       ** If a set callback is registered the user is notified that the ADI is
01032       ** updated.
01033       */
01034       psAdiEntry->pnSetAdiValue( psAdiEntry,
01035                                  bNumElements,
01036                                  bStartIndex );
01037    }
01038 #endif
01039 }
01040 
01041 /*******************************************************************************
01042 ** Public Services
01043 ********************************************************************************
01044 */
01045 EXTFUNC AD_ErrType AD_Init( const AD_AdiEntryType* psAdiEntry,
01046                             UINT16 iNumAdi,
01047                             const AD_DefaultMapType* psDefaultMap )
01048 {
01049    UINT16 iMapIndex = 0;
01050    UINT16 iAdiIndex = 0;
01051    UINT8 bNumElem;
01052    UINT8 bElemStartIndex;
01053    /*
01054    ** In this context we should initialize the AD object to be prepared for
01055    ** startup.
01056    */
01057    ad_asADIEntryList = psAdiEntry;
01058    ad_asDefaultMap = psDefaultMap;
01059 
01060    ad_iNumOfADIs =  iNumAdi;
01061    ad_iHighestInstanceNumber = 0;
01062 
01063    ad_ReadMapInfo.paiMappedAdiList = ad_PdReadMapping;
01064    ad_ReadMapInfo.iPdSize = 0;
01065    ad_ReadMapInfo.iNumMappedAdi = 0;
01066    ad_ReadMapInfo.iMaxNumMappedAdi = AD_MAX_NUM_READ_ADI_TO_MAP;
01067 
01068    ad_WriteMapInfo.paiMappedAdiList = ad_PdWriteMapping;
01069    ad_WriteMapInfo.iPdSize = 0;
01070    ad_WriteMapInfo.iNumMappedAdi = 0;
01071    ad_WriteMapInfo.iMaxNumMappedAdi = AD_MAX_NUM_WRITE_ADI_TO_MAP;
01072 
01073    if( ad_asDefaultMap != NULL )
01074    {
01075       while( ad_asDefaultMap[ iMapIndex ].eDir != PD_END_MAP )
01076       {
01077          iAdiIndex = GetAdiIndex( ad_asDefaultMap[ iMapIndex ].iInstance );
01078 
01079          if( iAdiIndex == AD_INVALID_ADI_INDEX )
01080          {
01081             return AD_UNKNOWN_ADI;
01082          }
01083 
01084          bNumElem = ad_asDefaultMap[ iMapIndex ].bNumElem;
01085          bElemStartIndex = ad_asDefaultMap[ iMapIndex ].bElemStartIndex;
01086 
01087          if( iAdiIndex != AD_MAP_PAD_INDEX )
01088          {
01089             if( ad_asDefaultMap[ iMapIndex ].bNumElem == AD_DEFAULT_MAP_ALL_ELEM )
01090             {
01091                bNumElem = ad_asADIEntryList[ iAdiIndex ].bNumOfElements;
01092                bElemStartIndex = 0;
01093             }
01094          }
01095 
01096          if( ad_asDefaultMap[ iMapIndex ].eDir == PD_READ )
01097          {
01098             if( ad_ReadMapInfo.iNumMappedAdi >= ad_ReadMapInfo.iMaxNumMappedAdi )
01099             {
01100                return AD_TOO_MANY_READ_MAPPINGS;
01101             }
01102 
01103             ad_ReadMapInfo.paiMappedAdiList[ ad_ReadMapInfo.iNumMappedAdi ].bNumElements = bNumElem;
01104             ad_ReadMapInfo.paiMappedAdiList[ ad_ReadMapInfo.iNumMappedAdi ].bStartIndex = bElemStartIndex;
01105             ad_ReadMapInfo.paiMappedAdiList[ ad_ReadMapInfo.iNumMappedAdi ].iAdiIndex = iAdiIndex;
01106             ad_ReadMapInfo.iNumMappedAdi++;
01107          }
01108          else
01109          {
01110             if( ad_WriteMapInfo.iNumMappedAdi >= ad_WriteMapInfo.iMaxNumMappedAdi )
01111             {
01112                return AD_TOO_MANY_WRITE_MAPPINGS;
01113             }
01114 
01115             ad_WriteMapInfo.paiMappedAdiList[ ad_WriteMapInfo.iNumMappedAdi ].bNumElements = bNumElem;
01116             ad_WriteMapInfo.paiMappedAdiList[ ad_WriteMapInfo.iNumMappedAdi ].bStartIndex = bElemStartIndex;
01117             ad_WriteMapInfo.paiMappedAdiList[ ad_WriteMapInfo.iNumMappedAdi ].iAdiIndex = iAdiIndex;
01118             ad_WriteMapInfo.iNumMappedAdi++;
01119          }
01120          iMapIndex++;
01121       }
01122    }
01123 
01124    UpdateMapSize( &ad_WriteMapInfo );
01125    UpdateMapSize( &ad_ReadMapInfo );
01126 
01127    if( ad_ReadMapInfo.iPdSize > ABCC_CFG_MAX_PROCESS_DATA_SIZE )
01128    {
01129       return AD_PD_READ_SIZE_ERR;
01130    }
01131 
01132    if( ad_WriteMapInfo.iPdSize > ABCC_CFG_MAX_PROCESS_DATA_SIZE )
01133    {
01134       return AD_PD_WRITE_SIZE_ERR;
01135    }
01136 
01137    for( iAdiIndex = 0; iAdiIndex < ad_iNumOfADIs; iAdiIndex++ )
01138    {
01139       if( ad_asADIEntryList[ iAdiIndex ].iInstance > ad_iHighestInstanceNumber )
01140       {
01141          ad_iHighestInstanceNumber = ad_asADIEntryList[ iAdiIndex ].iInstance;
01142       }
01143    }
01144 
01145    return AD_NO_ERROR;
01146 }
01147 
01148 const AD_AdiEntryType* AD_GetAdiInstEntry( UINT16 iInstance )
01149 {
01150    UINT16 i;
01151    const AD_AdiEntryType* psEntry = NULL;
01152 
01153    i = GetAdiIndex( iInstance );
01154    if( i != 0xffff )
01155    {
01156       psEntry = &ad_asADIEntryList[ i ];
01157    }
01158    return( psEntry );
01159 }
01160 
01161 void AD_ProcObjectRequest( ABP_MsgType* psMsgBuffer )
01162 {
01163    const AD_AdiEntryType* psAdiEntry;
01164    UINT16 iMsgBitOffset;
01165    UINT16 iItemSize;
01166    UINT16 iTemp;
01167    UINT16 iDataSize;
01168    UINT8  bErrCode;
01169 
01170    iMsgBitOffset = 0;
01171    iDataSize = 0;
01172    bErrCode = ABP_ERR_NO_ERROR;
01173 
01174    if( iLeTOi( psMsgBuffer->sHeader.iInstance ) == ABP_INST_OBJ )
01175    {
01176       /*
01177       ** A request to the object instance.
01178       */
01179       switch( ABCC_GetMsgCmdBits( psMsgBuffer ) )
01180       {
01181       case ABP_CMD_GET_ATTR:
01182          switch( ABCC_GetMsgCmdExt0( psMsgBuffer ) )
01183          {
01184          case ABP_OA_NAME:
01185             ABCC_SetMsgString( psMsgBuffer, "Application data",16 ,0 );
01186             iDataSize = 16;
01187             break;
01188 
01189          case ABP_OA_REV:
01190             ABCC_SetMsgData8( psMsgBuffer, 1, 0 );
01191             iDataSize = ABP_OA_REV_DS;
01192             break;
01193 
01194          case ABP_OA_NUM_INST:
01195             ABCC_SetMsgData16( psMsgBuffer, ad_iNumOfADIs, 0 );
01196             iDataSize = ABP_OA_NUM_INST_DS;
01197             break;
01198 
01199          case ABP_OA_HIGHEST_INST:
01200             ABCC_SetMsgData16( psMsgBuffer, ad_iHighestInstanceNumber, 0 );
01201             iDataSize = ABP_OA_HIGHEST_INST_DS;
01202             break;
01203 
01204          case ABP_APPD_OA_NR_READ_PD_MAPPABLE_INSTANCES:
01205             {
01206                UINT16 iIndex;
01207                UINT16 iCnt = 0;
01208 
01209                for( iIndex=0; iIndex < ad_iNumOfADIs; iIndex++ )
01210                {
01211                   if( ad_asADIEntryList[iIndex ].bDesc & ABP_APPD_DESCR_MAPPABLE_READ_PD )
01212                   {
01213                      iCnt++;
01214                   }
01215                }
01216                ABCC_SetMsgData16( psMsgBuffer, iCnt, 0 );
01217                iDataSize = ABP_UINT16_SIZEOF;
01218             }
01219             break;
01220 
01221          case ABP_APPD_OA_NR_WRITE_PD_MAPPABLE_INSTANCES:
01222             {
01223                UINT16 iIndex;
01224                UINT16 iCnt = 0;
01225 
01226                for( iIndex=0; iIndex < ad_iNumOfADIs; iIndex++ )
01227                {
01228                   if( ad_asADIEntryList[ iIndex ].bDesc & ABP_APPD_DESCR_MAPPABLE_WRITE_PD )
01229                   {
01230                      iCnt++;
01231                   }
01232                }
01233                ABCC_SetMsgData16( psMsgBuffer, iCnt, 0 );
01234                iDataSize = ABP_UINT16_SIZEOF;
01235             }
01236             break;
01237 
01238          default:
01239             /*
01240             ** Unsupported attribute.
01241             */
01242             bErrCode = ABP_ERR_INV_CMD_EXT_0;
01243             break;
01244          }
01245          break;
01246 
01247       case ABP_APPD_CMD_GET_INST_BY_ORDER:
01248          iTemp = ABCC_GetMsgCmdExt( psMsgBuffer );
01249 
01250          if( ( iTemp == 0 ) ||
01251              ( iTemp > ad_iNumOfADIs ) )
01252          {
01253             /*
01254             ** Requested order number does not exist.
01255             */
01256             bErrCode = ABP_ERR_INV_CMD_EXT_0;
01257          }
01258          else
01259          {
01260             ABCC_SetMsgData16( psMsgBuffer,
01261                                ad_asADIEntryList[ iTemp - 1 ].iInstance,
01262                                0 );
01263             iDataSize = ABP_UINT16_SIZEOF;
01264          }
01265          break;
01266 
01267 #if( ABCC_CFG_REMAP_SUPPORT_ENABLED )
01268       case ABP_APPD_REMAP_ADI_WRITE_AREA:
01269          RemapProcessDataCommand( psMsgBuffer, &ad_WriteMapInfo );
01270          psMsgBuffer = NULL;
01271          break;
01272 
01273       case ABP_APPD_REMAP_ADI_READ_AREA:
01274          RemapProcessDataCommand( psMsgBuffer, &ad_ReadMapInfo );
01275          psMsgBuffer = NULL;
01276          break;
01277 #endif
01278       case ABP_APPD_GET_INSTANCE_NUMBERS:
01279 
01280          if( ABCC_GetMsgCmdExt0( psMsgBuffer ) != 0 )
01281          {
01282             bErrCode = ABP_ERR_INV_CMD_EXT_0;
01283          }
01284          else
01285          {
01286             UINT16 iStartingOrder;
01287             UINT16 iReqInstances;
01288             UINT16 i;
01289             UINT16 ii;
01290 
01291             ABCC_GetMsgData16( psMsgBuffer, &iStartingOrder, 0 );
01292             ABCC_GetMsgData16( psMsgBuffer, &iReqInstances, 2 );
01293 
01294             switch( ABCC_GetMsgCmdExt1( psMsgBuffer ) )
01295             {
01296             case ABP_APPD_LIST_TYPE_ALL:
01297                iDataSize = 0;
01298                for ( i = 0; ( i < iReqInstances ) && ( iStartingOrder + i <= ad_iNumOfADIs ); i++ )
01299                {
01300                   ABCC_SetMsgData16( psMsgBuffer,
01301                                      ad_asADIEntryList[ iStartingOrder + i - 1 ].iInstance,
01302                                      iDataSize );
01303                   iDataSize += ABP_UINT16_SIZEOF;
01304                }
01305                break;
01306 
01307             case ABP_APPD_LIST_TYPE_RD_PD_MAPPABLE:
01308                iDataSize = 0;
01309                for ( i = 0, ii = 1; ( ii < ( iStartingOrder + iReqInstances ) ) && ( i < ad_iNumOfADIs ); i++ )
01310                {
01311                   if( ad_asADIEntryList[ i ].bDesc & ABP_APPD_DESCR_MAPPABLE_READ_PD )
01312                   {
01313                      if( ii >= iStartingOrder )
01314                      {
01315                         ABCC_SetMsgData16( psMsgBuffer,
01316                                            ad_asADIEntryList[ i ].iInstance,
01317                                            iDataSize );
01318                         iDataSize += ABP_UINT16_SIZEOF;
01319                      }
01320                      ii++;
01321                   }
01322                }
01323                break;
01324 
01325             case ABP_APPD_LIST_TYPE_WR_PD_MAPPABLE:
01326                iDataSize = 0;
01327                for ( i = 0, ii = 1; ( ii < ( iStartingOrder + iReqInstances ) ) && ( i < ad_iNumOfADIs ); i++ )
01328                {
01329                   if( ad_asADIEntryList[ i ].bDesc & ABP_APPD_DESCR_MAPPABLE_WRITE_PD )
01330                   {
01331                      if( ii >= iStartingOrder )
01332                      {
01333                         ABCC_SetMsgData16( psMsgBuffer, ad_asADIEntryList[ i ].iInstance, iDataSize );
01334                         iDataSize += ABP_UINT16_SIZEOF;
01335                      }
01336                      ii++;
01337                   }
01338                }
01339                break;
01340 
01341             default:
01342                bErrCode = ABP_ERR_INV_CMD_EXT_1;
01343                break;
01344             }
01345          }
01346          break;
01347 
01348       default:
01349          bErrCode = ABP_ERR_UNSUP_CMD;
01350          break;
01351       }
01352    }
01353    else if( ( psAdiEntry = AD_GetAdiInstEntry( ABCC_GetMsgInstance( psMsgBuffer ) ) ) != NULL )
01354    {
01355       /*
01356       ** The ADI instance was found. Now switch on command.
01357       */
01358       switch( ABCC_GetMsgCmdBits( psMsgBuffer ) )
01359       {
01360       case ABP_CMD_GET_ATTR:
01361          /*
01362          ** Switch on attribute.
01363          */
01364          switch( ABCC_GetMsgCmdExt0( psMsgBuffer ) )
01365          {
01366          case ABP_APPD_IA_NAME:
01367             if( psAdiEntry->pacName )
01368             {
01369                iDataSize = (UINT16)strlen( psAdiEntry->pacName );
01370                ABCC_SetMsgString( psMsgBuffer,
01371                                   psAdiEntry->pacName, iDataSize, 0 );
01372             }
01373             else
01374             {
01375                iDataSize = 0;
01376             }
01377             break;
01378 
01379          case ABP_APPD_IA_DATA_TYPE:
01380 #if( ABCC_CFG_STRUCT_DATA_TYPE )
01381             if( psAdiEntry->psStruct != NULL )
01382             {
01383                UINT16 i;
01384 
01385                iDataSize = ABP_APPD_IA_DATA_TYPE_DS*psAdiEntry->bNumOfElements;
01386                for ( i = 0; i < psAdiEntry->bNumOfElements; i++ )
01387                {
01388                   ABCC_SetMsgData8( psMsgBuffer,
01389                                     psAdiEntry->psStruct[i].bDataType, i );
01390                }
01391             }
01392             else
01393 #endif
01394             {
01395                ABCC_SetMsgData8( psMsgBuffer, psAdiEntry->bDataType, 0 );
01396                iDataSize = ABP_APPD_IA_DATA_TYPE_DS;
01397             }
01398             break;
01399 
01400          case ABP_APPD_IA_NUM_ELEM:
01401             ABCC_SetMsgData8( psMsgBuffer, psAdiEntry->bNumOfElements, 0 );
01402             iDataSize = ABP_APPD_IA_NUM_ELEM_DS;
01403             break;
01404 
01405          case ABP_APPD_IA_DESCRIPTOR:
01406 #if( ABCC_CFG_STRUCT_DATA_TYPE )
01407             if( psAdiEntry->psStruct != NULL )
01408             {
01409                UINT16 i;
01410 
01411                iDataSize = ABP_APPD_IA_DESCRIPTOR_DS * psAdiEntry->bNumOfElements;
01412                for ( i = 0; i < psAdiEntry->bNumOfElements; i++ )
01413                {
01414                   ABCC_SetMsgData8( psMsgBuffer,
01415                                     psAdiEntry->psStruct[i].bDesc, i );
01416                }
01417             }
01418             else
01419 #endif
01420             {
01421                ABCC_SetMsgData8( psMsgBuffer, psAdiEntry->bDesc, 0 );
01422                iDataSize = ABP_APPD_IA_DESCRIPTOR_DS;
01423             }
01424             break;
01425 
01426          case ABP_APPD_IA_VALUE: /* Value. */
01427             if( !( psAdiEntry->bDesc & ABP_APPD_DESCR_GET_ACCESS ) )
01428             {
01429                bErrCode = ABP_ERR_ATTR_NOT_GETABLE;
01430                break;
01431             }
01432             ABCC_GetMsgDataPtr( psMsgBuffer )[ 0 ] = 0;
01433 
01434             GetAdiValue( psAdiEntry, ABCC_GetMsgDataPtr( psMsgBuffer ),
01435                             psAdiEntry->bNumOfElements, 0,
01436                             &iMsgBitOffset);
01437             iDataSize = SizeInOctets( 0, iMsgBitOffset );
01438             break;
01439 #if( AD_IA_MIN_MAX_DEFAULT_ENABLE )
01440          case ABP_APPD_IA_MAX_VALUE:
01441             bErrCode = GetMinMaxDefault( psAdiEntry,
01442                                          ABCC_GetMsgDataPtr( psMsgBuffer ),
01443                                          AD_MAX_VALUE_INDEX,
01444                                          &iDataSize );
01445             iDataSize = SizeInOctets( 0, iDataSize );
01446             break;
01447          case ABP_APPD_IA_MIN_VALUE:
01448             bErrCode = GetMinMaxDefault( psAdiEntry,
01449                                          ABCC_GetMsgDataPtr( psMsgBuffer ),
01450                                          AD_MIN_VALUE_INDEX,
01451                                          &iDataSize );
01452             iDataSize = SizeInOctets( 0, iDataSize );
01453             break;
01454          case ABP_APPD_IA_DFLT_VALUE:
01455             bErrCode = GetMinMaxDefault( psAdiEntry,
01456                                          ABCC_GetMsgDataPtr( psMsgBuffer ),
01457                                          AD_DEFAULT_VALUE_INDEX,
01458                                          &iDataSize );
01459             iDataSize = SizeInOctets( 0, iDataSize );
01460             break;
01461 #endif
01462          case ABP_APPD_IA_NUM_SUB_ELEM:
01463 #if( ABCC_CFG_STRUCT_DATA_TYPE )
01464             if( psAdiEntry->psStruct != NULL )
01465             {
01466                UINT16 i;
01467 
01468                iDataSize = ABP_APPD_IA_NUM_SUB_ELEM_DS * psAdiEntry->bNumOfElements;
01469                for ( i = 0; i < psAdiEntry->bNumOfElements; i++ )
01470                {
01471                   ABCC_SetMsgData16( psMsgBuffer,
01472                                      psAdiEntry->psStruct[i].iNumSubElem,
01473                                      ( i * ABP_APPD_IA_NUM_SUB_ELEM_DS ) );
01474                }
01475             }
01476             else
01477 #endif
01478             {
01479                ABCC_SetMsgData16( psMsgBuffer, AD_DEFAULT_NUM_SUB_ELEMS, 0 );
01480                iDataSize = ABP_APPD_IA_NUM_SUB_ELEM_DS;
01481             }
01482             break;
01483          default:
01484             /*
01485             ** Unsupported attribute.
01486             */
01487             bErrCode = ABP_ERR_INV_CMD_EXT_0;
01488             break;
01489          }
01490          break;
01491       case ABP_CMD_SET_ATTR:
01492          switch( ABCC_GetMsgCmdExt0( psMsgBuffer ) )
01493          {
01494          case ABP_APPD_IA_NAME:
01495          case ABP_APPD_IA_DATA_TYPE:
01496          case ABP_APPD_IA_NUM_ELEM:
01497          case ABP_APPD_IA_DESCRIPTOR:
01498             /*
01499             ** Attributes are not settable.
01500             */
01501             bErrCode = ABP_ERR_ATTR_NOT_SETABLE;
01502             break;
01503 
01504          case ABP_APPD_IA_VALUE:
01505             if( !( psAdiEntry->bDesc & ABP_APPD_DESCR_SET_ACCESS ) )
01506             {
01507                bErrCode = ABP_ERR_ATTR_NOT_SETABLE;
01508                break;
01509             }
01510 
01511             /*
01512             ** Check the length of each array.
01513             */
01514             iItemSize = GetAdiSizeInOctets( psAdiEntry );
01515             if( iLeTOi( psMsgBuffer->sHeader.iDataSize ) > iItemSize )
01516             {
01517                bErrCode = ABP_ERR_TOO_MUCH_DATA;
01518                break;
01519             }
01520             else if( iLeTOi( psMsgBuffer->sHeader.iDataSize ) < iItemSize )
01521             {
01522                bErrCode = ABP_ERR_NOT_ENOUGH_DATA;
01523                break;
01524             }
01525             /*
01526             ** TODO Range check
01527             */
01528             if(  FALSE )
01529             {
01530                bErrCode = ABP_ERR_OUT_OF_RANGE;
01531             }
01532             else
01533             {
01534                SetAdiValue( psAdiEntry, ABCC_GetMsgDataPtr( psMsgBuffer ),
01535                             psAdiEntry->bNumOfElements, 0,
01536                             &iMsgBitOffset);
01537                /*
01538                ** Success.
01539                */
01540                iDataSize = 0;
01541             }
01542             break;
01543 
01544          default:
01545             /*
01546             ** Unsupported attribute.
01547             */
01548             bErrCode = ABP_ERR_INV_CMD_EXT_0;
01549             break;
01550          }
01551          break;
01552 
01553       case ABP_CMD_GET_ENUM_STR:
01554          switch( ABCC_GetMsgCmdExt0( psMsgBuffer ) )
01555          {
01556          case ABP_APPD_IA_VALUE:
01557             if( psAdiEntry->bDataType == ABP_ENUM )
01558             {
01559                if( ( psAdiEntry->uData.sENUM.psValueProps == NULL ) ||
01560                    ( psAdiEntry->uData.sENUM.psValueProps->pasEnumStrings == NULL ) )
01561                {
01562                   bErrCode = ABP_ERR_UNSUP_CMD;
01563                }
01564                else
01565                {
01566                   UINT8 b = 0;
01567 
01568                   for( b = 0; b < psAdiEntry->uData.sENUM.psValueProps->bNumOfEnumStrings; b++ )
01569                   {
01570                      if( psAdiEntry->uData.sENUM.psValueProps->pasEnumStrings[ b ].eValue ==
01571                          ABCC_GetMsgCmdExt1( psMsgBuffer ) )
01572                      {
01573                         break;
01574                      }
01575                   }
01576 
01577                   if( b < psAdiEntry->uData.sENUM.psValueProps->bNumOfEnumStrings )
01578                   {
01579                      iDataSize = (UINT16)strlen( psAdiEntry->uData.sENUM.psValueProps->pasEnumStrings[ b ].acEnumStr );
01580                      ABCC_SetMsgString( psMsgBuffer,
01581                                         psAdiEntry->uData.sENUM.psValueProps->pasEnumStrings[ b ].acEnumStr,
01582                                         iDataSize, 0 );
01583                   }
01584                   else
01585                   {
01586                      /*
01587                      ** The enum value was not found in the string lookup.
01588                      */
01589                      bErrCode = ABP_ERR_OUT_OF_RANGE;
01590                   }
01591                }
01592             }
01593             else
01594             {
01595                bErrCode = ABP_ERR_UNSUP_CMD;
01596             }
01597             break;
01598 
01599          default:
01600             bErrCode = ABP_ERR_UNSUP_CMD;
01601             break;
01602          }
01603          break;
01604       case ABP_CMD_GET_INDEXED_ATTR:
01605          switch( ABCC_GetMsgCmdExt0( psMsgBuffer ) )
01606          {
01607             case ABP_APPD_IA_VALUE:
01608                if( !( psAdiEntry->bDesc & ABP_APPD_DESCR_GET_ACCESS ) )
01609                {
01610                   bErrCode = ABP_ERR_ATTR_NOT_GETABLE;
01611                   break;
01612                }
01613                else
01614                {
01615                   GetAdiValue( psAdiEntry, ABCC_GetMsgDataPtr( psMsgBuffer ),
01616                                   1, ABCC_GetMsgCmdExt1( psMsgBuffer ),
01617                                   &iMsgBitOffset );
01618 
01619                   iDataSize = SizeInOctets( 0, iMsgBitOffset );
01620 
01621                   if( iDataSize == 0 )
01622                   {
01623                      bErrCode = ABP_ERR_OUT_OF_RANGE;
01624                   }
01625                }
01626             break;
01627 
01628          default:
01629             bErrCode = ABP_ERR_UNSUP_CMD;
01630             break;
01631          }
01632          break;
01633       case ABP_CMD_SET_INDEXED_ATTR:
01634          switch( ABCC_GetMsgCmdExt0( psMsgBuffer ) )
01635          {
01636             case ABP_APPD_IA_VALUE:
01637                if( !( psAdiEntry->bDesc & ABP_APPD_DESCR_SET_ACCESS ) )
01638                {
01639                   bErrCode = ABP_ERR_ATTR_NOT_SETABLE;
01640                   break;
01641                }
01642                else
01643                {
01644                   if( FALSE )
01645                   {
01646                      bErrCode = ABP_ERR_OUT_OF_RANGE;
01647                   }
01648                   else
01649                   {
01650                      SetAdiValue( psAdiEntry,
01651                                   ABCC_GetMsgDataPtr( psMsgBuffer ),
01652                                   1, ABCC_GetMsgCmdExt1( psMsgBuffer ),
01653                                   &iMsgBitOffset);
01654                      /*
01655                      ** Success.
01656                      */
01657                      iDataSize = 0;
01658                   }
01659                }
01660                break;
01661 
01662          default:
01663             bErrCode =  ABP_ERR_UNSUP_CMD;
01664             break;
01665          }
01666          break;
01667 
01668       default:
01669          /*
01670          ** Unsupported command.
01671          */
01672          bErrCode = ABP_ERR_UNSUP_CMD;
01673          break;
01674       }
01675    }
01676    else
01677    {
01678       /*
01679       ** The instance was not found.
01680       */
01681       bErrCode = ABP_ERR_UNSUP_INST;
01682    }
01683 
01684    /*
01685    ** Special handling. The remap response is already handled.
01686    */
01687    if( psMsgBuffer != NULL )
01688    {
01689       if( bErrCode == ABP_ERR_NO_ERROR )
01690       {
01691          ABP_SetMsgResponse( psMsgBuffer, iDataSize );
01692       }
01693       else
01694       {
01695          ABP_SetMsgErrorResponse( psMsgBuffer, 1, bErrCode );
01696       }
01697 
01698       ABCC_SendRespMsg( psMsgBuffer );
01699    }
01700 }
01701 
01702 
01703 void AD_UpdatePdReadData( void* pxPdDataBuf )
01704 {
01705    UINT16 i;
01706    UINT16 iRdPdBitOffset;
01707    const ad_MapType* AD_paiPdReadMap = ad_ReadMapInfo.paiMappedAdiList;
01708 
01709    iRdPdBitOffset = 0;
01710 
01711    if( AD_paiPdReadMap )
01712    {
01713       for ( i = 0; i < ad_ReadMapInfo.iNumMappedAdi; i++ )
01714       {
01715          if( AD_paiPdReadMap->iAdiIndex != AD_MAP_PAD_INDEX )
01716          {
01717             SetAdiValue( &ad_asADIEntryList[ AD_paiPdReadMap->iAdiIndex ],
01718                             pxPdDataBuf,
01719                             AD_paiPdReadMap->bNumElements,
01720                             AD_paiPdReadMap->bStartIndex,
01721                             &iRdPdBitOffset );
01722          }
01723          else
01724          {
01725             iRdPdBitOffset += AD_paiPdReadMap->bNumElements;
01726          }
01727 
01728          AD_paiPdReadMap++;
01729       }
01730    }
01731 }
01732 
01733 BOOL AD_UpdatePdWriteData( void* pxPdDataBuf )
01734 {
01735    UINT16 i;
01736    UINT16 iWrPdBitOffset;
01737    const ad_MapType* paiPdWriteMap = ad_WriteMapInfo.paiMappedAdiList;
01738 
01739    if( paiPdWriteMap )
01740    {
01741       iWrPdBitOffset = 0;
01742 
01743       for( i = 0; i < ad_WriteMapInfo.iNumMappedAdi ; i++)
01744       {
01745          if( paiPdWriteMap->iAdiIndex != AD_MAP_PAD_INDEX )
01746          {
01747             GetAdiValue( &ad_asADIEntryList[ paiPdWriteMap->iAdiIndex ],
01748                          pxPdDataBuf,
01749                          paiPdWriteMap->bNumElements,
01750                          paiPdWriteMap->bStartIndex ,
01751                          &iWrPdBitOffset);
01752          }
01753          else
01754          {
01755             iWrPdBitOffset += paiPdWriteMap->bNumElements;
01756          }
01757          paiPdWriteMap++;
01758       }
01759       return( TRUE );
01760    }
01761    return( FALSE );
01762 }
01763 
01764 UINT16 AD_AdiMappingReq( const AD_AdiEntryType** ppsAdiEntry,
01765                          const AD_DefaultMapType** ppsDefaultMap )
01766 {
01767    NetFormatType eNetFormat;
01768    eNetFormat = ABCC_NetFormatType();
01769 #ifdef ABCC_SYS_BIG_ENDIAN
01770    ad_fDoNetworkEndianSwap = ( eNetFormat == NET_LITTLEENDIAN ) ? TRUE : FALSE;
01771 #else
01772    ad_fDoNetworkEndianSwap = ( eNetFormat == NET_LITTLEENDIAN ) ? FALSE : TRUE;
01773 #endif
01774 
01775    *ppsAdiEntry = ad_asADIEntryList;
01776    *ppsDefaultMap = ad_asDefaultMap;
01777 
01778    return ad_iNumOfADIs;
01779 }
01780 
01781 void AD_RemapDone( void )
01782 {
01783    /*
01784    ** This Write Process Data update is to ensure that the write process data
01785    ** is updated with the right content.
01786    */
01787    ABCC_TriggerWrPdUpdate();
01788 }