diff --git a/contrib/patches/README.ppdev b/contrib/patches/README.ppdev new file mode 100644 index 0000000..032d73e --- /dev/null +++ b/contrib/patches/README.ppdev @@ -0,0 +1,27 @@ +By Andréss Trapanotto : + +And then, the explanation of how it works: + +Up to now, LCDd access right to the parallel port thru io functions +(port_in, port_out, etc...). This way needs root permission and the +known of the parallel port io configuration... And this functions are +included in-line from port.h to the driver. + +I've written another set some functions (pp_init, pp_bye, +pp_write_data, etc.) in port.c that are not in-line compiled, has a new +struct pp_driver as argument allowing to pass them more parameters (now +we need to tell which port, register and data we want to use, read or +write). + +And there is something else that is a wrapper to get old functions +(port_in, port_out, etc) supported for such drivers that are not +modified to use new parallel port functions. + +So, if you have an LCD attached to your parallel port (like my hd44780) +without keys attached to it, you can apply this patch and just forget +the io access to the parallel port :) + +Well, I hope these could be useful to the project. The patch itself has +some in-line comments but ask me for any doubt. + +Best regards, Andrés! diff --git a/contrib/patches/ppdev.diff b/contrib/patches/ppdev.diff new file mode 100644 index 0000000..dbb97aa --- /dev/null +++ b/contrib/patches/ppdev.diff @@ -0,0 +1,345 @@ +--- server/drivers/port.h ++++ server/drivers/port.h 2006-03-26 19:45:58.416006888 -0300 +@@ -15,6 +15,8 @@ + * + * Access to ports over 0x3FF by Joris Robijn, 04/2003 + * ++ * ppdev support by Andrés Trapanotto 03/2006 ++ * + */ + + /* +@@ -57,10 +59,75 @@ + + #include + ++struct pp_driver ++{ ++#ifdef __linux__ ++ int fd,mode; ++#else ++ int base_addr; ++#endif ++ unsigned char data,control,status; ++} ; ++ ++/* ------------------------------------------------------------- */ ++/* Use ppdev (Linux) */ ++#if defined HAVE_PPDEV ++#include ++#include ++#include ++#include ++ ++/* Libc5 */ ++# ifdef HAVE_UNISTD_H ++# include ++# endif ++ ++extern int pp_read_data ( struct pp_driver * ); ++extern int pp_read_status ( struct pp_driver * ); ++extern int pp_read_control ( struct pp_driver * ); ++extern int pp_write_data ( struct pp_driver * ); ++extern int pp_write_status ( struct pp_driver * ); /* Obsolete */ ++extern int pp_write_control ( struct pp_driver * ); ++extern int pp_init ( struct pp_driver * , char * ); ++extern int pp_bye ( struct pp_driver * ); ++extern int pp_port ( unsigned short , unsigned char , unsigned char ); ++ ++/* The following 6 functions are used by the drivers that don't use ppdev natively */ ++static inline int port_in ( unsigned short port ) ++{ ++ return pp_port ( port, 0, 0); ++} ++ ++static inline void port_out ( unsigned short port, unsigned char val) ++{ ++ pp_port ( port, 1, val); ++ return; ++} ++ ++static inline int port_access ( unsigned short port ) ++{ ++ return pp_port ( port, 2, 0); ++} ++ ++static inline int port_deny ( unsigned short port ) ++{ ++ return pp_port ( port, 3, 0); ++} ++ ++static inline int port_access_multiple ( unsigned short port, int val) ++{ ++ return pp_port ( port, 2, 0); ++} ++ ++static inline int port_deny_multiple ( unsigned short port, int val) ++{ ++ return pp_port ( port, 3, 0); ++} ++ + /* ------------------------------------------------------------- */ + /* Use ioperm, inb and outb in (Linux) */ + /* And iopl for higher addresses of PCI LPT cards */ +-#if defined HAVE_IOPERM ++#elif defined HAVE_IOPERM + + /* Glibc2 and Glibc1 */ + # ifdef HAVE_SYS_IO_H +--- server/drivers/port.c ++++ server/drivers/port.c 2006-03-26 19:45:58.416006888 -0300 +@@ -0,0 +1,254 @@ ++/* $id$ ++ * Low level ppdev based I/O functions ++ * ++ * This file is released under the GPL. See file COPYING in this ++ * package for further details. ++ * ++ * ppdev support by Andrés Trapanotto 03/2005 ++ */ ++ ++/* ++This file defines 8 functions for port I/O (2 obsolete ones): ++ ++int pp_read_data ( struct pp_driver * driver ); -- NOT IMPLEMENTED -- ++ Read a byte from data port ++ Returns 0 if successful, -1 if failed ++ ++int pp_read_status ( struct pp_driver * driver ); ++ Read a byte from status port ++ Returns 0 if successful, -1 if failed ++ ++int pp_read_control ( struct pp_driver * driver ); ++ Read a byte from control port ++ Returns 0 if successful, -1 if failed ++ ++int pp_write_data ( struct pp_driver * driver ); ++ Write a byte to data port ++ Returns 0 if successful, -1 if failed ++ ++int pp_write_status ( struct pp_driver * driver ); -- Obsolete -- ++ Write a byte to status port ++ Returns 0 if successful, -1 if failed ++ ++int pp_write_control ( struct pp_driver * driver ); ++ Write a byte to control port ++ Returns 0 if successful, -1 if failed ++ ++int pp_init ( struct pp_driver * driver, char * device ) ++ Get access to a specific port (/dev/parport0,1,2) ++ Returns 0 if successful, -1 if failed ++ ++int pp_bye ( struct pp_driver * driver) ++ Close access to a specific port ++ Returns 0 if successful, -1 if failed ++ ++ppdev support: ++- If the drivers is writted to work with ppdev, it has to have a pp_driver where the ppdev data and descriptors will be ++ stored. I can be part of private_data :) ++ Then, the driver have to use pp_* functions to open/close/write/read the parallel port ++ ++- If the driver isn't writted to work woth ppdev, you can compile the project using USE_PPDEV and it will use ppdev ++ anyway :) ++ ++- The idea is that drivers can be modified to use ppdev, and then port_* functions can be removed. ++*/ ++ ++#include ++ ++#if defined HAVE_PPDEV ++#include ++ ++/* ++// I think that it is useless by now ++int pp_read_data ( struct pp_driver * driver) ++{ ++ return (-1); ++// return ioctl (driver->fd, PPRDATA, &(driver->data)); ++} ++*/ ++ ++int pp_read_status ( struct pp_driver * driver) ++{ ++ return ioctl (driver->fd, PPRSTATUS, &(driver->status)); ++} ++ ++int pp_read_control ( struct pp_driver * driver) ++{ ++ return ioctl (driver->fd, PPRCONTROL, &(driver->control)); ++} ++ ++int pp_write_data ( struct pp_driver * driver) ++{ ++ return ioctl (driver->fd, PPWDATA, &(driver->data)); ++} ++ ++/* ++int pp_write_status ( struct pp_driver * driver) -- Obsolete -- ++ return (-1); ++// return ioctl (driver->fd, PPWSTATUS, driver->status); ++} ++*/ ++ ++int pp_write_control ( struct pp_driver * driver) ++{ ++ return ioctl (driver->fd, PPWCONTROL, &(driver->control)); ++} ++ ++int pp_init ( struct pp_driver * driver, char * device ) ++{ ++ int retval=0,modes,dir; ++ ++ driver->fd=open (device,O_RDWR); ++ if (driver->fd<0) { ++ fprintf (stderr, "Error opening %s",device); ++ exit (-1); ++ return -1; ++ } ++ ++ retval=ioctl (driver->fd, PPCLAIM); ++ if (retval<0) { ++ fprintf (stderr, "I can't get %s",device); ++ return retval; ++ } ++ ++/* Is mandatory to set the data direction */ ++ dir=0; /* Data Forward */ ++ retval=ioctl (driver->fd, PPDATADIR, &dir); ++ if (retval<0) { ++ fprintf (stderr,"\nError setting the data direction on %s ",device); ++ close (driver->fd); ++ return (-1); ++ } ++ ++return 0; ++} ++ ++int pp_bye ( struct pp_driver * driver) ++{ ++ int retval; ++ ++ retval=ioctl (driver->fd, PPRELEASE); ++ if (retval<0) ++ fprintf (stderr,"\nI can't free the parallel port."); ++ ++ close (driver->fd); ++ ++ return retval; ++} ++ ++/* The following function is used by the drivers that don't use ppdev natively */ ++int pp_port (unsigned short port, unsigned char arg, unsigned char val ) ++{ ++ static struct pp_driver driver; ++ static int init=-1; ++ int retval=0; ++ char device[200]; ++ ++ switch (arg) { ++ case 0: // Read Port ++ case 1: // Write Port ++ case 3: // Close Parallel Port ++ if (!init){ ++ fprintf (stderr, "You must initialize the parallel port before using it!\n"); ++ exit (-1); ++ } ++ break; // Doesn't matters ++ case 2: ++ if (init>0) return 0; //Already initializated ++ break; // Doesn't matters ++ default: ++ fprintf (stderr,"HEY! Programmer! What are you doing?\n"); ++ exit (-1); ++ } ++ ++ switch (arg) { ++ case 0: // Read Parallel Port ++ switch (port&0x03) { ++ case 0x00: ++ return (-1); ++/* retval=pp_read_data (&driver); -- NOT IMPLEMENTED -- ++ if (retval<0) fprintf (stderr, "ERROR: Reading data bus.\n"); ++ retval=driver.data; ++*/ ++ break; ++ ++ case 0x01: ++ retval=pp_read_status (&driver); ++ if (retval<0) fprintf (stderr, "ERROR: Reading status lines.\n"); ++ retval=driver.status; ++ break; ++ ++ case 0x02: ++ retval=pp_read_control (&driver); ++ if (retval<0) fprintf (stderr, "ERROR: Reading control lines.\n"); ++ retval=driver.control; ++ break; ++ default: ++ fprintf (stderr,"HEY! Programmer! ¿What are you doing?\n"); ++ exit (-1); ++ } ++ break; ++ ++ case 1: // Write Parallel Port ++ switch (port&0x03) { ++ case 0x00: ++ driver.data=val; ++ retval=pp_write_data (&driver); ++ if (retval<0) fprintf (stderr, "ERROR: Writing data bus.\n"); ++ break; ++ ++ case 0x01: ++ return (-1); ++/* driver.status=val; -- Obsolete -- ++ retval=pp_write_status (&driver); ++ if (retval<0) fprintf (stderr, "ERROR: Writing status lines.\n"); ++*/ ++ break; ++ ++ case 0x02: ++ driver.control=val; ++ retval=pp_write_control (&driver); ++ if (retval<0) fprintf (stderr, "ERROR: Writing control lines.\n"); ++ break; ++ default: ++ fprintf (stderr,"HEY! Programmer! ¿What are you doing?\n"); ++ exit (-1); ++ } ++ break; ++ ++ case 2: // Init Parallel Port ++ // It's possible to add a selection of which parallel port you want ++ // to use but is easier to implement use of pp_* in your driver and ++ // select the parallel port there. :) ++ ++/* Sick code... ++ switch (port) { ++ case 0x378: ++ strcpy (device, "/dev/parport0"); ++ break; ++ case 0x278: ++ strcpy (device, "/dev/parport1"); ++ break; ++ case 0x3BC: ++ strcpy (device, "/dev/parport2"); ++ break; ++ default: ++ strcpy (device, "/dev/parport0"); ++ } ++*/ ++ strcpy (device, "/dev/parport0"); ++ retval=pp_init (&driver, device); ++ if (retval==0) init=1; ++ break; ++ ++ case 3: // Close Parallel Port ++ retval=pp_bye (&driver); ++ if (retval==0) init=-1; ++ break; ++ } ++ ++ return retval; ++} ++ ++#endif /* HAVE_PPDEV */ ++