Beispiel #1
0
int init_linedccar(bus_t busnumber, char *name)
{
    struct termios interface;
    syslog_bus(busnumber, DBG_INFO, "Try opening serial line %s \n", name);
    fd = open(name, O_RDWR);
    if (fd == -1) {
        syslog_bus(busnumber, DBG_ERROR, "Open serial line failed: %s (errno = %d).\n", strerror(errno), errno);
    }
    else {
        tcgetattr(fd, &interface);

        if (__dccar->mode == DCCAR) {		/* dc-car: 9600 bps, 8 bit, odd parity, 2 stopbits */
            interface.c_cflag = PARENB | PARODD | CSTOPB | CSIZE | CS8 | CLOCAL;
            cfsetispeed(&interface, B9600);
            cfsetospeed(&interface, B9600);
        }
        else {									/* infracar: 2400 bps, 8 Bit, no parity, 1 stopbits */
            interface.c_cflag = CSIZE | CS8 | CLOCAL;
            cfsetispeed(&interface, B2400);
            cfsetospeed(&interface, B2400);
        }

        interface.c_cc[VMIN] = 0;
        interface.c_cc[VTIME] = 1;
        tcsetattr(fd, TCSANOW, &interface);
    }
    return fd;
}
Beispiel #2
0
static int write_PCF8574(bus_t bus, int addr, uint8_t byte)
{

    int busfd = buses[bus].device.file.fd;
    int result;

    result = ioctl(busfd, I2C_SLAVE, addr);

    if (result < 0) {
        syslog_bus(bus, DBG_INFO, "Couldn't access address %d (%s)",
                   addr, strerror(errno));
        return (result);
    }

    /* ret = i2c_smbus_write_byte(busfd, byte); */

    if (result < 0) {
        syslog_bus(bus, DBG_INFO,
                   "Couldn't send byte %d to address %d (%s)", byte, addr,
                   strerror(errno));
        return (result);
    }

    syslog_bus(bus, DBG_DEBUG, "Sent byte %d to address %d", byte, addr);
    return (0);

}
Beispiel #3
0
/*
*
* Initializes the I2C-Bus and sets fd for the bus
* If bus unavailable, fd = -1
*
*/
int init_bus_I2C_DEV(bus_t i)
{

    I2CDEV_DATA *data = (I2CDEV_DATA *) buses[i].driverdata;
    int ga_hardware_inverters;
    int j, multiplexer_adr;
    int multiplex_buses;
    char buf;
    static char *protocols = "P";
    buses[i].protocols = protocols;

    syslog_bus(i, DBG_INFO, "i2c-dev init: bus #%ld, debug %d", i,
               buses[i].debuglevel);

    /* init the hardware interface */
    if (buses[i].debuglevel < 6) {
        buses[i].device.file.fd = init_lineI2C_DEV(i);
    }
    else {
        buses[i].device.file.fd = -1;
    }

    /* init software */
    ga_hardware_inverters = data->ga_hardware_inverters;
    multiplex_buses = data->multiplex_buses;

    memset(data->i2c_values, 0, sizeof(I2C_DEV_VALUES));

    if (ga_hardware_inverters == 1) {
        buf = 0xFF;
    }
    else {
        buf = 0x00;
    }

    /* preload data->i2c_values */

    if (multiplex_buses > 0) {

        for (multiplexer_adr = 1; multiplexer_adr <= multiplex_buses;
             multiplexer_adr++) {
            /* first PCF 8574 P */
            for (j = 32; j <= 39; j++) {
                data->i2c_values[j][multiplexer_adr - 1] = buf;
            }

            /* now PCF 8574 AP */
            for (j = 56; j <= 63; j++) {
                data->i2c_values[j][multiplexer_adr - 1] = buf;
            }
        }
    }

    syslog_bus(i, DBG_INFO, "i2c-dev init done");
    return 0;
}
Beispiel #4
0
/* return code wird ignoriert (vorerst) */
int init_bus_DCCAR(bus_t busnumber)
{
    static char *protocols = "MN";
    buses[busnumber].protocols = protocols;
    syslog_bus(busnumber, DBG_INFO, "DC-Car init: debug %d, device %s",
               buses[busnumber].debuglevel, buses[busnumber].device.file.path);
    buses[busnumber].device.file.fd =
        init_linedccar(busnumber, buses[busnumber].device.file.path);
    syslog_bus(busnumber, DBG_INFO, "DC-Car init done");
    return 0;
}
Beispiel #5
0
/* Uebernehme die neuen Angaben fuer die Weiche, einige wenige Pruefungen */
int enqueueGA(bus_t busnumber, int addr, int port, int action,
              long int activetime)
{
    int result;
    struct timeval akt_time;
    int number_ga = get_number_ga(busnumber);

    if ((addr > 0) && (addr <= number_ga)) {
        if (queue_isfull(busnumber)) {
            syslog_bus(busnumber, DBG_WARN, "GA Command Queue full");
            return SRCP_TEMPORARILYPROHIBITED;
        }

        result = pthread_mutex_lock(&queue_mutex[busnumber]);
        if (result != 0) {
            syslog_bus(busnumber, DBG_ERROR,
                       "pthread_mutex_lock() failed: %s (errno = %d).",
                       strerror(result), result);
        }

        queue[busnumber][in[busnumber]].protocol =
                ga[busnumber].gastate[addr].protocol;
        queue[busnumber][in[busnumber]].type =
                ga[busnumber].gastate[addr].type;
        queue[busnumber][in[busnumber]].action = action;
        queue[busnumber][in[busnumber]].port = port;
        queue[busnumber][in[busnumber]].activetime = activetime;
        gettimeofday(&akt_time, NULL);
        queue[busnumber][in[busnumber]].tv[port] = akt_time;
        queue[busnumber][in[busnumber]].id = addr;

        in[busnumber]++;
        if (in[busnumber] == QUEUELEN)
            in[busnumber] = 0;

        result = pthread_mutex_unlock(&queue_mutex[busnumber]);
        if (result != 0) {
            syslog_bus(busnumber, DBG_ERROR,
                       "pthread_mutex_unlock() failed: %s (errno = %d).",
                       strerror(result), result);
        }
        /* Restart thread to send GL command */
        resume_bus_thread(busnumber);
    }
    else {
        return SRCP_WRONGVALUE;
    }
    return SRCP_OK;
}
Beispiel #6
0
void write_command(unsigned char *command, int length, int fd, bus_t busnumber)
{
    if (!write(fd,command,length))
        syslog_bus(busnumber, DBG_ERROR, "could not send data to device");
    /* the cars need a short delay between two commands */
    usleep(__dccar->pause_between_cmd * 1000);
}
Beispiel #7
0
int init_lineI2C_DEV(bus_t bus)
{
    int fd;

    if (buses[bus].debuglevel > 0) {
        syslog_bus(bus, DBG_INFO, "Opening i2c-dev: %s",
                   buses[bus].device.file.path);
    }

    fd = open(buses[bus].device.file.path, O_RDWR);

    if (fd == -1) {
        syslog_bus(bus, DBG_ERROR, "Open device '%s' failed: %s "
                   "(errno = %d).\n", buses[bus].device.file.path,
                   strerror(errno), errno);
    }

    return fd;
}
Beispiel #8
0
static int write_i2c_dev(bus_t bus, int addr, I2C_VALUE value)
{
    /* Currently we handle only PCF8574 */
    if (((addr >= 32) && (addr < 39)) || ((addr >= 56) && (addr < 63))) {
        return (write_PCF8574(bus, addr, 0xFF & value));
    }

    syslog_bus(bus, DBG_ERROR, "Unsupported i2c device at address %d",
               addr);
    return (-1);
}
Beispiel #9
0
/* cancel network connection thread */
void cancel_netservice_thread()
{
    int result;
    void *thr_result;

    result = pthread_cancel(netservice_tid);
    if (result != 0)
        syslog_bus(0, DBG_ERROR,
                   "Netservice thread cancel failed: %s (errno = %d).",
                   strerror(result), result);

    /*wait for termination */
    result = pthread_join(netservice_tid, &thr_result);
    if (result != 0)
        syslog_bus(0, DBG_ERROR,
                   "Netservice thread join failed: %s (errno = %d).",
                   strerror(result), result);

    syslog_bus(0, DBG_INFO, "Netservice thread terminated.");
}
Beispiel #10
0
/* create network connection thread */
void create_netservice_thread()
{
    int result;
    unsigned short int port;

    port = ((SERVER_DATA *) buses[0].driverdata)->TCPPORT;

    /*TODO: search for other solution than doubled type cast */
    result = pthread_create(&netservice_tid, NULL, thr_handlePort,
                            (void *) (unsigned long int) port);

    if (result != 0) {
        syslog_bus(0, DBG_ERROR, "Create netservice thread failed: %s "
                   "(errno = %d). Terminating...\n", strerror(result),
                   result);
        exit(EXIT_FAILURE);
    }

    syslog_bus(0, DBG_INFO, "Netservice thread for port %d created.",
               port);
}
Beispiel #11
0
/*thread cleanup routine for this bus*/
static void end_bus_thread(bus_thread_t * btd)
{
    int result;

    syslog_bus(btd->bus, DBG_INFO, "DC-Car bus terminated.");
    result = pthread_mutex_destroy(&buses[btd->bus].transmit_mutex);
    if (result != 0) {
        syslog_bus(btd->bus, DBG_WARN,
                   "pthread_mutex_destroy() failed: %s (errno = %d).",
                   strerror(result), result);
    }

    result = pthread_cond_destroy(&buses[btd->bus].transmit_cond);
    if (result != 0) {
        syslog_bus(btd->bus, DBG_WARN,
                   "pthread_mutex_init() failed: %s (errno = %d).",
                   strerror(result), result);
    }

    free(buses[btd->bus].driverdata);
    free(btd);
}
Beispiel #12
0
int startup_GA(void)
{
    int result;
    unsigned int i;

    for (i = 0; i < MAX_BUSES; i++) {
        in[i] = 0;
        out[i] = 0;
        ga[i].numberOfGa = 0;
        ga[i].gastate = NULL;

        result = pthread_mutex_init(&queue_mutex[i], NULL);
        if (result != 0) {
            syslog_bus(0, DBG_ERROR,
                       "pthread_mutex_init() failed: %s (errno = %d).",
                       strerror(result), result);
        }
    }
    return 0;
}
Beispiel #13
0
int initGA(bus_t busnumber, long addr, char protocol, long type)
{
    int i = 0;
    int rc = SRCP_OK;
    int number_ga = get_number_ga(busnumber);
    syslog_bus(busnumber, DBG_INFO, "init GA: %d %c", addr, protocol);
    if ((addr > 0) && (addr <= number_ga)) {
        char msg[100];
        rc = bus_supports_protocol(busnumber, protocol);
        if (rc != SRCP_OK) {
            return rc;
        }
        ga[busnumber].gastate[addr].protocol = protocol;
        gettimeofday(&ga[busnumber].gastate[addr].inittime, NULL);
        ga[busnumber].gastate[addr].activetime = 0;
        ga[busnumber].gastate[addr].action = 0;
        ga[busnumber].gastate[addr].type = type;
        ga[busnumber].gastate[addr].id = addr;
        for (i = 0; i < MAXGAPORT; i++) {
            ga[busnumber].gastate[addr].tv[i].tv_sec = 0;
            ga[busnumber].gastate[addr].tv[i].tv_usec = 0;
        }
        if (buses[busnumber].init_ga_func != NULL)
            rc = (*buses[busnumber].init_ga_func) (&ga[busnumber].
                                                   gastate[addr]);
        if (rc == SRCP_OK) {
            ga[busnumber].gastate[addr].state = 1;
            describeGA(busnumber, addr, msg);
            enqueueInfoMessage(msg);
        }
        return rc;
    }
    else {
        return SRCP_UNSUPPORTEDDEVICE;
    }
}
Beispiel #14
0
void change_privileges()
{
    struct group *group;
    struct passwd *passwd;
    char *grp = ((SERVER_DATA *) buses[0].driverdata)->groupname;
    char *uid = ((SERVER_DATA *) buses[0].driverdata)->username;


    if (grp != NULL) {
        if ((group = getgrnam(grp)) != NULL ||
            (group = getgrgid((gid_t) atoi(grp))) != NULL) {
            if (setegid(group->gr_gid) != 0) {
                syslog_bus(0, DBG_WARN, "Could not change to group %s: %s",
                           group->gr_name, strerror(errno));
            }
            else {
                syslog_bus(0, DBG_INFO, "Changed to group %s",
                           group->gr_name);
            }
        }
        else {
            syslog_bus(0, DBG_WARN, "Could not change to group %s", grp);
        }
    }

    if (uid != NULL) {
        if ((passwd = getpwnam(uid)) != NULL ||
            (passwd = getpwuid((uid_t) atoi(uid))) != NULL) {
            if (seteuid(passwd->pw_uid) != 0) {
                syslog_bus(0, DBG_INFO, "Could not change to user %s: %s",
                           passwd->pw_name, strerror(errno));
            }
            else {
                syslog_bus(0, DBG_INFO, "Changed to user %s",
                           passwd->pw_name);
            }
        }
        else {
            syslog_bus(0, DBG_INFO, "Could not change to user %s", uid);
        }
    }
}
Beispiel #15
0
/**
 * WAIT
 */
int handleWAIT(sessionid_t sessionid, bus_t bus, char *device,
               char *parameter, char *reply, size_t length)
{
    struct timeval time;
    int rc = SRCP_UNSUPPORTEDDEVICEGROUP;
    *reply = 0x00;
    gettimeofday(&time, NULL);

    /* check, if bus has FB's */
    if (bus_has_devicegroup(bus, DG_FB)
        && strncasecmp(device, "FB", 2) == 0) {
        long int port, timeout, nelem;
        int value, waitvalue;
        nelem =
            sscanf(parameter, "%ld %d %ld", &port, &waitvalue, &timeout);
        syslog_bus(bus, DBG_INFO, "wait: %d %d %d", port, waitvalue,
                   timeout);
        if (nelem >= 3) {
            if (getFB(bus, port, &time, &value) == SRCP_OK
                && value == waitvalue) {
                rc = infoFB(bus, port, reply, length);
            }
            else {
                /* we exactly wait for 1/20 seconds */
                timeout *= 20;
                do {
                    if (usleep(50000) == -1) {
                        syslog_bus(bus, DBG_ERROR,
                                   "usleep() failed: %s (errno = %d)\n",
                                   strerror(errno), errno);
                    }
                    getFB(bus, port, &time, &value);
                    timeout--;
                }
                while ((timeout >= 0) && (value != waitvalue));

                if (timeout < 0) {
                    gettimeofday(&time, NULL);
                    rc = srcp_fmt_msg(SRCP_TIMEOUT, reply, time);
                }
                else {
                    rc = infoFB(bus, port, reply, length);
                }
            }
        }
        else {
            rc = srcp_fmt_msg(SRCP_LISTTOOSHORT, reply, time);
        }
    }

    else if (bus_has_devicegroup(bus, DG_TIME)
             && strncasecmp(device, "TIME", 4) == 0) {
        long d, h, m, s;
        int nelem;
        nelem = sscanf(parameter, "%ld %ld %ld %ld", &d, &h, &m, &s);
        if (nelem >= 4) {
            if (time_is_available()) {
                /*FIXME: race condition */
                bool mustwait;
                vtime_t vt;
                getTIME(&vt);
                do {
                    mustwait = (((d * 24 + h) * 60 + m) * 60 + s) >=
                        (((vt.day * 24 + vt.hour) * 60 +
                          vt.min) * 60 + vt.sec);

                    /* wait 10ms real time.. */
                    if (mustwait) {
                        if (usleep(10000) == -1) {
                            syslog_bus(bus, DBG_ERROR,
                                       "usleep() failed: %s (errno = %d)\n",
                                       strerror(errno), errno);
                        }
                        getTIME(&vt);
                    }
                }
                while (mustwait);
                rc = infoTIME(reply);
            }
            else {
                rc = srcp_fmt_msg(SRCP_NODATA, reply, time);
            }
        }
        else {
            rc = srcp_fmt_msg(SRCP_LISTTOOSHORT, reply, time);
        }
    }
    return rc;
}
Beispiel #16
0
/*
*
* The main worker-thread for the i2c-dev device
* Enters an endless loop that waits for commands and
* executes them.
*
* Currently we only support GA-devices
*
*/
void *thr_sendrec_I2C_DEV(void *v)
{
    char msg[1000];
    ga_state_t gatmp;
    int last_cancel_state, last_cancel_type;

    bus_thread_t *btd = (bus_thread_t *) malloc(sizeof(bus_thread_t));
    if (btd == NULL)
        pthread_exit((void *) 1);
    btd->bus = (bus_t) v;
    btd->fd = -1;

    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &last_cancel_state);
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &last_cancel_type);

    /*register cleanup routine */
    pthread_cleanup_push((void *) end_bus_thread, (void *) btd);

    syslog_bus(btd->bus, DBG_INFO, "i2c-dev bus started (device =  %s).",
               buses[btd->bus].device.file.path);

    I2CDEV_DATA *data = buses[btd->bus].driverdata;
    int ga_reset_devices = data->ga_reset_devices;
    buses[btd->bus].watchdog = 1;

    /* command processing starts here */
    while (true) {

        /* process POWER changes */
        if (buses[btd->bus].power_changed == 1) {

            /* dummy select, power state is directly read by select_bus() */
            select_bus(0, btd->bus);
            buses[btd->bus].power_changed = 0;
            infoPower(btd->bus, msg);
            enqueueInfoMessage(msg);

            if ((ga_reset_devices == 1)
                && (buses[btd->bus].power_state == 1)) {
                reset_ga(btd->bus);
            }

        }

        /* do nothing, if power is off */
        if (buses[btd->bus].power_state == 0) {
            if (usleep(1000) == -1) {
                syslog_bus(btd->bus, DBG_ERROR,
                           "usleep() failed: %s (errno = %d)\n",
                           strerror(errno), errno);
            }
            continue;
        }

        buses[btd->bus].watchdog = 4;

        /* process GA commands */
        if (!queue_GA_isempty(btd->bus)) {
            dequeueNextGA(btd->bus, &gatmp);
            handle_i2c_set_ga(btd->bus, &gatmp);
            setGA(btd->bus, gatmp.id, gatmp);
            select_bus(0, btd->bus);
            buses[btd->bus].watchdog = 6;
        }
        if (usleep(1000) == -1) {
            syslog_bus(btd->bus, DBG_ERROR,
                       "usleep() failed: %s (errno = %d)\n",
                       strerror(errno), errno);
        }
    }

    /*run the cleanup routine */
    pthread_cleanup_pop(1);
    return NULL;
}
Beispiel #17
0
/*main thread routine for this bus*/
void *thr_sendrec_DCCAR(void *v)
{
    int addr, ctr;
    struct timeval akt_time, cmp_time;
    ga_state_t gatmp;
    int last_cancel_state, last_cancel_type;

    bus_thread_t *btd = (bus_thread_t *) malloc(sizeof(bus_thread_t));

    if (btd == NULL)
        pthread_exit((void *) 1);
    btd->bus = (bus_t) v;
    btd->fd = -1;

    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &last_cancel_state);
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &last_cancel_type);

    /*register cleanup routine */
    pthread_cleanup_push((void *) end_bus_thread, (void *) btd);

    syslog_bus(btd->bus, DBG_INFO, "DC-Car bus started (device = %s).",
               buses[btd->bus].device.file.path);

    /*enter endless loop to process work tasks */
    while (true) {
        buses[btd->bus].watchdog = 1;

        /*POWER action arrived */
        if (buses[btd->bus].power_changed == 1)
            handle_power_command(btd->bus);

        /* loop shortcut to prevent processing of GA, GL (and FB)
         * without power on; arriving commands will flood the command
         * queue */
        if (buses[btd->bus].power_state == 0) {

            /* wait 1 ms */
            if (usleep(1000) == -1) {
                syslog_bus(btd->bus, DBG_ERROR,
                           "usleep() failed: %s (errno = %d)\n",
                           strerror(errno), errno);
            }
            continue;
        }

        /*GL action arrived */
        if (!queue_GL_isempty(btd->bus))
            handle_gl_command(btd->bus);

        /*FB action arrived */
        /* currently nothing to do here */
        buses[btd->bus].watchdog++;

        /* busy wait and continue loop */
        /* wait 1 ms */
        if (usleep(1000) == -1) {
            syslog_bus(btd->bus, DBG_ERROR,
                       "usleep() failed: %s (errno = %d)\n",
                       strerror(errno), errno);
        }
    }

    /*run the cleanup routine */
    pthread_cleanup_pop(1);
    return NULL;
}
Beispiel #18
0
static int handle_setcheck(sessionid_t sessionid, bus_t bus, char *device,
                           char *parameter, char *reply, int setorcheck)
{
    struct timeval time;
    int rc = SRCP_UNSUPPORTEDDEVICEGROUP;
    *reply = 0x00;

    if (bus_has_devicegroup(bus, DG_GL)
        && strncasecmp(device, "GL", 2) == 0) {
        long laddr, direction, speed, maxspeed, f[29];
        int func, i, anzparms;
        func = 0;
        /* We could provide a maximum of 32 on/off functions,
           but for now 28+1 will be good enough */
        anzparms = sscanf(parameter, "%ld %ld %ld %ld %ld %ld %ld %ld "
                          "%ld %ld %ld %ld %ld %ld %ld %ld %ld "
                          "%ld %ld %ld %ld %ld %ld %ld %ld "
                          "%ld %ld %ld %ld %ld %ld %ld %ld",
                          &laddr, &direction, &speed, &maxspeed, &f[0],
                          &f[1], &f[2], &f[3], &f[4], &f[5], &f[6], &f[7],
                          &f[8], &f[9], &f[10], &f[11], &f[12], &f[13],
                          &f[14], &f[15], &f[16], &f[17], &f[18], &f[19],
                          &f[20], &f[21], &f[22], &f[23], &f[24], &f[25],
                          &f[26], &f[27], &f[28]);
        for (i = 0; i < anzparms - 4; i++) {
            func += (f[i] ? 1 : 0) << i;
        }
        if (anzparms >= 4) {
            sessionid_t lockid = 0;
            /* Only if not locked or emergency stop !! */
            cacheGetLockGL(bus, laddr, &lockid);
            if (lockid == 0 || lockid == sessionid || direction == 2) {
                rc = SRCP_OK;
                if (setorcheck == 1)
                    rc = enqueueGL(bus, laddr, direction, speed, maxspeed,
                                   func);
            }
            else {
                rc = SRCP_DEVICELOCKED;
            }
        }
        else {
            rc = SRCP_LISTTOOSHORT;
        }
    }

    else if (bus_has_devicegroup(bus, DG_GA)
             && strncasecmp(device, "GA", 2) == 0) {
        long gaddr, port, aktion, delay;
        sessionid_t lockid;
        int anzparms;
        anzparms =
            sscanf(parameter, "%ld %ld %ld %ld", &gaddr, &port, &aktion,
                   &delay);
        if (anzparms >= 4) {
            /* Port 0,1; Action 0,1 */
            /* Only if not locked!! */
            getlockGA(bus, gaddr, &lockid);
            if (lockid == 0 || lockid == sessionid) {
                rc = SRCP_OK;
                if (setorcheck == 1)
                    rc = enqueueGA(bus, gaddr, port, aktion, delay);
            }
            else {
                rc = SRCP_DEVICELOCKED;
            }
        }
        else {
            rc = SRCP_LISTTOOSHORT;
        }
    }

    else if (bus_has_devicegroup(bus, DG_FB)
             && strncasecmp(device, "FB", 2) == 0) {
        long fbport, value;
        int anzparms;
        anzparms = sscanf(parameter, "%ld %ld", &fbport, &value);
        if (anzparms >= 2) {
            if (setorcheck == 1)
                rc = setFB(bus, fbport, value);
        }
    }

    /* SET 0 GM "<send_to_id> <reply_to_id> <message_type> <message>" */
    else if (bus_has_devicegroup(bus, DG_GM)
             && strncasecmp(device, "GM", 2) == 0) {
        sessionid_t sendto, replyto;
        int result;
        char msg[MAXSRCPLINELEN];

        memset(msg, 0, sizeof(msg));
        /*TODO: scan also message type */
        result =
            sscanf(parameter, "%lu %lu %990c", &sendto, &replyto, msg);
        if (result < 3)
            rc = SRCP_LISTTOOSHORT;
        else
            rc = setGM(sendto, replyto, msg);
    }

    /* SET <bus> SM "<decoderaddress> <type> <1 or more values>" */
    else if (bus_has_devicegroup(bus, DG_SM)
             && strncasecmp(device, "SM", 2) == 0) {
        long addr, value1, value2, value3;
        int type;
        int result;
        char ctype[MAXSRCPLINELEN];

        result = sscanf(parameter, "%ld %s %ld %ld %ld", &addr, ctype,
                        &value1, &value2, &value3);
        if (result < 4)
            rc = SRCP_LISTTOOSHORT;
        else {
            type = -1;
            if (strcasecmp(ctype, "REG") == 0)
                type = REGISTER;
            else if (strcasecmp(ctype, "CV") == 0)
                type = CV;
            else if (strcasecmp(ctype, "CVBIT") == 0)
                type = CV_BIT;
            else if (strcasecmp(ctype, "PAGE") == 0)
                type = PAGE;

            if (type == -1)
                rc = SRCP_WRONGVALUE;
            else {
                if (type == CV_BIT)
                    if (result < 5)
                        rc = SRCP_LISTTOOSHORT;
                    else
                        rc = infoSM(bus, SET, type, addr, value1,
                                    value2, value3, reply);
                else
                    rc = infoSM(bus, SET, type, addr, value1, 0,
                                value2, reply);
            }
        }
    }

    else if (bus_has_devicegroup(bus, DG_TIME)
             && strncasecmp(device, "TIME", 4) == 0) {
        long d, h, m, s, nelem;
        nelem = sscanf(parameter, "%ld %ld %ld %ld", &d, &h, &m, &s);
        if (nelem >= 4) {
            rc = SRCP_OK;
            if (setorcheck == 1)
                rc = setTIME(d, h, m, s);
        }
        else
            rc = SRCP_LISTTOOSHORT;
    }

    else if (bus_has_devicegroup(bus, DG_LOCK)
             && strncasecmp(device, "LOCK", 4) == 0) {
        long int addr, duration;
        char devgrp[MAXSRCPLINELEN];
        int nelem = -1;
        if (strlen(parameter) > 0) {
            nelem =
                sscanf(parameter, "%s %ld %ld", devgrp, &addr, &duration);
            syslog_bus(bus, DBG_INFO, "LOCK: %s", parameter);
        }
        if (nelem >= 3) {
            rc = SRCP_UNSUPPORTEDDEVICEGROUP;
            if (strncmp(devgrp, "GL", 2) == 0) {
                rc = SRCP_OK;
                if (setorcheck == 1)
                    rc = cacheLockGL(bus, addr, duration, sessionid);
            }
            else if (strncmp(devgrp, "GA", 2) == 0) {
                rc = SRCP_OK;
                if (setorcheck == 1)
                    rc = lockGA(bus, addr, duration, sessionid);
            }
        }
        else {
            rc = SRCP_LISTTOOSHORT;
        }
    }

    else if (bus_has_devicegroup(bus, DG_POWER)
             && strncasecmp(device, "POWER", 5) == 0) {
        int nelem;
        char state[5], msg[256];
        memset(msg, 0, sizeof(msg));
        nelem = sscanf(parameter, "%3s %100c", state, msg);
        if (nelem >= 1) {
            rc = SRCP_WRONGVALUE;
            if (strncasecmp(state, "OFF", 3) == 0) {
                rc = SRCP_OK;
                if (setorcheck == 1)
                    rc = setPower(bus, 0, msg);
            }
            else if (strncasecmp(state, "ON", 2) == 0) {
                rc = SRCP_OK;
                if (setorcheck == 1)
                    rc = setPower(bus, 1, msg);
            }
        }
        else {
            rc = SRCP_LISTTOOSHORT;
        }
    }

    gettimeofday(&time, NULL);
    srcp_fmt_msg(rc, reply, time);
    return rc;
}
Beispiel #19
0
int readconfig_DCCAR(xmlDocPtr doc, xmlNodePtr node, bus_t busnumber)
{
    buses[busnumber].driverdata = malloc(sizeof(struct _DCCAR_DATA));

    if (buses[busnumber].driverdata == NULL) {
        syslog_bus(busnumber, DBG_ERROR,
                   "Memory allocation error in module '%s'.", node->name);
        return 0;
    }

    buses[busnumber].type = SERVER_DCCAR;
    buses[busnumber].init_func = &init_bus_DCCAR;
    buses[busnumber].thr_func = &thr_sendrec_DCCAR;
    buses[busnumber].init_gl_func = &init_gl_DCCAR;
    strcpy(buses[busnumber].description,
           "GL POWER LOCK DESCRIPTION");

    __dccar->mode = DCCAR;
    __dccar->pause_between_cmd = 10;

    xmlNodePtr child = node->children;
    xmlChar *txt = NULL;

    while (child != NULL) {
        if ((xmlStrncmp(child->name, BAD_CAST "text", 4) == 0) ||
                (xmlStrncmp(child->name, BAD_CAST "comment", 7) == 0)) {
            /* just do nothing, it is only formatting text or a comment */
        }

        else if (xmlStrcmp(child->name, BAD_CAST "number_gl") == 0) {
            txt = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
            if (txt != NULL) {
                __dccar->number_gl = atoi((char *) txt);
                xmlFree(txt);
            }
        }

        else if (xmlStrcmp(child->name, BAD_CAST "pause_between_commands") == 0) {
            txt = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
            if (txt != NULL) {
                __dccar->pause_between_cmd = atoi((char *) txt);
                xmlFree(txt);
            }
        }

        else if (xmlStrcmp(child->name, BAD_CAST "mode") == 0) {
            txt = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
            if (txt != NULL) {
                if (xmlStrcmp(txt, BAD_CAST "dccar") == 0)
                    __dccar->mode = DCCAR;
                else if (xmlStrcmp(txt, BAD_CAST "infracar") == 0)
                    __dccar->mode = INFRACAR;
                xmlFree(txt);
            }
        }

        else
            syslog_bus(busnumber, DBG_WARN,
                       "WARNING, unknown tag found: \"%s\"!\n",
                       child->name);;
        child = child->next;
    }

    if (__dccar->mode == DCCAR && __dccar->number_gl > 1023)
        __dccar->number_gl = 1023;
    else if (__dccar->mode == INFRACAR && __dccar->number_gl > 4096)
        __dccar->number_gl = 4096;

    if (init_GL(busnumber, __dccar->number_gl)) {
        __dccar->number_gl = 0;
        syslog_bus(busnumber, DBG_ERROR,
                   "Can't create array for locomotives");
    }

    return (1);
}
Beispiel #20
0
/*  Handle set command of GA */
static int handle_i2c_set_ga(bus_t bus, ga_state_t * gatmp)
{
    I2C_ADDR i2c_addr;
    I2C_VALUE i2c_val;
    I2C_VALUE value;
    I2C_PORT port;
    I2C_MUX_BUS mult_busnum;
    I2CDEV_DATA *data = (I2CDEV_DATA *) buses[bus].driverdata;
    int addr;
    int reset_old_value;
    int ga_min_active_time = data->ga_min_active_time;
    int ga_hardware_inverters = data->ga_hardware_inverters;

    addr = gatmp->id;
    port = gatmp->port;
    value = gatmp->action;

    mult_busnum = (addr / 256) + 1;
    select_bus(mult_busnum, bus);

    i2c_addr = (addr % 256);
    /* gettimeofday(gatmp->tv[0], NULL); */

    if (gatmp->activetime >= 0) {
        gatmp->activetime = (gatmp->activetime > ga_min_active_time) ?
            gatmp->activetime : ga_min_active_time;
        reset_old_value = 1;
    }
    else {
        gatmp->activetime = ga_min_active_time; /* always wait minimum time */
        reset_old_value = 0;
    }

    syslog_bus(bus, DBG_DEBUG, "i2c_addr = %d on multiplexed bus #%d",
               i2c_addr, mult_busnum);
    /* port: 0     - direct write of value to device */
    /* other - select port pins directly, value = {0,1} */

    if (port == 0) {

        /* write directly to device */

        if (ga_hardware_inverters == 1) {
            i2c_val = ~value;
        }
        else {
            i2c_val = value;
        }

    }
    else {

        /* set bit for selected port to 1 */
        I2C_VALUE pin_bit = 1 << (port - 1);
        value = (value & 1);
        i2c_val = data->i2c_values[i2c_addr][mult_busnum - 1];

        if (ga_hardware_inverters == 1) {
            value = (~value) & 1;
        }

        if (value != 0) {       /* Set bit */
            i2c_val |= pin_bit;
        }
        else {                  /* Reset bit */
            i2c_val &= (~pin_bit);
        }

    }

    if (write_i2c_dev(bus, i2c_addr, i2c_val) < 0) {
        syslog_bus(bus, DBG_ERROR, "Device not found at address %d", addr);
        return (-1);
    }

    if (usleep((unsigned long) gatmp->activetime * 1000) == -1) {
        syslog_bus(bus, DBG_ERROR,
                   "usleep() failed: %s (errno = %d)\n",
                   strerror(errno), errno);
    }

    if (reset_old_value == 1) {

        if (write_i2c_dev
            (bus, i2c_addr,
             data->i2c_values[i2c_addr][mult_busnum - 1]) < 0) {
            syslog_bus(bus, DBG_ERROR, "Device not found at address %d",
                       addr);
            return (-1);
        }

        if (usleep((unsigned long) gatmp->activetime * 1000) == -1) {
            syslog_bus(bus, DBG_ERROR,
                       "usleep() failed: %s (errno = %d)\n",
                       strerror(errno), errno);
        }

    }
    else {
        data->i2c_values[i2c_addr][mult_busnum - 1] = i2c_val;
    }

    return (0);
}
Beispiel #21
0
int readconfig_I2C_DEV(xmlDocPtr doc, xmlNodePtr node, bus_t busnumber)
{
    buses[busnumber].driverdata = malloc(sizeof(I2CDEV_DATA));

    if (buses[busnumber].driverdata == NULL) {
        syslog_bus(busnumber, DBG_ERROR,
                   "Memory allocation error in module '%s'.", node->name);
        return 0;
    }

    buses[busnumber].type = SERVER_I2C_DEV;
    buses[busnumber].init_func = &init_bus_I2C_DEV;
    buses[busnumber].thr_func = &thr_sendrec_I2C_DEV;
    strcpy(buses[busnumber].description, "GA POWER DESCRIPTION");

    __i2cdev->number_ga = 0;
    __i2cdev->multiplex_buses = 0;
    __i2cdev->ga_hardware_inverters = 0;
    __i2cdev->ga_reset_devices = 1;
    __i2cdev->ga_min_active_time = 75;

    xmlNodePtr child = node->children;
    xmlChar *txt = NULL;

    while (child != NULL) {

        if ((xmlStrncmp(child->name, BAD_CAST "text", 4) == 0) ||
            (xmlStrncmp(child->name, BAD_CAST "comment", 7) == 0)) {
            /* just do nothing, it is only formatting text or a comment */
        }

        /*
           else if (xmlStrcmp(child->name, BAD_CAST "number_gl") == 0) {
           txt = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
           if (txt != NULL) {
           __i2cdev->number_gl = atoi((char*) txt);
           xmlFree(txt);
           }
           }
         */

        else if (xmlStrcmp(child->name, BAD_CAST "multiplex_buses") == 0) {
            txt = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
            if (txt != NULL) {
                __i2cdev->multiplex_buses = atoi((char *) txt);
                xmlFree(txt);
            }
        }

        else if (xmlStrcmp(child->name, BAD_CAST "ga_hardware_inverters")
                 == 0) {
            txt = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
            if (txt != NULL) {
                __i2cdev->ga_hardware_inverters = atoi((char *) txt);
                xmlFree(txt);
            }
        }

        else if (xmlStrcmp(child->name, BAD_CAST "ga_reset_devices") == 0) {
            txt = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
            if (txt != NULL) {
                __i2cdev->ga_reset_devices = atoi((char *) txt);
                xmlFree(txt);
            }
        }

        else
            syslog_bus(busnumber, DBG_WARN,
                       "WARNING, unknown tag found: \"%s\"!\n",
                       child->name);;

        child = child->next;
    }

    /* init the stuff */

    __i2cdev->number_ga = 256 * (__i2cdev->multiplex_buses);

    if (init_GA(busnumber, __i2cdev->number_ga)) {
        __i2cdev->number_ga = 0;
        syslog_bus(busnumber, DBG_ERROR,
                   "Can't create array for accessoires");
    }

    /*
       if (init_GL(busnumber, __i2cdev->number_gl)) {
       __i2cdev->number_gl = 0;
       syslog_bus(busnumber, DBG_ERROR, "Can't create array for locomotives");
       }
     */
    /*
       if (init_FB(busnumber, __i2cdev->number_ga)) {
       __i2cdev->number_ga = 0;
       syslog_bus(busnumber, DBG_ERROR, "Can't create array for feedback");
       }
     */
    return (1);
}
Beispiel #22
0
/*handle incoming network syn requests*/
void *thr_handlePort(void *v)
{
    int last_cancel_state, last_cancel_type;
    pthread_t ttid;
    int result;

    net_thread_t *ntd = (net_thread_t *) malloc(sizeof(net_thread_t));
    if (ntd == NULL)
        pthread_exit((void *) 1);

    ntd->port = (unsigned long int) v;

    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &last_cancel_state);
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &last_cancel_type);

    /*register cleanup routine */
    pthread_cleanup_push((void *) end_netrequest_thread, (void *) ntd);

#ifdef ENABLE_IPV6
    struct sockaddr_in6 sin6;
    struct sockaddr_in6 fsin6;
#endif
    struct sockaddr_in sin;
    struct sockaddr_in fsin;
    struct sockaddr *saddr, *fsaddr;
    socklen_t socklen;
    int sock_opt;
    bool has_ipv6_support = ipv6_supported();

#ifdef ENABLE_IPV6
    if (has_ipv6_support) {
        memset(&sin6, 0, sizeof(sin6));
        sin6.sin6_family = AF_INET6;

        sin6.sin6_port = htons(ntd->port);
        sin6.sin6_addr = in6addr_any;

        /* create a socket for listening */
        ntd->socket = socket(AF_INET6, SOCK_STREAM, 0);
        if (ntd->socket == -1) {
            syslog_bus(0, DBG_ERROR,
                       "Socket creation failed: %s (errno = %d). "
                       "Terminating...\n", strerror(errno), errno);
            exit(EXIT_FAILURE);
        }
        saddr = (struct sockaddr *) &sin6;
        fsaddr = (struct sockaddr *) &fsin6;
        socklen = sizeof(sin6);
    }
    else
#endif
    {
        /* Here would be the original IPv4 code as usual */
        memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;       /* IPv4 address family */
        sin.sin_port = htons(ntd->port);
        sin.sin_addr.s_addr = INADDR_ANY;

        /* Create the socket */
        ntd->socket = socket(AF_INET, SOCK_STREAM, 0);
        if (ntd->socket == -1) {
            syslog_bus(0, DBG_ERROR,
                       "Socket creation failed: %s (errno = %d). "
                       "Terminating...\n", strerror(errno), errno);
            exit(EXIT_FAILURE);
        }
        saddr = (struct sockaddr *) &sin;
        fsaddr = (struct sockaddr *) &fsin;
        socklen = sizeof(sin);
    }
    if (getuid() == 0) {
        change_privileges();
    }

    sock_opt = 1;
    if (setsockopt(ntd->socket, SOL_SOCKET, SO_REUSEADDR, &sock_opt,
                   sizeof(sock_opt)) == -1) {
        syslog_bus(0, DBG_ERROR, "setsockopt() failed: %s (errno = %d). "
                   "Terminating...\n", strerror(errno), errno);
        close(ntd->socket);
        exit(EXIT_FAILURE);
    }

    /* saddr=(sockaddr_in) if ntd.socket is of type AF_INET else its (sockaddr_in6) */
    if (bind(ntd->socket, (struct sockaddr *) saddr, socklen) == -1) {
        syslog_bus(0, DBG_ERROR, "bind() failed: %s (errno = %d). "
                   "Terminating...\n", strerror(errno), errno);
        close(ntd->socket);
        exit(EXIT_FAILURE);
    }

    if (listen(ntd->socket, 1) == -1) {
        syslog_bus(0, DBG_ERROR, "Listen failed: %s (errno = %d). "
                   "Terminating...\n", strerror(errno), errno);
        close(ntd->socket);
        exit(EXIT_FAILURE);
    }

    /* Wait for connection requests */
    for (;;) {
        pthread_testcancel();
        int clientsocket = accept(ntd->socket, (struct sockaddr *) fsaddr,
                &socklen);

        if (clientsocket == -1) {
            /* Possibly the connection got aborted */
            syslog_bus(0, DBG_WARN, "accept() failed: %s (errno = %d)\n",
                       strerror(errno), errno);
            continue;
        }

        syslog_bus(0, DBG_INFO, "New connection received.\n");
        /* Now process the connection as per the protocol */
#ifdef ENABLE_IPV6
        if (has_ipv6_support) {
            /* This casting must work as we have taken care of the
             * appropriate data structures */
            struct sockaddr_in6 *sin6_ptr = (struct sockaddr_in6 *) fsaddr;
            char addrbuf[INET6_ADDRSTRLEN];

            if (IN6_IS_ADDR_V4MAPPED(&(sin6_ptr->sin6_addr))) {
                syslog_bus(0, DBG_INFO,
                           "Connection from an IPv4 client\n");
            }

            syslog_bus(0, DBG_INFO, "Connection from %s/%d\n",
                       inet_ntop(AF_INET6, (void *) &(sin6_ptr->sin6_addr),
                                 addrbuf, sizeof(addrbuf)),
                       ntohs(sin6_ptr->sin6_port));
        }
        else
#endif
        {
            struct sockaddr_in *sin_ptr = (struct sockaddr_in *) fsaddr;
            syslog_bus(0, DBG_INFO, "Connection from %s/%d\n",
                       inet_ntoa(sin_ptr->sin_addr),
                       ntohs(sin_ptr->sin_port));
        }
        sock_opt = 1;
        if (setsockopt(clientsocket, SOL_SOCKET, SO_KEEPALIVE, &sock_opt,
                       sizeof(sock_opt)) == -1) {
            syslog_bus(0, DBG_ERROR,
                       "Setsockopt failed: %s (errno = %d)\n",
                       strerror(errno), errno);
            close(clientsocket);
            continue;
        }

        /* create an anonymous session with a valid socket */
        session_node_t *asn = create_anonymous_session(clientsocket);
        if (asn == NULL) {
            close(clientsocket);
            syslog_bus(0, DBG_ERROR, "Session create failed!");
            continue;
        }

        /* hand over client service to "thr_doClient()" from clientservice.c */
        result = pthread_create(&ttid, NULL, thr_doClient, asn);
        if (result != 0) {
            syslog_bus(0, DBG_ERROR, "Create thread for network client "
                       "failed: %s (errno = %d). Terminating...\n",
                       strerror(result), result);
            close(clientsocket);
            destroy_anonymous_session(asn);
            continue;
        }
    }

    /*run the cleanup routine */
    pthread_cleanup_pop(1);
    return NULL;
}
Beispiel #23
0
/**
 * GET
 */
