📄 serdrv.c
字号:
/* * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved. * * This software may be freely used, copied, modified, and distributed * provided that the above copyright notice is preserved in all copies of the * software. *//* -*-C-*- * * $Revision: 1.7 $ * $Date: 2000/01/12 12:53:29 $ * * * serdrv.c - Synchronous Serial Driver for Angel. * This is nice and simple just to get something going. */#ifdef __hpux# define _POSIX_SOURCE 1#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include "crc.h"#include "devices.h"#include "buffers.h"#include "rxtx.h"#include "hostchan.h"#include "params.h"#include "logging.h"extern int baud_rate; /* From gdb/top.c */#ifdef COMPILING_ON_WINDOWS# undef ERROR# undef IGNORE# include <windows.h># include "angeldll.h"# include "comb_api.h"#else# ifdef __hpux# define _TERMIOS_INCLUDED# include <sys/termio.h># undef _TERMIOS_INCLUDED# else# include <termios.h># endif# include "unixcomm.h"#endif#ifndef UNUSED# define UNUSED(x) (x = x) /* Silence compiler warnings */#endif #define MAXREADSIZE 512#define MAXWRITESIZE 512#define SERIAL_FC_SET ((1<<serial_XON)|(1<<serial_XOFF))#define SERIAL_CTL_SET ((1<<serial_STX)|(1<<serial_ETX)|(1<<serial_ESC))#define SERIAL_ESC_SET (SERIAL_FC_SET|SERIAL_CTL_SET)static const struct re_config config = { serial_STX, serial_ETX, serial_ESC, /* self-explanatory? */ SERIAL_FC_SET, /* set of flow-control characters */ SERIAL_ESC_SET, /* set of characters to be escaped */ NULL /* serial_flow_control */, NULL , /* what to do with FC chars */ angel_DD_RxEng_BufferAlloc, NULL /* how to get a buffer */};static struct re_state rxstate;typedef struct writestate { unsigned int wbindex; /* static te_status testatus;*/ unsigned char writebuf[MAXWRITESIZE]; struct te_state txstate;} writestate;static struct writestate wstate;/* * The set of parameter options supported by the device */static unsigned int baud_options[] = {#if defined(B115200) || defined(__hpux) 115200,#endif#if defined(B57600) || defined(__hpux) 57600, #endif 38400, 19200, 9600};static ParameterList param_list[] = { { AP_BAUD_RATE, sizeof(baud_options)/sizeof(unsigned int), baud_options }};static const ParameterOptions serial_options = { sizeof(param_list)/sizeof(ParameterList), param_list };/* * The default parameter config for the device */static Parameter param_default[] = { { AP_BAUD_RATE, 9600 }};static ParameterConfig serial_defaults = { sizeof(param_default)/sizeof(Parameter), param_default };/* * The user-modified options for the device */static unsigned int user_baud_options[sizeof(baud_options)/sizeof(unsigned)];static ParameterList param_user_list[] = { { AP_BAUD_RATE, sizeof(user_baud_options)/sizeof(unsigned), user_baud_options }};static ParameterOptions user_options = { sizeof(param_user_list)/sizeof(ParameterList), param_user_list };static bool user_options_set;/* forward declarations */static int serial_reset( void );static int serial_set_params( const ParameterConfig *config );static int SerialMatch(const char *name, const char *arg);static void process_baud_rate( unsigned int target_baud_rate ){ const ParameterList *full_list; ParameterList *user_list; /* create subset of full options */ full_list = Angel_FindParamList( &serial_options, AP_BAUD_RATE ); user_list = Angel_FindParamList( &user_options, AP_BAUD_RATE ); if ( full_list != NULL && user_list != NULL ) { unsigned int i, j; unsigned int def_baud = 0; /* find lower or equal to */ for ( i = 0; i < full_list->num_options; ++i ) if ( target_baud_rate >= full_list->option[i] ) { /* copy remaining */ for ( j = 0; j < (full_list->num_options - i); ++j ) user_list->option[j] = full_list->option[i+j]; user_list->num_options = j; /* check this is not the default */ Angel_FindParam( AP_BAUD_RATE, &serial_defaults, &def_baud ); if ( (j == 1) && (user_list->option[0] == def_baud) ) {#ifdef DEBUG printf( "user selected default\n" );#endif } else { user_options_set = TRUE;#ifdef DEBUG printf( "user options are: " ); for ( j = 0; j < user_list->num_options; ++j ) printf( "%u ", user_list->option[j] ); printf( "\n" );#endif } break; /* out of i loop */ } #ifdef DEBUG if ( i >= full_list->num_options ) printf( "couldn't match baud rate %u\n", target_baud_rate );#endif }#ifdef DEBUG else printf( "failed to find lists\n" );#endif}static int SerialOpen(const char *name, const char *arg){ const char *port_name = name;#ifdef DEBUG printf("SerialOpen: name %s arg %s\n", name, arg ? arg : "<NULL>");#endif#ifdef COMPILING_ON_WINDOWS if (IsOpenSerial()) return -1;#else if (Unix_IsSerialInUse()) return -1;#endif#ifdef COMPILING_ON_WINDOWS if (SerialMatch(name, arg) != adp_ok) return adp_failed;#else port_name = Unix_MatchValidSerialDevice(port_name);# ifdef DEBUG printf("translated port to %s\n", port_name == 0 ? "NULL" : port_name);# endif if (port_name == 0) return adp_failed;#endif user_options_set = FALSE; /* interpret and store the arguments */ if ( arg != NULL ) { unsigned int target_baud_rate; target_baud_rate = (unsigned int)strtoul(arg, NULL, 10); if (target_baud_rate > 0) {#ifdef DEBUG printf( "user selected baud rate %u\n", target_baud_rate );#endif process_baud_rate( target_baud_rate ); }#ifdef DEBUG else printf( "could not understand baud rate %s\n", arg );#endif } else if (baud_rate > 0) { /* If the user specified a baud rate on the command line "-b" or via the "set remotebaud" command then try to use that one */ process_baud_rate( baud_rate ); }#ifdef COMPILING_ON_WINDOWS { int port = IsValidDevice(name); if (OpenSerial(port, FALSE) != COM_OK) return -1; }#else if (Unix_OpenSerial(port_name) < 0) return -1;#endif serial_reset();#if defined(__unix) || defined(__CYGWIN__) Unix_ioctlNonBlocking();#endif Angel_RxEngineInit(&config, &rxstate); /* * DANGER!: passing in NULL as the packet is ok for now as it is just * IGNOREd but this may well change */ Angel_TxEngineInit(&config, NULL, &wstate.txstate); return 0;}static int SerialMatch(const char *name, const char *arg){ UNUSED(arg);#ifdef COMPILING_ON_WINDOWS if (IsValidDevice(name) == COM_DEVICENOTVALID) return -1; else return 0;#else return Unix_MatchValidSerialDevice(name) == 0 ? -1 : 0;#endif}static void SerialClose(void){#ifdef DO_TRACE printf("SerialClose()\n");#endif#ifdef COMPILING_ON_WINDOWS CloseSerial();#else Unix_CloseSerial();#endif}static int SerialRead(DriverCall *dc, bool block) { static unsigned char readbuf[MAXREADSIZE]; static int rbindex=0; int nread; int read_errno; int c=0; re_status restatus; int ret_code = -1; /* assume bad packet or error */ /* must not overflow buffer and must start after the existing data */#ifdef COMPILING_ON_WINDOWS { BOOL dummy = FALSE; nread = BytesInRXBufferSerial(); if (nread > MAXREADSIZE - rbindex) nread = MAXREADSIZE - rbindex; if ((read_errno = ReadSerial(readbuf+rbindex, nread, &dummy)) == COM_READFAIL) { MessageBox(GetFocus(), "Read error\n", "Angel", MB_OK | MB_ICONSTOP); return -1; /* SJ - This really needs to return a value, which is picked up in */ /* DevSW_Read as meaning stop debugger but don't kill. */ } else if (pfnProgressCallback != NULL && read_errno == COM_OK) { progressInfo.nRead += nread; (*pfnProgressCallback)(&progressInfo); } }#else nread = Unix_ReadSerial(readbuf+rbindex, MAXREADSIZE-rbindex, block); read_errno = errno;#endif if ((nread > 0) || (rbindex > 0)) {#ifdef DO_TRACE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -