/* Project: DS1992 memory iButton dumper Author: Florian Jung (flo@windfisch.org) Copyright (c) 2015,2016, Florian Jung. All rights reserved. License: 3-Clause-BSD as follows: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This project is based on the code for the AVR ATtiny USB Tutorial at http://codeandlife.com/ by Joonas Pihlajamaa, joonas.pihlajamaa@iki.fi, which is in turn based on the V-USB example code by Christian Starkjohann (Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH) Note that, while this file is BSD-licensed, different licensing applies for V-USB, and thus for the resulting binaries. */ #include #include #include #include #include #include #include "usbdrv/usbdrv.h" #include "1wire.h" #define LED_BLUE (1<<5) #define LED_RED (1<<4) #define LED_GREEN (1<<3) #define FUNC_READ 0x42 #define FUNC_WRITE 0x21 #define FUNC_START_BOOTLOADER 30 #define FUNC_GET_TYPE 0xFE volatile int got_data = 0; // set to 1, if we get data to write from the PC volatile int recvd_data_len = 0; void jump_to_bootloader(void) { cli(); wdt_enable(WDTO_15MS); while (1); } static uchar replyBuffer[130]="Hello world initial"; static uchar buf[33]; usbMsgLen_t usbFunctionSetup(uchar data[8]) { usbRequest_t *rq = (void *) data; int len = 1; switch (rq->bRequest) { case FUNC_GET_TYPE: replyBuffer[0]=10; len = 1; break; case FUNC_START_BOOTLOADER: jump_to_bootloader(); len = 0; break; case FUNC_READ: recvd_data_len = 0; return USB_NO_MSG; case FUNC_WRITE: PORTC ^= LED_RED; //strcpy(replyBuffer, "Hello world"); //len = strlen(replyBuffer)+1; len = 130; break; } usbMsgPtr = replyBuffer; return len; } volatile int count = 5; uchar usbFunctionWrite(uint8_t * data, uchar len) { memcpy(replyBuffer+recvd_data_len,data,len); recvd_data_len+=len; if (recvd_data_len >= 33) got_data = 1; //replyBuffer[len]='\0'; return len; } void usb_disconnect() { USB_INTR_ENABLE &= ~(1 << USB_INTR_ENABLE_BIT); usbDeviceDisconnect(); } void usb_reconnect() { cli(); usbDeviceDisconnect(); // enforce re-enumeration for (int i = 0; i < 250; i++) { // wait 500 ms wdt_reset(); // keep the watchdog happy _delay_ms(10); } usbDeviceConnect(); USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT); sei(); } int main(void) { uint32_t c = 0; DDRC = 0x38; // LEDs as output PORTC |= LED_BLUE | LED_RED | LED_GREEN; DDRD &= ~0xF3; // connector ports as input DDRB &= ~0x3C; PORTD &= ~0xF3; // disable pullups for unused ports PORTB &= ~0x0C; PORTB |= 0x30; // enable pullups for PB4 and 5 replyBuffer[129] = 0; cli(); wdt_enable(WDTO_1S); // enable 1s watchdog timer usbInit(); usbDeviceDisconnect(); // enforce re-enumeration for (int i = 0; i < 250; i++) { // wait 500 ms wdt_reset(); // keep the watchdog happy _delay_ms(10); } usbDeviceConnect(); sei(); // Enable interrupts after re-enumeration uint8_t error = 0; while (1) { wdt_reset(); // keep the watchdog happy usbPoll(); if (++c % (error ? 12000 : got_data ? 1000 : 3000) == 0) { PORTC^=LED_BLUE; PORTC |= LED_RED | LED_GREEN; } if (c % 12000 == 0) { if (!got_data) // we want to read the token { uint8_t result = w1_reset(); if (result == 0) // device detected { PORTC &= ~LED_GREEN; ds1992_read(0, replyBuffer, 128); } else if (result == 1) // no presence pulse == no device detected PORTC &= ~LED_RED; else // short circuit detected PORTC &= ~(LED_RED | LED_GREEN); } else // we want to WRITE the token (*shudder*!) { uint8_t result = w1_reset(); if (result == 0) // device detected { PORTC &= ~LED_GREEN; cli(); memcpy(buf, replyBuffer, 33); got_data = 0; sei(); uint16_t writepos = ((uint16_t)buf[32]) * 32; ds1992_scratch_write(writepos, buf, 32); result = w1_reset(); if (result != 0) { replyBuffer[0] = 0x01; error = 1; goto write_failed; } uint8_t es_reg; result = ds1992_scratch_verify(writepos, buf, 32, &es_reg); if (result != 0) { replyBuffer[0] = 0x02; error = 1; goto write_failed; } result = w1_reset(); if (result != 0) { replyBuffer[0] = 0x03; error = 1; goto write_failed; } // commit the write ds1992_scratch_copy(writepos, es_reg); replyBuffer[0] = 0xFF; // success error = 0; write_failed: 1; } else if (result == 1) // no presence pulse == no device detected PORTC &= ~LED_RED; else // short circuit detected PORTC &= ~(LED_RED | LED_GREEN); } } } jump_to_bootloader(); return 0; }