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; }
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); }
/* * * 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; }
/* 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; }
/* 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; }
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); }
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; }
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); }
/* 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."); }
/* 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); }
/*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); }
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; }
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; } }
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); } } }
/** * 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; }
/* * * 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; }
/*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; }
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; }
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); }
/* 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); }
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); }
/*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; }
/** * 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; }