NetBSD-Users archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: Help on serial ports
This is my C code for opening the device. All of the termios stuff I wrote by
looking at code in uucp, which I know to be working on netbsd. I don't know
anything about tcl on netbsd. I suppose it is possible that you could turn my
code into a small program which your script uses to connect to the device.
I have attached the whole source file to this email. Hope it helps. Maybe you
can find a way to set the termios flags in tcl.
/* Open the specified device */
void openDevice(char *deviceName)
{
struct termios term;
int result;
file = open(deviceName,O_RDWR|O_NONBLOCK,0);
fprintf(log_file,"openDevice: file %d\n",file);
if(file == -1)
{
fprintf(log_file,"openDevice: errno %d\n",errno);
}
DEBUG(TRUE,"deviceName",deviceName);
memset(&term,0,sizeof(struct termios));
term.c_iflag = IXON|IXOFF|IXANY|IMAXBEL|BRKINT;
term.c_oflag = ONLCR|OXTABS|ONOCR|ONLRET;
term.c_cflag = CREAD|CS8|HUPCL|CLOCAL;
term.c_lflag = ECHOE|ECHOKE|ECHOCTL;
term.c_cc[0] = '\0';
term.c_ispeed = 9600;
term.c_ospeed = 9600;
result = tcsetattr(file,TCSADRAIN,&term);
if(result == -1)
{
fprintf(log_file,"tcsetattr: errno %d\n",errno);
}
}
Regards,
--
Michael Smith
+61 416 062 898
http://glitch.tl
#include <stdio.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>
#include <signal.h>
#include <dirent.h>
#define BUFFERSIZE 1024
#define TRUE 1
#define FALSE 0
#define MAX_MESSAGES 100
#define SPOOL "/var/spool/smsd"
FILE *log_file;
/*
gcc -o smsd smsd.c
/home/smithm/src/smsd/smsd /dev/ugen0.02
*/
int match(char *buffer,char *string)
{
return(!strncmp(buffer,string,strlen(string)));
}
/* The name of the configuration file */
char configuration[BUFFERSIZE];
#define VERBOSE_MESSAGES 100
int verbose = VERBOSE_MESSAGES;
int activityCount = 0;
void trace(int important,char *file,int line,char *identify,char *desc)
{
char buffer[BUFFERSIZE];
char timestamp[BUFFERSIZE];
char *ch;
time_t now;
if(verbose || important)
{
if(verbose) verbose--;
for(ch = buffer; *desc; desc++)
{
if(*desc == '\n' || *desc == '\r')
{
*ch = '\\';
ch++;
*ch = *desc == '\n' ? 'n' : 'r';
}
else
{
*ch = *desc;
}
ch++;
}
*ch = '\0';
time(&now);
strftime(timestamp,BUFFERSIZE,"%Y-%m-%d %T",gmtime(&now));
fprintf(log_file,"%s: %s:%d (%s) %s
[%s]\n",timestamp,file,line,VERSION,identify,buffer);
fflush(log_file);
}
}
#define DEBUG(important,identify,desc)
trace(important,__FILE__,__LINE__,identify,desc)
int file;
void writeLine(char *string)
{
int result;
DEBUG(FALSE,"writeLine",string);
result = write(file,string,strlen(string));
if(result == -1)
{
fprintf(log_file,"writeLine: errno %d\n",errno);
}
}
char scheduledDestination[BUFFERSIZE];
char scheduledMessage[BUFFERSIZE];
int messageScheduled = FALSE;
unsigned int messagesSent = 0;
void sendMessage()
{
char buffer[BUFFERSIZE];
sprintf(buffer,"AT+CMGS=\"%s\"\r%s",scheduledDestination,scheduledMessage);
writeLine(buffer);
buffer[0] = 26;
buffer[1] = 0;
writeLine(buffer);
messageScheduled = FALSE;
if(messagesSent++ > MAX_MESSAGES)
{
exit(0);
}
}
void scheduleMessage(char *destination,char *message)
{
DEBUG(TRUE,"scheduleMessage",destination);
DEBUG(TRUE,"scheduleMessage",message);
if(!destination[0] == '+')
{
DEBUG(TRUE,"Address must start with a + character",destination);
return;
}
if(!strlen(destination) == 12)
{
DEBUG(TRUE,"Address must be characters long",destination);
return;
}
if(!strlen(message) <= 140)
{
DEBUG(TRUE,"Message can not be longer than 140 characters",message);
return;
}
strcpy(scheduledDestination,destination);
strcpy(scheduledMessage,message);
messageScheduled = TRUE;
activityCount = 0;
}
int currentMessage;
int messageToDelete = 0;
int expectMessageText = FALSE;
char message[BUFFERSIZE];
char messageOrigin[BUFFERSIZE];
/* Transmit a CMGR command to retrieve a message */
void writeCMGR(int messageIndex)
{
char buffer[BUFFERSIZE];
currentMessage = messageIndex;
message[0] = '\0';
sprintf(buffer,"AT+CMGR=%d\n",messageIndex);
writeLine(buffer);
}
#define MISSES 3
char currentAlarm[BUFFERSIZE] = "clear";
char alarmRecipient[BUFFERSIZE] = "+61416062898";
struct Host
{
struct host *next;
char hostName[BUFFERSIZE];
int gracePeriod;
time_t lastDetection;
};
struct Host *hosts = NULL;
/*
s5# stty -f /dev/tty00 -e
speed 9600 baud; 0 rows; 0 columns;
lflags: -icanon -isig -iexten -echo echoe -echok echoke -echonl echoctl
-echoprt -altwerase -noflsh -tostop -flusho -pendin -nokerninfo
-extproc
iflags: -istrip -icrnl -inlcr -igncr ixon ixoff ixany imaxbel -ignbrk
brkint -inpck -ignpar -parmrk
oflags: -opost onlcr -ocrnl oxtabs onocr onlret
cflags: cread cs8 -parenb -parodd hupcl clocal -cstopb -crtscts -mdmbuf
-cdtrcts
discard dsusp eof eol eol2 erase intr kill lnext
^O ^Y ^D <undef> <undef> ^? ^C ^U ^V
min quit reprint start status stop susp time werase
1 ^\ ^R ^Q ^T ^S ^Z 0 ^W
*/
/* Open the specified device */
void openDevice(char *deviceName)
{
struct termios term;
int result;
file = open(deviceName,O_RDWR|O_NONBLOCK,0);
fprintf(log_file,"openDevice: file %d\n",file);
if(file == -1)
{
fprintf(log_file,"openDevice: errno %d\n",errno);
}
DEBUG(TRUE,"deviceName",deviceName);
memset(&term,0,sizeof(struct termios));
term.c_iflag = IXON|IXOFF|IXANY|IMAXBEL|BRKINT;
term.c_oflag = ONLCR|OXTABS|ONOCR|ONLRET;
term.c_cflag = CREAD|CS8|HUPCL|CLOCAL;
term.c_lflag = ECHOE|ECHOKE|ECHOCTL;
term.c_cc[0] = '\0';
term.c_ispeed = 9600;
term.c_ospeed = 9600;
result = tcsetattr(file,TCSADRAIN,&term);
if(result == -1)
{
fprintf(log_file,"tcsetattr: errno %d\n",errno);
}
}
/* Close the device */
void closeDevice()
{
DEBUG(TRUE,"closing",deviceName);
close(file);
}
/* Read the configuration file */
void readConfigurationFile(char *fileName)
{
FILE *fin;
char keyword[BUFFERSIZE];
char line[BUFFERSIZE];
fin = fopen(fileName,"r");
while(fscanf(fin,"%s %s",keyword,line) != EOF)
{
if(!strcmp(keyword,"host"))
{
struct Host *host = (struct Host *) calloc(1,sizeof(struct Host));
host->next = hosts;
hosts = host;
sscanf(line,"%s %d",host->hostName,&host->gracePeriod);
time(&host->lastDetection);
DEBUG(TRUE,"hostName",host->hostName);
}
if(!strcmp(keyword,"recipient"))
{
strcpy(alarmRecipient,line);
DEBUG(TRUE,"recipient",alarmRecipient);
}
if(!strcmp(keyword,"device"))
{
openDevice(line);
}
if(!strcmp(keyword,"log"))
{
log_file = fopen(line,"a");
DEBUG(TRUE,"logFile",line);
}
}
fclose(fin);
}
/* Free the linked list of hosts */
void freeHosts(struct Host *host)
{
if(host->next)
{
freeHosts(host->next);
}
free(host);
}
/* Close the configuration */
void closeConfiguration()
{
freeHosts(hosts);
hosts = NULL;
closeDevice();
DEBUG(TRUE,"Closing log file");
fclose(log_file);
}
/* Check for alarms */
void checkForAlarms()
{
char message[BUFFERSIZE];
char command[BUFFERSIZE];
int result;
struct Host *host;
time_t now;
time(&now);
message[0] = '\0';
for(host = hosts; host; host = host->next)
{
sprintf(command,"ping -q -c 1 %s > /dev/null",host->hostName);
DEBUG(TRUE,"checkForAlarms",command);
result = system(command);
if(result)
{
DEBUG(TRUE,"checkForAlarms:missed",host->hostName);
}
else
{
host->lastDetection = now;
}
if(now - host->lastDetection > host->gracePeriod)
{
strcat(message,host->hostName);
strcat(message," ");
}
}
if(strlen(message) == 0)
{
strcpy(message,"clear");
}
if(strcmp(message,currentAlarm))
{
verbose = VERBOSE_MESSAGES;
strcpy(currentAlarm,message);
scheduleMessage(alarmRecipient,currentAlarm);
}
}
int stopScheduled = FALSE;
int rebootScheduled = FALSE;
int commOK = FALSE;
int heartBeatIndex = 21;
void update()
{
if(!commOK)
{
writeLine("AT\r\n");
return;
}
switch(heartBeatIndex++)
{
case 0: writeLine("ATE0\n"); break;
case 1: writeLine("AT+CMEE=1\n"); break;
case 2: writeLine("AT+CPIN?\n"); break;
case 3: writeLine("AT+CMGL\n"); break;
case 4: writeLine("AT+CGMI\n"); break;
case 5: writeLine("AT+CGMM\n"); break;
case 6: writeLine("AT+CGMR\n"); break;
case 7: writeLine("AT+CGSN\n"); break;
case 8: writeLine("AT+CREG?\n"); break;
case 9: writeLine("AT+COPS?\n"); break;
case 10: writeLine("AT+CSQ\n"); break;
case 11: writeCMGR(1); break;
case 12: writeCMGR(2); break;
case 13: writeCMGR(3); break;
case 14: writeCMGR(4); break;
case 15: writeCMGR(5); break;
case 16: writeCMGR(6); break;
case 17: writeCMGR(7); break;
case 18: writeCMGR(8); break;
case 19: writeCMGR(9); break;
case 20: writeCMGR(10); break;
case 21: checkForAlarms(); break;
default:
heartBeatIndex = 0;
break;
}
if(stopScheduled)
{
exit(0);
}
if(rebootScheduled)
{
system("/sbin/reboot");
}
}
void processCMGR(char *buffer)
{
char *comma;
char *ch;
messageOrigin[0] = '\0';
comma = strchr(buffer,',');
if(comma)
{
comma++;
if(*comma == '"')
{
comma++;
ch = messageOrigin;
while(*comma && *comma != '"')
{
*ch++ = *comma++;
}
*ch = '\0';
}
DEBUG(TRUE,"processCMGR",messageOrigin);
}
expectMessageText = TRUE;
}
void processMessage(char *message)
{
DEBUG(TRUE,"processMessage",message);
if(match(message,"status"))
{
strcpy(alarmRecipient,messageOrigin);
currentAlarm[0] = '\0';
checkForAlarms();
}
if(match(message,"stop"))
{
stopScheduled = TRUE;
}
if(match(message,"reboot"))
{
rebootScheduled = TRUE;
}
}
void handleMessageText(char *buffer)
{
DEBUG(TRUE,"handleMessageText",message);
if(match(buffer,"OK"))
{
if(strlen(message))
{
expectMessageText = FALSE;
processMessage(message);
messageToDelete = currentMessage;
}
}
else
{
strcat(message,buffer);
}
}
void processPrompt()
{
}
/*
+CMTI: "SM",1\n
*/
void processCMTI(char *buffer)
{
char *comma;
char number[BUFFERSIZE];
char *ch;
int messageNumber;
verbose = VERBOSE_MESSAGES;
comma = strchr(buffer,',');
if(comma)
{
comma++;
ch = number;
while(*comma && *comma != '\n')
{
*ch++ = *comma++;
}
*ch = '\0';
DEBUG(TRUE,"processCMTI",number);
sscanf(number,"%d",&messageNumber);
writeCMGR(messageNumber);
}
}
// Process an error message
void processCmsError(char *buffer)
{
int errorNumber;
sscanf(buffer,"%d",&errorNumber);
switch(errorNumber)
{
case 301: DEBUG(FALSE,"processCmsError","SMS service of ME reserved");
break;
case 302: DEBUG(FALSE,"processCmsError","Operation not allowed"); break;
case 303: DEBUG(FALSE,"processCmsError","Operation not supported"); break;
case 305: DEBUG(FALSE,"processCmsError","Invalid text mode parameter");
break;
case 311:
DEBUG(FALSE,"processCmsError","SIM PIN required");
writeLine("AT+CPIN=57429\n");
break;
case 313: DEBUG(FALSE,"processCmsError","SIM failure"); break;
case 321: DEBUG(FALSE,"processCmsError","Invalid memory index"); break;
case 322: DEBUG(FALSE,"processCmsError","SIM memory full"); break;
case 330: DEBUG(FALSE,"processCmsError","SC address unknown"); break;
default:
DEBUG(FALSE,"processCmsError",buffer);
return;
}
}
// Process an error message
void processCmeError(char *buffer)
{
int errorNumber;
sscanf(buffer,"%d",&errorNumber);
switch(errorNumber)
{
case 0: DEBUG(FALSE,"processCmeError","Phone failure"); break;
case 3: DEBUG(FALSE,"processCmeError","Operation not allowed"); break;
case 4: DEBUG(FALSE,"processCmeError","Operation not supported"); break;
case 8: DEBUG(FALSE,"processCmeError","Operator determined barring"); break;
case 10: DEBUG(FALSE,"processCmeError","SIM not inserted"); break;
case 11: DEBUG(FALSE,"processCmeError","SIM PIN required"); break;
case 12: DEBUG(FALSE,"processCmeError","SIM PUK required"); break;
case 13: DEBUG(FALSE,"processCmeError","SIM failure"); break;
case 16: DEBUG(FALSE,"processCmeError","Incorrect password"); break;
case 22: DEBUG(FALSE,"processCmeError","Not found"); break;
case 24: DEBUG(FALSE,"processCmeError","Text string too long"); break;
case 26: DEBUG(FALSE,"processCmeError","Dial string too long"); break;
case 30: DEBUG(FALSE,"processCmeError","No network service"); break;
case 256: DEBUG(FALSE,"processCmeError","protocol stack bad state"); break;
case 257: DEBUG(FALSE,"processCmeError","Bad cell ( not in the synchronised
ones)"); break;
case 258: DEBUG(FALSE,"processCmeError","Lost cell"); break;
default:
DEBUG(FALSE,"processCmeError",buffer);
}
}
void deleteMessage(int messageToDelete)
{
char buffer[BUFFERSIZE];
sprintf(buffer,"AT+CMGD=%d\n",messageToDelete);
writeLine(buffer);
}
void processInputSegment(char *buffer)
{
DEBUG(FALSE,"processInputSegment",buffer);
if(expectMessageText)
{
handleMessageText(buffer);
}
if(match(buffer,"OK"))
{
commOK = TRUE;
if(messageScheduled)
{
sendMessage();
return;
}
if(messageToDelete)
{
deleteMessage(messageToDelete);
messageToDelete = 0;
return;
}
}
if(match(buffer,"+CME ERROR:"))
{
processCmeError(&buffer[12]);
}
if(match(buffer,"+CMS ERROR:"))
{
processCmsError(&buffer[12]);
}
if(match(buffer,"+CSQ:"))
{
// processCsq();
}
if(match(buffer,"+CREG:"))
{
// processCREG();
}
if(match(buffer,"\nERROR\n"))
{
writeLine("AT+CMEE=1\n");
}
if(match(buffer,"+CMTI:"))
{
processCMTI(buffer);
}
if(match(buffer,"+CMGR"))
{
processCMGR(buffer);
}
if(match(buffer,">"))
{
processPrompt();
}
if(match(buffer,"+CPIN: SIM PIN"))
{
writeLine("AT+CPIN=57429\n");
}
}
void processInput(char buffer[])
{
int indx;
int msgindx;
char message[BUFFERSIZE];
DEBUG(FALSE,"processInput",buffer);
msgindx = 0;
for(indx = 0; indx < strlen(buffer); indx++)
{
if(buffer[indx] == '\n' || buffer[indx] == '\r')
{
if(msgindx > 0)
{
message[msgindx] = '\0';
processInputSegment(message);
msgindx = 0;
}
}
else
{
message[msgindx] = buffer[indx];
msgindx++;
}
}
}
/* Look for spooled messages to send */
void sendSpooledMessages()
{
DIR *directoryStream;
directoryStream = opendir(SPOOL);
if(directoryStream != NULL)
{
struct dirent *directory;
directory = readdir(directoryStream);
if(directory != NULL && directory->d_name[0] != '.')
{
FILE *file;
char filename[BUFFERSIZE];
char address[BUFFERSIZE];
char message[BUFFERSIZE];
sprintf(filename,"%s/%s",SPOOL,directory->d_name);
DEBUG(TRUE,"reading spooled message",filename);
file = fopen(filename,"r");
fgets(address,BUFFERSIZE,file);
fgets(message,BUFFERSIZE,file);
fclose(file);
remove(filename);
scheduleMessage(address,message);
}
}
}
/* Handle SIGUSR1 */
void handleSIGUSR1(int sig)
{
DEBUG(TRUE,"handleSIGUSR1","Reloading configuration");
closeConfiguration();
readConfigurationFile(configuration);
activityCount = 0;
verbose = VERBOSE_MESSAGES;
sendSpooledMessages();
}
/* Handle SIGUSR1 */
void handleSIGUSR2(int sig)
{
DEBUG(TRUE,"handleSIGUSR2","Waking up");
activityCount = 0;
verbose = VERBOSE_MESSAGES;
}
/* Entry point */
int main(int argc,char *argv[])
{
struct bufferevent *bufferEvent;
struct event_base *base;
char buffer[BUFFERSIZE];
int bytes;
log_file = stdout;
signal(SIGUSR1,handleSIGUSR1);
signal(SIGUSR1,handleSIGUSR1);
strcpy(configuration,argv[1]);
readConfigurationFile(configuration);
writeLine("\n\n\n\n\n\n\n\n\n\nAT\n");
while(1)
{
sleep(1);
if(activityCount++ % (verbose ? 10 : 100) == 0)
{
update();
}
do
{
bytes = read(file,buffer,BUFFERSIZE-1);
if(errno != 35 && errno != 0)
{
fprintf(log_file,"errno: %d\n",errno);
}
if(bytes > 0)
{
buffer[bytes] = '\0';
if(strlen(buffer))
{
processInput(buffer);
}
}
}
while(bytes > 0);
}
}
Home |
Main Index |
Thread Index |
Old Index