summaryrefslogtreecommitdiffstats
path: root/tools/serial_probe/serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/serial_probe/serial.c')
-rw-r--r--tools/serial_probe/serial.c770
1 files changed, 342 insertions, 428 deletions
diff --git a/tools/serial_probe/serial.c b/tools/serial_probe/serial.c
index 14b315817..5159c3dae 100644
--- a/tools/serial_probe/serial.c
+++ b/tools/serial_probe/serial.c
@@ -1,6 +1,4 @@
-/* probe serial port for PnP/Legacy devices
- *
- * Copyright 1999 Red Hat, Inc.
+/* Copyright 1999-2003 Red Hat, Inc.
*
* This software may be freely redistributed under the terms of the GNU
* public license.
@@ -9,6 +7,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
+ * probe serial port for PnP/Legacy devices
*/
@@ -26,9 +25,13 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
+#include <sys/sysmacros.h>
+#include <asm/types.h>
#include <linux/serial.h>
+
#include "serial.h"
+#include "kudzu.h"
/* character strings ARE null-terminated in the following structure */
/* these elements are marked with a (string) in the comment */
@@ -76,10 +79,6 @@ struct pnp_com_id {
#define PNP_COM_NOEXIST 8 /* no device seen */
#define PNP_COM_PNPDEV 512 /* its a PNP device */
-/* level of debugging output */
-/* current any value > 0 dumps all available debugging output */
-static int debug_level=0;
-
static void serialFreeDevice(struct serialDevice *dev) {
if (dev->pnpmfr) free(dev->pnpmfr);
if (dev->pnpmodel) free(dev->pnpmodel);
@@ -90,111 +89,74 @@ static void serialFreeDevice(struct serialDevice *dev) {
static void serialWriteDevice(FILE *file, struct serialDevice *dev)
{
- writeDevice(file, (struct device *) dev);
- if (dev->pnpmfr)
- fprintf(file,"pnpmfr: %s\n",dev->pnpmfr);
- if (dev->pnpmodel)
- fprintf(file,"pnpmodel: %s\n",dev->pnpmodel);
- if (dev->pnpcompat)
- fprintf(file,"pnpcompat: %s\n",dev->pnpcompat);
- if (dev->pnpdesc)
- fprintf(file,"pnpdesc: %s\n",dev->pnpdesc);
+ writeDevice(file, (struct device *) dev);
+ if (dev->pnpmfr)
+ fprintf(file,"pnpmfr: %s\n",dev->pnpmfr);
+ if (dev->pnpmodel)
+ fprintf(file,"pnpmodel: %s\n",dev->pnpmodel);
+ if (dev->pnpcompat)
+ fprintf(file,"pnpcompat: %s\n",dev->pnpcompat);
+ if (dev->pnpdesc)
+ fprintf(file,"pnpdesc: %s\n",dev->pnpdesc);
}
static int serialCompareDevice( struct serialDevice *dev1, struct serialDevice *dev2)
{
- int x;
-
- x = compareDevice((struct device *)dev1, (struct device *)dev2);
- if (x && x!=2) return x;
- if (dev1->pnpmfr && dev2->pnpmfr && strcmp(dev1->pnpmfr,dev2->pnpmfr))
- return 1;
- if ((!dev1->pnpmfr || !dev2->pnpmfr) && (dev1->pnpmfr != dev2->pnpmfr))
- return 1;
- if (dev1->pnpmodel && dev2->pnpmodel && strcmp(dev1->pnpmodel,dev2->pnpmodel))
- return 1;
- if ((!dev1->pnpmodel || !dev2->pnpmodel) && (dev1->pnpmodel != dev2->pnpmodel))
- return 1;
- if (dev1->pnpcompat && dev2->pnpcompat && strcmp(dev1->pnpcompat,dev2->pnpcompat))
- return 1;
- if ((!dev1->pnpcompat || !dev2->pnpcompat) && (dev1->pnpcompat != dev2->pnpcompat))
- return 1;
- if (dev1->pnpdesc && dev2->pnpdesc && strcmp(dev1->pnpdesc,dev2->pnpdesc))
- return 1;
- if ((!dev1->pnpdesc || !dev2->pnpdesc) && (dev1->pnpdesc != dev2->pnpdesc))
- return 1;
- return x;
-}
-
-
-struct serialDevice * serialNewDevice(struct serialDevice *dev) {
- struct serialDevice *ret;
-
- ret = malloc(sizeof(struct serialDevice));
- memset(ret,'\0',sizeof(struct serialDevice));
- ret=(struct serialDevice *)newDevice((struct device *)dev,(struct device *)ret);
- ret->bus = BUS_SERIAL;
- ret->newDevice = serialNewDevice;
- ret->freeDevice = serialFreeDevice;
- ret->writeDevice = serialWriteDevice;
- ret->compareDevice = serialCompareDevice;
- if (dev && dev->bus == BUS_SERIAL) {
- if (dev->pnpmfr)
- ret->pnpmfr=strdup(dev->pnpmfr);
- if (dev->pnpmodel)
- ret->pnpmodel=strdup(dev->pnpmodel);
- if (dev->pnpcompat)
- ret->pnpcompat=strdup(dev->pnpcompat);
- if (dev->pnpdesc)
- ret->pnpdesc=strdup(dev->pnpdesc);
- }
- return ret;
-}
-
-/* UNUSED */
-void print_status_lines( int fd ) {
- int modem_lines;
-
- ioctl(fd, TIOCMGET, &modem_lines);
-
- printf("DTR : %s\n",(modem_lines & TIOCM_DTR ? "On" : "Off"));
- printf("RTS : %s\n",(modem_lines & TIOCM_RTS ? "On" : "Off"));
- printf("CTS : %s\n",(modem_lines & TIOCM_CTS ? "On" : "Off"));
- printf("DSR : %s\n",(modem_lines & TIOCM_DSR ? "On" : "Off"));
- printf("CD : %s\n",(modem_lines & TIOCM_CD ? "On" : "Off"));
- printf("RI : %s\n",(modem_lines & TIOCM_RI ? "On" : "Off"));
+ int x;
+ x = compareDevice((struct device *)dev1, (struct device *)dev2);
+ if (x && x!=2) return x;
+ if (dev1->pnpmfr && dev2->pnpmfr && strcmp(dev1->pnpmfr,dev2->pnpmfr))
+ return 1;
+ if ((!dev1->pnpmfr || !dev2->pnpmfr) && (dev1->pnpmfr != dev2->pnpmfr))
+ return 1;
+ if (dev1->pnpmodel && dev2->pnpmodel && strcmp(dev1->pnpmodel,dev2->pnpmodel))
+ return 1;
+ if ((!dev1->pnpmodel || !dev2->pnpmodel) && (dev1->pnpmodel != dev2->pnpmodel))
+ return 1;
+ if (dev1->pnpcompat && dev2->pnpcompat && strcmp(dev1->pnpcompat,dev2->pnpcompat))
+ return 1;
+ if ((!dev1->pnpcompat || !dev2->pnpcompat) && (dev1->pnpcompat != dev2->pnpcompat))
+ return 1;
+ if (dev1->pnpdesc && dev2->pnpdesc && strcmp(dev1->pnpdesc,dev2->pnpdesc))
+ return 1;
+ if ((!dev1->pnpdesc || !dev2->pnpdesc) && (dev1->pnpdesc != dev2->pnpdesc))
+ return 1;
+ return x;
}
-/* UNUSED except in debug */
-/* outputs data in a hex table, 8 values per row */
-void print_hex_data( unsigned char *data, int len ) {
- int i, j, pos;
-
- if (len == 0) {
- printf("No data to print.\n");
- return;
- }
+struct serialDevice * serialNewDevice(struct serialDevice *dev) {
+ struct serialDevice *ret;
- pos = 0;
- for (i=0; i< len; i+=8) {
- printf("0x%.4x ", i);
- for (j=i; j < len && j < i+8; j++) {
- printf("0x%.2x ",data[pos++]);
- }
- printf("\n");
- }
+ ret = malloc(sizeof(struct serialDevice));
+ memset(ret,'\0',sizeof(struct serialDevice));
+ ret=(struct serialDevice *)newDevice((struct device *)dev,(struct device *)ret);
+ ret->bus = BUS_SERIAL;
+ ret->newDevice = serialNewDevice;
+ ret->freeDevice = serialFreeDevice;
+ ret->writeDevice = serialWriteDevice;
+ ret->compareDevice = serialCompareDevice;
+ if (dev && dev->bus == BUS_SERIAL) {
+ if (dev->pnpmfr)
+ ret->pnpmfr=strdup(dev->pnpmfr);
+ if (dev->pnpmodel)
+ ret->pnpmodel=strdup(dev->pnpmodel);
+ if (dev->pnpcompat)
+ ret->pnpcompat=strdup(dev->pnpcompat);
+ if (dev->pnpdesc)
+ ret->pnpdesc=strdup(dev->pnpdesc);
+ }
+ return ret;
}
-
/*
* wait_input - wait until there is data available on fd,
* for the length of time specified by *timo (indefinite
* if timo is NULL).
*/
-int wait_for_input (int fd, struct timeval *timo) {
+static int wait_for_input (int fd, struct timeval *timo) {
fd_set ready;
int n;
@@ -205,72 +167,31 @@ int wait_for_input (int fd, struct timeval *timo) {
return n;
}
-/* UNUSED */
-/* read characters into the buffer buf, until one of: */
-/* char_timeout expired before next character arrives */
-/* total_timeout expires */
-/* maxlen characters are retrieved */
-/* */
-/* returns < 0 if it fails */
-/* otherwise the # of characters received is returned */
-/* char_timeout is in microseconds (millionths of a sec) */
-/* total_timeout is in seconds */
-int timed_serial_read(int fd, int char_timeout, int total_timeout,
- unsigned char *buf, int maxlen ) {
-
- int done, pos, starttime, temp;
- struct timeval timo;
- unsigned char intbuf[2];
-
- /* start reading */
- done = 0;
- pos = 0;
- starttime=time(NULL);
- memset(buf, 0, maxlen);
- while (!done) {
- timo.tv_sec=0;
- timo.tv_usec=char_timeout;
- if (wait_for_input(fd, &timo) > 0) {
- temp = read( fd, intbuf, 1 );
- if (temp < 0) {
- if (errno != EAGAIN)
- return -1;
- } else {
- buf[pos++] = intbuf[0];
- buf[pos] = 0;
- }
- } else
- done = 1;
-
- /* shouldnt run more than 5 seconds */
- if (time(NULL)-starttime > total_timeout )
- done = 1;
-
- if (pos > maxlen)
- done = 1;
- }
- return pos;
-}
-
-
-int open_serial_port( char *port ) {
+static int open_serial_port( char *port ) {
int fd;
+ DEBUG("opening serial port %s...", port);
+
fd = open( port, O_RDWR | O_NONBLOCK);
- if (fd < 0)
+ if (fd < 0) {
+ DEBUG("failed.\n");
return -1;
-
+ } else {
+ DEBUG("successful.\n");
+ }
+
/* reset file so it is no longer in non-blocking mode */
if (fcntl(fd, F_SETFL, 0) < 0) {
close(fd);
+ DEBUG("Failed to set port to non-blocking mode\n");
return -1;
}
-
+
return fd;
}
/* <0 means ioctl error occurred */
-int get_serial_lines( int fd ) {
+static int get_serial_lines( int fd ) {
int modem_lines;
ioctl(fd, TIOCMGET, &modem_lines);
@@ -278,13 +199,15 @@ int get_serial_lines( int fd ) {
}
/* <0 means ioctl error occurred */
-int set_serial_lines( int fd, int modem_lines ) {
+static int set_serial_lines( int fd, int modem_lines ) {
return ioctl(fd, TIOCMSET, &modem_lines);
}
/* set serial port to 1200 baud, 'nbits' bits, 1 stop, no parity */
-int setup_serial_port( int fd, int nbits, struct termios *attr ) {
-
+static int setup_serial_port( int fd, int nbits, struct termios *attr ) {
+
+ DEBUG("setting up serial port\n");
+
attr->c_iflag = IGNBRK | IGNPAR;
attr->c_cflag = 0;
attr->c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | PARENB);
@@ -299,8 +222,10 @@ int setup_serial_port( int fd, int nbits, struct termios *attr ) {
attr->c_cc[VMIN] = 1;
attr->c_cc[VTIME] = 5;
- cfsetospeed( attr, B1200);
- cfsetispeed( attr, B1200);
+ if (cfsetospeed( attr, B1200))
+ return -1;
+ if (cfsetispeed( attr, B1200))
+ return -1;
return tcsetattr(fd, TCSANOW, attr);
}
@@ -309,19 +234,19 @@ int setup_serial_port( int fd, int nbits, struct termios *attr ) {
* to respond to PnP probes after they've been opened by gpm or XFree.
*/
-int init_port(int fd) {
- struct termios attr;
-
- if (tcgetattr(fd,&attr))
- return 1;
-
- cfsetospeed(&attr, B2400);
- cfsetispeed(&attr, B2400);
- attr.c_iflag = IXON | ICRNL;
- attr.c_cflag = CLOCAL | HUPCL | CREAD | B9600 | CS8;
- attr.c_oflag = 0;
- attr.c_lflag = 0;
- return tcsetattr(fd, TCSANOW, &attr);
+static int init_port(int fd) {
+ struct termios attr;
+
+ if (tcgetattr(fd,&attr))
+ return 1;
+
+ cfsetospeed(&attr, B2400);
+ cfsetispeed(&attr, B2400);
+ attr.c_iflag = IXON | ICRNL;
+ attr.c_cflag = CLOCAL | HUPCL | CREAD | B9600 | CS8;
+ attr.c_oflag = 0;
+ attr.c_lflag = 0;
+ return tcsetattr(fd, TCSANOW, &attr);
}
@@ -331,21 +256,23 @@ int init_port(int fd) {
/* */
/* PNP_COM_FATAL - error, errno has reason */
/* PNP_COM_OK - probe initiated successfully */
-/* PNP_COM_FAIL - DSR never came on - try alterntives */
-/* means (ATI9?) to get PnP string */
-int init_pnp_com_seq1( int fd ) {
+static int init_pnp_com_seq1( int fd ) {
int modem_lines;
int temp;
int dsr_status;
int rc = PNP_COM_OK;
struct termios portattr;
+ DEBUG("initializing 1st PNP sequence\n");
if (init_port(fd))
- return PNP_COM_FATAL;
+ return PNP_COM_FATAL;
modem_lines = get_serial_lines(fd);
- /* turn off RTS */
+ /* COM port initialization, check for device enumerate */
+
+ /* turn on DTR, turn off RTS */
+ modem_lines |= TIOCM_DTR;
modem_lines &= ~TIOCM_RTS;
set_serial_lines(fd, modem_lines);
@@ -356,18 +283,15 @@ int init_pnp_com_seq1( int fd ) {
/* see if we got DSR coming up */
if (!dsr_status) {
- /* turn DTR and RTS back on and try alternative methods */
- modem_lines |= TIOCM_DTR | TIOCM_RTS;
- set_serial_lines(fd, modem_lines);
- rc = PNP_COM_OK;
+ DEBUG("Device did not set DSR\n");
}
/* COM port Setup, 1st phase */
- /* now we set port to be 1200 baud, 7 bits, no parity, 1 stop bit */
temp = tcgetattr(fd, &portattr);
if (temp < 0)
return PNP_COM_FATAL;
- /* goto 1200 baud, etc etc as PnP requires */
+
+ /* now we set port to be 1200 baud, 7 bits, no parity, 1 stop bit */
temp = setup_serial_port( fd, 7, &portattr );
if (temp < 0)
return PNP_COM_FATAL;
@@ -382,16 +306,43 @@ int init_pnp_com_seq1( int fd ) {
set_serial_lines(fd, modem_lines);
usleep(200000);
- /* now entering next phase */
+ /* Wait for response, 1st phase */
modem_lines |= TIOCM_RTS;
set_serial_lines(fd, modem_lines);
- usleep(200000);
+ /* usleep(200000); => AQ: not valid as we should look to receive data during this time!! */
return rc;
}
/* Request for PnP info from serial device */
+/* See page 6 of the pnpcom doc from Microsoft */
+/* Always returns PNP_COM_OK */
+static int init_pnp_com_seq2( int fd ) {
+ int modem_lines;
+ int rc = PNP_COM_OK;
+
+ DEBUG("initializing 2nd PNP sequence\n");
+
+ modem_lines = get_serial_lines(fd);
+
+ /* COM port setup, 2nd phase */
+ /* turn off DTR and RTS */
+ modem_lines &= ~(TIOCM_DTR | TIOCM_RTS);
+ set_serial_lines(fd, modem_lines);
+ usleep(200000);
+
+ /* wait for response, 2nd phase */
+ /* turn on DTR and RTS */
+ modem_lines |= (TIOCM_DTR | TIOCM_RTS);
+ set_serial_lines(fd, modem_lines);
+ /* usleep(200000); => AQ: not valid as we should look to receive data during this time!! */
+
+ return rc;
+}
+
+
+/* Request for PnP info from serial modem device */
/* Uses ATI9 code, may not do anything but return 'ERROR' */
/* Return code tells us what happened */
/* */
@@ -399,7 +350,7 @@ int init_pnp_com_seq1( int fd ) {
/* PNP_COM_OK - probe initiated successfully */
/* PNP_COM_FAIL - DSR never came on - try alterntives */
/* means (ATI9?) to get PnP string */
-int init_pnp_com_ati9( int fd ) {
+static int init_pnp_com_ati9( int fd ) {
int modem_lines;
int temp;
int done;
@@ -409,6 +360,7 @@ int init_pnp_com_ati9( int fd ) {
struct timeval timo;
struct termios portattr;
+ DEBUG("Querying ATI9 info from modem\n");
modem_lines = get_serial_lines(fd);
/* turn off RTS */
@@ -441,8 +393,7 @@ int init_pnp_com_ati9( int fd ) {
usleep(200000);
/* send the 'AT' command */
- if (debug_level > 0)
- printf("Sending ATI9 command to modem\n");
+ DEBUG("Sending ATI9 command to modem\n");
write(fd, "ATI9\r", 5);
@@ -476,8 +427,7 @@ int init_pnp_com_ati9( int fd ) {
if (strstr(resp, "ATI9\r"))
done = 1;
- if (debug_level > 0)
- printf("ATI9 probe ->%d \"%s\"\n",respindex, resp);
+ DEBUG("ATI9 probe ->%d \"%s\"\n",respindex, resp);
}
/* see if we saw the 'OK' response */
@@ -501,7 +451,7 @@ int init_pnp_com_ati9( int fd ) {
/* PNP_COM_OK - probe saw 'M' */
/* PNP_COM_FAIL - Never saw the 'M' response */
-int find_legacy_mouse( int fd ) {
+static int find_legacy_mouse( int fd ) {
int modem_lines;
int temp;
int done;
@@ -510,6 +460,8 @@ int find_legacy_mouse( int fd ) {
struct timeval timo;
struct termios portattr;
+ DEBUG("looking for a legacy mouse\n");
+
/* now we set port to be 1200 baud, 7 bits, no parity, 1 stop bit */
temp = tcgetattr(fd, &portattr);
if (temp < 0)
@@ -552,9 +504,10 @@ int find_legacy_mouse( int fd ) {
if (time(NULL)-starttime > 2 )
done = 1;
}
- if (*resp == 'M')
+ if (*resp == 'M') {
+ DEBUG("Found legacy mouse\n");
return PNP_COM_OK;
- else
+ } else
return PNP_COM_FAIL;
}
@@ -567,7 +520,7 @@ int find_legacy_mouse( int fd ) {
/* PNP_COM_FATAL - error, errno has reason */
/* PNP_COM_OK - probe saw 'OK' */
/* PNP_COM_FAIL - Never saw the 'OK' response */
-int find_legacy_modem( int fd ) {
+static int find_legacy_modem( int fd ) {
int modem_lines;
int temp;
int done;
@@ -577,6 +530,8 @@ int find_legacy_modem( int fd ) {
struct timeval timo;
struct termios portattr;
+ DEBUG("looking for a legacy modem\n");
+
/* now we set port to be 1200 baud, 8 bits, no parity, 1 stop bit */
temp = tcgetattr(fd, &portattr);
if (temp < 0)
@@ -594,8 +549,7 @@ int find_legacy_modem( int fd ) {
usleep(200000);
/* send the 'AT' command */
- if (debug_level > 0)
- printf("Sending AT command to modem\n");
+ DEBUG("Sending AT command to modem\n");
write(fd, "AT\r", 3);
@@ -637,7 +591,7 @@ int find_legacy_modem( int fd ) {
/* timeout after 3 seconds */
/* should probably set a 200 msec timeout per char, as spec says */
/* if no char received, we're done */
-int read_pnp_string( int fd, unsigned char *pnp_string, int *pnp_len, int pnp_stringbuf_size ) {
+static int read_pnp_string( int fd, unsigned char *pnp_string, int *pnp_len, int pnp_stringbuf_size ) {
int pnp_index;
int temp, done, counter;
int seen_start;
@@ -645,9 +599,11 @@ int read_pnp_string( int fd, unsigned char *pnp_string, int *pnp_len, int pnp_st
struct timeval timo;
unsigned char buf[80];
unsigned char end_char;
+
+ DEBUG("Attempting to read PNP ID string\n");
/* see if we have any input waiting */
- pnp_index =0;
+ pnp_index = 0;
seen_start = 0;
done = 0;
end_char = 0;
@@ -659,7 +615,7 @@ int read_pnp_string( int fd, unsigned char *pnp_string, int *pnp_len, int pnp_st
temp = read( fd, buf, 1 );
if (temp < 0) {
if (errno != EAGAIN)
- return PNP_COM_FATAL;
+ return PNP_COM_FAIL;
} else {
for (counter=0; counter < temp; counter++) {
pnp_string[pnp_index++] = buf[counter];
@@ -682,30 +638,23 @@ int read_pnp_string( int fd, unsigned char *pnp_string, int *pnp_len, int pnp_st
} else
done = 1;
- /* shouldnt run more than 4 seconds */
- if (time(NULL)-starttime > 4 )
+ /* shouldnt run more than 3 seconds */
+ if (time(NULL)-starttime > 3 )
done = 1;
if (pnp_index >= pnp_stringbuf_size)
done = 1;
}
pnp_string[pnp_index] = 0;
- *pnp_len=pnp_index;
- return 0;
+ *pnp_len=pnp_index;
+ if(*pnp_len > 0)
+ return PNP_COM_OK;
+ else /* allows to call seq2 to be conformant */
+ return PNP_COM_FAIL;
}
-/* UNUSED */
-/* simple little helper function */
-void xlate_memcpy( void *dest, void *src, int len, int xlate_flag ) {
- unsigned char *d, *s;
- int i;
-
- for (i=0,d=dest,s=src; i<len; i++, d++, s++)
- *d = (*s) + ((xlate_flag) ? 0x20 : 0 );
-}
-
/* parse the PnP ID string into components */
-int parse_pnp_string( unsigned char *pnp_id_string, int pnp_len,
+static int parse_pnp_string( unsigned char *pnp_id_string, int pnp_len,
struct pnp_com_id *pnp_id ) {
unsigned char *p1, *p2;
unsigned char *start;
@@ -714,7 +663,6 @@ int parse_pnp_string( unsigned char *pnp_id_string, int pnp_len,
unsigned char *endfield;
unsigned char *temppos;
unsigned char *pnp_string;
- unsigned char end_char;
int no_more_extensions=0;
int stage;
@@ -724,6 +672,8 @@ int parse_pnp_string( unsigned char *pnp_id_string, int pnp_len,
char extension_delims[] = {EndPnP1, EndPnP2, ExtendPnP1, ExtendPnP2, 0};
char end_delims[] = {EndPnP1, EndPnP2, 0};
+ unsigned char* p1end = NULL;
+ unsigned char* p2end = NULL;
/* clear out pnp_id */
memset(pnp_id, 0, sizeof(*pnp_id));
@@ -736,13 +686,23 @@ int parse_pnp_string( unsigned char *pnp_id_string, int pnp_len,
p1 = memchr( pnp_string, BeginPnP1, pnp_len );
p2 = memchr( pnp_string, BeginPnP2, pnp_len );
+
+ if (p1) {
+ int p_len = pnp_len - (p1 - pnp_string);
+ p1end = memchr(p1, EndPnP1, p_len);
+ }
+ if (p2) {
+ int p_len = pnp_len - (p2 - pnp_string);
+ p2end = memchr(p2, EndPnP2, p_len);
+ }
+
/* use the one which points nearest to start of the string */
/* and is actually defined */
- if ( p1 && p2 ) {
+ if ( p1 && p1end && p2 && p2end ) {
start = (p1 < p2) ? p1 : p2;
- } else if (p1)
+ } else if ( p1 && p1end )
start = p1;
- else if (p2)
+ else if ( p2 && p2end )
start = p2;
else
start = NULL;
@@ -758,7 +718,6 @@ int parse_pnp_string( unsigned char *pnp_id_string, int pnp_len,
/* setup end character we are looking for based on the start character */
if (start == p2) {
pnp_id->xlate_6bit = 1;
- end_char = EndPnP2;
/* we need to xlate data in PnP fields */
/* remember to skip the revision fields (bytes 1 and 2 after start) */
temppos=start;
@@ -773,7 +732,6 @@ int parse_pnp_string( unsigned char *pnp_id_string, int pnp_len,
}
} else {
pnp_id->xlate_6bit = 0;
- end_char = EndPnP1;
}
/* move everything before the start of the PnP block */
@@ -867,85 +825,43 @@ int parse_pnp_string( unsigned char *pnp_id_string, int pnp_len,
return 0;
}
-/* UNUSED except for debugging */
-void print_pnp_id( struct pnp_com_id id ) {
- int i;
- int extensions_exist;
- int revision_temp;
-
- if (id.other_len != 0) {
- printf("Detected non-PnP data stream at start.\n");
- printf(" Length = 0x%x\n",id.other_len);
- printf(" Contents =");
- for (i=0; i<id.other_len; i++)
- printf(" 0x%x",id.other_id[i]);
- printf("\n");
- } else
- printf("Non-PnP data stream not detected at start.\n");
-
-
- /* parse PnP revision bytes into a string values (eg. "1.00") */
- revision_temp = ((id.pnp_rev[0]&0x3f) << 6)+(id.pnp_rev[1]&0x3f);
- sprintf(id.pnp_rev_str, "%d.%d",revision_temp/100,revision_temp % 100);
-
- printf("\nPnP Required fields:\n");
- printf(" Revision = %s\n",id.pnp_rev_str);
- printf(" Manufacturer = %s\n",id.eisa_id);
- printf(" Product ID = %s\n",id.product_id);
-
- extensions_exist = id.serial_number[0] || id.class_name[0] ||
- id.driver_id[0] || id.user_name[0];
-
- if (extensions_exist) {
- printf("\nPnP extension field(s) exist:\n");
- if (id.serial_number[0])
- printf(" Serial Number = %s\n",id.serial_number);
- if (id.class_name[0])
- printf(" PnP class name = %s\n",id.class_name);
- if (id.driver_id[0])
- printf(" PnP Compatible = %s\n",id.driver_id);
- if (id.user_name[0])
- printf(" PnP Description = %s\n",id.user_name);
- }
-}
-
-int attempt_pnp_retrieve(int fd, char *pnp_string, int *pnp_strlen, int pnp_stringbuf_size) {
+static int attempt_pnp_retrieve(int fd, char *pnp_string, int *pnp_strlen, int pnp_stringbuf_size) {
int pnp_probe_status;
- int tried_at_prodding;
- int give_up;
struct pnp_com_id pnp_id;
-
- tried_at_prodding=0;
- give_up=0;
+ int tried_at_prodding=0, give_up=0;
+
+ DEBUG("Attempting PNP information retrieval\n");
while (!give_up) {
pnp_probe_status = init_pnp_com_seq1(fd);
- if (pnp_probe_status == PNP_COM_FATAL) {
- return(PNP_COM_FATAL);
- } else if (pnp_probe_status == PNP_COM_OK) {
- read_pnp_string(fd, pnp_string, pnp_strlen, pnp_stringbuf_size );
-
- if (debug_level > 0) {
- printf("\nPNP string = |%s|\n\n",pnp_string);
- print_hex_data(pnp_string, *pnp_strlen);
- }
-
- if (*pnp_strlen == 1 && pnp_string[0] == 'M') /* legacy mouse */
- return PNP_COM_OK;
- /* see if we got anything useful, if not try at command */
- /* to prod device into correct serial params */
- if (parse_pnp_string( pnp_string, *pnp_strlen, &pnp_id )<0)
- if (!tried_at_prodding) {
- write(fd, "AT\r", 3);
- tried_at_prodding=1;
- } else
- give_up = 1;
- else
- return PNP_COM_OK;
+ if (pnp_probe_status == PNP_COM_FATAL)
+ return PNP_COM_FATAL;
+ pnp_probe_status = read_pnp_string(fd, pnp_string, pnp_strlen,
+ pnp_stringbuf_size);
+ if (pnp_probe_status == PNP_COM_FAIL) {
+ init_pnp_com_seq2(fd); /* always succeeds */
+
+ pnp_probe_status = read_pnp_string(fd, pnp_string, pnp_strlen,
+ pnp_stringbuf_size);
+ }
+
+ if (*pnp_strlen == 1 && pnp_string[0] == 'M') /* legacy mouse */
+ return PNP_COM_OK;
+ /* see if we got anything useful, if not try AT command */
+ /* to prod device into correct serial params */
+ if (parse_pnp_string( pnp_string, *pnp_strlen, &pnp_id )<0) {
+ DEBUG("That failed.\n");
+ if (!tried_at_prodding) {
+ DEBUG("Prod modem with AT command.\n");
+ write(fd, "AT\r", 3);
+ tried_at_prodding=1;
+ } else
+ give_up = 1;
} else
- give_up = 1;
- }
+ return PNP_COM_OK;
+ }
+ /* normal PNP detection has failed. */
/* try sending a ATI9 code to the modem to see if we get PnP id back */
init_pnp_com_ati9(fd);
read_pnp_string(fd, pnp_string, pnp_strlen, pnp_stringbuf_size );
@@ -962,7 +878,6 @@ struct device *serialProbe(enum deviceClass probeClass, int probeFlags,
int fd;
int temp;
int pnp_strlen;
- int devicetype=-1;
unsigned char pnp_string[100];
char port[20];
struct termios origattr;
@@ -973,57 +888,51 @@ struct device *serialProbe(enum deviceClass probeClass, int probeFlags,
int console=-1;
int stdin_line=-1;
struct serial_struct si;
-
+
+ DEBUG("Probing for serial ports\n");
+
if (probeFlags & PROBE_SAFE) return devlist;
/* Are we on a serial console? */
fstat(0,&sb);
maj = major(sb.st_rdev);
if (maj != 4 && (maj < 136 || maj > 143)) {
- if (ioctl (0, TIOCLINUX, &twelve) < 0) {
- if (ioctl (0, TIOCGSERIAL, &si) >= 0) {
- if (si.line > 0) {
- stdin_line = 1 << si.line;
- } else {
- stdin_line = 0;
- }
- } else stdin_line = 0;
- }
+ if (ioctl (0, TIOCLINUX, &twelve) < 0) {
+ if (ioctl (0, TIOCGSERIAL, &si) >= 0) {
+ if (si.line > 0) {
+ stdin_line = 1 << si.line;
+ } else {
+ stdin_line = 0;
+ }
+ } else stdin_line = 0;
+ }
}
fd=open("/dev/console",O_RDWR);
if (fd != -1) {
- fstat(fd,&sb);
- maj = major(sb.st_rdev);
- if (maj != 4 && (maj < 136 || maj > 143)) {
- if (ioctl (fd, TIOCLINUX, &twelve) < 0) {
- #ifdef __powerpc__
- // we could have gotten an error for another reason - like EINVAL
- // skipping ttyS0 on PPC - which is where most modems reside
- if (errno == ENOTTY) {
- #endif
- if (ioctl (fd, TIOCGSERIAL, &si) >= 0) {
- if (si.line > 0) {
- console = 1 << si.line;
- } else {
- console = 0;
- }
- } else console = 0;
- #ifdef __powerpc__
- }
- #endif
+ fstat(fd,&sb);
+ maj = major(sb.st_rdev);
+ if (maj != 4 && (maj < 136 || maj > 143)) {
+ if (ioctl (fd, TIOCLINUX, &twelve) < 0) {
+ if (ioctl (fd, TIOCGSERIAL, &si) >= 0) {
+ if (si.line > 0) {
+ console = 1 << si.line;
+ } else {
+ console = 0;
}
+ } else console = 0;
}
- close(fd);
+ }
+ close(fd);
}
-
-
+
+
if (
- (probeClass == CLASS_UNSPEC) ||
- (probeClass == CLASS_OTHER) ||
- (probeClass == CLASS_MOUSE) ||
- (probeClass == CLASS_MODEM) ||
- (probeClass == CLASS_PRINTER)
+ (probeClass & CLASS_UNSPEC) ||
+ (probeClass & CLASS_OTHER) ||
+ (probeClass & CLASS_MOUSE) ||
+ (probeClass & CLASS_MODEM) ||
+ (probeClass & CLASS_PRINTER)
) {
int x;
@@ -1035,82 +944,77 @@ struct device *serialProbe(enum deviceClass probeClass, int probeFlags,
/* Make sure it's not in use */
snprintf(lockfile,32,"/var/lock/LCK..ttyS%d",x);
- if (!stat(lockfile,&sbuf))
- continue;
+ if (!stat(lockfile,&sbuf)) {
+ DEBUG("Port %s in use, skipping probe.\n",
+ port);
+ continue;
+ }
memset(lockfile,'\0',32);
if (readlink("/dev/modem",lockfile,32)>0) {
if (!strcmp(basename(port),basename(lockfile))) {
- snprintf(lockfile,32,"/var/lock/LCK..modem");
- if (!stat(lockfile,&sbuf))
- continue;
+ snprintf(lockfile,32,"/var/lock/LCK..modem");
+ if (!stat(lockfile,&sbuf)) {
+ DEBUG("Port %s in use, skipping probe.\n",
+ port);
+ continue;
+ }
}
}
if ((fd=open_serial_port(port)) < 0) {
- continue;
+ continue;
}
/* save the current state of the port */
temp = tcgetattr(fd, &origattr);
if (temp < 0) {
- close(fd);
- continue;
+ DEBUG("unable to retrieve port attributes...no port present?\n");
+ close(fd);
+ continue;
}
+
/* try twiddling RS232 control lines and see if it talks to us */
- devicetype=-1;
pnp_strlen = 0;
- attempt_pnp_retrieve( fd, pnp_string, &pnp_strlen, sizeof(pnp_string) - 1 );
-
+ if (attempt_pnp_retrieve( fd, pnp_string, &pnp_strlen,
+ sizeof(pnp_string) - 1 ) == PNP_COM_FATAL)
+ goto endprobe;
+
/* see if we found any PnP signature */
- if (pnp_strlen != 0) {
- if (*pnp_string == 'M') { /* Legacy mouse */
- if (probeClass == CLASS_MOUSE || probeClass == CLASS_UNSPEC) {
- serdev = serialNewDevice(NULL);
- serdev->class=CLASS_MOUSE;
- serdev->device=strdup(port+5);
- serdev->desc=strdup("Generic Serial Mouse");
- serdev->driver=strdup("generic");
- if (devlist)
- serdev->next = devlist;
- devlist = (struct device *)serdev;
- if (probeFlags & PROBE_ONE) {
- tcsetattr(fd, TCSANOW, &origattr);
- tcflush(fd, TCIOFLUSH);
- close(fd);
- return devlist;
- }
- }
- tcsetattr(fd, TCSANOW, &origattr);
- close(fd);
- continue;
- }
+ if (pnp_strlen != 0 && (pnp_strlen != 1 || pnp_string[0] != 'M')) {
+
/* fill in the PnP com structure */
if (parse_pnp_string( pnp_string, pnp_strlen, &pnp_id )<0) {
- goto endprobe;
+ DEBUG("Got PNP data back, but failed to parse. Aborting\n");
+ goto endprobe;
} else {
char *foo;
int len;
- if (debug_level > 0) {
- printf("PnP ID string for serial device on port %s\n",port);
- print_pnp_id( pnp_id );
- }
+ DEBUG("PNP data parsed.\n");
serdev = serialNewDevice(NULL);
+
if (pnp_id.user_name[0]) {
- serdev->pnpdesc = strdup(pnp_id.user_name);
- len = strlen(pnp_id.eisa_id)+strlen(pnp_id.product_id)+strlen(pnp_id.user_name)+3;
+ serdev->pnpdesc = strdup(pnp_id.user_name);
+ len = strlen(pnp_id.eisa_id) +
+ strlen(pnp_id.product_id) +
+ strlen(pnp_id.user_name) + 3;
foo = malloc(len);
- snprintf(foo,len,"%s|%s %s",pnp_id.eisa_id,pnp_id.product_id,pnp_id.user_name);
+ snprintf(foo,len,"%s|%s %s",pnp_id.eisa_id,
+ pnp_id.product_id,pnp_id.user_name);
} else {
- len = strlen(pnp_id.eisa_id)+strlen(pnp_id.product_id)+3;
+ len = strlen(pnp_id.eisa_id) +
+ strlen(pnp_id.product_id) + 3;
foo = malloc(len);
- snprintf(foo,len,"%s|%s",pnp_id.eisa_id,pnp_id.product_id);
+ snprintf(foo,len,"%s|%s",pnp_id.eisa_id,
+ pnp_id.product_id);
}
+ if (serdev->desc) free(serdev->desc);
serdev->desc=strdup(foo);
serdev->device=strdup(port+5);
+ if (serdev->driver) free(serdev->driver);
serdev->driver=strdup("ignore");
- serdev->pnpmfr = strdup(pnp_id.eisa_id);
- serdev->pnpmodel = strdup(pnp_id.product_id);
+ serdev->pnpmfr = strdup(pnp_id.eisa_id);
+ serdev->pnpmodel = strdup(pnp_id.product_id);
free(foo);
foo=pnp_id.product_id;
@@ -1119,87 +1023,97 @@ struct device *serialProbe(enum deviceClass probeClass, int probeFlags,
foo = strstr(pnp_id.driver_id,"PNP")+3;
serdev->pnpcompat = strdup(pnp_id.driver_id);
}
- if (!strncmp(foo, "0F", 2))
- serdev->class = CLASS_MOUSE;
- else if (!strncmp(foo, "C", 1))
- serdev->class = CLASS_MODEM;
- else if (!strncmp(pnp_id.class_name, "Modem", 5))
- serdev->class = CLASS_MODEM;
+
+ if (*pnp_id.other_id == 'M' ||
+ !strncmp(pnp_id.class_name, "MOUSE", 5) ||
+ !strncmp(foo, "0F", 2)) {
+ serdev->type = CLASS_MOUSE;
+ if (!strncmp(serdev->desc, "|", 1)) {
+ free(serdev->desc);
+ serdev->desc=strdup("Generic Serial Mouse");
+ }
+ if (serdev->driver) free(serdev->driver);
+ serdev->driver = strdup("generic");
+ }
+ else if (!strncmp(pnp_id.class_name, "MODEM", 5) ||
+ !strncmp(foo, "C", 1))
+ serdev->type = CLASS_MODEM;
+ else if (!strncmp(pnp_id.class_name, "PRINTER", 7))
+ serdev->type = CLASS_PRINTER;
else
- serdev->class = CLASS_OTHER;
- if (serdev->class == probeClass || probeClass == CLASS_UNSPEC) {
- if (devlist)
- serdev->next = devlist;
- devlist = (struct device *)serdev;
- if (probeFlags & PROBE_ONE) {
- tcsetattr(fd, TCSANOW, &origattr);
- tcflush(fd, TCIOFLUSH);
- close(fd);
- return devlist;
- }
+ serdev->type = CLASS_OTHER;
+ if (serdev->type & probeClass) {
+ if (devlist)
+ serdev->next = devlist;
+ devlist = (struct device *)serdev;
+ if (probeFlags & PROBE_ONE) {
+ tcsetattr(fd, TCSANOW, &origattr);
+ tcflush(fd, TCIOFLUSH);
+ close(fd);
+ return devlist;
+ }
} else {
- serdev->freeDevice(serdev);
+ serdev->freeDevice(serdev);
}
goto endprobe;
}
} else {
+ DEBUG("No PNP data received.\n");
/* try to find a legacy device */
temp = find_legacy_mouse(fd);
if (temp == PNP_COM_FATAL) {
goto endprobe;
} else if (temp == PNP_COM_OK) {
- if (probeClass == CLASS_UNSPEC || probeClass == CLASS_MOUSE) {
- serdev=serialNewDevice(NULL);
- serdev->class = CLASS_MOUSE;
- serdev->device = strdup(port+5);
- serdev->driver= strdup("generic");
- serdev->desc = strdup("Generic Serial Mouse");
- if (devlist)
- serdev->next = devlist;
- devlist = (struct device *)serdev;
- if (probeFlags & PROBE_ONE) {
- tcsetattr(fd, TCSANOW, &origattr);
- tcflush(fd, TCIOFLUSH);
- close(fd);
- return devlist;
- }
+ if (probeClass & CLASS_MOUSE) {
+ serdev=serialNewDevice(NULL);
+ serdev->type = CLASS_MOUSE;
+ serdev->device = strdup(port+5);
+ serdev->driver= strdup("generic");
+ serdev->desc = strdup("Generic Serial Mouse");
+ if (devlist)
+ serdev->next = devlist;
+ devlist = (struct device *)serdev;
+ if (probeFlags & PROBE_ONE) {
+ tcsetattr(fd, TCSANOW, &origattr);
+ tcflush(fd, TCIOFLUSH);
+ close(fd);
+ return devlist;
}
- goto endprobe;
+ }
+ goto endprobe;
} else {
- if (debug_level > 0)
- printf("Didnt see a legacy mouse, need to ATI it now.\n");
-
+ DEBUG("Didn't see a legacy mouse.\n");
+
temp = find_legacy_modem(fd);
if (temp == PNP_COM_FATAL) {
- goto endprobe;
+ goto endprobe;
} else if (temp == PNP_COM_OK) {
- if (debug_level > 0)
- printf("\nLegacy modem signature seen.\n\n");
- if (probeClass == CLASS_UNSPEC || probeClass == CLASS_MODEM) {
- serdev=serialNewDevice(NULL);
- serdev->class = CLASS_MODEM;
- serdev->device = strdup(port+5);
- serdev->driver= strdup("ignore");
- serdev->desc = strdup("Generic Serial Modem");
- if (devlist)
- serdev->next = devlist;
- devlist = (struct device *)serdev;
- if (probeFlags & PROBE_ONE) {
- tcsetattr(fd, TCSANOW, &origattr);
- tcflush(fd, TCIOFLUSH);
- close(fd);
- return devlist;
- }
+ DEBUG("Legacy modem signature seen.\n");
+ if (probeClass & CLASS_MODEM) {
+ serdev=serialNewDevice(NULL);
+ serdev->type = CLASS_MODEM;
+ serdev->device = strdup(port+5);
+ serdev->driver= strdup("ignore");
+ serdev->desc = strdup("Generic Serial Modem");
+ if (devlist)
+ serdev->next = devlist;
+ devlist = (struct device *)serdev;
+ if (probeFlags & PROBE_ONE) {
+ tcsetattr(fd, TCSANOW, &origattr);
+ tcflush(fd, TCIOFLUSH);
+ close(fd);
+ return devlist;
+ }
}
- goto endprobe;
+ goto endprobe;
} else {
- if (debug_level > 0)
- printf("Didnt see a legacy modem, game over.\n");
+ DEBUG("Didnt see a legacy modem, game over.\n");
}
}
}
-endprobe:
+ endprobe:
+ DEBUG("Restoring original port attributes\n");
tcsetattr(fd, TCSANOW, &origattr);
tcflush(fd, TCIOFLUSH);
close(fd);