summaryrefslogblamecommitdiffstats
path: root/cpukit/libmisc/serdbg/serdbgio.c
blob: 07c77a0b0373b94391292ce1f30098c8015c033e (plain) (tree)
1
2
3
4
5
6
7
8
9
10

                                           







                                                               
                                                                  

                       



















                                                                              
   
 



                    


                         
                               




                               
                         




















                                                                             
                                                   





                                                                             
                            






























                                         
                                                            





                                                        
    





                                        
                            



                                              
                                





                                                  
                             










                                                     
                          

                      
                                     


                            
                        







                                                 
                          

                      
                       

                                       
                       
                
 






                                                         
                            

     

                      






















                                                                             
                                              






                                                  
                             






























                                                                             
                             


                                              
                                                  











                                                         
/* SPDX-License-Identifier: BSD-2-Clause */

/*
 * TERMIOS serial gdb interface support
 * the functions in this file allow the standard gdb stubs like
 * "m68k-stub.c" to access any serial interfaces that work with
 * RTEMS termios in polled mode
 */

/*
 * Copyright (c) 2002 IMD Ingenieurbuero fuer Microcomputertechnik
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <rtems.h>
#include <rtems/libio_.h>
#include <errno.h>
#include <unistd.h> /* close */
#include <stdio.h>
#include <fcntl.h>
#include <termios.h>

#include <rtems/termiostypes.h>
#include <rtems/serdbg.h>


/*
 * internal variables
 */
int serdbg_fd = -1;
struct rtems_termios_tty *serdbg_tty;

/*=========================================================================*\
| Function:                                                                 |
\*-------------------------------------------------------------------------*/
int serdbg_open

/*-------------------------------------------------------------------------*\
| Purpose:                                                                  |
|    try to open given serial debug port                                    |
+---------------------------------------------------------------------------+
| Input Parameters:                                                         |
\*-------------------------------------------------------------------------*/
(
 const char *dev_name, /* name of device to open */
 uint32_t   baudrate   /* baud rate to use       */
)
/*-------------------------------------------------------------------------*\
| Return Value:                                                             |
|    0 on success, -1 and errno otherwise                                   |
\*=========================================================================*/
{
  bool err_occurred = false;
  rtems_libio_t *iop = NULL;
  struct termios act_termios;
  tcflag_t baudcode = B0;

#define FD_STORE_CNT 3
  int fd_store[FD_STORE_CNT];
  int fd_store_used = 0;

  /*
   * translate baudrate into baud code
   */
  switch(baudrate) {
  case     50: baudcode =     B50; break;
  case     75: baudcode =     B75; break;
  case    110: baudcode =    B110; break;
  case    134: baudcode =    B134; break;
  case    150: baudcode =    B150; break;
  case    200: baudcode =    B200; break;
  case    300: baudcode =    B300; break;
  case    600: baudcode =    B600; break;
  case   1200: baudcode =   B1200; break;
  case   1800: baudcode =   B1800; break;
  case   2400: baudcode =   B2400; break;
  case   4800: baudcode =   B4800; break;
  case   9600: baudcode =   B9600; break;
  case  19200: baudcode =  B19200; break;
  case  38400: baudcode =  B38400; break;
  case  57600: baudcode =  B57600; break;
  case 115200: baudcode = B115200; break;
  case 230400: baudcode = B230400; break;
  case 460800: baudcode = B460800; break;
  default    :   err_occurred = true; errno = EINVAL; break;
  }

 /*
  * open device for serdbg operation
  * skip any fds that are between 0..2, because they are
  * reserved for stdin/out/err
  */
  if (!err_occurred &&
      (dev_name != NULL) &&
      (dev_name[0] != '\0')) {
    do {
      serdbg_fd = open(dev_name,O_RDWR);
      if (serdbg_fd < 0) {
	err_occurred = true;
      }
      else {
	if (serdbg_fd < 3) {
	  if (fd_store_used >= FD_STORE_CNT) {
	    err_occurred = true;
	  }
	  else {
	    fd_store[fd_store_used++] = serdbg_fd;
	  }
	}
      }
    } while (!err_occurred &&
	     (serdbg_fd < 3));
  }
  /*
   * close any fds, that have been placed in fd_store
   * so fd 0..2 are reusable again
   */
  while (--fd_store_used >= 0) {
    close(fd_store[fd_store_used]);
  }

  /*
   * capture tty structure
   */
  if (!err_occurred) {
    iop = rtems_libio_iop(serdbg_fd);
    serdbg_tty = iop->data1;
  }
  /*
   * set device baudrate
   * (and transp mode, this is not really needed)
   * ...
   */
  /*
   * ... get fd settings
   */
  if (!err_occurred &&
      (0 != tcgetattr(serdbg_fd,&act_termios))) {
      err_occurred = true;
  }
  if (!err_occurred) {
    act_termios.c_iflag
      &=  ~(IGNBRK|BRKINT|PARMRK|ISTRIP
	    |INLCR|IGNCR|ICRNL|IXON);
    act_termios.c_oflag
      &= ~OPOST;

    act_termios.c_lflag
      &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);

    cfsetospeed(&act_termios,baudcode);
    cfsetispeed(&act_termios,baudcode);

    if (0 != tcsetattr(serdbg_fd,TCSANOW,&act_termios)) {
	err_occurred = true;
    }
  }
  return (err_occurred
	  ? -1
	  : 0);
}

void putDebugChar(char c) __attribute__ ((__weak__));
/*=========================================================================*\
| Function:                                                                 |
\*-------------------------------------------------------------------------*/
void putDebugChar
/*-------------------------------------------------------------------------*\
| Purpose:                                                                  |
|    send one character to serial port                                      |
+---------------------------------------------------------------------------+
| Input Parameters:                                                         |
\*-------------------------------------------------------------------------*/
(
 char c  /* character to print */
)
/*-------------------------------------------------------------------------*\
| Return Value:                                                             |
|    <none>                                                                 |
\*=========================================================================*/
{
  /*
   * call serdbg polling callout, if available
   */
  if (serdbg_conf.callout != NULL) {
    serdbg_conf.callout();
  }
  /*
   * check, whether debug serial port is available
   */
  if ((serdbg_tty != NULL) &&
      (serdbg_tty->device.write != NULL)) {
    /*
     * send character to debug serial port
     */
    serdbg_tty->device.write(serdbg_tty->minor,&c,1);
  }
}

int getDebugChar(void) __attribute__ ((__weak__));
/*=========================================================================*\
| Function:                                                                 |
\*-------------------------------------------------------------------------*/
int getDebugChar
/*-------------------------------------------------------------------------*\
| Purpose:                                                                  |
|    wait for one character from serial port                                |
+---------------------------------------------------------------------------+
| Input Parameters:                                                         |
\*-------------------------------------------------------------------------*/
(
 void  /* none */
)
/*-------------------------------------------------------------------------*\
| Return Value:                                                             |
|    received character                                                     |
\*=========================================================================*/
{
  int c = -1;
  /*
   * check, whether debug serial port is available
   */
  if ((serdbg_tty != NULL) &&
      (serdbg_tty->device.pollRead != NULL)) {
    do {
      /*
       * call serdbg polling callout, if available
       */
      if (serdbg_conf.callout != NULL) {
	serdbg_conf.callout();
      }
      /*
       * get character from debug serial port
       */
      c = serdbg_tty->device.pollRead(serdbg_tty->minor);
    } while (c < 0);
  }
  return c;
}