LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Serial / IOCTL (https://www.linuxquestions.org/questions/programming-9/serial-ioctl-221632/)

fgordon 08-24-2004 03:15 AM

Serial / IOCTL
 
Hello,

Hmm I've got a programm showing the status of my Raid-5 with a small device attached to the serial port.

Though serial support is in my kernel (when copying "garbage" to /dev/ttyS0" it "works") my program stopped working.

I'm using the RTS and DTR Lines (high and low) to signal the status of the raid with 2.4 and pre it worked without any problems but now :Pengy:


Maybe someone can help me how to set the RTS/DTR lines high and low with 2.6

Thnx :-) FGordon



This is my code doing the line switching and that worked with all kernels pre 2.6


int Ioctl(int fd, int flag, int *state)
{
int ret;
if ((ret=ioctl(fd, flag, state)) < 0) err_sys("ioctl() error");
return (ret);
}


/* Switch the LEDs on or off */
int setled(enum led whichled, int fd, int onoff, int *ledstate)
{
int bitpat;
int state;
int dummy;

if (whichled == green)
{
bitpat=TIOCM_RTS;
}
else if (whichled == red)
{
bitpat=TIOCM_DTR;
}
else bitpat=(TIOCM_RTS | TIOCM_DTR);


if (onoff) *ledstate |= bitpat;
else *ledstate &= ~bitpat;


dummy = Ioctl(fd, TIOCMSET, ledstate);
dummy = Ioctl(fd, TIOCMGET, &state);

return (*ledstate);
}

Hko 08-24-2004 06:18 AM

This is what works for me.
Works fine on 2.4 as well as 2.6 kernels.
Code:

/* Copyright (C) 2003 Heiko Noordhof <heikyAusers.sf.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h> 
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>

/* Function prototypes (belong in a seperate header file) */
int  openserial(char *devicename);
void  closeserial(void);
int  setDTR(unsigned short level);
int  setRTS(unsigned short level);


/* Two globals for use by this module only */
static int fd;
static struct termios oldterminfo;


void closeserial(void)
{
    tcsetattr(fd, TCSANOW, &oldterminfo);
    close(fd);
}


int openserial(char *devicename)
{
    struct termios attr;

    if ((fd = open(devicename, O_RDWR)) == -1) return 0; /* Error */
    atexit(closeserial);

    if (tcgetattr(fd, &oldterminfo) == -1) return 0; /* Error */
    attr = oldterminfo;
    attr.c_cflag |= CRTSCTS | CLOCAL;
    attr.c_oflag = 0;
    if (tcflush(fd, TCIOFLUSH) == -1) return 0; /* Error */
    if (tcsetattr(fd, TCSANOW, &attr) == -1) return 0; /* Error */

    /* Set the lines to a known state, and */
    /* finally return non-zero is successful. */
    return setRTS(0) && setDTR(0);
}


/* For the two functions below:
 *    level=0 to set line to LOW
 *    level=1 to set line to HIGH
 */

int setRTS(unsigned short level)
{
    int status;

    if (ioctl(fd, TIOCMGET, &status) == -1) {
          perror("setRTS(): TIOCMGET");
          return 0;
    }
    if (level) status |= TIOCM_RTS;
    else status &= ~TIOCM_RTS;
    if (ioctl(fd, TIOCMSET, &status) == -1) {
          perror("setRTS(): TIOCMSET");
          return 0;
    }
    return 1;
}


int setDTR(unsigned short level)
{
    int status;

    if (ioctl(fd, TIOCMGET, &status) == -1) {
          perror("setDTR(): TIOCMGET");
          return 0;
    }
    if (level) status |= TIOCM_DTR;
    else status &= ~TIOCM_DTR;
    if (ioctl(fd, TIOCMSET, &status) == -1) {
          perror("setDTR: TIOCMSET");
          return 0;
    }
    return 1;
}


fgordon 08-24-2004 08:51 AM

Many Thanks :-)) :-)) this does work finally :-)


All times are GMT -5. The time now is 04:33 AM.