graphlcd-base/glcddrivers/port.c
author test@rika
Mon, 30 Mar 2009 18:40:54 +0200
changeset 29 2723893dc865
parent 21 f1573dd6dace
child 30 7fd00015f62f
permissions -rw-r--r--
fixed segfault, port initialization
     1 /*
     2  * GraphLCD driver library
     3  *
     4  * port.c  -  parallel port class with low level routines
     5  *
     6  * This file is released under the GNU General Public License. Refer
     7  * to the COPYING file distributed with this package.
     8  *
     9  * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
    10  */
    11 
    12 #include <errno.h>
    13 #include <fcntl.h>
    14 #include <stdio.h>
    15 #include <string.h>
    16 #include <syslog.h>
    17 #include <unistd.h>
    18 #include <termios.h>
    19 #include <signal.h>
    20 #include <sys/io.h>
    21 #include <sys/ioctl.h>
    22 #include <linux/ppdev.h>
    23 #include <linux/parport.h>
    24 
    25 
    26 
    27 #include "port.h"
    28 
    29 
    30 
    31 
    32 namespace GLCD
    33 {
    34 
    35 static inline int port_in(int port)
    36 {
    37     unsigned char value;
    38     __asm__ volatile ("inb %1,%0"
    39                       : "=a" (value)
    40                       : "d" ((unsigned short) port));
    41     return value;
    42 }
    43 
    44 static inline void port_out(unsigned short int port, unsigned char val)
    45 {
    46     __asm__ volatile ("outb %0,%1\n"
    47                       :
    48                       : "a" (val), "d" (port));
    49 }
    50 
    51 cParallelPort::cParallelPort()
    52 :   fd(-1),
    53     port(0),
    54     usePPDev(false)
    55 {
    56 }
    57 
    58 cParallelPort::~cParallelPort()
    59 {
    60 }
    61 
    62 int cParallelPort::Open(int portIO)
    63 {
    64     usePPDev = false;
    65     port = portIO;
    66 
    67     if (port < 0x400)
    68     {
    69         if (ioperm(port, 3, 255) == -1)
    70         {
    71             syslog(LOG_ERR, "glcd drivers: ERROR ioperm(0x%X) failed! Err:%s (cParallelPort::Open)\n",
    72                    port, strerror(errno));
    73             return -1;
    74         }
    75     }
    76     else
    77     {
    78         if (iopl(3) == -1)
    79         {
    80             syslog(LOG_ERR, "glcd drivers: ERROR iopl failed! Err:%s (cParallelPort::Init)\n",
    81                    strerror(errno));
    82             return -1;
    83         }
    84     }
    85     return 0;
    86 }
    87 
    88 int cParallelPort::Open(const char * device)
    89 {
    90     usePPDev = true;
    91 
    92     fd = open(device, O_RDWR);
    93     if (fd == -1)
    94     {
    95         syslog(LOG_ERR, "glcd drivers: ERROR cannot open %s. Err:%s (cParallelPort::Init)\n",
    96                device, strerror(errno));
    97         return -1;
    98     }
    99 
   100     if (ioctl(fd, PPCLAIM, NULL) == -1)
   101     {
   102         syslog(LOG_ERR, "glcd drivers: ERROR cannot claim %s. Err:%s (cParallelPort::Init)\n",
   103                device, strerror(errno));
   104         close(fd);
   105         return -1;
   106     }
   107 
   108     int mode = PARPORT_MODE_PCSPP;
   109     if (ioctl(fd, PPSETMODE, &mode) == -1)
   110     {
   111         syslog(LOG_ERR, "glcd drivers: ERROR cannot setmode %s. Err:%s (cParallelPort::Init)\n",
   112                device, strerror(errno));
   113         close(fd);
   114         return -1;
   115     }
   116 
   117     return 0;
   118 }
   119 
   120 int cParallelPort::Close()
   121 {
   122     if (usePPDev)
   123     {
   124         if (fd != -1)
   125         {
   126             ioctl(fd, PPRELEASE);
   127             close(fd);
   128             fd = -1;
   129         }
   130         else
   131         {
   132             return -1;
   133         }
   134     }
   135     else
   136     {
   137         if (port < 0x400)
   138         {
   139             if (ioperm(port, 3, 0) == -1)
   140             {
   141                 return -1;
   142             }
   143         }
   144         else
   145         {
   146             if (iopl(0) == -1)
   147             {
   148                 return -1;
   149             }
   150         }
   151     }
   152     return 0;
   153 }
   154 
   155 void cParallelPort::Claim()
   156 {
   157     if (usePPDev)
   158         ioctl(fd, PPCLAIM);
   159 }
   160 
   161 void cParallelPort::Release()
   162 {
   163     if (usePPDev)
   164         ioctl(fd, PPRELEASE);
   165 }
   166 
   167 void cParallelPort::SetDirection(int direction)
   168 {
   169     if (usePPDev)
   170     {
   171         if (ioctl(fd, PPDATADIR, &direction) == -1)
   172         {
   173             perror("ioctl(PPDATADIR)");
   174             //exit(1);
   175         }
   176     }
   177     else
   178     {
   179         if (direction == kForward)
   180             port_out(port + 2, port_in(port + 2) & 0xdf);
   181         else
   182             port_out(port + 2, port_in(port + 2) | 0x20);
   183     }
   184 }
   185 
   186 unsigned char cParallelPort::ReadControl()
   187 {
   188     unsigned char value;
   189 
   190     if (usePPDev)
   191     {
   192         if (ioctl(fd, PPRCONTROL, &value) == -1)
   193         {
   194             perror("ioctl(PPRCONTROL)");
   195             //exit(1);
   196         }
   197     }
   198     else
   199     {
   200         value = port_in(port + 2);
   201     }
   202 
   203     return value;
   204 }
   205 
   206 void cParallelPort::WriteControl(unsigned char value)
   207 {
   208     if (usePPDev)
   209     {
   210         if (ioctl(fd, PPWCONTROL, &value) == -1)
   211         {
   212             perror("ioctl(PPWCONTROL)");
   213             //exit(1);
   214         }
   215     }
   216     else
   217     {
   218         port_out(port + 2, value);
   219     }
   220 }
   221 
   222 unsigned char cParallelPort::ReadStatus()
   223 {
   224     unsigned char value;
   225 
   226     if (usePPDev)
   227     {
   228         if (ioctl(fd, PPRSTATUS, &value) == -1)
   229         {
   230             perror("ioctl(PPRSTATUS)");
   231             //exit(1);
   232         }
   233     }
   234     else
   235     {
   236         value = port_in(port + 1);
   237     }
   238 
   239     return value;
   240 }
   241 
   242 unsigned char cParallelPort::ReadData()
   243 {
   244     unsigned char data;
   245 
   246     if (usePPDev)
   247     {
   248         if (ioctl(fd, PPRDATA, &data) == -1)
   249         {
   250             perror("ioctl(PPRDATA)");
   251             //exit(1);
   252         }
   253     }
   254     else
   255     {
   256         data = port_in(port);
   257     }
   258 
   259     return data;
   260 }
   261 
   262 void cParallelPort::WriteData(unsigned char data)
   263 {
   264     if (usePPDev)
   265     {
   266         if (ioctl(fd, PPWDATA, &data) == -1)
   267         {
   268             perror("ioctl(PPWDATA)");
   269             //exit(1);
   270         }
   271     }
   272     else
   273     {
   274         port_out(port, data);
   275     }
   276 }
   277 
   278 
   279 
   280 cSerialPort::cSerialPort()
   281 :   fd(-1)
   282 {
   283 }
   284 
   285 cSerialPort::~cSerialPort()
   286 {
   287 }
   288 
   289 int cSerialPort::Open(const char * device, void (*FP)(int))
   290 {
   291     struct sigaction saio;
   292 
   293     if (FP == NULL) {
   294         return -1;
   295     }
   296 
   297     if (Open(device) == 0) {
   298     	// install the signal handler before making the device asynchronous/
   299     	saio.sa_handler = FP;
   300     	sigemptyset (&saio.sa_mask);
   301     	saio.sa_flags = 0;
   302     	saio.sa_restorer = NULL;
   303     	sigaction(SIGIO,&saio,NULL);
   304     
   305     	// allow the process to receive SIGIO
   306     	fcntl(fd, F_SETOWN, getpid());
   307     	// Make the file descriptor asynchronous 
   308     	fcntl(fd, F_SETFL, FASYNC | O_NONBLOCK);
   309 
   310     	return(0);
   311     }
   312     else {
   313     	return -1;
   314     }
   315 }
   316 
   317 int cSerialPort::Open(const char * device)
   318 {
   319     struct termios options;
   320 
   321     fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK);
   322     if (fd == -1)
   323     {
   324         printf("error opening port\n");
   325         return -1;
   326     }
   327 
   328     tcgetattr(fd, &options);
   329 
   330     cfsetispeed(&options, B921600);
   331     cfsetospeed(&options, B921600);
   332 
   333     options.c_cflag &= ~PARENB;
   334     options.c_cflag &= ~CSTOPB;
   335     options.c_cflag &= ~CSIZE;
   336     options.c_cflag |= CS8;
   337 
   338     options.c_cflag &= ~CRTSCTS;
   339 
   340     options.c_cflag |= (CLOCAL | CREAD);
   341 
   342     options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
   343 
   344     options.c_iflag &= ~(IXON | IXOFF | IXANY);
   345 
   346     options.c_oflag &= ~OPOST;
   347 
   348     tcsetattr(fd, TCSANOW, &options);
   349 
   350     return 0;
   351 }
   352 
   353 int cSerialPort::Close()
   354 {
   355     struct sigaction saio;
   356     if (fd == -1)
   357         return -1;
   358     close(fd);
   359     
   360     saio.sa_handler = NULL;
   361     sigemptyset (&saio.sa_mask);
   362     saio.sa_flags = 0;
   363     saio.sa_restorer = NULL;
   364     sigaction(SIGIO,&saio,NULL);
   365 
   366     return 0;
   367 }
   368 
   369 int cSerialPort::ReadData(unsigned char * data)
   370 {
   371     if (fd == -1)
   372         return 0;
   373     return read(fd, data, 1);
   374 }
   375 
   376 void cSerialPort::WriteData(unsigned char data)
   377 {
   378     WriteData(&data, 1);
   379 }
   380 
   381 void cSerialPort::WriteData(unsigned char * data, unsigned short length)
   382 {
   383     if (fd == -1)
   384         return;
   385     write(fd, data, length);
   386 //    for (int x=0; x<length; x++)   printf("0x%x ",data[x]);
   387 }
   388 
   389 
   390 } // end of namespace
   391