Hi Urjtag authors!

Some time ago, while experimenting with UrJTAG, I wrote a driver to be able
to use the parallel port of my NetBSD machine with a ByteblasterMV cable.

The driver is called ppbusgpio.c, or just "gpio", because the ppbus under
NetBSD attaches 17 GPIO pins to control all parallel port lines via
/dev/gpio0.

Some days ago, while using UrJTAG again to unbrick my Allnet 6250, I adapted
my source to compile with the current r2012 revision.

You find a diff file on r2012 attached. It is complete, also in respect to
auto configuration (a new lowlevel driver "gpio" can be selected). I also
fixed some bugs with missing "(unsigned char)" casts, which cause error
messages since gcc 4.5.

It is tested and proven to work. Would be nice if you consider to include it
into future releases.

Regards,

-- 
Frank Wille
--- urjtag/configure.ac.orig    2011-11-19 20:20:43.000000000 +0100
+++ urjtag/configure.ac 2011-11-19 20:25:16.000000000 +0100
@@ -149,6 +149,7 @@
 
 AC_CHECK_HEADERS([linux/ppdev.h], [HAVE_LINUX_PPDEV_H="yes"])
 AC_CHECK_HEADERS([dev/ppbus/ppi.h], [HAVE_DEV_PPBUS_PPI_H="yes"])
