/* See if a cached location is accurate -- called with "Known Bus" set */ INDEX_OR_ERROR ReCheckPresence(struct parsedname *pn) { INDEX_OR_ERROR bus_nr; if (NotRealDir(pn)) { return INDEX_DEFAULT; } if ((pn->selected_device == DeviceSimultaneous) || (pn->selected_device == DeviceThermostat)) { return INDEX_DEFAULT; } if (KnownBus(pn)) { if ( INDEX_VALID( CheckThisConnection(pn->known_bus->index,pn) ) ) { return pn->known_bus->index ; } } if ( GOOD( Cache_Get_Device(&bus_nr, pn)) ) { LEVEL_DEBUG("Found device on bus %d",bus_nr); if ( INDEX_VALID( CheckThisConnection(bus_nr,pn) ) ) { SetKnownBus(bus_nr, pn); return bus_nr ; } } UnsetKnownBus(pn); Cache_Del_Device(pn) ; return CheckPresence(pn); }
static void * RemoteAlias_callback_conn(void * v) { struct remotealias_struct * ras = (struct remotealias_struct *) v ; struct remotealias_struct ras_next ; pthread_t thread; int threadbad = 0; // set up for next server connection ras_next.cin = NextServer(ras->cin->next) ; if ( ras_next.cin == NO_CONNECTION ) { threadbad = 1 ; } else { ras_next.pin = ras->pin ; ras_next.pn = ras->pn ; ras_next.bus_nr = INDEX_BAD ; memset( ras_next.sn, 0, SERIAL_NUMBER_SIZE) ; threadbad = pthread_create(&thread, DEFAULT_THREAD_ATTR, RemoteAlias_callback_conn, (void *) (&ras_next)) ; } // Result for this server connection (while next one is processing) ras->bus_nr = ServerAlias( ras->sn, ras->cin, ras->pn ) ; if (threadbad == 0) { /* was a thread created? */ if (pthread_join(thread, NULL)==0) { // Set answer to the next bus if it's found // else use current answer if ( INDEX_VALID(ras_next.bus_nr) ) { ras->bus_nr = ras_next.bus_nr ; memcpy( ras->sn, ras_next.sn, SERIAL_NUMBER_SIZE ) ; } } } return VOID_RETURN ; }
static void * CheckPresence_callback_port(void * v) { struct checkpresence_struct * cps = (struct checkpresence_struct *) v ; struct checkpresence_struct cps_next ; pthread_t thread; int threadbad = 0 ; cps_next.pin = cps->pin->next ; if ( cps_next.pin == NULL ) { threadbad = 1 ; } else { cps_next.pn = cps->pn ; cps_next.bus_nr = INDEX_BAD ; threadbad = pthread_create(&thread, DEFAULT_THREAD_ATTR, CheckPresence_callback_port, (void *) (&cps_next)) ; } cps->cin = cps->pin->first ; if ( cps->cin != NO_CONNECTION ) { CheckPresence_callback_conn(v) ; } if (threadbad == 0) { /* was a thread created? */ if (pthread_join(thread, NULL)==0) { if ( INDEX_VALID(cps_next.bus_nr) ) { cps->bus_nr = cps_next.bus_nr ; } } } return VOID_RETURN ; }
static INDEX_OR_ERROR CheckPresence_low(struct parsedname *pn) { struct port_in * pin ; for ( pin=Inbound_Control.head_port ; pin ; pin=pin->next ) { struct connection_in * cin ; for ( cin=pin->first ; cin ; cin=cin->next ) { int bus_nr = CheckThisConnection( cin->index, pn ) ; if ( INDEX_VALID(bus_nr) ) { return bus_nr ; } } } return INDEX_BAD; // no success }
// Look on a given connection for the device static INDEX_OR_ERROR CheckThisConnection(int bus_nr, struct parsedname *pn) { struct parsedname s_pn_copy; struct parsedname * pn_copy = &s_pn_copy ; struct connection_in * in = find_connection_in(bus_nr) ; INDEX_OR_ERROR connection_result = INDEX_BAD ; if ( in == NO_CONNECTION ) { return INDEX_BAD ; } memcpy(pn_copy, pn, sizeof(struct parsedname)); // shallow copy pn_copy->selected_connection = in; if ( BAD( TestConnection(pn_copy) ) ) { // Connection currently disconnected return INDEX_BAD; } else if (BusIsServer(in)) { // Server if ( INDEX_VALID( ServerPresence(pn_copy) ) ) { connection_result = in->index; } } else if ( in->iroutines.flags & ADAP_FLAG_sham ) { return INDEX_BAD ; } else if ( in->iroutines.flags & ADAP_FLAG_presence_from_dirblob ) { // local connection with a dirblob (like fake, mock, ...) if ( GOOD( PresenceFromDirblob( pn_copy ) ) ) { connection_result = in->index ; } } else { // local connection but need to ask directly struct transaction_log t[] = { TRXN_NVERIFY, TRXN_END, }; if ( GOOD( BUS_transaction(t, pn_copy) ) ) { connection_result = in->index ; } } if ( connection_result == INDEX_BAD ) { LEVEL_DEBUG("Presence of "SNformat" NOT found on bus %s",SNvar(pn_copy->sn),SAFESTRING(DEVICENAME(in))) ; } else { LEVEL_DEBUG("Presence of "SNformat" FOUND on bus %s",SNvar(pn_copy->sn),SAFESTRING(DEVICENAME(in))) ; Cache_Add_Device(in->index,pn_copy->sn) ; // add or update cache */ } return connection_result ; }
INDEX_OR_ERROR RemoteAlias(struct parsedname *pn) { struct port_in * pin ; for ( pin = Inbound_Control.head_port ; pin ; pin = pin->first ) { struct connection_in * cin ; for ( cin=NextServer(pin->first) ; cin ; cin=NextServer(cin->next) ) { BYTE sn[SERIAL_NUMBER_SIZE] ; INDEX_OR_ERROR bus_nr = ServerAlias( sn, cin, pn ) ; if ( INDEX_VALID(bus_nr) ) { memcpy( pn->sn, sn, SERIAL_NUMBER_SIZE ) ; LEVEL_DEBUG("Remote alias for %s bus=%d "SNformat,pn->path_to_server,bus_nr,SNvar(sn)); return bus_nr ; } } } return INDEX_BAD; // no success }
void uu_list_insert(uu_list_t *lp, void *elem, uu_list_index_t idx) { uu_list_node_impl_t *np; np = INDEX_TO_NODE(idx); if (np == NULL) np = &lp->ul_null_node; if (lp->ul_debug) { if (!INDEX_VALID(lp, idx)) uu_panic("uu_list_insert(%p, %p, %p): %s\n", (void *)lp, elem, (void *)idx, INDEX_CHECK(idx)? "outdated index" : "invalid index"); if (np->uln_prev == NULL) uu_panic("uu_list_insert(%p, %p, %p): out-of-date " "index\n", (void *)lp, elem, (void *)idx); } list_insert(lp, ELEM_TO_NODE(lp, elem), np->uln_prev, np); }
INDEX_OR_ERROR RemoteAlias(struct parsedname *pn) { struct remotealias_struct ras ; ras.pin = Inbound_Control.head_port ; ras.pn = pn ; ras.bus_nr = INDEX_BAD ; memset( ras.sn, 0, SERIAL_NUMBER_SIZE) ; if ( ras.pin != NULL ) { RemoteAlias_callback_port( (void *) (&ras) ) ; } memcpy( pn->sn, ras.sn, SERIAL_NUMBER_SIZE ) ; if ( INDEX_VALID( ras.bus_nr ) ) { LEVEL_DEBUG("Remote alias for %s bus=%d "SNformat,pn->path_to_server,ras.bus_nr,SNvar(ras.sn)); } else { LEVEL_DEBUG("Remote alias for %s not found",pn->path_to_server); } return ras.bus_nr; }
/* Check if device exists -- >=0 yes, -1 no */ INDEX_OR_ERROR CheckPresence(struct parsedname *pn) { INDEX_OR_ERROR bus_nr; if (NotRealDir(pn)) { return INDEX_DEFAULT; } if ((pn->selected_device == DeviceSimultaneous) || (pn->selected_device == DeviceThermostat)) { return INDEX_DEFAULT; } /* If set, already found bus. */ /* Use UnsetKnownBus to clear and allow a new search */ if (KnownBus(pn)) { return pn->known_bus->index; } if ( GOOD( Cache_Get_Device(&bus_nr, pn)) ) { LEVEL_DEBUG("Found device on bus %d",bus_nr); SetKnownBus(bus_nr, pn); return bus_nr; } LEVEL_DETAIL("Checking presence of %s", SAFESTRING(pn->path)); bus_nr = CheckPresence_low(pn); // check only allocated inbound connections if ( INDEX_VALID(bus_nr) ) { SetKnownBus(bus_nr, pn); Cache_Add_Device( bus_nr, pn->sn ) ; return bus_nr; } UnsetKnownBus(pn); return INDEX_BAD; }