Exemple #1
0
/* Moves new to old tree, initializes new tree, and clears former old tree location */
static void FlipTree( void )
{
	void * flip = cache.temporary_tree_old; // old old saved for later clearing
	void * flip_alias = cache.temporary_alias_tree_old; // old old saved for later clearing

	/* Flip caches! old = new. New truncated, reset time and counters and flag */
	LEVEL_DEBUG("Flipping cache tree (purging timed-out data)");

	// move "new" pointers to "old"
	cache.temporary_tree_old = cache.temporary_tree_new;
	cache.old_ram_size = cache.new_ram_size;
	cache.temporary_alias_tree_old = cache.temporary_alias_tree_new;

	// New cache setup
	cache.temporary_tree_new = NULL;
	cache.temporary_alias_tree_new = NULL;
	cache.new_ram_size = 0;
	cache.added = 0;

	// set up "old" cache times
	cache.time_retired = NOW_TIME;
	cache.time_to_kill = cache.time_retired + cache.retired_lifespan;

	// delete really old tree
	LEVEL_DEBUG("flip cache. tdestroy() will be called.");
	SAFETDESTROY( flip, owfree_func);
	SAFETDESTROY( flip_alias, owfree_func);
	STATLOCK;
	++cache_flips;			/* statistics */
	memcpy(&old_avg, &new_avg, sizeof(struct average));
	AVERAGE_CLEAR(&new_avg);
	STATUNLOCK;
}
Exemple #2
0
static GOOD_OR_BAD LINK_detect_serial(struct connection_in * in)
{
	struct port_in * pin = in->pown ;
	/* Set up low-level routines */
	LINK_setroutines(in);
	pin->timeout.tv_sec = Globals.timeout_serial ;
	pin->timeout.tv_usec = 0 ;

	/* Open the com port */
	RETURN_BAD_IF_BAD(COM_open(in)) ;
	
	//COM_break( in ) ;
	LEVEL_DEBUG("Slurp in initial bytes");
	LINK_slurp( in ) ;
	UT_delay(100) ; // based on http://morpheus.wcf.net/phpbb2/viewtopic.php?t=89&sid=3ab680415917a0ebb1ef020bdc6903ad
	LINK_slurp( in ) ;
	
	RETURN_GOOD_IF_GOOD( LINK_version(in) ) ;
	LEVEL_DEFAULT("LINK detection error");
	
	serial_powercycle(in) ;
	LEVEL_DEBUG("Slurp in initial bytes");
	LINK_slurp( in ) ;
	UT_delay(100) ; // based on http://morpheus.wcf.net/phpbb2/viewtopic.php?t=89&sid=3ab680415917a0ebb1ef020bdc6903ad
	LINK_slurp( in ) ;
	
	RETURN_GOOD_IF_GOOD( LINK_version(in) ) ;
	LEVEL_DEFAULT("LINK detection error");
	COM_close(in) ;
	return gbBAD;
}
/* Use an single OWQ as a template for the aggregate one */
struct one_wire_query * OWQ_create_aggregate( struct one_wire_query * owq_single )
{
    int sz = sizeof( struct one_wire_query ) + OWQ_DEFAULT_READ_BUFFER_SIZE;
	struct one_wire_query * owq_all = owmalloc( sz );
	
	LEVEL_DEBUG("%s with extension ALL", PN(owq_single)->path);

	if ( owq_all == NO_ONE_WIRE_QUERY) {
		LEVEL_DEBUG("No memory to create object for extension ALL") ;
		return NO_ONE_WIRE_QUERY ;
	}
	
	memset(owq_all, 0, sz);
	OWQ_cleanup(owq_all) = owq_cleanup_owq ;
	
