Exemplo n.º 1
0
// Bind the master netlink socket for all communication
// responses will have to be routed to appropriate bus master
GOOD_OR_BAD w1_bind( struct connection_in * in )
{
	struct port_in * pin = in->pown ;
	struct sockaddr_nl l_local ;

	pin->type = ct_netlink ;
	Test_and_Close( &(pin->file_descriptor) ) ; // just in case
	
	// Example from http://lxr.linux.no/linux+v3.0/Documentation/connector/ucon.c#L114
	//pin->file_descriptor = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
//    pin->file_descriptor = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC , NETLINK_CONNECTOR);
    pin->file_descriptor = socket(PF_NETLINK, SOCK_RAW , NETLINK_CONNECTOR);
	if ( FILE_DESCRIPTOR_NOT_VALID( pin->file_descriptor ) ) {
		ERROR_CONNECT("Netlink (w1) socket (are you root?)");
		return gbBAD;
	}
//	fcntl (pin->file_descriptor, F_SETFD, FD_CLOEXEC); // for safe forking

	l_local.nl_pid = in->master.w1_monitor.pid = getpid() ;
	l_local.nl_pad = 0;
	l_local.nl_family = AF_NETLINK;
	l_local.nl_groups = 23;

	if ( bind( pin->file_descriptor, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl) ) == -1 ) {
		ERROR_CONNECT("Netlink (w1) bind (are you root?)");
		Test_and_Close( &( pin->file_descriptor) );
		return gbBAD ;
	}
	pin->state = cs_deflowered ;
	return gbGOOD ;
}
Exemplo n.º 2
0
/* Called on head of multibus group */
void serial_free(struct connection_in *connection)
{
    FILE_DESCRIPTOR_OR_ERROR fd ;
    struct port_in * pin = connection->pown ;

    if ( pin->state == cs_virgin ) {
        return ;
    }

    fd = pin->file_descriptor ;
    if ( FILE_DESCRIPTOR_NOT_VALID( fd ) ) {
        // reopen to restore attributes
        fd = open( pin->init_data, O_RDWR | O_NONBLOCK | O_NOCTTY ) ;
    }

    // restore tty settings
    if ( FILE_DESCRIPTOR_VALID( fd ) ) {
        LEVEL_DEBUG("COM_close: flush");
        tcflush( fd, TCIOFLUSH);
        LEVEL_DEBUG("COM_close: restore");
        if ( tcsetattr( fd, TCSANOW, &(pin->dev.serial.oldSerialTio) ) < 0) {
            ERROR_CONNECT("Cannot restore port attributes: %s", pin->init_data);
        }
    }
    Test_and_Close( &( pin->file_descriptor) ) ;
}
Exemplo n.º 3
0
int watchdog_init(struct watchdog_s *w, int inactivity_timeout)
{
	pthread_t thread_id;
	int error_code;

	daemon_assert(w != NULL);
	daemon_assert(inactivity_timeout > 0);

	_MUTEX_INIT(w->mutex);
	w->inactivity_timeout = inactivity_timeout;
	w->oldest = NULL;
	w->newest = NULL;

	error_code = pthread_create(&thread_id, DEFAULT_THREAD_ATTR, watcher, w);
	if (error_code != 0) {
		errno = error_code;
		ERROR_CONNECT("Watchdog thread create problem\n");
		return 0;
	}
	pthread_detach(thread_id);

	daemon_assert(invariant(w));

	return 1;
}
Exemplo n.º 4
0
/* Re-open a DS2482 */
static GOOD_OR_BAD DS2482_redetect(const struct parsedname *pn)
{
    struct connection_in *head = pn->selected_connection->master.i2c.head;
    int address = head->master.i2c.i2c_address;
    FILE_DESCRIPTOR_OR_ERROR file_descriptor;
    struct address_pair ap ; // to get device name from device:address

    /* open the i2c port */
    Parse_Address( DEVICENAME(head), &ap ) ;
    file_descriptor = open(ap.first.alpha, O_RDWR );
    Free_Address( &ap ) ;
    if ( FILE_DESCRIPTOR_NOT_VALID(file_descriptor) ) {
        ERROR_CONNECT("Could not open i2c device %s", DEVICENAME(head));
        return gbBAD;
    }

    /* address is known */
    if (ioctl(file_descriptor, I2C_SLAVE, address) < 0) {
        ERROR_CONNECT("Cound not set i2c address to %.2X", address);
    } else {
        BYTE c;
        /* write the RESET code */
        if (i2c_smbus_write_byte(file_descriptor, DS2482_CMD_RESET)	// reset
                || BAD(DS2482_readstatus(&c, file_descriptor, DS2482_Chip_reset_usec))	// pause .5 usec then read status
                || (c != (DS2482_REG_STS_LL | DS2482_REG_STS_RST))	// make sure status is properly set
           ) {
            LEVEL_CONNECT("i2c device at %s address %d cannot be reset. Not a DS2482.", DEVICENAME(head), address);
        } else {
            struct connection_in * next ;
            head->master.i2c.current = 0;
            head->pown->file_descriptor = file_descriptor;
            head->pown->state = cs_deflowered ;
            head->pown->type = ct_i2c ;
            head->master.i2c.configchip = 0x00;	// default configuration register after RESET
            LEVEL_CONNECT("i2c device at %s address %d reset successfully", DEVICENAME(head), address);
            for ( next = head->pown->first; next; next = next->next ) {
                /* loop through devices, matching those that have the same "head" */
                /* BUSLOCK also locks the sister channels for this */
                next->reconnect_state = reconnect_ok;
            }
            return gbGOOD;
        }
    }
    /* fellthough, no device found */
    close(file_descriptor);
    return gbBAD;
}
Exemplo n.º 5
0
/* return GOOD if any found */
static GOOD_OR_BAD DS2482_detect_sys( int any, enum ds2482_address chip_num, struct port_in *pin_original)
{
    DIR * i2c_list_dir ;
    struct dirent * i2c_bus ;
    int found = 0 ;
    struct port_in * pin_current = pin_original ;

    // We'll look in this directory for available i2c adapters.
    // This may be linux 2.6 specific
    i2c_list_dir = opendir( SYSFS_I2C_Path ) ;
    if ( i2c_list_dir == NULL ) {
        ERROR_CONNECT( "Cannot open %d to find available i2c devices",SYSFS_I2C_Path ) ;
        // Use the cruder approach of trying all possible numbers
        return DS2482_detect_dir( any, chip_num, pin_original ) ;
    }

    /* cycle through entries in /sys/class/i2c-adapter */
    while ( (i2c_bus=readdir(i2c_list_dir)) != NULL ) {
        char dev_name[128] ; // room for /dev/name
        int sn_ret ;

        UCLIBCLOCK ;
        sn_ret = snprintf( dev_name, 128, "/dev/%s", i2c_bus->d_name ) ;
        UCLIBCUNLOCK ;
        if ( sn_ret < 0 ) {
            break ;
        }

        // Now look for the ds2482's
        if ( BAD( DS2482_detect_bus( chip_num, dev_name, pin_current ) ) ) {
            continue ; // none found on this i2c bus
        }

        // at least one found on this i2c bus
        ++found ;
        if ( any ) { // found one -- that's enough
            closedir( i2c_list_dir ) ;
            return gbGOOD ;
        }

        // ALL? then set up a new connection_in slot for the next one
        pin_current = NewPort(pin_current) ;
        if ( pin_current == NULL ) {
            break ;
        }
    }

    closedir( i2c_list_dir ) ;

    if ( found==0 ) {
        return gbBAD ;
    }

    if ( pin_current != pin_original ) {
        RemovePort( pin_current ) ;
    }
    return gbGOOD ;
}
Exemplo n.º 6
0
/* All ow library closeup */
void PIDstop(void)
{
	if (pid_created && pid_file) {
		if (unlink(pid_file)) {
			ERROR_CONNECT("Cannot remove PID file: %s", pid_file);
		}
		owfree(pid_file);
		pid_file = NULL;
	}
}
Exemplo n.º 7
0
/* Puts in 9600 baud */
static GOOD_OR_BAD DS9097_pre_reset(struct connection_in *in )
{
	struct port_in * pin = in->pown ;

	RETURN_BAD_IF_BAD( COM_test(in) ) ;

	/* 8 data bits */
	pin->bits = 8 ;
	pin->baud = B9600 ;

	if ( BAD( COM_change(in)) ) {
		ERROR_CONNECT("Cannot set attributes: %s", SAFESTRING(DEVICENAME(in)));
		DS9097_post_reset( in ) ;
		return gbBAD;
	}
	return gbGOOD;
}
Exemplo n.º 8
0
void PIDstart(void)
{
/* store the PID */
	pid_t pid_num = getpid();

	if (pid_file) {
		FILE *pid = fopen(pid_file, "w+");
		if (pid == NULL) {
			ERROR_CONNECT("Cannot open PID file: %s", pid_file);
			owfree(pid_file);
			pid_file = NULL;
		} else {
			fprintf(pid, "%lu", (unsigned long int) pid_num);
			fclose(pid);
			pid_created = 1;
		}
	}
}
Exemplo n.º 9
0
/* Usually called with BUS locked, to protect ai settings */
FILE_DESCRIPTOR_OR_ERROR ClientConnect(struct connection_in *in)
{
	struct port_in * pin = in->pown ;
	FILE_DESCRIPTOR_OR_ERROR file_descriptor;
	struct addrinfo *ai;

	if ( pin->dev.tcp.ai == NULL) {
		LEVEL_DEBUG("Client address not yet parsed");
		return FILE_DESCRIPTOR_BAD;
	}

	/* Can't change ai_ok without locking the in-device.
	 * First try the last working address info, if it fails lock
	 * the in-device and loop through the list until it works.
	 * Not a perfect solution, but it should work at least.
	 */
	ai = pin->dev.tcp.ai_ok;
	if (ai) {
		file_descriptor = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
		if ( FILE_DESCRIPTOR_VALID(file_descriptor) ) {
			if (connect(file_descriptor, ai->ai_addr, ai->ai_addrlen) == 0) {
				return file_descriptor;
			}
			close(file_descriptor);
		}
	}

	ai = pin->dev.tcp.ai;		// loop from first address info since it failed.
	do {
		file_descriptor = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
		if ( FILE_DESCRIPTOR_VALID(file_descriptor) ) {
			if (connect(file_descriptor, ai->ai_addr, ai->ai_addrlen) == 0) {
				pin->dev.tcp.ai_ok = ai;
				return file_descriptor;
			}
			close(file_descriptor);
		}
	} while ((ai = ai->ai_next));
	pin->dev.tcp.ai_ok = NULL;

	ERROR_CONNECT("Socket problem");
	STAT_ADD1(NET_connection_errors);
	return FILE_DESCRIPTOR_BAD;
}
Exemplo n.º 10
0
static int Get_HA7_response( struct addrinfo *now, char * name )
{
	struct timeval tv = { 50, 0 };
	FILE_DESCRIPTOR_OR_ERROR file_descriptor;
	struct HA7_response ha7_response ;

	struct sockaddr_in from ;
	socklen_t fromlen = sizeof(struct sockaddr_in) ;
	int on = 1;

	file_descriptor = socket(now->ai_family, now->ai_socktype, now->ai_protocol) ;
	if ( FILE_DESCRIPTOR_NOT_VALID(file_descriptor) ) {
		ERROR_DEBUG("Cannot get socket file descriptor for broadcast.");
		return 1;
	}
//	fcntl (file_descriptor, F_SETFD, FD_CLOEXEC); // for safe forking
	if (setsockopt(file_descriptor, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) == -1) {
		ERROR_DEBUG("Cannot set socket option for broadcast.");
		return 1;
	}
	if (sendto(file_descriptor, "HA\000\001", 4, 0, now->ai_addr, now->ai_addrlen)
		!= 4) {
		ERROR_CONNECT("Trouble sending broadcast message");
		return 1;
	}

	/* now read */
	if ( udp_read(file_descriptor, &ha7_response, sizeof(struct HA7_response), &tv, &from, &fromlen) != sizeof(struct HA7_response) ) {
		LEVEL_CONNECT("HA7 response bad length");
		return 1;
	}

	if ( Test_HA7_response( &ha7_response ) ) {
		return 1 ;
	}

	UCLIBCLOCK ;
	snprintf(name,INET_ADDRSTRLEN+20,"%s:%d",inet_ntoa(from.sin_addr),ntohs(ha7_response.port));
	UCLIBCUNLOCK ;

	return 0 ;
}
Exemplo n.º 11
0
GOOD_OR_BAD W1_detect(struct port_in *pin)
{
	struct connection_in * in = pin->first ;

	/* Set up low-level routines */
	pin->type = ct_none ;
	W1_setroutines(in);
	Init_Pipe( in->master.w1.netlink_pipe ) ;

	if ( pipe( in->master.w1.netlink_pipe ) != 0 ) {
		ERROR_CONNECT("W1 pipe creation error");
		Init_Pipe( in->master.w1.netlink_pipe ) ;
		return gbBAD ;
	}

	in->Adapter = adapter_w1;
	in->adapter_name = "w1";
	pin->busmode = bus_w1;
	in->master.w1.seq = SEQ_INIT;
	return gbGOOD;
}
Exemplo n.º 12
0
//open serial port ( called on head of connection_in group from com_open )
GOOD_OR_BAD serial_open(struct connection_in *connection)
{
	struct port_in * pin = connection->pown ;
	FILE_DESCRIPTOR_OR_ERROR fd = open( DEVICENAME(connection), O_RDWR | O_NONBLOCK | O_NOCTTY) ;
	pin->file_descriptor = fd ;
	if ( FILE_DESCRIPTOR_NOT_VALID( fd ) ) {
		// state doesn't change
		ERROR_DEFAULT("Cannot open port: %s Permissions problem?", SAFESTRING(DEVICENAME(connection)));
		return gbBAD;
	}

	if ( pin->state == cs_virgin ) {
		// valgrind warns about uninitialized memory in tcsetattr(), so clear all.
		memset( &(pin->dev.serial.oldSerialTio), 0, sizeof(struct termios));
		if ((tcgetattr( fd, &(pin->dev.serial.oldSerialTio) ) < 0)) {
			ERROR_CONNECT("Cannot get old port attributes: %s", SAFESTRING(DEVICENAME(connection)));
			// proceed anyway
		}
		pin->state = cs_deflowered ;
	}

	return serial_change( connection ) ;
}
Exemplo n.º 13
0
// Wait for a resolve, then return. Timeout after 2 minutes
static void ResolveWait( DNSServiceRef sref )
{
	FILE_DESCRIPTOR_OR_ERROR file_descriptor = DNSServiceRefSockFD(sref);

	if ( FILE_DESCRIPTOR_VALID(file_descriptor) ) {
		while (1) {
			fd_set readfd;
			struct timeval tv = { 120, 0 };

			FD_ZERO(&readfd);
			FD_SET(file_descriptor, &readfd);
			if (select(file_descriptor + 1, &readfd, NULL, NULL, &tv) > 0) {
				if (FD_ISSET(file_descriptor, &readfd)) {
					DNSServiceProcessResult(sref);
				}
			} else if (errno == EINTR) {
				continue;
			} else {
				ERROR_CONNECT("Resolve timeout error");
			}
			break;
		}
	}
}
Exemplo n.º 14
0
/* Try to see if there is a DS2482 device on the specified i2c bus */
static GOOD_OR_BAD DS2482_detect_single(int lowindex, int highindex, char * i2c_device, struct port_in *pin)
{
    int test_address[8] = { 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, };	// the last 4 are -800 only
    int i2c_index;
    FILE_DESCRIPTOR_OR_ERROR file_descriptor;
    struct connection_in * in = pin->first ;

    /* Sanity check */
    if ( lowindex < 0 ) {
        LEVEL_DEBUG("Bad lower bound");
        return gbBAD ;
    }
    if ( highindex >= (int) (sizeof(test_address)/sizeof(int)) ) {
        LEVEL_DEBUG("Bad upper bound");
        return gbBAD ;
    }

    /* open the i2c port */
    file_descriptor = open(i2c_device, O_RDWR);
    if ( FILE_DESCRIPTOR_NOT_VALID(file_descriptor) ) {
        ERROR_CONNECT("Could not open i2c device %s", i2c_device);
        return gbBAD;
    }

    /* Set up low-level routines */
    DS2482_setroutines(in);

    for (i2c_index = lowindex; i2c_index <= highindex; ++i2c_index) {
        int trial_address = test_address[i2c_index] ;
        /* set the candidate address */
        if (ioctl(file_descriptor, I2C_SLAVE, trial_address) < 0) {
            ERROR_CONNECT("Cound not set trial i2c address to %.2X", trial_address);
        } else {
            BYTE c;
            LEVEL_CONNECT("Found an i2c device at %s address %.2X", i2c_device, trial_address);
            /* Provisional setup as a DS2482-100 ( 1 channel ) */
            in->pown->file_descriptor = file_descriptor;
            pin->state = cs_deflowered;
            pin->type = ct_i2c ;
            in->master.i2c.i2c_address = trial_address;
            in->master.i2c.i2c_index = i2c_index;
            in->master.i2c.index = 0;
            in->master.i2c.channels = 1;
            in->master.i2c.current = 0;
            in->master.i2c.head = in;
            in->adapter_name = "DS2482-100";
            in->master.i2c.configreg = 0x00 ;	// default configuration setting desired
            if ( Globals.i2c_APU ) {
                in->master.i2c.configreg |= DS2482_REG_CFG_APU ;
            }
            if ( Globals.i2c_PPM ) {
                in->master.i2c.configreg |= DS2482_REG_CFG_PPM ;
            }
            in->Adapter = adapter_DS2482_100;

            /* write the RESET code */
            if (i2c_smbus_write_byte(file_descriptor, DS2482_CMD_RESET)	// reset
                    || BAD(DS2482_readstatus(&c, file_descriptor, DS2482_Chip_reset_usec))	// pause .5 usec then read status
                    || (c != (DS2482_REG_STS_LL | DS2482_REG_STS_RST))	// make sure status is properly set
               ) {
                LEVEL_CONNECT("i2c device at %s address %.2X cannot be reset. Not a DS2482.", i2c_device, trial_address);
                continue;
            }
            LEVEL_CONNECT("i2c device at %s address %.2X appears to be DS2482-x00", i2c_device, trial_address);
            in->master.i2c.configchip = 0x00;	// default configuration register after RESET
            // Note, only the lower nibble of the device config stored

            // Create name
            SAFEFREE( DEVICENAME(in) ) ;
            DEVICENAME(in) = owmalloc( strlen(i2c_device) + 10 ) ;
            if ( DEVICENAME(in) ) {
                UCLIBCLOCK;
                snprintf(DEVICENAME(in), strlen(i2c_device) + 10, "%s:%.2X", i2c_device, trial_address);
                UCLIBCUNLOCK;
            }

            /* Now see if DS2482-100 or DS2482-800 */
            return HeadChannel(in);
        }
    }
    /* fell though, no device found */
    COM_close( in ) ;
    return gbBAD;
}
Exemplo n.º 15
0
//change serial port settings
GOOD_OR_BAD serial_change(struct connection_in *connection)
{
	struct port_in * pin = connection->pown ;
	struct termios newSerialTio;	/*new serial port settings */
	FILE_DESCRIPTOR_OR_ERROR fd = pin->file_descriptor ;
	size_t baud = pin->baud ;

	// read the attribute structure
	// valgrind warns about uninitialized memory in tcsetattr(), so clear all.
	memset(&newSerialTio, 0, sizeof(struct termios));
	if ((tcgetattr( fd, &newSerialTio) < 0)) {
		ERROR_CONNECT("Cannot get existing port attributes: %s", SAFESTRING(DEVICENAME(connection)));
	}
	
	// set baud in structure
	if (cfsetospeed(&newSerialTio, baud) < 0 || cfsetispeed(&newSerialTio, baud) < 0) {
		ERROR_CONNECT("Trouble setting port speed: %s", SAFESTRING(DEVICENAME(connection)));
		cfsetospeed(&newSerialTio, B9600) ;
		cfsetispeed(&newSerialTio, B9600) ;
		pin->baud = B9600 ;
	}

	// Set to non-canonical mode, and no RTS/CTS handshaking
	newSerialTio.c_iflag &= ~(BRKINT | ICRNL | IGNCR | INLCR | INPCK | ISTRIP | IXON | IXOFF | PARMRK);
	newSerialTio.c_iflag |= IGNBRK | IGNPAR;

	newSerialTio.c_oflag &= ~(OPOST);

	newSerialTio.c_cflag &= ~ HUPCL ;
	newSerialTio.c_cflag |= (CLOCAL | CREAD);

	switch( pin->flow ) {
		case flow_hard:
			newSerialTio.c_cflag |= CRTSCTS ;
			break ;
		case flow_none:
			newSerialTio.c_cflag &= ~CRTSCTS;
			break ;
		case flow_soft:
		default:
			LEVEL_DEBUG("Unsupported COM port flow control");
			return -ENOTSUP ;
	}

	// set bit length
	newSerialTio.c_cflag &= ~ CSIZE ;
	switch (pin->bits) {
		case 5:
			newSerialTio.c_cflag |= CS5 ;
			break ;
		case 6:
			newSerialTio.c_cflag |= CS6 ;
			break ;
		case 7:
			newSerialTio.c_cflag |= CS7 ;
			break ;
		case 8:
		default:
			newSerialTio.c_cflag |= CS8 ;
			break ;
	}

	// parity
	switch (pin->parity) {
		case parity_none:
			newSerialTio.c_cflag &= ~PARENB ;
			break ;
		case parity_even:
			newSerialTio.c_cflag |= PARENB ;
			newSerialTio.c_cflag &= ~( PARODD | CMSPAR ) ;
			break ;
		case parity_odd:
			newSerialTio.c_cflag |= PARENB | PARODD;
			newSerialTio.c_cflag &= ~CMSPAR ;
			break ;
		case parity_mark:
			newSerialTio.c_cflag |= PARENB | PARODD | CMSPAR;
			break ;
	}

	// stop bits
	switch (pin->stop) {
		case stop_15:
			LEVEL_DEBUG("1.5 Stop bits not supported");
			pin->stop = stop_1 ;
			// fall through
		case stop_1:
			newSerialTio.c_cflag &= ~CSTOPB ;
			break ;
		case stop_2:
			newSerialTio.c_cflag |= CSTOPB ;
			break ;
	}


	newSerialTio.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL | ICANON | IEXTEN | ISIG);
	newSerialTio.c_cc[VMIN] = pin->vmin;
	newSerialTio.c_cc[VTIME] = pin->vtime;
	if (tcsetattr( fd, TCSAFLUSH, &newSerialTio)) {
		ERROR_CONNECT("Cannot set port attributes: %s", SAFESTRING(DEVICENAME(connection)));
		return gbBAD;
	}
	tcflush( fd, TCIOFLUSH);
	return gbGOOD;
}