+AC_CHECK_HEADERS([sys/gpio.h], [HAVE_SYS_GPIO_H="yes"])
 AC_CHECK_HEADERS(m4_flatten([
        wchar.h
        windows.h
@@ -685,6 +686,7 @@
        ftd2xx
        ppdev
        ppi
+       gpio
 ],[
 ],[
        # automatically disable lowlevel drivers when a required feature is not 
available
@@ -700,6 +702,9 @@
        AS_IF([test "x$HAVE_DEV_PPBUS_PPI_H" != "xyes"], [
                drivers=`echo ${drivers} | $SED -e "s/ppi//"`
        ])
+       AS_IF([test "x$HAVE_SYS_GPIO_H" != "xyes"], [
+               drivers=`echo ${drivers} | $SED -e "s/gpio//"`
+       ])
        AS_IF([test "x$HAVE_IOPERM" != "xyes" -a "x$HAVE_I386_SET_IOPERM" != 
"xyes" -a "x$HAVE_INPOUTXX" != "xyes" ], [
                drivers=`echo ${drivers} | $SED -e "s/direct//"`
        ])
--- urjtag/include/urjtag/parport.h.orig        2011-11-19 20:35:12.000000000 
+0100
+++ urjtag/include/urjtag/parport.h     2011-11-19 20:35:40.000000000 +0100
@@ -36,6 +36,7 @@
     URJ_CABLE_PARPORT_DEV_PARALLEL,
     URJ_CABLE_PARPORT_DEV_PPDEV,
     URJ_CABLE_PARPORT_DEV_PPI,
+    URJ_CABLE_PARPORT_DEV_GPIO,
     URJ_CABLE_PARPORT_N_DEVS,
 }
 urj_cable_parport_devtype_t;
--- urjtag/src/tap/parport/ppbusgpio.c.orig     2011-11-20 12:33:26.000000000 
+0100
+++ urjtag/src/tap/parport/ppbusgpio.c  2011-11-20 12:55:31.000000000 +0100
@@ -0,0 +1,277 @@
+/*
+ * $Id: $
+ *
+ * NetBSD ppbus/gpio Driver
+ * Copyright (C) 2011 Frank Wille
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by Frank Wille <[email protected]>, 2011.
+ *
+ */
+
+#include <sysdep.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/gpio.h>
+#include <sys/ioctl.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <urjtag/error.h>
+#include <urjtag/log.h>
+#include <urjtag/parport.h>
+#include <urjtag/cable.h>
+#include "../parport.h"
+
+static port_node_t *ports = NULL;       /* ppi parallel ports */
+
+typedef struct {
+       char *portname;
+       int fd;
+       uint8_t data, stat, ctrl;
+} gpio_params_t;
+
+static urj_parport_t *
+gpio_parport_alloc (const char *port)
+{
+    gpio_params_t *params = malloc (sizeof *params);
+    char *portname = strdup (port);
+    urj_parport_t *parport = malloc (sizeof *parport);
+    port_node_t *node = malloc (sizeof *node);
+
+    if (!node || !parport || !params || !portname) {
+        free (node);
+        free (parport);
+        free (params);
+        free (portname);
+        urj_error_set (URJ_ERROR_OUT_OF_MEMORY,
+                       "malloc(%zd)/strdup(%s)/malloc(%zd)/malloc(%zd) fails",
+                       sizeof *params, port, sizeof *parport, sizeof *node);
+        return NULL;
+    }
+
+    params->portname = portname;
+    params->fd = -1;
+
+    parport->params = params;
+    parport->driver = &urj_tap_parport_gpio_parport_driver;
+    parport->cable = NULL;
+
+    node->port = parport;
+    node->next = ports;
+
+    ports = node;
+
+    return parport;
+}
+
+static void
+gpio_parport_free (urj_parport_t *port)
+{
+    port_node_t **prev;
+
+    for (prev = &ports; *prev; prev = &((*prev)->next))
+        if ((*prev)->port == port)
+            break;
+
+    if (*prev) {
+        port_node_t *pn = *prev;
+        *prev = pn->next;
+        free (pn);
+    }
+
+    free (((gpio_params_t *) port->params)->portname);
+    free (port->params);
+    free (port);
+}
+
+static urj_parport_t *
+gpio_connect (const char *devname)
+{
+    port_node_t *pn;
+    urj_parport_t *parport;
+
+    for (pn = ports; pn; pn = pn->next)
+        if (strcmp (pn->port->params, devname) == 0)
+        {
+            urj_log (URJ_LOG_LEVEL_NORMAL,
+                     _("Disconnecting %s from gpio port %s\n"),
+                     _(pn->port->cable->driver->description), devname);
+            pn->port->cable->driver->disconnect (pn->port->cable);
+            break;
+        }
+
+    urj_log (URJ_LOG_LEVEL_NORMAL, _("Initializing gpio port %s\n"), devname);
+
+    parport = gpio_parport_alloc (devname);
+    if (!parport)
+        return NULL;
+
+    return parport;
+}
+
+static int
+gpio_open (urj_parport_t *parport)
+{
+    gpio_params_t *p = parport->params;
+    struct gpio_req req;
+    int pin;
+
+    p->fd = open (p->portname, O_RDWR);
+    if (p->fd < 0) {
+        urj_error_IO_set ("Cannot open(%s)", p->portname);
+        return URJ_STATUS_FAIL;
+    }
+
+    /* Initialize all GPIO pins with 0 */
+    memset(&req, 0, sizeof(req));
+    req.gp_value = GPIO_PIN_LOW;
+    for (pin = 0; pin < 17; pin++) {
+        req.gp_pin = pin;
+        if (ioctl(p->fd, GPIOWRITE, &req) == -1) {
+            close(p->fd);
+            p->fd = -1;
+            return URJ_STATUS_FAIL;
+        }
+    }
+    p->data = p->stat = p->ctrl = 0;
+
+    return URJ_STATUS_OK;
+}
+
+static int
+gpio_close (urj_parport_t *parport)
+{
+    int r = URJ_STATUS_OK;
+    gpio_params_t *p = parport->params;
+
+    if (close (p->fd) != 0) {
+        urj_error_IO_set ("Cannot close(%d)", p->fd);
+        return URJ_STATUS_FAIL;
+    }
+
+    p->fd = -1;
+    return r;
+}
+
+static int
+gpio_set_data (urj_parport_t *parport, unsigned char data)
+{
+    gpio_params_t *p = parport->params;
+    struct gpio_req req;
+    uint8_t changed, mask;
+    int i;
+
+    memset(&req, 0, sizeof(req));
+
+    if ((changed = data ^ p->data)) {
+        for (mask = 1, i = 1; i <= 8; mask <<= 1, i++) {
+            if ((changed & mask) != 0) {
+                req.gp_pin = i;
+                req.gp_value = (data & mask) ? GPIO_PIN_HIGH : GPIO_PIN_LOW;
+                if (ioctl(p->fd, GPIOWRITE, &req) == -1)
+                    return URJ_STATUS_FAIL;
+            }
+        }
+        p->data = data;
+    }
+
+    return URJ_STATUS_OK;
+}
+
+static int
+gpio_get_data (urj_parport_t *parport)
+{
+    gpio_params_t *p = parport->params;
+    struct gpio_req req;
+    int d, i, mask;
+
+    memset(&req, 0, sizeof(req));
+
+    for (d = 0, mask = 1, i = 1; i <= 8; mask <<= 1, i++) {
+        req.gp_pin = i;
+        if (ioctl( p->fd, GPIOREAD, &req ) == -1)
+            return -1;
+        if (req.gp_value == GPIO_PIN_HIGH)
+            d |= mask;
+    }
+    p->data = d;
+
+    return d;
+}
+
+static int
+gpio_get_status (urj_parport_t *parport)
+{
+    gpio_params_t *p = parport->params;
+    struct gpio_req req;
+    int d, i, mask;
+    int pins[8] = { 0, 0, 0, 14, 12, 11, 9, 10 };
+
+    memset(&req, 0, sizeof(req));
+
+    for (d = 0, mask = (1<<3), i = 3; i < 8; mask <<= 1, i++) {
+        req.gp_pin = pins[i];
+        if (ioctl( p->fd, GPIOREAD, &req ) == -1)
+            return -1;
+        if (req.gp_value == GPIO_PIN_HIGH)
+            d |= mask;
+    }
+    p->stat = d;
+
+    return d;
+}
+
+static int
+gpio_set_control (urj_parport_t *parport, unsigned char data)
+{
+    gpio_params_t *p = parport->params;
+    struct gpio_req req;
+    unsigned char changed, mask;
+    int i;
+    int pins[4] = { 0, 13, 15, 16 };
+
+    memset(&req, 0, sizeof(req));
+
+    if ((changed = data ^ p->ctrl)) {
+        for (mask = 1, i = 0; i < 4; mask <<= 1, i++) {
+            if ((changed & mask) != 0) {
+                req.gp_pin = pins[i];
+                req.gp_value = (data & mask) ? GPIO_PIN_HIGH : GPIO_PIN_LOW;
+                if (ioctl( p->fd, GPIOWRITE, &req ) == -1)
+                    return URJ_STATUS_FAIL;
+            }
+        }
+        p->ctrl = data;
+    }
+
+    return URJ_STATUS_OK;
+}
+
+const urj_parport_driver_t urj_tap_parport_gpio_parport_driver = {
+    URJ_CABLE_PARPORT_DEV_GPIO,
+    gpio_connect,
+    gpio_parport_free,
+    gpio_open,
+    gpio_close,
+    gpio_set_data,
+    gpio_get_data,
+    gpio_get_status,
+    gpio_set_control
+};
--- urjtag/src/tap/cable/generic_parport.c.orig 2011-11-19 20:38:06.000000000 
+0100
+++ urjtag/src/tap/cable/generic_parport.c      2011-11-19 20:41:46.000000000 
+0100
@@ -124,12 +124,18 @@
 #if HAVE_DEV_PPBUS_PPI_H
                "   or: cable %s ppi PPIDEV\n"
 #endif
+#if HAVE_SYS_GPIO_H
+               "   or: cable %s gpio GPIODEV\n"
+#endif
                "\n" "PORTADDR   parallel port address (e.g. 0x378)\n"
 #if ENABLE_LOWLEVEL_PPDEV
                "PPDEV      ppdev device (e.g. /dev/parport0)\n"
 #endif
 #if HAVE_DEV_PPBUS_PPI_H
-               "PPIDEF     ppi device (e.g. /dev/ppi0)\n"
+               "PPIDEV     ppi device (e.g. /dev/ppi0)\n"
+#endif
+#if HAVE_SYS_GPIO_H
+               "GPIODEV    gpio device (e.g. /dev/gpio0)\n"
 #endif
                "\n"),
 #if ENABLE_LOWLEVEL_PPDEV
@@ -138,5 +144,8 @@
 #if HAVE_DEV_PPBUS_PPI_H
              cablename,
 #endif
+#if HAVE_SYS_GPIO_H
+             cablename,
+#endif
              cablename);
 }
