⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wvmodemscan.cc

📁 wvdial 软件包是一个自动拨号程序
💻 CC
字号:
/* * Worldvisions Weaver Software: *   Copyright (C) 1997-2003 Net Integration Technologies, Inc. * * Intelligent serial port scanner: try to find a port (or ports) * with a working modem, guess a basic startup init string, and find * the maximum baud rate. */#include "wvmodemscan.h"#include "wvmodem.h"#include "strutils.h"#include <time.h>#include <assert.h>#include <dirent.h>#include <ctype.h>#include <sys/stat.h>WvString isdn_init;bool     default_asyncmap = false;// startup at atz atq0 atv1 ate1 ats0 carrier dtr fastdial// baudstep reinit donestatic char *commands[WvModemScan::NUM_STAGES] = {    NULL, "Q0 V1 E1", "Z", "S0=0",    "&C1", "&D2", "+FCLASS=0", NULL,    NULL, "", NULL};static int baudcheck[6] = {	2400,	9600,	115200,	0};static int default_baud =   baudcheck[0];static int isdn_speed   = 115200;WvModemScan::WvModemScan(WvStringParm devname, bool is_modem_link)	: debug(devname, WvLog::Debug){    stage = Startup;    memset(status, 0, sizeof(status));    if (devname[0] == '/')	file = devname;    else	file = WvString("/dev/%s", devname);        use_modem_link = is_modem_link;    baud = default_baud;    modem = NULL;    tries = 0;    broken = false;}WvModemScan::~WvModemScan(){    if (isok() && isdone())	debug(WvLog::Info, "Speed %s; init \"%s\"\n", maxbaud(), initstr());        WVRELEASE(modem);}bool WvModemScan::use_default_asyncmap() const{    return default_asyncmap;}bool WvModemScan::isok() const{    return !broken;}WvString WvModemScan::initstr() const{    char s[200];    if (isdn_init)	return (isdn_init);    strcpy(s, "AT");        for (int i = 0; i < NUM_STAGES; i++)    {	if (status[i] != Worked && status[i] != Test)	    continue;	if (!commands[i] || !commands[i][0])	    continue;	if ((commands[i][0]=='Z' || commands[i][0]=='I') && status[i] != Test)	    continue;		strcat(s, commands[i]);	strcat(s, " ");    }        return WvString(trim_string(s));}void WvModemScan::execute(){    if (isdone() || !isok()) return;    switch ((Stage)stage)    {    case Startup:	assert(!modem);	modem = new WvModem(file, baud);	modem->die_fast = true;	if (!modem->isok())	{	    if (modem->geterr()		&& modem->geterr() != EIO		&& modem->geterr() != ENOENT		&& modem->geterr() != ENODEV)	    {		debug(WvLog::Info, "%s\n", modem->errstr());	    }	    broken = true;	}	else	    stage++;	break;	    case AT:    case ATZ:    case ATS0:    case Carrier:    case DTR:    case FCLASS:    case Reinit:	assert(modem);	status[stage] = Test;	if (!strncmp(file, "/dev/ircomm", 11)) 	{	    while (baudcheck[tries+1] <= 9600 && baudcheck[tries+1] != 0) 		tries++;	    if (baudcheck[tries] > 19200 || baudcheck[tries] == 0) 	    {		broken = true;		debug("failed at 9600 and 19200 baud.\n");		return;	    }	    baud = modem->speed(baudcheck[tries]);	}	if (!doresult(WvString("%s\r", initstr()), stage==ATZ ? 3000 : 500)	    || ((stage <= AT || stage == Reinit) && status[stage]==Fail))	{	    int old_baud = baud;	    tries++;	    //modem->drain();	    //modem->speed(baud*2);	    //baud = modem->speed(baud);	    if (baudcheck[tries] == 0) 	    {		broken = true;		debug("and failed too at %s, giving up.\n",			WvString(isdn_speed));		// Go back to default_baud:		modem->speed(default_baud);	    	baud = modem->getspeed();	    } 	    else if (strncmp(file, "/dev/ircomm", 11))	        debug("failed with %s baud, next try: %s baud\n",		      old_baud,		      baud = modem->speed(baudcheck[tries]));	            //baud = modem->speed(baud*2));#if 0	    	    if (tries >= 4)	    {		if (baud == default_baud) 		{			debug("nothing at %s baud,\n", WvString(default_baud));			// Ok, then let's try ISDN speed for ISDN TAs:			modem->speed(isdn_speed);	    		baud = modem->getspeed();	    		tries = 0;		} 		else 		{			// Ok, we tried default_baud and ISDN speed, give up:			broken = true;			debug("nor at %s.\n", WvString(isdn_speed));			// Go back to default_baud:			modem->speed(default_baud);	    		baud = modem->getspeed();		}	    }#endif	    	    // else try again shortly	}	else	{	    tries = 0;	    stage++;	}	break;	    case GetIdent:	assert(modem);	status[stage] = Test;	debug("Modem Identifier: ");	if (!doresult(WvString("ATI\r"), 500) || (status[stage]==Fail))	{	    tries++;	    if (tries >= 3)	    	debug("nothing.\n");	    // else try again shortly	}	else	{	    if (is_isdn())	    	debug("Looks like an ISDN modem.\n");	    if (!strncmp(identifier, "Hagenuk", 7)) 	    {	        status[stage] = Test;		if (doresult(WvString("ATI1\r"), 500)) 		    if (!strncmp(identifier, "Speed Dragon", 12)		    ||  !strncmp(identifier, "Power Dragon", 12)) 		    {		    	isdn_init = "ATB8";		    	modem_name = WvString("Hagenuk %s", identifier);		    }	        status[stage] = Worked;	    } 	    else if (!strncmp(identifier, "346900", 6)) 	    {	        status[stage] = Test;		if (doresult(WvString("ATI3\r"), 500))		    if (!strncmp(identifier, "3Com U.S. Robotics ISDN",23)) 		    {			isdn_init = "AT*PPP=1";			modem_name = identifier;		    }	        status[stage] = Worked;	    } 	    else if (!strncmp(identifier, "SP ISDN", 7)) 	    {	        status[stage] = Test;		if (doresult(WvString("ATI4\r"), 500))		    if (!strncmp(identifier, "Sportster ISDN TA", 17)) 		    {			isdn_init = "ATB3";			modem_name = identifier;		    }	        status[stage] = Worked;	    } 	    else if (!strncmp(identifier, "\"Version", 8)) 	    {	        status[stage] = Test;		if (doresult(WvString("ATI6\r"), 500))		    modem_name = identifier;	        status[stage] = Worked;	    } 	    else if (!strncmp(identifier, "644", 3)) 	    {	        status[stage] = Test;		if (doresult(WvString("ATI6\r"), 500))		    if (!strncmp(identifier, "ELSA MicroLink ISDN", 19)) 		    {			isdn_init = "AT$IBP=HDLCP";			modem_name = identifier;			default_asyncmap = true;		    }	        status[stage] = Worked;	    } 	    else if (!strncmp(identifier, "643", 3)) 	    {	        status[stage] = Test;		if (doresult(WvString("ATI6\r"), 500))		    if (!strncmp(identifier, "MicroLink ISDN/TLV.34", 21)) 		    {			isdn_init = "AT\\N10%P1";			modem_name = identifier;		    }	        status[stage] = Worked;	    } 	    else if (!strncmp(identifier, "ISDN TA", 6)) 	    {	        status[stage] = Test;		if (doresult(WvString("ATI5\r"), 500))		    if (strstr(identifier, ";ASU")) 		    {			isdn_init = "ATB40";			modem_name = "ASUSCOM ISDNLink TA";		    }	        status[stage] = Worked;	    } 	    else if (!strncmp(identifier, "128000", 6)) 	    {	        status[stage] = Test;		if (doresult(WvString("ATI3\r"), 500))		    if (!strncmp(identifier, "Lasat Speed", 11)) 		    {			isdn_init = "AT\\P1&B2X3";			modem_name = identifier;		    }	        status[stage] = Worked;	    } 	    else if (!strncmp(identifier, "28642", 5) // Elite 2864I		     || !strncmp(identifier, "1281", 4)  // Omni TA128 USA		     || !strncmp(identifier, "1282", 4)  // Omni TA128 DSS1		     || !strncmp(identifier, "1283", 4)  // Omni TA128 1TR6		     || !strncmp(identifier, "1291", 4)  // Omni.Net USA		     || !strncmp(identifier, "1292", 4)  // Omni.Net DSS1		     || !strncmp(identifier, "1293", 4)  // Omni.Net 1TR6		     ) 	    {	        status[stage] = Test;		if (doresult(WvString("ATI1\r"), 500))		    if (!strncmp(identifier, "Elite 2864I", 11)			|| !strncmp(identifier, "ZyXEL omni", 10)) 		    {			isdn_init = "AT&O2B40";			if (strncmp(identifier, "ZyXEL", 5))		            modem_name = WvString("ZyXEL %s", identifier);			else			    modem_name = identifier;		    }	        status[stage] = Worked;	    }	    	    tries = 0;	    stage++;	}	    case BaudStep:	assert(modem);	modem->drain();	modem->speed(baud*2);	// if we try 2*baud three times without success, or setting 2*baud	// results in a lower setting than 1*baud, we have reached the	// top speed of the modem or the serial port, respectively.	if (tries >= 3 || modem->getspeed() <= baud)	{	    // using the absolute maximum baud rate confuses many slower modems	    // in obscure ways; step down one.	    baud = modem->speed(baud);	    debug("Max speed is %s; that should be safe.\n", baud);	    	    stage++;	    status[stage] = Worked;	    break;	}		debug("Speed %s: ", modem->getspeed());		if (!doresult("AT\r", 500) || status[stage] == Fail)	{	    tries++;	}	else // got a response	{	    baud = modem->getspeed();	    tries = 0;	    // next time through we try a faster speed	}	break;	    case Done:    case NUM_STAGES:	assert(0);	break; // should never happen    }        if (stage == Done) // we just incremented stage number to Done    {	WVRELEASE(modem);    }}bool WvModemScan::doresult(WvStringParm _s, int msec){    char buf[1024], *cptr;    size_t len;    WvString s(_s);        modem->drain();    usleep(50 * 1000); // delay a bit after emptying the buffer    modem->write(s);    debug("%s -- ", trim_string(s.edit()));        len = coagulate(buf, sizeof(buf), msec);    if (!len)    {	// debug("(no answer yet)\n");	return false;    }        buf[len] = 0;        cptr = trim_string(buf);    while (strchr(cptr, '\r'))    {	cptr = trim_string(strchr(cptr, '\r'));	if (stage == GetIdent && status[stage] == Test)	{	    char *p = strpbrk(cptr, "\n\r");	    if (p) *p=0;	    identifier = cptr;	    status[stage] = Worked;	    debug("%s\n", identifier);	    return true;	}    }    while (strchr(cptr, '\n'))	cptr = trim_string(strchr(cptr, '\n'));        debug("%s\n", cptr);    if (!strncmp(cptr, "OK", 2))	status[stage] = Worked;    else	status[stage] = Fail;        return true;}size_t WvModemScan::coagulate(char *buf, size_t size, int msec){    size_t len = 0, amt;    char *cptr = buf;    assert(modem);        if (!modem->isok())    {	broken = true;	return 0;    }        while (modem->select(msec, true, false))    {	amt = modem->read(cptr, size-1);	cptr[amt] = 0;	len += amt;	size -= amt;	cptr += amt;	if (strstr(buf, "OK") || strstr(buf, "ERROR"))	    break;    }        return len;}const char *WvModemScan::is_isdn() const{    if (isdn_init)	return isdn_init;    if (!identifier)    	return NULL;    if (identifier == "3C882")		// 3Com Impact IQ    	return identifier;    if (identifier == "346800")		// USR ISDN TA    	return identifier;#if 0 // this isn't nearly unique enough...    if (identifier == "960")		// Motorola BitSurfr    	return identifier;#endif        return NULL;}	static int fileselect(const struct dirent *e){    return !strncmp(e->d_name, "ttyS", 4)      	// serial       || !strncmp(e->d_name, "ttyLT", 5)	// Lucent WinModem       || !strncmp(e->d_name, "ttyACM", 6)      // USB acm Modems       || !strncmp(e->d_name, "ttyUSB", 6)      // Modems on USB RS232       || !strncmp(e->d_name, "ircomm", 6)      // Handys over IrDA       || !strncmp(e->d_name, "ttySL", 5);	// SmartLink WinModem	// (no internal ISDN support)   || !strncmp(e->d_name, "ttyI", 4);}static int filesort(const void *_e1, const void *_e2){    dirent const * const *e1 = (dirent const * const *)_e1;    dirent const * const *e2 = (dirent const * const *)_e2;    const char *p1, *p2;    int diff;        for (p1=(*e1)->d_name, p2=(*e2)->d_name; *p1 || *p2; p1++, p2++)    {	if (!isdigit(*p1) || !isdigit(*p2))	{	    // Scan i (ircomm*) after t (tty*):	    if (*p1 == 'i' && *p2 == 't')		return(1);	    // Scan A (ttyACM*) after S (ttyS*):	    if (*p1 == 'A' && *p2 == 'S')		return(1);	    if (*p1 == 'S' && *p2 == 'A')		return(-1);	    diff = *p1 - *p2;	    if (diff) return diff;	}	else // both are digits	{	    return atoi(p1) - atoi(p2);	}    }        return 0;}WvModemScanList::WvModemScanList(WvStringParm _exception)     : log("Modem Port Scan", WvLog::Debug){    struct dirent **namelist;    struct stat mouse, modem;    int num, count, mousestat, modemstat;    WvString exception;        thisline = -1;    printed = false;        mousestat = stat("/dev/mouse", &mouse);    modemstat = stat("/dev/modem", &modem);    num = scandir("/dev", &namelist, fileselect, filesort);        if (num < 0)	return;        // there shouldn't be a /dev/    if (!!_exception)	exception = strrchr(_exception, '/') + 1;        for (count = 0; count < num; count++)    {	// never search the device assigned to /dev/mouse; most mouse-using	// programs neglect to lock the device, so we could mess up the	// mouse response!  (We are careful to put things back when done,	// but X seems to still get confused.)  Anyway the mouse is seldom	// a modem.	if (mousestat==0 && mouse.st_ino == (ino_t)namelist[count]->d_ino)	{	    log("\nIgnoring %s because /dev/mouse is a link to it.\n",		       namelist[count]->d_name);	    continue;	}		if (!!exception && !strcmp(exception, namelist[count]->d_name))	{	    log("\nIgnoring %s because I've been told to ignore it.\n",		namelist[count]->d_name);	    continue;	}		// bump /dev/modem to the top of the list, if it exists	// and also use /dev/modem as the device name which will be used later	// so PCMCIA can change it where it has detected a serial port and	// wvdial will follow without the need for another wvdialconf call.	if (modemstat==0 && modem.st_ino == (ino_t)namelist[count]->d_ino) 	{	    log("\nScanning %s first, /dev/modem is a link to it.\n",		       namelist[count]->d_name);	    prepend(new WvModemScan(WvString("%s", namelist[count]->d_name), true),		   true);	} 	else	    append(new WvModemScan(WvString("%s", namelist[count]->d_name), false),		   true);    }    while (--num >= 0)	free(namelist[num]);    free(namelist);}// we used to try to scan all ports simultaneously; unfortunately, this// caused problems when people had "noncritical" IRQ conflicts (ie. two// serial ports with the same IRQ, but they work as long as only one port// is used at a time).  Also, the log messages looked really confused.//// So now we do the scanning sequentially, which is slower.  The port// being scanned is at the head of the list.  If the probe fails, we// unlink the element.  If it succeeds, we have found a modem -- so,// isdone() knows we are done when the _first_ element is done.//void WvModemScanList::execute(){    assert (!isdone());    WvModemScanList::Iter i(*this);    for (i.rewind(); i.next(); )	if (!i().isdone()) break;    if (!i.cur()) return;         WvModemScan &s(*i);        if (!s.isok())    {	if (!printed)	{	    WvStringParm f = s.filename();	    const char *cptr = strrchr(f, '/');	    if (cptr)		cptr++;	    else		cptr = f;	    if (!strncmp(cptr, "tty", 3))		cptr += 3;	    	    ++thisline %= 8;	    if (!thisline)		log("\n");	    log("%-4s ", cptr);	}	i.unlink();	printed = false;    }    else    {	s.execute();		if (s.isok())	    printed = true;    }	        if (isdone()) 	log("\n");}bool WvModemScanList::isdone(){    WvModemScanList::Iter i(*this);        for (i.rewind(); i.next(); )	if (!i().isdone()) return false;        return true;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -