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