--- urjtag/src/tap/cable/wiggler.c.orig 2011-11-19 20:41:59.000000000 +0100
+++ urjtag/src/tap/cable/wiggler.c      2011-11-19 20:45:53.000000000 +0100
@@ -397,12 +397,18 @@
 #if HAVE_DEV_PPBUS_PPI_H
                "   or: cable %s ppi PPIDEV [TDO,TRST,TDI,TCK,TMS,SRESET]\n"
 #endif
+#if HAVE_SYS_GPIO_H
+               "   or: cable %s gpio GPIODEV [TDO,TRST,TDI,TCK,TMS,SRESET]\n"
+#endif
                "\n" "PORTADDR   parallel port address (e.g. 0x378)\n"
 #if ENABLE_LOWLEVEL_PPDEV
                "PPDEV      ppdev device (e.g. /dev/parport0)\n"
 #endif
 #if HAVE_DEV_PPBUS_PPI_H
-               "PPIDEF     ppi device (e.g. /dev/ppi0)\n"
+               "PPIDEV     ppi device (e.g. /dev/ppi0)\n"
+#endif
+#if HAVE_SYS_GPIO_H
+               "GPIODEV    ppi device (e.g. /dev/gpio0)\n"
 #endif
                "TDO, ...   parallel port bit number, prepend '#' for 
