/* Write now that connection is set */ static ZERO_OR_ERROR FS_w_given_bus(struct one_wire_query *owq) { struct parsedname *pn = PN(owq); if ( BAD(TestConnection(pn)) ) { return -ECONNABORTED; } else if (KnownBus(pn) && BusIsServer(pn->selected_connection)) { return ServerWrite(owq); } else if (OWQ_pn(owq).type == ePN_real) { ZERO_OR_ERROR write_or_error = DeviceLockGet(pn); if (write_or_error == 0) { write_or_error = FS_w_local(owq); DeviceLockRelease(pn); } else { LEVEL_DEBUG("Cannot lock device for writing") ; } return write_or_error ; } else if ( IsInterfaceDir(pn) ) { ZERO_OR_ERROR write_or_error; BUSLOCK(pn); write_or_error = FS_w_local(owq); BUSUNLOCK(pn); return write_or_error ; } else { return FS_w_local(owq); } }
/* USB is a special case, in gets reenumerated, so we look for similar DS2401 chip */ GOOD_OR_BAD TestConnection(const struct parsedname *pn) { GOOD_OR_BAD ret = 0; struct connection_in *in ; if ( pn == NO_PARSEDNAME ) { return gbGOOD ; } in = pn->selected_connection ; if ( in == NO_CONNECTION ) { return gbGOOD ; } // Test without a lock -- efficient if ( in->reconnect_state < reconnect_error ) { return gbGOOD; } // Lock the bus BUSLOCK(pn); // Test again if (in->reconnect_state >= reconnect_error) { // Add Statistics STAT_ADD1_BUS(e_bus_reconnects, in); // Close the bus (should leave enough reconnection information available) BUS_close(in); // already locked // Call reconnection in->AnyDevices = anydevices_unknown ; if ( in->iroutines.reconnect != NO_RECONNECT_ROUTINE ) { // reconnect method exists ret = (in->iroutines.reconnect) (pn) ; // call bus-specific reconnect } else { ret = BUS_detect(in->pown) ; // call initial opener } if ( BAD( ret ) ) { in->reconnect_state = reconnect_ok + 1 ; // delay to slow thrashing UT_delay(200); } else { in->reconnect_state = reconnect_ok; } } BUSUNLOCK(pn); if ( BAD( ret ) ) { LEVEL_DEFAULT("Failed to reconnect %s bus master!", in->adapter_name); } else { LEVEL_DEFAULT("%s bus master reconnected", in->adapter_name); } return ret; }
/* Then a series of bytes is sent and returned, including sending data and reading the return data */ GOOD_OR_BAD BUS_transaction(const struct transaction_log *tl, const struct parsedname *pn) { GOOD_OR_BAD ret ; if (tl == NULL) { return gbGOOD; } BUSLOCK(pn); ret = BUS_transaction_nolock(tl, pn); BUSUNLOCK(pn); return ret; }
static GOOD_OR_BAD OW_w_status(BYTE * data, size_t size, off_t offset, struct parsedname *pn) { BYTE p[6] = { _1W_WRITE_STATUS, LOW_HIGH_ADDRESS(offset), data[0] }; GOOD_OR_BAD ret = gbGOOD; struct transaction_log tfirst[] = { TRXN_START, TRXN_WR_CRC16(p, 4, 0), TRXN_PROGRAM, TRXN_READ1(p), TRXN_END, }; if (size == 0) { return gbGOOD; } if (size == 1) { return BUS_transaction(tfirst, pn) || (p[0] & (~data[0])); } BUSLOCK(pn); if ( BAD(BUS_transaction(tfirst, pn)) || (p[0] & ~data[0])) { ret = gbBAD; } else { size_t i; const BYTE *d = &data[1]; UINT s = offset + 1; struct transaction_log trest[] = { //TRXN_WR_CRC16_SEEDED( p, &s, 1, 0 ) , TRXN_WR_CRC16_SEEDED(p, p, 1, 0), TRXN_PROGRAM, TRXN_READ1(p), TRXN_END, }; for (i = 0; i < size; ++i, ++d, ++s) { if ( BAD(BUS_transaction(trest, pn)) || (p[0] & ~d[0])) { ret = gbBAD; break; } } } BUSUNLOCK(pn); return ret; }
// This function should return number of bytes read... not status. // Works for all the virtual directories, like statistics, interface, ... // Doesn't need three-peat and bus was already set or not needed. static SIZE_OR_ERROR FS_r_virtual(struct one_wire_query *owq) { struct parsedname *pn = PN(owq); SIZE_OR_ERROR read_status = 0; if (SpecifiedRemoteBus(pn)) { /* The bus is not local... use a network connection instead */ // Read afar -- returns already formatted in buffer read_status = ServerRead(owq); LEVEL_DEBUG("back from server"); Debug_OWQ(owq); } else { /* local bus -- any special locking needs? */ STAT_ADD1(read_calls); /* statistics */ switch (pn->type) { case ePN_structure: read_status = FS_structure(owq); break; case ePN_interface: BUSLOCK(pn); read_status = FS_r_local(owq); // this returns status BUSUNLOCK(pn); break; case ePN_statistics: // reading /statistics/read/tries.ALL // will cause a deadlock since it calls STAT_ADD1(read_array); // Should perhaps create a new mutex for this. // Comment out this STATLOCK until it's solved. // STATLOCK now done at time of actual read in ow_stats.c read_status = FS_r_local(owq); // this returns status break; default: read_status = FS_r_local(owq); // this returns status } if (read_status >= 0) { // local success -- now format in buffer read_status = OWQ_parse_output(owq); // this returns nr. bytes } } LEVEL_DEBUG("return %d", read_status); return read_status; }