Velleman K8000 & Linux HOWTO: the programs

## 3. the programs

## 3.1 check-i2c.c

This small C-program checks all addresses from 0 to 127 if there are reacheable i2c-chips connected to your parallel port. Before you start this program, you should compile and link it by typing make all and load all i2c kernel modules with the above described script named "velle"

> `

>     /*
>     **   $Id: check-i2c.c,v 0.01
>     **
>     **   File:     check-i2c.c
>     **   Author:   Heimo Schoen / heimo.schoen@gmx.at
>     **
>     **   Abstract: Routine for testing the Kerneldriver
>     **             ../driver/char/i2cv-elleman.c
>     **
>     #
>     # Copyright (C) 2001,2002 by Heimo Schön  <heimo.schoen@gmx.at>
>     #
>     # 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, BUT NOT (!!!)
>     # 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., 675 Mass Ave, Cambridge, MA 02139, USA.
>     #
>     */

>     # include <errno.h>
>     # include <stdio.h>
>     # include <signal.h>
>     # include <stdarg.h>
>     # include <time.h>

>     #include <stdlib.h>
>     #include <sys/types.h>
>     #include <sys/stat.h>
>     #include <sys/ioctl.h>
>     #include <fcntl.h>
>     #include <linux/i2c.h>
>     #include <linux/i2c-dev.h>
>     #include <unistd.h>

>     int main(int argc, char *argv[])
>     {
>       int fh   = 0;
>       unsigned int port = 0;
>       int res;
>       char devicename[100] = "/dev/velleman";

>       if (argc == 2)
>         sprintf(devicename, "%s", argv[1]);

>       fh  = open(devicename, O_RDWR);

>       if (fh < 3) {

>         printf("\n");
>         printf("check-i2c had a problem opening %s\n", devicename);
>         printf("\n");
>         printf("  please execute script velle included in the package check-i2c\n");
>         printf("\n");
>         printf("  You should have a file /dev/velleman generated with the command\n");
>         printf("     mknod /dev/velleman c 89 0\n");
>         printf("\n");
>         printf("  You also should have loaded i2c-velleman i2c-dev i2c-core and i2c-algo-bit\n");
>         printf("  into your kernel. See script velle for details how to do this\n");
>         printf("\n");
>         printf("usage of check-i2c:\n");
>         printf("\n");
>         printf("    check-i2c [devicename]\n");
>         printf("\n");
>         printf("    if parameter devicename is not given, check-i2c will try to open\n");
>         printf("    /dev/velleman.\n");
>         printf("\n");
>         printf("(c) 2001,2002 by Heimo Schön / heimo.schoen@gmx.at / http://schoen.priv.at\n");
>         printf("\n");
>         printf("       have a lot fun ...\n");
>         printf("\n");

>         exit (1);

>       } else {

>         printf("\n");
>         printf("check-i2c will search now on %s for reachable i2c-devices and will show you the addresses:\n", devicename);
>         printf("\n");

>         // Loop across all available 7-Bit addresses
>         for (port=0; port<=127; port++) {

>           // Try to ioctl this device-address
>           if (ioctl(fh, I2C_SLAVE, port) < 0)
>             perror ("IOCTL Problem");

>           /* Using SMBus commands */
>           res = i2c_smbus_write_byte(fh, 0x00);
>           if (res >= 0)
>             printf("found i2c-chip at     i2c-address: 0x%02x (%d)      (real-address: 0x%02x)\n",
>                    port, port, port*2);

>           //usleep(1000);

>         } // loop port=0-127

>         printf("\n");
>         printf("NOTE:\n");
>         printf("the i2c-drivers in the kernel use a 7-bit adress.\n");
>         printf("E.g. if you want to write to a PCF8574A at the adress 0x70\n");
>         printf("than you have to divide 0x70 by two. This is 0x38, which is the\n");
>         printf("address for the kernel-drivers.\n");
>         printf("With other words, the kernel-driver is shifting your adress (0x38)\n");
>         printf("one byte left an adds 0 if you write ore 1 if you read from the\n");
>         printf("address.\n");
>         printf("I know, this is a little bit complecated ;-) But this is also the\n");
>         printf("reason why I wrote this small program\n");
>         printf("\n");
>         printf("      have a lot of fun ...\n");
>         printf("\n");

>         exit (0);
>       }
>     }

> `

You can download this program with the Makefile here

## 3.2 velleman.c

velleman.c is doing some test with digital-output on your velleman K8000. This program is expecting that you have a K8000 connected to your /dev/lp0 and that all i2c drivers are loaded as described before. It switches all outputs on and off. There is a small help available (just read the source ;-)

