Previous Next Table of Contents

5. lp_open(struct inode * inode, struct file * file)

5.1 General info.

Function: lp_open opens a parallel device for data.

Called from: open (Base driver operation).

Files: drivers/char/lp.c, include/linux/lp.h

5.2 Code description

The parameters that lp_open takes are: inode, the inode to which the called device corresponds; and file, the file to which the called device belongs.

static int lp_open(struct inode * inode, struct file * file)
{

Again, the initial reality checks(TM). Get the minor device, check it's not out of range, check it actually exists and check it's not already busy.

        unsigned int minor = MINOR(inode->i_rdev);

        if (minor >= LP_NO)
                return -ENXIO;
        if ((LP_F(minor) & LP_EXIST) == 0)
                return -ENXIO;
        if (LP_F(minor) & LP_BUSY)
                return -EBUSY;

        MOD_INC_USE_COUNT;

Just in case the following comments aren't clear enough, the following code will bail out upon out-of-paper, off-line or any other printer error, unless the the file was opened using the O_NONBLOCK flag.

        /* If ABORTOPEN is set and the printer is offline or out of paper,
           we may still want to open it to perform ioctl()s.  Therefore we
           have commandeered O_NONBLOCK, even though it is being used in
           a non-standard manner.  This is strictly a Linux hack, and
           should most likely only ever be used by the tunelp application. */
        if ((LP_F(minor) & LP_ABORTOPEN) && !(file->f_flags & O_NONBLOCK)) {
                int status = r_str(minor);
                if (status & LP_POUTPA) {
                        printk(KERN_INFO "lp%d out of paper\n", minor);
                        MOD_DEC_USE_COUNT;
                        return -ENOSPC;
                } else if (!(status & LP_PSELECD)) {
                        printk(KERN_INFO "lp%d off-line\n", minor);
                        MOD_DEC_USE_COUNT;
                        return -EIO;
                } else if (!(status & LP_PERRORP)) {
                        printk(KERN_ERR "lp%d printer error\n", minor);
                        MOD_DEC_USE_COUNT;
                        return -EIO;
                }
        }

Allocate some memory for the buffer. If we can't get any memory, then exit with a complaint. Otherwise, set the LP_BUSY flag and return cleanly.

        lp_table[minor].lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL);
        if (!lp_table[minor].lp_buffer) {
                MOD_DEC_USE_COUNT;
                return -ENOMEM;
        }
        LP_F(minor) |= LP_BUSY;
        return 0;
}


Previous Next Table of Contents