/* write flag */ static ZERO_OR_ERROR FS_w_flag(struct one_wire_query *owq) { struct parsedname *pn = PN(owq); BYTE cr; BYTE fl = pn->selected_filetype->data.c; OWQ_allocate_struct_and_pointer(owq_flag); OWQ_create_temporary(owq_flag, (char *) &cr, 1, 0x0201, pn); if (COMMON_read_memory_F0(owq_flag, 0, 0)) { return -EINVAL; } if (OWQ_Y(owq)) { if (cr & fl) { return 0; } } else { if ((cr & fl) == 0) { return 0; } } cr ^= fl; /* flip the bit */ if (OW_w_mem(&cr, 1, 0x0201, pn)) { return -EINVAL; } return 0; }
static GOOD_OR_BAD OW_r_mem(BYTE * p, size_t size, off_t offset, struct parsedname *pn) { OWQ_allocate_struct_and_pointer(owq_read); OWQ_create_temporary(owq_read, (char *) p, size, offset, pn); return COMMON_read_memory_crc16_AA(owq_read, 0, _1W_2450_PAGESIZE); }
static ZERO_OR_ERROR FS_r_set_alarm(struct one_wire_query *owq) { BYTE c; OWQ_allocate_struct_and_pointer(owq_alarm); OWQ_create_temporary(owq_alarm, (char *) &c, 1, 0x0200, PN(owq)); if (COMMON_read_memory_F0(owq_alarm, 0, 0)) { return -EINVAL; } OWQ_U(owq) = Avals[(c >> 3) & 0x07]; return 0; }
/* read flag */ static ZERO_OR_ERROR FS_r_flag(struct one_wire_query *owq) { struct parsedname *pn = PN(owq); BYTE cr; BYTE fl = pn->selected_filetype->data.c; OWQ_allocate_struct_and_pointer(owq_flag); OWQ_create_temporary(owq_flag, (char *) &cr, 1, 0x0201, pn); if (COMMON_read_memory_F0(owq_flag, 0, 0)) { return -EINVAL; } OWQ_Y(owq) = (cr & fl) ? 1 : 0; return 0; }
// This function probably needs to be modified a bit... static SIZE_OR_ERROR FS_r_simultaneous(struct one_wire_query *owq) { // Device not locked. OWQ_allocate_struct_and_pointer(owq_given); if (SpecifiedBus(PN(owq))) { return FS_r_given_bus(owq); } memcpy(owq_given, owq, sizeof(struct one_wire_query)); // shallow copy // it's hard to know what we should return when reading /simultaneous/temperature SetKnownBus(0, PN(owq_given)); return FS_r_given_bus(owq_given); }
SIZE_OR_ERROR FS_get(const char *path, char **return_buffer, size_t * buffer_length) { SIZE_OR_ERROR size = 0 ; /* current buffer string length */ OWQ_allocate_struct_and_pointer( owq ) ; /* Check the parameters */ if (return_buffer == NULL) { // No buffer for read result. return -EINVAL; } if (path == NULL) { path = "/"; } *return_buffer = NULL; // default return string on error if ( BAD( OWQ_create(path, owq) ) ) { /* Can we parse the input string */ return -ENOENT; } if ( IsDir( PN(owq) ) ) { /* A directory of some kind */ struct charblob cb ; CharblobInit(&cb) ; getdir( &cb, owq ) ; size = CharblobLength(&cb) ; *return_buffer = copy_buffer( CharblobData(&cb), size ) ; CharblobClear( &cb ) ; } else { /* A regular file -- so read */ if ( GOOD(OWQ_allocate_read_buffer(owq)) ) { // make the space in the buffer size = FS_read_postparse(owq) ; *return_buffer = copy_buffer( OWQ_buffer(owq), size ) ; } } // the buffer is allocated by getdir or getval OWQ_destroy(owq); /* Check the parameters */ if (*return_buffer == NULL) { // no data. return -EINVAL; } if ( buffer_length != NULL ) { *buffer_length = size ; } return size ; }
/* return size if ok, else negative */ SIZE_OR_ERROR FS_write(const char *path, const char *buf, const size_t size, const off_t offset) { ZERO_OR_ERROR write_return; OWQ_allocate_struct_and_pointer(owq); LEVEL_CALL("path=%s size=%d offset=%d", SAFESTRING(path), (int) size, (int) offset); // parsable path? if ( OWQ_create(path, owq) != 0 ) { // for write return -ENOENT; } OWQ_assign_write_buffer(buf, size, offset, owq) ; write_return = FS_write_postparse(owq); OWQ_destroy(owq); return write_return; /* here's where the size is used! */ }
SIZE_OR_ERROR FS_read(const char *path, char *buf, const size_t size, const off_t offset) { SIZE_OR_ERROR read_or_error; OWQ_allocate_struct_and_pointer(owq); LEVEL_CALL("path=%s size=%d offset=%d", SAFESTRING(path), (int) size, (int) offset); // Parseable path? if ( BAD( OWQ_create(path, owq) ) ) { // for read return -ENOENT; } OWQ_assign_read_buffer( buf, size, offset, owq) ; read_or_error = FS_read_postparse(owq); OWQ_destroy(owq); return read_or_error; }
/* read REAL DS2431 pages -- 8 bytes. */ static GOOD_OR_BAD OW_w_2Dpage(BYTE * data, size_t size, off_t offset, struct parsedname *pn) { off_t pageoff = offset & 0x07; BYTE p[4 + 8 + 2] = { _1W_WRITE_SCRATCHPAD, LOW_HIGH_ADDRESS(offset - pageoff), }; struct transaction_log tcopy[] = { TRXN_START, TRXN_WRITE(p, 3 + 8), TRXN_END, }; struct transaction_log tread[] = { TRXN_START, TRXN_WR_CRC16(p, 1, 3 + 8), TRXN_COMPARE(&p[4], data, size), TRXN_END, }; struct transaction_log tsram[] = { TRXN_START, TRXN_WRITE(p, 4), TRXN_DELAY(13), TRXN_END, }; if (size != 8) { // incomplete page OWQ_allocate_struct_and_pointer(owq_old); OWQ_create_temporary(owq_old, (char *) &p[3], 8, offset - pageoff, pn); if (COMMON_read_memory_F0(owq_old, 0, 0)) { return gbBAD; } } memcpy(&p[3 + pageoff], data, size); /* Copy to scratchpad */ RETURN_BAD_IF_BAD(BUS_transaction(tcopy, pn)) ; /* Re-read scratchpad and compare */ p[0] = _1W_READ_SCRATCHPAD; RETURN_BAD_IF_BAD(BUS_transaction(tread, pn)) ; /* Copy Scratchpad to SRAM */ p[0] = _1W_COPY_SCRATCHPAD; return BUS_transaction(tsram, pn) ; }
/* read 4 or 5 byte number */ static GOOD_OR_BAD OW_r_ulong(uint64_t * L, size_t size, off_t offset, struct parsedname *pn) { BYTE data[5] = { 0x00, 0x00, 0x00, 0x00, 0x00, }; OWQ_allocate_struct_and_pointer(owq_ulong); OWQ_create_temporary(owq_ulong, (char *) data, size, offset, pn); if (size > 5) { return gbBAD; } if (COMMON_read_memory_F0(owq_ulong, 0, 0)) { return gbBAD; } L[0] = ((uint64_t) data[0]) + (((uint64_t) data[1]) << 8) + (((uint64_t) data[2]) << 16) + (((uint64_t) data[3]) << 24) + (((uint64_t) data[4]) << 32); return gbGOOD; }
/* This function is only used by "Simultaneous" */ static ZERO_OR_ERROR FS_w_simultaneous(struct one_wire_query *owq) { if (SpecifiedBus(PN(owq))) { return FS_w_given_bus(owq); } else if (Inbound_Control.head_port) { struct port_in * pin ; OWQ_allocate_struct_and_pointer(owq_given); memcpy(owq_given, owq, sizeof(struct one_wire_query)); // shallow copy for ( pin=Inbound_Control.head_port ; pin != NULL ; pin = pin->next ) { struct connection_in * cin; for( cin=pin->first; cin!=NO_CONNECTION ; cin=cin->next ) { SetKnownBus(cin->index, PN(owq_given)); FS_w_given_bus(owq_given); } } } return 0; }
SIZE_OR_ERROR FS_get(const char *path, char **return_buffer, size_t * buffer_length) { SIZE_OR_ERROR size = 0 ; /* current buffer string length */ OWQ_allocate_struct_and_pointer( owq ) ; /* Check the parameters */ if (return_buffer == NULL) { // No buffer supplied for read result. return -EINVAL; } if (path == NULL) { path = "/"; } *return_buffer = NULL; // default return string on error if ( BAD( OWQ_create(path, owq) ) ) { /* Can we parse the input string */ return -ENOENT; } // Check for known type. if ( (PN(owq)->selected_filetype) != NO_FILETYPE ) { // local owlib knows the type. if ( IsDir( PN(owq) ) ) { /* A directory of some kind */ struct charblob cb ; CharblobInit(&cb) ; getdir( &cb, owq ) ; size = CharblobLength(&cb) ; *return_buffer = copy_buffer( CharblobData(&cb), size ) ; CharblobClear(&cb) ; } else { /* A regular file -- so read */ if ( GOOD(OWQ_allocate_read_buffer(owq)) ) { // make the space in the buffer size = FS_read_postparse(owq) ; *return_buffer = copy_buffer( OWQ_buffer(owq), size ) ; } } } else { // local owlib doesn't know the type. struct charblob cb ; CharblobInit(&cb) ; // Try directory first. if (getdir( &cb, owq ) != -ENOTDIR) { // Is a directory. size = CharblobLength(&cb) ; *return_buffer = copy_buffer( CharblobData(&cb), size ) ; } else { // Is not a directory. Try file. if ( GOOD(OWQ_allocate_read_buffer(owq)) ) { // make the space in the buffer size = FS_read_postparse(owq) ; *return_buffer = copy_buffer( OWQ_buffer(owq), size ) ; } } CharblobClear(&cb) ; } // the buffer is allocated by getdir or getval OWQ_destroy(owq); /* Check the parameters */ if (*return_buffer == NULL) { // error return -EINVAL; } if ( buffer_length != NULL ) { // return buffer length as well *buffer_length = size ; } return size ; }
/* * lower level routine for actually handling a request * deals with data (ping is handled higher) */ void *DataHandler(void *v) { struct handlerdata *hd = v; char *retbuffer = NULL; struct client_msg cm; // the return message #if OW_CYGWIN /* Random generator seem to need initialization for each new thread * If not, seed will be reset and rand() will return 0 the first call. */ { struct timeval tv; gettimeofday(&tv, NULL); srand((unsigned int) tv.tv_usec); } #endif memset(&cm, 0, sizeof(struct client_msg)); cm.version = MakeServerprotocol(OWSERVER_PROTOCOL_VERSION); cm.control_flags = hd->sm.control_flags; // default flag return -- includes persistence state /* Pre-handling for special testing mode to exclude certain messages */ switch ((enum msg_classification) hd->sm.type) { case msg_dirall: case msg_dirallslash: if (Globals.no_dirall) { LEVEL_DEBUG("DIRALL message rejected.") ; hd->sm.type = msg_error; } break; case msg_get: case msg_getslash: if (Globals.no_get) { LEVEL_DEBUG("GET message rejected.") ; hd->sm.type = msg_error; } break; default: break; } /* Now Check message types and only parse valid messages */ switch ((enum msg_classification) hd->sm.type) { // outer switch case msg_read: // good message case msg_write: // good message case msg_dir: // good message case msg_presence: // good message case msg_dirall: // good message case msg_dirallslash: // good message case msg_get: // good message case msg_getslash: // good message if (hd->sm.payload == 0) { /* Bad query -- no data after header */ LEVEL_DEBUG("No payload -- ignore.") ; cm.ret = -EBADMSG; } else { struct parsedname *pn; OWQ_allocate_struct_and_pointer(owq); pn = PN(owq); /* Parse the path string and crete query object */ LEVEL_CALL("DataHandler: parse path=%s", hd->sp.path); cm.ret = BAD( OWQ_create(hd->sp.path, owq) ) ? -1 : 0 ; if ( cm.ret != 0 ) { LEVEL_DEBUG("DataHandler: OWQ_create failed cm.ret=%d", cm.ret); break; } /* Use client persistent settings (temp scale, display mode ...) */ pn->control_flags = hd->sm.control_flags; /* Override some settings from control flags */ if ( (pn->control_flags & UNCACHED) != 0 ) { // client wants uncached pn->state |= ePS_uncached; } if ( (pn->control_flags & ALIAS_REQUEST) == 0 ) { // client wants unaliased pn->state |= ePS_unaliased; } /* Antilooping tags */ pn->tokens = hd->sp.tokens; pn->tokenstring = hd->sp.tokenstring; //printf("Handler: sm.sg=%X pn.state=%X\n", sm.sg, pn.state); //printf("Scale=%s\n", TemperatureScaleName(SGTemperatureScale(sm.sg))); switch ((enum msg_classification) hd->sm.type) { case msg_presence: LEVEL_CALL("Presence message for %s", SAFESTRING(pn->path)); // Basically, if we were able to ParsedName it's here! cm.size = 0; retbuffer = owmalloc( SERIAL_NUMBER_SIZE ) ; if ( retbuffer ) { memcpy( retbuffer, pn->sn, SERIAL_NUMBER_SIZE ) ; cm.payload = SERIAL_NUMBER_SIZE ; } else { cm.payload = 0 ; } cm.ret = 0; // good answer break; case msg_read: LEVEL_CALL("Read message"); retbuffer = ReadHandler(hd, &cm, owq); LEVEL_DEBUG("Read message done value=%p", retbuffer); break; case msg_write: LEVEL_CALL("Write message"); if ( (int) hd->sp.datasize < hd->sm.size ) { cm.ret = -EMSGSIZE; } else { /* set buffer (size already set) */ OWQ_assign_write_buffer( (ASCII *) hd->sp.data, hd->sm.size, hd->sm.offset, owq) ; WriteHandler(hd, &cm, owq); } break; case msg_dir: LEVEL_CALL("Directory message (one at a time)"); DirHandler(hd, &cm, pn); break; case msg_dirall: LEVEL_CALL("Directory message (all at once)"); retbuffer = DirallHandler(hd, &cm, pn); break; case msg_dirallslash: LEVEL_CALL("Directory message (all at once, with directory /)"); retbuffer = DirallslashHandler(hd, &cm, pn); break; case msg_get: if (IsDir(pn)) { LEVEL_CALL("Get -> Directory message (all at once)"); retbuffer = DirallHandler(hd, &cm, pn); } else { LEVEL_CALL("Get -> Read message"); retbuffer = ReadHandler(hd, &cm, owq); } break; case msg_getslash: if (IsDir(pn)) { LEVEL_CALL("Get -> Directory message (all at once)"); retbuffer = DirallslashHandler(hd, &cm, pn); } else { LEVEL_CALL("Get -> Read message"); retbuffer = ReadHandler(hd, &cm, owq); } break; default: // never reached LEVEL_CALL("Error: unknown message %d", (int) hd->sm.type); break; } OWQ_destroy(owq); LEVEL_DEBUG("DataHandler: FS_ParsedName_destroy done"); } break; case msg_nop: // "bad" message LEVEL_CALL("NOP message"); cm.ret = 0; break; case msg_size: // no longer used case msg_error: default: // "bad" message cm.ret = -ENOMSG; LEVEL_CALL("No message"); break; } LEVEL_DEBUG("DataHandler: cm.ret=%d", cm.ret); TOCLIENTLOCK(hd); if (cm.ret != -EIO) { ToClient(hd->file_descriptor, &cm, retbuffer); } else { ErrorToClient(hd, &cm) ; } // Signal to PingLoop that we're done. hd->toclient = toclient_complete ; if ( hd->ping_pipe[fd_pipe_write] != FILE_DESCRIPTOR_BAD ) { ignore_result = write( hd->ping_pipe[fd_pipe_write],"X",1) ; //dummy payload } TOCLIENTUNLOCK(hd); if (retbuffer) { owfree(retbuffer); } LEVEL_DEBUG("Finished with client request"); return VOID_RETURN; }