Fixed boot command to work with old and new bootloader
[iot-gateway/lighting-gateway.git] / zbSocDriver / zbSocCmd.c
1 /*
2  * zbSocCmd.c
3  *
4  * This module contains the API for the zll SoC Host Interface.
5  *
6  * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ 
7  * 
8  * 
9  *  Redistribution and use in source and binary forms, with or without 
10  *  modification, are permitted provided that the following conditions 
11  *  are met:
12  *
13  *    Redistributions of source code must retain the above copyright 
14  *    notice, this list of conditions and the following disclaimer.
15  *
16  *    Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the 
18  *    documentation and/or other materials provided with the   
19  *    distribution.
20  *
21  *    Neither the name of Texas Instruments Incorporated nor the names of
22  *    its contributors may be used to endorse or promote products derived
23  *    from this software without specific prior written permission.
24  *
25  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
26  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
27  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
29  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
30  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
31  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
34  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
35  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  *
37  */
39 /*********************************************************************
40  * INCLUDES
41  */
42 #include <termios.h>
43 #include <string.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <fcntl.h>
48 #include <sys/ioctl.h>
50 #include <errno.h>
51 #include <string.h>
53 #include "zbSocCmd.h"
55 /*********************************************************************
56  * MACROS
57  */
59 #define APPCMDHEADER(len) \
60 0xFE,                                                                             \
61 len,   /*RPC payload Len                                      */     \
62 0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP        */     \
63 0x00, /*MT_APP_MSG                                                   */     \
64 0x0B, /*Application Endpoint                                  */     \
65 0x02, /*short Addr 0x0002                                     */     \
66 0x00, /*short Addr 0x0002                                     */     \
67 0x0B, /*Dst EP                                                             */     \
68 0xFF, /*Cluster ID 0xFFFF invalid, used for key */     \
69 0xFF, /*Cluster ID 0xFFFF invalid, used for key */     \
71 #define BUILD_UINT16(loByte, hiByte) \
72           ((uint16_t)(((loByte) & 0x00FF) + (((hiByte) & 0x00FF) << 8)))
74 #define BUILD_UINT32(Byte0, Byte1, Byte2, Byte3) \
75           ((uint32_t)((uint32_t)((Byte0) & 0x00FF) \
76           + ((uint32_t)((Byte1) & 0x00FF) << 8) \
77           + ((uint32_t)((Byte2) & 0x00FF) << 16) \
78           + ((uint32_t)((Byte3) & 0x00FF) << 24)))
80 /*********************************************************************
81  * CONSTANTS
82  */
83 #define ZLL_MT_APP_RPC_CMD_TOUCHLINK          0x01
84 #define ZLL_MT_APP_RPC_CMD_RESET_TO_FN        0x02
85 #define ZLL_MT_APP_RPC_CMD_CH_CHANNEL         0x03
86 #define ZLL_MT_APP_RPC_CMD_JOIN_HA            0x04
87 #define ZLL_MT_APP_RPC_CMD_PERMIT_JOIN        0x05
88 #define ZLL_MT_APP_RPC_CMD_SEND_RESET_TO_FN   0x06
89 #define ZLL_MT_APP_RPC_CMD_START_DISTRIB_NWK  0x07
91 #define MT_APP_RSP                           0x80
92 #define MT_APP_ZLL_TL_IND                    0x81
93 #define MT_APP_ZLL_NEW_DEV_IND               0x82
95 #define MT_DEBUG_MSG                         0x80
97 #define COMMAND_LIGHTING_MOVE_TO_HUE                    0x00
98 #define COMMAND_LIGHTING_MOVE_TO_SATURATION 0x03
99 #define COMMAND_LEVEL_MOVE_TO_LEVEL                             0x00
100 #define COMMAND_IDENTIFY                    0x00
101 #define COMMAND_IDENTIFY_TRIGGER_EFFECT     0x40
103 /*** Foundation Command IDs ***/
104 #define ZCL_CMD_READ                                    0x00
105 #define ZCL_CMD_READ_RSP                                0x01
106 #define ZCL_CMD_WRITE                                   0x02
107 #define ZCL_CMD_WRITE_UNDIVIDED                         0x03
108 #define ZCL_CMD_WRITE_RSP                               0x04
109 //ZDO
110 #define MT_ZDO_SIMPLE_DESC_RSP             0x84 
111 #define MT_ZDO_ACTIVE_EP_RSP               0x85 
112 #define MT_ZDO_END_DEVICE_ANNCE_IND          0xC1
113 #define MT_ZDO_LEAVE_IND                     0xC9
115 //UTIL
116 #define MT_UTIL_GET_DEVICE_INFO              0x00
118 // General Clusters
119 #define ZCL_CLUSTER_ID_GEN_BASIC                             0x0000
120 #define ZCL_CLUSTER_ID_GEN_IDENTIFY                          0x0003
121 #define ZCL_CLUSTER_ID_GEN_GROUPS                            0x0004
122 #define ZCL_CLUSTER_ID_GEN_SCENES                            0x0005
123 #define ZCL_CLUSTER_ID_GEN_ON_OFF                            0x0006
124 #define ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL                     0x0008
125 // Lighting Clusters
126 #define ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL                0x0300
128 // Data Types
129 #define ZCL_DATATYPE_BOOLEAN                            0x10
130 #define ZCL_DATATYPE_UINT8                              0x20
131 #define ZCL_DATATYPE_INT16                              0x29
132 #define ZCL_DATATYPE_INT24                              0x2a
133 #define ZCL_DATATYPE_CHAR_STR                           0x42
135 /*******************************/
136 /*** Generic Cluster ATTR's  ***/
137 /*******************************/
138 #define ATTRID_BASIC_MODEL_ID                             0x0005
139 #define ATTRID_ON_OFF                                     0x0000
140 #define ATTRID_LEVEL_CURRENT_LEVEL                        0x0000
142 /*******************************/
143 /*** Lighting Cluster ATTR's  ***/
144 /*******************************/
145 #define ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_HUE         0x0000
146 #define ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_SATURATION  0x0001
148 /*******************************/
149 /*** Scenes Cluster Commands ***/
150 /*******************************/
151 #define COMMAND_SCENE_STORE                               0x04
152 #define COMMAND_SCENE_RECALL                              0x05
154 /*******************************/
155 /*** Groups Cluster Commands ***/
156 /*******************************/
157 #define COMMAND_GROUP_ADD                                 0x00
159 /* The 3 MSB's of the 1st command field byte are for command type. */
160 #define MT_RPC_CMD_TYPE_MASK  0xE0
162 /* The 5 LSB's of the 1st command field byte are for the subsystem. */
163 #define MT_RPC_SUBSYSTEM_MASK 0x1F
165 #define MT_RPC_SOF         0xFE
167 /*******************************/
168 /*** Bootloader Commands ***/
169 /*******************************/
170 #define SB_FORCE_BOOT               0xF8
171 #define SB_FORCE_RUN               (SB_FORCE_BOOT ^ 0xFF)
172 #define SB_FORCE_BOOT_1             0x10
173 #define SB_FORCE_RUN_1             (SB_FORCE_BOOT_1 ^ 0xFF)
176 typedef enum {
177         MT_RPC_CMD_POLL = 0x00,
178         MT_RPC_CMD_SREQ = 0x20,
179         MT_RPC_CMD_AREQ = 0x40,
180         MT_RPC_CMD_SRSP = 0x60,
181         MT_RPC_CMD_RES4 = 0x80,
182         MT_RPC_CMD_RES5 = 0xA0,
183         MT_RPC_CMD_RES6 = 0xC0,
184         MT_RPC_CMD_RES7 = 0xE0
185 } mtRpcCmdType_t;
187 typedef enum {
188         MT_RPC_SYS_RES0, /* Reserved. */
189         MT_RPC_SYS_SYS,
190         MT_RPC_SYS_MAC,
191         MT_RPC_SYS_NWK,
192         MT_RPC_SYS_AF,
193         MT_RPC_SYS_ZDO,
194         MT_RPC_SYS_SAPI, /* Simple API. */
195         MT_RPC_SYS_UTIL,
196         MT_RPC_SYS_DBG,
197         MT_RPC_SYS_APP,
198         MT_RPC_SYS_OTA,
199         MT_RPC_SYS_ZNP,
200         MT_RPC_SYS_SPARE_12,
201         MT_RPC_SYS_UBL = 13, // 13 to be compatible with existing RemoTI.
202         MT_RPC_SYS_MAX // Maximum value, must be last (so 14-32 available, not yet assigned).
203 } mtRpcSysType_t;
205 /************************************************************
206  * TYPEDEFS
207  */
209 /*********************************************************************
210  * GLOBAL VARIABLES
211  */
213 /*********************************************************************
214  * LOCAL VARIABLES
215  */
216 int serialPortFd = 0;
217 uint8_t transSeqNumber = 0;
219 zbSocCallbacks_t zbSocCb;
221 /*********************************************************************
222  * LOCAL FUNCTIONS
223  */
224 void calcFcs(uint8_t *msg, int size);
225 static void processRpcSysAppTlInd(uint8_t *TlIndBuff);
226 static void processRpcSysAppZcl(uint8_t *zclRspBuff);
227 static void processRpcSysAppZclFoundation(uint8_t *zclRspBuff,
228                 uint8_t zclFrameLen, uint16_t clusterID, uint16_t nwkAddr, uint8_t endpoint);
229 static void processRpcSysApp(uint8_t *rpcBuff);
230 static void processRpcSysDbg(uint8_t *rpcBuff);
231 static void zbSocTransportWrite(uint8_t* buf, uint8_t len);
233 /*********************************************************************
234  * @fn      calcFcs
235  *
236  * @brief   populates the Frame Check Sequence of the RPC payload.
237  *
238  * @param   msg - pointer to the RPC message
239  *
240  * @return  none
241  */
242 void calcFcs(uint8_t *msg, int size)
244         uint8_t result = 0;
245         int idx = 1; //skip SOF
246         int len = (size - 1); // skip FCS
248         while ((len--) != 0)
249         {
250                 result ^= msg[idx++];
251         }
253         msg[(size - 1)] = result;
256 /*********************************************************************
257  * API FUNCTIONS
258  */
260 /*********************************************************************
261  * @fn      zbSocOpen
262  *
263  * @brief   opens the serial port to the CC253x.
264  *
265  * @param   devicePath - path to the UART device
266  *
267  * @return  status
268  */
269 int32_t zbSocOpen(char *devicePath)
271         struct termios tio;
273         /* open the device to be non-blocking (read will return immediatly) */
274         serialPortFd = open(devicePath, O_RDWR | O_NOCTTY | O_NONBLOCK);
275         if (serialPortFd < 0)
276         {
277                 perror(devicePath);
278                 printf("%s open failed\n", devicePath);
279                 return (-1);
280         }
282         //make the access exclusive so other instances will return -1 and exit
283         ioctl(serialPortFd, TIOCEXCL);
285         /* c-iflags
286          B115200 : set board rate to 115200
287          CRTSCTS : HW flow control (disabled below)
288          CS8     : 8n1 (8bit,no parity,1 stopbit)
289          CLOCAL  : local connection, no modem contol
290          CREAD   : enable receiving characters*/
291         tio.c_cflag = B38400 | CRTSCTS | CS8 | CLOCAL | CREAD;
292         /* c-iflags
293          ICRNL   : maps 0xD (CR) to 0x10 (LR), we do not want this.
294          IGNPAR  : ignore bits with parity erros, I guess it is
295          better to ignStateore an erronious bit then interprit it incorrectly. */
296         tio.c_iflag = IGNPAR & ~ICRNL;
297         tio.c_oflag = 0;
298         tio.c_lflag = 0;
300         tcflush(serialPortFd, TCIFLUSH);
301         tcsetattr(serialPortFd, TCSANOW, &tio);
303         //Send the bootloader force boot incase we have a bootloader that waits
304         uint8_t forceBoot[] = {SB_FORCE_RUN, SB_FORCE_RUN_1};
305         zbSocTransportWrite(forceBoot, 2);
307         return serialPortFd;
310 void zbSocClose(void)
312         tcflush(serialPortFd, TCOFLUSH);
313         close(serialPortFd);
315         return;
318 /*********************************************************************
319  * @fn      zbSocTransportWrite
320  *
321  * @brief   Write to the the serial port to the CC253x.
322  *
323  * @param   fd - file descriptor of the UART device
324  *
325  * @return  status
326  */
327 static void zbSocTransportWrite(uint8_t* buf, uint8_t len)
329         int remain = len;
330         int offset = 0;
331 #if 1
332         //printf("zbSocTransportWrite : len = %d\n", len);
334         while (remain > 0)
335         {
336                 int sub = (remain >= 8 ? 8 : remain);
337                 //printf("writing %d bytes (offset = %d, remain = %d)\n", sub, offset,
338                 //              remain);
339                 write(serialPortFd, buf + offset, sub);
341                 tcflush(serialPortFd, TCOFLUSH);
342                 usleep(5000);
343                 remain -= 8;
344                 offset += 8;
345         }
346 #else
347         write (serialPortFd, buf, len);
348         tcflush(serialPortFd, TCOFLUSH);
350 #endif
351         return;
354 /*********************************************************************
355  * @fn      zbSocRegisterCallbacks
356  *
357  * @brief   opens the serial port to the CC253x.
358  *
359  * @param   devicePath - path to the UART device
360  *
361  * @return  status
362  */
363 void zbSocRegisterCallbacks(zbSocCallbacks_t zbSocCallbacks)
365         //copy the callback function pointers
366         memcpy(&zbSocCb, &zbSocCallbacks, sizeof(zbSocCallbacks_t));
367         return;
370 /*********************************************************************
371  * @fn      zbSocTouchLink
372  *
373  * @brief   Send the touchLink command to the CC253x.
374  *
375  * @param   none
376  *
377  * @return  none
378  */
379 void zbSocTouchLink(void)
381         uint8_t cmd[] =
382         { APPCMDHEADER(13) 0x06, //Data Len
383                         0x02, //Address Mode
384                         0x00,//2dummy bytes
385                         0x00, ZLL_MT_APP_RPC_CMD_TOUCHLINK, 0x00, //
386                         0x00, //
387                         0x00 //FCS - fill in later
388                         };
390         calcFcs(cmd, sizeof(cmd));
391         zbSocTransportWrite(cmd, sizeof(cmd));
394 /*********************************************************************
395  * @fn      zbSocBridgeStartNwk
396  *
397  * @brief   Send the start network command to the CC253x.
398  *
399  * @param   none
400  *
401  * @return  none
402  */
403 void zbSocBridgeStartNwk(void)
405         uint8_t cmd[] =
406         { APPCMDHEADER(13) 0x06, //Data Len
407                         0x02, //Address Mode
408                         0x00,//2dummy bytes
409                         0x00, ZLL_MT_APP_RPC_CMD_START_DISTRIB_NWK, 0x00, //
410                         0x00, //
411                         0x00 //FCS - fill in later
412                         };
414         calcFcs(cmd, sizeof(cmd));
415         zbSocTransportWrite(cmd, sizeof(cmd));
418 /*********************************************************************
419  * @fn      zbSocResetToFn
420  *
421  * @brief   Send the reset to factory new command to the CC253x.
422  *
423  * @param   none
424  *
425  * @return  none
426  */
427 void zbSocResetToFn(void)
429         uint8_t cmd[] =
430         { APPCMDHEADER(13) 0x06, //Data Len
431                         0x02, //Address Mode
432                         0x00,//2dummy bytes
433                         0x00, ZLL_MT_APP_RPC_CMD_RESET_TO_FN, 0x00, //
434                         0x00, //
435                         0x00 //FCS - fill in later
436                         };
438         calcFcs(cmd, sizeof(cmd));
439         zbSocTransportWrite(cmd, sizeof(cmd));
442 /*********************************************************************
443  * @fn      zbSocSendResetToFn
444  *
445  * @brief   Send the reset to factory new command to a ZLL device.
446  *
447  * @param   none
448  *
449  * @return  none
450  */
451 void zbSocSendResetToFn(void)
453         uint8_t cmd[] =
454         { APPCMDHEADER(13) 0x06, //Data Len
455                         0x02, //Address Mode
456                         0x00,//2dummy bytes
457                         0x00, ZLL_MT_APP_RPC_CMD_SEND_RESET_TO_FN, 0x00, //
458                         0x00, //
459                         0x00 //FCS - fill in later
460                         };
462         calcFcs(cmd, sizeof(cmd));
463         zbSocTransportWrite(cmd, sizeof(cmd));
466 /*********************************************************************
467  * @fn      zbSocOpenNwk
468  *
469  * @brief   Send the open network command to a ZLL device.
470  *
471  * @param   none
472  *
473  * @return  none
474  */
475 void zbSocOpenNwk(uint8_t duration)
477         uint16_t srcNwkAddr = 0xFFFD; //Everyone with RxOnWhenIdle == TRUE
479         uint8_t mgmtPermit[] =
480         { 0xFE, 5, /*RPC payload Len */
481         MT_RPC_CMD_SREQ | MT_RPC_SYS_ZDO,
482         0x36, /*MT_ZDO_MGMT_PERMIT_JOIN_REQ*/
483         afAddrBroadcast, //addr mode
484         (srcNwkAddr & 0x00ff), /*Src Nwk Addr - To send the bind message to*/
485         (srcNwkAddr & 0xff00) >> 8, /*Src Nwk Addr - To send the bind message to*/
486         duration, /*Dst endpoint for the binding*/
487         1, /*trust center significance set*/
488         0x00 //FCS - fill in later
489         };
491         uint8_t localPermit[] =
492         { APPCMDHEADER(13) 0x06, //Data Len
493                         0x02, //Address Mode
494                         0x00,//2dummy bytes
495                         0x00, ZLL_MT_APP_RPC_CMD_PERMIT_JOIN,
496                         duration, //
497                         0x00, //
498                         0x00 //FCS - fill in later
499                         };
501         printf("zbSocOpenNwk: duration %ds\n", duration);
503         calcFcs(localPermit, sizeof(localPermit));
504         zbSocTransportWrite(localPermit, sizeof(localPermit));
506         //wait for message to be consumed
507         usleep(30);
509         calcFcs(mgmtPermit, sizeof(mgmtPermit));
510         zbSocTransportWrite(mgmtPermit, sizeof(mgmtPermit));
513 /*********************************************************************
514  * @fn      zbSocSendIdentify
515  *
516  * @brief   Send identify command to a ZLL light.
517  *
518  * @param   identifyTime - in s.
519  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
520  * @param   endpoint - endpoint of the Light.
521  * @param   addrMode - Unicast or Group cast.
522  *
523  * @return  none
524  */
525 void zbSocSendIdentify(uint16_t identifyTime, uint16_t dstAddr,
526                 uint8_t endpoint, uint8_t addrMode)
528         uint8_t cmd[] =
529         { 0xFE,
530                         13, //RPC payload Len
531                         0x29, //MT_RPC_CMD_AREQ + MT_RPC_SYS_APP
532                         0x00, //MT_APP_MSG
533                         0x0B, //Application Endpoint
534                         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8,
535                         endpoint, //Dst EP
536                         (ZCL_CLUSTER_ID_GEN_IDENTIFY & 0x00ff),
537                         (ZCL_CLUSTER_ID_GEN_IDENTIFY & 0xff00) >> 8, 0x06, //Data Len
538                         addrMode, 0x01, //0x01 ZCL frame control field.  (send to the light cluster only)
539                         transSeqNumber++, COMMAND_IDENTIFY, (identifyTime
540                                         & 0xff), (identifyTime & 0xff00) >> 8, 0x00 //FCS - fill in later
541                         };
543         calcFcs(cmd, sizeof(cmd));
545         zbSocTransportWrite(cmd, sizeof(cmd));
547         printf("zbSocSendIdentify: dstAddr=%x, endpoint=%x, addrMode=%x, identifyTime=%x\n",
548                         dstAddr, endpoint, addrMode, identifyTime);
551 /*********************************************************************
552  * @fn      COMMAND_IDENTIFY_TRIGGER_EFFECT
553  *
554  * @brief   Send identify command to a ZLL light.
555  *
556  * @param   effect - effect.
557  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
558  * @param   endpoint - endpoint of the Light.
559  * @param   addrMode - Unicast or Group cast.
560  *
561  * @return  none
562  */
563 void zbSocSendIdentifyEffect(uint8_t effect, uint8_t effectVarient, uint16_t dstAddr,
564                 uint8_t endpoint, uint8_t addrMode)
566         uint8_t cmd[] =
567         { 0xFE,
568                         13, //RPC payload Len
569                         0x29, //MT_RPC_CMD_AREQ + MT_RPC_SYS_APP
570                         0x00, //MT_APP_MSG
571                         0x0B, //Application Endpoint
572                         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8,
573                         endpoint, //Dst EP
574                         (ZCL_CLUSTER_ID_GEN_IDENTIFY & 0x00ff),
575                         (ZCL_CLUSTER_ID_GEN_IDENTIFY & 0xff00) >> 8, 0x06, //Data Len
576                         addrMode, 0x01, //0x01 ZCL frame control field.  (send to the light cluster only)
577                         transSeqNumber++, COMMAND_IDENTIFY_TRIGGER_EFFECT, effect,
578                         effectVarient, 0x00 //FCS - fill in later
579                         };
581         calcFcs(cmd, sizeof(cmd));
583         zbSocTransportWrite(cmd, sizeof(cmd));
585         printf("zbSocSendIdentify: dstAddr=%x, endpoint=%x, addrMode=%x, effect=%x\n",
586                         dstAddr, endpoint, addrMode, effect);
589 /*********************************************************************
590  * @fn      zbSocSetState
591  *
592  * @brief   Send the on/off command to a ZLL light.
593  *
594  * @param   state - 0: Off, 1: On.
595  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
596  * @param   endpoint - endpoint of the Light.
597  * @param   addrMode - Unicast or Group cast.
598  *
599  * @return  none
600  */
601 void zbSocSetState(uint8_t state, uint16_t dstAddr, uint8_t endpoint,
602                 uint8_t addrMode)
604         uint8_t cmd[] =
605         { 0xFE, 11, /*RPC payload Len */
606         0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
607         0x00, /*MT_APP_MSG  */
608         0x0B, /*Application Endpoint */
609         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8, endpoint, /*Dst EP */
610         (ZCL_CLUSTER_ID_GEN_ON_OFF & 0x00ff), (ZCL_CLUSTER_ID_GEN_ON_OFF & 0xff00)
611                         >> 8, 0x04, //Data Len
612                         addrMode, 0x01, //0x01 ZCL frame control field.  (send to the light cluster only)
613                         transSeqNumber++, (state ? 1 : 0), 0x00 //FCS - fill in later
614                         };
616         calcFcs(cmd, sizeof(cmd));
617         zbSocTransportWrite(cmd, sizeof(cmd));
620 /*********************************************************************
621  * @fn      zbSocSetLevel
622  *
623  * @brief   Send the level command to a ZLL light.
624  *
625  * @param   level - 0-128 = 0-100%
626  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
627  * @param   endpoint - endpoint of the Light.
628  * @param   addrMode - Unicast or Group cast.
629  *
630  * @return  none
631  */
632 void zbSocSetLevel(uint8_t level, uint16_t time, uint16_t dstAddr,
633                 uint8_t endpoint, uint8_t addrMode)
635         uint8_t cmd[] =
636         { 0xFE,
637                         14, //RPC payload Len
638                         0x29, //MT_RPC_CMD_AREQ + MT_RPC_SYS_APP
639                         0x00, //MT_APP_MSG
640                         0x0B, //Application Endpoint
641                         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8,
642                         endpoint, //Dst EP
643                         (ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL & 0x00ff),
644                         (ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL & 0xff00) >> 8, 0x07, //Data Len
645                         addrMode, 0x01, //0x01 ZCL frame control field.  (send to the light cluster only)
646                         transSeqNumber++, COMMAND_LEVEL_MOVE_TO_LEVEL, (level & 0xff), (time
647                                         & 0xff), (time & 0xff00) >> 8, 0x00 //FCS - fill in later
648                         };
650         calcFcs(cmd, sizeof(cmd));
652         zbSocTransportWrite(cmd, sizeof(cmd));
654         printf("zbSocSetLevel: dstAddr=%x, endpoint=%x, addrMode=%x, level=%x\n",
655                         dstAddr, endpoint, addrMode, level);
658 /*********************************************************************
659  * @fn      zbSocSetHue
660  *
661  * @brief   Send the hue command to a ZLL light.
662  *
663  * @param   hue - 0-128 represent the 360Deg hue color wheel : 0=red, 42=blue, 85=green  
664  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
665  * @param   endpoint - endpoint of the Light.
666  * @param   addrMode - Unicast or Group cast.
667  *
668  * @return  none
669  */
670 void zbSocSetHue(uint8_t hue, uint16_t time, uint16_t dstAddr, uint8_t endpoint,
671                 uint8_t addrMode)
673         uint8_t cmd[] =
674         { 0xFE,
675                         15, //RPC payload Len
676                         0x29, //MT_RPC_CMD_AREQ + MT_RPC_SYS_APP
677                         0x00, //MT_APP_MSG
678                         0x0B, //Application Endpoint
679                         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8,
680                         endpoint, //Dst EP
681                         (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0x00ff),
682                         (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0xff00) >> 8, 0x08, //Data Len
683                         addrMode, 0x01, //0x01 ZCL frame control field.  (send to the light cluster only)
684                         transSeqNumber++, COMMAND_LIGHTING_MOVE_TO_HUE, (hue & 0xff), 0x00, //Move with shortest distance
685                         (time & 0xff), (time & 0xff00) >> 8, 0x00 //FCS - fill in later
686                         };
688         calcFcs(cmd, sizeof(cmd));
689         zbSocTransportWrite(cmd, sizeof(cmd));
692 /*********************************************************************
693  * @fn      zbSocSetSat
694  *
695  * @brief   Send the satuartion command to a ZLL light.
696  *
697  * @param   sat - 0-128 : 0=white, 128: fully saturated color  
698  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
699  * @param   endpoint - endpoint of the Light.
700  * @param   addrMode - Unicast or Group cast.
701  *
702  * @return  none
703  */
704 void zbSocSetSat(uint8_t sat, uint16_t time, uint16_t dstAddr, uint8_t endpoint,
705                 uint8_t addrMode)
707         uint8_t cmd[] =
708         { 0xFE,
709                         14, //RPC payload Len
710                         0x29, //MT_RPC_CMD_AREQ + MT_RPC_SYS_APP
711                         0x00, //MT_APP_MSG
712                         0x0B, //Application Endpoint
713                         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8,
714                         endpoint, //Dst EP
715                         (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0x00ff),
716                         (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0xff00) >> 8, 0x07, //Data Len
717                         addrMode, 0x01, //0x01 ZCL frame control field.  (send to the light cluster only)
718                         transSeqNumber++, COMMAND_LIGHTING_MOVE_TO_SATURATION, (sat & 0xff), (time
719                                         & 0xff), (time & 0xff00) >> 8, 0x00 //FCS - fill in later
720                         };
722         calcFcs(cmd, sizeof(cmd));
723         zbSocTransportWrite(cmd, sizeof(cmd));
726 /*********************************************************************
727  * @fn      zbSocSetHueSat
728  *
729  * @brief   Send the hue and satuartion command to a ZLL light.
730  *
731  * @param   hue - 0-128 represent the 360Deg hue color wheel : 0=red, 42=blue, 85=green  
732  * @param   sat - 0-128 : 0=white, 128: fully saturated color  
733  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
734  * @param   endpoint - endpoint of the Light.
735  * @param   addrMode - Unicast or Group cast.
736  *
737  * @return  none
738  */
739 void zbSocSetHueSat(uint8_t hue, uint8_t sat, uint16_t time, uint16_t dstAddr,
740                 uint8_t endpoint, uint8_t addrMode)
742         uint8_t cmd[] =
743         { 0xFE,
744                         15, //RPC payload Len
745                         0x29, //MT_RPC_CMD_AREQ + MT_RPC_SYS_APP
746                         0x00, //MT_APP_MSG
747                         0x0B, //Application Endpoint
748                         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8,
749                         endpoint, //Dst EP
750                         (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0x00ff),
751                         (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0xff00) >> 8, 0x08, //Data Len
752                         addrMode, 0x01, //ZCL Header Frame Control
753                         transSeqNumber++, 0x06, //ZCL Header Frame Command (COMMAND_LEVEL_MOVE_TO_HUE_AND_SAT)
754                         hue, //HUE - fill it in later
755                         sat, //SAT - fill it in later
756                         (time & 0xff), (time & 0xff00) >> 8, 0x00 //fcs
757                         };
759         calcFcs(cmd, sizeof(cmd));
760         zbSocTransportWrite(cmd, sizeof(cmd));
763 /*********************************************************************
764  * @fn      zbSocAddGroup
765  *
766  * @brief   Add Group.
767  *
768  * @param   groupId - Group ID of the Scene.
769  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
770  * @param   endpoint - endpoint of the Light.
771  * @param   addrMode - Unicast or Group cast. 
772  *
773  * @return  none
774  */
775 void zbSocAddGroup(uint16_t groupId, uint16_t dstAddr, uint8_t endpoint,
776                 uint8_t addrMode)
778         uint8_t cmd[] =
779         { 0xFE, 14, /*RPC payload Len */
780         0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
781         0x00, /*MT_APP_MSG  */
782         0x0B, /*Application Endpoint */
783         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8, endpoint, /*Dst EP */
784         (ZCL_CLUSTER_ID_GEN_GROUPS & 0x00ff), (ZCL_CLUSTER_ID_GEN_GROUPS & 0xff00)
785                         >> 8,
786                         0x07, //Data Len
787                         addrMode,
788                         0x01, //0x01 ZCL frame control field.  (send to the light cluster only)
789                         transSeqNumber++, COMMAND_GROUP_ADD, (groupId & 0x00ff),
790                         (groupId & 0xff00) >> 8, 0, //Null group name - Group Name not pushed to the devices
791                         0x00 //FCS - fill in later
792                         };
794         printf("zbSocAddGroup: dstAddr 0x%x\n", dstAddr);
796         calcFcs(cmd, sizeof(cmd));
797         zbSocTransportWrite(cmd, sizeof(cmd));
800 /*********************************************************************
801  * @fn      zbSocStoreScene
802  *
803  * @brief   Store Scene.
804  * 
805  * @param   groupId - Group ID of the Scene.
806  * @param   sceneId - Scene ID of the Scene.
807  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be controled.
808  * @param   endpoint - endpoint of the Light.
809  * @param   addrMode - Unicast or Group cast. 
810  *
811  * @return  none
812  */
813 void zbSocStoreScene(uint16_t groupId, uint8_t sceneId, uint16_t dstAddr,
814                 uint8_t endpoint, uint8_t addrMode)
816         uint8_t cmd[] =
817         { 0xFE, 14, /*RPC payload Len */
818         0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
819         0x00, /*MT_APP_MSG  */
820         0x0B, /*Application Endpoint */
821         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8, endpoint, /*Dst EP */
822         (ZCL_CLUSTER_ID_GEN_SCENES & 0x00ff), (ZCL_CLUSTER_ID_GEN_SCENES & 0xff00)
823                         >> 8, 0x07, //Data Len
824                         addrMode, 0x01, //0x01 ZCL frame control field.  (send to the light cluster only)
825                         transSeqNumber++, COMMAND_SCENE_STORE, (groupId & 0x00ff), (groupId
826                                         & 0xff00) >> 8, sceneId++, 0x00 //FCS - fill in later
827                         };
829         calcFcs(cmd, sizeof(cmd));
830         zbSocTransportWrite(cmd, sizeof(cmd));
833 /*********************************************************************
834  * @fn      zbSocRecallScene
835  *
836  * @brief   Recall Scene.
837  *
838  * @param   groupId - Group ID of the Scene.
839  * @param   sceneId - Scene ID of the Scene.
840  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be controled. 
841  * @param   endpoint - endpoint of the Light.
842  * @param   addrMode - Unicast or Group cast. 
843  
844  * @return  none
845  */
846 void zbSocRecallScene(uint16_t groupId, uint8_t sceneId, uint16_t dstAddr,
847                 uint8_t endpoint, uint8_t addrMode)
849         uint8_t cmd[] =
850         { 0xFE, 14, /*RPC payload Len */
851         0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
852         0x00, /*MT_APP_MSG  */
853         0x0B, /*Application Endpoint */
854         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8, endpoint, /*Dst EP */
855         (ZCL_CLUSTER_ID_GEN_SCENES & 0x00ff), (ZCL_CLUSTER_ID_GEN_SCENES & 0xff00)
856                         >> 8, 0x07, //Data Len
857                         addrMode, 0x01, //0x01 ZCL frame control field.  (send to the light cluster only)
858                         transSeqNumber++, COMMAND_SCENE_RECALL, (groupId & 0x00ff), (groupId
859                                         & 0xff00) >> 8, sceneId++, 0x00 //FCS - fill in later
860                         };
862         calcFcs(cmd, sizeof(cmd));
863         zbSocTransportWrite(cmd, sizeof(cmd));
866 /*********************************************************************
867  * @fn      zbSocBind
868  *
869  * @brief   Recall Scene.
870  *
871  * @param   
872  *
873  * @return  none
874  */
875 void zbSocBind(uint16_t srcNwkAddr, uint8_t srcEndpoint, uint8_t srcIEEE[8],
876                 uint8_t dstEndpoint, uint8_t dstIEEE[8], uint16_t clusterID)
878         uint8_t cmd[] =
879         { 0xFE, 23, /*RPC payload Len */
880         MT_RPC_CMD_SREQ | MT_RPC_SYS_ZDO,
881         0x21, /*MT_ZDO_BIND_REQ*/
882         (srcNwkAddr & 0x00ff), /*Src Nwk Addr - To send the bind message to*/
883         (srcNwkAddr & 0xff00) >> 8, /*Src Nwk Addr - To send the bind message to*/
884         srcIEEE[0], /*Src IEEE Addr for the binding*/
885         srcIEEE[1], /*Src IEEE Addr for the binding*/
886         srcIEEE[2], /*Src IEEE Addr for the binding*/
887         srcIEEE[3], /*Src IEEE Addr for the binding*/
888         srcIEEE[4], /*Src IEEE Addr for the binding*/
889         srcIEEE[5], /*Src IEEE Addr for the binding*/
890         srcIEEE[6], /*Src IEEE Addr for the binding*/
891         srcIEEE[7], /*Src IEEE Addr for the binding*/
892         srcEndpoint, /*Src endpoint for the binding*/
893         (clusterID & 0x00ff), /*cluster ID to bind*/
894         (clusterID & 0xff00) >> 8, /*cluster ID to bind*/
895         afAddr64Bit, /*Addr mode of the dst to bind*/
896         dstIEEE[0], /*Dst IEEE Addr for the binding*/
897         dstIEEE[1], /*Dst IEEE Addr for the binding*/
898         dstIEEE[2], /*Dst IEEE Addr for the binding*/
899         dstIEEE[3], /*Dst IEEE Addr for the binding*/
900         dstIEEE[4], /*Dst IEEE Addr for the binding*/
901         dstIEEE[5], /*Dst IEEE Addr for the binding*/
902         dstIEEE[6], /*Dst IEEE Addr for the binding*/
903         dstIEEE[7], /*Dst IEEE Addr for the binding*/
904         dstEndpoint, /*Dst endpoint for the binding*/
905         0x00 //FCS - fill in later
906                         };
908         /*printf("zbSocBind: srcNwkAddr=0x%x, srcEndpoint=0x%x, srcIEEE=0x%x:%x:%x:%x:%x:%x:%x:%x, dstEndpoint=0x%x, dstIEEE=0x%x:%x:%x:%x:%x:%x:%x:%x, clusterID:%x\n",
909          srcNwkAddr, srcEndpoint, srcIEEE[0], srcIEEE[1], srcIEEE[2], srcIEEE[3], srcIEEE[4], srcIEEE[5], srcIEEE[6], srcIEEE[7],
910          srcEndpoint, dstIEEE[0], dstIEEE[1], dstIEEE[2], dstIEEE[3], dstIEEE[4], dstIEEE[5], dstIEEE[6], dstIEEE[7], clusterID);*/
912         calcFcs(cmd, sizeof(cmd));
913         zbSocTransportWrite(cmd, sizeof(cmd));
916 void zbSocGetInfo(void)
918         uint8_t cmd[] =
919         { 0xFE, 0, /*RPC payload Len */
920         MT_RPC_CMD_SREQ | MT_RPC_SYS_UTIL,
921         MT_UTIL_GET_DEVICE_INFO,
922         0x00 //FCS - fill in later
923         };
925         //printf("zbSocGetInfo++ \n");
927         calcFcs(cmd, sizeof(cmd));
928         zbSocTransportWrite(cmd, sizeof(cmd));
931 /*********************************************************************
932  * @fn      zbSocGetState
933  *
934  * @brief   Send the get state command to a ZLL light.
935  *
936  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be sent the command.
937  * @param   endpoint - endpoint of the Light.
938  * @param   addrMode - Unicast or Group cast.
939  *
940  * @return  none
941  */
942 void zbSocGetState(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
944         uint8_t cmd[] =
945         { 0xFE, 13, /*RPC payload Len */
946         0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
947         0x00, /*MT_APP_MSG  */
948         0x0B, /*Application Endpoint */
949         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8, endpoint, /*Dst EP */
950         (ZCL_CLUSTER_ID_GEN_ON_OFF & 0x00ff), (ZCL_CLUSTER_ID_GEN_ON_OFF & 0xff00)
951                         >> 8, 0x06, //Data Len
952                         addrMode, 0x00, //0x00 ZCL frame control field.  not specific to a cluster (i.e. a SCL founadation command)
953                         transSeqNumber++, ZCL_CMD_READ, (ATTRID_ON_OFF & 0x00ff), (ATTRID_ON_OFF
954                                         & 0xff00) >> 8, 0x00 //FCS - fill in later
955                         };
957         calcFcs(cmd, sizeof(cmd));
958         zbSocTransportWrite(cmd, sizeof(cmd));
961 /*********************************************************************
962  * @fn      zbSocGetLevel
963  *
964  * @brief   Send the get level command to a ZLL light.
965  *
966  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be sent the command.
967  * @param   endpoint - endpoint of the Light.
968  * @param   addrMode - Unicast or Group cast.
969  *
970  * @return  none
971  */
972 void zbSocGetLevel(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
974         uint8_t cmd[] =
975         { 0xFE, 13, /*RPC payload Len */
976         0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
977         0x00, /*MT_APP_MSG  */
978         0x0B, /*Application Endpoint */
979         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8, endpoint, /*Dst EP */
980         (ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL & 0x00ff), (ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL
981                         & 0xff00) >> 8,
982                         0x06, //Data Len
983                         addrMode,
984                         0x00, //0x00 ZCL frame control field.  not specific to a cluster (i.e. a SCL founadation command)
985                         transSeqNumber++, ZCL_CMD_READ, (ATTRID_LEVEL_CURRENT_LEVEL & 0x00ff),
986                         (ATTRID_LEVEL_CURRENT_LEVEL & 0xff00) >> 8, 0x00 //FCS - fill in later
987                         };
989         calcFcs(cmd, sizeof(cmd));
990         zbSocTransportWrite(cmd, sizeof(cmd));
993 /*********************************************************************
994  * @fn      zbSocGetHue
995  *
996  * @brief   Send the get hue command to a ZLL light.
997  *
998  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be sent the command.
999  * @param   endpoint - endpoint of the Light.
1000  * @param   addrMode - Unicast or Group cast.
1001  *
1002  * @return  none
1003  */
1004 void zbSocGetHue(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
1006         uint8_t cmd[] =
1007         { 0xFE, 13, /*RPC payload Len */
1008         0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
1009         0x00, /*MT_APP_MSG  */
1010         0x0B, /*Application Endpoint */
1011         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8, endpoint, /*Dst EP */
1012         (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0x00ff),
1013                         (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0xff00) >> 8,
1014                         0x06, //Data Len
1015                         addrMode,
1016                         0x00, //0x00 ZCL frame control field.  not specific to a cluster (i.e. a SCL founadation command)
1017                         transSeqNumber++, ZCL_CMD_READ, (ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_HUE
1018                                         & 0x00ff), (ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_HUE & 0xff00) >> 8,
1019                         0x00 //FCS - fill in later
1020                         };
1022         calcFcs(cmd, sizeof(cmd));
1023         zbSocTransportWrite(cmd, sizeof(cmd));
1026 /*********************************************************************
1027  * @fn      zbSocGetSat
1028  *
1029  * @brief   Send the get saturation command to a ZLL light.
1030  *
1031  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be sent the command.
1032  * @param   endpoint - endpoint of the Light.
1033  * @param   addrMode - Unicast or Group cast.
1034  *
1035  * @return  none
1036  */
1037 void zbSocGetSat(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
1039         uint8_t cmd[] =
1040         { 0xFE, 13, /*RPC payload Len */
1041         0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
1042         0x00, /*MT_APP_MSG  */
1043         0x0B, /*Application Endpoint */
1044         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8, endpoint, /*Dst EP */
1045         (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0x00ff),
1046                         (ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL & 0xff00) >> 8,
1047                         0x06, //Data Len
1048                         addrMode,
1049                         0x00, //0x00 ZCL frame control field.  not specific to a cluster (i.e. a SCL founadation command)
1050                         transSeqNumber++, ZCL_CMD_READ,
1051                         (ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_SATURATION & 0x00ff),
1052                         (ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_SATURATION & 0xff00) >> 8, 0x00 //FCS - fill in later
1053                         };
1055         calcFcs(cmd, sizeof(cmd));
1056         zbSocTransportWrite(cmd, sizeof(cmd));
1059 /*********************************************************************
1060  * @fn      zbSocGetModel
1061  *
1062  * @brief   Send the get saturation command to a ZLL light.
1063  *
1064  * @param   dstAddr - Nwk Addr or Group ID of the Light(s) to be sent the command.
1065  * @param   endpoint - endpoint of the Light.
1066  * @param   addrMode - Unicast or Group cast.
1067  *
1068  * @return  none
1069  */
1070 void zbSocGetModel(uint16_t dstAddr, uint8_t endpoint, uint8_t addrMode)
1072         uint8_t cmd[] =
1073         { 0xFE, 13, /*RPC payload Len */
1074         0x29, /*MT_RPC_CMD_AREQ + MT_RPC_SYS_APP */
1075         0x00, /*MT_APP_MSG  */
1076         0x0B, /*Application Endpoint */
1077         (dstAddr & 0x00ff), (dstAddr & 0xff00) >> 8, endpoint, /*Dst EP */
1078         (ZCL_CLUSTER_ID_GEN_BASIC & 0x00ff),
1079                         (ZCL_CLUSTER_ID_GEN_BASIC & 0xff00) >> 8,
1080                         0x06, //Data Len
1081                         addrMode,
1082                         0x00, //0x00 ZCL frame control field.  not specific to a cluster (i.e. a SCL foundation command)
1083                         transSeqNumber++, ZCL_CMD_READ,
1084                         (ATTRID_BASIC_MODEL_ID & 0x00ff),
1085                         (ATTRID_BASIC_MODEL_ID & 0xff00) >> 8,
1086                         0x00 //FCS - fill in later
1087                         };
1089         //printf("zbSocGetModel: dstAddr:%x, endpoint:%x, addrMode:%x\n", dstAddr, endpoint, addrMode);
1091         calcFcs(cmd, sizeof(cmd));
1092         zbSocTransportWrite(cmd, sizeof(cmd));
1095 /*************************************************************************************************
1096  * @fn      processRpcSysAppTlInd()
1097  *
1098  * @brief  process the TL Indication from the ZLL controller
1099  *
1100  * @param   none
1101  *
1102  * @return  length of current Rx Buffer
1103  *************************************************************************************************/
1104 static void processRpcSysAppTlInd(uint8_t *TlIndBuff)
1106         epInfo_t epInfo;
1108         epInfo.nwkAddr = BUILD_UINT16(TlIndBuff[0], TlIndBuff[1]);
1109         TlIndBuff += 2;
1110         epInfo.endpoint = *TlIndBuff++;
1111         epInfo.profileID = BUILD_UINT16(TlIndBuff[0], TlIndBuff[1]);
1112         TlIndBuff += 2;
1113         epInfo.deviceID = BUILD_UINT16(TlIndBuff[0], TlIndBuff[1]);
1114         TlIndBuff += 2;
1115         epInfo.version = *TlIndBuff++;
1116         epInfo.status = *TlIndBuff++;
1118         if (zbSocCb.pfnTlIndicationCb)
1119         {
1120                 zbSocCb.pfnTlIndicationCb(&epInfo);
1121         }
1124 /*************************************************************************************************
1125  * @fn      processRpcSysAppZcl()
1126  *
1127  * @brief  process the ZCL Rsp from the ZLL controller
1128  *
1129  * @param   none
1130  *
1131  * @return  length of current Rx Buffer
1132  *************************************************************************************************/
1133 static void processRpcSysAppZcl(uint8_t *zclRspBuff)
1135         uint8_t zclHdrLen = 3;
1136         uint16_t nwkAddr, clusterID;
1137         uint8_t endpoint, zclFrameLen, zclFrameFrameControl;
1139         //printf("processRpcSysAppZcl++\n");
1141         //This is a ZCL response
1143         //Index past app EP
1144         zclRspBuff++;
1145         nwkAddr = BUILD_UINT16(zclRspBuff[0], zclRspBuff[1]);
1146         zclRspBuff += 2;
1148         endpoint = *zclRspBuff++;
1149         clusterID = BUILD_UINT16(zclRspBuff[0], zclRspBuff[1]);
1150         zclRspBuff += 2;
1152         zclFrameLen = *zclRspBuff++;
1153         zclFrameFrameControl = *zclRspBuff++;
1154         //is it manufacturer specific
1155         if (zclFrameFrameControl & (1 << 2))
1156         {
1157                 //currently not supported shown for reference
1158                 uint16_t ManSpecCode;
1159                 //manu spec code
1160                 ManSpecCode = BUILD_UINT16(zclRspBuff[0], zclRspBuff[1]);
1161                 zclRspBuff += 2;
1162                 //Manufacturer specif commands have 2 extra byte in te header
1163                 zclHdrLen += 2;
1165                 //supress warning
1166                 (void)ManSpecCode;
1167         }
1169         //is this a foundation command
1170         if ((zclFrameFrameControl & 0x3) == 0)
1171         {
1172                 //printf("processRpcSysAppZcl: Foundation messagex\n");
1173                 processRpcSysAppZclFoundation(zclRspBuff, zclFrameLen, clusterID, nwkAddr,
1174                                 endpoint);
1175         }
1178 /*************************************************************************************************
1179  * @fn      processRpcSysAppZclFoundation()
1180  *
1181  * @brief  process the ZCL Rsp from the ZLL controller
1182  *
1183  * @param   none
1184  *
1185  * @return  length of current Rx Buffer
1186  *************************************************************************************************/
1187 static void processRpcSysAppZclFoundation(uint8_t *zclRspBuff,
1188                 uint8_t zclFrameLen, uint16_t clusterID, uint16_t nwkAddr, uint8_t endpoint)
1190         uint8_t transSeqNum, commandID;
1192         transSeqNum = *zclRspBuff++;
1193         commandID = *zclRspBuff++;
1195         if (commandID == ZCL_CMD_READ_RSP)
1196         {
1197                 uint16_t attrID;
1198                 uint8_t status;
1199                 uint8_t dataType;
1201                 attrID = BUILD_UINT16(zclRspBuff[0], zclRspBuff[1]);
1202                 zclRspBuff += 2;
1203                 status = *zclRspBuff++;
1204                 //get data type;
1205                 dataType = *zclRspBuff++;
1207                 //printf("processRpcSysAppZclFoundation: clusterID:%x, attrID:%x, dataType=%x\n", clusterID, attrID, dataType);
1208                 if ((clusterID == ZCL_CLUSTER_ID_GEN_BASIC) && (attrID == ATTRID_BASIC_MODEL_ID)
1209                                 && (dataType == ZCL_DATATYPE_CHAR_STR))
1210                 {
1211                         if (zbSocCb.pfnZclGetModelCb)
1212                         {
1213                                 zbSocCb.pfnZclGetModelCb(&zclRspBuff[0]);
1214                         }
1215                 }
1216                 else if ((clusterID == ZCL_CLUSTER_ID_GEN_ON_OFF) && (attrID == ATTRID_ON_OFF)
1217                                 && (dataType == ZCL_DATATYPE_BOOLEAN))
1218                 {
1219                         if (zbSocCb.pfnZclGetStateCb)
1220                         {
1221                                 uint8_t state = zclRspBuff[0];
1222                                 zbSocCb.pfnZclGetStateCb(state, nwkAddr, endpoint);
1223                         }
1224                 }
1225                 else if ((clusterID == ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL)
1226                                 && (attrID == ATTRID_LEVEL_CURRENT_LEVEL)
1227                                 && (dataType == ZCL_DATATYPE_UINT8))
1228                 {
1229                         if (zbSocCb.pfnZclGetLevelCb)
1230                         {
1231                                 uint8_t level = zclRspBuff[0];
1232                                 zbSocCb.pfnZclGetLevelCb(level, nwkAddr, endpoint);
1233                         }
1234                 }
1235                 else if ((clusterID == ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL)
1236                                 && (attrID == ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_HUE)
1237                                 && (dataType == ZCL_DATATYPE_UINT8))
1238                 {
1239                         if (zbSocCb.pfnZclGetHueCb)
1240                         {
1241                                 uint8_t hue = zclRspBuff[0];
1242                                 zbSocCb.pfnZclGetHueCb(hue, nwkAddr, endpoint);
1243                         }
1244                 }
1245                 else if ((clusterID == ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL)
1246                                 && (attrID == ATTRID_LIGHTING_COLOR_CONTROL_CURRENT_SATURATION)
1247                                 && (dataType == ZCL_DATATYPE_UINT8))
1248                 {
1249                         if (zbSocCb.pfnZclGetSatCb)
1250                         {
1251                                 uint8_t sat = zclRspBuff[0];
1252                                 zbSocCb.pfnZclGetSatCb(sat, nwkAddr, endpoint);
1253                         }
1254                 }
1255                 else
1256                 {
1257                         //unsupported ZCL Read Rsp
1258                         printf("processRpcSysAppZclFoundation: Unsupported ZCL Rsp\n");
1259                 }
1260         }
1261         else
1262         {
1263                 //unsupported ZCL Rsp
1264                 printf("processRpcSysAppZclFoundation: Unsupported ZCL Rsp");
1265                 ;
1266         }
1268         return;
1271 /*************************************************************************************************
1272  * @fn      processRpcSysZdoEndDeviceAnnceInd
1273  *
1274  * @brief   read and process the RPC ZDO message from the ZLL controller
1275  *
1276  * @param   none
1277  *
1278  * @return  length of current Rx Buffer
1279  *************************************************************************************************/
1280 void processRpcSysZdoEndDeviceAnnceInd(uint8_t *EndDeviceAnnceIndBuff)
1282         epInfo_t epInfo =       { 0 };
1283         uint8_t i;
1285         EndDeviceAnnceIndBuff += 2;
1286         epInfo.nwkAddr =
1287                         BUILD_UINT16(EndDeviceAnnceIndBuff[0], EndDeviceAnnceIndBuff[1]);
1288         EndDeviceAnnceIndBuff += 2;
1290         printf("processRpcSysZdoEndDeviceAnnceInd nwkAddr: %x, IEEE Addr: ",
1291                         epInfo.nwkAddr);
1293         for (i = 0; i < 8; i++)
1294         {
1295                 epInfo.IEEEAddr[i] = *EndDeviceAnnceIndBuff++;
1296                 printf("%x", epInfo.IEEEAddr[i]);
1297                 if (i < 7) printf(":");
1298         }
1299         printf("\n");
1301         if (zbSocCb.pfnNewDevIndicationCb)
1302         {
1303                 zbSocCb.pfnNewDevIndicationCb(&epInfo);
1304         }
1308 /*************************************************************************************************
1309  * @fn      processRpcSysZdoActiveEPRsp
1310  *
1311  * @brief   read and process the RPC ZDO message from the ZLL controller
1312  *
1313  * @param   none
1314  *
1315  * @return  length of current Rx Buffer
1316  *************************************************************************************************/
1317 void processRpcSysZdoActiveEPRsp(uint8_t *ActiveEPRspBuff)
1319         uint16_t nwkAddr;
1320         uint8_t epCount;
1322         nwkAddr = BUILD_UINT16(ActiveEPRspBuff[0], ActiveEPRspBuff[1]);
1323         ActiveEPRspBuff += 2;
1324         epCount = *ActiveEPRspBuff;
1326         printf("processRpcSysZdoActiveEPRsp nwkAddr: %x, Num Ep's: %d\n", nwkAddr,
1327                         epCount);
1329         //Can be used to check all Ep's have associated ZdoSimpleDesc.
1332 /*************************************************************************************************
1333  * @fn      processRpcSysZdoSimpleDescRsp
1334  *
1335  * @brief   read and process the RPC ZDO message from the ZLL controller
1336  *
1337  * @param   none
1338  *
1339  * @return  length of current Rx Buffer
1340  *************************************************************************************************/
1341 void processRpcSysZdoSimpleDescRsp(uint8_t *SimpleDescRspBuff)
1343         epInfo_t epInfo;
1344         uint8_t numInputClusters, numOutputClusters, clusterIdx;
1345         uint16_t  *inClusters, *outClusters;
1347         SimpleDescRspBuff += 2; //src address
1348         epInfo.status = *SimpleDescRspBuff++; //status..offset 2
1349         epInfo.nwkAddr = BUILD_UINT16(SimpleDescRspBuff[0], SimpleDescRspBuff[1]); //network address
1350         SimpleDescRspBuff += 2; //increment
1351         //printf("processRpcSysZdoSimpleDescRsp: Length:%x \n",SimpleDescRspBuff[0]  );
1352         SimpleDescRspBuff += 1;
1353         epInfo.endpoint = *SimpleDescRspBuff++; //end point
1354         epInfo.profileID = BUILD_UINT16(SimpleDescRspBuff[0], SimpleDescRspBuff[1]); //profile id
1355         SimpleDescRspBuff += 2;
1356         epInfo.deviceID = BUILD_UINT16(SimpleDescRspBuff[0], SimpleDescRspBuff[1]); //device id
1357         SimpleDescRspBuff += 2;
1358         epInfo.version = *SimpleDescRspBuff++;
1359         // epInfo.status = *TlIndBuff++;
1360         epInfo.deviceName = NULL;
1362         printf("processRpcSysZdoSimpleDescRsp: nwkAddr:%x endpoint:%x\n",  epInfo.nwkAddr, epInfo.endpoint);
1364         numInputClusters = *SimpleDescRspBuff++;
1365         inClusters = (uint16_t*) malloc(2*numInputClusters);
1366         if(inClusters)
1367         {
1368                 printf("processRpcSysZdoSimpleDescRsp: inClusters[%d]:\n",  numInputClusters);
1369                 for(clusterIdx = 0; clusterIdx < numInputClusters; clusterIdx++)
1370                 {
1371                         inClusters[clusterIdx] = BUILD_UINT16(SimpleDescRspBuff[0], SimpleDescRspBuff[1]); //profile id
1372                         SimpleDescRspBuff += 2;
1373                         printf("0x%x ", inClusters[clusterIdx]);
1374                 }
1375         }
1376         printf("\n");
1378         numOutputClusters = *SimpleDescRspBuff++;
1379         outClusters = (uint16_t*) malloc(2*numOutputClusters);
1380         if(outClusters)
1381         {
1382                 printf("processRpcSysZdoSimpleDescRsp: outClusters[%d]:\n",  numOutputClusters);
1383                 for(clusterIdx = 0; clusterIdx < numOutputClusters; clusterIdx++)
1384                 {
1385                         outClusters[clusterIdx] = BUILD_UINT16(SimpleDescRspBuff[0], SimpleDescRspBuff[1]); //profile id
1386                         SimpleDescRspBuff += 2;
1387                         printf("0x%x ", outClusters[clusterIdx]);
1388                 }
1389         }
1390         printf("\n");
1392         //if this is the TL endpoint then ignore it
1393         if( !((numInputClusters == 1) && (numOutputClusters == 1) && (epInfo.profileID) == (0xC05E)) )
1394         {
1395                 if (zbSocCb.pfnZdoSimpleDescRspCb)
1396                 {
1397                         zbSocCb.pfnZdoSimpleDescRspCb(&epInfo);
1398                 }
1399         }
1401         if(inClusters)
1402         {
1403                 free(inClusters);
1404         }
1405         if(outClusters)
1406         {
1407                 free(outClusters);
1408         }
1411 void processRpcSysZdoLeaveInd(uint8_t *LeaveIndRspBuff)
1413         uint16_t nwkAddr;
1415         nwkAddr = BUILD_UINT16(LeaveIndRspBuff[0], LeaveIndRspBuff[1]);
1416         LeaveIndRspBuff += 2;
1418         printf("processRpcSysZdoLeaveInd nwkAddr: %x\n", nwkAddr);
1420         if (zbSocCb.pfnZdoLeaveIndCb)
1421         {
1422                 zbSocCb.pfnZdoLeaveIndCb(nwkAddr);
1423         }
1426 void processRpcUtilGetDevInfoRsp(uint8_t *GetDevInfoRsp)
1428         uint8_t ieeeAddr[8], ieeeIdx, devType, devState, status;
1429         uint16_t nwkAddr;
1431         status = *GetDevInfoRsp++;
1433         if(status == 0)
1434         {
1435                 for(ieeeIdx = 0; ieeeIdx < 8; ieeeIdx++)
1436                 {
1437                         ieeeAddr[ieeeIdx] = *GetDevInfoRsp++;
1438                 }
1440                 nwkAddr = BUILD_UINT16(GetDevInfoRsp[0], GetDevInfoRsp[1]);
1441                 GetDevInfoRsp += 2;
1443                 devType = *GetDevInfoRsp++;
1445                 devState = *GetDevInfoRsp++;
1447                 //printf("processRpcUtilGetDevInfoRsp: status:%x devState:%x, nwkAddr:%x ieeeIdx:%x:%x:%x:%x:%x:%x:%x:%x\n", status, devState, nwkAddr,
1448                 //              ieeeAddr[7], ieeeAddr[6], ieeeAddr[5], ieeeAddr[4], ieeeAddr[3], ieeeAddr[2], ieeeAddr[1], ieeeAddr[0]);
1449         }
1451         if (zbSocCb.pfnUtilGetDevInfoRsp)
1452         {
1453                 zbSocCb.pfnUtilGetDevInfoRsp(status, nwkAddr, ieeeAddr, devType, devState);
1454         }
1457 /*************************************************************************************************
1458  * @fn      processRpcSysApp()
1459  *
1460  * @brief   read and process the RPC App message from the ZLL controller
1461  *
1462  * @param   none
1463  *
1464  * @return  length of current Rx Buffer
1465  *************************************************************************************************/
1466 static void processRpcSysApp(uint8_t *rpcBuff)
1468         if (rpcBuff[1] == MT_APP_ZLL_TL_IND)
1469         {
1470                 processRpcSysAppTlInd(&rpcBuff[2]);
1471         }
1473         else if (rpcBuff[1] == MT_APP_RSP)
1474         {
1475                 processRpcSysAppZcl(&rpcBuff[2]);
1476         }
1477         else if (rpcBuff[1] == 0)
1478         {
1479                 if (rpcBuff[2] == 0)
1480                 {
1481                         //printf("processRpcSysApp: Command Received Successfully\n\n");
1482                 }
1483                 else
1484                 {
1485                         printf("processRpcSysApp: Command Error\n\n");
1486                 }
1487         }
1488         else
1489         {
1490                 printf("processRpcSysApp: Unsupported MT App Msg\n");
1491         }
1493         return;
1496 /*************************************************************************************************
1497  * @fn      processRpcSysZdo()
1498  *
1499  * @brief   read and process the RPC ZDO messages from the ZLL controller
1500  *
1501  * @param   none
1502  *
1503  * @return  length of current Rx Buffer
1504  *************************************************************************************************/
1505 void processRpcSysZdo(uint8_t *rpcBuff)
1507         if (rpcBuff[1] == MT_ZDO_END_DEVICE_ANNCE_IND)
1508         {
1509                 processRpcSysZdoEndDeviceAnnceInd(&rpcBuff[2]);
1510         }
1511         else if (rpcBuff[1] == MT_ZDO_ACTIVE_EP_RSP)
1512         {
1513                 processRpcSysZdoActiveEPRsp(&rpcBuff[2]);
1514         }
1515         else if (rpcBuff[1] == MT_ZDO_SIMPLE_DESC_RSP)
1516         {
1517                 processRpcSysZdoSimpleDescRsp(&rpcBuff[2]);
1518         }
1519         else if (rpcBuff[1] == MT_ZDO_LEAVE_IND)
1520         {
1521                 processRpcSysZdoLeaveInd(&rpcBuff[2]);
1522         }
1523         else
1524         {
1525                 //printf("processRpcSysZdo: Unsupported MT ZDO Msg\n");
1526         }
1528         return;
1532 /*************************************************************************************************
1533  * @fn      processRpcSysUtil()
1534  *
1535  * @brief   read and process the RPC UTIL messages from the ZLL controller
1536  *
1537  * @param   none
1538  *
1539  * @return  length of current Rx Buffer
1540  *************************************************************************************************/
1541 void processRpcSysUtil(uint8_t *rpcBuff)
1543         if (rpcBuff[1] == MT_UTIL_GET_DEVICE_INFO)
1544         {
1545                 processRpcUtilGetDevInfoRsp(&rpcBuff[2]);
1546         }
1547         else
1548         {
1549                 printf("processRpcSysUtil: Unsupported MT UTIL Msg\n");
1550         }
1552         return;
1556 /* @fn      processRpcSysDbg()
1557  *
1558  * @brief   read and process the RPC debug message from the ZLL controller
1559  *
1560  * @param   none
1561  *
1562  * @return  length of current Rx Buffer
1563  *************************************************************************************************/
1564 static void processRpcSysDbg(uint8_t *rpcBuff)
1566         if (rpcBuff[1] == MT_DEBUG_MSG)
1567         {
1568                 //we got a debug string
1569                 printf("lcd_debug message from zll controller: %s\n",
1570                                 (char*) &(rpcBuff[2]));
1571         }
1572         else if (rpcBuff[1] == 0)
1573         {
1574                 if (rpcBuff[2] == 0)
1575                 {
1576                         //printf("processRpcSysDbg: Command Received Successfully\n\n");
1577                 }
1578                 else
1579                 {
1580                         printf("processRpcSysDbg: Command Error\n\n");
1581                 }
1582         }
1583         else
1584         {
1585                 printf("processRpcSysDbg: Unsupported MT App Msg\n");
1586         }
1589 /*************************************************************************************************
1590  * @fn      zbSocProcessRpc()
1591  *
1592  * @brief   read and process the RPC from the ZLL controller
1593  *
1594  * @param   none
1595  *
1596  * @return  length of current Rx Buffer
1597  *************************************************************************************************/
1598 void zbSocProcessRpc(void)
1600         uint8_t rpcLen, bytesRead, sofByte, *rpcBuff, rpcBuffIdx;
1601         static uint8_t retryAttempts = 0;
1603         //read first byte and check it is a SOF
1604         read(serialPortFd, &sofByte, 1);
1605         if (sofByte == MT_RPC_SOF)
1606         {
1607                 retryAttempts = 0;
1609                 //read len
1610                 bytesRead = read(serialPortFd, &rpcLen, 1);
1612                 if (bytesRead == 1)
1613                 {
1614                         //allocating RPC payload (+ cmd0, cmd1 and fcs)
1615                         rpcLen += 3;
1617                         rpcBuff = malloc(rpcLen);
1619                         //non blocking read, so we need to wait for the rpc to be read
1620                         rpcBuffIdx = 0;
1621                         while (rpcLen > 0)
1622                         {
1623                                 //read rpc
1624                                 bytesRead = read(serialPortFd, &(rpcBuff[rpcBuffIdx]), rpcLen);
1626                                 //check for error
1627                                 if (bytesRead > rpcLen)
1628                                 {
1629                                         //there was an error
1630                                         printf("zbSocProcessRpc: read of %d bytes failed - %s\n", rpcLen,
1631                                                         strerror(errno));
1633                                         if (retryAttempts++ < 5)
1634                                         {
1635                                                 //sleep for 10ms
1636                                                 usleep(10000);
1637                                                 //try again
1638                                                 bytesRead = 0;
1639                                         }
1640                                         else
1641                                         {
1642                                                 //something went wrong.
1643                                                 printf("zbSocProcessRpc: failed\n");
1644                                                 free(rpcBuff);
1645                                                 return;
1646                                         }
1647                                 }
1649                                 rpcLen -= bytesRead;
1650                                 rpcBuffIdx += bytesRead;
1651                         }
1653                         //printf("zbSocProcessRpc: Processing CMD0:%x, CMD1:%x\n", rpcBuff[0],
1654                         //              rpcBuff[1]);
1655                         //Read CMD0
1656                         switch (rpcBuff[0] & MT_RPC_SUBSYSTEM_MASK)
1657                         {
1658                                 case MT_RPC_SYS_DBG:
1659                                 {
1660                                         processRpcSysDbg(rpcBuff);
1661                                         break;
1662                                 }
1663                                 case MT_RPC_SYS_APP:
1664                                 {
1665                                         processRpcSysApp(rpcBuff);
1666                                         break;
1667                                 }
1669                                 case MT_RPC_SYS_ZDO:
1670                                 {
1671                                         processRpcSysZdo(rpcBuff);
1672                                         break;
1673                                 }
1675                                 case MT_RPC_SYS_UTIL:
1676                                 {
1677                                         processRpcSysUtil(rpcBuff);
1678                                         break;
1679                                 }
1681                                 default:
1682                                 {
1683                                         //printf("zbSocProcessRpc: CMD0:%x, CMD1:%x, not handled\n", rpcBuff[0] , rpcBuff[1])
1684                                         break;
1685                                 }
1686                         }
1688                         free(rpcBuff);
1689                 }
1690                 else
1691                 {
1692                         printf("zbSocProcessRpc: No valid Start Of Frame found\n");
1693                 }
1694         }
1696         return;