PRINT65 - print to Jetdirect printer over net
This commit is contained in:
parent
84bcdc2043
commit
3f9ad451e2
|
@ -45,7 +45,7 @@ TCP =\
|
|||
tweet65 \
|
||||
pop65-slow
|
||||
|
||||
bin: wget65.bin pop65.bin smtp65.bin email.bin rebuild.bin edit.bin attacher.bin nntp65.bin nntp65.up.bin
|
||||
bin: wget65.bin pop65.bin smtp65.bin email.bin rebuild.bin edit.bin attacher.bin nntp65.bin nntp65.up.bin print65.bin
|
||||
|
||||
wget65.bin: w5100.c w5100_http.c linenoise.c
|
||||
wget65.bin: IP65LIB = ../ip65/ip65.lib
|
||||
|
@ -67,6 +67,10 @@ nntp65.up.bin: w5100.c
|
|||
nntp65.up.bin: IP65LIB = ../ip65/ip65.lib
|
||||
nntp65.up.bin: A2_DRIVERLIB = ../drivers/ip65_apple2_uther2.lib
|
||||
|
||||
print65.bin: w5100.c
|
||||
print65.bin: IP65LIB = ../ip65/ip65.lib
|
||||
print65.bin: A2_DRIVERLIB = ../drivers/ip65_apple2_uther2.lib
|
||||
|
||||
email.bin: gettime.s
|
||||
|
||||
date65.bin hfs65.bin tweet65.bin: CL65FLAGS = --start-addr 0x0C00 apple2enh-iobuf-0800.o
|
||||
|
@ -166,6 +170,8 @@ ip65.dsk: bin
|
|||
java -jar $(AC) -p $@ nntp65up.system sys < $(CC65)/apple2enh/util/loader.system
|
||||
java -jar $(AC) -as $@ pop65 < pop65.bin
|
||||
java -jar $(AC) -p $@ pop65.system sys < $(CC65)/apple2enh/util/loader.system
|
||||
java -jar $(AC) -as $@ print65 < print65.bin
|
||||
java -jar $(AC) -p $@ print65.system sys < $(CC65)/apple2enh/util/loader.system
|
||||
java -jar $(AC) -as $@ rebuild < rebuild.bin
|
||||
java -jar $(AC) -p $@ rebuild.system sys < $(CC65)/apple2enh/util/loader.system
|
||||
java -jar $(AC) -as $@ smtp65 < smtp65.bin
|
||||
|
|
|
@ -0,0 +1,311 @@
|
|||
/////////////////////////////////////////////////////////////////
|
||||
// PRINT65
|
||||
// Print files over the network to an HP Jetdirect printer
|
||||
// Bobbi June 2021
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <cc65.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <conio.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <apple2_filetype.h>
|
||||
|
||||
#include "../inc/ip65.h"
|
||||
#include "w5100.h"
|
||||
|
||||
#include "email_common.h"
|
||||
|
||||
#define BELL 7
|
||||
#define BACKSPACE 8
|
||||
#define NORMAL 0x0e
|
||||
#define INVERSE 0x0f
|
||||
#define CLRLINE 0x1a
|
||||
|
||||
// Both pragmas are obligatory to have cc65 generate code
|
||||
// suitable to access the W5100 auto-increment registers.
|
||||
#pragma optimize (on)
|
||||
#pragma static-locals (on)
|
||||
|
||||
#define NETBUFSZ 1500
|
||||
#define LINEBUFSZ 1000 // According to RFC2822 Section 2.1.1 (998+CRLF)
|
||||
#define READSZ 1024 // Must be less than NETBUFSZ to fit in buf[]
|
||||
|
||||
static unsigned char buf[NETBUFSZ+1]; // One extra byte for null terminator
|
||||
static char linebuf[LINEBUFSZ];
|
||||
|
||||
static uint8_t exec_email_on_exit = 0;
|
||||
static char filename[256];
|
||||
static FILE *fp;
|
||||
static uint32_t filesize;
|
||||
static uint16_t jetdirect_port;
|
||||
|
||||
/*
|
||||
* Keypress before quit
|
||||
*/
|
||||
void confirm_exit(void) {
|
||||
printf("\n[Press Any Key]");
|
||||
cgetc();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called for all non IP65 errors
|
||||
*/
|
||||
void error_exit() {
|
||||
confirm_exit();
|
||||
}
|
||||
|
||||
/*
|
||||
* Called if IP65 call fails
|
||||
*/
|
||||
void ip65_error_exit(void) {
|
||||
printf("%s\n", ip65_strerror(ip65_error));
|
||||
confirm_exit();
|
||||
}
|
||||
|
||||
/*
|
||||
* Print message to the console, stripping extraneous CRLF stuff
|
||||
* from the end.
|
||||
*/
|
||||
void print_strip_crlf(char *s) {
|
||||
uint8_t i = 0;
|
||||
while ((s[i] != '\0') && (s[i] != '\r') && (s[i] != '\n'))
|
||||
putchar(s[i++]);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
/*
|
||||
* Spinner while uploading files
|
||||
*/
|
||||
void spinner(uint32_t sz, uint8_t final) {
|
||||
static char chars[] = "|/-\\";
|
||||
static char buf[10] = "";
|
||||
static uint8_t i = 0;
|
||||
uint8_t j;
|
||||
for (j = 0; j < strlen(buf); ++j)
|
||||
putchar(BACKSPACE);
|
||||
if (final) {
|
||||
sprintf(buf, " [%lu]\n", sz);
|
||||
printf("%s", buf);
|
||||
strcpy(buf, "");
|
||||
}
|
||||
else {
|
||||
sprintf(buf, "%c %lu", chars[(i++) % 4], sz);
|
||||
printf("%s", buf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a text file a line at a time
|
||||
* Returns number of chars in the line, or 0 if EOF.
|
||||
* Expects Apple ][ style line endings (CR) and does no conversion
|
||||
* fp - file to read from
|
||||
* reset - if 1 then just reset the buffer and return
|
||||
* writep - Pointer to buffer into which line will be written
|
||||
* n - length of buffer. Longer lines will be truncated and terminated with CR.
|
||||
*/
|
||||
uint16_t get_line(FILE *fp, uint8_t reset, char *writep, uint16_t n) {
|
||||
static uint16_t rd = 0; // Read
|
||||
static uint16_t end = 0; // End of valid data in buf
|
||||
uint16_t i = 0;
|
||||
if (reset) {
|
||||
rd = end = 0;
|
||||
return 0;
|
||||
}
|
||||
while (1) {
|
||||
if (rd == end) {
|
||||
end = fread(buf, 1, READSZ, fp);
|
||||
rd = 0;
|
||||
}
|
||||
if (end == 0)
|
||||
goto done;
|
||||
if (i == n - 1) {
|
||||
writep[i - 1] = '\r';
|
||||
goto done;
|
||||
}
|
||||
writep[i++] = buf[rd++];
|
||||
if (writep[i - 1] == '\r')
|
||||
goto done;
|
||||
}
|
||||
done:
|
||||
writep[i] = '\0';
|
||||
return i;
|
||||
}
|
||||
|
||||
#define DO_SEND 1 // For do_send param
|
||||
#define DONT_SEND 0 // For do_send param
|
||||
#define CMD_MODE 0 // For mode param
|
||||
#define DATA_MODE 1 // For mode param
|
||||
|
||||
// Read file handle fp and send message over TCP
|
||||
bool w5100_tcp_send() {
|
||||
|
||||
//
|
||||
// Handle sending of email body
|
||||
//
|
||||
uint16_t pos = 0;
|
||||
uint8_t cont = 1;
|
||||
uint16_t snd;
|
||||
uint16_t len;
|
||||
|
||||
filesize = 0;
|
||||
len = get_line(fp, 1, linebuf, LINEBUFSZ); // Reset buffer
|
||||
|
||||
while (cont) {
|
||||
|
||||
len = get_line(fp, 0, linebuf, LINEBUFSZ - 1);
|
||||
pos = 0;
|
||||
|
||||
if (len == 0) {
|
||||
strcpy(linebuf, "\r\n");
|
||||
len = 2;
|
||||
cont = 0;
|
||||
} else {
|
||||
linebuf[len++] = '\n'; // CR -> CRLF
|
||||
linebuf[len] = '\0';
|
||||
filesize += len;
|
||||
}
|
||||
|
||||
while (len) {
|
||||
if (input_check_for_abort_key()) {
|
||||
printf("User abort\n");
|
||||
w5100_disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
snd = w5100_send_request();
|
||||
if (!snd) {
|
||||
if (!w5100_connected()) {
|
||||
printf("Connection lost\n");
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (len < snd)
|
||||
snd = len;
|
||||
|
||||
{
|
||||
// One less to allow for faster pre-increment below
|
||||
const char *dataptr = linebuf + pos - 1;
|
||||
uint16_t i;
|
||||
for (i = 0; i < snd; ++i) {
|
||||
// The variable is necessary to have cc65 generate code
|
||||
// suitable to access the W5100 auto-increment register.
|
||||
char data = *++dataptr;
|
||||
*w5100_data = data;
|
||||
}
|
||||
}
|
||||
|
||||
w5100_send_commit(snd);
|
||||
len -= snd;
|
||||
pos += snd;
|
||||
}
|
||||
spinner(filesize, 0);
|
||||
}
|
||||
spinner(filesize, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read parms from PRINT.CFG
|
||||
*/
|
||||
void readconfigfile(void) {
|
||||
char *colon;
|
||||
fp = fopen("PRINT.CFG", "r");
|
||||
if (!fp) {
|
||||
puts("Can't open config file PRINT.CFG");
|
||||
error_exit();
|
||||
}
|
||||
fscanf(fp, "%s", cfg_server);
|
||||
fclose(fp);
|
||||
|
||||
colon = strchr(cfg_server, ':');
|
||||
if (!colon)
|
||||
jetdirect_port = 9100;
|
||||
else {
|
||||
jetdirect_port = atoi(colon + 1);
|
||||
*colon = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
void main(int argc, char *argv[]) {
|
||||
uint8_t eth_init = ETH_INIT_DEFAULT, connected = 0;
|
||||
|
||||
videomode(VIDEOMODE_80COL);
|
||||
printf("%c%s PRINT%c\n", 0x0f, PROGNAME, 0x0e);
|
||||
|
||||
puts("\nThis utility allows printing to a network-connected printer");
|
||||
puts("using the HP Jetdirect protocol.\n");
|
||||
if (argc == 2) {
|
||||
strcpy(filename, argv[1]);
|
||||
} else {
|
||||
printf("\nFilename to print >");
|
||||
scanf("%s", filename);
|
||||
puts("");
|
||||
}
|
||||
|
||||
readconfigfile();
|
||||
|
||||
{
|
||||
int file;
|
||||
|
||||
printf("\nSetting slot - ");
|
||||
file = open("ethernet.slot", O_RDONLY);
|
||||
if (file != -1) {
|
||||
read(file, ð_init, 1);
|
||||
close(file);
|
||||
eth_init &= ~'0';
|
||||
}
|
||||
}
|
||||
|
||||
printf("%d\nInitializing %s - ", eth_init, eth_name);
|
||||
if (ip65_init(eth_init)) {
|
||||
ip65_error_exit();
|
||||
}
|
||||
|
||||
// Abort on Ctrl-C to be consistent with Linenoise
|
||||
abort_key = 0x83;
|
||||
|
||||
printf("Ok\nObtaining IP address - ");
|
||||
if (dhcp_init()) {
|
||||
ip65_error_exit();
|
||||
}
|
||||
printf("Ok\n");
|
||||
|
||||
// Copy IP config from IP65 to W5100
|
||||
w5100_config(eth_init);
|
||||
|
||||
fp = fopen(filename, "rb");
|
||||
if (!fp) {
|
||||
printf("Can't open %s\n", filename);
|
||||
error_exit();
|
||||
}
|
||||
|
||||
if (!connected) {
|
||||
printf("\nConnecting to %s:%d - ", cfg_server, jetdirect_port);
|
||||
|
||||
if (!w5100_connect(parse_dotted_quad(cfg_server), jetdirect_port)) {
|
||||
printf("Fail\n");
|
||||
error_exit();
|
||||
}
|
||||
|
||||
printf("Ok\n\n");
|
||||
|
||||
}
|
||||
if (!w5100_tcp_send()) {
|
||||
error_exit();
|
||||
}
|
||||
fclose(fp);
|
||||
printf("Disconnecting\n");
|
||||
w5100_disconnect();
|
||||
|
||||
confirm_exit();
|
||||
}
|
||||
|
Loading…
Reference in New Issue