	memcpy( PN(owq_all), PN(owq_single), sizeof(struct parsedname) ) ;
	PN(owq_all)->extension = EXTENSION_ALL ;
	OWQ_buffer(owq_all) = (char *) (& owq_all[1]) ; // point just beyond the one_wire_query struct
	OWQ_size(owq_all) = OWQ_DEFAULT_READ_BUFFER_SIZE ;
	OWQ_offset(owq_all) = 0 ;
	if ( BAD( OWQ_allocate_array(owq_all)) ) {
		OWQ_destroy(owq_all);
		return NO_ONE_WIRE_QUERY ;
	}
	return owq_all ;
}
static GOOD_OR_BAD Bundle_pack(const struct transaction_log *tl, const struct parsedname *pn)
{
	const struct transaction_log *t_index;
	struct transaction_bundle s_tb;
	struct transaction_bundle *tb = &s_tb;

	Bundle_init(tb, pn);

	for (t_index = tl; t_index->type != trxn_end; ++t_index) {
		switch (Pack_item(t_index, tb)) {
		case gbGOOD:
			LEVEL_DEBUG("Item added");
			break;
		case gbBAD:
			LEVEL_DEBUG("Item cannot be bundled");
			RETURN_BAD_IF_BAD(Bundle_ship(tb, pn)) ;
			RETURN_BAD_IF_BAD(BUS_transaction_single(t_index, pn)) ;
			break;
		case gbOTHER:
			LEVEL_DEBUG("Item too big");
			RETURN_BAD_IF_BAD(Bundle_ship(tb, pn)) ;
			if ( GOOD( Pack_item(t_index, tb) ) ) {
				break;
			}
			RETURN_BAD_IF_BAD(BUS_transaction_single(t_index, pn)) ;
			break;
		}
	}
	return Bundle_ship(tb, pn);
}
Exemple #5
0
static void AddPropertyToTree( char * s_property, char * s_family, enum ft_format s_format, size_t s_array, enum ag_combined s_combined, enum ag_index s_index_type, size_t s_length, enum fc_change s_change, char * s_read, char * s_write, char * s_data, char * s_other, enum external_type et )
{
	struct property_node * n  ;
	struct {
		struct property_node * key ;
		char other[0] ;
	} * opaque ;
	
	NonNull( s_property )
	NonNull( s_family )
	NonNull( s_read )
	NonNull( s_write )
	NonNull( s_data )
	NonNull( s_other )

	n = create_property_node( s_property, s_family, s_format, s_array, s_combined, s_index_type, s_length, s_change, s_read, s_write, s_data, s_other, et ) ;
	opaque = tsearch( (void *) n, &property_tree, property_compare ) ;
	
	if ( opaque->key != n ) {
		// already exists
		LEVEL_DEBUG("Duplicate property entry: %s,%s,%s,%s,%s,%s",s_property,s_family,s_read,s_write,s_data,s_other);
		owfree( n ) ;
	} else {
		LEVEL_DEBUG("New property entry: %s,%s,%s,%s,%s,%s",s_property,s_family,s_read,s_write,s_data,s_other);
	}		
}
Exemple #6
0
static enum search_status LINK_next_both(struct device_search *ds, const struct parsedname *pn)
{
	struct connection_in * in = pn->selected_connection ;

	//Special case for DS2409 hub, use low-level code
	if ( pn->ds2409_depth>0 ) {
		return search_error ;
	}

	if (ds->LastDevice) {
		return search_done;
	}

	if (ds->index == -1) {
		if ( BAD(LINK_directory(ds, in)) ) {
			return search_error;
		}
	}

	// LOOK FOR NEXT ELEMENT
	++ds->index;
	LEVEL_DEBUG("Index %d", ds->index);

