Master sample: fix the failure in detecting the slave duplication
[processor-sdk/cclink.git] / CCIEF-BASIC_Master / sample / src / CCIEF_BASIC_MASTER.c
1 /*
2  * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
3  * Copyright (C) 2016 CC-Link Partner Association -http://am.cc-link.org/
4  * 
5  * 
6  *  Redistribution and use in source and binary forms, with or without 
7  *  modification, are permitted provided that the following conditions 
8  *  are met:
9  *
10  *    Redistributions of source code must retain the above copyright 
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  *    Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the 
15  *    documentation and/or other materials provided with the   
16  *    distribution.
17  *
18  *    Neither the name of Texas Instruments Incorporated nor the names of
19  *    its contributors may be used to endorse or promote products derived
20  *    from this software without specific prior written permission.
21  *
22  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
23  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
24  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
26  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
27  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
28  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
31  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
32  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34 */
36 #include "SLMP.h"
37 #include "CCIEF_BASIC_MASTER.h"
38 #include "CCIEF_BASIC_SLAVES.h"
39 #include "SOCKET.h"
40 #include "TIMER.h"
42 /************************************************************************************/
43 /* The following is an user defined main program. This main program is one of a         */
44 /* sample in the Windows OS and Intel x86 CPU. Please rewrite if necessary.                     */
45 /* This main program is one of a sample in the Linux. Please rewrite if necessary.      */
46 /*                                                                                                                                                                      */
47 /* This sample program for CCIEF-BASIC Slave Application.                                                       */
48 /*                                                                                                                                                                      */
49 /************************************************************************************/
51 #ifdef _WIN32
52 #include <WinSock2.h>
53 #include <Ws2tcpip.h>
54 #include <windows.h>
55 #elif __linux__
56 #include <sys/socket.h>
57 #include <netinet/in.h>
58 #include <string.h>
59 #endif
60 #include <stdio.h>
61 #include <time.h>
63 #ifdef _WIN32
64 #elif __linux__
65 #define INVALID_SOCKET          -1
66 #endif
68 /*[ Structure for Information of the CCIEF-BASIC Master ]*/
69 typedef struct 
70 {
71         uint8_t                                                         ucGroupNumber;                                                          /* Group number */
72         int                                                                     iTotalSlaveNumber;                                                      /* Total number of the slaves */
73         int                                                                     iOccupiedStationNumberTotal;                            /* Total number of the occupied station number */
74         int                                                                     iState;                                                                         /* State of Master */
75         CCIEF_BASIC_GROUP_PARAMETER                     *pGroupParameter;                                                       /* Pointer of the group parameter */
76         CCIEF_BASIC_SLAVES_CYCLIC_DATA_INFO     *pSlave[CCIEF_BASIC_MAX_SLAVE_NUMBER];          /* Pointer of information of the slaves */
77         uint16_t                                                        usFrameSequenceNumber;                                          /* Frame sequence number */
78         int                                                                     iPersuasionTimerId;                                                     /* Timer id for persuasion */
79         int                                                                     iCyclicTimerId;                                                         /* Timer id for cyclic time */
80         uint8_t                                                         aucCyclicData[CCIEF_BASIC_MAX_FRAME_SIZE];      /* Data for sending cyclic data */
81         int                                                                     iCyclicDataSize;                                                        /* Size of data for sending cyclic data */
82         int                                                                     iConstantLinkScanUse;                                           /* Using the constant link scan */
83         uint32_t                                                        ulResponseWaitTime;                                                     /* Time of waiting response[ms] */
84         int64_t                                                         llTimeData;                                                                     /* Time data of the sending latest cyclic data */
85         int64_t                                                         llLinkScanTimeStart;                                            /* Start time of link scan[us] */
86         int64_t                                                         llLinkScanTimeCurrent;                                          /* Current the link scan time[us] */
87         int64_t                                                         llLinkScanTimeMinimum;                                          /* Minimum the link scan time[us] */
88         int64_t                                                         llLinkScanTimeMaximum;                                          /* Maximum the link scan time[us] */
89 } CCIEF_BASIC_MASTER_GROUP_INFO;
91 #ifdef _WIN32
92 typedef struct 
93 {
94         uint32_t                                                ulIpAddress;                                                    /* Ip address */
95         CCIEF_BASIC_MASTER_PARAMETER    Parameter;                                                              /* Parameter */
96         int                                                             iGroupTotalNumber;                                              /* Total number of the groups */
97         CCIEF_BASIC_MASTER_GROUP_INFO   *pGroup[CCIEF_BASIC_MAX_GROUP_NUMBER];  /* Pointer of information of the groups */
98         uint32_t                                                ulId;                                                                   /* Id number */
99         uint32_t                                                ulDirectedIpAddress;                                    /* Directed broadcast ip address */
100         int                                                             iOccupiedStationNumberTotal;                    /* Total number of the occupied station number */
101         uint16_t                                                usParameterId;                                                  /* Parameter id */
102         uint16_t                                                usUnitInfo;                                                             /* Information of the unit */
103         int                                                             iErrCode;                                                               /* Error code of the master */
104 } CCIEF_BASIC_MASTER_CYCLIC_DATA_INFO;
105 #elif __linux__
106 typedef struct 
108         uint32_t                                                ulIpAddress;                                                    /* Ip address */
109         uint32_t                                                ulSubnetMask;                                                   /* Slave subnet mask */
110         CCIEF_BASIC_MASTER_PARAMETER    Parameter;                                                              /* Parameter */
111         int                                                             iGroupTotalNumber;                                              /* Total number of the groups */
112         CCIEF_BASIC_MASTER_GROUP_INFO   *pGroup[CCIEF_BASIC_MAX_GROUP_NUMBER];  /* Pointer of information of the groups */
113         uint32_t                                                ulId;                                                                   /* Id number */
114         uint32_t                                                ulDirectedIpAddress;                                    /* Directed broadcast ip address */
115         int                                                             iOccupiedStationNumberTotal;                    /* Total number of the occupied station number */
116         uint16_t                                                usParameterId;                                                  /* Parameter id */
117         uint16_t                                                usUnitInfo;                                                             /* Information of the unit */
118         int                                                             iErrCode;                                                               /* Error code of the master */
119 } CCIEF_BASIC_MASTER_CYCLIC_DATA_INFO;
120 #endif
122 /* Definition of external variable of sample program */
123 #ifdef _WIN32
124 static SOCKET sock;             /* sokect of CCIEF-BASIC Master */
125 #elif __linux__
126 static int sock;                /* sokect of CCIEF-BASIC Master */
127 #endif
129 static unsigned char    aucSendData[CCIEF_BASIC_MAX_FRAME_SIZE];        /* Data for sending packet */
130 static unsigned char    aucRecvData[CCIEF_BASIC_MAX_FRAME_SIZE];        /* Data for receiving packet */
131 static unsigned char    aucSendPacket[CCIEF_BASIC_MAX_FRAME_SIZE];      /* Buffer for sending packet */
132 static unsigned char    aucRecvPacket[CCIEF_BASIC_MAX_FRAME_SIZE];      /* Buffer for receiving packet */
134 static unsigned short   ausRX[(CCIEF_BASIC_RX_RY_SIZE / sizeof( uint16_t )) * CCIEF_BASIC_MAX_SLAVE_NUMBER];    /* RX for the master */
135 static unsigned short   ausRY[(CCIEF_BASIC_RX_RY_SIZE / sizeof( uint16_t )) * CCIEF_BASIC_MAX_SLAVE_NUMBER];    /* RY for the master */
136 static unsigned short   ausRWw[(CCIEF_BASIC_RWW_RWR_SIZE / sizeof( uint16_t )) * CCIEF_BASIC_MAX_SLAVE_NUMBER]; /* RWw for the master */
137 static unsigned short   ausRWr[(CCIEF_BASIC_RWW_RWR_SIZE / sizeof( uint16_t )) * CCIEF_BASIC_MAX_SLAVE_NUMBER]; /* RWr for the master */
139 static CCIEF_BASIC_MASTER_CALLBACK_CYCLIC_LINK_SCAN_END pUserLinkScanEndFunc = NULL;    /* Callback function for end of the link scan */
141 static CCIEF_BASIC_MASTER_CYCLIC_DATA_INFO      Master;                                                                 /* Information of the master */
142 static CCIEF_BASIC_MASTER_GROUP_INFO            Group[CCIEF_BASIC_MAX_GROUP_NUMBER];    /* Information of the groups */
143 static CCIEF_BASIC_SLAVES_CYCLIC_DATA_INFO      Slave[CCIEF_BASIC_MAX_SLAVE_NUMBER];    /* Information of the slaves cyclic data */
145 /* Definition of function of sample program */
146 static int ccief_basic_master_check_parameter( CCIEF_BASIC_MASTER_PARAMETER *pParameter );
147 static int ccief_basic_master_recv( void );
148 static int ccief_basic_master_polling( CCIEF_BASIC_MASTER_GROUP_INFO *pGroup );
149 static void ccief_basic_master_execute_state( CCIEF_BASIC_MASTER_GROUP_INFO *pGroup, int iEvent );
150 static void ccief_basic_master_execute_state_wait_cyclic( CCIEF_BASIC_MASTER_GROUP_INFO *pGroup, int iEvent );
151 static void ccief_basic_master_execute_state_persuasion( CCIEF_BASIC_MASTER_GROUP_INFO *pGroup, int iEvent );
152 static void ccief_basic_master_execute_state_linkscan_end( CCIEF_BASIC_MASTER_GROUP_INFO *pGroup, int iEvent );
153 static void ccief_basic_master_execute_state_linkscan( CCIEF_BASIC_MASTER_GROUP_INFO *pGroup, int iEvent );
154 static void ccief_basic_master_persuasion_timer_timeout( int iId, void *pCallbackArg );
155 static void ccief_basic_master_cyclic_timer_timeout( int iId, void *pCallbackArg );
156 static int ccief_basic_master_make_cyclic_data( CCIEF_BASIC_MASTER_GROUP_INFO *pGroup );
157 static int ccief_basic_master_send_cyclic_data( uint32_t ulIpAddress, uint8_t *pucData, int iDataSize );
158 static void ccief_basic_master_recv_cyclic_data_response( uint8_t *pucData );
160 /************************************************************************************/
161 /* This is an user defined function for initialization of CCIEF-BASIC Master.                   */
162 /************************************************************************************/
163 int ccief_basic_master_initialize( uint32_t ulIpAddress, uint32_t ulSubnetMask, CCIEF_BASIC_MASTER_PARAMETER *pParameter,
164                                                                  CCIEF_BASIC_MASTER_CALLBACK_CYCLIC_LINK_SCAN_END pCyclicLinkScanEndFunc )
166         CCIEF_BASIC_MASTER_GROUP_INFO           *pGroup;
167         CCIEF_BASIC_SLAVES_CYCLIC_DATA_INFO *pSlave;
168         uint8_t ucGroupNumber;
169         int i, j, iGroupCheck;
170         int iErrCode;
172         /* Initialize of the master */
173         memset( &Master, 0, sizeof( Master ) );
174         memset( &Group, 0, sizeof( Group ) );
175         pGroup = (CCIEF_BASIC_MASTER_GROUP_INFO*)NULL;
177         /* Getting the parameter */
178         memcpy( &Master.Parameter, pParameter, sizeof( Master.Parameter ) );
180         /* User callback function */
181         pUserLinkScanEndFunc = pCyclicLinkScanEndFunc;
183         /* Setting the master information */
184         Master.ulIpAddress = ulIpAddress;
185         Master.ulId = ulIpAddress;
186 #ifdef _WIN32
187 #elif __linux__
188         Master.ulSubnetMask = ulSubnetMask;
189 #endif
190         Master.ulDirectedIpAddress = ((ulIpAddress & ulSubnetMask) | ~ulSubnetMask);
192         /* Check the Parameter */
193         iErrCode = ccief_basic_master_check_parameter( pParameter );
194         if ( iErrCode != CCIEF_BASIC_MASTER_ERR_OK )
195         {
196                 return iErrCode;
197         }
199         for ( i = 0; i < pParameter->iTotalSlaveNumber; i ++ )
200         {
201                 ucGroupNumber = pParameter->Slave[i].ucGroupNumber;
202                 iGroupCheck = CCIEF_BASIC_MASTER_ERR_NG;
203                 for ( j = 0; j < Master.iGroupTotalNumber; j ++ )
204                 {
205                         if ( ucGroupNumber == Master.pGroup[j]->ucGroupNumber )
206                         {
207                                 pGroup = Master.pGroup[j];
208                                 iGroupCheck = CCIEF_BASIC_MASTER_ERR_OK;
209                                 break;
210                         }
211                 }
212                 if ( iGroupCheck == CCIEF_BASIC_MASTER_ERR_NG )
213                 {
214                         pGroup = &Group[Master.iGroupTotalNumber];
215                         pGroup->ucGroupNumber = ucGroupNumber;
216                         for ( j = 0; j < pParameter->iTotalGroupNumber; j ++ )
217                         {
218                                 if ( ucGroupNumber == pParameter->Group[j].ucGroupNumber )
219                                 {
220                                         break;
221                                 }
222                         }
223                         pGroup->pGroupParameter = &pParameter->Group[j];
224                         Master.pGroup[Master.iGroupTotalNumber] = pGroup;
225                         Master.iGroupTotalNumber ++;
226                 }
227                 pSlave = &Slave[i];
228                 pSlave->iNumber = i;
229                 pSlave->pParameter = &Master.Parameter.Slave[i];
230                 pSlave->ulId = pParameter->Slave[i].ulIpAddress;
231                 if ( pGroup->pGroupParameter->usCyclicTransmissionTimeoutCount == 0 )
232                 {
233                         pSlave->usCyclicTransmissionTimeoutCount = CCIEF_BASIC_CYCLIC_TRANSMISSION_TIMEOUT_COUNT;
234                 }
235                 else
236                 {
237                         pSlave->usCyclicTransmissionTimeoutCount = pGroup->pGroupParameter->usCyclicTransmissionTimeoutCount;
238                 }
239                 pSlave->iStationNumber = Master.iOccupiedStationNumberTotal;
240                 pSlave->iGroupStationNumber = pGroup->iOccupiedStationNumberTotal;
241                 pSlave->iReceiveComplete = CCIEF_BASIC_SLAVE_RESPONSE_NOT_RECEIVED;
242                 pSlave->iDuplicateState = CCIEF_BASIC_SLAVE_DUPLICATION_NOT_DETECT;
243                 pSlave->pusRWw = &ausRWw[pSlave->iStationNumber * ( CCIEF_BASIC_RWW_RWR_SIZE / sizeof( uint16_t ) )];
244                 pSlave->pusRY = &ausRY[pSlave->iStationNumber * ( CCIEF_BASIC_RX_RY_SIZE / sizeof( uint16_t ) )];
245                 pSlave->pusRWr = &ausRWr[pSlave->iStationNumber * ( CCIEF_BASIC_RWW_RWR_SIZE / sizeof( uint16_t ) )];
246                 pSlave->pusRX = &ausRX[pSlave->iStationNumber * ( CCIEF_BASIC_RX_RY_SIZE / sizeof( uint16_t ) )];
247                 pSlave->pusFrameSequenceNumber = &pGroup->usFrameSequenceNumber;
248                 pGroup->pSlave[pGroup->iTotalSlaveNumber] = pSlave;
249                 pGroup->iTotalSlaveNumber ++;
250                 pGroup->iOccupiedStationNumberTotal += pParameter->Slave[i].usOccupiedStationNumber;
251                 Master.iOccupiedStationNumberTotal += pParameter->Slave[i].usOccupiedStationNumber;
252         }
254         /* Calucurate of the parameter id */
255         srand( (unsigned)time( NULL ) );
256         Master.usParameterId = (uint16_t)rand();
258         /* Initialize a socket */
259         sock = INVALID_SOCKET;
261         /* Initialize of the slaves */
262         for ( i = 0; i < Master.Parameter.iTotalSlaveNumber; i ++ )
263         {
264                 ccief_basic_slaves_initialize( &Slave[i] );
265         }
267         for ( i = 0; i < Master.iGroupTotalNumber; i ++ )
268         {
269                 /* Set the master state */
270                 Master.pGroup[i]->iState = CCIEF_BASIC_STATE_MASTER_WAITING;
272                 /* Execute the state of the master */
273                 ccief_basic_master_execute_state( Master.pGroup[i], CCIEF_BASIC_EVENT_MASTER_PARAMETER_GET );
274         }
276         return CCIEF_BASIC_MASTER_ERR_OK;
279 /************************************************************************************/
280 /* This is an user defined function for termination of CCIEF-BASIC Master.                      */
281 /************************************************************************************/
282 void ccief_basic_master_terminate( void )
284         /* Termination of socket */
285         socket_terminate( sock );
287         return;
290 /************************************************************************************/
291 /* This is an user defined function for main function of CCIEF-BASIC Master.                    */
292 /************************************************************************************/
293 int ccief_basic_master_main( void )
295         int i, iErrCode = 0;
297         /* Receive data */
298         iErrCode = ccief_basic_master_recv();
299         if ( iErrCode != CCIEF_BASIC_MASTER_ERR_OK )
300         {
301                 return iErrCode;
302         }
304         /* Execute the state of the master */
305         for ( i = 0; i < Master.iGroupTotalNumber; i ++ )
306         {
307                 (void)ccief_basic_master_polling( Master.pGroup[i] );
308         }
310         return CCIEF_BASIC_MASTER_ERR_OK;
313 /************************************************************************************/
314 /* This is an user defined function for set of the start cyclic of the slave.           */
315 /************************************************************************************/
316 int ccief_basic_master_start_cyclic( int iSlaveNumber )
318         if (( iSlaveNumber < 0 ) || ( Master.Parameter.iTotalSlaveNumber <= iSlaveNumber ))
319         {
320                 return CCIEF_BASIC_MASTER_ERR_NG;
321         }
323         /* Start cyclic from user operation. */
324         Slave[iSlaveNumber].iCyclicStart = CCIEF_BASIC_CYCLIC_START;
326         return CCIEF_BASIC_MASTER_ERR_OK;
329 /************************************************************************************/
330 /* This is an user defined function for set of the stop cyclic of the slave.            */
331 /************************************************************************************/
332 int ccief_basic_master_stop_cyclic( int iSlaveNumber )
334         if (( iSlaveNumber < 0 ) || ( Master.Parameter.iTotalSlaveNumber <= iSlaveNumber ))
335         {
336                 return CCIEF_BASIC_MASTER_ERR_NG;
337         }
339         /* Stop cyclic from user operation. */
340         Slave[iSlaveNumber].iCyclicStart = CCIEF_BASIC_CYCLIC_STOP;
342         return CCIEF_BASIC_MASTER_ERR_OK;
345 /************************************************************************************/
346 /* This is an user defined function for getting the RX.                                                         */
347 /************************************************************************************/
348 int ccief_basic_master_get_rx( int iNumber, int *piValue )
350         unsigned short usTemp;
352         /* Check the number of device */
353         if (( iNumber < 0 ) || ( sizeof( ausRX ) * 8 ) <= iNumber )
354         {
355                 return CCIEF_BASIC_MASTER_ERR_DEVICE_RANGE;
356         }
358         usTemp = ausRX[iNumber / 16];
359         if (( usTemp & ( 1 << ( iNumber % 16 ))) == CCIEF_BASIC_BIT_OFF )
360         {
361                 *piValue = CCIEF_BASIC_BIT_OFF;
362         }
363         else
364         {
365                 *piValue = CCIEF_BASIC_BIT_ON;
366         }
367         
368         return CCIEF_BASIC_MASTER_ERR_OK;
371 /************************************************************************************/
372 /* This is an user defined function for setting the RY.                                                         */
373 /************************************************************************************/
374 int ccief_basic_master_set_ry( int iNumber, int iValue )
376         unsigned short usTemp;
378         /* Check the number of device */
379         if (( iNumber < 0 ) || ( sizeof( ausRY ) * 8 ) <= iNumber )
380         {
381                 return CCIEF_BASIC_MASTER_ERR_DEVICE_RANGE;
382         }
384         /* Check the value */
385         if (( iValue == CCIEF_BASIC_BIT_OFF ) || ( iValue == CCIEF_BASIC_BIT_ON ))
386         {
387                 usTemp = ausRY[( iNumber / 16 )];
388                 usTemp = (uint16_t)(( usTemp & ~( 1 << ( iNumber % 16 ))) | ( iValue << ( iNumber % 16 )));
389                 ausRY[( iNumber / 16 )] = usTemp;
390         }
391         else
392         {
393                 return CCIEF_BASIC_MASTER_ERR_NG;
394         }
396         return CCIEF_BASIC_MASTER_ERR_OK;
399 /************************************************************************************/
400 /* This is an user defined function for setting the RWw.                                                        */
401 /************************************************************************************/
402 int ccief_basic_master_set_rww( int iNumber, uint16_t usValue )
404         int iMaxNumber;
406         /* Check the number of device */
407         iMaxNumber = sizeof( ausRWw ) / sizeof( uint16_t );
408         if (( iNumber < 0 ) || (iMaxNumber <= iNumber ))
409         {
410                 return CCIEF_BASIC_MASTER_ERR_DEVICE_RANGE;
411         }
413         ausRWw[iNumber] = usValue;
414         
415         return CCIEF_BASIC_MASTER_ERR_OK;
418 /************************************************************************************/
419 /* This is an user defined function for getting the RWr.                                                        */
420 /************************************************************************************/
421 int ccief_basic_master_get_rwr( int iNumber, uint16_t *pusValue )
423         int iMaxNumber;
425         /* Check the number of device */
426         iMaxNumber = sizeof( ausRWr ) / sizeof( uint16_t );
427         if (( iNumber < 0 ) || (iMaxNumber <= iNumber ))
428         {
429                 return CCIEF_BASIC_MASTER_ERR_DEVICE_RANGE;
430         }
432         *pusValue = ausRWr[iNumber];
433         
434         return CCIEF_BASIC_MASTER_ERR_OK;
437 /************************************************************************************/
438 /* This is an user defined function for getting the device start pointer.                       */
439 /************************************************************************************/
440 uint16_t *ccief_basic_master_get_pointer( int iDeviceType )
442         uint16_t *pusStartPointer;
444         /* Getting the device start pointer */
446         /* Check the device type */
447         switch ( iDeviceType )
448         {
449                 /* RX */
450                 case CCIEF_BASIC_DEVICE_TYPE_RX:
451                         pusStartPointer = ausRX;
452                         break;
453                 /* RY */
454                 case CCIEF_BASIC_DEVICE_TYPE_RY:
455                         pusStartPointer = ausRY;
456                         break;
457                 /* RWw */
458                 case CCIEF_BASIC_DEVICE_TYPE_RWW:
459                         pusStartPointer = ausRWw;
460                         break;
461                 /* RWr */
462                 case CCIEF_BASIC_DEVICE_TYPE_RWR:
463                         pusStartPointer = ausRWr;
464                         break;
465                 /* Error of argument */
466                 default:
467                         pusStartPointer = NULL;
468                         break;
469         }
470         
471         return pusStartPointer;
474 /************************************************************************************/
475 /* This is an user defined function for setting the unit info.                                          */
476 /************************************************************************************/
477 void ccief_basic_master_set_unit_info( uint16_t usUnitInfo )
479         Master.usUnitInfo = usUnitInfo;
481         return;
484 /************************************************************************************/
485 /* This is an user defined function for getting information of the slave.                       */
486 /************************************************************************************/
487 int ccief_basic_master_get_slave_info( int iSlaveNumber, CCIEF_BASIC_SLAVE_INFO *pSlaveInfo )
490         if (( iSlaveNumber < 0 ) || ( Master.Parameter.iTotalSlaveNumber <= iSlaveNumber ))
491         {
492                 return CCIEF_BASIC_MASTER_ERR_NG;
493         }
495         if ( pSlaveInfo == NULL )
496         {
497                 return CCIEF_BASIC_MASTER_ERR_NG;
498         }
500         /* Getting information of the slave */
501         pSlaveInfo->usProtocolVersion = Slave[iSlaveNumber].usProtocolVersion;
502         pSlaveInfo->usEndCode = Slave[iSlaveNumber].usEndCode;
503         pSlaveInfo->ucGroupNumber = Slave[iSlaveNumber].pParameter->ucGroupNumber;
504         pSlaveInfo->ulId = Slave[iSlaveNumber].ulId;
505         pSlaveInfo->usFrameSequenceNumber = Slave[iSlaveNumber].usFrameSequenceNumber;
506         pSlaveInfo->usOccupiedStationNumber = Slave[iSlaveNumber].pParameter->usOccupiedStationNumber;
507         pSlaveInfo->iState = Slave[iSlaveNumber].iState;
508         memcpy( &pSlaveInfo->NotifyInfo, &Slave[iSlaveNumber].NotifyInfo, sizeof( pSlaveInfo->NotifyInfo ) );
509         pSlaveInfo->iCyclicState = Slave[iSlaveNumber].iCyclicState;
510         pSlaveInfo->iStationNumber = Slave[iSlaveNumber].iStationNumber;
512         return CCIEF_BASIC_MASTER_ERR_OK;
515 /************************************************************************************/
516 /* This is an user defined function for getting information of the master.                      */
517 /************************************************************************************/
518 int ccief_basic_master_get_group_info( int iGroupNumber, CCIEF_BASIC_GROUP_INFO *pGroupInfo )
521         if ( pGroupInfo == NULL )
522         {
523                 return CCIEF_BASIC_MASTER_ERR_NG;
524         }
526         /* Getting information of the master */
527         pGroupInfo->usProtocolVersion = CCIEF_BASIC_PROTCOL_VERSION;
528         pGroupInfo->ulId = Master.ulId;
529         pGroupInfo->ucGroupNumber = Group[iGroupNumber].ucGroupNumber;
530         pGroupInfo->iTotalSlaveNumber = Group[iGroupNumber].iTotalSlaveNumber;
531         pGroupInfo->usTotalOccupiedStationNumber = Group[iGroupNumber].iOccupiedStationNumberTotal;
532         pGroupInfo->iState = Group[iGroupNumber].iState;
533         pGroupInfo->usUnitInfo = Master.usUnitInfo;
534         pGroupInfo->usFrameSequenceNumber = Group[iGroupNumber].usFrameSequenceNumber;
535         pGroupInfo->usParameterId = Master.usParameterId;
536         pGroupInfo->llTimeData = Group[iGroupNumber].llTimeData;
537         pGroupInfo->llLinkScanTimeCurrent = Group[iGroupNumber].llLinkScanTimeCurrent;
538         pGroupInfo->llLinkScanTimeMinimum = Group[iGroupNumber].llLinkScanTimeMinimum;
539         pGroupInfo->llLinkScanTimeMaximum = Group[iGroupNumber].llLinkScanTimeMaximum;
541         return CCIEF_BASIC_MASTER_ERR_OK;
544 /************************************************************************************/
545 /* This is an user defined function for check the parameter of CCIEF-BASIC Master.      */
546 /************************************************************************************/
547 int ccief_basic_master_check_parameter( CCIEF_BASIC_MASTER_PARAMETER *pParameter )
549         int     i, j, iOccupiedStationNumberTotal;
550         struct in_addr addr;
551         char Ipaddr[16];
553         /* Check the master ip address */
554         for ( i = 0; i < pParameter->iTotalSlaveNumber; i ++ )
555         {
556                 if ( Master.ulIpAddress == pParameter->Slave[i].ulIpAddress )
557                 {
558                         printf( "Parameter Error: Duplicate master ip address in slaves!\n" );
559                         return CCIEF_BASIC_MASTER_ERR_NG;
560                 }
561         }
563         /* Check the total number of the slaves */
564         if (( pParameter->iTotalSlaveNumber == 0 ) || ( CCIEF_BASIC_MAX_SLAVE_NUMBER < pParameter->iTotalSlaveNumber )) {
565                 printf( "Parameter Error: Out of range of total slave number! %d (range: 1-64)\n", pParameter->iTotalSlaveNumber );
566                 return CCIEF_BASIC_MASTER_ERR_NG;
567         }
568         
569         /* Check the total number of occupied stations */
570         iOccupiedStationNumberTotal = 0;
571         for ( i = 0; i < pParameter->iTotalSlaveNumber; i ++ )
572         {
573                 if (( pParameter->Slave[i].usOccupiedStationNumber < 1 ) || ( CCIEF_BASIC_MAX_NUMBER_OF_OCCUPIED_STATIONS_GROUP < pParameter->Slave[i].usOccupiedStationNumber )) {
574                         printf( "Parameter Error: Invalid number of occupied stations! %d(No.%d) (range: 1-16)\n", pParameter->Slave[i].usOccupiedStationNumber, i+1 );
575                         return CCIEF_BASIC_MASTER_ERR_NG;
576                 }
577                 iOccupiedStationNumberTotal += pParameter->Slave[i].usOccupiedStationNumber;
579         }
580         if ( CCIEF_BASIC_MAX_SLAVE_NUMBER < iOccupiedStationNumberTotal )
581         {
582                 printf( "Parameter Error: Invalid total number of occupied stations! %d (range: 1-64)\n", iOccupiedStationNumberTotal );
583                 return CCIEF_BASIC_MASTER_ERR_NG;
584         }
586         /* Check the total number of occupied stations(for group) */
587         for ( i = 0; i < CCIEF_BASIC_MAX_GROUP_NUMBER; i ++ )
588         {
589                 iOccupiedStationNumberTotal = 0;
590                 for ( j = 0; j < pParameter->iTotalSlaveNumber; j ++ )
591                 {
592                         if (( i + 1 ) == pParameter->Slave[j].ucGroupNumber )
593                         {
594                                 iOccupiedStationNumberTotal += pParameter->Slave[j].usOccupiedStationNumber;
595                         }
596                 }
597                 if ( CCIEF_BASIC_MAX_NUMBER_OF_OCCUPIED_STATIONS_GROUP < iOccupiedStationNumberTotal )
598                 {
599                         printf( "Parameter Error: Invalid total number of occupied stations! (Group Number %d)\n", ( i + 1 ));
600                         return CCIEF_BASIC_MASTER_ERR_NG;
601                 }
602         }
604         /* Check the slave ip address */
605         for ( i = 0; i < pParameter->iTotalSlaveNumber; i ++ )
606         {
607                 for ( j = 0; j < pParameter->iTotalSlaveNumber; j ++ )
608                 {
609                         if (( i != j ) && ( pParameter->Slave[i].ulIpAddress == pParameter->Slave[j].ulIpAddress ))
610                         {
611 #ifdef _WIN32
612                                 addr.S_un.S_addr = htonl(pParameter->Slave[j].ulIpAddress);
613 #elif __linux__
614                                 addr.s_addr = htonl(pParameter->Slave[j].ulIpAddress);  
615 #endif
616                                 inet_ntop(AF_INET, &addr, Ipaddr, sizeof(Ipaddr) );
617                                 printf( "Parameter Error: Duplicate slaves ip address %s!\n", Ipaddr );
618                                 return CCIEF_BASIC_MASTER_ERR_NG;
619                         }
620                 }
621         }
623         /* Check the total number of the group */
624         if (( pParameter->iTotalGroupNumber == 0 ) || ( CCIEF_BASIC_MAX_GROUP_NUMBER < pParameter->iTotalGroupNumber )) {
625                 printf( "Parameter Error: Out of range of total group number! %d (range: 1-64)\n", pParameter->iTotalGroupNumber );
626                 return CCIEF_BASIC_MASTER_ERR_NG;
627         }
629         /* Check the group number */
630         for ( i = 0; i < pParameter->iTotalSlaveNumber; i ++ )
631         {
632                 if (( pParameter->Slave[i].ucGroupNumber == 0) || ( CCIEF_BASIC_MAX_GROUP_NUMBER < pParameter->Slave[i].ucGroupNumber ))
633                 {
634                         printf( "Parameter Error: Invalid group number at the slave No.%d! (range: 1-64)\n", ( i + 1 ));
635                         return CCIEF_BASIC_MASTER_ERR_NG;
636                 }
637         }
638         for ( i = 0; i < pParameter->iTotalSlaveNumber; i ++ )
639         {
640                 for ( j = 0; j < pParameter->iTotalGroupNumber; j ++ )
641                 {
642                         if ( pParameter->Slave[i].ucGroupNumber == pParameter->Group[j].ucGroupNumber )
643                         {
644                                 break;
645                         }
646                 }
647                 if ( j == pParameter->iTotalGroupNumber )
648                 {
649                         printf( "Parameter Error: Not found the parameter of group number %d!\n", pParameter->Slave[i].ucGroupNumber );
650                         return CCIEF_BASIC_MASTER_ERR_NG;
651                 }
652         }
654         /* Check the constant link scan time */
655         for ( i = 0; i < pParameter->iTotalGroupNumber; i ++ )
656         {
657                 if ( CCIEF_BASIC_MAX_CONSTANT_LINK_SCAN_TIME < pParameter->Group[i].usConstantLinkScanTime )
658                 {
659                         printf( "Parameter Error: Invalid constant link scan time! %d (range: 0-2000)\n", pParameter->Group[i].usConstantLinkScanTime );
660                         printf( "(0:no use)\n" );
661                         return CCIEF_BASIC_MASTER_ERR_NG;
662                 }
663         }
665         return CCIEF_BASIC_MASTER_ERR_OK;
668 /************************************************************************************/
669 /* This is an user defined function for receiving packet. The following is one of a     */
670 /* sample in the Windows OS. Please rewrite if necessary.                                                       */
671 /* The following is one of a sample in the Linux. Please rewrite if necessary.          */
672 /************************************************************************************/
673 int ccief_basic_master_recv( void )
675         uint32_t                ulRecvAddr;
676         uint16_t                usRecvPortNumber;
677         struct in_addr  addr;
678         SLMP_INFO               source; /* SLMP Infomation for received packet */
679         int                             iErrCode;
680         int                             i;
681         char                    Ipaddr[16];
682 #ifdef _WIN32
683 #elif __linux__
684         uint32_t                ulMyNetAddress;
685         uint32_t                ulOtherNetAddress;
686 #endif
687         uint16_t                usPacketCount = 0;      /* Number of processed packets */
689         /* Check the socket */
690         if ( sock == INVALID_SOCKET ) {
691                 return CCIEF_BASIC_MASTER_ERR_OK;
692         }
694         /* Packet receiving */
695         while ( usPacketCount <= CCIEF_BASIC_PACKET_COUNT_MAX )
696         {
697             memset( &source, 0, sizeof(SLMP_INFO) );
698             iErrCode = 0;
700             iErrCode = socket_recv( sock, aucRecvPacket, sizeof( aucRecvPacket ), &ulRecvAddr, &usRecvPortNumber );
701             if ( iErrCode != SOCKET_ERR_OK )
702             {
703                 if ( iErrCode == SOCKET_ERR_NO_RECEIVABLE )
704                 {
705                         return CCIEF_BASIC_MASTER_ERR_OK;
706                 }
707                 else
708                 {
709                         return iErrCode;
710                 }
711             }
713 #ifdef _WIN32
714 #elif __linux__
715             ulMyNetAddress = ( Master.ulIpAddress & Master.ulSubnetMask );
716             ulOtherNetAddress = ( ulRecvAddr & Master.ulSubnetMask );
718             /* Other network broadcast break*/
719             if( ulMyNetAddress != ulOtherNetAddress )
720             {
721                 return CCIEF_BASIC_MASTER_ERR_OK;
722             }
723 #endif
726             /* Sets the SLMP Information for receiving. */
727             source.pucData = aucRecvData;
729             /* Get the SLMP Information from the request packet using the SLMP library. */
730             iErrCode = SLMP_GetSlmpInfo( &source, aucRecvPacket );
731             if ( iErrCode != SLMP_ERR_OK )
732             {
733                 /* Invalid SLMP Frame. */
734                 printf( "ERR : Invalid SLMP frame received!\n" );
735                 return CCIEF_BASIC_MASTER_ERR_OK;
736             }
738             /* Check the SLMP frame. */
739             if ( source.ulFrameType == SLMP_FTYPE_BIN_RES_ST )
740             {
741                 /* Response of the SLMP frame */
742                 if ( source.usEndCode == SLMP_ERR_OK )
743                 {
744                         /* Receiving response of the cyclic data. */
745                         ccief_basic_master_recv_cyclic_data_response( source.pucData );
746                 }
747                 else
748                 {
749 #ifdef _WIN32
750                         addr.S_un.S_addr = htonl(ulRecvAddr);
751 #elif __linux__
752                         addr.s_addr = htonl(ulRecvAddr);        
753 #endif
754                         inet_ntop(AF_INET, &addr, Ipaddr, sizeof(Ipaddr) );
755                         printf( "ERR : EndCode %04X from %s!\n", source.usEndCode, Ipaddr );
756                 }
757             }
758             else
759             {
760                 /* Request of the SLMP frame */
761                 if ( source.usCommand == SLMP_COMMAND_CYCLIC_DATA )
762                 {
763                         /* Cyclic Data(0E70h) */
764                         for ( i = 0; i < Master.iGroupTotalNumber; i ++ )
765                         {
766                                 /* Execute the state of the master */
767                                 ccief_basic_master_execute_state( Master.pGroup[i], CCIEF_BASIC_EVENT_MASTER_CYCLIC_DATA_RECV );
768                         }
769                 }
770             }
772             /* Check the error code of the master duplication */
773             if ( Master.iErrCode == CCIEF_BASIC_MASTER_ERR_MASTER_DUPLICATION )
774             {
775                 return CCIEF_BASIC_MASTER_ERR_MASTER_DUPLICATION;
776             }
777         
778             /* Check the error code of the slave duplication */
779             if ( Master.iErrCode == CCIEF_BASIC_MASTER_ERR_SLAVE_DUPLICATION )
780             {
781                 return CCIEF_BASIC_MASTER_ERR_SLAVE_DUPLICATION;
782             }
784             /* Increment the number of processed packets */
785             usPacketCount++;
786         }
788         return CCIEF_BASIC_MASTER_ERR_OK;
791 /************************************************************************************/
792 /* This is an user defined function for polling operation.                                                      */
793 /************************************************************************************/
794 int ccief_basic_master_polling( CCIEF_BASIC_MASTER_GROUP_INFO *pGroup )
796         int     i;
797         int iSlaveCyclicStateOffNumber, iSlaveCyclicStateOffCyclicEndNumber;
798         int iSlaveCyclicStateOnNumber, iSlaveCyclicStateOnCyclicEndNumber;
799         int iErrCode = CCIEF_BASIC_MASTER_ERR_OK;
801         /* Check the state of the master */
802         if ( pGroup->iState == CCIEF_BASIC_STATE_MASTER_LINK_SCAN )
803         {
804                 /* Check using the constant link scan */
805                 if ( pGroup->iConstantLinkScanUse == CCIEF_BASIC_CONSTANT_LINK_SCAN_NOT_USE )
806                 {
807                         /* Check the cyclic end of the slave */
808                         iSlaveCyclicStateOffNumber = 0;
809                         iSlaveCyclicStateOffCyclicEndNumber = 0;
810                         iSlaveCyclicStateOnNumber = 0;
811                         iSlaveCyclicStateOnCyclicEndNumber = 0;
812                         for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
813                         {
814                                 if ( pGroup->pSlave[i]->iCyclicState == CCIEF_BASIC_CYCLIC_STATE_OFF )
815                                 {
816                                         /* OFF the slave cyclic state */
817                                         iSlaveCyclicStateOffNumber ++;
818                                         if ( pGroup->pSlave[i]->iState == CCIEF_BASIC_STATE_SLAVE_CYCLIC_END )
819                                         {
820                                                 iSlaveCyclicStateOffCyclicEndNumber ++;
821                                         }
822                                 }
823                                 else
824                                 {
825                                         /* ON the slave cyclic state */
826                                         iSlaveCyclicStateOnNumber ++;
827                                         if ( pGroup->pSlave[i]->iState == CCIEF_BASIC_STATE_SLAVE_CYCLIC_END )
828                                         {
829                                                 iSlaveCyclicStateOnCyclicEndNumber ++;
830                                         }
831                                 }
832                         }
833                         if ((( 0 < iSlaveCyclicStateOnNumber ) && ( iSlaveCyclicStateOnNumber == iSlaveCyclicStateOnCyclicEndNumber ))
834                          || (( 0 == iSlaveCyclicStateOnNumber ) && ( iSlaveCyclicStateOffNumber == iSlaveCyclicStateOffCyclicEndNumber )))
835                         {
836                                 /* End of the cyclic */
837                                 /* Execute the state of the slave */
838                                 for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
839                                 {
840                                         ccief_basic_slaves_execute_state( pGroup->pSlave[i], CCIEF_BASIC_EVENT_SLAVE_CYCLIC_END );
841                                 }
842                                 /* Execute the state of the master */
843                                 ccief_basic_master_execute_state( pGroup, CCIEF_BASIC_EVENT_MASTER_LINK_SCAN_END );
844                         }
845                 }
846         }
848         return iErrCode;
851 /************************************************************************************/
852 /* This is an user defined function for executed according to the state                         */
853 /* of the master.                                                                                                                                       */
854 /************************************************************************************/
855 void ccief_basic_master_execute_state( CCIEF_BASIC_MASTER_GROUP_INFO *pGroup, int iEvent )
857         /* Execute the state of the master */
858         switch ( pGroup->iState )
859         {
860                 /* Waiting for the cyclic operation. */
861                 case CCIEF_BASIC_STATE_MASTER_WAITING:
862                         ccief_basic_master_execute_state_wait_cyclic( pGroup, iEvent );
863                         break;
864                 /* Persuasion of the master. */
865                 case CCIEF_BASIC_STATE_MASTER_PERSUASION:
866                         ccief_basic_master_execute_state_persuasion( pGroup, iEvent );
867                         break;
868                 /* End of the link scan. */
869                 case CCIEF_BASIC_STATE_MASTER_LINK_SCAN_END:
870                         ccief_basic_master_execute_state_linkscan_end( pGroup, iEvent );
871                         break;
872                 /* Running the link scan. */
873                 case CCIEF_BASIC_STATE_MASTER_LINK_SCAN:
874                         ccief_basic_master_execute_state_linkscan( pGroup, iEvent );
875                         break;
876                 default:
877                         break;
878         }
880         return;
883 /************************************************************************************/
884 /* This is an user defined function for state of waiting of the cyclic operation.       */
885 /************************************************************************************/
886 void ccief_basic_master_execute_state_wait_cyclic( CCIEF_BASIC_MASTER_GROUP_INFO *pGroup, int iEvent )
888         /* Check the event */
889         switch ( iEvent )
890         {
891                 /* Getting the parameter */
892                 case CCIEF_BASIC_EVENT_MASTER_PARAMETER_GET:
893                         /* Initialization of the socket */
894                         if ( sock == INVALID_SOCKET )
895                         {
896                                 Master.iErrCode = socket_initialize( &sock, Master.ulIpAddress, CCIEF_BASIC_PORT_NUMBER_CYCLIC );
897                                 if( Master.iErrCode != CCIEF_BASIC_MASTER_ERR_OK )
898                                 {
899                                         return;
900                                 }
901                         }
902                         /* Check constant link scan */
903                         pGroup->iConstantLinkScanUse = CCIEF_BASIC_CONSTANT_LINK_SCAN_NOT_USE;
904                         if ( pGroup->pGroupParameter->usConstantLinkScanTime != 0 )
905                         {
906                                 /* Set waiting of the end of constant link scan */
907                                 pGroup->iConstantLinkScanUse = CCIEF_BASIC_CONSTANT_LINK_SCAN_USE;
908                         }
909                         /* Start the master persuasion timer*/
910                         timer_start( CCIEF_BASIC_MASTER_PERSUASION_TIME, &pGroup->iPersuasionTimerId,
911                                                  &ccief_basic_master_persuasion_timer_timeout, (void *)pGroup );
912                         /* Set the master state */
913                         pGroup->iState = CCIEF_BASIC_STATE_MASTER_PERSUASION;
914                         break;
915                 /* Changing the parameter */
916                 case CCIEF_BASIC_EVENT_MASTER_PARAMETER_CHANGE:
917                         /* Nothing */
918                         break;
919                 default:
920                         break;
921         }
923         return;
926 /************************************************************************************/
927 /* This is an user defined function for state of persuasion of the master.                      */
928 /************************************************************************************/
929 void ccief_basic_master_execute_state_persuasion( CCIEF_BASIC_MASTER_GROUP_INFO *pGroup, int iEvent )
931         int     i;
933         /* Check the event */
934         switch ( iEvent )
935         {
936                 /* Changing the parameter */
937                 case CCIEF_BASIC_EVENT_MASTER_PARAMETER_CHANGE:
938                         /* Execute the state of the slave */
939                         for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
940                         {
941                                 ccief_basic_slaves_execute_state( pGroup->pSlave[i], CCIEF_BASIC_EVENT_SLAVE_PARAMETER_CHANGE );
942                         }
943                         /* Stop the master persuasion timer*/
944                         timer_stop( pGroup->iPersuasionTimerId );
945                         /* Termination of socket */
946                         socket_terminate( sock );
947                         /* Set the master state */
948                         pGroup->iState = CCIEF_BASIC_STATE_MASTER_WAITING;
949                         break;
950                 /* Timeout of monitoring the persuasion frame */
951                 case CCIEF_BASIC_EVENT_MASTER_PERSUASION_TIMEOUT:
952                         /* Check the constant link scan time */
953                         if ( pGroup->pGroupParameter->usConstantLinkScanTime != 0 )
954                         {
955                                 /* Set the constant link scan time */
956                                 pGroup->ulResponseWaitTime = pGroup->pGroupParameter->usConstantLinkScanTime;
957                         }
958                         else
959                         {
960                                 /* Set the cyclic transmission timeout */
961                                 pGroup->ulResponseWaitTime = pGroup->pGroupParameter->usCyclicTransmissionTimeout;
962                         }
963                         if ( pGroup->ulResponseWaitTime == 0 )
964                         {
965                                 pGroup->ulResponseWaitTime = CCIEF_BASIC_CYCLIC_TRANSMISSION_TIMEOUT;
966                         }
967                         /* Set the master state */
968                         pGroup->iState = CCIEF_BASIC_STATE_MASTER_LINK_SCAN_END;
969                         /* Initialization of the frame sequence number */
970                         pGroup->usFrameSequenceNumber = 0;
971                         /* Execute the state of the master */
972                         ccief_basic_master_execute_state( pGroup, CCIEF_BASIC_EVENT_MASTER_LINK_SCAN_START );
973                         break;
974                 /* Receiving the cyclic data from the master */
975                 case CCIEF_BASIC_EVENT_MASTER_CYCLIC_DATA_RECV:
976                         /* Stop the master persuasion timer*/
977                         timer_stop( pGroup->iPersuasionTimerId );
978                         /* Termination of socket */
979                         socket_terminate( sock );
980                         /* Set the master state */
981                         pGroup->iState = CCIEF_BASIC_STATE_MASTER_WAITING;
982                         /* Set the error code of the master duplication */
983                         Master.iErrCode = CCIEF_BASIC_MASTER_ERR_MASTER_DUPLICATION;
984                         return;
985                 default:
986                         break;
987         }
989         return;
992 /************************************************************************************/
993 /* This is an user defined function for state of end of the link scan.                          */
994 /************************************************************************************/
995 void ccief_basic_master_execute_state_linkscan_end( CCIEF_BASIC_MASTER_GROUP_INFO *pGroup, int iEvent )
997         int     i;
999         /* Check the event */
1000         switch ( iEvent )
1001         {
1002                 /* Changing the parameter */
1003                 case CCIEF_BASIC_EVENT_MASTER_PARAMETER_CHANGE:
1004                         /* Execute the state of the slave */
1005                         for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
1006                         {
1007                                 ccief_basic_slaves_execute_state( pGroup->pSlave[i], CCIEF_BASIC_EVENT_SLAVE_PARAMETER_CHANGE );
1008                         }
1009                         /* Termination of socket */
1010                         socket_terminate( sock );
1011                         /* Set the master state */
1012                         pGroup->iState = CCIEF_BASIC_STATE_MASTER_WAITING;
1013                         break;
1014                 /* Starting the link scan */
1015                 case CCIEF_BASIC_EVENT_MASTER_LINK_SCAN_START:
1016                         /* Execute the state of the slave */
1017                         for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
1018                         {
1019                                 /* Reset the receive complete flag */
1020                                 pGroup->pSlave[i]->iReceiveComplete = CCIEF_BASIC_SLAVE_RESPONSE_NOT_RECEIVED;
1021                                 
1022                                 ccief_basic_slaves_execute_state( pGroup->pSlave[i], CCIEF_BASIC_EVENT_SLAVE_LINK_SCAN_START );
1023                         }
1024                         /* Callback function for notification of end of the link scan to user operation */
1025                         if ( pUserLinkScanEndFunc != NULL )
1026                         {
1027                                 pUserLinkScanEndFunc( pGroup->ucGroupNumber );
1028                         }
1029                         /* Make the request data of Cyclic Data */
1030                         pGroup->iCyclicDataSize = ccief_basic_master_make_cyclic_data( pGroup );
1031                         /* Start the link scan time */
1032                         pGroup->llLinkScanTimeStart = timer_get_time();
1033                         /* Sending Cyclic Data */
1034                         ccief_basic_master_send_cyclic_data( Master.ulDirectedIpAddress, pGroup->aucCyclicData, pGroup->iCyclicDataSize );
1035                         /* Start the timer for cyclic time */
1036                         timer_start( pGroup->ulResponseWaitTime, &pGroup->iCyclicTimerId, &ccief_basic_master_cyclic_timer_timeout, (void *)pGroup );
1037                         /* Set the master state */
1038                         pGroup->iState = CCIEF_BASIC_STATE_MASTER_LINK_SCAN;
1039                         break;
1040                 /* Receiving the cyclic data from the master */
1041                 case CCIEF_BASIC_EVENT_MASTER_CYCLIC_DATA_RECV:
1042                         /* Nothing */
1043                         break;
1044                 /* Receiving the error of the duplication master from the slave */
1045                 case CCIEF_BASIC_EVENT_MASTER_DUPLICATION_ERR_RECV:
1046                         /* Execute the state of the slave */
1047                         for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
1048                         {
1049                                 ccief_basic_slaves_execute_state( pGroup->pSlave[i], CCIEF_BASIC_EVENT_SLAVE_DUPLICATION_MASTER_ERR );
1050                         }
1051                         /* Termination of socket */
1052                         socket_terminate( sock );
1053                         /* Set the master state */
1054                         pGroup->iState = CCIEF_BASIC_STATE_MASTER_WAITING;
1055                         /* Set the error code of the master duplication */
1056                         Master.iErrCode = CCIEF_BASIC_MASTER_ERR_MASTER_DUPLICATION;
1057                         return;
1058                 default:
1059                         break;
1060         }
1062         return;
1065 /************************************************************************************/
1066 /* This is an user defined function for state of running the link scan.                         */
1067 /************************************************************************************/
1068 void ccief_basic_master_execute_state_linkscan( CCIEF_BASIC_MASTER_GROUP_INFO *pGroup, int iEvent )
1070         int     i;
1071         int64_t llLinkScanTimeEnd;
1073         /* Check the event */
1074         switch ( iEvent )
1075         {
1076                 /* Changing the parameter */
1077                 case CCIEF_BASIC_EVENT_MASTER_PARAMETER_CHANGE:
1078                         /* Execute the state of the slave */
1079                         for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
1080                         {
1081                                 ccief_basic_slaves_execute_state( pGroup->pSlave[i], CCIEF_BASIC_EVENT_SLAVE_PARAMETER_CHANGE );
1082                         }
1083                         /* Stop the cyclic timer*/
1084                         timer_stop( pGroup->iCyclicTimerId );
1085                         /* Termination of socket */
1086                         socket_terminate( sock );
1087                         /* Set the master state */
1088                         pGroup->iState = CCIEF_BASIC_STATE_MASTER_WAITING;
1089                         break;
1090                 /* End of the link scan */
1091                 case CCIEF_BASIC_EVENT_MASTER_LINK_SCAN_END:
1092                         /* Stop the cyclic timer*/
1093                         timer_stop( pGroup->iCyclicTimerId );
1094                         /* Stop the link scan time */
1095                         llLinkScanTimeEnd = timer_get_time();
1096                         pGroup->llLinkScanTimeCurrent = llLinkScanTimeEnd - pGroup->llLinkScanTimeStart;
1097                         if (( pGroup->llLinkScanTimeMinimum == 0 ) || ( pGroup->llLinkScanTimeCurrent < pGroup->llLinkScanTimeMinimum ))
1098                         {
1099                                 pGroup->llLinkScanTimeMinimum = pGroup->llLinkScanTimeCurrent;
1100                         }
1101                         if ( pGroup->llLinkScanTimeMaximum < pGroup->llLinkScanTimeCurrent )
1102                         {
1103                                 pGroup->llLinkScanTimeMaximum = pGroup->llLinkScanTimeCurrent;
1104                         }
1105                         pGroup->llLinkScanTimeStart = llLinkScanTimeEnd;
1106                         /* Set the master state */
1107                         pGroup->iState = CCIEF_BASIC_STATE_MASTER_LINK_SCAN_END;
1108                         /* Increasing of th frame sequence number */
1109                         pGroup->usFrameSequenceNumber ++;
1110                         if ( pGroup->usFrameSequenceNumber == 0 )
1111                         {
1112                                 pGroup->usFrameSequenceNumber = 1;
1113                         }
1114                         /* Execute the state of the master */
1115                         ccief_basic_master_execute_state( pGroup, CCIEF_BASIC_EVENT_MASTER_LINK_SCAN_START );
1116                         break;
1117                 /* Receiving the cyclic data from the master */
1118                 case CCIEF_BASIC_EVENT_MASTER_CYCLIC_DATA_RECV:
1119                         /* Nothing */
1120                         break;
1121                 /* Receiving the error of the duplication master from the slave */
1122                 case CCIEF_BASIC_EVENT_MASTER_DUPLICATION_ERR_RECV:
1123                         /* Execute the state of the slave */
1124                         for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
1125                         {
1126                                 ccief_basic_slaves_execute_state( pGroup->pSlave[i], CCIEF_BASIC_EVENT_SLAVE_DUPLICATION_MASTER_ERR );
1127                         }
1128                         /* Stop the cyclic timer*/
1129                         timer_stop( pGroup->iCyclicTimerId );
1130                         /* Termination of socket */
1131                         socket_terminate( sock );
1132                         /* Set the master state */
1133                         pGroup->iState = CCIEF_BASIC_STATE_MASTER_WAITING;
1134                         /* Set the error code of the master duplication */
1135                         Master.iErrCode = CCIEF_BASIC_MASTER_ERR_MASTER_DUPLICATION;
1136                         return;
1137                 default:
1138                         break;
1139         }
1141         return;
1144 /************************************************************************************/
1145 /* This is an user defined function for timeout of the persuasion timer.                        */
1146 /************************************************************************************/
1147 void ccief_basic_master_persuasion_timer_timeout( int iId, void *pCallbackArg )
1149         
1150         /* Execute the state of the master */
1151         ccief_basic_master_execute_state( (CCIEF_BASIC_MASTER_GROUP_INFO *)pCallbackArg, CCIEF_BASIC_EVENT_MASTER_PERSUASION_TIMEOUT );
1153         return;
1156 /************************************************************************************/
1157 /* This is an user defined function for timeout of the cyclic transmission timeout.     */
1158 /************************************************************************************/
1159 void ccief_basic_master_cyclic_timer_timeout( int iId, void *pCallbackArg )
1161         int i;
1162         CCIEF_BASIC_MASTER_GROUP_INFO *pGroup;
1163         
1164         pGroup = (CCIEF_BASIC_MASTER_GROUP_INFO *)pCallbackArg;
1166         /* Execute the state of the slave */
1167         for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
1168         {
1169                 ccief_basic_slaves_execute_state( pGroup->pSlave[i], CCIEF_BASIC_EVENT_SLAVE_CYCLIC_DATA_TIMEOUT );
1170         }
1172         /* Execute the state of the master */
1173         ccief_basic_master_execute_state( pGroup, CCIEF_BASIC_EVENT_MASTER_LINK_SCAN_END );
1175         return;
1178 /************************************************************************************/
1179 /* This is an user defined function for make the request data of Cyclic Data.           */
1180 /************************************************************************************/
1181 #define REQUEST_OFFSET_ADDRESS_CYCLIC_INFO      0x0024
1183 int ccief_basic_master_make_cyclic_data( CCIEF_BASIC_MASTER_GROUP_INFO *pGroup )
1185         uint8_t *pucData;
1186         int iIndex, iIndexCyclicState, iIndexRWw, iIndexRY;
1187         int i, j, iDataSize;
1188         static uint8_t aucCyclicStateBits[2];
1189         int64_t llTimeData;
1190         uint16_t usOccupiedStationNumber;
1192         pucData = pGroup->aucCyclicData;
1194         /* Make the request data of Cyclic Data. */
1195         iIndex = 0;
1196         /* Protocol Version */
1197         pucData[iIndex    ] = SHIFT_R0(CCIEF_BASIC_PROTCOL_VERSION);
1198         pucData[iIndex + 1] = SHIFT_R8(CCIEF_BASIC_PROTCOL_VERSION);
1199         iIndex += 2;
1200         /* Reserve */
1201         pucData[iIndex    ] = SHIFT_R0(0);
1202         pucData[iIndex + 1] = SHIFT_R8(0);
1203         iIndex += 2;
1204         /* Offset address (Cyclic information) */
1205         pucData[iIndex    ] = SHIFT_R0(REQUEST_OFFSET_ADDRESS_CYCLIC_INFO);
1206         pucData[iIndex + 1] = SHIFT_R8(REQUEST_OFFSET_ADDRESS_CYCLIC_INFO);
1207         iIndex += 2;
1208         /* Offset address (Reserved) */
1209         memset( &pucData[iIndex], 0, 14 );
1210         iIndex += 14;
1212         /* Master information data */
1213         /* Unit info */
1214         pucData[iIndex    ] = SHIFT_R0(Master.usUnitInfo);
1215         pucData[iIndex + 1] = SHIFT_R8(Master.usUnitInfo);
1216         iIndex += 2;
1217         /* Reserve */
1218         pucData[iIndex    ] = 0;
1219         pucData[iIndex + 1] = 0;
1220         iIndex += 2;
1221         /* Time data */
1222         llTimeData = timer_calculate_time_data();
1223         memcpy( &pucData[iIndex], &llTimeData, sizeof( llTimeData ) );
1224         pGroup->llTimeData = llTimeData;
1225         iIndex += 8;
1227         /* Cyclic information */
1228         /* Master id */
1229         memcpy( &pucData[iIndex], &Master.ulId, sizeof( Master.ulId ) );
1230         iIndex += 4;
1231         /* Group number */
1232         pucData[iIndex    ] = pGroup->ucGroupNumber;
1233         iIndex += 1;
1234         /* Reserve */
1235         pucData[iIndex    ] = 0;
1236         iIndex += 1;
1237         /* Frame sequence number */
1238         pucData[iIndex    ] = SHIFT_R0(pGroup->usFrameSequenceNumber);
1239         pucData[iIndex + 1] = SHIFT_R8(pGroup->usFrameSequenceNumber);
1240         iIndex += 2;
1241         /* Cyclic Transmission Timeout */
1242         /* Check the constant link scan time */
1243         if ( pGroup->pGroupParameter->usConstantLinkScanTime != 0 )
1244         {
1245                 /* Set the constant link scan time */
1246                 pucData[iIndex    ] = SHIFT_R0(pGroup->pGroupParameter->usConstantLinkScanTime);
1247                 pucData[iIndex + 1] = SHIFT_R8(pGroup->pGroupParameter->usConstantLinkScanTime);
1248         }
1249         else
1250         {
1251                 /* Set the cyclic transmission timeout */
1252                 pucData[iIndex    ] = SHIFT_R0(pGroup->pGroupParameter->usCyclicTransmissionTimeout);
1253                 pucData[iIndex + 1] = SHIFT_R8(pGroup->pGroupParameter->usCyclicTransmissionTimeout);
1254         }
1255         iIndex += 2;
1256         /* Count of cyclic transmission timeout */
1257         pucData[iIndex    ] = SHIFT_R0(pGroup->pGroupParameter->usCyclicTransmissionTimeoutCount);
1258         pucData[iIndex + 1] = SHIFT_R8(pGroup->pGroupParameter->usCyclicTransmissionTimeoutCount);
1259         iIndex += 2;
1260         /* Parameter id */
1261         pucData[iIndex    ] = SHIFT_R0(Master.usParameterId);
1262         pucData[iIndex + 1] = SHIFT_R8(Master.usParameterId);
1263         iIndex += 2;
1264         /* Total occupied station number of the slaves */
1265         pucData[iIndex    ] = SHIFT_R0(pGroup->iOccupiedStationNumberTotal);
1266         pucData[iIndex + 1] = SHIFT_R8(pGroup->iOccupiedStationNumberTotal);
1267         iIndex += 2;
1268         /* State of the cyclic and Slave id */
1269         iIndexCyclicState = iIndex;
1270         memset( &aucCyclicStateBits, 0, sizeof( aucCyclicStateBits ) );
1271         iIndex += 2;
1272         /* Reserve */
1273         pucData[iIndex    ] = 0;
1274         pucData[iIndex + 1] = 0;
1275         iIndex += 2;
1276         for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
1277         {
1278                 /* Make the cyclic insication bits */
1279                 if ( pGroup->pSlave[i]->iCyclicState == CCIEF_BASIC_CYCLIC_STATE_ON )
1280                 {
1281                         aucCyclicStateBits[( pGroup->pSlave[i]->iGroupStationNumber ) / 8] |= ( 1 << ( ( pGroup->pSlave[i]->iGroupStationNumber ) % 8 ));
1282                 }
1283                 /* Check the current start cyclic of user operation */
1284                 if (( pGroup->pSlave[i]->iCyclicStateSet == CCIEF_BASIC_CYCLIC_STATE_SET_CONNECTING )
1285                  || ( pGroup->pSlave[i]->iCyclicStateSet == CCIEF_BASIC_CYCLIC_STATE_SET_CYCLIC ))
1286                 {
1287                         memcpy( &pucData[iIndex], &(pGroup->pSlave[i]->ulId), sizeof( pGroup->pSlave[i]->ulId ) );
1288                 }
1289                 else
1290                 {
1291                         memset( &pucData[iIndex], 0, sizeof( uint32_t ) );
1292                 }
1293                 iIndex += 4;
1294                 /* Occupied station number */
1295                 usOccupiedStationNumber = pGroup->pSlave[i]->pParameter->usOccupiedStationNumber;
1296                 if ( 1 < usOccupiedStationNumber )
1297                 {
1298                         for ( j = 1; j < usOccupiedStationNumber; j ++ )
1299                         {
1300                                 memset( &pucData[iIndex], 0xFF, sizeof( uint32_t ) );
1301                                 iIndex += 4;
1302                         }
1303                 }
1304         }
1305         memcpy( &pucData[iIndexCyclicState], aucCyclicStateBits, sizeof( aucCyclicStateBits ) );
1306         /* Send data */
1307         iIndexRWw = iIndex;
1308         iIndexRY = iIndex + ( CCIEF_BASIC_RWW_RWR_SIZE * pGroup->iOccupiedStationNumberTotal );
1309         for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
1310         {
1311                 /* Get the cyclic insication of the slave */
1312                 usOccupiedStationNumber = pGroup->pSlave[i]->pParameter->usOccupiedStationNumber;
1313                 /* Set data */
1314                 if ( pGroup->pSlave[i]->iCyclicStateSet == CCIEF_BASIC_CYCLIC_STATE_SET_CYCLIC )
1315                 {
1316                         /* Valid the cyclic data */
1317                         memcpy( &pucData[iIndexRWw], pGroup->pSlave[i]->pusRWw,
1318                                         CCIEF_BASIC_RWW_RWR_SIZE * usOccupiedStationNumber );
1319                         memcpy( &pucData[iIndexRY], pGroup->pSlave[i]->pusRY,
1320                                         CCIEF_BASIC_RX_RY_SIZE * usOccupiedStationNumber );
1321                 }
1322                 else
1323                 {
1324                         /* Invalid the cyclic data */
1325                         memset( &pucData[iIndexRWw], 0, CCIEF_BASIC_RWW_RWR_SIZE * usOccupiedStationNumber );
1326                         memset( &pucData[iIndexRY], 0, CCIEF_BASIC_RX_RY_SIZE * usOccupiedStationNumber );
1327                 }
1328                 iIndexRWw += CCIEF_BASIC_RWW_RWR_SIZE * usOccupiedStationNumber;
1329                 iIndexRY += CCIEF_BASIC_RX_RY_SIZE * usOccupiedStationNumber;
1330         }
1332         /* Total length of the making data */
1333         iDataSize = iIndexRY;
1335         return iDataSize;
1338 /************************************************************************************/
1339 /* This is an user defined function for send packet.                                                            */
1340 /************************************************************************************/
1341 int ccief_basic_master_send_cyclic_data( uint32_t ulIpAddress, uint8_t *pucData, int iDataSize )
1343         SLMP_INFO target;       /* SLMP Infomation for sending packet*/
1344         int iSendPacketSize;
1345         int iErrCode = 0;
1347         /* Sets the SLMP Information for sending. */
1348         target.usNetNumber      = 0;                                            /* Network number */
1349         target.usNodeNumber     = 0xFF;                                         /* Node number  */
1350         target.usProcNumber = SLMP_CPU_DEFAULT;                 /* Processor number */
1351         target.usDataLength = (uint16_t)(6 + iDataSize);/* Data length */
1352                                                                                                         /* timer(2)+command(2)+subcommand(2)+Data */
1353         target.usTimer = SLMP_TIMER_WAIT_FOREVER;               /* Timer value */
1354         target.usCommand = SLMP_COMMAND_CYCLIC_DATA;    /* Command = NodeSearch */
1355         target.usSubCommand = 0x0000;                                   /* Sub command */
1356         target.pucData = pucData;                                               /* Pointer for sending data */
1358         /* Make a packet stream using the SLMP library. */
1359         iErrCode = SLMP_MakePacketStream( SLMP_FTYPE_BIN_REQ_ST, &target, aucSendPacket );
1360         if( iErrCode != CCIEF_BASIC_MASTER_ERR_OK )
1361         {
1362                 /* Could not be created. */
1363                 return iErrCode;
1364         }
1366         /* Send the packet for cyclic request. */
1367         iSendPacketSize = 15+iDataSize; /* subheader(2)+network number(1)+node number(1)+processor number(2)+ */
1368                                                                         /* multidrop node number(1)+data length(2)+fixed value(2)+command(2)+subcommand(2)+data */
1369         iErrCode = socket_send( sock, aucSendPacket, iSendPacketSize, ulIpAddress, CCIEF_BASIC_PORT_NUMBER_CYCLIC );
1370         if ( iErrCode != CCIEF_BASIC_MASTER_ERR_OK )
1371         {
1372                 return iErrCode;
1373         }
1375         return CCIEF_BASIC_MASTER_ERR_OK;
1378 /************************************************************************************/
1379 /* This is an user defined function for receiving the response data of Cyclic Data.     */
1380 /************************************************************************************/
1381 #define RESPONSE_OFFSET_ADDRESS_SLAVE_INFO              0x0014
1383 void ccief_basic_master_recv_cyclic_data_response( uint8_t *pucData )
1385         CCIEF_BASIC_MASTER_GROUP_INFO   *pGroup;
1386         uint32_t ulSlaveId;
1387         uint8_t ucGroupNumber;
1388         uint16_t usProtocolVersion;
1389         int i, j, iIndex;
1390         uint16_t usEndCode;
1392         /* Get the protocol version and the group number and the slave id from received data */
1393         usProtocolVersion = SHIFT_L8( pucData[1] ) + SHIFT_L0( pucData[0] );
1394         usEndCode = SHIFT_L8( pucData[3] ) + SHIFT_L0( pucData[2] );
1395         /* Check the end code */
1396         if ( usEndCode == SLMP_END_DUPLICATE_MASTER )
1397         {
1398                 for ( i = 0; i < Master.iGroupTotalNumber; i ++ )
1399                 {
1400                         /* Execute the state of the master */
1401                         ccief_basic_master_execute_state( Master.pGroup[i], CCIEF_BASIC_EVENT_MASTER_DUPLICATION_ERR_RECV );
1402                 }
1404                 return;
1405         }
1406         iIndex = SHIFT_L8( pucData[5] ) + SHIFT_L0( pucData[4]);
1407         memcpy( &ulSlaveId, &pucData[iIndex], sizeof(uint32_t) );
1408         iIndex += 4;
1409         ucGroupNumber = pucData[iIndex];
1411         for ( i = 0; i < Master.iGroupTotalNumber; i ++ )
1412         {
1413                 /* Check the group number */
1414                 if ( Master.pGroup[i]->ucGroupNumber == ucGroupNumber )
1415                 {
1416                         pGroup = Master.pGroup[i];
1418                         for ( j = 0; j < pGroup->iTotalSlaveNumber; j ++ )
1419                         {
1420                                 /* Check the slave id */
1421                                 if ( pGroup->pSlave[j]->ulId == ulSlaveId )
1422                                 {
1423                                         /* Get the information from received data */
1424                                         /* Check the cyclic start of the slave */
1425                                         if ( pGroup->pSlave[j]->iCyclicStart == CCIEF_BASIC_CYCLIC_START )
1426                                         {
1427                                                 /* Get the information from received data */
1428                                                 /* Slave information data */
1429                                                 memcpy( &pGroup->pSlave[j]->NotifyInfo, &pucData[RESPONSE_OFFSET_ADDRESS_SLAVE_INFO],
1430                                                                 sizeof( pGroup->pSlave[j]->NotifyInfo ) );
1432                                                 /* Protocol version */
1433                                                 pGroup->pSlave[j]->usProtocolVersion = usProtocolVersion;
1434                                                 /* End code */
1435                                                 pGroup->pSlave[j]->usEndCode = usEndCode;
1436                                                 /* Frame sequence number */
1437                                                 pGroup->pSlave[j]->usFrameSequenceNumber = SHIFT_L8( pucData[iIndex + 3] ) + SHIFT_L0( pucData[iIndex + 2] );
1438                                                 /* Pointer of RWr */
1439                                                 pGroup->pSlave[j]->pusSlaveRWr = (uint16_t*)&pucData[iIndex + 4];
1440                                                 /* Pointer of RX */
1441                                                 pGroup->pSlave[j]->pusSlaveRX = (uint16_t*)&pucData[iIndex + 4
1442                                                                                                           + ( Master.Parameter.Slave[j].usOccupiedStationNumber * CCIEF_BASIC_RWW_RWR_SIZE )];
1443                                                 /* Execute the state of the slave */
1444                                                 ccief_basic_slaves_execute_state( pGroup->pSlave[j], CCIEF_BASIC_EVENT_SLAVE_CYCLIC_DATA_RECV );
1445                                                 
1446                                                 /* Check the state of slave duplication */
1447                                                 if( pGroup->pSlave[j]->iDuplicateState == CCIEF_BASIC_SLAVE_DUPLICATION_DETECT )
1448                                                 {
1449                                                         Master.iErrCode = CCIEF_BASIC_MASTER_ERR_SLAVE_DUPLICATION;
1450                                                 }
1451                                         }
1452                                 }
1453                         }
1454                 }
1455         }
1457         return;