graphlcd-base/glcddrivers/port.c
author cpresser@rika
Thu, 07 Feb 2008 14:28:07 +0100
changeset 21 f1573dd6dace
parent 15 cba463042186
child 29 2723893dc865
permissions -rw-r--r--
glcddrivers: reworked cSerialPort::Open. now avrctl also compiles.
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
cpresser@21
   293
    if (FP == NULL)
root@4
   294
    {
root@4
   295
        printf("error opening port\n");
root@4
   296
        return -1;
root@4
   297
    }
root@5
   298
cpresser@21
   299
    Open(device);
root@5
   300
root@5
   301
    // install the signal handler before making the device asynchronous/
root@5
   302
    saio.sa_handler = FP;
root@5
   303
    sigemptyset (&saio.sa_mask);
root@5
   304
    saio.sa_flags = 0;
root@5
   305
    saio.sa_restorer = NULL;
root@5
   306
    sigaction(SIGIO,&saio,NULL);
root@5
   307
    
root@5
   308
    // allow the process to receive SIGIO
root@5
   309
    fcntl(fd, F_SETOWN, getpid());
root@5
   310
    // Make the file descriptor asynchronous 
cpresser@15
   311
    fcntl(fd, F_SETFL, FASYNC | O_NONBLOCK);
root@4
   312
cpresser@21
   313
    return(0);
cpresser@21
   314
}
cpresser@21
   315
cpresser@21
   316
int cSerialPort::Open(const char * device)
cpresser@21
   317
{
cpresser@21
   318
    struct termios options;
cpresser@21
   319
cpresser@21
   320
    fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK);
cpresser@21
   321
    if (fd == -1)
cpresser@21
   322
    {
cpresser@21
   323
        printf("error opening port\n");
cpresser@21
   324
        return -1;
cpresser@21
   325
    }
cpresser@21
   326
root@4
   327
    tcgetattr(fd, &options);
root@4
   328
root@4
   329
    cfsetispeed(&options, B921600);
root@4
   330
    cfsetospeed(&options, B921600);
root@4
   331
root@4
   332
    options.c_cflag &= ~PARENB;
root@4
   333
    options.c_cflag &= ~CSTOPB;
root@4
   334
    options.c_cflag &= ~CSIZE;
root@4
   335
    options.c_cflag |= CS8;
root@4
   336
root@4
   337
    options.c_cflag &= ~CRTSCTS;
root@4
   338
root@4
   339
    options.c_cflag |= (CLOCAL | CREAD);
root@4
   340
root@4
   341
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
root@4
   342
root@4
   343
    options.c_iflag &= ~(IXON | IXOFF | IXANY);
root@4
   344
root@4
   345
    options.c_oflag &= ~OPOST;
root@4
   346
root@4
   347
    tcsetattr(fd, TCSANOW, &options);
root@4
   348
root@4
   349
    return 0;
root@4
   350
}
root@4
   351
root@4
   352
int cSerialPort::Close()
root@4
   353
{
root@4
   354
    if (fd == -1)
root@4
   355
        return -1;
root@4
   356
    close(fd);
root@4
   357
    return 0;
root@4
   358
}
root@4
   359
root@7
   360
int cSerialPort::ReadData(unsigned char * data)
root@4
   361
{
root@4
   362
    if (fd == -1)
root@4
   363
        return 0;
root@7
   364
    return read(fd, data, 1);
root@4
   365
}
root@4
   366
root@4
   367
void cSerialPort::WriteData(unsigned char data)
root@4
   368
{
root@4
   369
    WriteData(&data, 1);
root@4
   370
}
root@4
   371
root@4
   372
void cSerialPort::WriteData(unsigned char * data, unsigned short length)
root@4
   373
{
root@4
   374
    if (fd == -1)
root@4
   375
        return;
root@4
   376
    write(fd, data, length);
root@4
   377
}
root@4
   378
root@5
   379
root@4
   380
} // end of namespace
root@5
   381