Before any other Parapin functions can be used, the library must be initialized. Parapin will fail ungracefully if any functions are called before its initialization. This is because the library's other functions do not check that the library is in a sane state before doing their jobs. This was an intentional design decision because the maximum possible efficiency is required in many applications that drive the parallel port at high speeds. My goal was for Parapin to be almost as fast as directly writing to registers.
The exact initialization method varies, depending on if Parapin is being used as a C library or as a kernel module.
C library initialization is performed using the function
int pin_init_user(int lp_base);whose single argument, lp_base, specifies the base I/O address of the parallel port being controlled. Common values of lp_base are 0x378 for LPT1, or 0x278 for LPT2; parapin.h defines the constants LPT1 and LPT2 to these values for convenience. However, the exact port address may vary depending on the configuration of your computer. If you're unsure, the BIOS status screen displayed while the computer boots usually shows the base addresses of all detected parallel ports.
Programs using Parapin must be running as root when they are initialized. Initialization of the library will fail if the process is owned by any user other than the super-user because Parapin has to request the right to write directly to hardware I/O registers using the ioperm function. The security-conscious programmer is encouraged to drop root privileges using setuid after a successful call to pin_init_user.
The return value of pin_init_user will be 0 if initialization is successful, or -1 if there is an error. Applications must not call other Parapin functions if initialization fails. Failed initialization is usually because the program is not running as root.
No shutdown function needs to be called in the C library version of Parapin.
Initialization and shutdown in the kernel flavor of Parapin is done using the following two functions:
int pin_init_kernel(int lpt, void (*irq_func)(int, void *, struct pt_regs *)); void pin_release();
The first function is not as intimidating as it looks. Its first argument, lpt, is the parallel port number that you want to control. The number references the kernel's table of detected parallel ports; 0 is the first parallel port and is a safe guess as a default.
The second argument, irq_func, is a pointer to a callback function to be used for servicing interrupts generated by the parallel port. This argument may be NULL if the driver does not need to handle interrupts. Details about interrupt handling are discussed in Section 9.
pin_init_kernel will return 0 on success, or a number less than 0 on error. The return value will be a standard errno value such as -ENODEV, suitable for passing up to higher layers. If Parapin initialization fails, the driver must not call Parapin's other functions. As described earlier, this requirement is not enforced for efficiency reasons.
When a driver is finished controlling the parallel port using Parapin, it must call pin_release. The state of the parallel port's interrupt-enable bit will be restored to the state it was in at the time pin_init_kernel was originally called.
Parapin's pin_init_kernel and pin_release functions work with the Linux kernel's standard parport facility; as noted above, the parport module must be loaded along with any module that uses Parapin. When initialized, Parapin will register itself as a user of the parallel port, and claim exclusive access to that port. This means no other processes will be allowed to use the parallel port until pin_release is called.