/* This is how you get the minor device number in case you have more than one physical device using the driver. */
printk("Device: %d.%d\n", inode->i_rdev >> 8, inode->i_rdev & 0xFF);
/* We don't want to talk to two processes at the same time */
if (Device_Open) return -EBUSY;
/* If this was a process, we would have had to be
* more careful here.
*
* In the case of processes, the danger would be
* that one process might have check Device_Open
* and then be replaced by the schedualer by another
* process which runs this function. Then, when the
* first process was back on the CPU, it would assume
* the device is still not open.
*
* However, Linux guarantees that a process won't be
* replaced while it is running in kernel context.
*
* In the case of SMP, one CPU might increment
* Device_Open while another CPU is here, right after
* the check. However, in version 2.0 of the
* kernel this is not a problem because there's a lock
* to guarantee only one CPU will be kernel module at
* the same time. This is bad in terms of
* performance, so version 2.2 changed it.
* Unfortunately, I don't have access to an SMP box
* to check how it works with SMP. */
Device_Open++;
/* Initialize the message. */
sprintf(Message, "If I told you once, I told you %d times - %s", counter++, "Hello, world\n");
/* The only reason we're allowed to do this sprintf
* is because the maximum length of the message
* (assuming 32 bit integers - up to 10 digits
* with the minus sign) is less than BUF_LEN, which
* is 80. BE CAREFUL NOT TO OVERFLOW BUFFERS,
* ESPECIALLY IN THE KERNEL!!! */
Message_Ptr = Message;
/* Make sure that the module isn't removed while
* the file is open by incrementing the usage count
* (the number of opened references to the module, if
* it's not zero rmmod will fail)
*/
MOD_INC_USE_COUNT;
return SUCCESS;
}
/* This function is called when a process closes the
* device file. It doesn't have a return value in
* version 2.0.x because it can't fail (you must ALWAYS
* be able to close a device). In version 2.2.x it is
* allowed to fail - but we won't let it. */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
static int device_release(struct inode *inode, struct file *file)
#else
static void device_release(struct inode *inode, struct file *file)
#endif
{
#ifdef DEBUG
printk("device_release(%p,%p)\n", inode, file);
#endif
/* We're now ready for our next caller */
Device_Open--;
/* Decrement the usage count, otherwise once you opened the file you'll never get rid of the module. */
MOD_DEC_USE_COUNT;