Skip to content

Linux Code to ring the hacked doorbell


After hacking the doorbell I did some code to make it ring and flash.

I’m new to software development on Linux. Doing my work in Eclipse with CDT has been fun so far.

Probably the hardest thing for me was figuring out that my printer port card not on a standard I/O address.

Parallel ports are going away on modern PCs but they are still easy to find in PCI interface cards.

I purchased mine from Wright Hobbies a good while ago.

I did a quick look and found a lot for $10, some including 2 serial ports.

Here is my code, with comments that should explain what’s going on. The source file is available below. Let me know of any suggested improvements.

IOPortTest.c Source

. You should be able to compile this straight from the Linux shell with “gcc IOPortTest.h –o IOPortTest”

This is just test code. I plan on restructuring it into a reusable module for use in future projects. I like the idea of using a full PC for interfacing projects. Its a great development environment.



1: /*

   2:  * IOPortTest uCHobby 8.20.2010

   3:  * sets bit 0 and 1 of the Parallel port Data pins high for 10mS.

   4:  * These two bits are pins 2 and 3 on the standard DB25 connector.

   5:  *

   6:  * Two methods are shown, the first using IOCTL calls,the second

   7:  * uses direct I/O writes. To use direct writes we need to know

   8:  * the IO port addresses, I found mine by hunting through boot

   9:  * up messages.

  10:  */


  12: #include <stdlib.h>

  13: #include <stdio.h>

  14: #include <unistd.h>


  16: #include <fcntl.h>

  17: #include <sys/ioctl.h>

  18: #include <sys/io.h>

  19: #include <linux/ppdev.h>

  20: #include <linux/parport.h>


  22: void ToggleWithIOCTL(void);

  23: void ToggleWithIORaw(void);


  25: int main() {

  26:     ToggleWithIOCTL();  //Use the IOCTL driver method to toggle the pins

  27:     sleep(1);           //Sleep for one second

  28:     ToggleWithIORaw();  //This time use the raw IO methods to toggle the pins

  29:     exit(EXIT_SUCCESS);

  30: }


  32: //Use IOCTL calls to control printer port IO - Works well.

  33: void ToggleWithIOCTL (void){

  34:     int portHandle;  //Handle to reference the parallel port as a file


  36:     portHandle=open("/dev/parport0", O_RDWR);  //Open the port.

  37:     if (portHandle == -1) {  //Did the port fail to open?

  38:         perror ("open");     //Could not open, output error with an explanation

  39:     }


  41:     if (portHandle != -1) { //if the port opened OK, claim it for our purposes

  42:         if (ioctl (portHandle, PPCLAIM)) { //Were we able to claim it?

  43:             perror ("PPCLAIM");  //Cannot claim port, output an explanation

  44:             close (portHandle);  //Close the file we had

  45:             portHandle=-1;       //set the handle to show not-valid

  46:         }

  47:      }


  49:     if(portHandle != -1){  //Do we have a valid file handle?

  50:         int iTemp=0x03;  //Just need to turn on the lower two bits, D0 and D1, 

  51:                          //leave D2-D7 low. Use a temp because we have to pass 

  52:                          //by reference.

  53:         if(ioctl(portHandle, PPWDATA,&iTemp)) { //Set the port value

  54:             printf("PPWDATA"); //Write failed, output error with an explanation

  55:         }


  57:         usleep(10000);  //Sleep for 10 milliseconds, value is in microseconds.


  59:         iTemp=0x00;  //turn off all the bits D0-D7

  60:         if(ioctl(portHandle, PPWDATA,&iTemp)) {  //Set the port value

  61:             printf("PPWDATA"); //Write failed, output error with an explanation

  62:         }

  63:     }


  65:     if(ioctl(portHandle, PPRELEASE)) { //Try and release the ppdev file handle

  66:         printf("PPRELEASE");  //Did not release, output an explanation

  67:     }

  68:     close(portHandle);

  69: }


  71: #define PPDEV_BASEPORT   0xC400  //Found by hunting in boot messages near ppdev

  72: #define PPDEV_DATA    (PPDEV_BASEPORT+0)  //Define constant for the DATA port

  73: #define PPDEV_STATUS  (PPDEV_BASEPORT+1)  //Define constant for the STATUS port

  74: #define PPDEV_CONTROL (PPDEV_BASEPORT+2)  //Define constant for the CONTROL port


  76: #define TRUE  1 //These should be defined somewhere in a generic module, 

  77: #define FALSE 0 //for now I'm defining them here.


  79: //Use raw I/O method to control printer port IO

  80: void ToggleWithIORaw (void) {

  81:     int portOK=FALSE;


  83:     if(iopl(3)){            //Request permission to access IO ports using raw 

  84:                             //functions. This may not be necessary

  85:         perror("iopl");     //No permission, output error with an explanation

  86:     }

  87:     else { //We got permission

  88:       /* Get access to the ports */

  89:       if (ioperm(PPDEV_BASEPORT, 3, 1)) {  //Get permission to access the 

  90:                                            //specific ports we need.

  91:           perror("ioperm");   //No permission, output error with an explanation

  92:           exit(EXIT_FAILURE); //We are done, bad code should not exit here

  93:       }

  94:       else {

  95:           portOK=TRUE;  //We have permission and have claimed the ports we need

  96:       }

  97:     }


  99:     if (portOK) {

 100:         outb(0x03, PPDEV_DATA);  //Set the lower two bits of DATA register.

 101:         usleep(10000);           //Sleep for 10 milliseconds, in microseconds.

 102:         outb(0x00, PPDEV_DATA);  //turn off all the bits D0-D7

 103:     }


 105:     if (ioperm(PPDEV_BASEPORT, 3, 0)) {  //Release the IO ports

 106:        perror("ioperm");  //Could not release, output error with an explanation

 107:        portOK=FALSE; //We had some trouble ending port access.

 108:     }

 109: //    return(portOK);  //not returning value right now.

 110: }

Posted in Uncategorized.

One Response

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

Continuing the Discussion

  1. Ding Dong, you have mail | E-Bigg News linked to this post on September 29, 2010

    […] as a cool indication. I would have used it to ding dong when I had a new email but David decided to hook it up to a Linux box to ring whenever someone mentioned uC Hobby on IRC. Goes to show that almost anything can be made […]