Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Class Members | File Members

DCDT_Channel_Serial.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 dEVICE cOMMUNITIES dEVELOPMENT tOOLKIT 
00003 
00004 DCDT_Channel_Serial.h
00005 
00006 COPYRIGHT (C) 2002   Alessandro Mazzini (mazzini@airlab.elet.polimi.it)
00007 
00008 
00009 This library is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU Lesser General Public
00011 License as published by the Free Software Foundation; either
00012 version 2 of the License, or (at your option) any later version.
00013 
00014 This library is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public
00020 License along with this library; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
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   // the Prepare function is responsible for the allocated area of the two classes passed as parameter
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   // Set serial channel parameters
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   // Start receiving header
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   // Receivig payload
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   // Start receiving header
00401   header = new HSMsgHeader();
00402   index = (char*)header;
00403   if ((nread = read(device, index, toread)) < 0)
00404     {
00405       //      cout << "\nread:" << nread;
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   // Sending Header
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   // Sending payload
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   // Sending
00544   sending_ptr = (char*)&notify;
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   // SENDING
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

Generated on Sun Jun 19 10:35:49 2005 for dcdt by  doxygen 1.3.9.1