drivewire: init commit "dwdate" - set system time from userspace.
authorBrett Gordon <beretta42@gmail.com>
Sun, 28 Aug 2016 20:48:04 +0000 (16:48 -0400)
committerBrett Gordon <beretta42@gmail.com>
Sun, 28 Aug 2016 20:55:35 +0000 (16:55 -0400)
Applications/dw/Makefile.6809
Applications/dw/dwdate.c [new file with mode: 0644]
Applications/dw/fuzix-dw.pkg

index 4745f39..5614c92 100644 (file)
@@ -15,7 +15,7 @@ CRT0 = ../../Library/libs/crt0_6809.o
 .SUFFIXES: .c .o
 
 
-SRCS  = dw.c dwgetty.c dwterm.c
+SRCS  = dw.c dwgetty.c dwterm.c dwdate.c
 
 OBJS = $(SRCS:.c=.o)
 
diff --git a/Applications/dw/dwdate.c b/Applications/dw/dwdate.c
new file mode 100644 (file)
index 0000000..74643b4
--- /dev/null
@@ -0,0 +1,174 @@
+/* A program to get the time from drivewire.  Displays it or sets the
+   system clock from it.  Must be super user
+*/
+
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/drivewire.h>
+
+
+char *devname="/dev/dw0";
+
+static const uint16_t mktime_moffset[12]= { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+
+
+static int printe( char *s ){
+    write(2, s, strlen(s) );
+    write(2, "\n", 1 );
+}
+
+/* A Classic, as stolen from Gnu */
+static uint32_t mul( uint32_t a, uint32_t b)
+{
+       uint32_t r=0;
+       while (a){
+               if (a & 1)
+                       r += b;
+               a >>= 1;
+               b <<= 1;
+       }
+       b=r;
+       return b;
+}
+
+
+static int get_time( uint8_t *tbuf )
+{
+    int fd;
+    int ret;
+    struct dw_trans d;
+
+    fd = open( devname, O_RDONLY );
+    if( fd < 1){
+       perror( "drivewire device open");
+       exit(1);
+    }
+
+    tbuf[0]=0x23;
+    d.sbuf = tbuf;
+    d.sbufz = 1;
+    d.rbuf = tbuf;
+    d.rbufz = 6;
+    
+    ret = ioctl( fd, DRIVEWIREC_TRANS, &d );
+    close( fd );
+    return ret;
+}
+
+
+int main( int argc, char *argv[] ){
+
+    int i,x;
+    char buf[6];
+    uint8_t year, month, day, hour, minute, second;
+    uint32_t ret;   /* accumulator for conversion */
+    int setflg = 0;     /* set system time flag */
+    int disflg = 0;     /* display retrieved time flag */
+    int parbrk = 0;     /* parse break flag */
+
+    /* scan args */
+    for( x = 1; x < argc; x++ ){
+       if( argv[x][0] != '-' ){
+           printe( "bad arg" );
+           exit(1);
+       }
+       for( i = 1; argv[x][i]; i++ ){
+           switch( argv[x][i] ){
+           case 's':
+               setflg = 1;
+               break;
+           case 'd':
+               disflg = 1;
+               break;
+           case 'x':
+               devname = argv[++x];
+               if( ! devname ){
+                   printe("bad device name");
+                   exit(1);
+               }
+               parbrk = 1;
+               break;
+           default:
+               printe("bad option" );
+               exit(1);
+           }
+           if( parbrk ){
+               parbrk = 0;
+               break;
+           }
+       }
+    }
+
+    x=get_time( buf );
+    if( x ){
+       perror("drivewire");
+       exit(1);
+    }
+
+    /* figure out secs from epoc */
+     
+    year   = buf[0];
+    month  = buf[1];
+    day    = buf[2];
+    hour   = buf[3];
+    minute = buf[4];
+    second = buf[5];
+    
+    if(year < 70)
+       year += 100;
+    
+    /* following code is based on utc_mktime() from ELKS
+       https://github.com/jbruchon/elks/blob/master/elkscmd/sh_utils/date.c 
+    */
+    
+    /* uses zero-based month index */
+    month--;
+    
+    /* calculate days from years */
+    ret=365;
+    ret = mul( ret, year - 70 );
+    
+    /* count leap days in preceding years */
+    ret += (year - 69) >> 2;
+    
+    
+    /* calculate days from months */
+    ret += mktime_moffset[month];
+    
+    /* add in this year's leap day, if any */
+    if (((year & 3) == 0) && (month > 1)) 
+       ret++;
+    
+    /* add in days in this month */
+    ret += day - 1;
+    /* convert to hours */
+    ret = mul( ret, 24 );
+    ret += hour;
+    
+    /* convert to minutes */
+    ret = mul( ret, 60 );
+    ret += minute;
+    
+    /* convert to seconds */
+    ret = mul( ret, 60 );
+    ret += second;
+
+    if( disflg || !setflg )
+       printf( ctime( (time_t *)&ret ) );
+
+    if( setflg ){
+       /* This is a sleezy cast */
+       x=stime( (time_t *)&ret );
+       if( x ){
+           perror( "stime" );
+           exit(1);
+       }
+    }
+
+    exit(0);
+    
+}
index 4156a05..e1259fb 100644 (file)
@@ -1,6 +1,8 @@
 package  drivewire
 if-file  dw
 
-f 0755 /usr/bin/dw           dw
-f 0755 /usr/bin/dwgetty      dwgetty
-f 0755 /usr/bin/dwterm       dwterm
+f 0755 /usr/bin/dw             dw
+f 0755 /usr/bin/dwgetty        dwgetty
+f 0755 /usr/bin/dwterm         dwterm
+f 0755 /usr/bin/dwdate         dwdate
+f 0644 /usr/man/man1/dwdate.1  dwdate.1
\ No newline at end of file