예제 #1
0
static int invariant(const struct telnet_session_s *t)
{
	if (t == NULL) {
		return 0;
	}
	if (FILE_DESCRIPTOR_NOT_VALID(t->in_fd)) {
		return 0;
	}
	if ((t->in_take < 0) || (t->in_take >= BUF_LEN)) {
		return 0;
	}
	if ((t->in_add < 0) || (t->in_add >= BUF_LEN)) {
		return 0;
	}
	if ((t->in_buflen < 0) || (t->in_buflen > BUF_LEN)) {
		return 0;
	}

	switch (t->in_status) {
	case NORMAL:
		break;
	case GOT_IAC:
		break;
	case GOT_WILL:
		break;
	case GOT_WONT:
		break;
	case GOT_DO:
		break;
	case GOT_DONT:
		break;
	case GOT_CR:
		break;
	default:
		return 0;
	}

	if (FILE_DESCRIPTOR_NOT_VALID(t->out_fd)) {
		return 0;
	}
	if ((t->out_take < 0) || (t->out_take >= BUF_LEN)) {
		return 0;
	}
	if ((t->out_add < 0) || (t->out_add >= BUF_LEN)) {
		return 0;
	}
	if ((t->out_buflen < 0) || (t->out_buflen > BUF_LEN)) {
		return 0;
	}

	return 1;
}
예제 #2
0
파일: ow_com_read.c 프로젝트: M-o-a-T/owfs
/* Called on head of multibus group */
SIZE_OR_ERROR COM_read_with_timeout( BYTE * data, size_t length, struct connection_in *connection)
{
	struct port_in * pin ;
	
	if ( length == 0 ) {
		return 0 ;
	}
	
	if ( connection == NO_CONNECTION || data == NULL ) {
		// bad parameters
		return -EIO ;
	}
	pin = connection->pown ;

	// unlike write or open, a closed connection isn't automatically opened.
	// the reason is that reopening won't have the data waiting. We really need
	// to restart the transaction from the "write" portion
	if ( FILE_DESCRIPTOR_NOT_VALID( pin->file_descriptor ) ) {
		return -EBADF ;
	} else {
		size_t actual_size ;
		ZERO_OR_ERROR zoe = tcp_read( pin->file_descriptor, data, length, &(pin->timeout), &actual_size ) ;

		if ( zoe == -EBADF ) {
			COM_close(connection) ;
			return zoe ;
		} else {
			return actual_size ;
		}
	}
}
예제 #3
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) ) ;
}
예제 #4
0
파일: ow_kevent.c 프로젝트: stromnet/owfs
void Config_Monitor_Add( const char * filename )
{
	FILE_DESCRIPTOR_OR_ERROR fd ;
	struct kevent ke ;
	if ( config_monitor_num_files == 0 ) {
		// first one
		kq = kqueue() ;
		if ( kq < 0 ) {
			LEVEL_DEBUG("Could not create a kevent queue (kqueue)" ) ;
			return ;
		}
	}
	fd = open( filename, O_EVTONLY ) ;
	if ( FILE_DESCRIPTOR_NOT_VALID( fd ) ) {
		LEVEL_DEBUG("Can't open %s for monitoring", filename ) ;
		return ;
	}
	EV_SET( &ke, fd, EVFILT_VNODE, EV_ADD, NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_RENAME, 0, NULL ) ;
	if ( kevent( kq, &ke, 1, NULL, 0, NULL ) != 0 ) {
		LEVEL_DEBUG("Couldn't add %s to kqueue for monitoring",filename ) ;
	} else {
		++ config_monitor_num_files ;
		LEVEL_DEBUG("Added %s to kqueue", filename ) ;
	}
}
예제 #5
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 ;
}
예제 #6
0
static GOOD_OR_BAD DS2482_channel_select(struct connection_in * in)
{
    struct connection_in *head = in->master.i2c.head;
    int chan = in->master.i2c.index;
    FILE_DESCRIPTOR_OR_ERROR file_descriptor = in->pown->file_descriptor;

    /*
    	Write and verify codes for the CHANNEL_SELECT command (DS2482-800 only).
    	To set the channel, write the value at the index of the channel.
    	Read and compare against the corresponding value to verify the change.
    */
    static const BYTE W_chan[8] = { 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87 };
    static const BYTE R_chan[8] = { 0xB8, 0xB1, 0xAA, 0xA3, 0x9C, 0x95, 0x8E, 0x87 };

    if ( FILE_DESCRIPTOR_NOT_VALID(file_descriptor) ) {
        LEVEL_CONNECT("Calling a closed i2c channel (%d) "I2Cformat" ", chan,I2Cvar(in));
        return gbBAD;
    }

    /* Already properly selected? */
    /* All `100 (1 channel) will be caught here */
    if (chan != head->master.i2c.current) {
        int read_back;

        /* Select command */
        if (i2c_smbus_write_byte_data(file_descriptor, DS2482_CMD_CHANNEL_SELECT, W_chan[chan]) < 0) {
            LEVEL_DEBUG("Channel select set error");
            return gbBAD;
        }

        /* Read back and confirm */
        read_back = i2c_smbus_read_byte(file_descriptor);
        if (read_back < 0) {
            LEVEL_DEBUG("Channel select get error");
            return gbBAD; // flag for DS2482-100 vs -800 detection
        }
        if (((BYTE) read_back) != R_chan[chan]) {
            LEVEL_DEBUG("Channel selected doesn't match");
            return gbBAD; // flag for DS2482-100 vs -800 detection
        }

        /* Set the channel in head */
        head->master.i2c.current = in->master.i2c.index;
    }

    /* Now check the configuration register */
    /* This is since configuration is per chip, not just channel */
    if (in->master.i2c.configreg != head->master.i2c.configchip) {
        return SetConfiguration(in->master.i2c.configreg, in);
    }

    return gbGOOD;
}
예제 #7
0
파일: ow_com_read.c 프로젝트: M-o-a-T/owfs
/* Called on head of multibus group */
GOOD_OR_BAD COM_read( BYTE * data, size_t length, struct connection_in *connection)
{
	struct port_in * pin ;
	
	if ( length == 0 ) {
		return gbGOOD ;
	}
	
	if ( connection == NO_CONNECTION || data == NULL ) {
		// bad parameters
		return gbBAD ;
	}
	pin = connection->pown ;

	// unlike write or open, a closed connection isn't automatically opened.
	// the reason is that reopening won't have the data waiting. We really need
	// to restart the transaction from the "write" portion
	if ( FILE_DESCRIPTOR_NOT_VALID( pin->file_descriptor ) ) {
		return gbBAD ;
	}

	switch ( pin->type ) {
		// test the type of connection
		case ct_unknown:
		case ct_none:
			LEVEL_DEBUG("Unknown type");
			break ;
		case ct_telnet:
			return telnet_read( data, length, connection ) ;
		case ct_tcp:
			// network is ok
			return COM_read_get_size( data, length, connection ) == (ssize_t) length ? gbGOOD : gbBAD ;
		case ct_i2c:
		case ct_netlink:
		case ct_usb:
			LEVEL_DEBUG("Unimplemented");
			break ; 
		case ct_serial:
		// serial is ok
		// printf("Serial read fd=%d length=%d\n",pin->file_descriptor, (int) length);
		{
			ssize_t actual = COM_read_get_size( data, length, connection ) ;
			if ( FILE_DESCRIPTOR_VALID( pin->file_descriptor ) ) {
				// tcdrain only works on serial conections
				tcdrain( pin->file_descriptor );
				return actual == (ssize_t) length ? gbGOOD : gbBAD ;
			}
			break ;
		}
	}
	return gbBAD ;
}
예제 #8
0
/* Device-specific functions */
GOOD_OR_BAD W1_monitor_detect(struct port_in *pin)
{
	struct connection_in * in = pin->first ;
	struct timeval tvslack = { 1, 0 } ; // 1 second
	
	pin->file_descriptor = FILE_DESCRIPTOR_BAD;
	pin->type = ct_none ;
	in->iroutines.detect = W1_monitor_detect;
	in->Adapter = adapter_w1_monitor;	/* OWFS assigned value */
	in->iroutines.reset = NO_RESET_ROUTINE;
	in->iroutines.next_both = NO_NEXT_BOTH_ROUTINE;
	in->iroutines.PowerByte = NO_POWERBYTE_ROUTINE;
	in->iroutines.ProgramPulse = NO_PROGRAMPULSE_ROUTINE;
	in->iroutines.sendback_data = NO_SENDBACKDATA_ROUTINE;
	in->iroutines.sendback_bits = NO_SENDBACKBITS_ROUTINE;
	in->iroutines.select = NO_SELECT_ROUTINE;
	in->iroutines.select_and_sendback = NO_SELECTANDSENDBACK_ROUTINE;
	in->iroutines.set_config = NO_SET_CONFIG_ROUTINE;
	in->iroutines.get_config = NO_GET_CONFIG_ROUTINE;
	in->iroutines.reconnect = NO_RECONNECT_ROUTINE;
	in->iroutines.close = W1_monitor_close;
	in->iroutines.verify = NO_VERIFY_ROUTINE ;
	in->iroutines.flags = ADAP_FLAG_sham;
	in->adapter_name = "W1 monitor";
	pin->busmode = bus_w1_monitor ;
	
	RETURN_BAD_IF_BAD( w1_monitor_in_use(in) ) ;
	
	// Initial setup
	Inbound_Control.w1_monitor = in ; // essentially a global pointer to the w1_monitor entry
	_MUTEX_INIT(in->master.w1_monitor.seq_mutex);
	_MUTEX_INIT(in->master.w1_monitor.read_mutex);

	timernow( &(in->master.w1_monitor.last_read) );
	timeradd( &(in->master.w1_monitor.last_read), &tvslack, &(in->master.w1_monitor.last_read) );

	in->master.w1_monitor.seq = SEQ_INIT ;
	in->master.w1_monitor.pid = 0 ;
	
	w1_bind(in) ; // sets in->file_descriptor
	if ( FILE_DESCRIPTOR_NOT_VALID( in->pown->file_descriptor ) ) {
		ERROR_DEBUG("Netlink problem -- are you root?");
		Inbound_Control.w1_monitor = NO_CONNECTION ;
		return gbBAD ;
	}
	
	return W1_Browse() ; // creates thread that runs forever.
}
예제 #9
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;
}
예제 #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 ;
}
예제 #11
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 ) ;
}
예제 #12
0
파일: ow_k1wm.c 프로젝트: M-o-a-T/owfs
// bus locking at a higher level
GOOD_OR_BAD K1WM_detect(struct port_in *pin)
{
	struct connection_in * in = pin->first ;
	long long int prebase ;
	unsigned int prechannels_count;
	void * mm ;
	FILE_DESCRIPTOR_OR_ERROR mem_fd ;
	const char * mem_device = "/dev/uio0";

	if (pin->init_data == NULL) {
		LEVEL_DEFAULT("K1WM needs a memory location");
		return gbBAD;
	}

	in->Adapter = adapter_k1wm ;
	in->master.ds1wm.longline = 0 ; // longline timing
	// in->master.ds1wm.frequency = 0 ; // unused in k1wm
	in->master.ds1wm.presence_mask = 1 ; // pulse presence mask
	in->master.ds1wm.active_channel = 0;
	in->master.ds1wm.channels_count = 1;

	int param_count = sscanf( pin->init_data, "%lli,%u", &prebase, &prechannels_count);
	if ( param_count < 1 || param_count > 2) {
		LEVEL_DEFAULT("K1WM: Could not interpret <%s> as a memory address:channel_count pair", pin->init_data ) ;
		return gbBAD ;
	}

	in->master.ds1wm.channels_count = prechannels_count ;
	in->master.ds1wm.base = prebase ; // convert types long long int -> off_t
	if ( in->master.ds1wm.base == 0 ) {
		LEVEL_DEFAULT("K1WM: Illegal address 0x0000 from <%s>", pin->init_data ) ;
		return gbBAD ;
	}
	LEVEL_DEBUG("K1WM at address %p",(void *)in->master.ds1wm.base);
	LEVEL_DEBUG("K1WM channels: %u",in->master.ds1wm.channels_count);

	read_device_map_size(mem_device, &(in->master.ds1wm.mm_size));
	read_device_map_offset(mem_device, &(in->master.ds1wm.page_start));

	// open /dev/uio0
	mem_fd = open( mem_device, O_RDWR | O_SYNC ) ;

	if ( FILE_DESCRIPTOR_NOT_VALID(mem_fd) ) {
		LEVEL_DEFAULT("K1WM: Cannot open memory directly -- permissions problem?");
		return gbBAD ;
	}

	mm = mmap( NULL, in->master.ds1wm.mm_size, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, in->master.ds1wm.page_start );

	close(mem_fd) ; // no longer needed

	if ( mm == MAP_FAILED ) {
		LEVEL_DEFAULT("K1WM: Cannot map memory") ;
		return gbBAD ;
	}

	in->master.ds1wm.mm = mm ;

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

	// Add channels
	K1WM_create_channels(in, in->master.ds1wm.channels_count);

	return K1WM_setup(in) ;
}
예제 #13
0
파일: ow_tcp_read.c 프로젝트: M-o-a-T/owfs
/* return < 0 if failure */
ZERO_OR_ERROR tcp_read(FILE_DESCRIPTOR_OR_ERROR file_descriptor, BYTE * buffer, size_t requested_size, const struct timeval * ptv, size_t * chars_in)
{
	size_t to_be_read = requested_size ;

	if ( FILE_DESCRIPTOR_NOT_VALID( file_descriptor ) ) {
		return -EBADF ;
	}

	LEVEL_DEBUG("attempt %d bytes Time: "TVformat,(int)requested_size, TVvar(ptv) ) ;
	*chars_in = 0 ;
	while (to_be_read > 0) {
		int select_result;
		fd_set readset;
		struct timeval tv ;

		/* Initialize readset */
		FD_ZERO(&readset);
		FD_SET(file_descriptor, &readset);

		/* Read if it doesn't timeout first */
		timercpy( &tv, ptv ) ;
		select_result = select(file_descriptor + 1, &readset, NULL, NULL, &tv);
		if (select_result > 0) {
			ssize_t read_result;

			/* Is there something to read? */
			if (FD_ISSET(file_descriptor, &readset) == 0) {
				LEVEL_DEBUG("tcp_error -- nothing avialable to read");
				return -EBADF ;	/* error */
			}
			errno = 0 ;
			read_result = read(file_descriptor, &buffer[*chars_in], to_be_read) ;
			if ( read_result < 0 ) {
				if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
					read_result = 0;	/* and call read() again */
				} else {
					LEVEL_DATA("Network data read error errno=%d %s", errno, strerror(errno));
					STAT_ADD1(NET_read_errors);
					return -EBADF ;
				}
			} else if (read_result == 0) {
				break;			/* EOF */
			}
			TrafficInFD("NETREAD", &buffer[*chars_in], read_result, file_descriptor ) ;
			to_be_read -= read_result;
			*chars_in += read_result ;
		} else if (select_result < 0) {	/* select error */
			if (errno == EINTR) {
				/* select() was interrupted, try again */
				continue;
			}
			ERROR_DATA("Select error");
			return -EBADF;
		} else {				/* timed out */
			LEVEL_CONNECT("TIMEOUT after %d bytes", requested_size - to_be_read);
			return -EAGAIN;
		}
	}
	LEVEL_DEBUG("read: %d - %d = %d",(int)requested_size, (int) to_be_read, (int) (requested_size-to_be_read) ) ;
	return 0;
}
예제 #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;
}
예제 #15
0
파일: ow_ds1wm.c 프로젝트: M-o-a-T/owfs
// bus locking at a higher level
GOOD_OR_BAD DS1WM_detect(struct port_in *pin)
{
	struct connection_in * in = pin->first ;
	long long int prebase ;
	off_t base ;
	void * mm ;
	FILE_DESCRIPTOR_OR_ERROR mem_fd ;
	const char * mem_device = "/dev/mem";

	
	in->Adapter = adapter_ds1wm ;
	in->master.ds1wm.longline = 0 ; // longline timing
	in->master.ds1wm.frequency = 10000000 ; // 10MHz
	in->master.ds1wm.presence_mask = 1 ; // pulse presence mask
	in->master.ds1wm.active_channel = 0; // always for ds1wm
	in->master.ds1wm.channels_count = 1; // always for ds1wm

	if (pin->init_data == NULL) {
		LEVEL_DEFAULT("DS1WM needs a memory location");
		return gbBAD;
	}

	if ( sscanf( pin->init_data, "%lli", &prebase ) != 1 ) {
		LEVEL_DEFAULT("DS1WM: Could not interpret <%s> as a memory address", pin->init_data ) ;
		return gbBAD ;
	}
	base = prebase ; // convert types long long int -> off_t
	if ( base == 0 ) {
		LEVEL_DEFAULT("DS1WM: Illegal address 0x0000 from <%s>", pin->init_data ) ;
		return gbBAD ;
	}
	LEVEL_DEBUG("DS1WM at address %p",(void *)base);
	
	in->master.ds1wm.mm_size = (size_t) getpagesize() ;
	in->master.ds1wm.base = base ;
	in->master.ds1wm.page_offset = base % in->master.ds1wm.mm_size ;
	in->master.ds1wm.page_start = base - in->master.ds1wm.page_offset ;
	
	// open /dev/mem
	mem_fd = open( mem_device, O_RDWR | O_SYNC ) ;
	
	if ( FILE_DESCRIPTOR_NOT_VALID(mem_fd) ) {
		LEVEL_DEFAULT("DS1WM: Cannot open memory directly -- permissions problem?");
		return gbBAD ;
	}
	
	mm = mmap( NULL, in->master.ds1wm.mm_size, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, in->master.ds1wm.page_start );
	
	close(mem_fd) ; // no longer needed
	
	if ( mm == MAP_FAILED ) {
		LEVEL_DEFAULT("DS1WM: Cannot map memory") ;
		return gbBAD ;
	}
	
	in->master.ds1wm.mm = mm ;

	/* Set up low-level routines */
	DS1WM_setroutines(in);
	in->adapter_name = "DS1WM";

	return DS1WM_setup(in) ;
}
예제 #16
0
/* Read from a telnet device
*/
GOOD_OR_BAD telnet_read(BYTE * buf, const size_t size, struct connection_in *in)
{
	struct port_in * pin ;
	// temporary buffer (add some extra space)
	BYTE readin_buf[size+2] ;

	// state machine for telnet escape chars
	// handles TELNET protocol, specifically RFC854
	// http://www.ietf.org/rfc/rfc854.txt
	enum {
		telnet_regular,
		telnet_iac,
		telnet_sb,
		telnet_sb_opt,
		telnet_sb_val,
		telnet_sb_iac,
		telnet_will,
		telnet_wont,
		telnet_do,
		telnet_dont,
	} telnet_read_state = telnet_regular ;

	size_t actual_readin = 0 ;
	size_t current_index = 0 ;
	size_t still_needed = size ;

	// test inputs
	if ( size == 0 ) {
		return gbGOOD ;
	}
	
	if ( in == NO_CONNECTION ) {
		return gbBAD ;
	}
	pin = in->pown ;

	if ( FILE_DESCRIPTOR_NOT_VALID(pin->file_descriptor) ) {
		return gbBAD ;
	}
	
	// loop and look for escape sequances
	while ( still_needed > 0 ) {

		// see if the state requires a longer read than currently scheduled
		size_t minimum_chars  = still_needed ;
		switch( telnet_read_state ) {
			case telnet_sb:
				minimum_chars += 4 ;
				break ;
			case telnet_sb_opt:
				minimum_chars += 3 ;
				break ;
			case telnet_sb_val:
				minimum_chars += 2 ;
				break ;
			case telnet_iac:
			case telnet_sb_iac:
			case telnet_will:
			case telnet_wont:
			case telnet_do:
			case telnet_dont:
				minimum_chars += 1 ;
				break ;
			case telnet_regular:
				break ;
		}

		if ( current_index >= actual_readin ) {
			// need to read more -- just read what we think we need -- escape chars may require repeat
			if ( tcp_read( pin->file_descriptor, readin_buf, minimum_chars, &(pin->timeout), &actual_readin) < 0 ) {
				LEVEL_DEBUG("tcp seems closed") ;
				Test_and_Close( &(pin->file_descriptor) ) ;
				return gbBAD ;
			}

			if (actual_readin < minimum_chars) {
				LEVEL_CONNECT("Telnet (ethernet) error");
				Test_and_Close( &(pin->file_descriptor) ) ;
				return gbBAD;
			}

			current_index = 0 ;
		}

		switch ( telnet_read_state ) {
			case telnet_regular :
				if ( readin_buf[current_index] == TELNET_IAC ) {
						if (Globals.traffic) {
							LEVEL_DEBUG("TELNET: IAC");
						}
					// starting escape sequence
					// following bytes will better characterize
					telnet_read_state = telnet_iac ;
				} else {
					// normal processing
					// move byte to response and decrement needed bytes
					// stay in current state
					buf[size - still_needed] = readin_buf[current_index] ;
					-- still_needed ;
				}
				break ;
			case telnet_iac:
				//printf("TELNET: IAC %d\n",readin_buf[current_index]);
				switch ( readin_buf[current_index] ) {
					case TELNET_EOF:
					case TELNET_SUSP:
					case TELNET_ABORT:
					case TELNET_EOR:
					case TELNET_SE:
					case TELNET_NOP:
					case TELNET_DM:
					case TELNET_BREAK:
					case TELNET_IP:
					case TELNET_AO:
					case TELNET_AYT:
					case TELNET_EC:
					case TELNET_EL:
					case TELNET_GA:
						// 2 byte sequence
						// just read 2nd character
						if (Globals.traffic) {
							LEVEL_DEBUG("TELNET: End 2-byte sequence");
						}
						telnet_read_state = telnet_regular ;
						break ;
					case TELNET_SB:
						// multibyte squence
						// start scanning for 0xF0
						telnet_read_state = telnet_sb ;
						break ;
					case TELNET_WILL:
						// 3 byte sequence
						// just read 2nd char
						telnet_read_state = telnet_will ;
						break ;
					case TELNET_WONT:
						// 3 byte sequence
						// just read 2nd char
						telnet_read_state = telnet_wont ;
						break ;
					case TELNET_DO:
						// 3 byte sequence
						// just read 2nd char
						telnet_read_state = telnet_do ;
						break ;
					case TELNET_DONT:
						// 3 byte sequence
						// just read 2nd char
						telnet_read_state = telnet_dont ;
						break ;
					case TELNET_IAC:
						// escape the FF character
						// make this a single regular FF char
						buf[size - still_needed] = 0xFF ;
						-- still_needed ;
						if (Globals.traffic) {
							LEVEL_DEBUG("TELNET: FF escape sequence");
						}
						telnet_read_state = telnet_regular ;
						break ;
					default:
						LEVEL_DEBUG("Unexpected telnet sequence");
						return gbBAD ;
				}
				break ;
			case telnet_sb:
				switch ( readin_buf[current_index] ) {
					case TELNET_IAC:
						LEVEL_DEBUG("Unexpected telnet sequence");
						return gbBAD ;
					default:
						//printf("TELNET: IAC SB opt=%d\n",readin_buf[current_index]);
						// stay in this mode
						telnet_read_state = telnet_sb_opt ;
						break ;
				}
				break ;
			case telnet_sb_opt:
				switch ( readin_buf[current_index] ) {
					case TELNET_IAC:
						LEVEL_DEBUG("Unexpected telnet sequence");
						return gbBAD ;
					default:
						//printf("TELNET: IAC SB sub_opt=%d\n",readin_buf[current_index]);
						// stay in this mode
						telnet_read_state = telnet_sb_val ;
						break ;
				}
				break ;
			case telnet_sb_val:
				switch ( readin_buf[current_index] ) {
					case TELNET_IAC:
						// stay in this mode
						telnet_read_state = telnet_sb_iac ;
						break ;
					default:
						//printf("TELNET: IAC SB val=%d\n",readin_buf[current_index]);
						// stay in this mode
						break ;
				}
				break ;
			case telnet_sb_iac:
				switch ( readin_buf[current_index] ) {
					case TELNET_SE:
						//printf("TELNET: IAC SE\n");
						if (Globals.traffic) {
							LEVEL_DEBUG("TELNET: End multi-byte sequence");
						}
						telnet_read_state = telnet_regular ;
						break ;					
					default:
						LEVEL_DEBUG("Unexpected telnet sequence");
						return gbBAD ;
				}
				break ;
			case telnet_will:
				//printf("TELNET: IAC WILL %d\n",readin_buf[current_index]);
				// 3 byte sequence
				// now reading 3rd char
				if (Globals.traffic) {
					LEVEL_DEBUG("TELNET: End 3-byte sequence");
				}
				telnet_read_state = telnet_regular ;
				break ;
			case telnet_wont:
				//printf("TELNET: IAC WONT %d\n",readin_buf[current_index]);
				// 3 byte sequence
				// now reading 3rd char
				if (Globals.traffic) {
					LEVEL_DEBUG("TELNET: End 3-byte sequence");
				}
				telnet_read_state = telnet_regular ;
				break ;
			case telnet_do:
				//printf("TELNET: IAC DO %d\n",readin_buf[current_index]);
				// 3 byte sequence
				// now reading 3rd char
				if (Globals.traffic) {
					LEVEL_DEBUG("TELNET: End 3-byte sequence");
				}
				telnet_read_state = telnet_regular ;
				break ;
			case telnet_dont:
				// 3 byte sequence
				// now reading 3rd char
				if (Globals.traffic) {
					LEVEL_DEBUG("TELNET: End 3-byte sequence");
				}
				telnet_read_state = telnet_regular ;
				break ;
		}
		++ current_index ;
	}
	return gbGOOD ;
}