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; }
/* write to 2450 */ static GOOD_OR_BAD OW_w_mem(BYTE * p, size_t size, off_t offset, struct parsedname *pn) { // command, address(2) , data , crc(2), databack BYTE buf[6] = { _1W_WRITE_MEMORY, LOW_HIGH_ADDRESS(offset), p[0], }; BYTE echo[1]; size_t i; struct transaction_log tfirst[] = { TRXN_START, TRXN_WR_CRC16(buf, 4, 0), TRXN_READ1(echo), TRXN_COMPARE(echo, p, 1), TRXN_END, }; struct transaction_log trest[] = { // note no TRXN_START TRXN_WRITE1(buf), TRXN_READ2(&buf[1]), TRXN_READ1(echo), TRXN_END, }; //printf("2450 W mem size=%d location=%d\n",size,location) ; if (size == 0) { return gbGOOD; } /* Send the first byte (handled differently) */ RETURN_BAD_IF_BAD(BUS_transaction(tfirst, pn)) ; /* rest of the bytes */ for (i = 1; i < size; ++i) { buf[0] = p[i]; RETURN_BAD_IF_BAD( BUS_transaction(trest, pn) ) ; if ( CRC16seeded(buf, 3, offset + i) || (echo[0] != p[i]) ) { return gbBAD; } } return gbGOOD; }
static GOOD_OR_BAD OW_r_std(BYTE *buf, size_t *buflen, BYTE type, BYTE stype, const struct parsedname *pn) { BYTE p[3] = { _1W_READ_MOAT, type,stype }; size_t maxlen = *buflen; BYTE len; GOOD_OR_BAD ret = gbGOOD; struct transaction_log tfirst[] = { TRXN_START, TRXN_WRITE3(p), TRXN_READ1(&len), TRXN_END, }; if (maxlen == 0) { return gbGOOD; } LEVEL_DEBUG( "read: read len for %d %d",type,stype) ; /* 0xFF means the device was too slow */ if ( BAD(BUS_transaction(tfirst, pn)) || len == 0xFF) { goto out_bad; } LEVEL_DEBUG( "read: got len %d",len) ; if (len > maxlen) { /* don't read all and don't bother with CRC. * This will abort the read on the client side so that * there'll be no side effects like marked-as-sent buffers * or cleared 'conditional search' flags */ struct transaction_log tinfo[] = { TRXN_READ(buf,maxlen), TRXN_END, }; if ( BAD(BUS_transaction(tinfo, pn)) ) { goto out_bad; } } else { UINT crc; BYTE crcbuf[2]; struct transaction_log recv_buf[] = { TRXN_READ(buf,len), TRXN_READ2(crcbuf), TRXN_END, }; struct transaction_log recv_crc[] = { TRXN_READ2(crcbuf), TRXN_END, }; struct transaction_log xmit_crc[] = { TRXN_WRITE2(crcbuf), TRXN_END, }; if ( BAD(BUS_transaction(len ? recv_buf : recv_crc, pn)) ) { goto out_bad; } crc = CRC16compute(p,3,0); crc = CRC16compute(&len,1,crc); if (len) crc = CRC16compute(buf,len,crc); LEVEL_DEBUG( "read CRC: GOOD, got %02x%02x",crcbuf[0],crcbuf[1]) ; if ( CRC16seeded (crcbuf,2,crc) ) { LEVEL_DEBUG("CRC error"); goto out_bad; } crcbuf[0] = ~crcbuf[0]; crcbuf[1] = ~crcbuf[1]; if ( BAD(BUS_transaction(xmit_crc, pn)) ) { goto out_bad; } *buflen = len; } LEVEL_DEBUG( "read: GOOD, got %d",*buflen) ; return ret; out_bad: return gbBAD; }
static GOOD_OR_BAD BUS_transaction_single(const struct transaction_log *t, const struct parsedname *pn) { GOOD_OR_BAD ret = gbGOOD; switch (t->type) { case trxn_select: // select a 1-wire device (by unique ID) ret = BUS_select(pn); LEVEL_DEBUG("select = %d", ret); break; case trxn_compare: // match two strings -- no actual 1-wire if ((t->in == NULL) || (t->out == NULL) || (memcmp(t->in, t->out, t->size) != 0)) { ret = gbBAD; } LEVEL_DEBUG("compare = %d", ret); break; case trxn_bitcompare: // match two strings -- no actual 1-wire if ((t->in == NULL) || (t->out == NULL) || BAD( BUS_compare_bits( t->in, t->out, t->size)) ) { ret = gbBAD; } LEVEL_DEBUG("compare = %d", ret); break; case trxn_match: // send data and compare response assert(t->in == NULL); // else use trxn_compare if (t->size == 0) { /* ignore for both cases */ break; } else { ret = BUS_send_data(t->out, t->size, pn); LEVEL_DEBUG("send = %d", ret); } break; case trxn_bitmatch: // send data and compare response assert(t->in == NULL); // else use trxn_compare if (t->size == 0) { /* ignore for both cases */ break; } else { ret = BUS_send_bits(t->out, t->size, pn); LEVEL_DEBUG("send bits = %d", ret); } break; case trxn_read: assert(t->out == NULL); // pure read if (t->size == 0) { /* ignore for all cases */ break; } else if (t->out == NULL) { ret = BUS_readin_data(t->in, t->size, pn); LEVEL_DEBUG("readin = %d", ret); } break; case trxn_bitread: assert(t->out == NULL); // pure read if (t->size == 0) { /* ignore for all cases */ break; } else if (t->out == NULL) { ret = BUS_readin_bits(t->in, t->size, pn); LEVEL_DEBUG("readin bits = %d", ret); } break; case trxn_modify: // write data and read response. No match needed ret = BUS_sendback_data(t->out, t->in, t->size, pn); LEVEL_DEBUG("modify = %d", ret); break; case trxn_bitmodify: // write data and read response. No match needed ret = BUS_sendback_bits(t->out, t->in, t->size, pn); LEVEL_DEBUG("bit modify = %d", ret); break; case trxn_blind: // write data ignore response { BYTE *dummy = owmalloc(t->size); if (dummy != NULL) { ret = BUS_sendback_data(t->out, dummy, t->size, pn); owfree(dummy); } else { ret = gbBAD; } } LEVEL_DEBUG("blind = %d", ret); break; case trxn_power: ret = BUS_PowerByte(t->out[0], t->in, t->size, pn); LEVEL_DEBUG("power (%d usec) = %d", t->size, ret); break; case trxn_bitpower: ret = BUS_PowerBit(t->out[0], t->in, t->size, pn); LEVEL_DEBUG("power bit (%d usec) = %d", t->size, ret); break; case trxn_program: ret = BUS_ProgramPulse(pn); LEVEL_DEBUG("program pulse = %d", ret); break; case trxn_crc8: ret = CRC8(t->out, t->size); LEVEL_DEBUG("CRC8 = %d", ret); break; case trxn_crc8seeded: ret = CRC8seeded(t->out, t->size, ((UINT *) (t->in))[0]); LEVEL_DEBUG("seeded CRC8 = %d", ret); break; case trxn_crc16: ret = CRC16(t->out, t->size); LEVEL_DEBUG("CRC16 = %d", ret); break; case trxn_crc16seeded: ret = CRC16seeded(t->out, t->size, ((UINT *) (t->in))[0]); LEVEL_DEBUG("seeded CRC16 = %d", ret); break; case trxn_delay: if (t->size > 0) { UT_delay(t->size); } LEVEL_DEBUG("Delay %d", t->size); break; case trxn_udelay: if (t->size > 0) { UT_delay_us(t->size); } LEVEL_DEBUG("Micro Delay %d", t->size); break; case trxn_reset: ret = BUS_reset(pn)==BUS_RESET_OK ? gbGOOD : gbBAD; LEVEL_DEBUG("reset = %d", ret); break; case trxn_end: LEVEL_DEBUG("end = %d", ret); return gbOTHER; // special "end" flag case trxn_verify: { struct parsedname pn2; memcpy(&pn2, pn, sizeof(struct parsedname)); //shallow copy pn2.selected_device = NO_DEVICE; if ( BAD( BUS_select(&pn2) )) { ret = gbBAD ; } else if ( BAD(BUS_verify(t->size, pn) )) { ret = gbBAD ; } else { ret = gbGOOD; } LEVEL_DEBUG("verify = %d", ret); } break; case trxn_nop: ret = gbGOOD; break; } return ret; }
static GOOD_OR_BAD Bundle_unpack(struct transaction_bundle *tb) { int packet_index; const struct transaction_log *tl; BYTE *data = MemblobData(&(tb->mb)); GOOD_OR_BAD ret = gbGOOD; LEVEL_DEBUG("unpacking"); for (packet_index = 0, tl = tb->start; packet_index < tb->packets; ++packet_index, ++tl) { switch (tl->type) { case trxn_compare: // match two strings -- no actual 1-wire LEVEL_DEBUG("unpacking #%d COMPARE", packet_index); if ((tl->in == NULL) || (tl->out == NULL) || (memcmp(tl->in, tl->out, tl->size) != 0)) { ret = gbBAD; } break; case trxn_bitcompare: // match two strings -- no actual 1-wire if ((tl->in == NULL) || (tl->out == NULL) || BAD( BUS_compare_bits( tl->in, tl->out, tl->size)) ) { ret = gbBAD; } break ; case trxn_match: // send data and compare response LEVEL_DEBUG("unpacking #%d MATCH", packet_index); if (memcmp(tl->out, data, tl->size) != 0) { ret = gbBAD; } data += tl->size; break; case trxn_read: case trxn_modify: // write data and read response. No match needed LEVEL_DEBUG("unpacking #%d READ MODIFY", packet_index); memmove(tl->in, data, tl->size); data += tl->size; break; case trxn_blind: LEVEL_DEBUG("unpacking #%d BLIND", packet_index); data += tl->size; break; case trxn_power: case trxn_program: LEVEL_DEBUG("unpacking #%d POWER PROGRAM", packet_index); memmove(tl->in, data, 1); data += 1; UT_delay(tl->size); break; case trxn_crc8: LEVEL_DEBUG("unpacking #%d CRC8", packet_index); if (CRC8(tl->out, tl->size) != 0) { ret = gbBAD; } break; case trxn_crc8seeded: LEVEL_DEBUG("unpacking #%d CRC8 SEEDED", packet_index); if (CRC8seeded(tl->out, tl->size, ((UINT *) (tl->in))[0]) != 0) { ret = gbBAD; } break; case trxn_crc16: LEVEL_DEBUG("unpacking #%d CRC16", packet_index); if (CRC16(tl->out, tl->size) != 0) { ret = gbBAD; } break; case trxn_crc16seeded: LEVEL_DEBUG("unpacking #%d CRC16 SEEDED", packet_index); if (CRC16seeded(tl->out, tl->size, ((UINT *) (tl->in))[0]) != 0) { ret = gbBAD; } break; case trxn_delay: LEVEL_DEBUG("unpacking #%d DELAY", packet_index); UT_delay(tl->size); break; case trxn_udelay: LEVEL_DEBUG("unpacking #%d UDELAY", packet_index); UT_delay_us(tl->size); break; case trxn_reset: case trxn_end: case trxn_verify: // should never get here LEVEL_DEBUG("unpacking #%d RESET END VERIFY", packet_index); ret = gbBAD; break; case trxn_nop: case trxn_select: LEVEL_DEBUG("unpacking #%d NOP or SELECT", packet_index); break; case trxn_bitmatch: LEVEL_DEBUG("Unsupported transaction request trxn_bitmatch"); break ; case trxn_bitmodify: LEVEL_DEBUG("Unsupported transaction request trxn_bitmodify"); break ; case trxn_bitread: LEVEL_DEBUG("Unsupported transaction request trxn_bitread"); break ; case trxn_bitpower: LEVEL_DEBUG("Unsupported transaction request trxn_bitpower"); break ; } if ( BAD(ret) ) { break; } } // clear the bundle MemblobClear(&tb->mb); tb->packets = 0; tb->select_first = 0; return ret; }