How to send a bit to the parallel port on Linux (2nd part)

In this second part of how to send bits to the parallel port on Linux, i describe here basics on how to do the same on kernel space.
Here is a simple linux kernel module, that create a char device named parlport, and you can communicate directly with device using the /dev/parlport

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/unistd.h>
#include <asm/uaccess.h>
#include <linux/file.h>
#include <asm/io.h>

#define NAME “parlp”
#define VERSION “0.1”
#define LICENSE “GPL”
#define DESCPT “Simple Parallel Port LED driver”
#define AUTHOR “Mezgani Ali\n”\
“mail: mezgani [AT] nativelabs [.] org\n”\
“blog: https://securfox.wordpress.com/&#8221;

#define SUCCESS 0
#define DEVICE_NAME “parlport”
#define BASEPORT 0x0378

static int major = 61; /* major number assigned to our device driver */

static int __init start_module(void);
static void __exit clean_module(void);

static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char *, size_t, loff_t *);
static ssize_t device_write(struct file *, char *, size_t, loff_t *);

static struct file_operations fops = {
.open = device_open,
.release = device_release,
.read = device_read,
.write = device_write
};

static int
__init start_module(void)
{
int result;

result = register_chrdev(major, DEVICE_NAME, &fops);

if (result < 0) {
printk(KERN_ALERT “Registering device failed with %d\n”, major);
return result;
}

if (!(request_region(BASEPORT, 1, DEVICE_NAME))){
printk(KERN_WARNING “Winbond error request region: %X\n”, BASEPORT);
release_region(BASEPORT, 1);

return result;
}

printk(KERN_INFO “I was assigned major number %d. To talk to\n”, major);
printk(KERN_INFO “the driver, create a dev file with\n”);
printk(KERN_INFO “‘mknod /dev/%s c %d 0’.\n”, DEVICE_NAME, major);

return SUCCESS;
}

static void
__exit clean_module(void)
{
release_region(BASEPORT, 1);

unregister_chrdev(major, DEVICE_NAME);
printk(KERN_ALERT “unregister_chrdev && cleaning module\n”);

}

static int
device_open(struct inode *inode, struct file *file)
{
try_module_get(THIS_MODULE);
return SUCCESS;
}

static int
device_release(struct inode *inode, struct file *file)
{
module_put(THIS_MODULE);
return 0;
}

static ssize_t
device_read(struct file *filp, char *buffer, size_t length, loff_t * offset)
{
unsigned char pbuffer;
int len;

/* input a byte (8 bits) from a port, call inb(port), it returns the byte it got */
pbuffer = inb(BASEPORT);

len = copy_to_user(buffer, &pbuffer, 1);
if (len) return -EFAULT;

if (*offset == 0) {
*offset += 1;
return 1;
} else {
return 0;
}
}

static ssize_t
device_write(struct file *filp, char *buffer, size_t length, loff_t * offset)
{

char pbuffer, *ptr;
int len;

ptr = buffer + length – 1;
len = copy_from_user(&pbuffer, ptr, 1);
if (len) return -EFAULT;

/* output the data to parallel port */
outb(pbuffer, BASEPORT);
return 1;
}

module_init(start_module);
module_exit(clean_module);

MODULE_LICENSE(LICENSE);
MODULE_AUTHOR(AUTHOR);
MODULE_DESCRIPTION(DESCPT);
MODULE_VERSION(VERSION);

Example of use after compilation ;

# insmod parlport.ko
# mknod /dev/parlport c 61 0
# chown 666 /dev/parlport
# echo F > /dev/parlport

How to send a bit to the parallel port on Linux (2nd part)

2 thoughts on “How to send a bit to the parallel port on Linux (2nd part)

  1. Hi sir, really I don’t know how to write into my device. I put a printk in the device_write section and later i see the tail of kernel messages, and don’t log the write over the device

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s