/* Open a DS9490 -- low level code (to allow for repeats) */ static GOOD_OR_BAD DS9490_redetect_low(struct connection_in * in) { // discover devices libusb_device **device_list; int n_devices = libusb_get_device_list( Globals.luc, &device_list) ; int i_device ; if ( n_devices < 1 ) { LEVEL_CONNECT("Could not find a list of USB devices"); if ( n_devices<0 ) { LEVEL_DEBUG("<%s>",libusb_error_name(n_devices)); } return gbBAD; } for ( i_device = 0 ; i_device < n_devices ; ++i_device ) { libusb_device * current = device_list[i_device] ; if ( GOOD( USB_match( current ) ) ) { // try to open the DS9490 if ( BAD(DS9490_open_and_name( current, in )) ) { LEVEL_CONNECT("Cannot open USB bus master, Find next..."); continue; } if ( GOOD( DS9490_redetect_match( in ) ) ) { break ; } DS9490_close(in); } } libusb_free_device_list(device_list, 1); return (in->master.usb.lusb_handle!=NULL) ? gbGOOD : gbBAD ; }
/* All general stored data will be assigned to this "head" channel */ static GOOD_OR_BAD HeadChannel(struct connection_in *head) { /* Intentionally put the wrong index */ head->master.i2c.index = 1; if ( BAD(DS2482_channel_select(head)) ) { /* Couldn't switch */ head->master.i2c.index = 0; /* restore correct value */ LEVEL_CONNECT("DS2482-100 (Single channel)"); if ( GOOD(DS2483_test(head->pown->file_descriptor)) ) { head->master.i2c.type = ds2483 ; } else { head->master.i2c.type = ds2482_100 ; } return gbGOOD; /* happy as DS2482-100 */ } // It's a DS2482-800 (8 channels) to set up other 7 with this one as "head" LEVEL_CONNECT("DS2482-800 (Eight channels)"); /* Must be a DS2482-800 */ head->master.i2c.channels = 8; head->master.i2c.type = ds2482_800 ; head->Adapter = adapter_DS2482_800; return CreateChannels(head); }
/* Open a DS9490 -- low level code (to allow for repeats) */ static GOOD_OR_BAD DS9490_detect_all_adapters(struct port_in * pin_first) { // discover devices struct port_in * pin = pin_first ; libusb_device **device_list; int n_devices = libusb_get_device_list( Globals.luc, &device_list) ; int i_device ; if ( n_devices < 1 ) { LEVEL_CONNECT("Could not find a list of USB devices"); if ( n_devices<0 ) { LEVEL_DEBUG("<%s>",libusb_error_name(n_devices)); } return gbBAD ; } for ( i_device = 0 ; i_device < n_devices ; ++i_device ) { libusb_device * current = device_list[i_device] ; if ( GOOD( USB_match( current ) ) ) { struct connection_in * in = pin->first ; if ( BAD(DS9490_open_and_name( current, in)) ) { LEVEL_DEBUG("Cannot open USB device %.d:%.d", libusb_get_device_address(current), libusb_get_bus_number(current) ); continue ; } else if ( BAD(DS9490_ID_this_master(in)) ) { DS9490_close(in) ; LEVEL_DEBUG("Cannot access USB device %.d:%.d", libusb_get_device_address(current), libusb_get_bus_number(current) ); continue; } else{ pin = NewPort(NULL) ; // no reason to copy anything if ( pin == NULL ) { return gbGOOD ; } // set up the new connection for the next adapter DS9490_setroutines(in); } } } libusb_free_device_list(device_list, 1); if ( pin == pin_first ) { LEVEL_CONNECT("No USB DS9490 bus masters used"); return gbBAD; } // Remove the extra connection RemovePort(pin); return gbGOOD ; }
/* Open a DS9490 -- low level code (to allow for repeats) */ static GOOD_OR_BAD DS9490_detect_specific_adapter(int bus_nr, int dev_nr, struct connection_in * in) { // discover devices libusb_device **device_list; int n_devices = libusb_get_device_list( Globals.luc, &device_list) ; int i_device ; if ( n_devices < 1 ) { LEVEL_CONNECT("Could not find a list of USB devices"); if ( n_devices<0 ) { LEVEL_DEBUG("<%s>",libusb_error_name(n_devices)); } return gbBAD ; } // Mark this connection as taking only this address pair. Important for reconnections. in->master.usb.specific_usb_address = 1 ; for ( i_device = 0 ; i_device < n_devices ; ++i_device ) { libusb_device * current = device_list[i_device] ; if ( GOOD( USB_match( current ) ) ) { if ( libusb_get_bus_number(current) != bus_nr ) { continue ; } if ( libusb_get_device_address(current) != dev_nr ) { continue ; } if ( BAD(DS9490_open_and_name( current, in)) ) { LEVEL_DEBUG("Cannot open USB device %.d:%.d", libusb_get_device_address(current), libusb_get_bus_number(current) ); break ; } else if ( BAD(DS9490_ID_this_master(in)) ) { DS9490_close(in) ; LEVEL_DEBUG("Cannot access USB device %.d:%.d", libusb_get_device_address(current), libusb_get_bus_number(current) ); break ; } else{ libusb_free_device_list(device_list, 1); return gbGOOD ; } } } libusb_free_device_list(device_list, 1); LEVEL_CONNECT("No USB DS9490 bus master found matching %d:%d", bus_nr,dev_nr); return gbBAD; }
// Called in a thread static void * OW_Browse_Bonjour(void * v) { struct connection_in * in = v ; DNSServiceErrorType dnserr; DETACH_THREAD; MONITOR_RLOCK ; dnserr = DNSServiceBrowse(&in->master.browse.bonjour_browse, 0, 0, "_owserver._tcp", NULL, BrowseBack, NULL); if (dnserr != kDNSServiceErr_NoError) { LEVEL_CONNECT("DNSServiceBrowse error = %d", dnserr); MONITOR_RUNLOCK ; return VOID_RETURN ; } // Blocks, which is why this is in it's own thread while (DNSServiceProcessResult(in->master.browse.bonjour_browse) == kDNSServiceErr_NoError) { //printf("DNSServiceProcessResult ref %ld\n",(long int)rs->sref) ; continue; } DNSServiceRefDeallocate(in->master.browse.bonjour_browse); in->master.browse.bonjour_browse = 0 ; MONITOR_RUNLOCK ; return VOID_RETURN; }
/* Register the out port with Bonjour -- might block so done in a separate thread */ static void *Announce(void *v) { struct connection_out *out = v; DNSServiceRef sref = 0; DNSServiceErrorType err; struct sockaddr sa; //socklen_t sl = sizeof(sa); socklen_t sl = 128; uint16_t port ; char * service_name ; char name[63] ; DETACH_THREAD; if (getsockname(out->file_descriptor, &sa, &sl)) { LEVEL_CONNECT("Could not get port number of device."); pthread_exit(NULL); return VOID_RETURN; } port = ntohs(((struct sockaddr_in *) (&sa))->sin_port) ; /* Add the service */ switch (Globals.program_type) { case program_type_httpd: service_name = (Globals.announce_name) ? Globals.announce_name : "OWFS (1-wire) Web" ; UCLIBCLOCK; snprintf(name,62,"%s <%d>",service_name,(int)port); UCLIBCUNLOCK; err = DNSServiceRegister(&sref, 0, 0, name,"_http._tcp", NULL, NULL, port, 0, NULL, RegisterBack, out) ; Announce_Post_Register(sref, err) ; err = DNSServiceRegister(&sref, 0, 0, name,"_owhttpd._tcp", NULL, NULL, port, 0, NULL, RegisterBack, out) ; break ; case program_type_server: case program_type_external: service_name = (Globals.announce_name) ? Globals.announce_name : "OWFS (1-wire) Server" ; UCLIBCLOCK; snprintf(name,62,"%s <%d>",service_name,(int)port); UCLIBCUNLOCK; err = DNSServiceRegister(&sref, 0, 0, name,"_owserver._tcp", NULL, NULL, port, 0, NULL, RegisterBack, out) ; break; case program_type_ftpd: service_name = (Globals.announce_name) ? Globals.announce_name : "OWFS (1-wire) FTP" ; UCLIBCLOCK; snprintf(name,62,"%s <%d>",service_name,(int)port); UCLIBCUNLOCK; err = DNSServiceRegister(&sref, 0, 0, name,"_owftp._tcp", NULL, NULL, port, 0, NULL, RegisterBack, out) ; break; default: err = kDNSServiceErr_NoError ; break ; } Announce_Post_Register(sref, err) ; LEVEL_DEBUG("Normal completion"); pthread_exit(NULL); return VOID_RETURN; }
// RESET called with bus locked RESET_TYPE BUS_reset(const struct parsedname *pn) { struct connection_in * in = pn->selected_connection ; STAT_ADD1_BUS(e_bus_resets, in); switch ( (in->iroutines.reset) (pn) ) { case BUS_RESET_OK: in->reconnect_state = reconnect_ok; // Flag as good! if (in->ds2404_found && ((in->iroutines.flags&ADAP_FLAG_no2404delay)==0) ) { // extra delay for alarming DS1994/DS2404 complience UT_delay(5); } return BUS_RESET_OK ; case BUS_RESET_SHORT: /* Shorted 1-wire bus or minor error shouldn't cause a reconnect */ in->AnyDevices = anydevices_unknown; LEVEL_CONNECT("1-wire bus short circuit."); STAT_ADD1_BUS(e_bus_short_errors, in); return BUS_RESET_SHORT; case BUS_RESET_ERROR: if ( in->ds2404_found ) { // extra reset for DS1994/DS2404 might be needed if ( (in->iroutines.reset) (pn) == BUS_RESET_OK ) { return BUS_RESET_OK ; } } default: in->reconnect_state++; // Flag for eventual reconnection LEVEL_DEBUG("Reset error. Reconnection %d/%d",in->reconnect_state,reconnect_error); STAT_ADD1_BUS(e_bus_reset_errors, in); return BUS_RESET_ERROR ; } }
/* Includes a count of the rejected existing USB devices * needed for compatibility with the -u2 -u3 arguments */ GOOD_OR_BAD USB_next_match_until_n(struct usb_list *ul, int num) { int found = 0 ; while (ul->bus) { // First pass, look for next device if (ul->dev == NULL) { ul->dev = ul->bus->devices; } else { // New bus, find first device ul->dev = ul->dev->next; ul->usb_dev_number = -1 ; } if (ul->dev) { // device found if (ul->dev->descriptor.idVendor != DS2490_USB_VENDOR || ul->dev->descriptor.idProduct != DS2490_USB_PRODUCT) { continue; // not DS9490 } if ( sscanf( ul->dev->filename, "%u", &(ul->usb_dev_number) ) <= 0 ) { ul->usb_dev_number = -1 ; } ++ found ; if ( found < num ) { continue ; } LEVEL_CONNECT("Bus master found: %.d:%.d", ul->usb_bus_number, ul->usb_dev_number); return usbdevice_in_use( ul ); } else { ul->bus = ul->bus->next; if ( ul->bus == NULL || sscanf( ul->bus->dirname, "%u", &(ul->usb_bus_number) ) <= 0 ) { ul->usb_bus_number = -1 ; } ul->dev = NULL; } } return gbBAD; }
/* 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; }
void OW_Browse(struct connection_in *in) { if ( Globals.zero == zero_avahi ) { #if OW_AVAHI if ( BAD(OW_Avahi_Browse(in))) { LEVEL_CONNECT("Avahi Browse problem."); } #endif /* OW_AVAHI */ } else if ( Globals.zero == zero_bonjour ) { pthread_t thread; int err = pthread_create(&thread, DEFAULT_THREAD_ATTR, OW_Browse_Bonjour, (void *) in); if (err) { LEVEL_CONNECT("Bonjour Browse thread error %d.", err); } } }
static void Announce_Post_Register(DNSServiceRef sref, DNSServiceErrorType err) { if (err == kDNSServiceErr_NoError) { DNSServiceProcessResult(sref); } else { LEVEL_CONNECT("Unsuccessful call to DNSServiceRegister err = %d", err); } }
/* Open a DS9490 -- low level code (to allow for repeats) */ static GOOD_OR_BAD DS9490_detect_single_adapter(int usb_nr, struct connection_in * in) { // discover devices libusb_device **device_list; int n_devices = libusb_get_device_list( Globals.luc, &device_list) ; int i_device ; if ( n_devices < 1 ) { LEVEL_CONNECT("Could not find a list of USB devices"); if ( n_devices<0 ) { LEVEL_DEBUG("<%s>",libusb_error_name(n_devices)); } return gbBAD ; } for ( i_device = 0 ; i_device < n_devices ; ++i_device ) { libusb_device * current = device_list[i_device] ; if ( GOOD( USB_match( current ) ) ) { --usb_nr ; if ( usb_nr > 0 ) { continue ; } if ( BAD(DS9490_open_and_name( current, in)) ) { LEVEL_DEBUG("Cannot open USB device %.d:%.d", libusb_get_device_address(current), libusb_get_bus_number(current) ); break ; } else if ( BAD(DS9490_ID_this_master(in)) ) { DS9490_close(in) ; LEVEL_DEBUG("Cannot access USB device %.d:%.d", libusb_get_device_address(current), libusb_get_bus_number(current) ); break ; } else{ libusb_free_device_list(device_list, 1); return gbGOOD ; } } } libusb_free_device_list(device_list, 1); LEVEL_CONNECT("No USB DS9490 bus master found"); return gbBAD; }
static int Test_HA7_response( struct HA7_response * ha7_response ) { LEVEL_DEBUG("From ha7_response: signature=%.2s, command=%X, port=%d, ssl=%d, MAC=%.12s, device=%s", ha7_response->signature, ntohs(ha7_response->command), ntohs(ha7_response->port), ntohs(ha7_response->sslport), ha7_response->serial_num, ha7_response->dev_name) ; if (memcmp("HA", ha7_response->signature, 2)) { LEVEL_CONNECT("HA7 response signature error"); return 1; } if ( 0x8001 != ntohs(ha7_response->command) ) { LEVEL_CONNECT("HA7 response command error"); return 1; } return 0 ; }
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 ; }
static GOOD_OR_BAD DS2482_channel_select(struct connection_in * in) { struct connection_in *head = in->master.i2c.head; int chan = in->master.i2c.index; FILE_DESCRIPTOR_OR_ERROR file_descriptor = in->pown->file_descriptor; /* Write and verify codes for the CHANNEL_SELECT command (DS2482-800 only). To set the channel, write the value at the index of the channel. Read and compare against the corresponding value to verify the change. */ static const BYTE W_chan[8] = { 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87 }; static const BYTE R_chan[8] = { 0xB8, 0xB1, 0xAA, 0xA3, 0x9C, 0x95, 0x8E, 0x87 }; if ( FILE_DESCRIPTOR_NOT_VALID(file_descriptor) ) { LEVEL_CONNECT("Calling a closed i2c channel (%d) "I2Cformat" ", chan,I2Cvar(in)); return gbBAD; } /* Already properly selected? */ /* All `100 (1 channel) will be caught here */ if (chan != head->master.i2c.current) { int read_back; /* Select command */ if (i2c_smbus_write_byte_data(file_descriptor, DS2482_CMD_CHANNEL_SELECT, W_chan[chan]) < 0) { LEVEL_DEBUG("Channel select set error"); return gbBAD; } /* Read back and confirm */ read_back = i2c_smbus_read_byte(file_descriptor); if (read_back < 0) { LEVEL_DEBUG("Channel select get error"); return gbBAD; // flag for DS2482-100 vs -800 detection } if (((BYTE) read_back) != R_chan[chan]) { LEVEL_DEBUG("Channel selected doesn't match"); return gbBAD; // flag for DS2482-100 vs -800 detection } /* Set the channel in head */ head->master.i2c.current = in->master.i2c.index; } /* Now check the configuration register */ /* This is since configuration is per chip, not just channel */ if (in->master.i2c.configreg != head->master.i2c.configchip) { return SetConfiguration(in->master.i2c.configreg, in); } return gbGOOD; }
/* Stolen from Unix Network Programming by Stevens, Fenner, Rudoff p89 */ ssize_t tcp_read(int file_descriptor, void *vptr, size_t n, const struct timeval * ptv) { size_t nleft; ssize_t nread; char *ptr; //printf("NetRead attempt %d bytes Time:(%ld,%ld)\n",(int)n,ptv->tv_sec,ptv->tv_usec ) ; ptr = vptr; nleft = n; while (nleft > 0) { int rc; fd_set readset; struct timeval tv = { ptv->tv_sec, ptv->tv_usec, }; /* Initialize readset */ FD_ZERO(&readset); FD_SET(file_descriptor, &readset); /* Read if it doesn't timeout first */ rc = select(file_descriptor + 1, &readset, NULL, NULL, &tv); if (rc > 0) { /* Is there something to read? */ if (FD_ISSET(file_descriptor, &readset) == 0) { return -EIO; /* error */ } //update_max_delay(pn); if ((nread = read(file_descriptor, ptr, nleft)) < 0) { if (errno == EINTR) { errno = 0; // clear errno. We never use it anyway. nread = 0; /* and call read() again */ } else { ERROR_DATA("Network data read error\n"); return (-1); } } else if (nread == 0) { break; /* EOF */ } //Debug_Bytes( "NETREAD",ptr, nread ) ; nleft -= nread; ptr += nread; } else if (rc < 0) { /* select error */ if (errno == EINTR) { /* select() was interrupted, try again */ continue; } ERROR_DATA("Selection error (network)\n"); return -EINTR; } else { /* timed out */ LEVEL_CONNECT("TIMEOUT after %d bytes\n", n - nleft); return -EAGAIN; } } return (n - nleft); /* return >= 0 */ }
/* 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; }
/* Note, config is stored as only the lower nibble */ static GOOD_OR_BAD SetConfiguration(BYTE c, struct connection_in *in) { struct connection_in *head = in->master.i2c.head; FILE_DESCRIPTOR_OR_ERROR file_descriptor = in->pown->file_descriptor; int read_back; /* Write, readback, and compare configuration register */ /* Logic error fix from Uli Raich */ if (i2c_smbus_write_byte_data(file_descriptor, DS2482_CMD_WRITE_CONFIG, c | ((~c) << 4)) || (read_back = i2c_smbus_read_byte(file_descriptor)) < 0 || ((BYTE) read_back != c) ) { head->master.i2c.configchip = 0xFF; // bad value to trigger retry LEVEL_CONNECT("Trouble changing DS2482 configuration register "I2Cformat" ",I2Cvar(in)); return gbBAD; } /* Clear the strong pull-up power bit(register is automatically cleared by reset) */ in->master.i2c.configreg = head->master.i2c.configchip = c & ~DS2482_REG_CFG_SPU; return gbGOOD; }
void ZeroConf_Announce(struct connection_out *out) { if ( Globals.announce_off) { return; } else if ( Globals.zero == zero_avahi ) { #if OW_AVAHI GOOD_OR_BAD oaa = OW_Avahi_Announce( out ) ; LEVEL_DEBUG( "Avahi (zero-configuration service) broadcast was %s successful",BAD(oaa)?"NOT":"") ; #endif /* OW_AVAHI */ } else if ( Globals.zero == zero_bonjour ) { pthread_t thread; int err = pthread_create(&thread, DEFAULT_THREAD_ATTR, Announce, (void *) out); if (err) { LEVEL_CONNECT("Zeroconf/Bonjour registration thread error %d.", err); } } }
static int Get_HA7_response( struct addrinfo *now, char * name ) { struct timeval tv = { 50, 0 }; FILE_DESCRIPTOR_OR_ERROR file_descriptor; struct HA7_response ha7_response ; struct sockaddr_in from ; socklen_t fromlen = sizeof(struct sockaddr_in) ; int on = 1; file_descriptor = socket(now->ai_family, now->ai_socktype, now->ai_protocol) ; if ( FILE_DESCRIPTOR_NOT_VALID(file_descriptor) ) { ERROR_DEBUG("Cannot get socket file descriptor for broadcast."); return 1; } // fcntl (file_descriptor, F_SETFD, FD_CLOEXEC); // for safe forking if (setsockopt(file_descriptor, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) == -1) { ERROR_DEBUG("Cannot set socket option for broadcast."); return 1; } if (sendto(file_descriptor, "HA\000\001", 4, 0, now->ai_addr, now->ai_addrlen) != 4) { ERROR_CONNECT("Trouble sending broadcast message"); return 1; } /* now read */ if ( udp_read(file_descriptor, &ha7_response, sizeof(struct HA7_response), &tv, &from, &fromlen) != sizeof(struct HA7_response) ) { LEVEL_CONNECT("HA7 response bad length"); return 1; } if ( Test_HA7_response( &ha7_response ) ) { return 1 ; } UCLIBCLOCK ; snprintf(name,INET_ADDRSTRLEN+20,"%s:%d",inet_ntoa(from.sin_addr),ntohs(ha7_response.port)); UCLIBCUNLOCK ; return 0 ; }
int ClientAddr(char *sname, struct connection_in *in) { struct addrinfo hint; char *p; int ret; if (sname == NULL || sname[0] == '\0') { sname = "4304"; } if ((p = strrchr(sname, ':'))) { /* : exists */ p[0] = '\0'; /* Separate tokens in the string */ in->tcp.host = strdup(sname); in->tcp.service = strdup(&p[1]); p[0] = ':'; /* restore name string */ } else { #if OW_CYGWIN in->tcp.host = strdup("127.0.0.1"); #else in->tcp.host = NULL; #endif in->tcp.service = strdup(sname); } memset(&hint, 0, sizeof(struct addrinfo)); hint.ai_socktype = SOCK_STREAM; #if OW_CYGWIN hint.ai_family = AF_INET; #else hint.ai_family = AF_UNSPEC; #endif //printf("ClientAddr: [%s] [%s]\n", in->connin.tcp.host, in->connin.tcp.service); if ((ret = getaddrinfo(in->tcp.host, in->tcp.service, &hint, &in->tcp.ai))) { LEVEL_CONNECT("GetAddrInfo error %s\n", gai_strerror(ret)); return -1; } return 0; }
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); }
void ZeroConf_Announce(struct connection_out *out) { (void) out; LEVEL_CONNECT("Zeroconf not enabled"); return; }
/* return < 0 if failure */ ZERO_OR_ERROR tcp_read(FILE_DESCRIPTOR_OR_ERROR file_descriptor, BYTE * buffer, size_t requested_size, const struct timeval * ptv, size_t * chars_in) { size_t to_be_read = requested_size ; if ( FILE_DESCRIPTOR_NOT_VALID( file_descriptor ) ) { return -EBADF ; } LEVEL_DEBUG("attempt %d bytes Time: "TVformat,(int)requested_size, TVvar(ptv) ) ; *chars_in = 0 ; while (to_be_read > 0) { int select_result; fd_set readset; struct timeval tv ; /* Initialize readset */ FD_ZERO(&readset); FD_SET(file_descriptor, &readset); /* Read if it doesn't timeout first */ timercpy( &tv, ptv ) ; select_result = select(file_descriptor + 1, &readset, NULL, NULL, &tv); if (select_result > 0) { ssize_t read_result; /* Is there something to read? */ if (FD_ISSET(file_descriptor, &readset) == 0) { LEVEL_DEBUG("tcp_error -- nothing avialable to read"); return -EBADF ; /* error */ } errno = 0 ; read_result = read(file_descriptor, &buffer[*chars_in], to_be_read) ; if ( read_result < 0 ) { if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { read_result = 0; /* and call read() again */ } else { LEVEL_DATA("Network data read error errno=%d %s", errno, strerror(errno)); STAT_ADD1(NET_read_errors); return -EBADF ; } } else if (read_result == 0) { break; /* EOF */ } TrafficInFD("NETREAD", &buffer[*chars_in], read_result, file_descriptor ) ; to_be_read -= read_result; *chars_in += read_result ; } else if (select_result < 0) { /* select error */ if (errno == EINTR) { /* select() was interrupted, try again */ continue; } ERROR_DATA("Select error"); return -EBADF; } else { /* timed out */ LEVEL_CONNECT("TIMEOUT after %d bytes", requested_size - to_be_read); return -EAGAIN; } } LEVEL_DEBUG("read: %d - %d = %d",(int)requested_size, (int) to_be_read, (int) (requested_size-to_be_read) ) ; return 0; }
/* 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; }
/* ---------------------------------------------- */ int main(int argc, char *argv[]) { int c; struct Fuse_option fuse_options; /* Set up owlib */ LibSetup(program_type_filesystem); /* grab our executable name */ if (argc > 0) { Globals.progname = owstrdup(argv[0]); } //mtrace() ; /* process command line arguments */ while ((c = getopt_long(argc, argv, OWLIB_OPT, owopts_long, NULL)) != -1) { switch (c) { case 'V': fprintf(stderr, "%s version:\n\t" VERSION "\n", argv[0]); break; case e_fuse_opt: /* fuse_mnt_opt */ if (fuse_mnt_opt) { owfree(fuse_mnt_opt); } fuse_mnt_opt = Fuse_arg(optarg, "FUSE mount options"); if (fuse_mnt_opt == NULL) { ow_exit(0); } break; case e_fuse_open_opt: /* fuse_open_opt */ if (fuse_open_opt) { owfree(fuse_open_opt); } fuse_open_opt = Fuse_arg(optarg, "FUSE open options"); if (fuse_open_opt == NULL) { ow_exit(0); } break; } if ( BAD( owopt(c, optarg) ) ) { ow_exit(0); /* rest of message */ } } /* non-option arguments */ while (optind < argc - 1) { ARG_Generic(argv[optind]); ++optind; } while (optind < argc) { if (Outbound_Control.active) { ARG_Generic(argv[optind]); } else { ARG_Server(argv[optind]); } ++optind; } if (Outbound_Control.active == 0) { LEVEL_DEFAULT("No mount point specified.\nTry '%s -h' for help.", argv[0]); ow_exit(1); } // FUSE directory mounting LEVEL_CONNECT("fuse mount point: %s", Outbound_Control.head->name); // Signal handler is set in fuse library //set_signal_handlers(exit_handler); /* Set up adapters */ if ( BAD(LibStart()) ) { ow_exit(1); } #if FUSE_VERSION >= 14 /* Set up "command line" for main fuse routines */ Fuse_setup(&fuse_options); // command line setup Fuse_add(Outbound_Control.head->name, &fuse_options); // mount point #if FUSE_VERSION >= 22 Fuse_add("-o", &fuse_options); // add "-o direct_io" to prevent buffering Fuse_add("direct_io", &fuse_options); #endif /* FUSE_VERSION >= 22 */ if (!Globals.want_background) { Fuse_add("-f", &fuse_options); // foreground for fuse too if (Globals.error_level > 2) { Fuse_add("-d", &fuse_options); // debug for fuse too } } Fuse_parse(fuse_mnt_opt, &fuse_options); LEVEL_DEBUG("fuse_mnt_opt=[%s]", fuse_mnt_opt); Fuse_parse(fuse_open_opt, &fuse_options); LEVEL_DEBUG("fuse_open_opt=[%s]", fuse_open_opt); if (Globals.allow_other) { Fuse_add("-o", &fuse_options); // add "-o allow_other" to permit other users access Fuse_add("allow_other", &fuse_options); } #if OW_MT == 0 Fuse_add("-s", &fuse_options); // single threaded #endif /* OW_MT */ Globals.now_background = Globals.want_background; // tell "error" that we are background #if 0 { int i; for (i = 0; i < fuse_options.argc; i++) { LEVEL_DEBUG("fuse_options.argv[%d]=[%s]", i, fuse_options.argv[i]); } } #endif #if FUSE_VERSION > 25 fuse_main(fuse_options.argc, fuse_options.argv, &owfs_oper, NULL); #else /* FUSE_VERSION <= 25 */ fuse_main(fuse_options.argc, fuse_options.argv, &owfs_oper); #endif /* FUSE_VERSION <= 25 */ Fuse_cleanup(&fuse_options); #endif ow_exit(0); return 0; }
void OW_Browse(struct connection_in *in) { (void) in ; LEVEL_CONNECT("Avahi and Bonjour not enabled"); }
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; }
/* 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 ; }
int main(int argc, char *argv[]) { int c; /* Set up owlib */ LibSetup(program_type_httpd); Setup_Systemd() ; // systemd? Setup_Launchd() ; // launchd? /* grab our executable name */ ArgCopy( argc, argv ) ; while ((c = getopt_long(argc, argv, OWLIB_OPT, owopts_long, NULL)) != -1) { switch (c) { case 'V': fprintf(stderr, "%s version:\n\t" VERSION "\n", argv[0]); break; default: break; } if ( BAD( owopt(c, optarg) ) ) { ow_exit(0); /* rest of message */ } } /* non-option arguments */ while (optind < argc) { ARG_Generic(argv[optind]); ++optind; } switch (Globals.daemon_status) { case e_daemon_sd: case e_daemon_sd_done: // systemd done later break ; default: if (Outbound_Control.active == 0) { if (Globals.zero == zero_none) { LEVEL_DEFAULT("%s would be \"locked in\" so will quit.\nBonjour and Avahi not available.", argv[0]); ow_exit(1); } else { LEVEL_CONNECT("%s will use an ephemeral port", argv[0]) ; } ARG_Server(NULL); // make an ephemeral assignment } break ; } /* become a daemon if not told otherwise */ if ( BAD(EnterBackground()) ) { ow_exit(1); } /* Set up adapters and systemd */ if ( BAD(LibStart(NULL)) ) { ow_exit(1); } set_exit_signal_handlers(exit_handler); set_signal_handlers(NULL); ServerProcess(Acceptor); LEVEL_DEBUG("ServerProcess done"); ow_exit(0); LEVEL_DEBUG("owhttpd done"); return 0; }