inversion\n"
                "           default is '%s'\n" "\n"),
@@ -412,6 +418,9 @@
 #if HAVE_DEV_PPBUS_PPI_H
              cablename,
 #endif
+#if HAVE_SYS_GPIO_H
+             cablename,
+#endif
              cablename, std_wgl_map);
 }
 
--- urjtag/src/tap/Makefile.am.orig     2011-11-19 21:15:00.000000000 +0100
+++ urjtag/src/tap/Makefile.am  2011-11-20 12:34:06.000000000 +0100
@@ -182,6 +182,11 @@
        parport/ppi.c
 endif
 
+if ENABLE_LOWLEVEL_GPIO
+libtap_la_SOURCES += \
+       parport/ppbusgpio.c
+endif
+
 if ENABLE_CABLE_EP9307
 libtap_la_SOURCES += \
        cable/vision_ep9307.c
--- urjtag/src/tap/parport.c.orig       2011-11-19 20:35:57.000000000 +0100
+++ urjtag/src/tap/parport.c    2011-11-19 20:36:39.000000000 +0100
@@ -81,6 +81,7 @@
     case URJ_CABLE_PARPORT_DEV_PARALLEL: return "parallel";
     case URJ_CABLE_PARPORT_DEV_PPDEV:    return "ppdev";
     case URJ_CABLE_PARPORT_DEV_PPI:      return "ppi";
+    case URJ_CABLE_PARPORT_DEV_GPIO:     return "gpio";
     case URJ_CABLE_PARPORT_N_DEVS:       return "#devs";
     }
     return "<unknown parport devtype>";
--- urjtag/src/tap/parport_list.h.orig  2011-11-19 20:36:01.000000000 +0100
+++ urjtag/src/tap/parport_list.h       2011-11-20 12:53:17.000000000 +0100
@@ -34,4 +34,8 @@
 _URJ_LIST(ppi_parport)
 #endif
 
+#ifdef ENABLE_LOWLEVEL_GPIO
+_URJ_LIST(gpio_parport)
+#endif
+
 #undef _URJ_LIST
--- urjtag/src/tap/detect.c.orig        2011-11-20 12:45:49.000000000 +0100
+++ urjtag/src/tap/detect.c     2011-11-20 12:47:07.000000000 +0100
@@ -86,14 +86,14 @@
         p = line;
 
         /* skip whitespace */
