Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 }
Generated on Tue Jul 12 2022 15:51:57 by