	switch ( DirblobGet(ds->index, ds->sn, &(ds->gulp) ) ) {
		case 0:
			LEVEL_DEBUG("SN found: " SNformat "", SNvar(ds->sn));
			return search_good;
		case -ENODEV:
		default:
			ds->LastDevice = 1;
			LEVEL_DEBUG("SN finished");
			return search_done;
	}
}
Exemple #7
0
static GOOD_OR_BAD read_device_map_offset(const char *device_name, off_t *offset)
{
	const unsigned char path_length = 100;
	FILE* file;
	unsigned int preoffset;

	// Get device filename (e.g. uio0)
	const char *uio_filename = strrchr(device_name, '/');
	if (uio_filename == NULL) {
		return gbBAD;
	}

	// Offset parameter file path
	char uio_map_offset_file[path_length];
	snprintf(uio_map_offset_file, path_length, "/sys/class/uio/%s/maps/map0/offset", uio_filename);

	// Read offset parameter
	file = fopen(uio_map_offset_file, "r");
	if (file == NULL) {
		return gbBAD;
	}
	if (fscanf(file, "%x", &preoffset) != 1) {
		fclose(file);
		return gbBAD;
	}
	fclose(file);
	*offset = preoffset;
	LEVEL_DEBUG("[%s] map offset: 0x%x", __FUNCTION__, preoffset);
	LEVEL_DEBUG("[%s] map offset: 0x%x", __FUNCTION__, *offset);

	return gbGOOD;
}
Exemple #8
0
// set control pins and frequency for defauts and global settings 
static GOOD_OR_BAD K1WM_setup( struct connection_in * in )
{
	uint8_t control_register = DS1WM_control(in) ;
	LEVEL_DEBUG("[%s] control_register before setup: 0x%x", __FUNCTION__, control_register);

	// Set to channel
	K1WM_channel(in) = in->master.ds1wm.active_channel ;

	// set some defaults:
	UT_setbit( &control_register, e_ds1wm_ppm, in->master.ds1wm.presence_mask ) ; // pulse presence masked
	UT_setbit( &control_register, e_ds1wm_en_fow, 0 ) ; // no bit banging
	
	UT_setbit( &control_register, e_ds1wm_stpen, 0 ) ; // strong pullup not supported in K1WM
	UT_setbit( &control_register, e_ds1wm_stp_sply, 0 ) ; // not in strong pullup state, too
	
	in->master.ds1wm.byte_mode = 1 ; // default
	UT_setbit( &control_register, e_ds1wm_bit_ctl, 0 ) ; // byte mode
	
	UT_setbit( &control_register, e_ds1wm_od, in->overdrive ) ; // not overdrive
	UT_setbit( &control_register, e_ds1wm_llm, in->master.ds1wm.longline ) ; // set long line flag
	DS1WM_control(in) = control_register ;
	LEVEL_DEBUG("[%s] control_register after setup: 0x%x", __FUNCTION__, DS1WM_control(in));
	
	if ( DS1WM_control(in) != control_register ) {
		return gbBAD ;
	}

	return gbGOOD ;
}	
Exemple #9
0
static RESET_TYPE LINK_reset_in(struct connection_in * in)
{
	BYTE resp[1+in->CRLF_size];

	if (in->changed_bus_settings > 0) {
		--in->changed_bus_settings ;
		LINK_set_baud(in);	// reset paramters
	} else {
		LINK_flush(in);
	}

	if ( BAD(LINK_write(LINK_string("r"), 1, in) || BAD( LINK_read(resp, 1, in))) ) {
		LEVEL_DEBUG("Error resetting LINK device");
		LINK_slurp(in);
		return BUS_RESET_ERROR;
	}

	switch (resp[0]) {

	case 'P':
		in->AnyDevices = anydevices_yes;
		return BUS_RESET_OK;
	case 'N':
		in->AnyDevices = anydevices_no;
		return BUS_RESET_OK;
	case 'S':
		return BUS_RESET_SHORT;
	default:
		LEVEL_DEBUG("bad, Unknown LINK response %c", resp[0]);
		LINK_slurp(in);
		return BUS_RESET_ERROR;
	}
}
Exemple #10
0
enum Netlink_Read_Status W1_Process_Response( void (* nrs_callback)( struct netlink_parse * nlp, void * v, const struct parsedname * pn), SEQ_OR_ERROR seq, void * v, const struct parsedname * pn )
{
	struct connection_in * in = pn->selected_connection ;
	FILE_DESCRIPTOR_OR_ERROR file_descriptor ;
	int bus ;

	if ( seq == SEQ_BAD ) {
		return nrs_bad_send ;
	}

	if ( in == NO_CONNECTION ) {
		// Send to main netlink rather than a particular bus
		file_descriptor = FILE_DESCRIPTOR_BAD ;
		bus = 0 ;
	} else {
		// Bus-specifc
		file_descriptor = in->master.w1.netlink_pipe[fd_pipe_read] ;
		bus = in->master.w1.id ;
	}

	while ( GOOD( W1PipeSelect_timeout(file_descriptor)) ) {
		struct netlink_parse nlp ;
		nlp.nlm = NULL ;
		
		LEVEL_DEBUG("Loop waiting for netlink piped message");
		if ( BAD( Get_and_Parse_Pipe( file_descriptor, &nlp )) ) {
			LEVEL_DEBUG("Error reading pipe for w1_bus_master%d",bus);
			// Don't need to free since nlm not set if BAD
			return nrs_error ;
		}
		if ( NL_SEQ(nlp.nlm->nlmsg_seq) != (unsigned int) seq ) {
			LEVEL_DEBUG("Netlink sequence number out of order");
			owfree(nlp.nlm) ;
			continue ;
		}
		if ( nlp.w1m->status != 0) {
			owfree(nlp.nlm) ;
			return nrs_nodev ;
		}
		if ( nrs_callback == NULL ) { // status message
			owfree(nlp.nlm) ;
			return nrs_complete ;
		}

		LEVEL_DEBUG("About to call nrs_callback");
		nrs_callback( &nlp, v, pn ) ;
		LEVEL_DEBUG("Called nrs_callback");
		owfree(nlp.nlm) ;
		if ( nlp.cn->ack != 0 ) {
			if ( nlp.w1m->type == W1_LIST_MASTERS ) {
				continue ; // look for more data
			}
			if ( nlp.w1c && (nlp.w1c->cmd==W1_CMD_SEARCH || nlp.w1c->cmd==W1_CMD_ALARM_SEARCH) ) {
				continue ; // look for more data
			}
		}
		nrs_callback = NULL ; // now look for status message
	}
	return nrs_timeout ;
}
Exemple #11
0
static enum search_status DS9490_next_both(struct device_search *ds, const struct parsedname *pn)
{
	int dir_gulp_elements = (pn->ds2409_depth==0) ? DS2490_DIR_GULP_ELEMENTS : 1 ;

