📄 cserialport.c
字号:
/*************************************************************************** CSerialPort.c Network component (c) 2003-2004 Daniel Campos Fernández <danielcampos@netcourrier.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.***************************************************************************/#define __CSERIALPORT_C#include <stdio.h>#include <termios.h>#include <unistd.h>#include <sys/ioctl.h>#include <sys/poll.h>#include <time.h>#ifdef __CYGWIN__/* Cygwin defines FIONREAD in <sys/socket.h>. */#include <sys/socket.h>#endif /* __CYGWIN__ */#include "main.h"#include "tools.h"#include "CSerialPort.h"#define MAX_SERIAL_BUFFER_SIZE 65536long *ser_objwatch=NULL;long *ser_portwatch=NULL;long ser_numwatch=0;GB_STREAM_DESC SerialStream = { CSerialPort_stream_open, CSerialPort_stream_close, CSerialPort_stream_read, CSerialPort_stream_write, CSerialPort_stream_seek, CSerialPort_stream_tell, CSerialPort_stream_flush, CSerialPort_stream_eof, CSerialPort_stream_lof};DECLARE_EVENT (Serial_Read);DECLARE_EVENT (Serial_DTR);DECLARE_EVENT (Serial_DSR);DECLARE_EVENT (Serial_RTS);DECLARE_EVENT (Serial_CTS);DECLARE_EVENT (Serial_DCD);DECLARE_EVENT (Serial_RNG);void Serial_Signal_Status(serialsignal *sdata,int iPort){ int ist; sdata->s_DSR=0; sdata->s_DTR=0; sdata->s_RTS=0; sdata->s_CTS=0; sdata->s_DCD=0; sdata->s_RNG=0; ioctl(iPort,TIOCMGET,&ist); if ( ist & TIOCM_DSR ) sdata->s_DSR=1; if ( ist & TIOCM_DTR ) sdata->s_DTR=1; if ( ist & TIOCM_RTS ) sdata->s_RTS=1; if ( ist & TIOCM_CTS ) sdata->s_CTS=1; if ( ist & TIOCM_CAR ) sdata->s_DCD=1; if ( ist & TIOCM_RNG ) sdata->s_RNG=1;}void CSerialPort_Event(long param){ serialevent *eparam; eparam=(serialevent*)param; switch(eparam->nevent) { case 0: GB.Raise(eparam->obj,Serial_DTR,1,GB_T_BOOLEAN,eparam->value); break; case 1: GB.Raise(eparam->obj,Serial_DSR,1,GB_T_BOOLEAN,eparam->value); break; case 2: GB.Raise(eparam->obj,Serial_RTS,1,GB_T_BOOLEAN,eparam->value); break; case 3: GB.Raise(eparam->obj,Serial_CTS,1,GB_T_BOOLEAN,eparam->value); break; case 4: GB.Raise(eparam->obj,Serial_DCD,1,GB_T_BOOLEAN,eparam->value); break; case 5: GB.Raise(eparam->obj,Serial_RNG,1,GB_T_BOOLEAN,eparam->value); break; } GB.Unref((void**)&eparam->obj);}void CSerialPort_CallBack(long lParam){ int position=0; serialsignal newstatus; struct pollfd mypoll; int numpoll; CSERIALPORT *mythis; /* Just sleeping a little to reduce CPU waste */ struct timespec mywait; mywait.tv_sec=0; mywait.tv_nsec=1000000; nanosleep(&mywait,NULL); if ((position=search_by_integer(ser_portwatch,ser_numwatch,(int)lParam))==-1) return; mythis=(CSERIALPORT*)ser_objwatch[position]; /* Serial port signals status */ Serial_Signal_Status(&newstatus,lParam); mythis->e_DTR.value=newstatus.s_DTR; mythis->e_DSR.value=newstatus.s_DSR; mythis->e_RTS.value=newstatus.s_RTS; mythis->e_CTS.value=newstatus.s_CTS; mythis->e_DCD.value=newstatus.s_DCD; mythis->e_RNG.value=newstatus.s_RNG; if (mythis->ser_status.s_DTR != newstatus.s_DTR ) { mythis->ser_status.s_DTR = newstatus.s_DTR; GB.Ref(mythis); GB.Post(CSerialPort_Event,(long)&mythis->e_DTR); } if (mythis->ser_status.s_DSR != newstatus.s_DSR ) { mythis->ser_status.s_DSR = newstatus.s_DSR; GB.Ref(mythis); GB.Post(CSerialPort_Event,(long)&mythis->e_DSR); } if (mythis->ser_status.s_RTS != newstatus.s_RTS ) { mythis->ser_status.s_RTS = newstatus.s_RTS; GB.Ref(mythis); GB.Post(CSerialPort_Event,(long)&mythis->e_RTS); } if (mythis->ser_status.s_CTS != newstatus.s_CTS ) { mythis->ser_status.s_CTS = newstatus.s_CTS; GB.Ref(mythis); GB.Post(CSerialPort_Event,(long)&mythis->e_CTS); } if (mythis->ser_status.s_DCD != newstatus.s_DCD ) { mythis->ser_status.s_DCD = newstatus.s_DCD; GB.Ref(mythis); GB.Post(CSerialPort_Event,(long)&mythis->e_DCD); } if (mythis->ser_status.s_RNG != newstatus.s_RNG ) { mythis->ser_status.s_RNG = newstatus.s_RNG; GB.Ref(mythis); GB.Post(CSerialPort_Event,(long)&mythis->e_RNG); } /* Data Available */ mypoll.fd=lParam; mypoll.events=POLLIN; mypoll.revents=0; numpoll=poll(&mypoll,1,0); if (numpoll) { GB.Raise((void*)mythis,Serial_Read,0); }}void CSerialPort_AssignCallBack(long t_obj,int t_port){ int position=0; CSERIALPORT *mythis; mythis=(CSERIALPORT*)t_obj; position=search_by_integer(ser_objwatch,ser_numwatch,t_obj); if (position>=0) GB.Watch (t_port , GB_WATCH_NONE , (void *)CSerialPort_CallBack,0); if (position<0) { position=ser_numwatch++; Alloc_CallBack_Pointers(ser_numwatch,&ser_objwatch,&ser_portwatch); } ser_objwatch[position]=t_obj; ser_portwatch[position]=t_port; GB.Watch (t_port , GB_WATCH_WRITE , (void *)CSerialPort_CallBack,0);}void CSerialPort_FreeCallBack(long t_obj){ int myloop; int position; position=search_by_integer(ser_objwatch,ser_numwatch,t_obj); if ( position==-1 ) return; GB.Watch (ser_portwatch[position] , GB_WATCH_NONE , (void *)CSerialPort_CallBack,0); for ( myloop=position;myloop < (ser_numwatch-1);myloop++ ) { ser_objwatch[myloop]=ser_objwatch[myloop+1]; ser_portwatch[myloop]=ser_portwatch[myloop+1]; } ser_numwatch--; Alloc_CallBack_Pointers(ser_numwatch,&ser_objwatch,&ser_portwatch);}//////////////////////////////////////////////////////////////////////////////////////////**********************************************************************************//===================================================================================//##################STREAM RELATED FUNCTIONS#########################################//===================================================================================//***********************************************************************************/////XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX///////////////////////////////////////////////////////////////////////////////////////int CSerialPort_stream_open(GB_STREAM *stream, const char *path, int mode, void *data){ return -1; /* not allowed */}int CSerialPort_stream_seek(GB_STREAM *stream, long pos, int whence){ return -1; /* not allowed */}int CSerialPort_stream_tell(GB_STREAM *stream, long *pos){ return -1; /* not allowed */}int CSerialPort_stream_flush(GB_STREAM *stream){ return 0; /* OK */}int CSerialPort_stream_close(GB_STREAM *stream){ CSERIALPORT *mythis; if (!(mythis=(CSERIALPORT*)stream->_free[0])) return -1; if (mythis->iStatus) { CSerialPort_FreeCallBack((long)mythis); mythis->stream.desc=NULL; CloseSerialPort(mythis->Port,&mythis->oldtio); mythis->iStatus=0; } return 0;}int CSerialPort_stream_lof(GB_STREAM *stream, long *len){ CSERIALPORT *mythis; int bytes; *len=0; if (!(mythis=(CSERIALPORT*)stream->_free[0])) return -1; if (ioctl(mythis->Port,FIONREAD,&bytes)) return -1; *len=bytes; return 0;}int CSerialPort_stream_eof(GB_STREAM *stream){ CSERIALPORT *mythis; int bytes; if (!(mythis=(CSERIALPORT*)stream->_free[0])) return -1; if (ioctl(mythis->Port,FIONREAD,&bytes)) return -1; if (!bytes) return -1; return 0;}int CSerialPort_stream_read(GB_STREAM *stream, char *buffer, long len){ CSERIALPORT *mythis; int npos=-1; int NoBlock=0; int bytes; if (!(mythis=(CSERIALPORT*)stream->_free[0])) return -1; if (ioctl(mythis->Port,FIONREAD,&bytes)) return -1; if (bytes < len) return -1; ioctl(mythis->Port,FIONBIO,&NoBlock); npos=read(mythis->Port,(void*)buffer,len); NoBlock++; ioctl(mythis->Port,FIONBIO,&NoBlock); if (npos==len) return 0; return -1;}int CSerialPort_stream_write(GB_STREAM *stream, char *buffer, long len){ CSERIALPORT *mythis; int npos=-1; int NoBlock=0; if (!(mythis=(CSERIALPORT*)stream->_free[0])) return -1; ioctl(mythis->Port,FIONBIO,&NoBlock); npos=write(mythis->Port,(void*)buffer,len); NoBlock++; ioctl(mythis->Port,FIONBIO,&NoBlock); if (npos>=0) return 0; return -1;}/************************************************************************########################################################################## GAMBAS OBJECT PUBLIC INTERFACE##########################################################################**************************************************************************//********************************************************************Returns current Status of the port (0->Closed, 1 --> Opened)*********************************************************************/BEGIN_PROPERTY ( CSERIALPORT_Status ) GB.ReturnInteger(THIS->iStatus);END_PROPERTY/************************************* Data Set Ready *************************************/BEGIN_PROPERTY ( CSERIALPORT_DSR ) if ( !THIS->iStatus ) { GB.ReturnBoolean(0); return; } Serial_Signal_Status(&THIS->ser_status,THIS->Port); GB.ReturnBoolean(THIS->ser_status.s_DSR);END_PROPERTY/*************************************** Data Transmission Ready ***************************************/BEGIN_PROPERTY ( CSERIALPORT_DTR ) int ist; if (READ_PROPERTY) { if ( !THIS->iStatus ) { GB.ReturnBoolean(0); return; } Serial_Signal_Status(&THIS->ser_status,THIS->Port); GB.ReturnBoolean(THIS->ser_status.s_DTR); return; } if (!THIS->iStatus ) { GB.Error ("Port is Closed."); return; } ioctl(THIS->Port,TIOCMGET,&ist); if (!VPROP(GB_BOOLEAN)) ist &= ~TIOCM_DTR; else ist = ist | TIOCM_DTR; ioctl(THIS->Port,TIOCMSET,&ist);END_PROPERTY
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -