/* Top level detect routine */ GOOD_OR_BAD DS2482_detect(struct port_in *pin) { struct address_pair ap ; GOOD_OR_BAD gbResult ; enum ds2482_address chip_num ; Parse_Address( pin->init_data, &ap ) ; switch ( ap.second.type ) { case address_numeric: if ( ap.second.number < ds2482_18 || ap.second.number >= ds2482_too_far ) { LEVEL_CALL("DS2482 bus address <%s> invalid. Will search.", ap.second.alpha) ; chip_num = ds2482_any ; } else { chip_num = ap.second.number ; } break ; case address_all: case address_asterix: chip_num = ds2482_all ; break ; case address_none: chip_num = ds2482_any ; break ; default: LEVEL_CALL("DS2482 bus address <%s> invalid. Will scan.", ap.second.alpha) ; chip_num = ds2482_any ; break ; } switch ( ap.first.type ) { case address_all: case address_asterix: // All adapters gbResult = DS2482_detect_sys( 0, chip_num, pin ) ; break ; case address_none: // Any adapter -- first one found gbResult = DS2482_detect_sys( 1, chip_num, pin ) ; break ; default: // traditional, actual bus specified gbResult = DS2482_detect_bus( chip_num, ap.first.alpha, pin ) ; break ; } Free_Address( &ap ) ; return gbResult ; }
/* Re-open a DS2482 */ static GOOD_OR_BAD DS2482_redetect(const struct parsedname *pn) { struct connection_in *head = pn->selected_connection->master.i2c.head; int address = head->master.i2c.i2c_address; FILE_DESCRIPTOR_OR_ERROR file_descriptor; struct address_pair ap ; // to get device name from device:address /* open the i2c port */ Parse_Address( DEVICENAME(head), &ap ) ; file_descriptor = open(ap.first.alpha, O_RDWR ); Free_Address( &ap ) ; if ( FILE_DESCRIPTOR_NOT_VALID(file_descriptor) ) { ERROR_CONNECT("Could not open i2c device %s", DEVICENAME(head)); return gbBAD; } /* address is known */ if (ioctl(file_descriptor, I2C_SLAVE, address) < 0) { ERROR_CONNECT("Cound not set i2c address to %.2X", address); } else { BYTE c; /* write the RESET code */ if (i2c_smbus_write_byte(file_descriptor, DS2482_CMD_RESET) // reset || BAD(DS2482_readstatus(&c, file_descriptor, DS2482_Chip_reset_usec)) // pause .5 usec then read status || (c != (DS2482_REG_STS_LL | DS2482_REG_STS_RST)) // make sure status is properly set ) { LEVEL_CONNECT("i2c device at %s address %d cannot be reset. Not a DS2482.", DEVICENAME(head), address); } else { struct connection_in * next ; head->master.i2c.current = 0; head->pown->file_descriptor = file_descriptor; head->pown->state = cs_deflowered ; head->pown->type = ct_i2c ; head->master.i2c.configchip = 0x00; // default configuration register after RESET LEVEL_CONNECT("i2c device at %s address %d reset successfully", DEVICENAME(head), address); for ( next = head->pown->first; next; next = next->next ) { /* loop through devices, matching those that have the same "head" */ /* BUSLOCK also locks the sister channels for this */ next->reconnect_state = reconnect_ok; } return gbGOOD; } } /* fellthough, no device found */ close(file_descriptor); return gbBAD; }
/* Open a DS9490 -- low level code (to allow for repeats) */ static GOOD_OR_BAD DS9490_redetect_specific_adapter( struct connection_in * in) { struct address_pair ap ; GOOD_OR_BAD gbResult ; Parse_Address( in->pown->init_data, &ap ) ; if ( ap.first.type != address_numeric || ap.second.type != address_numeric ) { LEVEL_DEBUG("Cannot understand the specific usb address pair to reconnect <%s>",in->pown->init_data) ; gbResult = gbBAD ; } else { /* Have to protect usb_find_busses() and usb_find_devices() with * a lock since libusb could crash if 2 threads call it at the same time. * It's not called until DS9490_redetect_low(), but I lock here just * to be sure DS9490_close() and DS9490_open() get one try first. */ LIBUSBLOCK; DS9490_close( in ) ; gbResult = DS9490_detect_specific_adapter( ap.first.number, ap.second.number, in) ; LIBUSBUNLOCK; } Free_Address( &ap ) ; return gbResult ; }
/* Device-specific functions */ GOOD_OR_BAD ENET_monitor_detect(struct port_in *pin) { struct connection_in * in = pin->first ; struct address_pair ap ; pthread_t thread ; /* init_data has form "scan" or "scan:15" (15 seconds) */ Parse_Address( pin->init_data, &ap ) ; in->master.enet_monitor.enet_scan_interval = DEFAULT_ENET_SCAN_INTERVAL ; switch ( ap.entries ) { case 0: in->master.enet_monitor.enet_scan_interval = DEFAULT_ENET_SCAN_INTERVAL ; break ; case 1: switch( ap.first.type ) { case address_numeric: in->master.enet_monitor.enet_scan_interval = ap.first.number ; break ; default: in->master.enet_monitor.enet_scan_interval = DEFAULT_ENET_SCAN_INTERVAL ; break ; } break ; case 2: switch( ap.second.type ) { case address_numeric: in->master.enet_monitor.enet_scan_interval = ap.second.number ; break ; default: in->master.enet_monitor.enet_scan_interval = DEFAULT_ENET_SCAN_INTERVAL ; break ; } break ; } Free_Address( &ap ) ; pin->type = ct_none ; // Device name will not be init_data copy SAFEFREE(DEVICENAME(in)) ; DEVICENAME(in) = owstrdup("ENET bus monitor") ; pin->file_descriptor = FILE_DESCRIPTOR_BAD; in->iroutines.detect = ENET_monitor_detect; in->Adapter = adapter_enet_monitor; in->iroutines.reset = NO_RESET_ROUTINE; in->iroutines.next_both = NO_NEXT_BOTH_ROUTINE; in->iroutines.PowerByte = NO_POWERBYTE_ROUTINE; in->iroutines.ProgramPulse = NO_PROGRAMPULSE_ROUTINE; in->iroutines.sendback_data = NO_SENDBACKDATA_ROUTINE; in->iroutines.sendback_bits = NO_SENDBACKBITS_ROUTINE; in->iroutines.select = NO_SELECT_ROUTINE; in->iroutines.select_and_sendback = NO_SELECTANDSENDBACK_ROUTINE ; in->iroutines.set_config = NO_SET_CONFIG_ROUTINE; in->iroutines.get_config = NO_GET_CONFIG_ROUTINE; in->iroutines.reconnect = NO_RECONNECT_ROUTINE; in->iroutines.close = ENET_monitor_close; in->iroutines.verify = NO_VERIFY_ROUTINE ; in->iroutines.flags = ADAP_FLAG_sham; in->adapter_name = "ENET scan"; pin->busmode = bus_enet_monitor ; // repeat since can come via usb=scan Init_Pipe( in->master.enet_monitor.shutdown_pipe ) ; if ( pipe( in->master.enet_monitor.shutdown_pipe ) != 0 ) { ERROR_DEFAULT("Cannot allocate a shutdown pipe. The program shutdown may be messy"); Init_Pipe( in->master.enet_monitor.shutdown_pipe ) ; } if ( BAD( ENET_monitor_in_use(pin) ) ) { LEVEL_CONNECT("Second call for ENET scanning ignored") ; return gbBAD ; } if ( pthread_create(&thread, DEFAULT_THREAD_ATTR, ENET_monitor_loop, (void *) in) != 0 ) { ERROR_CALL("Cannot create the ENET monitoring program thread"); return gbBAD ; } return gbGOOD ; }
GOOD_OR_BAD ClientAddr(char *sname, char * default_port, struct connection_in *in) { struct port_in * pin = in->pown ; struct addrinfo hint; struct address_pair ap ; int ret; Parse_Address( sname, &ap ) ; switch ( ap.entries ) { case 0: // Complete default address pin->dev.tcp.host = NULL; pin->dev.tcp.service = owstrdup(default_port); break ; case 1: // single entry -- usually port unless a dotted quad switch ( ap.first.type ) { case address_none: pin->dev.tcp.host = NULL; pin->dev.tcp.service = owstrdup(default_port); break ; case address_dottedquad: // looks like an IP address pin->dev.tcp.host = owstrdup(ap.first.alpha); pin->dev.tcp.service = owstrdup(default_port); break ; case address_numeric: pin->dev.tcp.host = NULL; pin->dev.tcp.service = owstrdup(ap.first.alpha); break ; default: // assume it's a port if it's the SERVER if ( strcasecmp( default_port, DEFAULT_SERVER_PORT ) == 0 ) { pin->dev.tcp.host = NULL; pin->dev.tcp.service = owstrdup(ap.first.alpha); } else { pin->dev.tcp.host = owstrdup(ap.first.alpha); pin->dev.tcp.service = owstrdup(default_port); } break ; } break ; case 2: default: // address:port format -- unambiguous pin->dev.tcp.host = ( ap.first.type == address_none ) ? NULL : owstrdup(ap.first.alpha) ; pin->dev.tcp.service = ( ap.second.type == address_none ) ? owstrdup(default_port) : owstrdup(ap.second.alpha) ; break ; } Free_Address( &ap ) ; memset(&hint, 0, sizeof(struct addrinfo)); // hint.ai_socktype = SOCK_STREAM | SOCK_CLOEXEC ; hint.ai_socktype = SOCK_STREAM ; #if OW_CYGWIN hint.ai_family = AF_INET; if( pin->dev.tcp.host == NULL) { /* getaddrinfo doesn't work with host=NULL for cygwin */ pin->dev.tcp.host = owstrdup("127.0.0.1"); } #else hint.ai_family = AF_UNSPEC; #endif LEVEL_DEBUG("IP address=[%s] port=[%s]", SAFESTRING( pin->dev.tcp.host), pin->dev.tcp.service); ret = getaddrinfo( pin->dev.tcp.host, pin->dev.tcp.service, &hint, &( pin->dev.tcp.ai) ) ; if ( ret != 0 ) { LEVEL_CONNECT("GETADDRINFO error %s", gai_strerror(ret)); return gbBAD; } return gbGOOD; }
/* Main routine for detecting (and setting up) the DS2490 1-wire USB chip */ GOOD_OR_BAD DS9490_detect(struct port_in *pin) { struct connection_in * in = pin->first ; struct address_pair ap ; GOOD_OR_BAD gbResult = gbBAD; DS9490_setroutines(in); if ( in->master.usb.lusb_dev != NULL ) { // special case: exists (from scan) return DS9490_open_and_name( in->master.usb.lusb_dev, in ) ; // Note DS9490_ID_this_master needs to be called, // but the bus hasn't yet been added. // So it's done in USB_scan_for_adapters } /* uses "name" before it's cleared by connection_init */ Parse_Address( pin->init_data, &ap ) ; switch ( ap.entries ) { case 0: // Minimal specification, so use first USB device gbResult = DS9490_detect_single_adapter( 1, in) ; break ; case 1: switch( ap.first.type ) { case address_all: case address_asterix: LEVEL_DEBUG("Look for all USB adapters"); gbResult = DS9490_detect_all_adapters(pin) ; break ; case address_numeric: LEVEL_DEBUG("Look for USB adapter number %d",ap.first.number); gbResult = DS9490_detect_single_adapter( ap.first.number, in) ; break ; case address_scan: // completely change personality! gbResult = USB_monitor_detect(pin) ; break ; default: LEVEL_DEFAULT("Unclear what <%s> means in USB specification, will use first adapter.",ap.first.alpha) ; gbResult = DS9490_detect_single_adapter( 1, in) ; break ; } break ; case 2: switch( ap.first.type ) { case address_all: case address_asterix: LEVEL_DEBUG("Look for all USB adapters"); gbResult = DS9490_detect_all_adapters(pin) ; break ; case address_numeric: LEVEL_DEBUG("Look for USB adapter number %d:%d",ap.first.number,ap.second.number); gbResult = DS9490_detect_specific_adapter( ap.first.number, ap.second.number, in ) ; break ; case address_scan: // completely change personality! gbResult = USB_monitor_detect(pin) ; break ; default: LEVEL_DEFAULT("USB address <%s:%s> not in number:number format",ap.first.alpha,ap.second.alpha) ; gbResult = gbBAD ; break ; } break ; } Free_Address( &ap ) ; return gbResult; }