> `

>     /*
>     **   $Id: velleman.c,v 0.01
>     **
>     **   File:     velleman.c
>     **   Author:   Heimo Schoen / heimo.schoen@gmx.at
>     **
>     **   Abstract: Routine for testing the Kerneldriver
>     **             ../driver/char/i2cv-elleman.c
>     **
>     #
>     # Copyright (C) 2001,2002 by Heimo Schön  <heimo.schoen@gmx.at>
>     #
>     # 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
>     #
>     */

>     # include <errno.h>
>     # include <stdio.h>
>     # include <signal.h>
>     # include <stdarg.h>
>     # include <time.h>

>     # include <sys/types.h>
>     # include <sys/time.h>
>     # include <sys/socket.h>

>     #include <stdlib.h>
>     #include <sys/types.h>
>     #include <sys/stat.h>
>     #include <sys/ioctl.h>
>     #include <fcntl.h>
>     #include <linux/i2c.h>
>     #include <linux/i2c-dev.h>
>     #include <unistd.h>

>     // ----------------------------------------------------------
>     int p_i2c_write(unsigned int  vf_fh,
>                     unsigned int  vf_port,
>                     unsigned char vf_data)
>     {
>       int vp_res;

>       if (ioctl(vf_fh,I2C_SLAVE,vf_port))
>         perror ("IOCTL Problem");
>       vp_res = i2c_smbus_write_byte(vf_fh, ~vf_data);
>       if (vp_res < 0)
>         perror("i2c_smbus_write_byte");
>       return (vp_res);
>     }

>     // ----------------------------------------------------------
>     int p_write(unsigned int  vf_fh,
>                 unsigned int  vf_port,
>                 unsigned char vf_data)
>     {
>       int vp_res;
>       unsigned char vp_buf[10];

>       if (ioctl(vf_fh,I2C_SLAVE,vf_port))
>         perror ("IOCTL Problem");
>       vp_buf[0] = ~vf_data;
>       vp_res = write(vf_fh, vp_buf, 1);
>       return (vp_res);
>     }

>     // ----------------------------------------------------------
>     int main(int argc, char *argv[])
>     {
>       int fh  = 0;
>       int res;
>       int i;
>       unsigned int port1 = 0x38;
>       unsigned int port2 = 0x39;
>       unsigned char buf[10];
>       char devicename[100] = "/dev/velleman";
>       unsigned char testmode = 0;

>       if (argc >= 2) {
>         if (strlen(argv[1]) > 1)
>           sprintf(devicename, "%s", argv[1]);
>         if (strlen(argv[1]) == 1)
>           testmode = atoi(argv[1]);
>       }

>       if (argc >= 3) {
>         if (strlen(argv[2]) > 1)
>           sprintf(devicename, "%s", argv[2]);
>         if (strlen(argv[2]) == 1)
>           testmode = atoi(argv[2]);
>       }

>       fh  = open(devicename, O_RDWR);

>       if (fh < 3) {

>         printf("\n");
>         printf("velleman had a problem opening %s\n", devicename);
>         printf("\n");
>         printf("  please execute script velle included in the package velleman\n");
>         printf("\n");
>         printf("  You should have a file /dev/velleman generated with the command\n");
>         printf("     mknod /dev/velleman c 89 0\n");
>         printf("\n");
>         printf("  You also should have loaded i2c-velleman i2c-dev i2c-core and i2c-algo-bit\n");
>         printf("  into your kernel. See script velle for details how to do this\n");
>         printf("\n");
>         printf("usage of velleman:\n");
>         printf("\n");
>         printf("    velleman [devicename] [test]\n");
>         printf("\n");
>         printf("    if parameter devicename is not given, velleman will try to open\n");
>         printf("    /dev/velleman.\n");
>         printf("\n");
>         printf("    parameter [test] has to be numeric and tells which testnumber you want\n");
>         printf("    If Parameter [test] is not found, velleman will only check the PCF8574A if present\n");
>         printf("\n");
>         printf("example:  velleman /dev/i2c-0 2\n");
>         printf("\n");
>         printf("(c) 2001,2002 by Heimo Schön / heimo.schoen@gmx.at / http://schoen.priv.at\n");
>         printf("\n");
>         printf("       have a lot fun ...\n");
>         printf("\n");

>         exit (1);

>       } else {

>         // checking if we can find the two PCF5874A

>         if (ioctl(fh,I2C_SLAVE,port1) < 0)
>           perror ("IOCTL Problem");
>         res = i2c_smbus_write_byte(fh, 0x00);
>         if (res >= 0)
>           printf("found i2c-chip at     i2c-address: 0x%02x (%d)      (real-address: 0x%02x)\n",
>                  port1, port1, port1*2);

>         if (ioctl(fh,I2C_SLAVE,port2) < 0)
>           perror ("IOCTL Problem");
>         res = i2c_smbus_write_byte(fh, 0x00);
>         if (res >= 0)
>           printf("found i2c-chip at     i2c-address: 0x%02x (%d)      (real-address: 0x%02x)\n",
>                  port2, port2, port2*2);

>         sleep(1);

>         if (testmode == 1) {
>           printf("Starting testmode 1 : Counter    (stop test with CTRL-C)\n");
>           while (1) {
>             /* Using SMBus commands */
>             for (i=0; i<=0xff; i++) {
>               p_i2c_write(fh, port1, i);
>               p_i2c_write(fh, port2, i);

>               usleep(5);
>             }
>           }
>         }

>         if (testmode == 2) {
>           printf("Starting testmode 2 : Knightrider    (stop test with CTRL-C)\n");
>           while (1) {
>             for (i=1; i<=15; i++) {

>               if (i<=7) {
>                 p_write(fh, port1, 1<<i);
>                 p_write(fh, port2, 0);
>               } else {
>                 p_write(fh, port2, 1<<(i-8));
>                 p_write(fh, port1, 0);
>               }
>               usleep(1);
>             }
>             for (i=14; i>=0; i--) {

>               if (i<=7) {
>                 p_write(fh, port1, 1<<i);
>                 p_write(fh, port2, 0);
>               } else {
>                 p_write(fh, port2, 1<<(i-8));
>                 p_write(fh, port1, 0);
>               }
>               usleep(1);
>             }
>           }
>         }

>     /*     ioctl(fh,I2C_UDELAY,5); */
>     /*     ioctl(fh,I2C_MDELAY, 2); */
>     /*     ioctl(fh,I2C_RETRIES,3); */

>         if (ioctl(fh,I2C_SLAVE,port1) /* ioctl(fh, I2C_SLAVE, port1) */ < 0)
>           perror ("IOCTL Problem");

>         errno = 0;
>         res = ~ i2c_smbus_read_byte(fh);
>         if (errno != 0)
>           perror("i2c_smbus_read_byte");
>         else
>           printf("i2c_smbus_read_byte: 0x%02x\n",
>                  res);

>         sleep(1);

>         /* Using I2C Read, equivalent of i2c_smbus_read_byte(file) */
>         res = read(fh,buf,1);
>         if ( res == 1)
>           printf("POSIX-Read: %d bytes buf[0]=0x%02x\n",
>                  res, ~ buf[0]);

>       }

>       return 0;
>     }

> `

