diff options
Diffstat (limited to 'src/byteblaster.c')
-rw-r--r-- | src/byteblaster.c | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/src/byteblaster.c b/src/byteblaster.c new file mode 100644 index 0000000..838c828 --- /dev/null +++ b/src/byteblaster.c @@ -0,0 +1,219 @@ +/*************************************************************************** + byteblaster.c - Low-level functions to access the byteblaster + ------------------------------------------------------------- + + begin : Sun Jan 09 2005 + copyright : (C) 2005 by Aurelien Jarno + email : aurelien@aurel32.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +/* Application specific includes */ +#include "byteblaster.h" +#include "main.h" + +/* Standard includes */ +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <linux/ppdev.h> +#include <linux/parport.h> +#include <sys/ioctl.h> + +/*************************************************************************** + * * + * Private functions * + * * + ***************************************************************************/ + +static void out_data(int device, unsigned char mask, unsigned char val) +{ + static unsigned char data = 0; + + data = (data & ~mask) | val; + ioctl(device, PPWDATA, &data); +} + +static void set_AUTOFEED(int device, int value) +{ + struct ppdev_frob_struct frob; + + frob.mask = PARPORT_CONTROL_AUTOFD; + frob.val = (value != 0) ? PARPORT_CONTROL_AUTOFD : 0; + ioctl(device, PPFCONTROL, &frob); + usleep(100000); +} + +static void set_D5(int device, int value) +{ + /* D5 */ + out_data(device, 0x20, (value != 0)? 0x20 : 0x00); +} + +static int get_ACK(int device) +{ + unsigned char status; + + ioctl(device, PPRSTATUS, &status); + return (status & PARPORT_STATUS_ACK) == PARPORT_STATUS_ACK; +} + +static int open_parport(char *device_name) +{ + int dev; + + if (debug) + printf("Opening %s\n", device_name); + + dev = open(device_name, O_RDWR); + if (dev < 0) + { + if (!quiet) + perror("open"); + return -1; + } + if (ioctl(dev, PPCLAIM) < 0) + { + if (!quiet) + perror("open"); + perror("ioctl"); + close(dev); + return -1; + } + return dev; +} + +static void close_parport(int device) +{ + if (device) + { + ioctl(device, PPRELEASE); + close(device); + } +} + +static int detect_byteblaster(int device) +{ + if (debug) + printf("Detecting byteblaster\n"); + + /* ACK and D5 are connected together */ + if (debug) + printf("Driving D5 low\n"); + set_D5(device, 0); + usleep(10000); + if (get_ACK(device) == 1) + { + if (debug) + fprintf(stderr, "ACK stuck high\n"); + return -1; + } + + if (debug) + printf("Driving D5 high\n"); + set_D5(device, 1); + usleep(10000); + if (get_ACK(device) == 0) + { + if (debug) + fprintf(stderr, "ACK stuck low\n"); + return -1; + } + + if (debug) + printf("Driving D5 low\n"); + set_D5(device, 0); + usleep(10000); + if (get_ACK(device) == 1) + { + if (debug) + fprintf(stderr, "ACK stuck high\n"); + return -1; + } + + return 0; +} + + +/*************************************************************************** + * * + * Public functions * + * * + ***************************************************************************/ + +int get_nSTATUS(int device) +{ + unsigned char status; + + ioctl(device, PPRSTATUS, &status); + return (status & PARPORT_STATUS_SELECT) == PARPORT_STATUS_SELECT; +} + +int get_CONF_DONE(int device) +{ + unsigned char status; + + ioctl(device, PPRSTATUS, &status); + return (status & PARPORT_STATUS_BUSY) != PARPORT_STATUS_BUSY; +} + +void set_DCLK(int device, int value) +{ + /* D0 */ + out_data(device, 0x01, (value != 0)? 0x01 : 0x00); +} + +void set_nCONFIG(int device, int value) +{ + /* D1 */ + out_data(device, 0x02, (value != 0)? 0x02 : 0x00); +} + +void set_DATA0(int device, int value) +{ + /* D6 */ + out_data(device, 0x40, (value != 0)? 0x40 : 0x00); +} + +int open_byteblaster(char *devicename) +{ + int dev; + + dev = open_parport(devicename); + if (dev < 0 ) + { + if (!quiet) + fprintf(stderr, "Can't open %s!\n", devicename); + return -1; + } + + if (detect_byteblaster(dev) < 0) + { + if (!quiet) + fprintf(stderr, "Byteblaster not found on %s!\n", devicename); + close_byteblaster(dev); + return -1; + } + + return dev; +} + +void close_byteblaster(int device) +{ + enable_byteblaster(device, 0); + close_parport(device); +} + +void enable_byteblaster(int device, int value) +{ + set_AUTOFEED(device, value); +} + |