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