00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef DCDT_CHANNEL_SERIAL_H
00026 #define DCDT_CHANNEL_SERIAL_H
00027
00028 #include <DCDT_Channel.h>
00029 #include <unistd.h>
00030 #include <fcntl.h>
00031 #include <errno.h>
00032 #include <termios.h>
00033 #include <iostream>
00034 #include <sys/time.h>
00035 #include <DCDT_ctrace.h>
00036
00037 #define DEVICE_NAME_LEN UNIX_PATH_MAX
00038 #define BAUDRATE B4000000
00039
00040 #define SER_LOST_TIMER_VAL 10000000
00041 #define SER_RECV_TIMER_VAL 100000
00042
00043 class CommData_Serial;
00044
00045 class DCDT_Channel_Serial : public DCDT_Channel {
00046 public:
00047 DCDT_Channel_Serial(int AgoraID) : DCDT_Channel(AgoraID) {
00048 localCD = NULL;
00049 device = status = trecv_flag = tlost_flag = unblock_recv_flag = 0;
00050 tlost_value.tv_sec = tlost_value.tv_usec = trecv_value.tv_sec = trecv_value.tv_usec = 0;
00051 }
00052
00053 inline void Open(int link_status = 0);
00054 inline void Reopen(int link_status);
00055
00056 inline void Prepare(CommData *local, CommData *remote);
00057 inline void StaticPrepare(unsigned int prof, char *dev);
00058 inline void ChooseChannel(int channel){channel = 0;};
00059 inline void WaitConn();
00060 inline void StartConn();
00061 inline void Send(const DCDT_Msg *msg);
00062 inline void SendNotify();
00063 inline void SendAnswer(CommData* to, CommData* local);
00064 inline DCDT_Msg* Receive();
00065 inline void ReceiveHS(HSMsgHeader*& header, CommData*& remote);
00066 inline void Dispose();
00067 inline void Close();
00068 inline void KeepAlive(){};
00070 inline CommData* GetStartingCD();
00071 inline unsigned int ReadStartingProfile();
00072 inline CommData* GetCommData();
00073 inline void SetTimers();
00074 inline void SetLostTimer(int usec);
00075 inline void LostTimerOn();
00076 inline void LostTimerOff();
00077 inline void SetConnTimer(int usec);
00078 inline void ConnTimerOn();
00079 inline void ConnTimerOff();
00080 inline void SetSendTimer(int usec);
00081 inline void SendTimerOn();
00082 inline void SendTimerOff();
00083 inline void UnblockSend();
00084 inline void SetReceiveTimer(int usec);
00085 inline void ReceiveTimerOn();
00086 inline void ReceiveTimerOff();
00087 inline void UnblockReceive();
00088 inline void Restart(int link_status);
00089 inline void Stop();
00090
00091 private:
00092 int device, status;
00093 CommData_Serial *localCD;
00094 struct termios options;
00095 int
00097 trecv_flag,
00099 tlost_flag,
00101 unblock_recv_flag;
00102
00103 struct timeval
00105 trecv_value,
00107 tlost_value;
00108
00109 char device_name[UNIX_PATH_MAX];
00110 unsigned int profile;
00111
00113 bool dynamic;
00114 };
00115
00116 class CommData_Serial : public CommData {
00117 public:
00118 char *device_name;
00119
00120 CommData_Serial() {
00121 device_name = new char[DEVICE_NAME_LEN];
00122 }
00123
00124 CommData_Serial(char *name) {
00125 device_name = new char[DEVICE_NAME_LEN];
00126 strcpy(device_name, name);
00127 }
00128
00129 CommData_Serial(CommData_Serial *cd) {
00130 device_name = new char[DEVICE_NAME_LEN];
00131 strcpy(device_name, cd->device_name);
00132 }
00133
00134 CommData_Serial& operator=(const CommData_Serial& cd) {
00135 strcpy(device_name, cd.device_name);
00136 return (*this);
00137 }
00138
00139 DCDT_Channel* CreateChannel(int AgoraID) {
00140 return (new DCDT_Channel_Serial(AgoraID));
00141 }
00142 };
00143
00146 inline void DCDT_Channel_Serial::Prepare(CommData *local, CommData *remote)
00147 {
00148 TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Prepare channel Serial"));
00149 if (local) {
00150 if (localCD)
00151 delete localCD;
00152 localCD = (CommData_Serial*)local;
00153
00154 TRC_PRINT( DCDT_TRC_COMM, TRC1, ("localCD: device_name=%s", localCD->device_name));
00155 } else
00156 localCD = new CommData_Serial();
00157 strcpy(device_name, localCD->device_name);
00158
00159 remote = NULL;
00160 }
00161
00164 inline void DCDT_Channel_Serial::StaticPrepare(unsigned int prof, char *dev)
00165 {
00166 TRC_PRINT( DCDT_TRC_COMM, TRC1, ("StaticPrepare channel Serial"));
00167 dynamic = false;
00168 profile = prof;
00169
00170 localCD = new CommData_Serial(dev);
00171 strcpy(device_name, dev);
00172 Open();
00173 SetReceiveTimer(0);
00174 ReceiveTimerOn();
00175 SetLostTimer(SER_LOST_TIMER_VAL);
00176 LostTimerOn();
00177 }
00178
00183 inline void DCDT_Channel_Serial::Open(int link_status )
00184 {
00185 device = open(localCD->device_name, O_RDWR | O_NOCTTY | O_NDELAY);
00186 if (device == -1) {
00187 TRC_PRINT( DCDT_TRC_COMM, TRC1, ( "Unable to open %s", localCD->device_name));
00188 throw ChannelError();
00189 }
00190 tcgetattr(device, &options);
00191
00192
00193 options.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
00194 options.c_iflag = 0;
00195 options.c_oflag = 0;
00196 options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG );
00197
00198 tcsetattr(device, TCSAFLUSH, &options);
00199 fcntl(device, F_SETFL, 0);
00200
00201 TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Serial port opened: %s", localCD->device_name));
00202 }
00203
00204 inline void DCDT_Channel_Serial::Reopen(int link_status)
00205 {
00206 Open(link_status);
00207 }
00208
00209 inline CommData* DCDT_Channel_Serial::GetCommData()
00210 {
00211 return localCD;
00212 }
00213
00219 inline void DCDT_Channel_Serial::WaitConn()
00220 {
00221 HSMsgHeader *h;
00222 CommData *c;
00223 ReceiveTimerOff();
00224 ReceiveHS(h, c);
00225 SendNotify();
00226 }
00227
00234 inline DCDT_Msg* DCDT_Channel_Serial::Receive()
00235 {
00236 DCDT_MsgHeader *msg_header;
00237 DCDT_Msg *msg;
00238 int plen;
00239 void *msg_payload;
00240
00241 char *index;
00242 int nread = 0, toread = MSGHEADER_LEN;
00243 fd_set rset;
00244 struct timeval tv, *tv_ptr = NULL;
00245
00246 FD_ZERO(&rset);
00247 FD_SET(device, &rset);
00248 if (unblock_recv_flag)
00249 {
00250 tv.tv_sec = 0;
00251 tv.tv_usec = 0;
00252 tv_ptr = &tv;
00253 }
00254 else if (trecv_flag)
00255 {
00256 tv.tv_sec = trecv_value.tv_sec;
00257 tv.tv_usec = trecv_value.tv_usec;
00258 tv_ptr = &tv;
00259 }
00260 else if (tlost_flag)
00261 {
00262 tv.tv_sec = tlost_value.tv_sec;
00263 tv.tv_usec = tlost_value.tv_usec;
00264 tv_ptr = &tv;
00265 }
00266 switch (select(device+1, &rset, NULL, NULL, tv_ptr))
00267 {
00268 case 0: return NULL;
00269 case -1: throw ConnError(errno);
00270 }
00271
00272 msg_header = new DCDT_MsgHeader;
00273 index = (char*)msg_header;
00274 if ((nread = read(device, index, toread)) < 0)
00275 {
00276 delete msg_header;
00277 msg_header = NULL;
00278 throw ConnError(errno);
00279 }
00280 else if (nread == 0)
00281 {
00282 delete msg_header;
00283 msg_header = NULL;
00284 throw ConnError();
00285 }
00286 index += nread;
00287
00288 TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Serial header byte read: %i", nread));
00289
00290 toread -= nread;
00291
00292 while ( toread )
00293 {
00294 FD_ZERO(&rset);
00295 FD_SET(device, &rset);
00296 if (tlost_flag)
00297 {
00298 tv.tv_sec = tlost_value.tv_sec;
00299 tv.tv_usec = tlost_value.tv_usec;
00300 tv_ptr = &tv;
00301 }
00302 switch (select(device+1, &rset, NULL, NULL, tv_ptr))
00303 {
00304 case 0:
00305 case -1:
00306 delete msg_header;
00307 msg_header = NULL;
00308 throw ConnError(errno);
00309 }
00310 if ((nread = read(device, index, toread)) < 0)
00311 {
00312 delete msg_header;
00313 msg_header = NULL;
00314 throw ConnError(errno);
00315 }
00316 else if (nread == 0)
00317 {
00318 delete msg_header;
00319 msg_header = NULL;
00320 throw ConnError();
00321 }
00322 index += nread;
00323
00324 TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Serial header byte read: %i", nread));
00325
00326 toread -= nread;
00327 }
00328 msg = new DCDT_Msg(msg_header);
00329
00330
00331 msg_payload = malloc(plen = msg->ReadPayloadLen());
00332 index = (char*)msg_payload;
00333 toread = plen;
00334 while ( toread )
00335 {
00336 if (tlost_flag)
00337 {
00338 tv.tv_sec = tlost_value.tv_sec;
00339 tv.tv_usec = tlost_value.tv_usec;
00340 tv_ptr = &tv;
00341 }
00342 switch (select(device+1, &rset, NULL, NULL, tv_ptr))
00343 {
00344 case 0:
00345 case -1: throw ConnError(errno);
00346 }
00347 if ((nread = read(device, index, toread)) < 0)
00348 {
00349 free(msg_payload);
00350 delete msg_header;
00351 msg_header = NULL;
00352 throw ConnError(errno);
00353 }
00354 else if (nread == 0)
00355 {
00356 free(msg_payload);
00357 delete msg_header;
00358 msg_header = NULL;
00359 throw ConnError();
00360 }
00361 index += nread;
00362
00363 TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Serial payload byte read: %i", nread));
00364 toread -= nread;
00365 }
00366 msg->SetPayload(msg_payload, plen);
00367
00368 TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Serial message successfully received"));
00369
00370 return msg;
00371 }
00372
00378 inline void DCDT_Channel_Serial::ReceiveHS(HSMsgHeader*& header, CommData*& remote)
00379 {
00380 char *index;
00381 int nread = 0, toread = HSMSGHEADER_LEN;
00382 fd_set rset;
00383 struct timeval tv, *tv_ptr = NULL;
00384
00385 FD_ZERO(&rset);
00386 FD_SET(device, &rset);
00387
00388 if (trecv_flag)
00389 {
00390 tv.tv_sec = trecv_value.tv_sec;
00391 tv.tv_usec = trecv_value.tv_usec;
00392 tv_ptr = &tv;
00393 }
00394 switch (select(device+1, &rset, NULL, NULL, tv_ptr))
00395 {
00396 case 0: return;
00397 case -1: throw ConnError(errno);
00398 }
00399
00400
00401 header = new HSMsgHeader();
00402 index = (char*)header;
00403 if ((nread = read(device, index, toread)) < 0)
00404 {
00405
00406 delete header;
00407 header = NULL;
00408 throw ConnError(errno);
00409 }
00410 else if (nread == 0)
00411 {
00412 delete header;
00413 header = NULL;
00414 throw ConnError();
00415 }
00416 index += nread;
00417
00418 TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Serial header byte read: %i", nread));
00419
00420 toread -= nread;
00421
00422 while ( toread )
00423 {
00424 FD_ZERO(&rset);
00425 FD_SET(device, &rset);
00426 if (tlost_flag)
00427 {
00428 tv.tv_sec = tlost_value.tv_sec;
00429 tv.tv_usec = tlost_value.tv_usec;
00430 tv_ptr = &tv;
00431 }
00432 switch (select(device+1, &rset, NULL, NULL, tv_ptr))
00433 {
00434 case 0:
00435 case -1:
00436 delete header;
00437 header = NULL;
00438 throw ConnError(errno);
00439 }
00440 if ((nread = read(device, index, toread)) < 0)
00441 {
00442 delete header;
00443 header = NULL;
00444 throw ConnError(errno);
00445 }
00446 else if (nread == 0)
00447 {
00448 delete header;
00449 header = NULL;
00450 throw ConnError();
00451 }
00452 index += nread;
00453
00454 TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Serial header byte read: %i", nread));
00455
00456 toread -= nread;
00457 }
00458
00459 TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Serial h-s message successfully received"));
00460 if (header->type == HS_ANSWER) {
00461 Stop();
00462 remote = new CommData_Serial(device_name);
00463 }
00464 }
00465
00471 inline void DCDT_Channel_Serial::Send(const DCDT_Msg *msg)
00472 {
00473 fd_set wset;
00474 struct timeval tv, *tv_ptr = NULL;
00475 int sent, tosend = MSGHEADER_LEN;
00476 char *sending_ptr;
00477
00478
00479 sending_ptr = (char*)msg->GetHeader();
00480 while (tosend) {
00481 FD_ZERO(&wset);
00482 FD_SET(device, &wset);
00483 if (tlost_flag)
00484 {
00485 tv.tv_sec = tlost_value.tv_sec;
00486 tv.tv_usec = tlost_value.tv_usec;
00487 tv_ptr = &tv;
00488 }
00489 switch (select(device+1, NULL, &wset, NULL, tv_ptr))
00490 {
00491 case 0: throw TimeOut();
00492 case -1: throw ConnError(errno);
00493 }
00494
00495 if ((sent = write(device, sending_ptr, tosend)) < 0)
00496 throw ConnError();
00497
00498 TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Serial header byte sent: %i", sent));
00499
00500 tosend -= sent;
00501 sending_ptr += sent;
00502 }
00503
00504
00505 sending_ptr = (char*)msg->GetPayload();
00506 tosend = msg->ReadPayloadLen();
00507 while (tosend) {
00508 FD_ZERO(&wset);
00509 FD_SET(device, &wset);
00510 if (tlost_flag)
00511 {
00512 tv.tv_sec = tlost_value.tv_sec;
00513 tv.tv_usec = tlost_value.tv_usec;
00514 tv_ptr = &tv;
00515 }
00516 switch (select(device+1, NULL, &wset, NULL, tv_ptr))
00517 {
00518 case 0:
00519 case -1: throw ConnError(errno);
00520 }
00521
00522 if ((sent = write(device, sending_ptr, tosend)) < 0)
00523 throw ConnError();
00524
00525 TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Serial payload byte sent: %i", sent));
00526
00527 tosend -= sent;
00528 sending_ptr += sent;
00529 }
00530
00531 TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Serial message successfully sent"));
00532 }
00533
00538 inline void DCDT_Channel_Serial::SendNotify()
00539 {
00540 int sent, tosend = HSMSGHEADER_LEN;
00541 char *sending_ptr;
00542
00543
00544 sending_ptr = (char*)¬ify;
00545 while (tosend) {
00546 sent = write(device, sending_ptr, tosend);
00547 if (sent < 0)
00548 throw ConnError();
00549
00550 TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Serial Notify byte sent: %i", sent));
00551
00552 tosend -= sent;
00553 sending_ptr += sent;
00554 }
00555
00556 TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Serial Notify successfully sent"));
00557 }
00558
00563 inline void DCDT_Channel_Serial::SendAnswer(CommData* to, CommData* local)
00564 {
00565 int sent, tosend = HSMSGHEADER_LEN;
00566 char *sending_ptr;
00567
00568
00569 sending_ptr = (char*)&answer;
00570 while (tosend) {
00571 if ((sent = write(device, sending_ptr, tosend)) < 0)
00572 throw ConnError();
00573
00574 TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Serial Answer byte sent: %i", sent));
00575
00576 tosend -= sent;
00577 sending_ptr += sent;
00578 }
00579
00580 TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Serial Answer successfully sent"));
00581 Stop();
00582
00583 to = NULL;
00584 local = NULL;
00585 }
00586
00587 inline CommData* DCDT_Channel_Serial::GetStartingCD()
00588 {
00589 CommData_Serial *cd = new CommData_Serial(device_name);
00590 return cd;
00591 }
00592
00593 inline unsigned int DCDT_Channel_Serial::ReadStartingProfile()
00594 {
00595 return profile;
00596 }
00597
00600 inline void DCDT_Channel_Serial::StartConn()
00601 {
00602 HSMsgHeader *h;
00603 CommData *c;
00604 SendNotify();
00605 ReceiveTimerOff();
00606 ReceiveHS(h, c);
00607 }
00608
00609 inline void DCDT_Channel_Serial::Dispose()
00610 {
00611 }
00612
00613 inline void DCDT_Channel_Serial::Close()
00614 {
00615 if (device) {
00616 close(device);
00617 device = 0;
00618 }
00619 }
00620
00621 inline void DCDT_Channel_Serial::SetTimers()
00622 {
00623 SetReceiveTimer(SER_RECV_TIMER_VAL);
00624 ReceiveTimerOn();
00625 SetLostTimer(SER_LOST_TIMER_VAL);
00626 LostTimerOn();
00627 }
00628
00629 inline void DCDT_Channel_Serial::SetLostTimer(int usec)
00630 {
00631 tlost_value.tv_usec = usec % 1000000;
00632 tlost_value.tv_sec = usec / 1000000;
00633 }
00634
00635 inline void DCDT_Channel_Serial::LostTimerOn()
00636 {
00637 tlost_flag = 1;
00638 }
00639
00640 inline void DCDT_Channel_Serial::LostTimerOff()
00641 {
00642 tlost_flag = 0;
00643 }
00644
00645 inline void DCDT_Channel_Serial::SetConnTimer(int usec)
00646 {
00647 usec = 0;
00648 }
00649
00650 inline void DCDT_Channel_Serial::ConnTimerOn()
00651 {
00652 }
00653
00654 inline void DCDT_Channel_Serial::ConnTimerOff()
00655 {
00656 }
00657
00658 inline void DCDT_Channel_Serial::SetSendTimer(int usec)
00659 {
00660 usec = 0;
00661 }
00662
00663 inline void DCDT_Channel_Serial::SendTimerOn()
00664 {
00665 }
00666
00667 inline void DCDT_Channel_Serial::SendTimerOff()
00668 {
00669 }
00670
00671 inline void DCDT_Channel_Serial::UnblockSend()
00672 {
00673 }
00674
00675 inline void DCDT_Channel_Serial::SetReceiveTimer(int usec)
00676 {
00677 trecv_value.tv_usec = usec % 1000000;
00678 trecv_value.tv_sec = usec / 1000000;
00679 }
00680
00681 inline void DCDT_Channel_Serial::ReceiveTimerOn()
00682 {
00683 trecv_flag = 1;
00684 unblock_recv_flag = 0;
00685 }
00686
00687 inline void DCDT_Channel_Serial::ReceiveTimerOff()
00688 {
00689 trecv_flag = 0;
00690 }
00691
00692 inline void DCDT_Channel_Serial::UnblockReceive()
00693 {
00694 unblock_recv_flag = 1;
00695 }
00696
00697 inline void DCDT_Channel_Serial::Restart(int link_status)
00698 {
00699 Open(link_status);
00700 }
00701
00702 inline void DCDT_Channel_Serial::Stop()
00703 {
00704 if (device) {
00705 close(device);
00706 device = 0;
00707 }
00708 }
00709
00710 #endif