/* Read real device (Non-virtual). Will repeat 3 times if needed */ static SIZE_OR_ERROR FS_read_real(struct one_wire_query *owq) { struct parsedname *pn = PN(owq); SIZE_OR_ERROR read_or_error; /* First try */ /* in and bus_nr already set */ read_or_error = FS_read_distribute(owq); /* Second Try */ /* if not a specified bus, relook for chip location */ if (read_or_error < 0) { //error STAT_ADD1(read_tries[1]); if (SpecifiedBus(pn)) { // this bus or bust! if ( BAD(TestConnection(pn)) ) { read_or_error = -ECONNABORTED; } else { read_or_error = FS_read_distribute(owq); // 2nd try if (read_or_error < 0) { // third try STAT_ADD1(read_tries[2]); read_or_error = FS_read_distribute(owq); } } } else if (BusIsServer(pn->selected_connection)) { int bus_nr = pn->selected_connection->index ; // current selected bus INDEX_OR_ERROR busloc_or_error = ReCheckPresence(pn) ; // special handling or remote // only repeat if the bus number is wrong // because the remote does the rereads if ( bus_nr != busloc_or_error ) { if (busloc_or_error < 0) { read_or_error = -ENOENT; } else { read_or_error = FS_read_distribute(owq); if (read_or_error < 0) { // third try STAT_ADD1(read_tries[2]); read_or_error = FS_read_distribute(owq); } } } } else { INDEX_OR_ERROR busloc_or_error = ReCheckPresence(pn); // search again if (busloc_or_error < 0) { read_or_error = -ENOENT; } else { read_or_error = FS_read_distribute(owq); if (read_or_error < 0) { // third try STAT_ADD1(read_tries[2]); read_or_error = FS_read_distribute(owq); } } } } return read_or_error; }
/* This function is only used by "Simultaneous" */ static ZERO_OR_ERROR FS_w_simultaneous(struct one_wire_query *owq) { if (SpecifiedBus(PN(owq))) { return FS_w_given_bus(owq); } else { struct simultaneous_struct ss ; ss.pin = Inbound_Control.head_port ; memcpy( &(ss.owq), owq, sizeof(struct one_wire_query)); // shallow copy Simultaneous_write_callback_port( (void *) (&ss) ) ; } return 0; }
// This function probably needs to be modified a bit... static SIZE_OR_ERROR FS_r_simultaneous(struct one_wire_query *owq) { // Device not locked. OWQ_allocate_struct_and_pointer(owq_given); if (SpecifiedBus(PN(owq))) { return FS_r_given_bus(owq); } memcpy(owq_given, owq, sizeof(struct one_wire_query)); // shallow copy // it's hard to know what we should return when reading /simultaneous/temperature SetKnownBus(0, PN(owq_given)); return FS_r_given_bus(owq_given); }
/* This function is only used by "Simultaneous" */ static ZERO_OR_ERROR FS_w_simultaneous(struct one_wire_query *owq) { if (SpecifiedBus(PN(owq))) { return FS_w_given_bus(owq); } else if (Inbound_Control.head_port) { struct port_in * pin ; OWQ_allocate_struct_and_pointer(owq_given); memcpy(owq_given, owq, sizeof(struct one_wire_query)); // shallow copy for ( pin=Inbound_Control.head_port ; pin != NULL ; pin = pin->next ) { struct connection_in * cin; for( cin=pin->first; cin!=NO_CONNECTION ; cin=cin->next ) { SetKnownBus(cin->index, PN(owq_given)); FS_w_given_bus(owq_given); } } } return 0; }
/* If error, try twice more */ static ZERO_OR_ERROR FS_write_real(int depth, struct one_wire_query *owq) { ZERO_OR_ERROR write_or_error; struct parsedname *pn = PN(owq); struct filetype * ft = pn->selected_filetype ; INDEX_OR_ERROR initial_bus = pn->selected_connection->index ; // current selected bus INDEX_OR_ERROR rechecked_bus ; if ( depth > 1 ) { LEVEL_DEBUG("Too many bus changes for write"); return -ENODEV ; } if ( ft->write == FS_w_alias ) { // Special check for alias // it's ok for fake and tester and mock as well // so do this before the fake test // also no need to three-peat. return FS_write_owq(owq) ; } /* Special case for "fake" adapter */ switch (get_busmode(pn->selected_connection)) { case bus_mock: // Mock -- write even "unwritable" to the cache for testing OWQ_Cache_Add(owq) ; // fall through case bus_fake: case bus_tester: return ( ft->write == NO_WRITE_FUNCTION ) ? -ENOTSUP : 0 ; default: // non-virtual devices get handled below break ; } /* First try */ /* in and bus_nr already set */ STAT_ADD1(write_tries[0]); write_or_error = FS_w_given_bus(owq); if ( write_or_error ==0 ) { return 0 ; } /* Second Try */ STAT_ADD1(write_tries[1]); if (SpecifiedBus(pn)) { // The bus number casn't be changed -- it was specified in the path write_or_error = FS_w_given_bus(owq); if ( write_or_error == 0 ) { return 0 ; } // The bus number casn't be changed -- it was specified in the path STAT_ADD1(write_tries[2]); return FS_w_given_bus(owq); } /* Recheck location */ /* if not a specified bus, relook for chip location */ rechecked_bus = ReCheckPresence(pn) ; if ( rechecked_bus < 0 ) { // can't find the location return -ENOENT ; } if ( initial_bus == rechecked_bus ) { // special handling for remote // only repeat if the bus number is wrong // because the remote does the rewrites if (BusIsServer(pn->selected_connection)) { return write_or_error ; } // try again STAT_ADD1(write_tries[1]); write_or_error = FS_w_given_bus(owq); if ( write_or_error == 0 ) { return 0 ; } // third try STAT_ADD1(write_tries[2]); return FS_w_given_bus(owq); } // Changed location retry everything LEVEL_DEBUG("Bus location changed from %d to %d\n",initial_bus,rechecked_bus); return FS_write_real(depth+1,owq); }
// Early parsing -- only bus entries, uncached and text may have preceeded static enum parse_enum Parse_Unspecified(char *pathnow, enum parse_pass remote_status, struct parsedname *pn) { static regex_t rx_bus ; static regex_t rx_set ; static regex_t rx_sta ; static regex_t rx_str ; static regex_t rx_sys ; static regex_t rx_int ; static regex_t rx_tex ; static regex_t rx_jso ; static regex_t rx_unc ; static regex_t rx_una ; struct ow_regmatch orm ; orm.number = 1 ; // for bus ow_regcomp( &rx_bus, "^bus\\.([[:digit:]]+)/?", REG_ICASE ) ; ow_regcomp( &rx_set, "^settings/?", REG_ICASE | REG_NOSUB ) ; ow_regcomp( &rx_sta, "^statistics/?", REG_ICASE | REG_NOSUB ) ; ow_regcomp( &rx_str, "^structure/?", REG_ICASE | REG_NOSUB ) ; ow_regcomp( &rx_sys, "^system/?", REG_ICASE | REG_NOSUB ) ; ow_regcomp( &rx_int, "^interface/?", REG_ICASE | REG_NOSUB ) ; ow_regcomp( &rx_tex, "^text/?", REG_ICASE | REG_NOSUB ) ; ow_regcomp( &rx_jso, "^json/?", REG_ICASE | REG_NOSUB ) ; ow_regcomp( &rx_unc, "^uncached/?", REG_ICASE | REG_NOSUB ) ; ow_regcomp( &rx_una, "^unaliased/?", REG_ICASE | REG_NOSUB ) ; if ( ow_regexec( &rx_bus, pathnow, &orm ) == 0) { INDEX_OR_ERROR bus_number = (INDEX_OR_ERROR) atoi(orm.match[1]) ; ow_regexec_free( &orm ) ; return Parse_Bus( bus_number, pn); } else if (ow_regexec( &rx_set, pathnow, NULL ) == 0) { return set_type( ePN_settings, pn ) ; } else if (ow_regexec( &rx_sta, pathnow, NULL ) == 0) { return set_type( ePN_statistics, pn ) ; } else if (ow_regexec( &rx_str, pathnow, NULL ) == 0) { return set_type( ePN_structure, pn ) ; } else if (ow_regexec( &rx_sys, pathnow, NULL ) == 0) { return set_type( ePN_system, pn ) ; } else if (ow_regexec( &rx_int, pathnow, NULL ) == 0) { if (!SpecifiedBus(pn)) { return parse_error; } pn->type = ePN_interface; return parse_nonreal; } else if (ow_regexec( &rx_tex, pathnow, NULL ) == 0) { pn->state |= ePS_text; return parse_first; } else if (ow_regexec( &rx_jso, pathnow, NULL ) == 0) { pn->state |= ePS_json; return parse_first; } else if (ow_regexec( &rx_unc, pathnow, NULL ) == 0) { pn->state |= ePS_uncached; return parse_first; } else if (ow_regexec( &rx_una, pathnow, NULL ) == 0) { pn->state |= ePS_unaliased; return parse_first; } pn->type = ePN_real; return Parse_Branch(pathnow, remote_status, pn); }