/*
 * Function:   w32DeviceInputStream_getReadCountNC
 * Purpose:    Check serial port device event 
 * Signature: ()I
 * Return:     0 - Fail
 *			   none zero - succeeds	
 */
int w32DeviceInputStream_getReadCountNC(JNIEnv *jenv, jobject jobj)
{
    DWORD	dwCommEvent = 0;
	HANDLE  osHandle;
	
	jclass		jc;
	jclass		ec;
	jfieldID	jf;
	jint 		fd = -1;
	int			dc = 0;
	// Get the exception class.
	ec = (*jenv)->FindClass(jenv, "java/io/IOException");
	assert(ec);
	// Get the file descriptor.
	jc = (*jenv)->GetObjectClass(jenv, jobj);
	assertexc(jc);
	jf = (*jenv)->GetFieldID(jenv, jc, "fd", "I");
	assertexc(jf);
	fd = (*jenv)->GetIntField(jenv, jobj, jf);
	if (fd == -1) {
		(*jenv)->ThrowNew(jenv, ec, "");
	}
	osHandle = (HANDLE)fd;
	if(!GetCommMask( osHandle, &dwCommEvent ))
		return GetLastError();
	
	dwCommEvent |= EV_RXCHAR;
	if( !SetCommMask( osHandle, dwCommEvent ))
		return GetLastError();
	if( !WaitCommEvent( osHandle, &dwCommEvent, NULL ))
		return GetLastError();
	return (dwCommEvent&EV_RXCHAR);
}  /* w32DeviceInputStream_getReadCountNC() */
Exemple #2
0
bool cSerialStream::isRinging()
{
    DWORD mask;
    CHECK(GetCommMask(m_serialHandle.getHandle()->getHandle(),
          &mask));
    return (mask & EV_RING) == EV_RING;
}
Exemple #3
0
// Wait up to msec for data to become available for reading.
// return 0 if timeout, or non-zero if one or more bytes are
// received and can be read.  -1 if an error occurs
int Serial::Input_wait(int msec)
{
	if (!port_is_open) return -1;
#if defined(LINUX) || defined(MACOSX)
	fd_set rfds;
	struct timeval tv;
	tv.tv_sec = msec / 1000;
	tv.tv_usec = (msec % 1000) * 1000;
	FD_ZERO(&rfds);
	FD_SET(port_fd, &rfds);
	return select(port_fd+1, &rfds, NULL, NULL, &tv);
#elif defined(WINDOWS)
	// http://msdn2.microsoft.com/en-us/library/aa363479(VS.85).aspx
	// http://msdn2.microsoft.com/en-us/library/aa363424(VS.85).aspx
	// http://source.winehq.org/WineAPI/WaitCommEvent.html
	COMSTAT st;
	DWORD errmask=0, eventmask=EV_RXCHAR, ret;
	OVERLAPPED ov;
	int r;
	// first, request comm event when characters arrive
	if (!SetCommMask(port_handle, EV_RXCHAR)) return -1;
	// look if there are characters in the buffer already
	if (!ClearCommError(port_handle, &errmask, &st)) return -1;
	//printf("Input_wait, %lu buffered, timeout = %d ms\n", st.cbInQue, msec);
	if (st.cbInQue > 0) return 1;

	ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (ov.hEvent == NULL) return -1;
	ov.Internal = ov.InternalHigh = 0;
	ov.Offset = ov.OffsetHigh = 0;
	if (WaitCommEvent(port_handle, &eventmask, &ov)) {
		//printf("Input_wait, WaitCommEvent, immediate success\n");
		r = 1;
	} else {
		if (GetLastError() == ERROR_IO_PENDING) {
			ret = WaitForSingleObject(ov.hEvent, msec);
			if (ret == WAIT_OBJECT_0) {
				//printf("Input_wait, WaitCommEvent, delayed success\n");
				r = 1;
			} else if (ret == WAIT_TIMEOUT) {
				//printf("Input_wait, WaitCommEvent, timeout\n");
				GetCommMask(port_handle, &eventmask);
				r = 0;
			} else {  // WAIT_FAILED or WAIT_ABANDONED
				//printf("Input_wait, WaitCommEvent, delayed error\n");
				r = -1;
			}
		} else {
			//printf("Input_wait, WaitCommEvent, immediate error\n");
			r = -1;
		}
	}
	SetCommMask(port_handle, 0);
	CloseHandle(ov.hEvent);
	return r;
#endif
}
Exemple #4
0
/*=================================================================
* Function ID :  GetEventMask
* Input       :  void
* Output      :  DWORD& dwMask
* Author      :  
* Date        :  2006  2
* Return	  :  TRUE/FALSE
* Description :  设置超时时间
* Notice	  :  
*			  :	 
*					
*=================================================================*/
bool CComSmart::GetEventMask(DWORD& dwMask)
{
	if( !GetCommMask(m_handle, &dwMask) )
	{
		sprintf(m_szErrorText,"GetEventMask()出错[%ld]!", GetLastError());
		return false;		
	}
	return true;	
}
void CSerialPort::GetMask(DWORD& dwMask)
{
  ASSERT(IsOpen());

  if (!GetCommMask(m_hComm, &dwMask))
  {
    TRACE(_T("Failed in call to GetCommMask\n"));
    AfxThrowSerialException();
  }
}
void EIO_Set(uv_work_t* req) {
  SetBaton* data = static_cast<SetBaton*>(req->data);

  if (data->rts) {
    EscapeCommFunction((HANDLE)data->fd, SETRTS);
  } else {
    EscapeCommFunction((HANDLE)data->fd, CLRRTS);
  }

  if (data->dtr) {
    EscapeCommFunction((HANDLE)data->fd, SETDTR);
  } else {
    EscapeCommFunction((HANDLE)data->fd, CLRDTR);
  }

  if (data->brk) {
    EscapeCommFunction((HANDLE)data->fd, SETBREAK);
  } else {
    EscapeCommFunction((HANDLE)data->fd, CLRBREAK);
  }

  DWORD bits = 0;

  GetCommMask((HANDLE)data->fd, &bits);

  bits &= ~(EV_CTS | EV_DSR);

  if (data->cts) {
    bits |= EV_CTS;
  }

  if (data->dsr) {
    bits |= EV_DSR;
  }

  if (!SetCommMask((HANDLE)data->fd, bits)) {
    ErrorCodeToString("Setting options on COM port (SetCommMask)", GetLastError(), data->errorString);
    return;
  }
}
void EIO_Set(uv_work_t* req) {
  SetBaton* data = static_cast<SetBaton*>(req->data);

  if (data->rts) {
    EscapeCommFunction((HANDLE)data->fd, SETRTS);
  } else {
    EscapeCommFunction((HANDLE)data->fd, CLRRTS);
  }

  if (data->dtr) {
    EscapeCommFunction((HANDLE)data->fd, SETDTR);
  } else {
    EscapeCommFunction((HANDLE)data->fd, CLRDTR);
  }

  if (data->brk) {
    EscapeCommFunction((HANDLE)data->fd, SETBREAK);
  } else {
    EscapeCommFunction((HANDLE)data->fd, CLRBREAK);
  }

  DWORD bits = 0;

  GetCommMask((HANDLE)data->fd, &bits);

  bits &= ~(EV_CTS | EV_DSR);

  if (data->cts) {
    bits |= EV_CTS;
  }

  if (data->dsr) {
    bits |= EV_DSR;
  }
  // TODO check for error
  data->result = SetCommMask((HANDLE)data->fd, bits);
}
Exemple #8
0
//
//  The CommThread Function.
///线程函数
///监视线程的大致流程:
///检查串口-->进入循环{WaitCommEvent(不阻塞询问)询问事件-->如果有事件来到-->到相应处理(关闭\读\写)}
//
DWORD WINAPI CSerialPort::CommThread(LPVOID pParam)
{
    // Cast the void pointer passed to the thread back to
    // a pointer of CSerialPort class
    CSerialPort *port = (CSerialPort*)pParam;

    // Set the status variable in the dialog class to
    // TRUE to indicate the thread is running.
    ///TRUE表示线程正在运行
    port->m_bThreadAlive = TRUE;

    // Misc. variables
    DWORD BytesTransfered = 0;
    DWORD Event = 0;
    DWORD CommEvent = 0;
    DWORD dwError = 0;
    COMSTAT comstat;
    BOOL  bResult = TRUE;

    // Clear comm buffers at startup
    ///开始时清除串口缓冲
    if (port->m_hComm)		// check if the port is opened
        PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);

    // begin forever loop.  This loop will run as long as the thread is alive.
    ///只要线程存在就不断读取数据
    for (;;)
    {

        // Make a call to WaitCommEvent().  This call will return immediatly
        // because our port was created as an async port (FILE_FLAG_OVERLAPPED
        // and an m_OverlappedStructerlapped structure specified).  This call will cause the
        // m_OverlappedStructerlapped element m_OverlappedStruct.hEvent, which is part of the m_hEventArray to
        // be placed in a non-signeled state if there are no bytes available to be read,
        // or to a signeled state if there are bytes available.  If this event handle
        // is set to the non-signeled state, it will be set to signeled when a
        // character arrives at the port.

        // we do this for each port!

        /*
        WaitCommEvent函数第3个参数1pOverlapped可以是一个OVERLAPPED结构的变量指针
        ,也可以是NULL,当用NULL时,表示该函数是同步的,否则表示该函数是异步的。
        调用WaitCommEvent时,如果异步操作不能立即完成,会立即返回FALSE,系统在
        WaitCommEvent返回前将OVERLAPPED结构成员hEvent设为无信号状态,等到产生通信
        事件时,系统将其置有信号
        */

        bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov);///表示该函数是异步的

        if (!bResult)
        {
            // If WaitCommEvent() returns FALSE, process the last error to determin
            // the reason..
            ///如果WaitCommEvent返回Error为FALSE,则查询错误信息
            switch (dwError = GetLastError())
            {
            case ERROR_IO_PENDING: 	///正常情况,没有字符可读
            {
                // This is a normal return value if there are no bytes
                // to read at the port.
                // Do nothing and continue
                break;
            }
            case 87:///系统错误
            {
                // Under Windows NT, this value is returned for some reason.
                // I have not investigated why, but it is also a valid reply
                // Also do nothing and continue.
                break;
            }
            default:///发生其他错误,其中有串口读写中断开串口连接的错误
            {
                // All other error codes indicate a serious error has
                // occured.  Process this error.
                port->ProcessErrorMessage("WaitCommEvent()");
                break;
            }
            }
        }
        else	///WaitCommEvent()能正确返回
        {
            // If WaitCommEvent() returns TRUE, check to be sure there are
            // actually bytes in the buffer to read.
            //
            // If you are reading more than one byte at a time from the buffer
            // (which this program does not do) you will have the situation occur
            // where the first byte to arrive will cause the WaitForMultipleObjects()
            // function to stop waiting.  The WaitForMultipleObjects() function
            // resets the event handle in m_OverlappedStruct.hEvent to the non-signelead state
            // as it returns.
            //
            // If in the time between the reset of this event and the call to
            // ReadFile() more bytes arrive, the m_OverlappedStruct.hEvent handle will be set again
            // to the signeled state. When the call to ReadFile() occurs, it will
            // read all of the bytes from the buffer, and the program will
            // loop back around to WaitCommEvent().
            //
            // At this point you will be in the situation where m_OverlappedStruct.hEvent is set,
            // but there are no bytes available to read.  If you proceed and call
            // ReadFile(), it will return immediatly due to the async port setup, but
            // GetOverlappedResults() will not return until the next character arrives.
            //
            // It is not desirable for the GetOverlappedResults() function to be in
            // this state.  The thread shutdown event (event 0) and the WriteFile()
            // event (Event2) will not work if the thread is blocked by GetOverlappedResults().
            //
            // The solution to this is to check the buffer with a call to ClearCommError().
            // This call will reset the event handle, and if there are no bytes to read
            // we can loop back through WaitCommEvent() again, then proceed.
            // If there are really bytes to read, do nothing and proceed.

            bResult = ClearCommError(port->m_hComm, &dwError, &comstat);

            if (comstat.cbInQue == 0)
                continue;
        }	// end if bResult

        ///主等待函数,会阻塞线程
        // Main wait function.  This function will normally block the thread
        // until one of nine events occur that require action.
        ///等待3个事件:关断/读/写,有一个事件发生就返回
        Event = WaitForMultipleObjects(3, ///3个事件
                                       port->m_hEventArray, ///事件数组
                                       FALSE, ///有一个事件发生就返回
                                       INFINITE);///超时时间

        switch (Event)
        {
        case 0:
        {
            // Shutdown event.  This is event zero so it will be
            // the higest priority and be serviced first.
            ///关断事件,关闭串口
            CloseHandle(port->m_hComm);
            port->m_hComm=NULL;
            port->m_bThreadAlive = FALSE;

            // Kill this thread.  break is not needed, but makes me feel better.
            //AfxEndThread(100);
            ::ExitThread(100);

            break;
        }
        case 1:	// read event 将定义的各种消息发送出去
        {
            GetCommMask(port->m_hComm, &CommEvent);
            if (CommEvent & EV_RXCHAR) //接收到字符,并置于输入缓冲区中
                ReceiveChar(port);

            if (CommEvent & EV_CTS) //CTS信号状态发生变化
                ::SendMessage(port->m_pOwner, WM_COMM_CTS_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
            if (CommEvent & EV_RXFLAG) //接收到事件字符,并置于输入缓冲区中
                ::SendMessage(port->m_pOwner, WM_COMM_RXFLAG_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
            if (CommEvent & EV_BREAK)  //输入中发生中断
                ::SendMessage(port->m_pOwner, WM_COMM_BREAK_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
            if (CommEvent & EV_ERR) //发生线路状态错误,线路状态错误包括CE_FRAME,CE_OVERRUN和CE_RXPARITY
                ::SendMessage(port->m_pOwner, WM_COMM_ERR_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
            if (CommEvent & EV_RING) //检测到振铃指示
                ::SendMessage(port->m_pOwner, WM_COMM_RING_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);

            break;
        }
        case 2: // write event 发送数据
        {
            // Write character event from port
            WriteChar(port);
            break;
        }
        default:
        {
            AfxMessageBox("接收有问题!");
            break;
        }

        } // end switch

    } // close forever loop

    return 0;
}
//
//  The CommThread Function.
//
UINT CSerialPort::CommThread(LPVOID pParam)
{
	// Cast the void pointer passed to the thread back to
	// a pointer of CSerialPort class
	CSerialPort *port = (CSerialPort*)pParam;
	
	// Set the status variable in the dialog class to
	// TRUE to indicate the thread is running.
	port->m_bThreadAlive = TRUE;	
		
	// Misc. variables
	DWORD BytesTransfered = 0; 
	DWORD Event = 0;
	DWORD CommEvent = 0;
	DWORD dwError = 0;
	static COMSTAT comstat;
	BOOL  bResult = TRUE;
		
	// Clear comm buffers at startup
	if (port->m_hComm)		// check if the port is opened
		PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);

	// begin forever loop.  This loop will run as long as the thread is alive.
	for (;;) 
	{ 

		// Make a call to WaitCommEvent().  This call will return immediatly
		// because our port was created as an async port (FILE_FLAG_OVERLAPPED
		// and an m_OverlappedStructerlapped structure specified).  This call will cause the 
		// m_OverlappedStructerlapped element m_OverlappedStruct.hEvent, which is part of the m_hEventArray to 
		// be placed in a non-signeled state if there are no bytes available to be read,
		// or to a signeled state if there are bytes available.  If this event handle 
		// is set to the non-signeled state, it will be set to signeled when a 
		// character arrives at the port.

		// we do this for each port!

		bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov);

		if (!bResult)  
		{ 
			// If WaitCommEvent() returns FALSE, process the last error to determin
			// the reason..
			switch (dwError = GetLastError()) 
			{ 
			case ERROR_IO_PENDING: 	
				{ 
					// This is a normal return value if there are no bytes
					// to read at the port.
					// Do nothing and continue
					break;
				}
			case 87:
				{
					// Under Windows NT, this value is returned for some reason.
					// I have not investigated why, but it is also a valid reply
					// Also do nothing and continue.
					break;
				}
			default:
				{
					// All other error codes indicate a serious error has
					// occured.  Process this error.
					port->ProcessErrorMessage("WaitCommEvent()");
					break;
				}
			}
		}
		else
		{
			// If WaitCommEvent() returns TRUE, check to be sure there are
			// actually bytes in the buffer to read.  
			//
			// If you are reading more than one byte at a time from the buffer 
			// (which this program does not do) you will have the situation occur 
			// where the first byte to arrive will cause the WaitForMultipleObjects() 
			// function to stop waiting.  The WaitForMultipleObjects() function 
			// resets the event handle in m_OverlappedStruct.hEvent to the non-signelead state
			// as it returns.  
			//
			// If in the time between the reset of this event and the call to 
			// ReadFile() more bytes arrive, the m_OverlappedStruct.hEvent handle will be set again
			// to the signeled state. When the call to ReadFile() occurs, it will 
			// read all of the bytes from the buffer, and the program will
			// loop back around to WaitCommEvent().
			// 
			// At this point you will be in the situation where m_OverlappedStruct.hEvent is set,
			// but there are no bytes available to read.  If you proceed and call
			// ReadFile(), it will return immediatly due to the async port setup, but
			// GetOverlappedResults() will not return until the next character arrives.
			//
			// It is not desirable for the GetOverlappedResults() function to be in 
			// this state.  The thread shutdown event (event 0) and the WriteFile()
			// event (Event2) will not work if the thread is blocked by GetOverlappedResults().
			//
			// The solution to this is to check the buffer with a call to ClearCommError().
			// This call will reset the event handle, and if there are no bytes to read
			// we can loop back through WaitCommEvent() again, then proceed.
			// If there are really bytes to read, do nothing and proceed.
		
			bResult = ClearCommError(port->m_hComm, &dwError, &comstat);

			if (comstat.cbInQue == 0)
				continue;
		}	// end if bResult

		// Main wait function.  This function will normally block the thread
		// until one of nine events occur that require action.
		Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE);

		switch (Event)
		{
		case 0:
			{
				// Shutdown event.  This is event zero so it will be
				// the higest priority and be serviced first.

			 	port->m_bThreadAlive = FALSE;
				
				// Kill this thread.  break is not needed, but makes me feel better.
				AfxEndThread(100);
				break;
			}
		case 1:	// read event
			{
				GetCommMask(port->m_hComm, &CommEvent);
				if (CommEvent & EV_CTS)
					::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_CTS_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
				if (CommEvent & EV_RXFLAG)
					::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RXFLAG_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
				if (CommEvent & EV_BREAK)
					::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_BREAK_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
				if (CommEvent & EV_ERR)
					::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_ERR_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
				if (CommEvent & EV_RING)
					::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RING_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
				
				if (CommEvent & EV_RXCHAR)
					// Receive character event from port.
					ReceiveChar(port, comstat);
					
				break;
			}  
		case 2: // write event
			{
				// Write character event from port
				WriteChar(port);
				break;
			}

		} // end switch

	} // close forever loop

	return 0;
}
Exemple #10
0
int RS232Interface::OpenSerial(int no)
{
	UserDebug1(UserApp1, "RS232Interface::OpenSerial(%d) I\n", no);

	int ret_val = E2ERR_OPENFAILED;

	if (no >= 1 && no <= MAX_COMPORTS)
	{
#ifdef	_WINDOWS
		char str[MAXPATH];

		snprintf(str, MAXPATH, "%s%d", profile->GetDevName(), no);
		hCom = CreateFile(str,
			GENERIC_READ | GENERIC_WRITE,
			0,		/* comm devices must be opened w/exclusive-access */
			NULL,	/* no security attrs */
			OPEN_EXISTING, /* comm devices must use OPEN_EXISTING */
			0,		/* not overlapped I/O */
			NULL	/* hTemplate must be NULL for comm devices */
		);

		if ( hCom != INVALID_HANDLE_VALUE )
		{
			GetCommState(hCom, &old_dcb);
			GetCommTimeouts(hCom, &old_timeout);
			GetCommMask(hCom, &old_mask);

			if (wait_endTX_mode)
				SetCommMask(hCom, EV_TXEMPTY);
			else
				SetCommMask(hCom, 0);

			SetSerialTimeouts();
			SetSerialParams();

			ret_val = OK;
		}
#else
#ifdef	_LINUX_

		char devname[MAXPATH];
		int chars_read;

		no--;		//linux call ttyS0 --> COM1, ttyS1 --> COM2, etc..

		// implement device locking in /var/lock/LCK..ttySx
		snprintf(lockname, MAXPATH, "%s/LCK..%s%d", profile->GetLockDir(), profile->GetDevName(), no);
		UserDebug1(UserApp2, "RS232Interface::OpenSerial() now lock the device %s\n", lockname);

		fd = open ((const char *)lockname,O_RDWR|O_EXCL|O_CREAT);
		if (fd < 0)
		{
			fd = open ((const char *)lockname,O_RDONLY);
			lockname[0]=0;
			UserDebug1(UserApp2, "RS232Interface::OpenSerial Can't lock port %d\n", no);
			if (fd < 0)
				return ret_val;
			chars_read = read(fd,devname,MAXLINESIZE-1);
			devname[chars_read]=0;
			UserDebug1(UserApp2, "RS232Interface::OpenSeriial locked by %s\n", devname);
			close(fd);
			return ret_val;
		}

		snprintf(devname, MAXPATH, "%10d\n", (int) getpid() );
		write(fd, devname, strlen(devname));
		close(fd);
		fd = INVALID_HANDLE_VALUE;

		snprintf(devname, MAXPATH, "%s/%s%d", profile->GetDevDir(), profile->GetDevName(), no);
		UserDebug1(UserApp2, "RS232Interface::OpenSerial() now open the device %s\n", devname);

		fd = open ((const char *)devname, O_RDWR|O_NONBLOCK|O_EXCL);
	//	fd = open ((const char *)devname, O_RDWR);

		UserDebug1(UserApp2, "RS232Interface::OpenSerial open result = %d\n", fd);

		if (fd < 0)
		{
			UserDebug1(UserApp2, "RS232Interface::OpenSerial can't open the device %s\n", devname);
			unlink(lockname);
			return ret_val;
		}
		// Check for the needed IOCTLS
#if defined(TIOCSBRK) && defined(TIOCCBRK) //check if available for compilation
		// Check if available during runtime
		if ((ioctl(fd,TIOCSBRK,0) == -1) || (ioctl(fd,TIOCCBRK,0) == -1))
		{
			UserDebug(UserApp2, "RS232Interface::OpenPort IOCTL not available\n");
			return ret_val;
		}
#else
		close(fd);
		fd = INVALID_HANDLE_VALUE;
		unlink(lockname);
		return ret_val;
#endif	/*TIOCSBRK*/

		/* open sets RTS and DTR, reset it */
#if defined(TIOCMGET) && defined(TIOCMSET) //check if available for compilation
		int flags;

		if (ioctl(fd,TIOCMGET, &flags)== -1)
		{
			UserDebug(UserApp2, "RS232Interface::OpenPort IOCTL not available\n");
			close(fd);
			fd = INVALID_HANDLE_VALUE;
			unlink(lockname);
			return ret_val;
		}
		else
		{
			flags &= ~(TIOCM_RTS|TIOCM_DTR);
			if (ioctl(fd,TIOCMSET, &flags)== -1)
			{
				UserDebug(UserApp2, "RS232Interface::OpenPort IOCTL not available\n");
				close(fd);
				fd = INVALID_HANDLE_VALUE;
				unlink(lockname);
				return ret_val;
			}
		}
#endif /*TIOCMGET */

		UserDebug(UserApp2, "RS232Interface::OpenPort GETATTR\n");
		if (tcgetattr(fd, &old_termios) == -1)
		{
			UserDebug(UserApp2, "RS232Interface::OpenPort GETATTR failed\n");

			close(fd);
			fd = INVALID_HANDLE_VALUE;
			unlink(lockname);
			return ret_val;
		}

		UserDebug(UserApp2, "RS232Interface::OpenPort SetTimeouts && Params\n");
		if ( SetSerialTimeouts() != OK )
		{
			UserDebug(UserApp2, "RS232Interface::OpenPort SetSerialTimeouts() failed\n");
			close(fd);
			fd = INVALID_HANDLE_VALUE;
			unlink(lockname);
		}
		else
		if ( SetSerialParams() != OK )
		{
			UserDebug(UserApp2, "RS232Interface::OpenPort SetSerialParams() failed\n");
			close(fd);
			fd = INVALID_HANDLE_VALUE;
			unlink(lockname);
		}
		else
		{
			fd_clear_flag(fd, O_NONBLOCK);		//Restore to blocking mode
			ret_val = OK;
		}

#endif	/*_LINUX_*/
#endif
	}

	UserDebug1(UserApp2, "RS232Interface::OpenSerial() = %d O\n", ret_val);

	return ret_val;
}
Exemple #11
0
int main(int argc, char *argv[])
{
    HANDLE hCommPort;

    const char* config_file = ".\\serie.ini";

    unsigned int baud_rate = GetPrivateProfileInt("Configuracion",
                                                  "Velocidad",
                                                  9600,
                                                  config_file);

    unsigned int data_bits = GetPrivateProfileInt("Configuracion",
                                                  "BitsDatos",
                                                  8,
                                                  config_file);

    unsigned int stop_bits = GetPrivateProfileInt("Configuracion",
                                                  "BitsParada",
                                                  2,
                                                  config_file);

    char port_name[30];
    unsigned int _len = GetPrivateProfileString("Configuracion",
                                                "Puerto",
                                                "COM1",
                                                port_name,
                                                sizeof(port_name),
                                                config_file);

    char parity[20];
    unsigned int _parity_len = GetPrivateProfileString("Configuracion",
                                                       "Paridad",
                                                       "Sin paridad",
                                                       parity,
                                                       sizeof(parity),
                                                       config_file);

    printf("Datos: %d %d %d %s %s\n", baud_rate, data_bits, stop_bits, port_name, parity);

    //-- Abre el puerto serie
    hCommPort = serie_abrir(port_name, baud_rate, data_bits, stop_bits, parity);
    if (hCommPort == INVALID_HANDLE_VALUE)
    {
        perror("ERROR: No se puede acceder al puerto serie.");
        exit(2);
    }

    DWORD mask;
    if (!GetCommMask(hCommPort, &mask)) {
        perror("GetCommMask");
        exit(3);
    }

    if (!SetCommMask(hCommPort, mask | EV_ERR)) {
        perror("SetCommMask");
        exit(4);
    }

    printf("Pulse la tecla ESC para empezar a leer\n");
    while ( _getch() != ESC ) { /* Do nothing */ }

    //-- Crea el hilo encargado de la lectura de datos del puerto serie
    HANDLE hHiloLectura;
    DWORD idHiloLectura;
    hHiloLectura = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)HiloLectura, &hCommPort, 0, &idHiloLectura);
    if (hHiloLectura == NULL)
    {
        perror("ERROR: No se puede crear el hilo de lectura");
        exit(5);
    }

    printf("Pulse la tecla ESC para salir\n");

    //-- Bucle principal de escritura por el puerto serie
    char c;
    do
    {
        c = _getch();
        if (c != ESC) {
            serie_escribir(hCommPort, &c, sizeof(c));
        }
    } while (c != ESC);

    //-- Termina el hilo de lectura
    TerminateThread(hHiloLectura, 0);
    CloseHandle(hHiloLectura);

    //-- Cierra el puerto serie
    serie_cerrar(hCommPort);

    system("PAUSE");
    return 0;
}
Exemple #12
0
DWORD HiloLectura(LPDWORD lpParam)
{
    DWORD dwEvtMask;

    OVERLAPPED ov = { 0 };
    ov.hEvent = CreateEvent(0, TRUE, 0, 0);

    //-- Recoge el manejador del puerto serie
    HANDLE hCommPort = (HANDLE)*lpParam;

    char szDatos[MAXCHARS + 1];

    DWORD dwErrors;

    //-- Bucle infinito de lectura
    while (TRUE)
    {
        if (!WaitCommEvent(hCommPort, &dwEvtMask, &ov)) {}

        if (!ClearCommError(hCommPort, &dwErrors, NULL)) {
            perror("ClearCommError");
            continue;
        }

        if (dwErrors & CE_FRAME) {
            printf("Frame error\n");
        }
        if (dwErrors & CE_RXPARITY) {
            printf("Parity error\n");
        }
        if (dwErrors & CE_OVERRUN) {
            printf("Overrun\n");
        }
        if (dwErrors & CE_BREAK) {
            printf("CE_BREAK\n");
        }
        if (dwErrors & CE_RXOVER) {
            printf("CE_RXOVER\n");
        }

        //-- Espera a que haya algo que leer
        if (WAIT_OBJECT_0 == WaitForSingleObject(ov.hEvent, INFINITE))
        {
            DWORD dwMask;
            if (GetCommMask(hCommPort, &dwMask))
            {
                if (dwMask & EV_TXEMPTY)
                {
                    ResetEvent(ov.hEvent);
                    continue;
                }
            }

            //-- Lee los datos del puerto serie
            if (serie_leer(hCommPort, szDatos, sizeof(szDatos)) > 0)
                printf("%s", szDatos);
            else
                printf("serie_leer returned 0");

            //-- Reinicia el estado del evento
            ResetEvent(ov.hEvent);
        }
    }

    return 0;
}
Exemple #13
0
int SIO_WaitForData(SIO_INFO *s,long timedelay)
{
#ifdef WINDOWS
  int ret;
  long tms;
  DWORD err;
  DWORD emask;
  COMMTIMEOUTS ct;
  COMSTAT comstat;

  /* sanity check */
  if (s==NULL)
    return -1;

  tms=timedelay/1000;
  tms+=ADD_DELAY;

  ret=0;
  GetCommTimeouts(s->fd,&ct);
  if (timedelay==SIO_READ_WAIT_FOREVER) {
    ct.ReadIntervalTimeout=MAXDWORD;
    ct.ReadTotalTimeoutMultiplier=0;
    ct.ReadTotalTimeoutConstant=MAXDWORD;
  } else {
    ct.ReadIntervalTimeout=tms;
    ct.ReadTotalTimeoutMultiplier=10;
    ct.ReadTotalTimeoutConstant=tms;
    /*
    ct.ReadIntervalTimeout=10;
    ct.ReadTotalTimeoutMultiplier=10;
    ct.ReadTotalTimeoutConstant=100;
    */
  }
  SetCommTimeouts(s->fd,&ct);

  /* have a quick look to see if there is data in the buffers
   * still ... and return notification to the caller without
   * doing any of the messy thread stuff with timeouts
   */
  ClearCommError(s->fd,&emask,&comstat);
  if (comstat.cbInQue>0)
    return(1);

#if 0
  /* now wait for a character to arrive ... unfortunately this
   * operation does not have any form of timeout on it which
   * makes it rather useless for detecting IO!
   */
  emask=EV_RXCHAR|EV_ERR|EV_RLSD|EV_CTS|EV_DSR;
  ret=WaitCommEvent(s->fd,&emask,NULL);
  if (ret) {
    /* we have a character we can read ... */
    return(1);
  } else {
    err=GetLastError();
    return(-1);
  }
#endif

  /* get the worker thread to start doing something */
  s->eventMask=EV_RXCHAR|EV_ERR|EV_RLSD|EV_CTS|EV_DSR; /* Custom: DCD? */

#ifdef NO_THREADS
  /* use overlapped I/O notification to simulate having
   * a timeout on WaitCommEvent() 
   */
  sio_init_overlapped(s);
  if (WaitCommEvent(s->fd,&s->eventMask,s->overlapped)==FALSE) {
    err=GetLastError();
    if (err==ERROR_IO_PENDING) {
  if (sio_wait_overlapped(s,timedelay)) {
    return(1);
  } else {
    return(-1);
  }
    }
  } else {
    return(1);
  }
#else /* !NO_THREADS */

  /* this thread stuff works fine under Win95 but doesn't under WinNT */
  SetEvent(s->hStartWait);
  err=WaitForSingleObject(s->hFinishedWait,tms);

  switch(err) {
    case WAIT_OBJECT_0:
      return(1);
    case WAIT_ABANDONED:
    case WAIT_TIMEOUT:
    default:
      {
        DWORD oldMask;

        /* make WaitCommEvent return in the worker thread */
        GetCommMask(s->fd,&oldMask);
        SetCommMask(s->fd,0);
        SetCommMask(s->fd,oldMask);

      }
        return(-1);
  }
#endif /* NO_THREADS */

#elif defined( __palmos__ )
  Long timeout;

  /* sanity check */
  if (s==NULL)
    return -1;

  if( timedelay==SIO_READ_WAIT_FOREVER ) {
    timeout = -1;
  } else {
    timeout = ( ( timedelay * sysTicksPerSecond ) / 1000000 ) + 1;
  }

  if( SerReceiveWait( s->fd, 1, (Long) timeout )!=0 ) return( -1 );

  return( 1 );

#else /* !WINDOWS && !__palmos__ */
  int ret;
  fd_set readfds;
  struct timeval tv, *tvwait;

  /* sanity check */
  if (s==NULL)
    return -1;

  /* isn't the Unix way of doing this so much more elegant :-) */
  FD_ZERO(&readfds); 
  FD_SET(s->fd,&readfds);

  tv.tv_sec=0; 
  tv.tv_usec=timedelay;

  if (timedelay==SIO_READ_WAIT_FOREVER)
    tvwait=NULL;
  else
    tvwait=&tv;

  ret=select(s->fd+1,&readfds,NULL,NULL,tvwait);

  /* if there is one descriptor ready for read then it is
   * a success ... so we can just use the return from select
   */
  return(ret);
#endif /* WINDOWS */

}
unsigned __stdcall CSerialCommHelper::ThreadFn(void*pvParam)
{

	CSerialCommHelper* CommHelper = (CSerialCommHelper*) pvParam ;
	bool condition = true;
	DWORD EventMask=0;

	OVERLAPPED ov;
	memset(&ov,0,sizeof(ov));
	ov.hEvent = CreateEvent( 0,true,0,0);
	HANDLE Handles[2];
	Handles[0] = CommHelper->ThreadTerm;

	DWORD Wait;
	SetEvent(CommHelper->ThreadStarted);
	while (  condition )
	{

		BOOL res = ::WaitCommEvent(CommHelper->CommPort,&EventMask, &ov) ;
		if ( !res )
		{

			g_assert( GetLastError () == ERROR_IO_PENDING);
		}


		Handles[1] = ov.hEvent ;

		Wait = WaitForMultipleObjects (2,Handles,FALSE,INFINITE);
		switch ( Wait )
		{
			case WAIT_OBJECT_0:
				{
					_endthreadex(1);
				}
				break;
			case WAIT_OBJECT_0 + 1:
				{
					DWORD Mask;
					if (GetCommMask(CommHelper->CommPort,&Mask) )
					{
						if ( Mask == EV_TXEMPTY )
						{
							MTXDBG(CRITICAL,_("Data sent"));
							ResetEvent ( ov.hEvent );
							continue;
						}

					}
					//read data here...
					int accum = 0;

					CommHelper->SerialBuffer.LockBuffer();

					try 
					{
						std::string Debug;
						BOOL res = FALSE;

						DWORD BytesRead = 0;
						OVERLAPPED ovRead;
						memset(&ovRead,0,sizeof(ovRead));
						ovRead.hEvent = CreateEvent( 0,true,0,0);

						do
						{
							ResetEvent( ovRead.hEvent  );
							char Tmp[1];
							int iSize  = sizeof ( Tmp );
							memset(Tmp,0,sizeof Tmp);
							res = ::ReadFile(CommHelper->CommPort,Tmp,sizeof(Tmp),&BytesRead,&ovRead);
							if (!res ) 
							{
								condition = FALSE;
								break;
							}
							if ( BytesRead > 0 )
							{
								CommHelper->SerialBuffer.AddData ( Tmp,BytesRead );
								accum += BytesRead;
							}
						}while (0);// BytesRead > 0 );
						CloseHandle(ovRead.hEvent );
					}
					catch(...)
					{
						g_assert(0);
					}

					//if we are not in started state then we should flush the queue...( we would still read the data)
					if (CommHelper->GetCurrentState() != SS_Started ) 
					{
						accum  = 0;
						CommHelper->SerialBuffer.Flush ();
					}

					CommHelper->SerialBuffer.UnLockBuffer();

					MTXDBG(CRITICAL,_("RCSeri: Q Unlocked:"));
					if ( accum > 0 )
					{
						MTXDBG(CRITICAL,_("CSerialCommHelper(worker thread):  SetDataReadEvent() len:{%d} data:{%s}"),accum,(CommHelper->SerialBuffer.GetData()).c_str ()  );
						CommHelper->SetDataReadEvent(); 
					}
					ResetEvent ( ov.hEvent );
				}
				break;
		}//switch
	}
	return 0;
}
Exemple #15
0
BOOL
DmKdInitComPort(
    BOOL KdModemControl
    )
{
    char   ComPortName[16];
    ULONG  Baud;
    DCB    LocalDcb;
    COMMTIMEOUTS To;
    DWORD  mask;


    Baud = (ULONG)KdOptions[KDO_BAUDRATE].value;
    sprintf( ComPortName, "\\\\.\\com%d", (ULONG)KdOptions[KDO_PORT].value );

    //
    // Open the device
    //
    DmKdComPort = CreateFile(
                        (PSZ)ComPortName,
                        GENERIC_READ | GENERIC_WRITE,
                        0,
                        NULL,
                        OPEN_ALWAYS,
                        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
                        NULL
                        );

    if ( DmKdComPort == (HANDLE)-1 ) {
        return FALSE;
    }

    SetupComm(DmKdComPort,(DWORD)4096,(DWORD)4096);

    //
    // Create the events used by the overlapped structures for the
    // read and write.
    //

    ReadOverlapped.hEvent = CreateEvent(
                                NULL,
                                TRUE,
                                FALSE,NULL
                                );

    if (!ReadOverlapped.hEvent) {
        return FALSE;
    }

    WriteOverlapped.hEvent = CreateEvent(
                                 NULL,
                                 TRUE,
                                 FALSE,NULL
                                 );

    if (!WriteOverlapped.hEvent) {
        return FALSE;
    }

    ReadOverlapped.Offset = 0;
    ReadOverlapped.OffsetHigh = 0;

    WriteOverlapped.Offset = 0;
    WriteOverlapped.OffsetHigh = 0;

    //
    // Set up the Comm port....
    //

    if (!GetCommState(
             DmKdComPort,
             &LocalDcb
             )) {

        return FALSE;
    }

    LocalDcb.BaudRate = Baud;
    LocalDcb.ByteSize = 8;
    LocalDcb.Parity = NOPARITY;
    LocalDcb.StopBits = ONESTOPBIT;
    LocalDcb.fDtrControl = DTR_CONTROL_ENABLE;
    LocalDcb.fRtsControl = RTS_CONTROL_ENABLE;
    LocalDcb.fBinary = TRUE;
    LocalDcb.fOutxCtsFlow = FALSE;
    LocalDcb.fOutxDsrFlow = FALSE;
    LocalDcb.fOutX = FALSE;
    LocalDcb.fInX = FALSE;

    if (!SetCommState(
            DmKdComPort,
            &LocalDcb
            )) {

        return FALSE;
    }

    //
    // Set the normal read and write timeout time.
    // The symbols are 10 millisecond intervals.
    //

    To.ReadIntervalTimeout = 0;
    To.ReadTotalTimeoutMultiplier = 0;
    To.ReadTotalTimeoutConstant = 4 * 1000;
    To.WriteTotalTimeoutMultiplier = 0;
    To.WriteTotalTimeoutConstant = 4 * 1000;

    if (!SetCommTimeouts(
             DmKdComPort,
             &To
             )) {

        return FALSE;
    }

    DmKdComEvent = 0;
    if (KdModemControl) {

        //
        //  Debugger is being run over a modem.  Set event to watch
        //  carrier detect.
        //

        GetCommMask (DmKdComPort, &mask);
        mask = mask | EV_ERR; // | EV_RLSD;
        if (!SetCommMask (DmKdComPort, mask)) {
            return FALSE;
        }

        EventOverlapped.hEvent = CreateEvent(
                                    NULL,
                                    TRUE,
                                    FALSE,NULL
                                    );

        if (!EventOverlapped.hEvent) {
            return FALSE;
        }

        EventOverlapped.Offset = 0;
        EventOverlapped.OffsetHigh = 0;

        DmKdComEvent = 1;     // Fake an event, so modem status will be checked
    }

    InitializeCriticalSection(&csComPort);
    InitializeCriticalSection(&csPacket);

    return TRUE;
}