	// LOOK FOR NEXT ELEMENT
	++ds->index;
	LEVEL_DEBUG("Index %d", ds->index);

	if (ds->index % dir_gulp_elements == 0) {
		if (ds->LastDevice) {
			return search_done;
		}
		switch ( DS9490_directory(ds, pn) ) {
			case search_done:
				return search_done;
			case search_error:
				return search_error;
			case search_good:
				break;
		}
	}

	switch ( DirblobGet(ds->index % dir_gulp_elements, ds->sn, &(ds->gulp) ) ) {
		case 0:
			LEVEL_DEBUG("SN found: " SNformat, SNvar(ds->sn));
			return search_good;
		case -ENODEV:
		default:
			LEVEL_DEBUG("SN finished");
			return search_done;
	}
}
Exemple #12
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) ) ;
}
Exemple #13
0
static GOOD_OR_BAD LINK_detect_net(struct connection_in * in)
{
	struct port_in * pin = in->pown ;
	/* Set up low-level routines */
	LINKE_setroutines(in);
	pin->timeout.tv_sec = 0 ;
	pin->timeout.tv_usec = 300000 ;

	/* Open the tcp port */
	RETURN_BAD_IF_BAD( COM_open(in) ) ;
	
	LEVEL_DEBUG("Slurp in initial bytes");
//	LINK_slurp( in ) ;
	UT_delay(1000) ; // based on http://morpheus.wcf.net/phpbb2/viewtopic.php?t=89&sid=3ab680415917a0ebb1ef020bdc6903ad
	LINK_slurp( in ) ;
//	LINK_flush(in);

	pin->dev.telnet.telnet_negotiated = needs_negotiation ;
	RETURN_GOOD_IF_GOOD( LINK_version(in) ) ;

	// second try -- send a break and line settings
	LEVEL_DEBUG("Second try -- send BREAK");
	COM_flush(in) ;
	COM_break(in);
	telnet_change(in);
//	LINK_slurp( in ) ;
	RETURN_GOOD_IF_GOOD( LINK_version(in) ) ;

	LEVEL_DEFAULT("LINK detection error");
	COM_close(in) ;
	return gbBAD;
}
Exemple #14
0
// Switch to overdrive speed -- 3 tries
static GOOD_OR_BAD DS9490_overdrive(const struct parsedname *pn)
{
	BYTE sp = _1W_OVERDRIVE_SKIP_ROM;
	BYTE resp;
	int i;

	// we need to change speed to overdrive
	for (i = 0; i < 3; i++) {
		LEVEL_DATA("set overdrive speed. Attempt %d",i);
		if ( BAD( gbRESET(BUS_reset(pn)) ) ) {
			continue;
		}
		if ( BAD( DS9490_sendback_data(&sp, &resp, 1, pn) ) || (_1W_OVERDRIVE_SKIP_ROM != resp) ) {
			LEVEL_DEBUG("error setting overdrive %.2X/0x%02X", _1W_OVERDRIVE_SKIP_ROM, resp);
			continue;
		}
		if ( GOOD( USB_Control_Msg(MODE_CMD, MOD_1WIRE_SPEED, ONEWIREBUSSPEED_OVERDRIVE, pn)) ) {
			LEVEL_DEBUG("speed is now set to overdrive");
			return gbGOOD;
		}
	}

	LEVEL_DEBUG("Error setting overdrive after 3 retries");
	return gbBAD;
}
Exemple #15
0
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 ) ;
	}
}
Exemple #16
0
/* After parsing, but before sending to various devices. Will repeat 3 times if needed */
SIZE_OR_ERROR FS_read_postparse(struct one_wire_query *owq)
{
	struct parsedname *pn = PN(owq);
	SIZE_OR_ERROR read_or_error;

	// ServerRead jumps in here, perhaps with non-file entry
	if (pn->selected_device == NO_DEVICE || pn->selected_filetype == NO_FILETYPE) {
		return -EISDIR;
	}

	/* Normal read. Try three times */
	LEVEL_DEBUG("%s", pn->path);
	STATLOCK;
	AVERAGE_IN(&read_avg);
	AVERAGE_IN(&all_avg);
	STATUNLOCK;

	/* First try */
	STAT_ADD1(read_tries[0]);

	read_or_error = (pn->type == ePN_real) ? FS_read_real(owq) : FS_r_virtual(owq);

	STATLOCK;
	if (read_or_error >= 0) {
		++read_success;			/* statistics */
		read_bytes += read_or_error;	/* statistics */
	}
	AVERAGE_OUT(&read_avg);
	AVERAGE_OUT(&all_avg);
	STATUNLOCK;
	LEVEL_DEBUG("%s return %d", pn->path, read_or_error);
	return read_or_error;
}
Exemple #17
0
/* After parsing, choose special read based on path type */
static SIZE_OR_ERROR FS_read_distribute(struct one_wire_query *owq)
{
	// Device not locked
	SIZE_OR_ERROR read_or_error = 0;

	LEVEL_DEBUG("%s", PN(owq)->path);
	STATLOCK;
	AVERAGE_IN(&read_avg);
	AVERAGE_IN(&all_avg);
	STATUNLOCK;

	/* handle DeviceSimultaneous */
	if (PN(owq)->selected_device == DeviceSimultaneous) {
		read_or_error = FS_r_simultaneous(owq);
	} else {
		read_or_error = FS_r_given_bus(owq);
	}

	STATLOCK;
	if (read_or_error >= 0) {
		++read_success;			/* statistics */
		read_bytes += read_or_error;		/* statistics */
	}
	AVERAGE_OUT(&read_avg);
	AVERAGE_OUT(&all_avg);
	STATUNLOCK;

	LEVEL_DEBUG("%s returns %d", PN(owq)->path, read_or_error);
	//printf("FS_read_distribute: pid=%ld return %d\n", pthread_self(), read_or_error);
	return read_or_error;
}
Exemple #18
0
// Wait max time needed for reset
static RESET_TYPE K1WM_wait_for_reset( struct connection_in * in )
{
	LEVEL_DEBUG("[%s]", __FUNCTION__);
	long int t_reset = in->overdrive ? (74000+63000) : (636000+626000) ; // nsec
	uint8_t interrupt ;
	struct timespec t = {
		0, 
		t_reset,
	} ;
	
	if ( nanosleep( & t, NULL ) != 0 ) {
		return gbBAD ;
	}

	interrupt = DS1WM_interrupt(in) ;
	if ( UT_getbit( &interrupt, e_ds1wm_pd ) == 0 ) {
		LEVEL_DEBUG("[%s] presence_detect bit == 0", __FUNCTION__);
		return BUS_RESET_ERROR ;
	}
	if ( UT_getbit( &interrupt, e_ds1wm_ow_short ) == 1 ) {
		LEVEL_DEBUG("[%s] short bit == 1", __FUNCTION__);
		return BUS_RESET_SHORT ;
	}

	in->AnyDevices = ( UT_getbit( &interrupt, e_ds1wm_pdr ) == 0 ) ? anydevices_yes : anydevices_no ;
	LEVEL_DEBUG("[%s] in->AnyDevices == %i", __FUNCTION__, in->AnyDevices);
	return BUS_RESET_OK ;
}
/* Create the Parsename structure and create the buffer */
struct one_wire_query * OWQ_create_from_path(const char *path)
{
	int sz = sizeof( struct one_wire_query ) + OWQ_DEFAULT_READ_BUFFER_SIZE;
	struct one_wire_query * owq = owmalloc( sz );
	
