Tools for working with Cidco Mailstations
at master 168 lines 3.4 kB view raw
1/* 2 * sendload 3 * 4 * must be run as root to set iopl and use inb/outb 5 * 6 * assumes Loader has been loaded on the Mailstation and is running 7 */ 8 9#include <err.h> 10#include <errno.h> 11#include <fcntl.h> 12#include <stdio.h> 13#include <stdlib.h> 14#include <string.h> 15#include <signal.h> 16#include <termios.h> 17#include <unistd.h> 18#include <sys/stat.h> 19#include <sys/types.h> 20 21#include "tribble.h" 22 23static int serial_fd = -1; 24static int serial_speed = B115200; 25 26void 27usage(void) 28{ 29 errx(1, "usage: %s [-dr] [-p lpt address | serial device] " 30 "[-s serial speed] <file to send>", getprogname()); 31} 32 33int 34sendbyte_shim(char b) 35{ 36 if (serial_fd >= 0) 37 return (write(serial_fd, &b, 1) != 1); 38 else 39 return sendbyte(b); 40} 41 42void 43setupserial(speed_t speed) 44{ 45 struct termios tty; 46 47 if (tcgetattr(serial_fd, &tty) < 0) 48 err(1, "tcgetattr"); 49 50 cfsetospeed(&tty, speed); 51 cfsetispeed(&tty, speed); 52 53 tty.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */ 54 tty.c_cflag &= ~CSIZE; 55 tty.c_cflag |= CS8; /* 8-bit characters */ 56 tty.c_cflag &= ~PARENB; /* no parity bit */ 57 tty.c_cflag &= ~CSTOPB; /* only need 1 stop bit */ 58 59 /* setup for non-canonical mode */ 60 tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); 61 tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); 62 tty.c_oflag &= ~OPOST; 63 64 /* fetch bytes as they become available */ 65 tty.c_cc[VMIN] = 1; 66 tty.c_cc[VTIME] = 1; 67 68 if (tcsetattr(serial_fd, TCSANOW, &tty) != 0) 69 err(1, "tcsetattr"); 70} 71 72int 73main(int argc, char *argv[]) 74{ 75 FILE *pFile; 76 struct stat sb; 77 unsigned int sent = 0, size = 0, raw = 0; 78 int ch; 79 char *fn, *serial_dev = NULL; 80 81 while ((ch = getopt(argc, argv, "dp:rs:")) != -1) { 82 switch (ch) { 83 case 'd': 84 tribble_debug = 1; 85 break; 86 case 'p': 87 if (optarg[0] == '/') { 88 if ((serial_dev = strdup(optarg)) == NULL) 89 err(1, "strdup"); 90 serial_fd = open(serial_dev, 91 O_RDWR | O_NOCTTY | O_SYNC); 92 if (serial_fd < 0) 93 err(1, "can't open %s", optarg); 94 } else { 95 tribble_port = (unsigned)strtol(optarg, NULL, 96 0); 97 if (errno) 98 err(1, "invalid port value"); 99 } 100 break; 101 case 'r': 102 raw = 1; 103 break; 104 case 's': 105 serial_speed = (unsigned)strtol(optarg, NULL, 0); 106 if (errno) 107 err(1, "invalid serial port speed value"); 108 break; 109 default: 110 usage(); 111 } 112 } 113 argc -= optind; 114 argv += optind; 115 116 if (argc != 1) 117 usage(); 118 119 if (serial_fd >= 0) 120 setupserial(serial_speed); 121 else 122 checkio(); 123 124 fn = argv[0]; 125 pFile = fopen(fn, "rb"); 126 if (!pFile) 127 err(1, "open: %s", fn); 128 129 if (fstat(fileno(pFile), &sb) != 0) 130 err(1, "fstat: %s", fn); 131 132 /* we're never going to send huge files */ 133 size = (unsigned int)sb.st_size; 134 135 if (serial_fd >= 0) 136 printf("[%s]", serial_dev); 137 else 138 printf("[lpt port 0x%x]", tribble_port); 139 140 printf(" sending %s (%d bytes)...", fn, size); 141 fflush(stdout); 142 143 /* loader expects two bytes, the low and then high of the file size */ 144 if (!raw) { 145 if (sendbyte_shim(size & 0xff) != 0) 146 errx(1, "sendbyte failed"); 147 if (sendbyte_shim((size >> 8) & 0xff) != 0) 148 errx(1, "sendbyte failed"); 149 } 150 151 while (sent < size) { 152 if (sendbyte_shim(fgetc(pFile)) != 0) 153 errx(1, "sendbyte failed at %d/%d", sent, size); 154 155 if (sent++ == 0) 156 printf("\n"); 157 158 if (sent % (raw ? 64 : 1024) == 0 || sent == size) { 159 printf("\rsent: %07d/%07d", sent, size); 160 fflush(stdout); 161 } 162 } 163 fclose(pFile); 164 165 printf("\n"); 166 167 return 0; 168}