add ppdev patches by Andrés Trapanotto

This commit is contained in:
marschap
2006-03-27 15:10:48 +00:00
parent cbfbebbef7
commit 9f9150e914
2 changed files with 372 additions and 0 deletions
+27
View File
@@ -0,0 +1,27 @@
By Andréss Trapanotto <mail@andrestrapanotto.com.ar>:
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!
+345
View File
@@ -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 <stdio.h>
+struct pp_driver
+{
+#ifdef __linux__
+ int fd,mode;
+#else
+ int base_addr;
+#endif
+ unsigned char data,control,status;
+} ;
+
+/* ------------------------------------------------------------- */
+/* Use ppdev <linux/ppdev.h> (Linux) */
+#if defined HAVE_PPDEV
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/parport.h>
+#include <linux/ppdev.h>
+
+/* Libc5 */
+# ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# 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 <sys/io.h> (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 <port.h>
+
+#if defined HAVE_PPDEV
+#include <string.h>
+
+/*
+// 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 */
+