aboutsummaryrefslogtreecommitdiff
path: root/src/byteblaster.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/byteblaster.c')
-rw-r--r--src/byteblaster.c219
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);
+}
+