You can download this program with the Makefile here

## 3.3 Makefile

Last but not least, the Makefile to the above two sources

> `

>     #
>     # Makefile for the velleman testprogram
>     #
>     # Copyright (C) 2001,2002 Heimo Schön <heimo.schoen@telecom.at>
>     #
>     # 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
>     #

>                CFLAGS        =  -pedantic -Wall -O -g

>                LDOPTIONS     = -g -DYY_SKIP_YYWRAP
>                RM            = rm -f
>                CP            = cp -v
>                STRIP         = strip --verbose

>                VELLEMANSRCS = velleman.c
>                VELLEMANOBJS = $(patsubst %.c,%.o,$(VELLEMANSRCS))
>                CHECKSRCS    = check-i2c.c
>                CHECKOBJS    = $(patsubst %.c,%.o,$(CHECKSRCS))

>     all:: velleman check-i2c

>     tags:
>             etags *.[hc]

>     velleman:  $(VELLEMANOBJS) $(DEPLIBS)
>             $(RM) $@
>             $(CC) -o $@ $(VELLEMANOBJS) $(LDOPTIONS) -O0 -g -L/usr/lib/termcap -lreadline -lhistory -ltermcap

>     check-i2c:  $(CHECKOBJS) $(DEPLIBS)
>             $(RM) $@
>             $(CC) -o $@ $(CHECKOBJS) $(LDOPTIONS) -O0 -g -L/usr/lib/termcap -lreadline -lhistory -ltermcap

>     clean::
>             $(RM) velleman check-i2c *.o *~

>     depend::
>             @if [ -n "$(VELLEMANSRCS)" ] ; then set -x;\
>               $(DEPEND) $(DEPENDFLAGS) $(VELLEMANSRCS);\
>             fi
>             @if [ -n "$(CHECKSRCS)" ] ; then set -x;\
>               $(DEPEND) $(DEPENDFLAGS) $(CHECKSRCS);\
>             fi

> `

## 3.4 notes

If you dont want to use the kernel-drivers, you find a solution for a user-space program here