/* ************************************************************************* */ /* SauthPalm.c */ /* DS Software Authorization Alpha01 API for the HandSpring Visor */ /* 04/03/2000 */ /* */ /* Copyright (C) 2000 Dallas Semiconductor Corporation. */ /* All rights Reserved. Printed in U.S.A. */ /* This software is protected by copyright laws of */ /* the United States and of foreign countries. */ /* This software is furnished under a license agreement and/or a */ /* nondisclosure agreement and may only be used or copied in accordance */ /* with the terms of those agreements. */ /* The mere transfer of this software does not imply any licenses */ /* of trade secrets, proprietary technology, copyrights, patents, */ /* trademarks, maskwork rights, or any other form of intellectual */ /* property whatsoever. Dallas Semiconductor retains all ownership rights. */ /* */ /* Additional Notes: */ /* This code was compiled using CodeWarrior 6 for Palm Computing Platform. */ /* This code was originally derived from SAuth400 in DS1410k and was */ /* modified to support the C-API for the Java Powered iButton. */ /* Functions that begin with iB (iBFirst(), ...) can be optimized by */ /* removing the call overhead of the non-iB versions of these functions */ /* (first(),...) */ /* */ /* ************************************************************************* */ #include #include "ownet.h" #include "SauthPalm.h" asm void Sleep6us(); asm unsigned long RawInByte ():__D0; asm void RawOutByte (unsigned long p_DataByte:__D0); static uchar Inbyte(void); static void OutByte(uchar p_DataByte); static uchar ToggleOverdrive(void); static void TogglePassthru(void); static void TogglePassthru(void); static uchar EnterPassthru(void); static uchar ExitPassthru(void); static uchar RomSearch(void); uchar DOWReset(void); static uchar DOWBit(uchar tbit); uchar DOWByte(uchar bts); static uchar DS1481Present(void); static uchar CheckOD(void); static uchar DS1481Comm(uchar DRegByte); static uchar CheckBusy(); void FastSleep(long Delay); // asm void Sleep6us(); asm void SpinUSec(long uSecs:__D0); // static uchar SetupOk = FALSE; static uchar Passthru = TRUE; static uchar FailNext; static uchar AccessGood; static uchar TimeOut; static uchar l0 = 0; static uchar RomDta[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; static ushort pa_vals[] = {PALM_EXTERNAL_DS1481, PALM_INTERNAL_DS1481}; static ushort bpa = PALM_EXTERNAL_DS1481; // static uchar g_OverdriveOn = FALSE; static uchar g_PowerOn = FALSE; // int gType = PARALLEL_DS1481; /* default to the parallel port */ // /*********************************************************************** * * read in a byte at visor's CS1 address * ***********************************************************************/ asm void Sleep6us() { rts; } // // These assembly routines gave me a little bit of trouble. // Move.b works fine for RawOutByte but not for RawInByte. // I kept getting the next-to-least significant byte in // RawInByte. I found that Move.l gave me the correct // results for this routine. // /*********************************************************************** * * read in a byte at visor's CS1 address * ***********************************************************************/ asm unsigned long RawInByte ():__D0 { movea.l #0x29000000, A0 move.l (A0), d0 // result is in d0 rts; } /*********************************************************************** * * read in a byte at visor's CS1 address * ***********************************************************************/ static uchar InByte (void) { ulong l_Temp = 0; /* if(!g_PowerOn) { RawOutByte(0x080); g_PowerOn = TRUE; } */ l_Temp = RawInByte(); return (uchar)(bpa? (l_Temp>>4): l_Temp); } /*********************************************************************** * * write in a byte at visor's CS1 address * ***********************************************************************/ asm void RawOutByte (unsigned long p_DataByte:__D0) { movea.l #0x29000000, A0 move.b d0, (A0) rts; } /*********************************************************************** * * write in a byte at visor's CS1 address * ***********************************************************************/ static void OutByte(uchar p_DataByte) { if(!g_PowerOn) { RawOutByte(0x080); g_PowerOn = TRUE; } RawOutByte((ulong)((bpa? p_DataByte<<4: p_DataByte)|0x80)); } //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// void FastSleep(long Delay) { Sleep(Delay); } //////////////////////////////////////////////////////////////////////// void Sleep(long p_Milliseconds) { long l_Centiseconds = (p_Milliseconds + 5) / 10; if(l_Centiseconds == 0) l_Centiseconds++; SysTaskDelay(l_Centiseconds); } //////////////////////////////////////////////////////////////////////// void AdapterPowerManagement(uchar p_PowerOn) { g_PowerOn = (uchar)(p_PowerOn? TRUE: FALSE); RawOutByte((ulong)(p_PowerOn? 0x80: 0)); } //////////////////////////////////////////////////////////////////////// uchar iBKeyOpen(void) { return keyopen(); } uchar far pascal keyopen(void) { ExitPassthru(); if(CheckOD()) OverdriveOff(); return TRUE; } //////////////////////////////////////////////////////////////////////// uchar iBKeyClose(void) { return keyclose(); } uchar far pascal keyclose(void) { EnterPassthru(); return TRUE; } //////////////////////////////////////////////////////////////////////// // // No device driver is required for Palm operation, so dowcheck will // simply return TRUE. // uchar far pascal dowcheck(void) { return TRUE; } //////////////////////////////////////////////////////////////////////// static void TogglePassthru(void) { uchar i = 0; for(i = 0; i < 4; i++) ToggleOverdrive(); Sleep(20); } //////////////////////////////////////////////////////////////////////// static uchar EnterPassthru(void) { Passthru = (uchar)!CheckBusy(); if(!Passthru) { TogglePassthru(); Passthru = (uchar)!CheckBusy(); } return Passthru; } //////////////////////////////////////////////////////////////////////// static uchar ExitPassthru(void) { Passthru = (uchar)!CheckBusy(); if(Passthru) { TogglePassthru(); Passthru = (uchar)!CheckBusy(); } return (uchar)(!Passthru); } //////////////////////////////////////////////////////////////////////// // // This function sets the base port address. // uchar iBSetup(uchar pn) { return setup(pn); } uchar far pascal setup(uchar pn) { // Initialize global flags SetupOk = FailNext = AccessGood = FALSE; // Reset RomSearch (first, next) algorithm FailNext = FALSE; l0 = 0; // Make sure port number is valid if(pn > 0 && pn < 3) { // This allows all other functions to execute SetupOk = TRUE; // Set base port address bpa = pa_vals[pn - 1]; } else bpa = pa_vals[0]; // Set to default in case caller ignores FALSE return // Return result of setup function return SetupOk; } //////////////////////////////////////////////////////////////////////// // // Find next DOW part on selected LPT port // uchar iBNext(void) { return next(); } uchar far pascal next(void) { uchar tr; if(SetupOk) { // See if last search found last button if(FailNext) { FailNext = FALSE; // Reset next function l0 = 0; } else while((tr = RomSearch()) != 0) { // See if we should force failure if(tr == 2) FailNext = 1; // Detect short circuit if(!RomDta[0]) { return FALSE; } AccessGood = TRUE; return TRUE; } } return FALSE; } //////////////////////////////////////////////////////////////////////// // // Find first DOW part on specified port // uchar iBFirst(void) { return first(); } uchar far pascal first(void) { // Don't force a failure here FailNext = FALSE; // Point Rom Search algorithm to the top l0 = 0; // Go look for the first DOW part on the bus return next(); } //////////////////////////////////////////////////////////////////////// // // Strong access // uchar iBAccess(void) { return access(); } uchar far pascal access(void) { uchar i, j; // Assume failure AccessGood = FALSE; // Send reset pulse if(DOWReset()) { // ROM search command byte DOWByte(0xF0); // Byte loop for(i = 0; i < 8; i++) { // Bit loop for(j = 0; j < 8; j++) { if(((DOWBit(TRUE) << 1) | DOWBit(TRUE)) == 3) return FALSE; // Send write time slot DOWBit((uchar) ((RomDta[i] >> j) & 1)); } } // Success if we made it through all the bits AccessGood = TRUE; } return AccessGood; } //////////////////////////////////////////////////////////////////////// // // Transmit data to buttons on the selected LPT port // uchar iBDataByte(uchar data) { return databyte(data); } uchar far pascal databyte(uchar br) { return (SetupOk && AccessGood) ? DOWByte(br) : br; } //////////////////////////////////////////////////////////////////////// uchar far pascal gndtest(void) { return SetupOk; } //////////////////////////////////////////////////////////////////////// uchar *iBROMData(void) { return romdata(); } uchar far * far pascal romdata(void) { // Return pointer to ROM Data buffer return RomDta; } //////////////////////////////////////////////////////////////////////// // // This function performs a ROM search and finds one part on the DOW bus // per call. // // Return values : 0 => No parts on bus or bus error // 1 => A part was found and more are out there // 2 => A part was found and it was last one on the bus // static uchar RomSearch(void) { uchar i = 0, x = 0, ld = l0; uchar RomBit, Mask; // Reset DOW bus if(DOWReset()) DOWByte(0xF0); // Send search command else { return FALSE; // No DOW parts were found on bus } // While not done and not bus error while((i++ < 64) && (x < 3)) { // Get bit mask Mask = (uchar)(1 << ((i - 1) % 8)) ; // Get last pass bit RomBit = (uchar)(RomDta[(i - 1) >> 3] & Mask ? TRUE : FALSE); // Send read time slots x = (uchar)(DOWBit(TRUE) << 1); x |= DOWBit(TRUE); // Is there a disagreement in this bit position if(!x) { // Stay on old path or pick a new one ? if(i >= ld) RomBit = (uchar)(i == ld); // Send write 1 if at position of ld // Save this value as temp last disagreement if(!RomBit) l0 = i; } else RomBit = (uchar)((x & 1) ^ 1); // Get lsb of x and flip it if(RomBit) RomDta[(i - 1) >> 3] |= Mask; // Set bit in Rom Data byte else RomDta[(i - 1) >> 3] &= (uchar)((Mask ^ 0xFF)); // Clear bit in Rom Data byte // Send write time slot DOWBit(RomBit); } return (uchar)((x == 3) ? 0 : 1 + (ld == l0)); } //////////////////////////////////////////////////////////////////////// uchar DOWReset(void) { // Sampling a low => presence detected => success return (uchar)(DS1481Comm(RESET) ^ 1); } //////////////////////////////////////////////////////////////////////// uchar iBDataBit(uchar bit) { return DOWBit(bit); } static uchar DOWBit(uchar tbit) { // Return sampled value return DS1481Comm((uchar)(tbit ? RWBIT : W0BIT)); } //////////////////////////////////////////////////////////////////////// uchar DOWByte(uchar bts) { uchar i, brecv = 0; // Call DOWBit 8 times to transfer entire byte for(i = 0; i < 8; i++) { brecv >>= 1; // Smush bit into byte brecv |= (uchar)(DOWBit((uchar) (bts & 1)) ? 0x80 : 0); bts >>= 1; } // Return result sampled on 1-wire bus return brecv; } //////////////////////////////////////////////////////////////////////// uchar iBOverdriveOn(void) { return OverdriveOn(); } uchar far pascal OverdriveOn(void) { // Comment out code so that it is not done twice...jpe // if(!DOWReset()) // { //Sleep(500); // return FALSE; // } // Put all parts in overdrive mode // DOWByte(0x3C); if(!(g_OverdriveOn = CheckOD())) { ToggleOverdrive(); //g_OverdriveOn = CheckOD(); } Sleep(20); return g_OverdriveOn; } //////////////////////////////////////////////////////////////////////// uchar iBOverdriveOff(void) { return OverdriveOff(); } uchar far pascal OverdriveOff(void) { // Turn overdrive off if((g_OverdriveOn = CheckOD())) { ToggleOverdrive(); //g_OverdriveOn = CheckOD(); } Sleep(20); return (uchar)(g_OverdriveOn? FALSE: TRUE); } //////////////////////////////////////////////////////////////////////// // // Change state of overdrive ff in all 1481s on LPT port. // static uchar ToggleOverdrive(void) { // Disable interrupts DisableInterrupts(); // Set initial state OutByte(0xff); // Set initial state - DClk, Res low OutByte(0xf9); // Drive chip select low OutByte(0xf8); // Drive pin 14 back high again !!! OutByte(0xff); // Allow interrupts back in EnableInterrupts(); g_OverdriveOn = (uchar)~g_OverdriveOn; return g_OverdriveOn; } //////////////////////////////////////////////////////////////////////// static uchar DS1481Present(void) { return (uchar)(CheckBusy() == TRUE); } //////////////////////////////////////////////////////////////////////// static uchar DS1481Comm(uchar DRegByte) { uchar DOWRes; ushort MDelay; DisableInterrupts(); OutByte(0xff); Sleep6us(); // Set initial state of data lines OutByte((uchar)(DRegByte | 1)); Sleep6us(); // Drive chip select low OutByte((uchar)(DRegByte & 0xfe)); // Wait for DS1481 to issue busy signal MDelay = 0; while((InByte() & 1) && (MDelay++ < MAX_W)) {} EnableInterrupts() // Now we can reset the state of the data lines OutByte(0xfe); MDelay = 0; while(!(InByte() & 1) && (MDelay++ < MAX_W)) {} // Drive clk line low to get our bit OutByte(0xfc); // Get bit result DOWRes = (uchar)((InByte() & 1) ? TRUE : FALSE); // Drive ENI back high again !!! OutByte(0xff); return DOWRes; } //////////////////////////////////////////////////////////////////////// // This function sends a WRITE1 and looks for the busy lines to go low. // If a low is detected the timeslot is aborted and TRUE is returned. // // If the 1481 is in passthrough mode the busy lines will never go low. // // ASSUMPTIONS are all based empirically on Palm Handheld timing. // static uchar CheckBusy() { uchar Busy; int i; DisableInterrupts(); OutByte(0xff); // Set initial state of data lines OutByte((uchar)(0xf7)); // Drive chip select low OutByte((uchar)(0xf6)); // Wait for DS1481 to issue busy signal for(i = 0; i < 10; i++) { Busy = (uchar)((InByte() & 1)? FALSE: TRUE); if(Busy) break; } OutByte(0xf4); EnableInterrupts() // Drive pin 14 back high again !!! OutByte(0xff); return Busy; } //////////////////////////////////////////////////////////////////////// // This function sends a WRITE1 and looks for the busy lines to go low. // If a low is detected the timeslot is aborted // // If the 1481 is in overdrive the WRITE1 is short and the second read // should miss the busy signal. // // ASSUMPTIONS are all based empirically on Palm Handheld timing. // static uchar CheckOD() { uchar l_OverDrive; int i; ushort MDelay; DisableInterrupts(); OutByte(0xff); // set initial state of data lines for write 1 OutByte((uchar)(0xf7)); // drive chip select low OutByte((uchar)(0xf6)); // wait for DS1481 to issue busy signal MDelay = 0; while((InByte() & 1) && (MDelay++ < MAX_W)) {} // wait for DS1481 to release busy signal // timeslot is on the order of 6 us for OD // and 60 us for regular speed for(i = 0; i < 2; i++) { Sleep6us(); l_OverDrive = (uchar)((InByte() & 1)? TRUE: FALSE); if(l_OverDrive) break; } EnableInterrupts() // Drive pin 14 back high again !!! OutByte(0xff); return l_OverDrive; } //////////////////////////////////////////////////////////////////////// /****************************************************************************** /* /* Block I/O command. Transmit data in blocks of size PAR_BLOCK_SIZE. /* Return received bytes in the same buffer. /* /******************************************************************************/ uchar iBDataBlock(uchar *data, int count) { int i; /* Byte-bang the thing */ for(i = 0; i < count; i++) data[i] = iBDataByte(data[i]); return TRUE; } //////////////////////////////////////////////////////////////////////// uchar SetAdapterType(uchar Type, char *type) { if(Type != DS1410) return FALSE; gType = DS1410; return TRUE; } //////////////////////////////////////////////////////////////////////// uchar SetAdapterSpeed(ulong speed) { return TRUE; } //////////////////////////////////////////////////////////////////////// uchar iBStream(uchar *arr,int length) { int i; int AccessGood = FALSE; uchar accessarray[9]; if (DOWReset()) { AccessGood = TRUE; /* Set up block for transmit */ accessarray[0] = 0x55; for (i = 1;i < 9;i++) accessarray[i] = RomDta[i-1]; /* Transmit block. */ iBDataBlock(accessarray,9); iBDataBlock(arr,length); } return (uchar)AccessGood; } //////////////////////////////////////////////////////////////////////// uchar iBFastAccess(void) { return iBAccess(); } //////////////////////////////////////////////////////////////////////// uchar iBStrongAccess(void) { uchar i, j; uchar mask = 0x80; //uchar byte; //uchar bit; //uchar bytesend[24]; /* Assume failure */ AccessGood = FALSE; /* Send reset pulse */ if (DOWReset()) { /* ROM search command byte */ DOWByte(0xF0); /* Byte loop */ for (i = 0; i < 8; i++) { /* Bit loop */ for (j = 0; j < 8; j++) { /* Send two read time slots */ if (((DOWBit(TRUE) << 1) | DOWBit(TRUE)) == 3) return FALSE; /* Send write time slot */ DOWBit((uchar) ((RomDta[i] >> j) & 1)); } } /* Success if we made it through all bits */ AccessGood = TRUE; } return AccessGood; } //////////////////////////////////////////////////////////////////////// uchar SetAdapter5VTime(uchar time) { return TRUE; } //////////////////////////////////////////////////////////////////////// uchar Adapter5VPrime(void) { return TRUE; } //////////////////////////////////////////////////////////////////////// uchar Adapter5VCancel(void) { return TRUE; } //////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////