Main Page | Data Structures | File List | Data Fields | Globals | Related Pages

network.c

Go to the documentation of this file.
00001 /***
00002  * This file is part of OpenHome, an open source home automation system.
00003  * Copyright (C) 2003 Jan Klötzke
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  */
00019 
00036 #include <avr/eeprom.h>
00037 #include <avr/pgmspace.h>
00038 #include <inttypes.h>
00039 #include "net/link.h"
00040 #include "net/network.h"
00041 #include "net.h"
00042 #include "utils.h"
00043 
00044 // local variables
00045 static net_ind_t ind;
00046 
00047 // eeprom variables
00048 uint16_t ee_addr_logic __attribute__(( section(".eeprom") ));
00049 uint16_t ee_addr_group[8] __attribute__(( section(".eeprom") ));
00050 
00051 // address length tables
00052 static prog_uchar dest_length_table[] = {2,1,4,0};
00053 static prog_uchar src_length_table[] = {2,2,4,0};
00054 
00055 // header bit masks
00056 #define DAF_MASK        0x03
00057 #define SAF_MASK        0x0c
00058 #define PDU_MASK        0x30
00059 
00060 // external functions (transport layer)
00061 extern void net_ind(uint8_t *buf, uint8_t len, const net_ind_t *ind);
00062 extern void net_con(void);
00063 
00064 /********************************************************************************
00065  * functions called from link layer
00066  */
00067 
00086 uint8_t lnk_ind(uint8_t *buf, uint8_t len)
00087 {
00088         uint8_t i, src_offset, src_len, result;
00089         
00090         // is this packet for us?
00091         result = 0;
00092         switch (buf[0] & DAF_MASK) {
00093                 case NAF_LOGIC:
00094                         if (*(uint16_t*)(buf+1) == eeprom_read_word(&ee_addr_logic)) {
00095                                 ind.rat = AT_LOGIC;
00096                                 result = 1;
00097                                 goto addr_match;
00098                         }
00099                         break;
00100                 case NAF_GROUP:
00101                         for (i=0;i<8;i++) 
00102                                 if (buf[1] == eeprom_read_byte(&ee_addr_group[i])) {
00103                                         ind.rat = AT_GROUP0+i;
00104                                         goto addr_match;
00105                                 }
00106                         break;
00107                 case NAF_PHYSIC:
00108                         if (*(uint32_t*)(buf+1) == NET_PHYSICAL_ADDR) {
00109                                 result = 1;
00110                                 ind.rat = AT_PHYSIC;
00111                                 goto addr_match;
00112                         }
00113                         break;
00114                 case NAF_BROADCAST:
00115                         ind.rat = AT_PHYSIC;
00116                         goto addr_match;
00117                 default:
00118                         break;
00119         }
00120         return 0;
00121 
00122 addr_match:
00123         ind.pdu = (buf[0]>>4) & 0x03;
00124         ind.src.format = (buf[0] & SAF_MASK) >> 2;
00125         src_len = __LPM(&src_length_table[ind.src.format]);
00126         src_offset = __LPM(&dest_length_table[buf[0] & DAF_MASK])+1;
00127         buf += src_offset;
00128         for (i=0;i<src_len;i++) ind.src.addr[i] = *buf++;
00129         len -= src_len+src_offset;
00130         net_ind(buf, len, &ind);
00131         return result;
00132 }
00133 
00139 void lnk_con(void)
00140 {
00141         net_con();
00142 }
00143 
00144 /********************************************************************************
00145  * Public functions
00146  */
00147 
00162 uint8_t net_requ(net_buf_t *buf, const net_requ_t *requ)
00163 {
00164         uint8_t hdr, i;
00165         
00166         // can we queue packet?
00167         if (!lnk_clear_to_send()) return 0;
00168         
00169         // prepare header
00170         hdr = (requ->pdu << 4) | requ->dest.format;
00171         
00172         // prepend source address
00173         if (requ->src == AT_LOGIC) {
00174                 hdr |= NAF_LOGIC << 2;
00175                 buf_prep_int(buf, eeprom_read_word(&ee_addr_logic));
00176         } else if (requ->src == AT_PHYSIC) {
00177                 hdr |= NAF_PHYSIC << 2;
00178                 buf_prep_long(buf, NET_PHYSICAL_ADDR);
00179         } else {
00180                 hdr |= NAF_GROUP << 2;
00181                 buf_prep_int(buf, eeprom_read_word(&ee_addr_group[requ->src-AT_GROUP0]));
00182         }
00183         
00184         // prepend destination address
00185         i = __LPM(&dest_length_table[requ->dest.format]);
00186         while (i > 0) buf_prep_char(buf, requ->dest.addr[--i]);
00187         
00188         // prepend header
00189         buf_prep_char(buf, hdr);
00190         
00191         // and go...
00192         if (lnk_ind(buf->data, buf->len)) {
00193                 net_con();
00194                 return 1;
00195         } else {
00196                 return lnk_requ(buf, requ->backlog);
00197         }
00198 }
00199 
00210 uint8_t net_compare_src_addr(const net_addr_t *addr1, const net_addr_t *addr2)
00211 {
00212         uint8_t i, len;
00213         
00214         if (addr1->format != addr2->format) return 0;
00215         len = __LPM(&src_length_table[addr1->format]);
00216         for (i=0;i<len;i++) if (addr1->addr[i] != addr2->addr[i]) return 0;
00217         return 1;
00218 }
00219 
00227 uint8_t net_get_local_member_id(uint8_t group)
00228 {
00229         return eeprom_read_byte(&ee_addr_group[group-AT_GROUP0]+1);
00230 }
00231 
00238 uint8_t net_clear_to_send(void)
00239 {
00240         return lnk_clear_to_send();
00241 }
00242 
00248 void net_set_logic_addr(uint16_t addr)
00249 {
00250         eeprom_write_word(&ee_addr_logic, addr);
00251 }
00252 
00258 uint16_t net_get_logic_addr(void)
00259 {
00260         return eeprom_read_word(&ee_addr_logic);
00261 }
00262 
00269 void net_set_group_addr(uint8_t group, uint16_t addr)
00270 {
00271         eeprom_write_word(&ee_addr_group[group], addr);
00272 }
00273 
00280 uint16_t net_get_group_addr(uint8_t group)
00281 {
00282         return eeprom_read_word(&ee_addr_group[group]);
00283 }

Generated on Fri Oct 17 16:45:54 2003 for OpenHome by doxygen 1.3.3