static void BUS_ERROR_fix(const struct parsedname *pn) { LEVEL_DEBUG("DS9490_Reset: ERROR -- will attempt a fix"); /* FIXME: FIXED. In ow_usb_msg.c an USB-reset was was issued: * USB_Control_Msg(CONTROL_CMD, CTL_RESET_DEVICE, 0x0000, pn) ; * So we need to setup the Adapter again * Though here is probably the wrong place, duplicated code from _setup_adaptor */ // enable both program and strong pulses if ( BAD( USB_Control_Msg(MODE_CMD, MOD_PULSE_EN, ENABLE_PROGRAM_AND_PULSE, pn)) ) { LEVEL_DATA("EnableProgram error"); } // enable speed changes if ( BAD( USB_Control_Msg(MODE_CMD, MOD_SPEED_CHANGE_EN, 1, pn)) ) { LEVEL_DATA("RESET_Error: SpeedEnable error"); } // set the strong pullup duration to infinite if ( BAD( USB_Control_Msg(COMM_CMD, COMM_SET_DURATION | COMM_IM, 0x0000, pn)) ) { LEVEL_DATA("StrongPullup error"); } // Don't set speed right now, it calls reset for infinite recursion. Just set for next pass ++ pn->selected_connection->changed_bus_settings ; }
// Switch to overdrive speed -- 3 tries static GOOD_OR_BAD DS9490_overdrive(const struct parsedname *pn) { BYTE sp = _1W_OVERDRIVE_SKIP_ROM; BYTE resp; int i; // we need to change speed to overdrive for (i = 0; i < 3; i++) { LEVEL_DATA("set overdrive speed. Attempt %d",i); if ( BAD( gbRESET(BUS_reset(pn)) ) ) { continue; } if ( BAD( DS9490_sendback_data(&sp, &resp, 1, pn) ) || (_1W_OVERDRIVE_SKIP_ROM != resp) ) { LEVEL_DEBUG("error setting overdrive %.2X/0x%02X", _1W_OVERDRIVE_SKIP_ROM, resp); continue; } if ( GOOD( USB_Control_Msg(MODE_CMD, MOD_1WIRE_SPEED, ONEWIREBUSSPEED_OVERDRIVE, pn)) ) { LEVEL_DEBUG("speed is now set to overdrive"); return gbGOOD; } } LEVEL_DEBUG("Error setting overdrive after 3 retries"); return gbBAD; }
static ZERO_OR_ERROR FS_w_vib_mode(struct one_wire_query *owq) { struct parsedname *pn = PN(owq); UINT vib_request = OWQ_U(owq) ; BYTE vib_stored ; switch (vib_request) { case e_mVM001_peak: case e_mVM001_rms: case e_mVM001_multi: break ; default: return -EINVAL ; } if ( BAD( Cache_Get_SlaveSpecific(&vib_stored, sizeof(vib_stored), SlaveSpecificTag(VIB), pn)) ) { if ( vib_stored == vib_request ) { return 0 ; } } if ( BAD( OW_set_vib_mode( vib_request, pn ) ) ) { return -EINVAL ; } Cache_Add_SlaveSpecific(&vib_request, sizeof(vib_request), SlaveSpecificTag(VIB), pn); return 0 ; }
static RESET_TYPE LINK_reset_in(struct connection_in * in) { BYTE resp[1+in->CRLF_size]; if (in->changed_bus_settings > 0) { --in->changed_bus_settings ; LINK_set_baud(in); // reset paramters } else { LINK_flush(in); } if ( BAD(LINK_write(LINK_string("r"), 1, in) || BAD( LINK_read(resp, 1, in))) ) { LEVEL_DEBUG("Error resetting LINK device"); LINK_slurp(in); return BUS_RESET_ERROR; } switch (resp[0]) { case 'P': in->AnyDevices = anydevices_yes; return BUS_RESET_OK; case 'N': in->AnyDevices = anydevices_no; return BUS_RESET_OK; case 'S': return BUS_RESET_SHORT; default: LEVEL_DEBUG("bad, Unknown LINK response %c", resp[0]); LINK_slurp(in); return BUS_RESET_ERROR; } }
// return 1 shorted, 0 ok, <0 error static RESET_TYPE DS2482_reset(const struct parsedname *pn) { BYTE status_byte; struct connection_in * in = pn->selected_connection ; FILE_DESCRIPTOR_OR_ERROR file_descriptor = in->pown->file_descriptor; /* Make sure we're using the correct channel */ if ( BAD(DS2482_channel_select(in)) ) { return BUS_RESET_ERROR; } /* write the RESET code */ if (i2c_smbus_write_byte(file_descriptor, DS2482_CMD_1WIRE_RESET)) { return BUS_RESET_ERROR; } /* wait */ // rstl+rsth+.25 usec /* read status */ if ( BAD( DS2482_readstatus(&status_byte, file_descriptor, DS2482_1wire_reset_usec) ) ) { return BUS_RESET_ERROR; // 8 * Tslot } in->AnyDevices = (status_byte & DS2482_REG_STS_PPD) ? anydevices_yes : anydevices_no ; LEVEL_DEBUG("DS2482 "I2Cformat" Any devices found on reset? %s",I2Cvar(in),in->AnyDevices==anydevices_yes?"Yes":"No"); return (status_byte & DS2482_REG_STS_SD) ? BUS_RESET_SHORT : BUS_RESET_OK; }
/* Puts in 9600 baud, sends 11110000 then reads response */ static RESET_TYPE DS9097_reset_in( struct connection_in * in ) { BYTE resetbyte = RESET_BYTE; BYTE responsebyte; if ( BAD( DS9097_pre_reset( in ) ) ) { return BUS_RESET_ERROR ; } if ( BAD( DS9097_send_and_get(&resetbyte, &responsebyte, 1, in )) ) { DS9097_post_reset( in) ; return BUS_RESET_ERROR ; } DS9097_post_reset(in) ; switch (responsebyte) { case 0x00: return BUS_RESET_SHORT; case RESET_BYTE: // no presence in->AnyDevices = anydevices_no ; return BUS_RESET_OK; default: in->AnyDevices = anydevices_yes ; return BUS_RESET_OK; } }
/* 2450 A/D */ static ZERO_OR_ERROR FS_volts(struct one_wire_query *owq) { struct parsedname *pn = PN(owq); int resolution ; int range ; _FLOAT V[4] ; switch ( pn->selected_filetype->data.i ) { case r_2V_8bit: range = 2 ; resolution = 8 ; break ; case r_5V_8bit: range = 5 ; resolution = 8 ; break ; case r_2V_16bit: range = 2 ; resolution = 16 ; break ; case r_5V_16bit: default: range = 5 ; resolution = 16 ; break ; } if ( BAD( OW_set_resolution( resolution, pn ) ) ) { return -EINVAL ; } if ( BAD( OW_set_range( range, pn ) ) ) { return -EINVAL ; } // Start A/D process if needed if ( BAD( OW_convert( OWQ_SIMUL_TEST(owq), (int)(.5+.16+4.*resolution*.08), pn) )) { return -EINVAL ; } if ( BAD( OW_volts( V, pn ) )) { return -EINVAL ; } switch ( pn->selected_filetype->data.i ) { case r_2V_8bit: case r_2V_16bit: OWQ_array_F(owq, 0) = V[0]*.5; OWQ_array_F(owq, 1) = V[1]*.5; OWQ_array_F(owq, 2) = V[2]*.5; OWQ_array_F(owq, 3) = V[3]*.5; break ; case r_5V_8bit: case r_5V_16bit: default: OWQ_array_F(owq, 0) = V[0]; OWQ_array_F(owq, 1) = V[1]; OWQ_array_F(owq, 2) = V[2]; OWQ_array_F(owq, 3) = V[3]; break ; } return 0 ; }
/* 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; }
int c3db_dump( C3HDL *h, FILE *to, int show_empty, int ts_fmt ) { if( !h ) return C3E_BAD_HANDLE; if( h->state == C3DB_ST_DIRTY ) BAD( C3E_BAD_STATE ); if( ts_fmt < C3DB_TS_SEC || ts_fmt >= C3DB_TS_MAX ) BAD( C3E_BAD_FORMAT ); return (h->f_dump)( h, to, show_empty, ts_fmt ); }
/* 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; }
/* 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); } }
float EDIT_scale_misfit( int nxyz , float fac , short *sar , float *far ) { float sf , ff , sum=0.0f , df ; int ii , nf=0 ; ENTRY("EDIT_scale_misfit") ; if( nxyz <= 0 || sar == NULL || far == NULL ) RETURN(0.0f) ; if( fac == 0.0f ) fac = 1.0f ; df = 1.0f / fac ; for( ii=0 ; ii < nxyz ; ii++ ) { if( BAD(ii) ) continue ; ff = far[ii] ; if( ff == 0.0f ) continue ; sf = (short)rintf(fac*sar[ii]) ; if( sf == 0.0f ) { if( fabsf(ff) < df ) sum += fabsf(ff)*fac ; else sum += 1.0f ; } else { sf = fabsf((sf-ff)/ff) ; if( sf > 1.0f ) sf = 1.0f ; sum += sf ; } nf++ ; } if( nf > 0 ) sum /= nf ; RETURN(sum) ; }
// range is 5=5V or 2=2.5V static GOOD_OR_BAD OW_set_range( int range, struct parsedname * pn ) { int stored_range ; /* Range */ if ( BAD( Cache_Get_SlaveSpecific(&stored_range, sizeof(stored_range), SlaveSpecificTag(RAN), pn)) || stored_range != range) { // need to set resolution BYTE p[_1W_2450_PAGESIZE]; RETURN_BAD_IF_BAD( OW_r_mem(p, _1W_2450_PAGESIZE, _ADDRESS_CONTROL_PAGE, pn) ) ; switch ( range ) { case 2: p[_1W_2450_REG_A+1] &= ~_1W_2450_IR ; p[_1W_2450_REG_B+1] &= ~_1W_2450_IR ; p[_1W_2450_REG_C+1] &= ~_1W_2450_IR ; p[_1W_2450_REG_D+1] &= ~_1W_2450_IR ; break ; case 5: default: p[_1W_2450_REG_A+1] |= _1W_2450_IR ; p[_1W_2450_REG_B+1] |= _1W_2450_IR ; p[_1W_2450_REG_C+1] |= _1W_2450_IR ; p[_1W_2450_REG_D+1] |= _1W_2450_IR ; break ; } RETURN_BAD_IF_BAD( OW_w_mem(p, _1W_2450_PAGESIZE, _ADDRESS_CONTROL_PAGE, pn) ); return Cache_Add_SlaveSpecific(&range, sizeof(int), SlaveSpecificTag(RAN), pn); } return gbGOOD ; }
static ZERO_OR_ERROR FS_Mclear(struct one_wire_query *owq) { struct parsedname *pn = PN(owq); int init = 1; if ( BAD( Cache_Get_SlaveSpecific(&init, sizeof(init), SlaveSpecificTag(INI), pn)) ) { OWQ_Y(owq) = 1; if ( FS_r_strobe(owq) != 0 ) { // set reset pin to strobe mode return -EINVAL; } RETURN_ERROR_IF_BAD( OW_w_pio(0x30, pn) ); UT_delay(100); // init RETURN_ERROR_IF_BAD( OW_w_pio(0x38, pn) ) ; UT_delay(10); // Enable Display, Cursor, and Blinking // Entry-mode: auto-increment, no shift RETURN_ERROR_IF_BAD( OW_w_pio(0x0F, pn) ) ; RETURN_ERROR_IF_BAD( OW_w_pio(0x06, pn) ) ; Cache_Add_SlaveSpecific(&init, sizeof(init), SlaveSpecificTag(INI), pn); } // clear RETURN_ERROR_IF_BAD( OW_w_pio(0x01, pn) ); UT_delay(2); return FS_Mhome(owq); }
/* 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); }
/* Use an single OWQ as a template for the aggregate one */ struct one_wire_query * OWQ_create_aggregate( struct one_wire_query * owq_single ) { int sz = sizeof( struct one_wire_query ) + OWQ_DEFAULT_READ_BUFFER_SIZE; struct one_wire_query * owq_all = owmalloc( sz ); LEVEL_DEBUG("%s with extension ALL", PN(owq_single)->path); if ( owq_all == NO_ONE_WIRE_QUERY) { LEVEL_DEBUG("No memory to create object for extension ALL") ; return NO_ONE_WIRE_QUERY ; } memset(owq_all, 0, sz); OWQ_cleanup(owq_all) = owq_cleanup_owq ; memcpy( PN(owq_all), PN(owq_single), sizeof(struct parsedname) ) ; PN(owq_all)->extension = EXTENSION_ALL ; OWQ_buffer(owq_all) = (char *) (& owq_all[1]) ; // point just beyond the one_wire_query struct OWQ_size(owq_all) = OWQ_DEFAULT_READ_BUFFER_SIZE ; OWQ_offset(owq_all) = 0 ; if ( BAD( OWQ_allocate_array(owq_all)) ) { OWQ_destroy(owq_all); return NO_ONE_WIRE_QUERY ; } return owq_all ; }
static enum search_status LINK_next_both(struct device_search *ds, const struct parsedname *pn) { struct connection_in * in = pn->selected_connection ; //Special case for DS2409 hub, use low-level code if ( pn->ds2409_depth>0 ) { return search_error ; } if (ds->LastDevice) { return search_done; } if (ds->index == -1) { if ( BAD(LINK_directory(ds, in)) ) { return search_error; } } // LOOK FOR NEXT ELEMENT ++ds->index; LEVEL_DEBUG("Index %d", ds->index); switch ( DirblobGet(ds->index, ds->sn, &(ds->gulp) ) ) { case 0: LEVEL_DEBUG("SN found: " SNformat "", SNvar(ds->sn)); return search_good; case -ENODEV: default: ds->LastDevice = 1; LEVEL_DEBUG("SN finished"); return search_done; } }
static GOOD_OR_BAD OW_r_counters(UINT * data, const struct parsedname *pn) { BYTE d[8]; UINT cum[4]; RETURN_BAD_IF_BAD( LCD_byte(_LCD_COMMAND_COUNTER_READ_TO_SCRATCH, 1, pn)) ; RETURN_BAD_IF_BAD( OW_r_scratch(d, 8, pn)) ; data[0] = ((UINT) d[1]) << 8 | d[0]; data[1] = ((UINT) d[3]) << 8 | d[2]; data[2] = ((UINT) d[5]) << 8 | d[4]; data[3] = ((UINT) d[7]) << 8 | d[6]; //printf("OW_COUNTER key=%s\n",key); if ( BAD( Cache_Get_SlaveSpecific((void *) cum, sizeof(cum), SlaveSpecificTag(CUM), pn)) ) { /* First pass at cumulative */ cum[0] = data[0]; cum[1] = data[1]; cum[2] = data[2]; cum[3] = data[3]; } else { cum[0] += data[0]; cum[1] += data[1]; cum[2] += data[2]; cum[3] += data[3]; } Cache_Add_SlaveSpecific((void *) cum, sizeof(cum), SlaveSpecificTag(CUM), pn); return gbGOOD; }
/* 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 ; }
static GOOD_OR_BAD DS9097_sendback_bits(const BYTE * outbits, BYTE * inbits, const size_t length, const struct parsedname *pn) { BYTE local_data[DS9097_MAX_BITS]; size_t global_counter ; size_t local_counter ; size_t offset ; struct connection_in * in = pn->selected_connection ; /* Split into smaller packets? */ for ( local_counter = global_counter = offset = 0 ; offset < length ; ) { // encode this bit local_data[local_counter] = outbits[global_counter] ? OneBit : ZeroBit; // point to next one ++local_counter ; ++global_counter ; // test if enough bits to send to master if (local_counter == DS9097_MAX_BITS || global_counter == length) { /* Communication with DS9097 routine */ /* Up to DS9097_MAX_BITS bits at a time */ if ( BAD( DS9097_send_and_get( local_data, &inbits[offset], local_counter, in )) ) { STAT_ADD1_BUS(e_bus_errors, in); return gbBAD; } offset += local_counter ; local_counter = 0 ; } } /* Decode Bits */ for (global_counter = 0; global_counter < length; ++global_counter) { inbits[global_counter] &= 0x01; // mask out all but lowest bit } return gbGOOD; }
GOOD_OR_BAD USB_next_match(struct usb_list *ul) { 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 ; } if ( BAD ( usbdevice_in_use( ul ) ) ) { continue ; } LEVEL_CONNECT("Bus master found: %.d:%.d", ul->usb_bus_number, ul->usb_dev_number); return gbGOOD; } 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; }
enum Netlink_Read_Status W1_Process_Response( void (* nrs_callback)( struct netlink_parse * nlp, void * v, const struct parsedname * pn), SEQ_OR_ERROR seq, void * v, const struct parsedname * pn ) { struct connection_in * in = pn->selected_connection ; FILE_DESCRIPTOR_OR_ERROR file_descriptor ; int bus ; if ( seq == SEQ_BAD ) { return nrs_bad_send ; } if ( in == NO_CONNECTION ) { // Send to main netlink rather than a particular bus file_descriptor = FILE_DESCRIPTOR_BAD ; bus = 0 ; } else { // Bus-specifc file_descriptor = in->master.w1.netlink_pipe[fd_pipe_read] ; bus = in->master.w1.id ; } while ( GOOD( W1PipeSelect_timeout(file_descriptor)) ) { struct netlink_parse nlp ; nlp.nlm = NULL ; LEVEL_DEBUG("Loop waiting for netlink piped message"); if ( BAD( Get_and_Parse_Pipe( file_descriptor, &nlp )) ) { LEVEL_DEBUG("Error reading pipe for w1_bus_master%d",bus); // Don't need to free since nlm not set if BAD return nrs_error ; } if ( NL_SEQ(nlp.nlm->nlmsg_seq) != (unsigned int) seq ) { LEVEL_DEBUG("Netlink sequence number out of order"); owfree(nlp.nlm) ; continue ; } if ( nlp.w1m->status != 0) { owfree(nlp.nlm) ; return nrs_nodev ; } if ( nrs_callback == NULL ) { // status message owfree(nlp.nlm) ; return nrs_complete ; } LEVEL_DEBUG("About to call nrs_callback"); nrs_callback( &nlp, v, pn ) ; LEVEL_DEBUG("Called nrs_callback"); owfree(nlp.nlm) ; if ( nlp.cn->ack != 0 ) { if ( nlp.w1m->type == W1_LIST_MASTERS ) { continue ; // look for more data } if ( nlp.w1c && (nlp.w1c->cmd==W1_CMD_SEARCH || nlp.w1c->cmd==W1_CMD_ALARM_SEARCH) ) { continue ; // look for more data } } nrs_callback = NULL ; // now look for status message } return nrs_timeout ; }
static GOOD_OR_BAD OW_w_pio(const BYTE data, const struct parsedname *pn) { BYTE write_string[] = { _1W_CHANNEL_ACCESS_WRITE, data, (BYTE) ~ data, }; BYTE read_back[2]; struct transaction_log t[] = { TRXN_START, TRXN_WRITE3(write_string), TRXN_READ2(read_back), TRXN_END, }; if ( BAD(BUS_transaction(t, pn)) ) { // may be in test mode, which causes Channel Access Write to fail // fix now, but need another attempt to see if will work OW_out_of_test_mode(pn) ; return gbBAD ; } if (read_back[0] != 0xAA) { return gbBAD; } /* Ignore byte 5 read_back[1] the PIO status byte */ return gbGOOD; }
static GOOD_OR_BAD OW_w_std(BYTE *buf, size_t size, BYTE type, BYTE stype, const struct parsedname *pn) { BYTE p[4] = { _1W_WRITE_MOAT, type,stype, size}; BYTE crcbuf[2]; UINT crc; struct transaction_log tfirst[] = { TRXN_START, TRXN_WRITE(p,4), TRXN_WRITE(buf,size), TRXN_READ2(crcbuf), TRXN_END, }; struct transaction_log xmit_crc[] = { TRXN_WRITE2(crcbuf), TRXN_END, }; if (size == 0) { return gbGOOD; } if (size > 255) { return gbBAD; } LEVEL_DEBUG( "write: %d for %d %d",size,type,stype) ; if ( BAD(BUS_transaction(tfirst, pn))) { goto out_bad; } crc = CRC16compute(p,4,0); crc = CRC16compute(buf,size,crc); if ( CRC16seeded (crcbuf,2,crc) ) { LEVEL_DEBUG("CRC error"); goto out_bad; } LEVEL_DEBUG( "read CRC: GOOD, got %02x%02x",crcbuf[0],crcbuf[1]) ; crcbuf[0] = ~crcbuf[0]; crcbuf[1] = ~crcbuf[1]; if ( BAD(BUS_transaction(xmit_crc, pn)) ) { goto out_bad; } return gbGOOD; out_bad: return gbBAD; }
static int VISIBLE_19( const struct parsedname * pn ) { int device_id = unknown_19 ; LEVEL_DEBUG("Checking visibility of %s",SAFESTRING(pn->path)) ; if ( BAD( GetVisibilityCache( &device_id, pn ) ) ) { BYTE a_byte[1] ; // use technique and address only specified on DS2407 if ( BAD( OW_r_all( a_byte, 1, 0x0080, pn ) ) ) { device_id = ds2502_19 ; } else { device_id = ds2407_19 ; } SetVisibilityCache( device_id, pn ) ; } return device_id ; }
/* return GOOD if any found */ static GOOD_OR_BAD DS2482_detect_sys( int any, enum ds2482_address chip_num, struct port_in *pin_original) { DIR * i2c_list_dir ; struct dirent * i2c_bus ; int found = 0 ; struct port_in * pin_current = pin_original ; // We'll look in this directory for available i2c adapters. // This may be linux 2.6 specific i2c_list_dir = opendir( SYSFS_I2C_Path ) ; if ( i2c_list_dir == NULL ) { ERROR_CONNECT( "Cannot open %d to find available i2c devices",SYSFS_I2C_Path ) ; // Use the cruder approach of trying all possible numbers return DS2482_detect_dir( any, chip_num, pin_original ) ; } /* cycle through entries in /sys/class/i2c-adapter */ while ( (i2c_bus=readdir(i2c_list_dir)) != NULL ) { char dev_name[128] ; // room for /dev/name int sn_ret ; UCLIBCLOCK ; sn_ret = snprintf( dev_name, 128, "/dev/%s", i2c_bus->d_name ) ; UCLIBCUNLOCK ; if ( sn_ret < 0 ) { break ; } // Now look for the ds2482's if ( BAD( DS2482_detect_bus( chip_num, dev_name, pin_current ) ) ) { continue ; // none found on this i2c bus } // at least one found on this i2c bus ++found ; if ( any ) { // found one -- that's enough closedir( i2c_list_dir ) ; return gbGOOD ; } // ALL? then set up a new connection_in slot for the next one pin_current = NewPort(pin_current) ; if ( pin_current == NULL ) { break ; } } closedir( i2c_list_dir ) ; if ( found==0 ) { return gbBAD ; } if ( pin_current != pin_original ) { RemovePort( pin_current ) ; } return gbGOOD ; }
/* Test for a simultaneous property * return true if simultaneous is the prefered method * bad if no simultaneous, or it's not the best */ static GOOD_OR_BAD Cache_Get_Simultaneous(enum simul_type type, struct one_wire_query *owq) { struct tree_node tn; time_t duration ; time_t time_left ; time_t dwell_time_simul ; struct parsedname * pn = PN(owq) ; size_t dsize = sizeof(union value_object) ; duration = TimeOut(pn->selected_filetype->change); if (duration <= 0) { // probably "uncached" requested return gbBAD; } LoadTK( pn->sn, pn->selected_filetype, pn->extension, &tn ) ; if ( Get_Stat(&cache_ext, Cache_Get_Common( &OWQ_val(owq), &dsize, &time_left, &tn)) == 0 ) { // valid cached primary data -- see if a simultaneous conversion should be used instead time_t dwell_time_data = duration - time_left ; if ( BAD( Cache_Get_Simul_Time( type, &dwell_time_simul, pn)) ) { // Simul not found or timed out LEVEL_DEBUG("Simultaneous conversion not found.") ; OWQ_SIMUL_CLR(owq) ; return gbGOOD ; } if ( dwell_time_simul < dwell_time_data ) { LEVEL_DEBUG("Simultaneous conversion is newer than previous reading.") ; OWQ_SIMUL_SET(owq) ; return gbBAD ; // Simul is newer } // Cached data is newer, so use it OWQ_SIMUL_CLR(owq) ; return gbGOOD ; } // fall through -- no cached primary data if ( BAD( Cache_Get_Simul_Time( type, &dwell_time_simul, pn)) ) { // no simultaneous either OWQ_SIMUL_CLR(owq) ; return gbBAD ; } OWQ_SIMUL_SET(owq) ; return gbBAD ; // Simul is newer }
static void LINK_set_baud(struct connection_in * in) { struct port_in * pin = in->pown ; char * speed_code ; if ( pin->type == ct_telnet ) { // telnet pinned at 115200 return ; } COM_BaudRestrict( &(pin->baud), B9600, B19200, B38400, B57600, 0 ) ; LEVEL_DEBUG("to %d",COM_BaudRate(pin->baud)); // Find rate parameter switch ( pin->baud ) { case B9600: COM_break(in) ; LINK_flush(in); return ; case B19200: speed_code = "," ; break ; case B38400: speed_code = "`" ; break ; #ifdef B57600 /* MacOSX support max 38400 in termios.h ? */ case B57600: speed_code = "^" ; break ; #endif default: LEVEL_DEBUG("Unrecognized baud rate"); return ; } LEVEL_DEBUG("LINK change baud string <%s>",speed_code); LINK_flush(in); if ( BAD( LINK_write(LINK_string(speed_code), 1, in) ) ) { LEVEL_DEBUG("LINK change baud error -- will return to 9600"); pin->baud = B9600 ; ++in->changed_bus_settings ; return ; } // Send configuration change LINK_flush(in); // Change OS view of rate UT_delay(5); COM_change(in) ; UT_delay(5); LINK_slurp(in); return ; }
/* cm.ret is also set to an error <0 or the read length */ void *ReadHandler(struct handlerdata *hd, struct client_msg *cm, struct one_wire_query *owq) { BYTE * retbuffer = NULL ; SIZE_OR_ERROR read_or_error; LEVEL_DEBUG("ReadHandler start"); if (hd == NULL || owq == NULL || cm == NULL) { LEVEL_DEBUG("ReadHandler: illegal null inputs hd==%p owq==%p cm==%p", hd, owq, cm); return NULL; // only sane response for bad inputs } LEVEL_DEBUG("ReadHandler: From Client sm->payload=%d sm->size=%d sm->offset=%d", hd->sm.payload, hd->sm.size, hd->sm.offset); if (hd->sm.payload >= PATH_MAX) { cm->ret = -EMSGSIZE; } else if ((hd->sm.size <= 0) || (hd->sm.size > MAX_OWSERVER_PROTOCOL_PAYLOAD_SIZE)) { cm->ret = -EMSGSIZE; LEVEL_DEBUG("ReadHandler: error hd->sm.size == %d", hd->sm.size); } else if ( BAD( OWQ_allocate_read_buffer(owq)) ) { // allocate read buffer LEVEL_DEBUG("ReadHandler: can't allocate memory"); cm->ret = -ENOBUFS; } else { struct parsedname *pn = PN(owq); if ( OWQ_size(owq) > (size_t) hd->sm.size ) { OWQ_size(owq) = hd->sm.size ; } OWQ_offset(owq) = hd->sm.offset ; LEVEL_DEBUG("ReadHandler: call FS_read_postparse on %s", pn->path); read_or_error = FS_read_postparse(owq); LEVEL_DEBUG("ReadHandler: FS_read_postparse read on %s return = %d", pn->path, read_or_error); Debug_OWQ(owq); if (read_or_error <= 0) { LEVEL_DEBUG("ReadHandler: FS_read_postparse error %d", read_or_error); cm->ret = read_or_error; } else { LEVEL_DEBUG("ReadHandler: FS_read_postparse ok size=%d", read_or_error); // make return size smaller (just large enough) cm->payload = read_or_error; cm->offset = hd->sm.offset; cm->size = read_or_error; cm->ret = read_or_error; /* Move this pointer, and let owfree remove it instead of OWQ_destroy() */ retbuffer = (BYTE *)OWQ_buffer(owq); OWQ_buffer(owq) = NULL; } } LEVEL_DEBUG("ReadHandler: To Client cm->payload=%d cm->size=%d cm->offset=%d", cm->payload, cm->size, cm->offset); if ((cm->size > 0)) { Debug_Bytes("Data returned to client",(BYTE *) OWQ_buffer(owq),cm->size) ; } return retbuffer; }