	LEVEL_DEBUG("%s", path);

	if ( owq== NO_ONE_WIRE_QUERY) {
		LEVEL_DEBUG("No memory to create object for path %s",path) ;
		return NO_ONE_WIRE_QUERY ;
	}
	
	memset(owq, 0, sz);
	OWQ_cleanup(owq) = owq_cleanup_owq ;
	
	if ( GOOD( OWQ_parsename(path,owq) ) ) {
		if ( GOOD( OWQ_allocate_array(owq)) ) {
			/*   Add a 1 byte buffer by default. This distinguishes from filesystem calls at end of buffer */
			/*   Read bufer is provided by OWQ_assign_read_buffer or OWQ_allocate_read_buffer */
			OWQ_buffer(owq) = (char *) (& owq[1]) ; // point just beyond the one_wire_query struct
			OWQ_size(owq) = OWQ_DEFAULT_READ_BUFFER_SIZE ;
			return owq ;
		}
		OWQ_destroy(owq);
	}
	return NO_ONE_WIRE_QUERY ;
}
Exemple #20
0
static void LINK_set_baud(struct connection_in * in)
{
	struct port_in * pin = in->pown ;
	char * speed_code ;

	if ( pin->type == ct_telnet ) {
		// telnet pinned at 115200
		return ;
	}

	COM_BaudRestrict( &(pin->baud), B9600, B19200, B38400, B57600, 0 ) ;

	LEVEL_DEBUG("to %d",COM_BaudRate(pin->baud));
	// Find rate parameter
	switch ( pin->baud ) {
		case B9600:
			COM_break(in) ;
			LINK_flush(in);
			return ;
		case B19200:
			speed_code = "," ;
			break ;
		case B38400:
			speed_code = "`" ;
			break ;
#ifdef B57600
		/* MacOSX support max 38400 in termios.h ? */
		case B57600:
			speed_code = "^" ;
			break ;
#endif
		default:
			LEVEL_DEBUG("Unrecognized baud rate");
			return ;
	}

	LEVEL_DEBUG("LINK change baud string <%s>",speed_code);
	LINK_flush(in);
	if ( BAD( LINK_write(LINK_string(speed_code), 1, in) ) ) {
		LEVEL_DEBUG("LINK change baud error -- will return to 9600");
		pin->baud = B9600 ;
		++in->changed_bus_settings ;
		return ;
	}


	// Send configuration change
	LINK_flush(in);

	// Change OS view of rate
	UT_delay(5);
	COM_change(in) ;
	UT_delay(5);
	LINK_slurp(in);

	return ;
}
Exemple #21
0
static GOOD_OR_BAD LINK_search_type(struct device_search *ds, struct connection_in * in)
{
	char resp[3+in->CRLF_size];
	int response_length ;

	LEVEL_DEBUG("Test to see if LINK supports the tF0 command");
	switch ( in->master.link.tmode ) {
		case e_link_t_unknown:
			RETURN_BAD_IF_BAD( LINK_write(LINK_string("tF0"), 3, in));
			RETURN_BAD_IF_BAD(LINK_read(LINK_string(resp), 2, in));
			switch ( resp[0] ) {
				case 'F':
					in->master.link.tmode = e_link_t_none ;
					response_length = 2 ;
					break;
				default:
					in->master.link.tmode = e_link_t_extra ;
					response_length = 3 ;
					LINK_slurp(in);
					break;
			}
			break ;	
		case e_link_t_extra:
			response_length = 3 ;
			break ;
		case e_link_t_none:
		default:
			response_length = 2 ;
			break ;
	}

	//Depending on the search type, the LINK search function
	//needs to be selected
	//tEC -- Conditional searching
	//tF0 -- Normal searching
	

	// Send the configuration command and check response
	if (ds->search == _1W_CONDITIONAL_SEARCH_ROM) {
		RETURN_BAD_IF_BAD(LINK_write(LINK_string("tEC"), 3, in)) ;
		RETURN_BAD_IF_BAD(LINK_read(LINK_string(resp), response_length, in)) ;
		if (strstr(resp, "EC") == NULL) {
			LEVEL_DEBUG("Did not change to conditional search");
			return gbBAD;
		}
		LEVEL_DEBUG("LINK set for conditional search");
	} else {
		RETURN_BAD_IF_BAD( LINK_write(LINK_string("tF0"), 3, in));
		RETURN_BAD_IF_BAD(LINK_read(LINK_string(resp), response_length, in));
		if (strstr(resp, "F0") == NULL) {
			LEVEL_DEBUG("Did not change to normal search");
			return gbBAD;
		}
		LEVEL_DEBUG("LINK set for normal search");
	}
	return gbGOOD ;
}
Exemple #22
0
/* cm.ret is also set to an error <0 or the read length */
void *ReadHandler(struct handlerdata *hd, struct client_msg *cm, struct one_wire_query *owq)
{
	BYTE * retbuffer = NULL ;
	SIZE_OR_ERROR read_or_error;

	LEVEL_DEBUG("ReadHandler start");
	if (hd == NULL || owq == NULL || cm == NULL) {
		LEVEL_DEBUG("ReadHandler: illegal null inputs hd==%p owq==%p cm==%p", hd, owq, cm);
		return NULL;			// only sane response for bad inputs
	}

	LEVEL_DEBUG("ReadHandler: From Client sm->payload=%d sm->size=%d sm->offset=%d", hd->sm.payload, hd->sm.size, hd->sm.offset);

	if (hd->sm.payload >= PATH_MAX) {
		cm->ret = -EMSGSIZE;
	} else if ((hd->sm.size <= 0) || (hd->sm.size > MAX_OWSERVER_PROTOCOL_PAYLOAD_SIZE)) {
		cm->ret = -EMSGSIZE;
		LEVEL_DEBUG("ReadHandler: error hd->sm.size == %d", hd->sm.size);
	} else if ( BAD( OWQ_allocate_read_buffer(owq)) ) {	// allocate read buffer
		LEVEL_DEBUG("ReadHandler: can't allocate memory");
		cm->ret = -ENOBUFS;
	} else {
		struct parsedname *pn = PN(owq);

		if ( OWQ_size(owq) > (size_t) hd->sm.size ) {
			OWQ_size(owq) = hd->sm.size ;
		}
		OWQ_offset(owq) = hd->sm.offset ;

		LEVEL_DEBUG("ReadHandler: call FS_read_postparse on %s", pn->path);
		read_or_error = FS_read_postparse(owq);
		LEVEL_DEBUG("ReadHandler: FS_read_postparse read on %s return = %d", pn->path, read_or_error);

		Debug_OWQ(owq);

		if (read_or_error <= 0) {
			LEVEL_DEBUG("ReadHandler: FS_read_postparse error %d", read_or_error);
			cm->ret = read_or_error;
		} else {
			LEVEL_DEBUG("ReadHandler: FS_read_postparse ok size=%d", read_or_error);
			// make return size smaller (just large enough)
			cm->payload = read_or_error;
			cm->offset = hd->sm.offset;
			cm->size = read_or_error;
			cm->ret = read_or_error;
			/* Move this pointer, and let owfree remove it instead of OWQ_destroy() */
			retbuffer = (BYTE *)OWQ_buffer(owq);
			OWQ_buffer(owq) = NULL;
		}
	}
	LEVEL_DEBUG("ReadHandler: To Client cm->payload=%d cm->size=%d cm->offset=%d", cm->payload, cm->size, cm->offset);
	if ((cm->size > 0)) {
		Debug_Bytes("Data returned to client",(BYTE *) OWQ_buffer(owq),cm->size) ;
	}
	return retbuffer;
}
Exemple #23
0
/* Is this a DS2483? Try to set to new register */
static GOOD_OR_BAD DS2483_test(FILE_DESCRIPTOR_OR_ERROR file_descriptor)
{
    /* Select the data register */
    if (i2c_smbus_write_byte_data(file_descriptor, DS2482_CMD_SET_READ_PTR, DS2482_PORT_CONFIGURATION_REGISTER) < 0) {
        LEVEL_DEBUG("Cannot set to port configuration -- not a DS2483");
        return gbBAD;
    }
    LEVEL_DEBUG("Can set to port configuration! a DS2483!");
    return gbGOOD;
}
Exemple #24
0
static GOOD_OR_BAD K1WM_sendback_byte(const BYTE * data, BYTE * resp, const struct connection_in * in )
{
	LEVEL_DEBUG("[%s] sending byte: 0x%x", __FUNCTION__, data[0]);
	RETURN_BAD_IF_BAD( K1WM_wait_for_write(in) ) ;
	DS1WM_txrx(in) = data[0] ;
	RETURN_BAD_IF_BAD( K1WM_wait_for_read(in) ) ;
	resp[0] = DS1WM_txrx(in) ;
	LEVEL_DEBUG("[%s] received byte: 0x%x", __FUNCTION__, resp[0]);
	return gbGOOD ;
}
Exemple #25
0
static void Config_Monitor_Block( void )
{
	// OS specific code
	struct kevent ke ;
	// kevent should block until an event
	while( kevent( kq, NULL, 0, &ke, 1, NULL ) < 1 ) {
		LEVEL_DEBUG("kevent loop (shouldn't happen!)" ) ;
	}
	// fall though -- event happened, time to resurrect
	LEVEL_DEBUG("Configuration file change -- time to resurrect");
}
/* Create the Parsename structure and load the relevant fields */
struct one_wire_query * OWQ_create_sibling(const char *sibling, struct one_wire_query *owq_original)
{
	char path[PATH_MAX] ;
	struct parsedname * pn_original = PN(owq_original) ;
	int dirlength = pn_original->dirlength ;
	struct one_wire_query * owq_sib ;

