Re: [PARPORT] Grabbing a parallel port

From: Philip Graham Willoughby (
Date: Mon Jul 14 2003 - 08:14:48 EDT

  • Next message: Tim Waugh: "Re: [PARPORT] Grabbing a parallel port"

    Hi all,

    Thank you for your many helpful replies. However, writing the parallel
    port code in userland is not an option, for the explanation, please see
    this URL:

    Since kbeat_led needs to poke the parallel port leds it must be in
    kernel space.

    Below my sig is the code I have currently, with the point-of-failure
    indicated (search for /*). I know how to write the code I want using
    direct access to the parallel port on the PC, but I wish to use the
    kernel parport stack so that it will work if I bung it on a sun too.


    Philip Willoughby

    Systems Programmer, Department of Computing, Imperial College, London, UK

    echo | tr "bizndfohces" "pwgd9ociaku"
    Why reinvent the wheel?                 Because we can make it rounder...

    #include <linux/module.h> #include <linux/kernel.h> #include <linux/parport.h> #include <linux/errno.h> #include <linux/leds.h> #include <linux/spinlock.h>

    static spinlock_t parled_lock= SPIN_LOCK_UNLOCKED; static unsigned char parled_state = 0; static int parled_parport = -1; static struct pardevice *parleds_dev;

    static void release (void) { MOD_DEC_USE_COUNT; }

    static void reserve (void) { MOD_INC_USE_COUNT; }

    static void set_state (unsigned int idx, unsigned char state) { spin_lock(&parled_lock); parled_state |= state & (1 << idx); parport_write_data (parleds_dev->port, parled_state); spin_unlock(&parled_lock); }

    static unsigned char get_state (unsigned int idx) { unsigned char reg; spin_lock(&parled_lock); reg = parled_state; spin_unlock(&parled_lock); reg &= (1 << idx); return reg; }

    static void attach (struct parport *thing) { for (parled_parport = 0 ; parled_parport < PARPORT_MAX ; ++parled_parport) { if (thing == NULL) { printk (KERN_DEBUG "parport_leds: Moo %d\n", parled_parport); continue; } if (thing->number == parled_parport) { if (thing->devices == NULL) /* It is. Why? */ { printk (KERN_DEBUG "parport_leds: Baa %d\n", parled_parport); continue; } if (!parport_claim (thing->devices) == 0) { parled_parport = -1; } else { parleds_dev = thing->devices; } return; } } parled_parport = -1; return; }

    static void detach (struct parport *thing) { }

    static struct linux_leds_info parleds = { get_state:get_state, set_state:set_state, reserve:reserve, release:release, count:2, };

    static struct parport_driver parleds_driver = { name:"parleds", attach:attach, detach:detach, };

    int __init init_parallel_leds (void) { int c; if (parport_register_driver (&parleds_driver) != 0) { printk (KERN_INFO "parport_leds: parport_register_driver failed\n"); return -EIO; } if (parled_parport < 0) { parport_unregister_driver (&parleds_driver); printk (KERN_INFO "parport_leds: couldn't claim a parallel port\n"); return -EIO; } c = leds_add (&parleds); if (c != 0) { parport_unregister_driver (&parleds_driver); printk (KERN_INFO "parport_leds: leds_add failed\n"); return -ENODEV; } return c; }

    void __exit cleanup_parallel_leds (void) { leds_del (&parleds); parport_release (parleds_dev); parport_unregister_driver (&parleds_driver); }

    module_init(init_parallel_leds); module_exit(cleanup_parallel_leds);

    MODULE_LICENSE("GPL"); MODULE_AUTHOR("Philip Graham Willoughby <>"); MODULE_DESCRIPTION("This module provides kernel control for programmable LEDs wired up to the parallel port"); MODULE_SUPPORTED_DEVICE("Parallel port LED boxes"); EXPORT_NO_SYMBOLS;

    -- To unsubscribe, send mail to: -- -- with the single word "unsubscribe" in the body of the message. --

    This archive was generated by hypermail 2b29 : Mon Jul 14 2003 - 08:24:49 EDT