/* 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; }
/* 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; }
static GOOD_OR_BAD PresenceFromDirblob( struct parsedname * pn ) { struct dirblob db; // cached dirblob if ( GOOD( Cache_Get_Dir( &db , pn ) ) ) { // Use the dirblob from the cache GOOD_OR_BAD ret = ( DirblobSearch(pn->sn, &db ) >= 0 ) ? gbGOOD : gbBAD ; DirblobClear( &db ) ; return ret ; } else { // look through actual directory struct device_search ds ; enum search_status nextboth = BUS_first( &ds, pn ) ; while ( nextboth == search_good ) { if ( memcmp( ds.sn, pn->sn, SERIAL_NUMBER_SIZE ) == 0 ) { // found it. Early exit. BUS_next_cleanup( &ds ); return gbGOOD ; } // Not found. Clean up done by BUS_next in this case nextboth = BUS_next( &ds, pn ) ; } return gbBAD ; } }
static enum search_status W1_next_both(struct device_search *ds, const struct parsedname *pn) { if (ds->LastDevice) { return search_done; } if (++(ds->index) == 0) { // first pass, load the directory DirblobClear( &(ds->gulp) ); if ( W1_Process_Response( search_callback, w1_send_search(ds,pn), ds, pn ) != nrs_complete) { return search_error; } } 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 void Fake_close(struct connection_in *in) { DirblobClear( &(in->master.fake.main) ); DirblobClear( &(in->master.fake.alarm) ); }
static GOOD_OR_BAD LINK_directory(struct device_search *ds, struct connection_in * in) { char resp[DEVICE_LENGTH+COMMA_LENGTH+PLUS_LENGTH+in->CRLF_size]; DirblobClear( &(ds->gulp) ); // Send the configuration command and check response RETURN_BAD_IF_BAD( LINK_search_type( ds, in )) ; // send the first search RETURN_BAD_IF_BAD(LINK_write(LINK_string("f"), 1, in)) ; //One needs to check the first character returned. //If nothing is found, the link will timeout rather then have a quick //return. This happens when looking at the alarm directory and //there are no alarms pending //So we grab the first character and check it. If not an E leave it //in the resp buffer and get the rest of the response from the LINK //device RETURN_BAD_IF_BAD(LINK_read(LINK_string(resp), 1, in)) ; switch (resp[0]) { case 'E': LEVEL_DEBUG("LINK returned E: No devices in alarm"); // pass through case 'N': // remove extra 2 bytes LEVEL_DEBUG("LINK returned E or N: Empty bus"); if (ds->search != _1W_CONDITIONAL_SEARCH_ROM) { in->AnyDevices = anydevices_no; } return gbGOOD ; default: break ; } if ( BAD(LINK_read(LINK_string(&resp[1+in->CRLF_size]), DEVICE_LENGTH+COMMA_LENGTH+PLUS_LENGTH-1-in->CRLF_size, in)) ) { return gbBAD; } // Check if we should start scanning switch (resp[0]) { case '-': case '+': if (ds->search != _1W_CONDITIONAL_SEARCH_ROM) { in->AnyDevices = anydevices_yes; } break; default: LEVEL_DEBUG("LINK_search unrecognized case"); return gbBAD; } /* Join the loop after the first query -- subsequent handled differently */ while ((resp[0] == '+') || (resp[0] == '-')) { BYTE sn[SERIAL_NUMBER_SIZE]; sn[7] = string2num(&resp[2]); sn[6] = string2num(&resp[4]); sn[5] = string2num(&resp[6]); sn[4] = string2num(&resp[8]); sn[3] = string2num(&resp[10]); sn[2] = string2num(&resp[12]); sn[1] = string2num(&resp[14]); sn[0] = string2num(&resp[16]); LEVEL_DEBUG("SN found: " SNformat, SNvar(sn)); // CRC check if (CRC8(sn, SERIAL_NUMBER_SIZE) || (sn[0] == 0x00)) { LEVEL_DEBUG("BAD family or CRC8"); return gbBAD; } DirblobAdd(sn, &(ds->gulp) ); switch (resp[0]) { case '+': // get next element if ( BAD(LINK_write(LINK_string("n"), 1, in))) { return gbBAD; } if ( BAD(LINK_read(LINK_string((resp)), DEVICE_LENGTH+COMMA_LENGTH+PLUS_LENGTH, in)) ) { return gbBAD; } break; case '-': return gbGOOD; default: break; } } return gbGOOD; }
// Read up to 7 (DS2490_DIR_GULP_ELEMENTS) at a time, and place into // a dirblob. Called from DS9490_next_both every 7 devices to fill. static enum search_status DS9490_directory(struct device_search *ds, const struct parsedname *pn) { BYTE status_buffer[ DS9490_getstatus_BUFFER_LENGTH + 1 ]; BYTE EP2_data[SERIAL_NUMBER_SIZE] ; //USB endpoint 3 buffer union { BYTE b[DS2490_BULK_BUFFER_SIZE] ; BYTE sn[DS2490_BULK_BUFFER_SIZE/SERIAL_NUMBER_SIZE][SERIAL_NUMBER_SIZE]; } EP3 ; //USB endpoint 3 buffer SIZE_OR_ERROR ret; int bytes_back; int devices_found; int device_index; int dir_gulp_elements = (pn->ds2409_depth==0) ? DS2490_DIR_GULP_ELEMENTS : 1 ; int readlen = 0 ; DirblobClear(&(ds->gulp)); if ( BAD( BUS_select(pn) ) ) { LEVEL_DEBUG("Selection problem before a directory listing") ; return search_error ; } if ( pn->selected_connection->AnyDevices == anydevices_no ) { // empty bus detected, no presence pulse detected return search_done ; } SetupDiscrepancy(ds, EP2_data); // set the search start location ret = DS9490_write(EP2_data, SERIAL_NUMBER_SIZE, pn) ; if ( ret < SERIAL_NUMBER_SIZE ) { LEVEL_DATA("bulk write problem = %d", ret); return search_error; } // Send the search request if ( BAD( USB_Control_Msg(COMM_CMD, COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS, (dir_gulp_elements << 8) | (ds->search), pn) ) ) { LEVEL_DATA("control error"); return search_error; } // read the search status if ( DS9490_getstatus(status_buffer, &readlen, pn) != BUS_RESET_OK ) { return search_error; } // test the buffer size waiting for us bytes_back = status_buffer[13]; LEVEL_DEBUG("Got %d bytes from USB search", bytes_back); if (bytes_back == 0) { /* Nothing found on the bus. Have to return something != search_good to avoid * getting stuck in loop in FS_realdir() and FS_alarmdir() * which ends when ret!=search_good */ LEVEL_DATA("ReadBufferstatus == 0"); return search_done; } else if ( bytes_back % SERIAL_NUMBER_SIZE != 0 ) { LEVEL_DATA("ReadBufferstatus size %d not a multiple of %d", bytes_back,SERIAL_NUMBER_SIZE); return search_error; } else if ( bytes_back > (dir_gulp_elements + 1) * SERIAL_NUMBER_SIZE ) { LEVEL_DATA("ReadBufferstatus size %d too large", bytes_back); return search_error; } devices_found = bytes_back / SERIAL_NUMBER_SIZE; if (devices_found > dir_gulp_elements) { devices_found = dir_gulp_elements; } // read in the buffer that holds the devices found if ((ret = DS9490_read(EP3.b, bytes_back, pn)) <= 0) { LEVEL_DATA("bulk read problem ret=%d", ret); return search_error; } // analyze each device found for (device_index = 0; device_index < devices_found; ++device_index) { /* test for CRC error */ LEVEL_DEBUG("gulp. Adding element %d:" SNformat, device_index, SNvar(EP3.sn[device_index])); if (CRC8(EP3.sn[device_index], SERIAL_NUMBER_SIZE) != 0 || EP3.sn[device_index][0] == 0) { LEVEL_DATA("CRC error"); return search_error; } } // all ok, so add the devices for (device_index = 0; device_index < devices_found; ++device_index) { DirblobAdd(EP3.sn[device_index], &(ds->gulp)); } ds->LastDiscrepancy = FindDiscrepancy(EP3.sn[devices_found-1], EP3.sn[devices_found]); ds->LastDevice = (bytes_back == devices_found * SERIAL_NUMBER_SIZE); // no more to read return search_good; }
void BUS_next_cleanup( struct device_search *ds ) { DirblobClear(&(ds->gulp)); }
void Detail_Close( void ) { DirblobClear( & (DD.sn) ) ; DirblobClear( & (DD.length) ) ; }