	strncpy(path, pn_original->path,dirlength) ;
	strcpy(&path[dirlength],sibling) ;
	
	if ( pn_original->selected_filetype == NO_FILETYPE ) {
		if ( pn_original->subdir == NO_SUBDIR ) {
			// not a filetype or a subdir
			return NO_ONE_WIRE_QUERY ;
		}
	// Add extension only if original property is aggregate
	} else if ( pn_original->selected_filetype->ag != NON_AGGREGATE ) {
		// search for sibling in the filetype array
		struct filetype * sib_filetype = bsearch(sibling, pn_original->selected_device->filetype_array,
				 (size_t) pn_original->selected_device->count_of_filetypes, sizeof(struct filetype), filetype_cmp) ;
		// see if sibling is also an aggregate property
		LEVEL_DEBUG("Path %s is an agggregate",SAFESTRING(pn_original->path));
		if ( sib_filetype != NO_FILETYPE && sib_filetype->ag != NON_AGGREGATE ) {
			char * aggregate_point = path + strlen(path) ;
			LEVEL_DEBUG("Sibling is also an aggregate",sibling);
			if (pn_original->extension == EXTENSION_BYTE ) {
				strcpy( aggregate_point, ".BYTE" ) ;
			} else if (pn_original->extension == EXTENSION_ALL ) {
				strcpy( aggregate_point, ".ALL" ) ;
			} else if (sib_filetype->ag->letters == ag_letters) {
				UCLIBCLOCK;
				snprintf(aggregate_point, OW_FULLNAME_MAX, ".%c", pn_original->extension + 'A');
				UCLIBCUNLOCK;
			} else {
				UCLIBCLOCK;
				snprintf(aggregate_point, OW_FULLNAME_MAX, ".%d", pn_original->extension );
				UCLIBCUNLOCK;
			}
		}			
	}
	
