Function: lp_open opens a parallel device for data.
Called from: open (Base driver operation).
Files: drivers/char/lp.c, include/linux/lp.h
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;
}