a0ef65db3760e237b772bbecd88bc7e179972338
[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 = { 0 }; /* SLMP Infomation for received packet */
679         int                             iErrCode = 0;
680         int                             i;
681         char                    Ipaddr[16];
682 #ifdef _WIN32
683 #elif __linux__
684         uint32_t                ulMyNetAddress;
685         uint32_t                ulOtherNetAddress;
686 #endif
688         /* Check the socket */
689         if ( sock == INVALID_SOCKET ) {
690                 return CCIEF_BASIC_MASTER_ERR_OK;
691         }
693         /* Packet receiving */
694         iErrCode = socket_recv( sock, aucRecvPacket, sizeof( aucRecvPacket ), &ulRecvAddr, &usRecvPortNumber );
695         if ( iErrCode != SOCKET_ERR_OK )
696         {
697                 if ( iErrCode == SOCKET_ERR_NO_RECEIVABLE )
698                 {
699                         return CCIEF_BASIC_MASTER_ERR_OK;
700                 }
701                 else
702                 {
703                         return iErrCode;
704                 }
705         }
707 #ifdef _WIN32
708 #elif __linux__
709         ulMyNetAddress = ( Master.ulIpAddress & Master.ulSubnetMask );
710         ulOtherNetAddress = ( ulRecvAddr & Master.ulSubnetMask );
712         /* Other network broadcast break*/
713         if( ulMyNetAddress != ulOtherNetAddress )
714         {
715                 return CCIEF_BASIC_MASTER_ERR_OK;
716         }
717 #endif
720         /* Sets the SLMP Information for receiving. */
721         source.pucData = aucRecvData;
723         /* Get the SLMP Information from the request packet using the SLMP library. */
724         iErrCode = SLMP_GetSlmpInfo( &source, aucRecvPacket );
725         if ( iErrCode != SLMP_ERR_OK )
726         {
727                 /* Invalid SLMP Frame. */
728                 printf( "ERR : Invalid SLMP frame received!\n" );
729                 return CCIEF_BASIC_MASTER_ERR_OK;
730         }
732         /* Check the SLMP frame. */
733         if ( source.ulFrameType == SLMP_FTYPE_BIN_RES_ST )
734         {
735                 /* Response of the SLMP frame */
736                 if ( source.usEndCode == SLMP_ERR_OK )
737                 {
738                         /* Receiving response of the cyclic data. */
739                         ccief_basic_master_recv_cyclic_data_response( source.pucData );
740                 }
741                 else
742                 {
743 #ifdef _WIN32
744                         addr.S_un.S_addr = htonl(ulRecvAddr);
745 #elif __linux__
746                         addr.s_addr = htonl(ulRecvAddr);        
747 #endif
748                         inet_ntop(AF_INET, &addr, Ipaddr, sizeof(Ipaddr) );
749                         printf( "ERR : EndCode %04X from %s!\n", source.usEndCode, Ipaddr );
750                 }
751         }
752         else
753         {
754                 /* Request of the SLMP frame */
755                 if ( source.usCommand == SLMP_COMMAND_CYCLIC_DATA )
756                 {
757                         /* Cyclic Data(0E70h) */
758                         for ( i = 0; i < Master.iGroupTotalNumber; i ++ )
759                         {
760                                 /* Execute the state of the master */
761                                 ccief_basic_master_execute_state( Master.pGroup[i], CCIEF_BASIC_EVENT_MASTER_CYCLIC_DATA_RECV );
762                         }
763                 }
764         }
766         /* Check the error code of the master duplication */
767         if ( Master.iErrCode == CCIEF_BASIC_MASTER_ERR_MASTER_DUPLICATION )
768         {
769                 return CCIEF_BASIC_MASTER_ERR_MASTER_DUPLICATION;
770         }
771         
772         /* Check the error code of the slave duplication */
773         if ( Master.iErrCode == CCIEF_BASIC_MASTER_ERR_SLAVE_DUPLICATION )
774         {
775                 return CCIEF_BASIC_MASTER_ERR_SLAVE_DUPLICATION;
776         }
778         return CCIEF_BASIC_MASTER_ERR_OK;
781 /************************************************************************************/
782 /* This is an user defined function for polling operation.                                                      */
783 /************************************************************************************/
784 int ccief_basic_master_polling( CCIEF_BASIC_MASTER_GROUP_INFO *pGroup )
786         int     i;
787         int iSlaveCyclicStateOffNumber, iSlaveCyclicStateOffCyclicEndNumber;
788         int iSlaveCyclicStateOnNumber, iSlaveCyclicStateOnCyclicEndNumber;
789         int iErrCode = CCIEF_BASIC_MASTER_ERR_OK;
791         /* Check the state of the master */
792         if ( pGroup->iState == CCIEF_BASIC_STATE_MASTER_LINK_SCAN )
793         {
794                 /* Check using the constant link scan */
795                 if ( pGroup->iConstantLinkScanUse == CCIEF_BASIC_CONSTANT_LINK_SCAN_NOT_USE )
796                 {
797                         /* Check the cyclic end of the slave */
798                         iSlaveCyclicStateOffNumber = 0;
799                         iSlaveCyclicStateOffCyclicEndNumber = 0;
800                         iSlaveCyclicStateOnNumber = 0;
801                         iSlaveCyclicStateOnCyclicEndNumber = 0;
802                         for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
803                         {
804                                 if ( pGroup->pSlave[i]->iCyclicState == CCIEF_BASIC_CYCLIC_STATE_OFF )
805                                 {
806                                         /* OFF the slave cyclic state */
807                                         iSlaveCyclicStateOffNumber ++;
808                                         if ( pGroup->pSlave[i]->iState == CCIEF_BASIC_STATE_SLAVE_CYCLIC_END )
809                                         {
810                                                 iSlaveCyclicStateOffCyclicEndNumber ++;
811                                         }
812                                 }
813                                 else
814                                 {
815                                         /* ON the slave cyclic state */
816                                         iSlaveCyclicStateOnNumber ++;
817                                         if ( pGroup->pSlave[i]->iState == CCIEF_BASIC_STATE_SLAVE_CYCLIC_END )
818                                         {
819                                                 iSlaveCyclicStateOnCyclicEndNumber ++;
820                                         }
821                                 }
822                         }
823                         if ((( 0 < iSlaveCyclicStateOnNumber ) && ( iSlaveCyclicStateOnNumber == iSlaveCyclicStateOnCyclicEndNumber ))
824                          || (( 0 == iSlaveCyclicStateOnNumber ) && ( iSlaveCyclicStateOffNumber == iSlaveCyclicStateOffCyclicEndNumber )))
825                         {
826                                 /* End of the cyclic */
827                                 /* Execute the state of the slave */
828                                 for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
829                                 {
830                                         ccief_basic_slaves_execute_state( pGroup->pSlave[i], CCIEF_BASIC_EVENT_SLAVE_CYCLIC_END );
831                                 }
832                                 /* Execute the state of the master */
833                                 ccief_basic_master_execute_state( pGroup, CCIEF_BASIC_EVENT_MASTER_LINK_SCAN_END );
834                         }
835                 }
836         }
838         return iErrCode;
841 /************************************************************************************/
842 /* This is an user defined function for executed according to the state                         */
843 /* of the master.                                                                                                                                       */
844 /************************************************************************************/
845 void ccief_basic_master_execute_state( CCIEF_BASIC_MASTER_GROUP_INFO *pGroup, int iEvent )
847         /* Execute the state of the master */
848         switch ( pGroup->iState )
849         {
850                 /* Waiting for the cyclic operation. */
851                 case CCIEF_BASIC_STATE_MASTER_WAITING:
852                         ccief_basic_master_execute_state_wait_cyclic( pGroup, iEvent );
853                         break;
854                 /* Persuasion of the master. */
855                 case CCIEF_BASIC_STATE_MASTER_PERSUASION:
856                         ccief_basic_master_execute_state_persuasion( pGroup, iEvent );
857                         break;
858                 /* End of the link scan. */
859                 case CCIEF_BASIC_STATE_MASTER_LINK_SCAN_END:
860                         ccief_basic_master_execute_state_linkscan_end( pGroup, iEvent );
861                         break;
862                 /* Running the link scan. */
863                 case CCIEF_BASIC_STATE_MASTER_LINK_SCAN:
864                         ccief_basic_master_execute_state_linkscan( pGroup, iEvent );
865                         break;
866                 default:
867                         break;
868         }
870         return;
873 /************************************************************************************/
874 /* This is an user defined function for state of waiting of the cyclic operation.       */
875 /************************************************************************************/
876 void ccief_basic_master_execute_state_wait_cyclic( CCIEF_BASIC_MASTER_GROUP_INFO *pGroup, int iEvent )
878         /* Check the event */
879         switch ( iEvent )
880         {
881                 /* Getting the parameter */
882                 case CCIEF_BASIC_EVENT_MASTER_PARAMETER_GET:
883                         /* Initialization of the socket */
884                         if ( sock == INVALID_SOCKET )
885                         {
886                                 Master.iErrCode = socket_initialize( &sock, Master.ulIpAddress, CCIEF_BASIC_PORT_NUMBER_CYCLIC );
887                                 if( Master.iErrCode != CCIEF_BASIC_MASTER_ERR_OK )
888                                 {
889                                         return;
890                                 }
891                         }
892                         /* Check constant link scan */
893                         pGroup->iConstantLinkScanUse = CCIEF_BASIC_CONSTANT_LINK_SCAN_NOT_USE;
894                         if ( pGroup->pGroupParameter->usConstantLinkScanTime != 0 )
895                         {
896                                 /* Set waiting of the end of constant link scan */
897                                 pGroup->iConstantLinkScanUse = CCIEF_BASIC_CONSTANT_LINK_SCAN_USE;
898                         }
899                         /* Start the master persuasion timer*/
900                         timer_start( CCIEF_BASIC_MASTER_PERSUASION_TIME, &pGroup->iPersuasionTimerId,
901                                                  &ccief_basic_master_persuasion_timer_timeout, (void *)pGroup );
902                         /* Set the master state */
903                         pGroup->iState = CCIEF_BASIC_STATE_MASTER_PERSUASION;
904                         break;
905                 /* Changing the parameter */
906                 case CCIEF_BASIC_EVENT_MASTER_PARAMETER_CHANGE:
907                         /* Nothing */
908                         break;
909                 default:
910                         break;
911         }
913         return;
916 /************************************************************************************/
917 /* This is an user defined function for state of persuasion of the master.                      */
918 /************************************************************************************/
919 void ccief_basic_master_execute_state_persuasion( CCIEF_BASIC_MASTER_GROUP_INFO *pGroup, int iEvent )
921         int     i;
923         /* Check the event */
924         switch ( iEvent )
925         {
926                 /* Changing the parameter */
927                 case CCIEF_BASIC_EVENT_MASTER_PARAMETER_CHANGE:
928                         /* Execute the state of the slave */
929                         for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
930                         {
931                                 ccief_basic_slaves_execute_state( pGroup->pSlave[i], CCIEF_BASIC_EVENT_SLAVE_PARAMETER_CHANGE );
932                         }
933                         /* Stop the master persuasion timer*/
934                         timer_stop( pGroup->iPersuasionTimerId );
935                         /* Termination of socket */
936                         socket_terminate( sock );
937                         /* Set the master state */
938                         pGroup->iState = CCIEF_BASIC_STATE_MASTER_WAITING;
939                         break;
940                 /* Timeout of monitoring the persuasion frame */
941                 case CCIEF_BASIC_EVENT_MASTER_PERSUASION_TIMEOUT:
942                         /* Check the constant link scan time */
943                         if ( pGroup->pGroupParameter->usConstantLinkScanTime != 0 )
944                         {
945                                 /* Set the constant link scan time */
946                                 pGroup->ulResponseWaitTime = pGroup->pGroupParameter->usConstantLinkScanTime;
947                         }
948                         else
949                         {
950                                 /* Set the cyclic transmission timeout */
951                                 pGroup->ulResponseWaitTime = pGroup->pGroupParameter->usCyclicTransmissionTimeout;
952                         }
953                         if ( pGroup->ulResponseWaitTime == 0 )
954                         {
955                                 pGroup->ulResponseWaitTime = CCIEF_BASIC_CYCLIC_TRANSMISSION_TIMEOUT;
956                         }
957                         /* Set the master state */
958                         pGroup->iState = CCIEF_BASIC_STATE_MASTER_LINK_SCAN_END;
959                         /* Initialization of the frame sequence number */
960                         pGroup->usFrameSequenceNumber = 0;
961                         /* Execute the state of the master */
962                         ccief_basic_master_execute_state( pGroup, CCIEF_BASIC_EVENT_MASTER_LINK_SCAN_START );
963                         break;
964                 /* Receiving the cyclic data from the master */
965                 case CCIEF_BASIC_EVENT_MASTER_CYCLIC_DATA_RECV:
966                         /* Stop the master persuasion timer*/
967                         timer_stop( pGroup->iPersuasionTimerId );
968                         /* Termination of socket */
969                         socket_terminate( sock );
970                         /* Set the master state */
971                         pGroup->iState = CCIEF_BASIC_STATE_MASTER_WAITING;
972                         /* Set the error code of the master duplication */
973                         Master.iErrCode = CCIEF_BASIC_MASTER_ERR_MASTER_DUPLICATION;
974                         return;
975                 default:
976                         break;
977         }
979         return;
982 /************************************************************************************/
983 /* This is an user defined function for state of end of the link scan.                          */
984 /************************************************************************************/
985 void ccief_basic_master_execute_state_linkscan_end( CCIEF_BASIC_MASTER_GROUP_INFO *pGroup, int iEvent )
987         int     i;
989         /* Check the event */
990         switch ( iEvent )
991         {
992                 /* Changing the parameter */
993                 case CCIEF_BASIC_EVENT_MASTER_PARAMETER_CHANGE:
994                         /* Execute the state of the slave */
995                         for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
996                         {
997                                 ccief_basic_slaves_execute_state( pGroup->pSlave[i], CCIEF_BASIC_EVENT_SLAVE_PARAMETER_CHANGE );
998                         }
999                         /* Termination of socket */
1000                         socket_terminate( sock );
1001                         /* Set the master state */
1002                         pGroup->iState = CCIEF_BASIC_STATE_MASTER_WAITING;
1003                         break;
1004                 /* Starting the link scan */
1005                 case CCIEF_BASIC_EVENT_MASTER_LINK_SCAN_START:
1006                         /* Execute the state of the slave */
1007                         for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
1008                         {
1009                                 /* Reset the receive complete flag */
1010                                 pGroup->pSlave[i]->iReceiveComplete = CCIEF_BASIC_SLAVE_RESPONSE_NOT_RECEIVED;
1011                                 
1012                                 ccief_basic_slaves_execute_state( pGroup->pSlave[i], CCIEF_BASIC_EVENT_SLAVE_LINK_SCAN_START );
1013                         }
1014                         /* Callback function for notification of end of the link scan to user operation */
1015                         if ( pUserLinkScanEndFunc != NULL )
1016                         {
1017                                 pUserLinkScanEndFunc( pGroup->ucGroupNumber );
1018                         }
1019                         /* Make the request data of Cyclic Data */
1020                         pGroup->iCyclicDataSize = ccief_basic_master_make_cyclic_data( pGroup );
1021                         /* Start the link scan time */
1022                         pGroup->llLinkScanTimeStart = timer_get_time();
1023                         /* Sending Cyclic Data */
1024                         ccief_basic_master_send_cyclic_data( Master.ulDirectedIpAddress, pGroup->aucCyclicData, pGroup->iCyclicDataSize );
1025                         /* Start the timer for cyclic time */
1026                         timer_start( pGroup->ulResponseWaitTime, &pGroup->iCyclicTimerId, &ccief_basic_master_cyclic_timer_timeout, (void *)pGroup );
1027                         /* Set the master state */
1028                         pGroup->iState = CCIEF_BASIC_STATE_MASTER_LINK_SCAN;
1029                         break;
1030                 /* Receiving the cyclic data from the master */
1031                 case CCIEF_BASIC_EVENT_MASTER_CYCLIC_DATA_RECV:
1032                         /* Nothing */
1033                         break;
1034                 /* Receiving the error of the duplication master from the slave */
1035                 case CCIEF_BASIC_EVENT_MASTER_DUPLICATION_ERR_RECV:
1036                         /* Execute the state of the slave */
1037                         for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
1038                         {
1039                                 ccief_basic_slaves_execute_state( pGroup->pSlave[i], CCIEF_BASIC_EVENT_SLAVE_DUPLICATION_MASTER_ERR );
1040                         }
1041                         /* Termination of socket */
1042                         socket_terminate( sock );
1043                         /* Set the master state */
1044                         pGroup->iState = CCIEF_BASIC_STATE_MASTER_WAITING;
1045                         /* Set the error code of the master duplication */
1046                         Master.iErrCode = CCIEF_BASIC_MASTER_ERR_MASTER_DUPLICATION;
1047                         return;
1048                 default:
1049                         break;
1050         }
1052         return;
1055 /************************************************************************************/
1056 /* This is an user defined function for state of running the link scan.                         */
1057 /************************************************************************************/
1058 void ccief_basic_master_execute_state_linkscan( CCIEF_BASIC_MASTER_GROUP_INFO *pGroup, int iEvent )
1060         int     i;
1061         int64_t llLinkScanTimeEnd;
1063         /* Check the event */
1064         switch ( iEvent )
1065         {
1066                 /* Changing the parameter */
1067                 case CCIEF_BASIC_EVENT_MASTER_PARAMETER_CHANGE:
1068                         /* Execute the state of the slave */
1069                         for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
1070                         {
1071                                 ccief_basic_slaves_execute_state( pGroup->pSlave[i], CCIEF_BASIC_EVENT_SLAVE_PARAMETER_CHANGE );
1072                         }
1073                         /* Stop the cyclic timer*/
1074                         timer_stop( pGroup->iCyclicTimerId );
1075                         /* Termination of socket */
1076                         socket_terminate( sock );
1077                         /* Set the master state */
1078                         pGroup->iState = CCIEF_BASIC_STATE_MASTER_WAITING;
1079                         break;
1080                 /* End of the link scan */
1081                 case CCIEF_BASIC_EVENT_MASTER_LINK_SCAN_END:
1082                         /* Stop the cyclic timer*/
1083                         timer_stop( pGroup->iCyclicTimerId );
1084                         /* Stop the link scan time */
1085                         llLinkScanTimeEnd = timer_get_time();
1086                         pGroup->llLinkScanTimeCurrent = llLinkScanTimeEnd - pGroup->llLinkScanTimeStart;
1087                         if (( pGroup->llLinkScanTimeMinimum == 0 ) || ( pGroup->llLinkScanTimeCurrent < pGroup->llLinkScanTimeMinimum ))
1088                         {
1089                                 pGroup->llLinkScanTimeMinimum = pGroup->llLinkScanTimeCurrent;
1090                         }
1091                         if ( pGroup->llLinkScanTimeMaximum < pGroup->llLinkScanTimeCurrent )
1092                         {
1093                                 pGroup->llLinkScanTimeMaximum = pGroup->llLinkScanTimeCurrent;
1094                         }
1095                         pGroup->llLinkScanTimeStart = llLinkScanTimeEnd;
1096                         /* Set the master state */
1097                         pGroup->iState = CCIEF_BASIC_STATE_MASTER_LINK_SCAN_END;
1098                         /* Increasing of th frame sequence number */
1099                         pGroup->usFrameSequenceNumber ++;
1100                         if ( pGroup->usFrameSequenceNumber == 0 )
1101                         {
1102                                 pGroup->usFrameSequenceNumber = 1;
1103                         }
1104                         /* Execute the state of the master */
1105                         ccief_basic_master_execute_state( pGroup, CCIEF_BASIC_EVENT_MASTER_LINK_SCAN_START );
1106                         break;
1107                 /* Receiving the cyclic data from the master */
1108                 case CCIEF_BASIC_EVENT_MASTER_CYCLIC_DATA_RECV:
1109                         /* Nothing */
1110                         break;
1111                 /* Receiving the error of the duplication master from the slave */
1112                 case CCIEF_BASIC_EVENT_MASTER_DUPLICATION_ERR_RECV:
1113                         /* Execute the state of the slave */
1114                         for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
1115                         {
1116                                 ccief_basic_slaves_execute_state( pGroup->pSlave[i], CCIEF_BASIC_EVENT_SLAVE_DUPLICATION_MASTER_ERR );
1117                         }
1118                         /* Stop the cyclic timer*/
1119                         timer_stop( pGroup->iCyclicTimerId );
1120                         /* Termination of socket */
1121                         socket_terminate( sock );
1122                         /* Set the master state */
1123                         pGroup->iState = CCIEF_BASIC_STATE_MASTER_WAITING;
1124                         /* Set the error code of the master duplication */
1125                         Master.iErrCode = CCIEF_BASIC_MASTER_ERR_MASTER_DUPLICATION;
1126                         return;
1127                 default:
1128                         break;
1129         }
1131         return;
1134 /************************************************************************************/
1135 /* This is an user defined function for timeout of the persuasion timer.                        */
1136 /************************************************************************************/
1137 void ccief_basic_master_persuasion_timer_timeout( int iId, void *pCallbackArg )
1139         
1140         /* Execute the state of the master */
1141         ccief_basic_master_execute_state( (CCIEF_BASIC_MASTER_GROUP_INFO *)pCallbackArg, CCIEF_BASIC_EVENT_MASTER_PERSUASION_TIMEOUT );
1143         return;
1146 /************************************************************************************/
1147 /* This is an user defined function for timeout of the cyclic transmission timeout.     */
1148 /************************************************************************************/
1149 void ccief_basic_master_cyclic_timer_timeout( int iId, void *pCallbackArg )
1151         int i;
1152         CCIEF_BASIC_MASTER_GROUP_INFO *pGroup;
1153         
1154         pGroup = (CCIEF_BASIC_MASTER_GROUP_INFO *)pCallbackArg;
1156         /* Execute the state of the slave */
1157         for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
1158         {
1159                 ccief_basic_slaves_execute_state( pGroup->pSlave[i], CCIEF_BASIC_EVENT_SLAVE_CYCLIC_DATA_TIMEOUT );
1160         }
1162         /* Execute the state of the master */
1163         ccief_basic_master_execute_state( pGroup, CCIEF_BASIC_EVENT_MASTER_LINK_SCAN_END );
1165         return;
1168 /************************************************************************************/
1169 /* This is an user defined function for make the request data of Cyclic Data.           */
1170 /************************************************************************************/
1171 #define REQUEST_OFFSET_ADDRESS_CYCLIC_INFO      0x0024
1173 int ccief_basic_master_make_cyclic_data( CCIEF_BASIC_MASTER_GROUP_INFO *pGroup )
1175         uint8_t *pucData;
1176         int iIndex, iIndexCyclicState, iIndexRWw, iIndexRY;
1177         int i, j, iDataSize;
1178         static uint8_t aucCyclicStateBits[2];
1179         int64_t llTimeData;
1180         uint16_t usOccupiedStationNumber;
1182         pucData = pGroup->aucCyclicData;
1184         /* Make the request data of Cyclic Data. */
1185         iIndex = 0;
1186         /* Protocol Version */
1187         pucData[iIndex    ] = SHIFT_R0(CCIEF_BASIC_PROTCOL_VERSION);
1188         pucData[iIndex + 1] = SHIFT_R8(CCIEF_BASIC_PROTCOL_VERSION);
1189         iIndex += 2;
1190         /* Reserve */
1191         pucData[iIndex    ] = SHIFT_R0(0);
1192         pucData[iIndex + 1] = SHIFT_R8(0);
1193         iIndex += 2;
1194         /* Offset address (Cyclic information) */
1195         pucData[iIndex    ] = SHIFT_R0(REQUEST_OFFSET_ADDRESS_CYCLIC_INFO);
1196         pucData[iIndex + 1] = SHIFT_R8(REQUEST_OFFSET_ADDRESS_CYCLIC_INFO);
1197         iIndex += 2;
1198         /* Offset address (Reserved) */
1199         memset( &pucData[iIndex], 0, 14 );
1200         iIndex += 14;
1202         /* Master information data */
1203         /* Unit info */
1204         pucData[iIndex    ] = SHIFT_R0(Master.usUnitInfo);
1205         pucData[iIndex + 1] = SHIFT_R8(Master.usUnitInfo);
1206         iIndex += 2;
1207         /* Reserve */
1208         pucData[iIndex    ] = 0;
1209         pucData[iIndex + 1] = 0;
1210         iIndex += 2;
1211         /* Time data */
1212         llTimeData = timer_calculate_time_data();
1213         memcpy( &pucData[iIndex], &llTimeData, sizeof( llTimeData ) );
1214         pGroup->llTimeData = llTimeData;
1215         iIndex += 8;
1217         /* Cyclic information */
1218         /* Master id */
1219         memcpy( &pucData[iIndex], &Master.ulId, sizeof( Master.ulId ) );
1220         iIndex += 4;
1221         /* Group number */
1222         pucData[iIndex    ] = pGroup->ucGroupNumber;
1223         iIndex += 1;
1224         /* Reserve */
1225         pucData[iIndex    ] = 0;
1226         iIndex += 1;
1227         /* Frame sequence number */
1228         pucData[iIndex    ] = SHIFT_R0(pGroup->usFrameSequenceNumber);
1229         pucData[iIndex + 1] = SHIFT_R8(pGroup->usFrameSequenceNumber);
1230         iIndex += 2;
1231         /* Cyclic Transmission Timeout */
1232         /* Check the constant link scan time */
1233         if ( pGroup->pGroupParameter->usConstantLinkScanTime != 0 )
1234         {
1235                 /* Set the constant link scan time */
1236                 pucData[iIndex    ] = SHIFT_R0(pGroup->pGroupParameter->usConstantLinkScanTime);
1237                 pucData[iIndex + 1] = SHIFT_R8(pGroup->pGroupParameter->usConstantLinkScanTime);
1238         }
1239         else
1240         {
1241                 /* Set the cyclic transmission timeout */
1242                 pucData[iIndex    ] = SHIFT_R0(pGroup->pGroupParameter->usCyclicTransmissionTimeout);
1243                 pucData[iIndex + 1] = SHIFT_R8(pGroup->pGroupParameter->usCyclicTransmissionTimeout);
1244         }
1245         iIndex += 2;
1246         /* Count of cyclic transmission timeout */
1247         pucData[iIndex    ] = SHIFT_R0(pGroup->pGroupParameter->usCyclicTransmissionTimeoutCount);
1248         pucData[iIndex + 1] = SHIFT_R8(pGroup->pGroupParameter->usCyclicTransmissionTimeoutCount);
1249         iIndex += 2;
1250         /* Parameter id */
1251         pucData[iIndex    ] = SHIFT_R0(Master.usParameterId);
1252         pucData[iIndex + 1] = SHIFT_R8(Master.usParameterId);
1253         iIndex += 2;
1254         /* Total occupied station number of the slaves */
1255         pucData[iIndex    ] = SHIFT_R0(pGroup->iOccupiedStationNumberTotal);
1256         pucData[iIndex + 1] = SHIFT_R8(pGroup->iOccupiedStationNumberTotal);
1257         iIndex += 2;
1258         /* State of the cyclic and Slave id */
1259         iIndexCyclicState = iIndex;
1260         memset( &aucCyclicStateBits, 0, sizeof( aucCyclicStateBits ) );
1261         iIndex += 2;
1262         /* Reserve */
1263         pucData[iIndex    ] = 0;
1264         pucData[iIndex + 1] = 0;
1265         iIndex += 2;
1266         for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
1267         {
1268                 /* Make the cyclic insication bits */
1269                 if ( pGroup->pSlave[i]->iCyclicState == CCIEF_BASIC_CYCLIC_STATE_ON )
1270                 {
1271                         aucCyclicStateBits[( pGroup->pSlave[i]->iGroupStationNumber ) / 8] |= ( 1 << ( ( pGroup->pSlave[i]->iGroupStationNumber ) % 8 ));
1272                 }
1273                 /* Check the current start cyclic of user operation */
1274                 if (( pGroup->pSlave[i]->iCyclicStateSet == CCIEF_BASIC_CYCLIC_STATE_SET_CONNECTING )
1275                  || ( pGroup->pSlave[i]->iCyclicStateSet == CCIEF_BASIC_CYCLIC_STATE_SET_CYCLIC ))
1276                 {
1277                         memcpy( &pucData[iIndex], &(pGroup->pSlave[i]->ulId), sizeof( pGroup->pSlave[i]->ulId ) );
1278                 }
1279                 else
1280                 {
1281                         memset( &pucData[iIndex], 0, sizeof( uint32_t ) );
1282                 }
1283                 iIndex += 4;
1284                 /* Occupied station number */
1285                 usOccupiedStationNumber = pGroup->pSlave[i]->pParameter->usOccupiedStationNumber;
1286                 if ( 1 < usOccupiedStationNumber )
1287                 {
1288                         for ( j = 1; j < usOccupiedStationNumber; j ++ )
1289                         {
1290                                 memset( &pucData[iIndex], 0xFF, sizeof( uint32_t ) );
1291                                 iIndex += 4;
1292                         }
1293                 }
1294         }
1295         memcpy( &pucData[iIndexCyclicState], aucCyclicStateBits, sizeof( aucCyclicStateBits ) );
1296         /* Send data */
1297         iIndexRWw = iIndex;
1298         iIndexRY = iIndex + ( CCIEF_BASIC_RWW_RWR_SIZE * pGroup->iOccupiedStationNumberTotal );
1299         for ( i = 0; i < pGroup->iTotalSlaveNumber; i ++ )
1300         {
1301                 /* Get the cyclic insication of the slave */
1302                 usOccupiedStationNumber = pGroup->pSlave[i]->pParameter->usOccupiedStationNumber;
1303                 /* Set data */
1304                 if ( pGroup->pSlave[i]->iCyclicStateSet == CCIEF_BASIC_CYCLIC_STATE_SET_CYCLIC )
1305                 {
1306                         /* Valid the cyclic data */
1307                         memcpy( &pucData[iIndexRWw], pGroup->pSlave[i]->pusRWw,
1308                                         CCIEF_BASIC_RWW_RWR_SIZE * usOccupiedStationNumber );
1309                         memcpy( &pucData[iIndexRY], pGroup->pSlave[i]->pusRY,
1310                                         CCIEF_BASIC_RX_RY_SIZE * usOccupiedStationNumber );
1311                 }
1312                 else
1313                 {
1314                         /* Invalid the cyclic data */
1315                         memset( &pucData[iIndexRWw], 0, CCIEF_BASIC_RWW_RWR_SIZE * usOccupiedStationNumber );
1316                         memset( &pucData[iIndexRY], 0, CCIEF_BASIC_RX_RY_SIZE * usOccupiedStationNumber );
1317                 }
1318                 iIndexRWw += CCIEF_BASIC_RWW_RWR_SIZE * usOccupiedStationNumber;
1319                 iIndexRY += CCIEF_BASIC_RX_RY_SIZE * usOccupiedStationNumber;
1320         }
1322         /* Total length of the making data */
1323         iDataSize = iIndexRY;
1325         return iDataSize;
1328 /************************************************************************************/
1329 /* This is an user defined function for send packet.                                                            */
1330 /************************************************************************************/
1331 int ccief_basic_master_send_cyclic_data( uint32_t ulIpAddress, uint8_t *pucData, int iDataSize )
1333         SLMP_INFO target;       /* SLMP Infomation for sending packet*/
1334         int iSendPacketSize;
1335         int iErrCode = 0;
1337         /* Sets the SLMP Information for sending. */
1338         target.usNetNumber      = 0;                                            /* Network number */
1339         target.usNodeNumber     = 0xFF;                                         /* Node number  */
1340         target.usProcNumber = SLMP_CPU_DEFAULT;                 /* Processor number */
1341         target.usDataLength = (uint16_t)(6 + iDataSize);/* Data length */
1342                                                                                                         /* timer(2)+command(2)+subcommand(2)+Data */
1343         target.usTimer = SLMP_TIMER_WAIT_FOREVER;               /* Timer value */
1344         target.usCommand = SLMP_COMMAND_CYCLIC_DATA;    /* Command = NodeSearch */
1345         target.usSubCommand = 0x0000;                                   /* Sub command */
1346         target.pucData = pucData;                                               /* Pointer for sending data */
1348         /* Make a packet stream using the SLMP library. */
1349         iErrCode = SLMP_MakePacketStream( SLMP_FTYPE_BIN_REQ_ST, &target, aucSendPacket );
1350         if( iErrCode != CCIEF_BASIC_MASTER_ERR_OK )
1351         {
1352                 /* Could not be created. */
1353                 return iErrCode;
1354         }
1356         /* Send the packet for cyclic request. */
1357         iSendPacketSize = 15+iDataSize; /* subheader(2)+network number(1)+node number(1)+processor number(2)+ */
1358                                                                         /* multidrop node number(1)+data length(2)+fixed value(2)+command(2)+subcommand(2)+data */
1359         iErrCode = socket_send( sock, aucSendPacket, iSendPacketSize, ulIpAddress, CCIEF_BASIC_PORT_NUMBER_CYCLIC );
1360         if ( iErrCode != CCIEF_BASIC_MASTER_ERR_OK )
1361         {
1362                 return iErrCode;
1363         }
1365         return CCIEF_BASIC_MASTER_ERR_OK;
1368 /************************************************************************************/
1369 /* This is an user defined function for receiving the response data of Cyclic Data.     */
1370 /************************************************************************************/
1371 #define RESPONSE_OFFSET_ADDRESS_SLAVE_INFO              0x0014
1373 void ccief_basic_master_recv_cyclic_data_response( uint8_t *pucData )
1375         CCIEF_BASIC_MASTER_GROUP_INFO   *pGroup;
1376         uint32_t ulSlaveId;
1377         uint8_t ucGroupNumber;
1378         uint16_t usProtocolVersion;
1379         int i, j, iIndex;
1380         uint16_t usEndCode;
1382         /* Get the protocol version and the group number and the slave id from received data */
1383         usProtocolVersion = SHIFT_L8( pucData[1] ) + SHIFT_L0( pucData[0] );
1384         usEndCode = SHIFT_L8( pucData[3] ) + SHIFT_L0( pucData[2] );
1385         /* Check the end code */
1386         if ( usEndCode == SLMP_END_DUPLICATE_MASTER )
1387         {
1388                 for ( i = 0; i < Master.iGroupTotalNumber; i ++ )
1389                 {
1390                         /* Execute the state of the master */
1391                         ccief_basic_master_execute_state( Master.pGroup[i], CCIEF_BASIC_EVENT_MASTER_DUPLICATION_ERR_RECV );
1392                 }
1394                 return;
1395         }
1396         iIndex = SHIFT_L8( pucData[5] ) + SHIFT_L0( pucData[4]);
1397         memcpy( &ulSlaveId, &pucData[iIndex], sizeof(uint32_t) );
1398         iIndex += 4;
1399         ucGroupNumber = pucData[iIndex];
1401         for ( i = 0; i < Master.iGroupTotalNumber; i ++ )
1402         {
1403                 /* Check the group number */
1404                 if ( Master.pGroup[i]->ucGroupNumber == ucGroupNumber )
1405                 {
1406                         pGroup = Master.pGroup[i];
1408                         for ( j = 0; j < pGroup->iTotalSlaveNumber; j ++ )
1409                         {
1410                                 /* Check the slave id */
1411                                 if ( pGroup->pSlave[j]->ulId == ulSlaveId )
1412                                 {
1413                                         /* Get the information from received data */
1414                                         /* Check the cyclic start of the slave */
1415                                         if ( pGroup->pSlave[j]->iCyclicStart == CCIEF_BASIC_CYCLIC_START )
1416                                         {
1417                                                 /* Get the information from received data */
1418                                                 /* Slave information data */
1419                                                 memcpy( &pGroup->pSlave[j]->NotifyInfo, &pucData[RESPONSE_OFFSET_ADDRESS_SLAVE_INFO],
1420                                                                 sizeof( pGroup->pSlave[j]->NotifyInfo ) );
1422                                                 /* Protocol version */
1423                                                 pGroup->pSlave[j]->usProtocolVersion = usProtocolVersion;
1424                                                 /* End code */
1425                                                 pGroup->pSlave[j]->usEndCode = usEndCode;
1426                                                 /* Frame sequence number */
1427                                                 pGroup->pSlave[j]->usFrameSequenceNumber = SHIFT_L8( pucData[iIndex + 3] ) + SHIFT_L0( pucData[iIndex + 2] );
1428                                                 /* Pointer of RWr */
1429                                                 pGroup->pSlave[j]->pusSlaveRWr = (uint16_t*)&pucData[iIndex + 4];
1430                                                 /* Pointer of RX */
1431                                                 pGroup->pSlave[j]->pusSlaveRX = (uint16_t*)&pucData[iIndex + 4
1432                                                                                                           + ( Master.Parameter.Slave[j].usOccupiedStationNumber * CCIEF_BASIC_RWW_RWR_SIZE )];
1433                                                 /* Execute the state of the slave */
1434                                                 ccief_basic_slaves_execute_state( pGroup->pSlave[j], CCIEF_BASIC_EVENT_SLAVE_CYCLIC_DATA_RECV );
1435                                                 
1436                                                 /* Check the state of slave duplication */
1437                                                 if( pGroup->pSlave[j]->iDuplicateState == CCIEF_BASIC_SLAVE_DUPLICATION_DETECT )
1438                                                 {
1439                                                         Master.iErrCode = CCIEF_BASIC_MASTER_ERR_SLAVE_DUPLICATION;
1440                                                 }
1441                                         }
1442                                 }
1443                         }
1444                 }
1445         }
1447         return;