	LEVEL_DEBUG("Create sibling %s from %s as %s", sibling, pn_original->path,path);

	owq_sib = OWQ_create_from_path(path) ;
	if ( owq_sib != NO_ONE_WIRE_QUERY ) {
		// Sib has no offset
		OWQ_offset(owq_sib) = 0 ;
		// Make uncached as restrictive as original
		// Make unaliased as restrictive as original
		PN(owq_sib)->state |= (pn_original->state & (ePS_uncached|ePS_unaliased) ) ;
		return owq_sib ;
	}
	return NO_ONE_WIRE_QUERY ;
}
Exemple #27
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;
}
Exemple #28
0
/* return 0 if good, 1 if not */
GOOD_OR_BAD Cache_Add_Dir(const struct dirblob *db, const struct parsedname *pn)
{
	time_t duration = TimeOut(fc_directory);
	struct tree_node *tn;
	size_t size = DirblobElements(db) * SERIAL_NUMBER_SIZE;
	struct parsedname pn_directory;

	if (pn==NO_PARSEDNAME || pn->selected_connection==NO_CONNECTION) {
		return gbGOOD;				// do check here to avoid needless processing
	}
	
	switch ( get_busmode(pn->selected_connection) ) {
		case bus_fake:
		case bus_tester:
		case bus_mock:
		case bus_w1:
		case bus_bad:
		case bus_unknown:
			return gbGOOD ;
		default:
			break ;
	}
	
	if (duration <= 0) {
		return 0;				/* in case timeout set to 0 */
	}

	if ( DirblobElements(db) < 1 ) {
		// only cache long directories.
		// zero (or one?) entry is possibly an error and needs to be repeated more quickly
		LEVEL_DEBUG("Won\'t cache empty directory");
		Cache_Del_Dir( pn ) ;
		return gbGOOD ;
	}
	
	// allocate space for the node and data
	tn = (struct tree_node *) owmalloc(sizeof(struct tree_node) + size);
	if (!tn) {
		return gbBAD;
	}
	
	LEVEL_DEBUG("Adding directory for " SNformat " elements=%d", SNvar(pn->sn), DirblobElements(db));
	
	// populate node with directory name and dirblob
	FS_LoadDirectoryOnly(&pn_directory, pn);
	LoadTK( pn_directory.sn, Directory_Marker, pn->selected_connection->index, tn );
	tn->expires = duration + NOW_TIME;
	tn->dsize = size;
	if (size) {
		memcpy(TREE_DATA(tn), db->snlist, size);
	}
	return Add_Stat(&cache_dir, Cache_Add_Common(tn));
}
Exemple #29
0
/* 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 ;
}
Exemple #30
0
// bus locking done at a higher level
GOOD_OR_BAD LINK_detect(struct port_in *pin)
{
	struct connection_in * in = pin->first ;

	if (pin->init_data == NULL) {
		// requires input string
		LEVEL_DEFAULT("LINK busmaster requires port name");
		return gbBAD;
	}

	COM_set_standard( in ) ; // standard COM port settings

	switch( pin->type ) {
		case ct_telnet:
			// LinkHub-E
			pin->baud = B115200 ;
			LEVEL_DEBUG("Attempt connection to networked LINK at 115200 baud");
			RETURN_GOOD_IF_GOOD(  LINK_detect_net( in )  );

			// Xport or ser2net
			pin->baud = B9600 ;
			LEVEL_DEBUG("Attempt connection to networked LINK at 9600 baud");
			RETURN_GOOD_IF_GOOD(  LINK_detect_net( in )  );

			break ;

			

		case ct_serial:
			pin->baud = B9600 ;

			pin->flow = flow_first ;
			RETURN_GOOD_IF_GOOD( LINK_detect_serial(in) ) ;

			LEVEL_DEBUG("Second attempt at serial LINK setup");
			pin->flow = flow_second ;
			RETURN_GOOD_IF_GOOD( LINK_detect_serial(in) ) ;

			LEVEL_DEBUG("Third attempt at serial LINK setup");
			pin->flow = flow_first ;
			RETURN_GOOD_IF_GOOD( LINK_detect_serial(in) ) ;

			LEVEL_DEBUG("Fourth attempt at serial LINK setup");
			pin->flow = flow_second ;
			RETURN_GOOD_IF_GOOD( LINK_detect_serial(in) ) ;
			break ;

		default:
			return gbBAD ;
	}
	return gbBAD ;
}