cm_tp1.cpp
1 /* 2 EIBD eib bus access and management daemon 3 Copyright (C) 2005-2011 Martin Koegler <mkoegler@auto.tuwien.ac.at> 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 20 #include "cm_tp1.h" 21 22 /* L_Data */ 23 24 LDataPtr CM_TP1_to_L_Data (const CArray & c, TracePtr) 25 { 26 LDataPtr l = LDataPtr(new L_Data_PDU ()); 27 if (c.size() < 6) 28 return nullptr; 29 if ((c[0] & 0x53) != 0x10) 30 return nullptr; 31 l->frame_format = (c[0] & 0x80) ? 1 : 0; 32 l->repeated = (c[0] & 0x20) ? 0 : 1; 33 l->priority = static_cast<EIB_Priority>((c[0] >> 2) & 0x3); 34 l->valid_length = 1; 35 if (l->frame_format) 36 { 37 /* Standard frame */ 38 l->source_address = (c[1] << 8) | (c[2]); 39 l->destination_address = (c[3] << 8) | (c[4]); 40 l->address_type = (c[5] & 0x80) ? GroupAddress : IndividualAddress; 41 l->hop_count = (c[5] >> 4) & 0x07; // @todo this is NPDU 42 uint8_t len = (c[5] & 0x0f) + 1; 43 if (len + 7 != c.size()) 44 return nullptr; 45 l->lsdu.set (c.data() + 6, len); 46 } 47 else 48 { 49 /* extended frame */ 50 if ((c[1] & 0x0f) != 0) 51 return nullptr; 52 if (c.size() < 7) 53 return nullptr; 54 l->address_type = (c[1] & 0x80) ? GroupAddress : IndividualAddress; 55 l->hop_count = (c[1] >> 4) & 0x07; // @todo this is NPDU 56 l->source_address = (c[2] << 8) | (c[3]); 57 l->destination_address = (c[4] << 8) | (c[5]); 58 uint8_t len = c[6] + 1; 59 if (len + 8 != c.size()) 60 { 61 if (c.size() == 23) 62 { 63 l->valid_length = 0; 64 l->lsdu.set (c.data() + 7, 8); 65 } 66 else 67 return nullptr; 68 } 69 else 70 l->lsdu.set (c.data() + 7, len); 71 } 72 73 /* checksum */ 74 uint8_t checksum = 0; 75 for (unsigned i = 0; i < c.size () - 1; i++) 76 checksum ^= c[i]; 77 checksum = ~checksum; 78 l->valid_checksum = (c[c.size () - 1] == checksum); 79 80 return l; 81 } 82 83 CArray L_Data_to_CM_TP1 (const LDataPtr & p) 84 { 85 assert (p->lsdu.size() >= 1); 86 assert (p->lsdu.size() <= 0xff); 87 assert ((p->hop_count & 0xf8) == 0); 88 89 CArray pdu; 90 uint8_t len = p->lsdu.size() - 1; 91 if (len <= 0x0f) 92 { 93 /* L_Data_Standard Frame */ 94 pdu.resize (7 + p->lsdu.size()); 95 pdu[0] = 0x90 | (p->repeated ? 0x00 : 0x20) | (p->priority << 2); 96 pdu[1] = p->source_address >> 8; 97 pdu[2] = p->source_address & 0xff; 98 pdu[3] = p->destination_address >> 8; 99 pdu[4] = p->destination_address & 0xff; 100 pdu[5] = 101 (p->address_type == GroupAddress ? 0x80 : 0x00) | 102 ((p->hop_count & 0x07) << 4) | 103 (len & 0x0f); 104 pdu.setpart (p->lsdu.data(), 6, 1 + (len & 0x0f)); 105 } 106 else 107 { 108 /* L_Data_Extended Frame */ 109 pdu.resize (8 + p->lsdu.size()); 110 pdu[0] = 0x10 | (p->repeated ? 0x00 : 0x20) | (p->priority << 2); 111 pdu[1] = 112 (p->address_type == GroupAddress ? 0x80 : 0x00) | 113 ((p->hop_count & 0x07) << 4); 114 pdu[2] = p->source_address >> 8; 115 pdu[3] = p->source_address & 0xff; 116 pdu[4] = p->destination_address >> 8; 117 pdu[5] = p->destination_address & 0xff; 118 pdu[6] = (p->lsdu.size() - 1) & 0xff; 119 pdu.setpart (p->lsdu.data(), 7, 1 + (len & 0xff)); 120 } 121 122 /* checksum */ 123 uint8_t checksum = 0; 124 for (unsigned i = 0; i < pdu.size() - 1; i++) 125 checksum ^= pdu[i]; 126 pdu[pdu.size() - 1] = ~checksum; 127 128 return pdu; 129 }