int handleGET(sessionid_t sessionid, bus_t bus, char *device,
              char *parameter, char *reply, size_t length)
{
    struct timeval akt_time;
    int rc = SRCP_UNSUPPORTEDDEVICEGROUP;
    *reply = 0x00;
    gettimeofday(&akt_time, NULL);

    if (bus_has_devicegroup(bus, DG_FB)
        && strncasecmp(device, "FB", 2) == 0) {
        long int nelem, port;
        nelem = sscanf(parameter, "%ld", &port);
        if (nelem >= 1)
            rc = infoFB(bus, port, reply, length);
        else
            rc = srcp_fmt_msg(SRCP_LISTTOOSHORT, reply, akt_time);
    }

    else if (bus_has_devicegroup(bus, DG_GL)
             && strncasecmp(device, "GL", 2) == 0) {
        long nelem, addr;
        nelem = sscanf(parameter, "%ld", &addr);
        if (nelem >= 1)
            rc = cacheInfoGL(bus, addr, reply);
        else
            rc = srcp_fmt_msg(SRCP_LISTTOOSHORT, reply, akt_time);
    }

    else if (bus_has_devicegroup(bus, DG_GA)
             && strncasecmp(device, "GA", 2) == 0) {
        long addr, port, nelem;
        nelem = sscanf(parameter, "%ld %ld", &addr, &port);
        switch (nelem) {
            case 0:
            case 1:
                rc = srcp_fmt_msg(SRCP_LISTTOOSHORT, reply, akt_time);;
                break;
            case 2:
                rc = infoGA(bus, addr, port, reply);
                break;
            default:
                rc = srcp_fmt_msg(SRCP_LISTTOOLONG, reply, akt_time);;
        }
    }

    else if (bus_has_devicegroup(bus, DG_SM)
             && strncasecmp(device, "SM", 2) == 0) {
        long addr, value1, value2;
        int nelem;
        int type;
        char ctype[MAXSRCPLINELEN];

        nelem = sscanf(parameter, "%ld %s %ld %ld", &addr, ctype, &value1,
                       &value2);
        if (nelem < 3) {
            rc = SRCP_LISTTOOSHORT;
        }
        else {
            type = -1;

            if (strcasecmp(ctype, "REG") == 0)
                type = REGISTER;
            else if (strcasecmp(ctype, "CVBIT") == 0)
                type = CV_BIT;
            else if (strcasecmp(ctype, "PAGE") == 0)
                type = PAGE;
            else if (strcasecmp(ctype, "CV") == 0)
                type = CV;

            if (type == -1) {
                rc = SRCP_WRONGVALUE;
            }
            else {
                if (type != CV_BIT)
                    value2 = 0;
                if (type == CV_BIT && nelem < 4) {
                    rc = SRCP_LISTTOOSHORT;
                }
                else {
                    rc = infoSM(bus, GET, type, addr, value1, value2, 0,
                                reply);
                }
            }
        }
    }

    else if (bus_has_devicegroup(bus, DG_POWER)
             && strncasecmp(device, "POWER", 5) == 0) {
        rc = infoPower(bus, reply);
    }

    else if (bus_has_devicegroup(bus, DG_SERVER)
             && strncasecmp(device, "SERVER", 6) == 0) {
        rc = infoSERVER(reply);
    }

    else if (bus_has_devicegroup(bus, DG_TIME)
             && strncasecmp(device, "TIME", 4) == 0) {
        rc = infoTIME(reply);
        if (rc != SRCP_INFO) {
            rc = srcp_fmt_msg(SRCP_NODATA, reply, akt_time);
        }
    }

    else if (strncasecmp(device, "DESCRIPTION", 11) == 0) {

        /* there are two descriptions */
        long int addr;
        char devgrp[11];
        int nelem = 0;
        if (strlen(parameter) > 0)
            nelem = sscanf(parameter, "%10s %ld", devgrp, &addr);
        if (nelem <= 0) {
            rc = describeBus(bus, reply);
        }
        else {
            if (bus_has_devicegroup(bus, DG_DESCRIPTION)) {
                syslog_bus(bus, DBG_INFO,
                           "DESCRIPTION: devgrp=%s addr=%ld", devgrp,
                           addr);
                if (strncmp(devgrp, "GL", 2) == 0)
                    rc = cacheDescribeGL(bus, addr, reply);
                else if (strncmp(devgrp, "GA", 2) == 0)
                    rc = describeGA(bus, addr, reply);
                else if (strncmp(devgrp, "FB", 2) == 0)
                    rc = describeFB(bus, addr, reply);
                else if (strncmp(devgrp, "SESSION", 7) == 0)
                    rc = describeSESSION(bus, addr, reply);
                else if (strncmp(devgrp, "TIME", 4) == 0)
                    rc = describeTIME(reply);
                else if (strncmp(devgrp, "SERVER", 6) == 0)
                    rc = describeSERVER(bus, addr, reply);
            }
            else {
                rc = srcp_fmt_msg(SRCP_UNSUPPORTEDDEVICEGROUP, reply,
                                  akt_time);
            }
        }
    }

    else if (bus_has_devicegroup(bus, DG_LOCK)
             && (strncasecmp(device, "LOCK", 4) == 0)) {
        long int addr;
        char devgrp[10];
        int nelem = -1;

        if (strlen(parameter) > 0)
            nelem = sscanf(parameter, "%s %ld", devgrp, &addr);
        if (nelem <= 1) {
            rc = srcp_fmt_msg(SRCP_LISTTOOSHORT, reply, akt_time);
        }
        else {
            rc = SRCP_UNSUPPORTEDDEVICEGROUP;
            if (strncmp(devgrp, "GL", 2) == 0)
                rc = describeLOCKGL(bus, addr, reply);
            else if (strncmp(devgrp, "GA", 2) == 0)
                rc = describeLOCKGA(bus, addr, reply);
        }
    }

    if (reply[0] == 0x00)
        rc = srcp_fmt_msg(rc, reply, akt_time);
    return rc;
}