/**************************************************************************** * apps/ieee802154/coord/coord_main.c * * Copyright (C) 2014-2015 Gregory Nutt. All rights reserved. * Copyright (C) 2014-2015 Sebastien Lorquet. All rights reserved. * Author: Sebastien Lorquet * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name NuttX nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************/ /* Application description * * The coordinator is a central node in any IEEE 802.15.4 wireless network. * It listens for clients and dispatches short addresses. It stores data from * source clients and makes it available to destination clients. * Also, in beacon enabled networks, it broadcasts beacons frames and * manages guaranteed time slots. * On non-beacon enabled networks, it sends a beacon only when a beacon * request is received. * * This coordinator is generic. It does not interpret the contents of data * frames. It only interprets command frames to manage client associations * and data dispatch. * * There is no support for mesh networking (coord/coord traffic and packet * forwarding). * * There is no support either for data security (yet). */ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include "ieee802154/ieee802154.h" /**************************************************************************** * Definitions ****************************************************************************/ #ifndef CONFIG_IEEE802154_COORD_MAXCLIENTS #define CONFIG_IEEE802154_COORD_MAXCLIENTS 8 #endif /**************************************************************************** * Private Types ****************************************************************************/ struct ieee_client_s { uint8_t eaddr[8]; /* client extended address */ uint8_t saddr[2]; /* client short address */ struct ieee802154_packet_s pending; /* pending packet for device */ }; struct ieee_frame_s { struct ieee802154_packet_s packet; struct ieee802154_addr_s dest; struct ieee802154_addr_s src; uint8_t seq; uint8_t plen; uint8_t *payload; }; struct ieee_coord_s { int fd; /* Device handle */ uint8_t chan; /* PAN channel */ struct ieee802154_addr_s addr; /* coord own address */ uint8_t nclients; /* Number of coordinated clients */ struct ieee_frame_s rxbuf; /* General rx buffer */ struct ieee_frame_s txbuf; /* General tx buffer */ struct ieee_client_s clients[CONFIG_IEEE802154_COORD_MAXCLIENTS]; uint8_t macBSN; }; /**************************************************************************** * Private Data ****************************************************************************/ static struct ieee_coord_s g_coord; /**************************************************************************** * coord_beacon ****************************************************************************/ static int coord_beacon(FAR struct ieee_coord_s *coord) { FAR struct ieee_frame_s *rx = &coord->rxbuf; printf("Beacon!\n"); return 0; } /**************************************************************************** * coord_data ****************************************************************************/ static int coord_data(FAR struct ieee_coord_s *coord) { printf("Data!\n"); return 0; } /**************************************************************************** * coord_ack ****************************************************************************/ static int coord_ack(FAR struct ieee_coord_s *coord) { printf("Ack!\n"); return 0; } /**************************************************************************** * coord_command_beacon_req ****************************************************************************/ static int coord_command_beacon_req(FAR struct ieee_coord_s *coord) { FAR struct ieee_frame_s *rx = &coord->rxbuf; FAR struct ieee802154_packet_s *tx = &coord->txbuf.packet; int i; printf("Beacon request\n"); /* check command */ /* build response */ tx->len = 0; /* frame control */ tx->data[tx->len++] = 0x00; /* beacon, no ack */ tx->data[tx->len++] = 0x00; /* updated later */ /* seq */ tx->data[tx->len++] = coord->macBSN; coord->macBSN++; /* adressing */ tx->len = ieee802154_addrstore(tx, NULL, &coord->addr); /* superframe spec */ tx->data[tx->len++] = 0xff; tx->data[tx->len++] = 0xcf; /* GTS fields */ tx->data[tx->len++] = 0x00; /* pending addresses */ tx->data[tx->len++] = 0x00; /* payload */ tx->data[tx->len++] = 'F'; tx->data[tx->len++] = '4'; tx->data[tx->len++] = 'G'; tx->data[tx->len++] = 'R'; tx->data[tx->len++] = 'X'; tx->data[tx->len++] = '/'; tx->data[tx->len++] = '0'; printf("Beacon: "); for(i=0;ilen;i++) printf("%02X", tx->data[i]); printf("\n"); return write(coord->fd, tx, sizeof(struct ieee802154_packet_s)); } /**************************************************************************** * coord_command ****************************************************************************/ static int coord_command(FAR struct ieee_coord_s *coord) { FAR struct ieee_frame_s *rx = &coord->rxbuf; uint8_t cmd = rx->payload[0]; printf("Command %02X!\n",cmd); switch(cmd) { case IEEE802154_CMD_ASSOC_REQ : break; case IEEE802154_CMD_ASSOC_RSP : break; case IEEE802154_CMD_DIS_NOT : break; case IEEE802154_CMD_DATA_REQ : break; case IEEE802154_CMD_PANID_CONF_NOT : break; case IEEE802154_CMD_ORPHAN_NOT : break; case IEEE802154_CMD_BEACON_REQ : return coord_command_beacon_req(coord); break; case IEEE802154_CMD_COORD_REALIGN : break; case IEEE802154_CMD_GTS_REQ : break; } return 0; } /**************************************************************************** * coord_manage ****************************************************************************/ static int coord_manage(FAR struct ieee_coord_s *coord) { /* Decode frame type */ uint8_t fc1, ftype; int hlen; char buf[IEEE802154_ADDRSTRLEN+1]; FAR struct ieee_frame_s *rx = &coord->rxbuf; int i; fc1 = rx->packet.data[0]; rx->seq = rx->packet.data[2]; hlen = ieee802154_addrparse(&rx->packet, &rx->dest, &rx->src); if(hlen<0) { printf("invalid packet\n"); return 1; } rx->payload = rx->packet.data + hlen; rx->plen = rx->packet.len - hlen; ftype = fc1 & IEEE802154_FC1_FTYPE; ieee802154_addrtostr(buf,sizeof(buf),&rx->src); printf("[%s -> ", buf); ieee802154_addrtostr(buf,sizeof(buf),&rx->dest); printf("%s] ", buf); for(i=0; iplen; i++) printf("%02X", rx->payload[i]); printf("\n"); switch(ftype) { case IEEE802154_FRAME_BEACON : coord_beacon (coord); break; case IEEE802154_FRAME_DATA : coord_data (coord); break; case IEEE802154_FRAME_ACK : coord_ack (coord); break; case IEEE802154_FRAME_COMMAND: coord_command(coord); break; default : fprintf(stderr, "unknown frame type!"); } return 0; } /**************************************************************************** * coord_loop ****************************************************************************/ static volatile int gRun; static pthread_t gDaemonPid; void task_signal(int sig) { gRun = 0; } /**************************************************************************** * coord_initialize ****************************************************************************/ static void coord_initialize(FAR struct ieee_coord_s *coord, FAR char *dev, FAR char *chan, FAR char *panid) { int i; coord->nclients = 0; for (i = 0; i < CONFIG_IEEE802154_COORD_MAXCLIENTS; i++) { coord->clients[i].pending.len = 0; } coord->chan = strtol(chan , NULL, 0); coord->addr.ia_len = 2; coord->addr.ia_panid = strtol(panid, NULL, 0); coord->addr.ia_saddr = 0x0001; coord->fd = open(dev, O_RDWR); } #define ACTION_STOP 1 #define ACTION_PANID 2 struct message { int action; unsigned long param; }; struct message g_message; /**************************************************************************** * coord_task ****************************************************************************/ int coord_task(int s_argc, char **s_argv) { FAR struct ieee_frame_s *rx = &g_coord.rxbuf; int ret; coord_initialize(&g_coord, s_argv[3], s_argv[4], s_argv[5]); printf("IEEE 802.15.4 Coordinator started, chan %d, panid %04X, argc %d\n", g_coord.chan, g_coord.addr.ia_panid, s_argc); ieee802154_setchan (g_coord.fd , g_coord.chan ); ieee802154_setsaddr(g_coord.fd , g_coord.addr.ia_saddr); ieee802154_setpanid(g_coord.fd , g_coord.addr.ia_panid); ieee802154_setdevmode(g_coord.fd, IEEE802154_MODE_PANCOORD); if(g_coord.fd<0) { fprintf(stderr, "cannot open %s, errno=%d\n", s_argv[3], errno); exit(ERROR); } gRun = 1; while(gRun) { ret = read(g_coord.fd, &rx->packet, sizeof(struct ieee802154_packet_s)); if(ret > 0) { coord_manage(&g_coord); } if(ret < 0) { if(errno==4) //EINTR, signal received { switch(g_message.action) { case ACTION_STOP: gRun = 0; break; case ACTION_PANID: g_coord.addr.ia_panid = (uint16_t)g_message.param; ieee802154_setpanid(g_coord.fd, g_coord.addr.ia_panid); break; default: printf("received unknown message\n"); } } } } printf("IEEE 802.15.4 Coordinator stopped\n"); return 0; } /**************************************************************************** * coord_main 11 ****************************************************************************/ #ifdef CONFIG_BUILD_KERNEL int main(int argc, FAR char *argv[]) #else int coord_main(int argc, FAR char *argv[]) #endif { if(argc < 2) { printf("coord start | stop | panid\n"); exit(1); } if(!strcmp(argv[1], "start")) { if(argc != 5) { printf("coord start \n"); exit(EXIT_FAILURE); } if(gRun) { printf("Already started.\n"); exit(EXIT_FAILURE); } printf("IEEE 802.15.4 Coordinator starting...\n"); gDaemonPid = task_create("coord", SCHED_PRIORITY_DEFAULT, 1024, coord_task, argv); } else if(!strcmp(argv[1], "stop")) { if(!gRun) { norun: printf("Not started.\n"); exit(EXIT_FAILURE); } printf("IEEE 802.15.4 Coordinator stopping...\n"); g_message.action = ACTION_STOP; kill(gDaemonPid, SIGUSR1); } else if(!strcmp(argv[1], "status")) { printf("IEEE 802.15.4 Coordinator %s.\n", gRun?"started":"stopped"); } else if(!strcmp(argv[1], "panid")) { if(argc != 3) { printf("coord panid \n"); exit(EXIT_FAILURE); } if(!gRun) { goto norun; } g_message.action = ACTION_PANID; g_message.param = strtol(argv[2], NULL, 0); kill(gDaemonPid, SIGUSR1); } return EXIT_SUCCESS; }