/* It does call lower level functions for higher ones, which of course is pointless since the lower ones don't work either */ GOOD_OR_BAD BadAdapter_detect(struct port_in *pin) { struct connection_in * in = pin->first ; pin->type = ct_none ; pin->file_descriptor = FILE_DESCRIPTOR_BAD ; in->Adapter = adapter_Bad; /* OWFS assigned value */ in->iroutines.reset = BadAdapter_reset; 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 = BadAdapter_sendback_bits; 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 = BadAdapter_close; in->iroutines.verify = NO_VERIFY_ROUTINE ; in->iroutines.flags = ADAP_FLAG_sham; in->adapter_name = "Bad Adapter"; SAFEFREE( DEVICENAME(in) ) ; DEVICENAME(in) = owstrdup("None") ; pin->busmode = bus_bad ; return gbGOOD; }
/* Choose in order: * (first) 0x81 * (first) 0x01 * first other family * 0x00 * */ GOOD_OR_BAD DS9490_ID_this_master(struct connection_in *in) { struct dirblob db ; BYTE sn[SERIAL_NUMBER_SIZE] ; int device_number ; RETURN_BAD_IF_BAD( DS9490_root_dir( &db, in ) ) ; // Use 0x00 if no devices (homegrown adapters?) if ( DirblobElements( &db) == 0 ) { DirblobClear( &db ) ; memset( in->master.usb.ds1420_address, 0, SERIAL_NUMBER_SIZE ) ; LEVEL_DEFAULT("Set DS9490 %s unique id 0x00 (no devices at all)", SAFESTRING(DEVICENAME(in))) ; return gbGOOD ; } // look for the special 0x81 device device_number = 0 ; while ( DirblobGet( device_number, sn, &db ) == 0 ) { if (sn[0] == 0x81) { // 0x81 family code memcpy(in->master.usb.ds1420_address, sn, SERIAL_NUMBER_SIZE); LEVEL_DEFAULT("Set DS9490 %s unique id to " SNformat, SAFESTRING(DEVICENAME(in)), SNvar(in->master.usb.ds1420_address)); DirblobClear( &db ) ; return gbGOOD ; } ++device_number ; } // look for the (less specific, for older DS9490s) 0x01 device device_number = 0 ; while ( DirblobGet( device_number, sn, &db ) == 0 ) { if (sn[0] == 0x01) { // 0x01 family code memcpy(in->master.usb.ds1420_address, sn, SERIAL_NUMBER_SIZE); LEVEL_DEFAULT("Set DS9490 %s unique id to " SNformat, SAFESTRING(DEVICENAME(in)), SNvar(in->master.usb.ds1420_address)); DirblobClear( &db ) ; return gbGOOD ; } ++device_number ; } // Take the first device, whatever it is DirblobGet( 0, sn, &db ) ; memcpy(in->master.usb.ds1420_address, sn, SERIAL_NUMBER_SIZE); LEVEL_DEFAULT("Set DS9490 %s unique id to " SNformat, SAFESTRING(DEVICENAME(in)), SNvar(in->master.usb.ds1420_address)); DirblobClear( &db ) ; return gbGOOD; }
/* When the errors stop the USB device from functioning -- close and reopen. * If it fails, re-scan the USB bus and search for the old adapter */ static GOOD_OR_BAD DS9490_reconnect(const struct parsedname *pn) { GOOD_OR_BAD ret; struct connection_in * in = pn->selected_connection ; if ( in->master.usb.specific_usb_address ) { // special case where a usb bus:dev pair was given // only connect to the same spot return DS9490_redetect_specific_adapter( in ) ; } /* 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 ) ; ret = DS9490_redetect_low(in) ; LIBUSBUNLOCK; if ( GOOD(ret) ) { LEVEL_DEFAULT("Found USB DS9490 bus master after USB rescan as [%s]", SAFESTRING(DEVICENAME(in))); } return ret; }
/* Only error is if parsename fails */ GOOD_OR_BAD DS9490_root_dir( struct dirblob * db, struct connection_in * in ) { ASCII path[PATH_MAX] ; struct parsedname pn_root ; UCLIBCLOCK; /* Force this adapter with bus.n path */ snprintf(path, PATH_MAX, "/uncached/bus.%d", in->index); UCLIBCUNLOCK; if ( FS_ParsedName(path, &pn_root) != 0 ) { LEVEL_DATA("Cannot get root directory on [%s] Parsing %s error.", SAFESTRING(DEVICENAME(in)), path); return gbBAD ; } DirblobInit( db ) ; /* First time pretend there are devices */ pn_root.selected_connection->changed_bus_settings |= CHANGED_USB_SPEED ; // Trigger needing new configuration pn_root.selected_connection->overdrive = 0 ; // not overdrive at start pn_root.selected_connection->flex = Globals.usb_flextime ; SetReconnect(&pn_root) ; FS_dir( DS9490_dir_callback, db, &pn_root ) ; LEVEL_DEBUG("Finished FS_dir"); FS_ParsedName_destroy(&pn_root) ; return gbGOOD ; // Dirblob must be cleared by recipient. }
/* 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; }
GOOD_OR_BAD FS_FindHA7(void) { struct addrinfo *ai; struct addrinfo hint; struct addrinfo *now; int number_found = 0; int getaddr_error ; LEVEL_DEBUG("Attempting udp multicast search for the HA7Net bus master at %s:%s",HA7_DISCOVERY_ADDRESS,HA7_DISCOVERY_PORT); Setup_HA7_hint( &hint ) ; if ((getaddr_error = getaddrinfo(HA7_DISCOVERY_ADDRESS, HA7_DISCOVERY_PORT, &hint, &ai))) { LEVEL_CONNECT("Couldn't set up HA7 broadcast message %s", gai_strerror(getaddr_error)); return gbBAD; } for (now = ai; now; now = now->ai_next) { ASCII name[INET_ADDRSTRLEN+20]; // tcp quad + port struct port_in * pin ; struct connection_in *in; if ( Get_HA7_response( now, name ) ) { continue ; } pin = NewPort(NO_CONNECTION) ; if (pin == NULL) { continue; } in = pin->first ; pin->type = ct_tcp ; pin->init_data = owstrdup(name); DEVICENAME(in) = owstrdup(name); pin->busmode = bus_ha7net; LEVEL_CONNECT("HA7Net bus master discovered at %s",DEVICENAME(in)); ++number_found ; } freeaddrinfo(ai); return number_found > 0 ? gbGOOD : gbBAD ; }
// Open usb device, // dev already set static GOOD_OR_BAD DS9490_open_and_name( libusb_device * dev, struct connection_in *in) { if (in->master.usb.lusb_handle != NULL) { LEVEL_DEFAULT("DS9490 %s was NOT closed?", DEVICENAME(in)); return gbBAD ; } DS9490_port_setup( dev, in->pown ) ; if ( BAD( DS9490_open( in ) ) ) { STAT_ADD1_BUS(e_bus_open_errors, in); return gbBAD ; } else if ( BAD( DS9490_setup_adapter(in)) ) { LEVEL_DEFAULT("Error setting up USB DS9490 bus master at %s.", DEVICENAME(in)); DS9490_close( in ) ; return gbBAD ; } DS9490_SetFlexParameters(in); return gbGOOD ; }
static void SetConninData( int indx, const char * type, struct port_in *pin ) { struct connection_in * in = pin->first ; char name[20] ; pin->file_descriptor = indx; pin->type = ct_none ; in->master.fake.index = indx; in->master.fake.templow = Globals.templow; in->master.fake.temphigh = Globals.temphigh; LEVEL_CONNECT("Setting up %s Bus Master (%d)", type, indx); UCLIBCLOCK ; snprintf(name, 18, "%s.%d", type, indx); UCLIBCUNLOCK ; GetAllDeviceNames( pin ) ; // Device name and init_data diverge now SAFEFREE(DEVICENAME(in)) ; DEVICENAME(in) = owstrdup(name); }
/* Open a DS9490 -- low level code (to allow for repeats) */ static GOOD_OR_BAD DS9490_redetect_match( struct connection_in * in) { struct dirblob db ; BYTE sn[SERIAL_NUMBER_SIZE] ; int device_number ; LEVEL_DEBUG("Attempting reconnect on %s",SAFESTRING(DEVICENAME(in))); // Special case -- originally untagged adapter if ( in->master.usb.ds1420_address[0] == '\0' ) { LEVEL_CONNECT("Since originally untagged bus master, we will use first available slot."); return gbGOOD ; } // Generate a root directory RETURN_BAD_IF_BAD( DS9490_root_dir( &db, in ) ) ; // This adapter has no tags, so not the one we want if ( DirblobElements( &db) == 0 ) { DirblobClear( &db ) ; LEVEL_DATA("Empty directory on [%s] (Doesn't match initial scan).", SAFESTRING(DEVICENAME(in))); return gbBAD ; } // Scan directory for a match to the original tag device_number = 0 ; while ( DirblobGet( device_number, sn, &db ) == 0 ) { if (memcmp(sn, in->master.usb.ds1420_address, SERIAL_NUMBER_SIZE) == 0) { // same tag device? LEVEL_DATA("Matching device [%s].", SAFESTRING(DEVICENAME(in))); DirblobClear( &db ) ; return gbGOOD ; } ++device_number ; } // Couldn't find correct ds1420 chip on this adapter LEVEL_CONNECT("Couldn't find correct ds1420 chip on this bus master [%s] (want: " SNformat ")", SAFESTRING(DEVICENAME(in)), SNvar(in->master.usb.ds1420_address)); DirblobClear( &db ) ; return gbBAD; }
//open serial port ( called on head of connection_in group from com_open ) GOOD_OR_BAD serial_open(struct connection_in *connection) { struct port_in * pin = connection->pown ; FILE_DESCRIPTOR_OR_ERROR fd = open( DEVICENAME(connection), O_RDWR | O_NONBLOCK | O_NOCTTY) ; pin->file_descriptor = fd ; if ( FILE_DESCRIPTOR_NOT_VALID( fd ) ) { // state doesn't change ERROR_DEFAULT("Cannot open port: %s Permissions problem?", SAFESTRING(DEVICENAME(connection))); return gbBAD; } if ( pin->state == cs_virgin ) { // valgrind warns about uninitialized memory in tcsetattr(), so clear all. memset( &(pin->dev.serial.oldSerialTio), 0, sizeof(struct termios)); if ((tcgetattr( fd, &(pin->dev.serial.oldSerialTio) ) < 0)) { ERROR_CONNECT("Cannot get old port attributes: %s", SAFESTRING(DEVICENAME(connection))); // proceed anyway } pin->state = cs_deflowered ; } return serial_change( connection ) ; }
/* This allows removing Bus Masters while program is running * The master is usually only read-locked for normal operation * write lock is done in a separate thread when no requests are being processed */ void Del_InFlight( GOOD_OR_BAD (*nomatch)(struct port_in * trial,struct port_in * existing), struct port_in * old_pin ) { struct connection_in * old_in ; if ( old_pin == NULL ) { return ; } old_in = old_pin->first ; LEVEL_DEBUG("Request master be removed: %s", DEVICENAME(old_in)); if ( nomatch != NULL ) { struct port_in * pin ; CONNIN_WLOCK ; for ( pin = Inbound_Control.head_port ; pin != NULL ; pin = pin->next ) { if ( BAD( nomatch( old_pin, pin )) ) { LEVEL_DEBUG("Removing BUS index=%d %s",pin->first->index,SAFESTRING(DEVICENAME(pin->first))); RemovePort(pin) ; } } CONNIN_WUNLOCK ; } }
// 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 ; }
/* Puts in 9600 baud */ static GOOD_OR_BAD DS9097_pre_reset(struct connection_in *in ) { struct port_in * pin = in->pown ; RETURN_BAD_IF_BAD( COM_test(in) ) ; /* 8 data bits */ pin->bits = 8 ; pin->baud = B9600 ; if ( BAD( COM_change(in)) ) { ERROR_CONNECT("Cannot set attributes: %s", SAFESTRING(DEVICENAME(in))); DS9097_post_reset( in ) ; return gbBAD; } return gbGOOD; }
void TrafficIn( const char * data_type, const BYTE * data, size_t length, const struct connection_in * in ) { fprintf(stderr, "TRAFFIC IN <%s> bus=%d (%s)\n", SAFESTRING(data_type), in->index, DEVICENAME(in) ) ; _Debug_Bytes( in->adapter_name, data, length ) ; }
//change serial port settings GOOD_OR_BAD serial_change(struct connection_in *connection) { struct port_in * pin = connection->pown ; struct termios newSerialTio; /*new serial port settings */ FILE_DESCRIPTOR_OR_ERROR fd = pin->file_descriptor ; size_t baud = pin->baud ; // read the attribute structure // valgrind warns about uninitialized memory in tcsetattr(), so clear all. memset(&newSerialTio, 0, sizeof(struct termios)); if ((tcgetattr( fd, &newSerialTio) < 0)) { ERROR_CONNECT("Cannot get existing port attributes: %s", SAFESTRING(DEVICENAME(connection))); } // set baud in structure if (cfsetospeed(&newSerialTio, baud) < 0 || cfsetispeed(&newSerialTio, baud) < 0) { ERROR_CONNECT("Trouble setting port speed: %s", SAFESTRING(DEVICENAME(connection))); cfsetospeed(&newSerialTio, B9600) ; cfsetispeed(&newSerialTio, B9600) ; pin->baud = B9600 ; } // Set to non-canonical mode, and no RTS/CTS handshaking newSerialTio.c_iflag &= ~(BRKINT | ICRNL | IGNCR | INLCR | INPCK | ISTRIP | IXON | IXOFF | PARMRK); newSerialTio.c_iflag |= IGNBRK | IGNPAR; newSerialTio.c_oflag &= ~(OPOST); newSerialTio.c_cflag &= ~ HUPCL ; newSerialTio.c_cflag |= (CLOCAL | CREAD); switch( pin->flow ) { case flow_hard: newSerialTio.c_cflag |= CRTSCTS ; break ; case flow_none: newSerialTio.c_cflag &= ~CRTSCTS; break ; case flow_soft: default: LEVEL_DEBUG("Unsupported COM port flow control"); return -ENOTSUP ; } // set bit length newSerialTio.c_cflag &= ~ CSIZE ; switch (pin->bits) { case 5: newSerialTio.c_cflag |= CS5 ; break ; case 6: newSerialTio.c_cflag |= CS6 ; break ; case 7: newSerialTio.c_cflag |= CS7 ; break ; case 8: default: newSerialTio.c_cflag |= CS8 ; break ; } // parity switch (pin->parity) { case parity_none: newSerialTio.c_cflag &= ~PARENB ; break ; case parity_even: newSerialTio.c_cflag |= PARENB ; newSerialTio.c_cflag &= ~( PARODD | CMSPAR ) ; break ; case parity_odd: newSerialTio.c_cflag |= PARENB | PARODD; newSerialTio.c_cflag &= ~CMSPAR ; break ; case parity_mark: newSerialTio.c_cflag |= PARENB | PARODD | CMSPAR; break ; } // stop bits switch (pin->stop) { case stop_15: LEVEL_DEBUG("1.5 Stop bits not supported"); pin->stop = stop_1 ; // fall through case stop_1: newSerialTio.c_cflag &= ~CSTOPB ; break ; case stop_2: newSerialTio.c_cflag |= CSTOPB ; break ; } newSerialTio.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL | ICANON | IEXTEN | ISIG); newSerialTio.c_cc[VMIN] = pin->vmin; newSerialTio.c_cc[VTIME] = pin->vtime; if (tcsetattr( fd, TCSAFLUSH, &newSerialTio)) { ERROR_CONNECT("Cannot set port attributes: %s", SAFESTRING(DEVICENAME(connection))); return gbBAD; } tcflush( fd, TCIOFLUSH); return gbGOOD; }
/* Try to see if there is a DS2482 device on the specified i2c bus */ static GOOD_OR_BAD DS2482_detect_single(int lowindex, int highindex, char * i2c_device, struct port_in *pin) { int test_address[8] = { 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, }; // the last 4 are -800 only int i2c_index; FILE_DESCRIPTOR_OR_ERROR file_descriptor; struct connection_in * in = pin->first ; /* Sanity check */ if ( lowindex < 0 ) { LEVEL_DEBUG("Bad lower bound"); return gbBAD ; } if ( highindex >= (int) (sizeof(test_address)/sizeof(int)) ) { LEVEL_DEBUG("Bad upper bound"); return gbBAD ; } /* open the i2c port */ file_descriptor = open(i2c_device, O_RDWR); if ( FILE_DESCRIPTOR_NOT_VALID(file_descriptor) ) { ERROR_CONNECT("Could not open i2c device %s", i2c_device); return gbBAD; } /* Set up low-level routines */ DS2482_setroutines(in); for (i2c_index = lowindex; i2c_index <= highindex; ++i2c_index) { int trial_address = test_address[i2c_index] ; /* set the candidate address */ if (ioctl(file_descriptor, I2C_SLAVE, trial_address) < 0) { ERROR_CONNECT("Cound not set trial i2c address to %.2X", trial_address); } else { BYTE c; LEVEL_CONNECT("Found an i2c device at %s address %.2X", i2c_device, trial_address); /* Provisional setup as a DS2482-100 ( 1 channel ) */ in->pown->file_descriptor = file_descriptor; pin->state = cs_deflowered; pin->type = ct_i2c ; in->master.i2c.i2c_address = trial_address; in->master.i2c.i2c_index = i2c_index; in->master.i2c.index = 0; in->master.i2c.channels = 1; in->master.i2c.current = 0; in->master.i2c.head = in; in->adapter_name = "DS2482-100"; in->master.i2c.configreg = 0x00 ; // default configuration setting desired if ( Globals.i2c_APU ) { in->master.i2c.configreg |= DS2482_REG_CFG_APU ; } if ( Globals.i2c_PPM ) { in->master.i2c.configreg |= DS2482_REG_CFG_PPM ; } in->Adapter = adapter_DS2482_100; /* 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 %.2X cannot be reset. Not a DS2482.", i2c_device, trial_address); continue; } LEVEL_CONNECT("i2c device at %s address %.2X appears to be DS2482-x00", i2c_device, trial_address); in->master.i2c.configchip = 0x00; // default configuration register after RESET // Note, only the lower nibble of the device config stored // Create name SAFEFREE( DEVICENAME(in) ) ; DEVICENAME(in) = owmalloc( strlen(i2c_device) + 10 ) ; if ( DEVICENAME(in) ) { UCLIBCLOCK; snprintf(DEVICENAME(in), strlen(i2c_device) + 10, "%s:%.2X", i2c_device, trial_address); UCLIBCUNLOCK; } /* Now see if DS2482-100 or DS2482-800 */ return HeadChannel(in); } } /* fell though, no device found */ COM_close( in ) ; return gbBAD; }
/* special check, -remote file length won't match local sizes */ static ZERO_OR_ERROR FS_port(struct one_wire_query *owq) { return OWQ_format_output_offset_and_size_z( SAFESTRING( DEVICENAME(PN(owq)->selected_connection)), owq); }
static GOOD_OR_BAD K1WM_reconnect(const struct parsedname * pn) { LEVEL_DEBUG("Attempting reconnect on %s",SAFESTRING(DEVICENAME(pn->selected_connection))); return K1WM_setup(pn->selected_connection) ; }
/* 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 ; }