-        while (*p && isspace (*p))
+        while (*p && isspace ((unsigned char)*p))
             p++;
 
         /* remove ending whitespace */
         s = strchr (p, '\0');
         while (s != p)
         {
-            if (!isspace (*--s))
+            if (!isspace ((unsigned char)*--s))
                 break;
             *s = '\0';
         }
@@ -104,7 +104,7 @@
 
         /* find end of field */
         s = p;
-        while (*s && !isspace (*s))
+        while (*s && !isspace ((unsigned char)*s))
             s++;
         if (*s)
             *s++ = '\0';
@@ -122,7 +122,7 @@
         p = s;
 
         /* skip whitespace */
-        while (*p && isspace (*p))
+        while (*p && isspace ((unsigned char)*p))
             p++;
 
         /* line is empty? */
@@ -131,7 +131,7 @@
 
         /* find end of field */
         s = p;
-        while (*s && !isspace (*s))
+        while (*s && !isspace ((unsigned char)*s))
             s++;
         if (*s)
             *s++ = '\0';
@@ -143,7 +143,7 @@
         p = s;
 
         /* skip whitespace */
-        while (*p && isspace (*p))
+        while (*p && isspace ((unsigned char)*p))
             p++;
 
         /* line is empty? */
--- urjtag/src/bsdl/vhdl_flex.l.orig    2011-11-20 13:10:13.000000000 +0100
+++ urjtag/src/bsdl/vhdl_flex.l 2011-11-20 13:10:47.000000000 +0100
@@ -503,8 +503,8 @@
     s = filename;
     while (*s)
     {
-        if (islower (*s))
-            *s = toupper (*s);
+        if (islower ((unsigned char)*s))
+            *s = toupper ((unsigned char)*s);
         s++;
     }
 
--- urjtag/src/svf/svf_flex.l.orig      2011-11-20 13:00:03.000000000 +0100
+++ urjtag/src/svf/svf_flex.l   2011-11-20 13:00:14.000000000 +0100
@@ -350,7 +350,7 @@
 
     for (dst = src; *src; src++)
     {
-        if (isxdigit (*src))
+        if (isxdigit ((unsigned char)*src))
            *dst++ = *src;
     }
     *dst = '\0';
--- urjtag/src/global/parse.c.orig      2011-11-20 12:58:25.000000000 +0100
+++ urjtag/src/global/parse.c   2011-11-20 12:58:42.000000000 +0100
@@ -77,7 +77,7 @@
     while (1)
     {
         /* eat up leading spaces */
-        while (isspace (*c))
+        while (isspace ((unsigned char)*c))
             c++;
 
         /* if the command ends here (either by NUL or comment) */
@@ -85,7 +85,7 @@
             break;
 
         /* copy the meat (non-space, non-NUL), consider escape and quotes */
-        while ((!isspace (*c)
+        while ((!isspace ((unsigned char)*c)
                 || escape
                 || quote_single
                 || quote_double) && *c != '\0')
--- urjtag/src/cmd/cmd_cmd.c.orig       2011-11-20 12:57:15.000000000 +0100
+++ urjtag/src/cmd/cmd_cmd.c    2011-11-20 12:57:44.000000000 +0100
@@ -173,7 +173,7 @@
     size_t token_point = 0;
 
     /* Skip all leading whitespace first to make 2nd loop easier */
-    while (isspace (*cs))
+    while (isspace ((unsigned char)*cs))
         ++cs;
 
     while (*cs)
@@ -183,10 +183,10 @@
 
         ++cs;
 
-        if (isspace (*cs))
+        if (isspace ((unsigned char)*cs))
         {
             ++token_point;
-            while (isspace (*cs))
+            while (isspace ((unsigned char)*cs))
                 ++cs;
         }
     }
------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure 
contains a definitive record of customers, application performance, 
security threats, fraudulent activity, and more. Splunk takes this 
data and makes sense of it. IT sense. And common sense.
http://p.sf.net/sfu/splunk-novd2d
_______________________________________________
UrJTAG-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/urjtag-development

Reply via email to