CROTUS / CROTUS_XBee

Dependents:   ProjetCasque

Fork of CROTUS_XBee by Valentin Libioulle

Committer:
libv2001
Date:
Mon Mar 27 15:09:52 2017 +0000
Revision:
0:2a59dd59ee5e
Child:
1:13c7d6237a53
Lib creation

Who changed what in which revision?

UserRevisionLine numberNew contents of line
libv2001 0:2a59dd59ee5e 1 #include "mbed.h"
libv2001 0:2a59dd59ee5e 2 #include "rtos.h"
libv2001 0:2a59dd59ee5e 3 #include "xbee.h"
libv2001 0:2a59dd59ee5e 4
libv2001 0:2a59dd59ee5e 5 DigitalOut _xbeeConnection(LED4);
libv2001 0:2a59dd59ee5e 6
libv2001 0:2a59dd59ee5e 7 Serial _xbee(p9, p10);
libv2001 0:2a59dd59ee5e 8 DigitalOut _xbeeRst(p8);
libv2001 0:2a59dd59ee5e 9
libv2001 0:2a59dd59ee5e 10 // Hidden functions
libv2001 0:2a59dd59ee5e 11 namespace {
libv2001 0:2a59dd59ee5e 12 char destination64bit[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
libv2001 0:2a59dd59ee5e 13 char destination16bit[2] = {0xff, 0xfe};
libv2001 0:2a59dd59ee5e 14
libv2001 0:2a59dd59ee5e 15 const int HARDWARE_RESET_SIGNAL = 0x10;
libv2001 0:2a59dd59ee5e 16 const int CONNECTED_SIGNAL = 0x20;
libv2001 0:2a59dd59ee5e 17 const int TICKER_SIGNAL = 0x40;
libv2001 0:2a59dd59ee5e 18 const int RESPONSE_SIGNAL = 0x80;
libv2001 0:2a59dd59ee5e 19
libv2001 0:2a59dd59ee5e 20 int responseStatus;
libv2001 0:2a59dd59ee5e 21
libv2001 0:2a59dd59ee5e 22 int panID = 0xB00B;
libv2001 0:2a59dd59ee5e 23 char frameID = 0;
libv2001 0:2a59dd59ee5e 24
libv2001 0:2a59dd59ee5e 25 Thread _xbeeReceiver;
libv2001 0:2a59dd59ee5e 26 Thread * _xbeeTransmitter;
libv2001 0:2a59dd59ee5e 27
libv2001 0:2a59dd59ee5e 28 void(*_callback)(char*, int) = 0;
libv2001 0:2a59dd59ee5e 29
libv2001 0:2a59dd59ee5e 30 inline char GetFrameID(){
libv2001 0:2a59dd59ee5e 31 ++frameID;
libv2001 0:2a59dd59ee5e 32 if (frameID == 0){
libv2001 0:2a59dd59ee5e 33 frameID = 1;
libv2001 0:2a59dd59ee5e 34 }
libv2001 0:2a59dd59ee5e 35 return frameID;
libv2001 0:2a59dd59ee5e 36 }
libv2001 0:2a59dd59ee5e 37
libv2001 0:2a59dd59ee5e 38 inline uint16_t GetFrameLength(char * buffer){
libv2001 0:2a59dd59ee5e 39 return (((uint16_t)buffer[LENGTH_MSB_IDX]) << 8) + buffer[LENGTH_LSB_IDX];
libv2001 0:2a59dd59ee5e 40 }
libv2001 0:2a59dd59ee5e 41
libv2001 0:2a59dd59ee5e 42 bool ValidateCheckSum(char * buffer){
libv2001 0:2a59dd59ee5e 43 uint16_t length = GetFrameLength(buffer);
libv2001 0:2a59dd59ee5e 44
libv2001 0:2a59dd59ee5e 45 char sum = 0;
libv2001 0:2a59dd59ee5e 46 for (int i = 0; i <= length; ++i){
libv2001 0:2a59dd59ee5e 47 sum += buffer[i + API_ID_IDX];
libv2001 0:2a59dd59ee5e 48 }
libv2001 0:2a59dd59ee5e 49
libv2001 0:2a59dd59ee5e 50 return sum == 0xff;
libv2001 0:2a59dd59ee5e 51 }
libv2001 0:2a59dd59ee5e 52
libv2001 0:2a59dd59ee5e 53 inline uint16_t GetAtParamLength(char * buffer){
libv2001 0:2a59dd59ee5e 54 return GetFrameLength(buffer) - AT_MIN_SIZE;
libv2001 0:2a59dd59ee5e 55 }
libv2001 0:2a59dd59ee5e 56
libv2001 0:2a59dd59ee5e 57 inline uint16_t GetAtQueueParamLength(char * buffer){
libv2001 0:2a59dd59ee5e 58 return GetFrameLength(buffer) - AT_QUEUE_MIN_SIZE;
libv2001 0:2a59dd59ee5e 59 }
libv2001 0:2a59dd59ee5e 60
libv2001 0:2a59dd59ee5e 61 inline uint16_t GetTransmitDataLength(char * buffer){
libv2001 0:2a59dd59ee5e 62 return GetFrameLength(buffer) - TRANSMIT_MIN_SIZE;
libv2001 0:2a59dd59ee5e 63 }
libv2001 0:2a59dd59ee5e 64
libv2001 0:2a59dd59ee5e 65 inline uint16_t GetRemoteAtRequestParamLength(char * buffer){
libv2001 0:2a59dd59ee5e 66 return GetFrameLength(buffer) - REMOTE_AT_RQST_MIN_SIZE;
libv2001 0:2a59dd59ee5e 67 }
libv2001 0:2a59dd59ee5e 68
libv2001 0:2a59dd59ee5e 69 inline uint16_t GetAtResponseParamLength(char * buffer){
libv2001 0:2a59dd59ee5e 70 return GetFrameLength(buffer) - AT_CMD_RSP_MIN_SIZE;
libv2001 0:2a59dd59ee5e 71 }
libv2001 0:2a59dd59ee5e 72
libv2001 0:2a59dd59ee5e 73 inline uint16_t GetReceivedPacketDataLength(char * buffer){
libv2001 0:2a59dd59ee5e 74 return GetFrameLength(buffer) - RECEIVED_PACKET_MIN_SIZE;
libv2001 0:2a59dd59ee5e 75 }
libv2001 0:2a59dd59ee5e 76
libv2001 0:2a59dd59ee5e 77 inline long long int Get64Addr(char * buffer, int start){
libv2001 0:2a59dd59ee5e 78 long long int addr = 0;
libv2001 0:2a59dd59ee5e 79 memcpy(&addr, &buffer[start], ADDR_64BIT_SIZE);
libv2001 0:2a59dd59ee5e 80
libv2001 0:2a59dd59ee5e 81 return addr;
libv2001 0:2a59dd59ee5e 82 }
libv2001 0:2a59dd59ee5e 83
libv2001 0:2a59dd59ee5e 84 inline short Get16Addr(char * buffer, int start){
libv2001 0:2a59dd59ee5e 85 short addr = 0;
libv2001 0:2a59dd59ee5e 86 memcpy(&addr, &buffer[start], ADDR_16BIT_SIZE);
libv2001 0:2a59dd59ee5e 87
libv2001 0:2a59dd59ee5e 88 return addr;
libv2001 0:2a59dd59ee5e 89 }
libv2001 0:2a59dd59ee5e 90
libv2001 0:2a59dd59ee5e 91 void SetCheckSum(char * buffer){
libv2001 0:2a59dd59ee5e 92 uint16_t length = GetFrameLength(buffer);
libv2001 0:2a59dd59ee5e 93
libv2001 0:2a59dd59ee5e 94 char sum = 0;
libv2001 0:2a59dd59ee5e 95
libv2001 0:2a59dd59ee5e 96 int max = length + 3;
libv2001 0:2a59dd59ee5e 97
libv2001 0:2a59dd59ee5e 98 for(int i = 3; i < max; ++i){
libv2001 0:2a59dd59ee5e 99 sum += buffer[i];
libv2001 0:2a59dd59ee5e 100 }
libv2001 0:2a59dd59ee5e 101
libv2001 0:2a59dd59ee5e 102 buffer[max] = 0xff - sum;
libv2001 0:2a59dd59ee5e 103 }
libv2001 0:2a59dd59ee5e 104
libv2001 0:2a59dd59ee5e 105 void XBeeSend(char * buffer, int count){
libv2001 0:2a59dd59ee5e 106 for ( int i = 0; i < count; ++i ){
libv2001 0:2a59dd59ee5e 107 _xbee.putc(buffer[i]);
libv2001 0:2a59dd59ee5e 108 wait_us(25);
libv2001 0:2a59dd59ee5e 109 }
libv2001 0:2a59dd59ee5e 110 }
libv2001 0:2a59dd59ee5e 111
libv2001 0:2a59dd59ee5e 112 void XBeeSendATCommand(bool queue, char * type, char * data, int dataLength){
libv2001 0:2a59dd59ee5e 113 char buffer[64];
libv2001 0:2a59dd59ee5e 114 buffer[START_IDX] = START;
libv2001 0:2a59dd59ee5e 115 buffer[LENGTH_MSB_IDX] = (dataLength + AT_MIN_SIZE) >> 8;
libv2001 0:2a59dd59ee5e 116 buffer[LENGTH_LSB_IDX] = (dataLength + AT_MIN_SIZE) & 0xff;
libv2001 0:2a59dd59ee5e 117 buffer[API_ID_IDX] = queue ? API_ID_AT_CMD_QUEUE : API_ID_AT_CMD;
libv2001 0:2a59dd59ee5e 118 buffer[FRAME_ID_IDX] = GetFrameID();
libv2001 0:2a59dd59ee5e 119 memcpy(&buffer[AT_CMD_ID_IDX], type, AT_CMD_ID_SIZE);
libv2001 0:2a59dd59ee5e 120 memcpy(&buffer[AT_PARAM_IDX], data, dataLength);
libv2001 0:2a59dd59ee5e 121
libv2001 0:2a59dd59ee5e 122 SetCheckSum(buffer);
libv2001 0:2a59dd59ee5e 123
libv2001 0:2a59dd59ee5e 124 while(true){
libv2001 0:2a59dd59ee5e 125 XBeeSend(buffer, dataLength + AT_MIN_SIZE + FRAME_MIN_SIZE);
libv2001 0:2a59dd59ee5e 126
libv2001 0:2a59dd59ee5e 127 Thread::signal_wait(RESPONSE_SIGNAL);
libv2001 0:2a59dd59ee5e 128
libv2001 0:2a59dd59ee5e 129 switch (responseStatus){
libv2001 0:2a59dd59ee5e 130 case AT_CMD_RSP_STATUS_OK:
libv2001 0:2a59dd59ee5e 131 return;
libv2001 0:2a59dd59ee5e 132 case AT_CMD_RSP_STATUS_ERROR:
libv2001 0:2a59dd59ee5e 133 case AT_CMD_RSP_STATUS_INVALID_CMD:
libv2001 0:2a59dd59ee5e 134 case AT_CMD_RSP_STATUS_INVALID_PARAM:
libv2001 0:2a59dd59ee5e 135 case AT_CMD_RSP_STATUS_TX_FAILURE:
libv2001 0:2a59dd59ee5e 136 default:
libv2001 0:2a59dd59ee5e 137 _xbeeConnection = 0;
libv2001 0:2a59dd59ee5e 138 break;
libv2001 0:2a59dd59ee5e 139 }
libv2001 0:2a59dd59ee5e 140 }
libv2001 0:2a59dd59ee5e 141 }
libv2001 0:2a59dd59ee5e 142
libv2001 0:2a59dd59ee5e 143 inline void XBeeSendATID(){
libv2001 0:2a59dd59ee5e 144 char idBuf[8];
libv2001 0:2a59dd59ee5e 145 for (int i = 0; i < 8; ++i){
libv2001 0:2a59dd59ee5e 146 idBuf[i] = (panID >> (56 - 8 * i)) & 0xff;
libv2001 0:2a59dd59ee5e 147 }
libv2001 0:2a59dd59ee5e 148 XBeeSendATCommand(true, "ID", idBuf, 8);
libv2001 0:2a59dd59ee5e 149 }
libv2001 0:2a59dd59ee5e 150
libv2001 0:2a59dd59ee5e 151 inline void XBeeSendATWR(){
libv2001 0:2a59dd59ee5e 152 XBeeSendATCommand(true, "WR", 0, 0);
libv2001 0:2a59dd59ee5e 153 }
libv2001 0:2a59dd59ee5e 154
libv2001 0:2a59dd59ee5e 155 inline void XBeeSendATAC(){
libv2001 0:2a59dd59ee5e 156 XBeeSendATCommand(true, "AC", 0, 0);
libv2001 0:2a59dd59ee5e 157 }
libv2001 0:2a59dd59ee5e 158
libv2001 0:2a59dd59ee5e 159 inline char XbeeReadChar(){
libv2001 0:2a59dd59ee5e 160 while(!_xbee.readable()){
libv2001 0:2a59dd59ee5e 161 }
libv2001 0:2a59dd59ee5e 162 return _xbee.getc();
libv2001 0:2a59dd59ee5e 163 }
libv2001 0:2a59dd59ee5e 164
libv2001 0:2a59dd59ee5e 165 void HandleXbeeReceivedPacket(char * cmd){
libv2001 0:2a59dd59ee5e 166 _callback(&cmd[RECEIVED_PACKET_DATA_IDX], GetReceivedPacketDataLength(cmd));
libv2001 0:2a59dd59ee5e 167 }
libv2001 0:2a59dd59ee5e 168
libv2001 0:2a59dd59ee5e 169 void HandleXbeeModemStatus(char * cmd){
libv2001 0:2a59dd59ee5e 170 switch(cmd[MODEM_STATUS_STATUS_IDX]){
libv2001 0:2a59dd59ee5e 171 case MODEM_STATUS_HARDWARE_RST:
libv2001 0:2a59dd59ee5e 172 _xbeeTransmitter->signal_set(HARDWARE_RESET_SIGNAL);
libv2001 0:2a59dd59ee5e 173 break;
libv2001 0:2a59dd59ee5e 174 case MODEM_STATUS_COORDINATOR_STARTED: // For the coordinator
libv2001 0:2a59dd59ee5e 175 case MODEM_STATUS_JOINED_NETWORK: // For the rooter
libv2001 0:2a59dd59ee5e 176 _xbeeTransmitter->signal_set(CONNECTED_SIGNAL);
libv2001 0:2a59dd59ee5e 177 break;
libv2001 0:2a59dd59ee5e 178 default:
libv2001 0:2a59dd59ee5e 179 _xbeeConnection = 0;
libv2001 0:2a59dd59ee5e 180 break;
libv2001 0:2a59dd59ee5e 181 }
libv2001 0:2a59dd59ee5e 182 }
libv2001 0:2a59dd59ee5e 183
libv2001 0:2a59dd59ee5e 184 void HandleXBeeATCommandResponse(char * cmd){
libv2001 0:2a59dd59ee5e 185 responseStatus = cmd[AT_CMD_RSP_STATUS_IDX];
libv2001 0:2a59dd59ee5e 186 _xbeeTransmitter->signal_set(RESPONSE_SIGNAL);
libv2001 0:2a59dd59ee5e 187 }
libv2001 0:2a59dd59ee5e 188
libv2001 0:2a59dd59ee5e 189 void HandleXbeeTransmitStatus(char * cmd){
libv2001 0:2a59dd59ee5e 190 switch(cmd[TRANSMIT_STATUS_DELIVERY_STATUS_IDX]){
libv2001 0:2a59dd59ee5e 191 case TRANSMIT_STATUS_OK:
libv2001 0:2a59dd59ee5e 192 responseStatus = cmd[TRANSMIT_STATUS_DELIVERY_STATUS_IDX];
libv2001 0:2a59dd59ee5e 193 _xbeeTransmitter->signal_set(RESPONSE_SIGNAL);
libv2001 0:2a59dd59ee5e 194 break;
libv2001 0:2a59dd59ee5e 195 default:
libv2001 0:2a59dd59ee5e 196 _xbeeConnection = 0;
libv2001 0:2a59dd59ee5e 197 }
libv2001 0:2a59dd59ee5e 198 }
libv2001 0:2a59dd59ee5e 199
libv2001 0:2a59dd59ee5e 200 void HandleXbeeReceivedCommand(char * cmd){
libv2001 0:2a59dd59ee5e 201 switch(cmd[API_ID_IDX]){
libv2001 0:2a59dd59ee5e 202 case API_ID_AT_CMD_RSP:
libv2001 0:2a59dd59ee5e 203 HandleXBeeATCommandResponse(cmd);
libv2001 0:2a59dd59ee5e 204 break;
libv2001 0:2a59dd59ee5e 205 case API_ID_MODEM_STATUS:
libv2001 0:2a59dd59ee5e 206 HandleXbeeModemStatus(cmd);
libv2001 0:2a59dd59ee5e 207 break;
libv2001 0:2a59dd59ee5e 208 case API_ID_RECEIVED_PACKET:
libv2001 0:2a59dd59ee5e 209 HandleXbeeReceivedPacket(cmd);
libv2001 0:2a59dd59ee5e 210 break;
libv2001 0:2a59dd59ee5e 211 case API_ID_TRANSMIT_STATUS:
libv2001 0:2a59dd59ee5e 212 HandleXbeeTransmitStatus(cmd);
libv2001 0:2a59dd59ee5e 213 break;
libv2001 0:2a59dd59ee5e 214 default:
libv2001 0:2a59dd59ee5e 215 _xbeeConnection = 0;
libv2001 0:2a59dd59ee5e 216 break;
libv2001 0:2a59dd59ee5e 217 }
libv2001 0:2a59dd59ee5e 218 }
libv2001 0:2a59dd59ee5e 219
libv2001 0:2a59dd59ee5e 220 void _XbeeReceiver(){
libv2001 0:2a59dd59ee5e 221 char buffer[64];
libv2001 0:2a59dd59ee5e 222 while(true){
libv2001 0:2a59dd59ee5e 223 buffer[START_IDX] = XbeeReadChar();
libv2001 0:2a59dd59ee5e 224 if (buffer[START_IDX] != START){
libv2001 0:2a59dd59ee5e 225 _xbeeConnection = 0;
libv2001 0:2a59dd59ee5e 226 continue;
libv2001 0:2a59dd59ee5e 227 }
libv2001 0:2a59dd59ee5e 228 buffer[LENGTH_MSB_IDX] = XbeeReadChar();
libv2001 0:2a59dd59ee5e 229 buffer[LENGTH_LSB_IDX] = XbeeReadChar();
libv2001 0:2a59dd59ee5e 230 int length = GetFrameLength(buffer);
libv2001 0:2a59dd59ee5e 231
libv2001 0:2a59dd59ee5e 232 for (int i = 0; i <= length; ++i){
libv2001 0:2a59dd59ee5e 233 buffer[i + API_ID_IDX] = XbeeReadChar();
libv2001 0:2a59dd59ee5e 234 }
libv2001 0:2a59dd59ee5e 235 if (!ValidateCheckSum(buffer)){
libv2001 0:2a59dd59ee5e 236 _xbeeConnection = 0;
libv2001 0:2a59dd59ee5e 237 continue;
libv2001 0:2a59dd59ee5e 238 }
libv2001 0:2a59dd59ee5e 239
libv2001 0:2a59dd59ee5e 240 HandleXbeeReceivedCommand(buffer);
libv2001 0:2a59dd59ee5e 241 }
libv2001 0:2a59dd59ee5e 242 }
libv2001 0:2a59dd59ee5e 243
libv2001 0:2a59dd59ee5e 244 };
libv2001 0:2a59dd59ee5e 245
libv2001 0:2a59dd59ee5e 246 /*******************************************************/
libv2001 0:2a59dd59ee5e 247 /**********************XBEE SEND************************/
libv2001 0:2a59dd59ee5e 248 /*******************************************************/
libv2001 0:2a59dd59ee5e 249
libv2001 0:2a59dd59ee5e 250 void XBeeSendData(char * data, int dataLength){
libv2001 0:2a59dd59ee5e 251 char buffer[64];
libv2001 0:2a59dd59ee5e 252 buffer[START_IDX] = START;
libv2001 0:2a59dd59ee5e 253 buffer[LENGTH_MSB_IDX] = (dataLength + TRANSMIT_MIN_SIZE) >> 8;
libv2001 0:2a59dd59ee5e 254 buffer[LENGTH_LSB_IDX] = (dataLength + TRANSMIT_MIN_SIZE) & 0xff;
libv2001 0:2a59dd59ee5e 255 buffer[API_ID_IDX] = API_ID_TRANSMIT;
libv2001 0:2a59dd59ee5e 256 buffer[FRAME_ID_IDX] = GetFrameID();
libv2001 0:2a59dd59ee5e 257 memcpy(&buffer[TRANSMIT_64BIT_MSB_IDX], destination64bit, ADDR_64BIT_SIZE);
libv2001 0:2a59dd59ee5e 258 memcpy(&buffer[TRANSMIT_16BIT_MSB_IDX], destination16bit, ADDR_16BIT_SIZE);
libv2001 0:2a59dd59ee5e 259 buffer[TRANSMIT_BROADCAST_IDX] = TRANSMIT_DEFAULT_BROADCAST;
libv2001 0:2a59dd59ee5e 260 buffer[TRANSMIT_OPT_IDX] = TRANSMIT_DEFAULT_OPT;
libv2001 0:2a59dd59ee5e 261 memcpy(&buffer[TRANSMIT_DATA_IDX], data, dataLength);
libv2001 0:2a59dd59ee5e 262
libv2001 0:2a59dd59ee5e 263 SetCheckSum(buffer);
libv2001 0:2a59dd59ee5e 264
libv2001 0:2a59dd59ee5e 265 while(true) {
libv2001 0:2a59dd59ee5e 266 XBeeSend(buffer, dataLength + TRANSMIT_MIN_SIZE + FRAME_MIN_SIZE);
libv2001 0:2a59dd59ee5e 267
libv2001 0:2a59dd59ee5e 268 Thread::signal_wait(RESPONSE_SIGNAL);
libv2001 0:2a59dd59ee5e 269
libv2001 0:2a59dd59ee5e 270 switch (responseStatus){
libv2001 0:2a59dd59ee5e 271 case TRANSMIT_STATUS_OK:
libv2001 0:2a59dd59ee5e 272 return;
libv2001 0:2a59dd59ee5e 273 default:
libv2001 0:2a59dd59ee5e 274 _xbeeConnection = 0;
libv2001 0:2a59dd59ee5e 275 break;
libv2001 0:2a59dd59ee5e 276 }
libv2001 0:2a59dd59ee5e 277 }
libv2001 0:2a59dd59ee5e 278 }
libv2001 0:2a59dd59ee5e 279
libv2001 0:2a59dd59ee5e 280 bool InitXBee(bool coordinator, void(*packetReceivedCallback)(char*, int), Thread * xbeeTransmitter){
libv2001 0:2a59dd59ee5e 281 _callback = packetReceivedCallback;
libv2001 0:2a59dd59ee5e 282 _xbeeTransmitter = xbeeTransmitter;
libv2001 0:2a59dd59ee5e 283
libv2001 0:2a59dd59ee5e 284 if (coordinator)
libv2001 0:2a59dd59ee5e 285 {
libv2001 0:2a59dd59ee5e 286 uint8_t temp[8] = {0x00, 0x13, 0xA2, 0x00, 0x40, 0x33, 0x19, 0x8D};
libv2001 0:2a59dd59ee5e 287 memcpy(destination64bit, temp, 8);
libv2001 0:2a59dd59ee5e 288 }
libv2001 0:2a59dd59ee5e 289
libv2001 0:2a59dd59ee5e 290 _xbeeReceiver.start(callback(_XbeeReceiver));
libv2001 0:2a59dd59ee5e 291
libv2001 0:2a59dd59ee5e 292 _xbeeRst.write(0);
libv2001 0:2a59dd59ee5e 293 wait(0.4);
libv2001 0:2a59dd59ee5e 294 _xbeeRst.write(1);
libv2001 0:2a59dd59ee5e 295
libv2001 0:2a59dd59ee5e 296 Thread::signal_wait(HARDWARE_RESET_SIGNAL);
libv2001 0:2a59dd59ee5e 297
libv2001 0:2a59dd59ee5e 298 XBeeSendATID();
libv2001 0:2a59dd59ee5e 299 XBeeSendATWR();
libv2001 0:2a59dd59ee5e 300 XBeeSendATAC();
libv2001 0:2a59dd59ee5e 301
libv2001 0:2a59dd59ee5e 302 Thread::signal_wait(CONNECTED_SIGNAL);
libv2001 0:2a59dd59ee5e 303
libv2001 0:2a59dd59ee5e 304 _xbeeConnection = 1;
libv2001 0:2a59dd59ee5e 305
libv2001 0:2a59dd59ee5e 306 return true;
libv2001 0:2a59dd59ee5e 307 }