1 /* ************************************************************************* */
2 /* SauthPalm.c */
3 /* DS Software Authorization Alpha01 API for the HandSpring Visor */
4 /* 04/03/2000 */
5 /* */
6 /* Copyright (C) 2000 Dallas Semiconductor Corporation. */
7 /* All rights Reserved. Printed in U.S.A. */
8 /* This software is protected by copyright laws of */
9 /* the United States and of foreign countries. */
10 /* This software is furnished under a license agreement and/or a */
11 /* nondisclosure agreement and may only be used or copied in accordance */
12 /* with the terms of those agreements. */
13 /* The mere transfer of this software does not imply any licenses */
14 /* of trade secrets, proprietary technology, copyrights, patents, */
15 /* trademarks, maskwork rights, or any other form of intellectual */
16 /* property whatsoever. Dallas Semiconductor retains all ownership rights. */
17 /* */
18 /* Additional Notes: */
19 /* This code was compiled using CodeWarrior 6 for Palm Computing Platform. */
20 /* This code was originally derived from SAuth400 in DS1410k and was */
21 /* modified to support the C-API for the Java Powered iButton. */
22 /* Functions that begin with iB (iBFirst(), ...) can be optimized by */
23 /* removing the call overhead of the non-iB versions of these functions */
24 /* (first(),...) */
25 /* */
26 /* ************************************************************************* */
27
28 #include <SystemMgr.h>
29 #include "ownet.h"
30 #include "SauthPalm.h"
31
32 asm void Sleep6us();
33 asm unsigned long RawInByte ():__D0;
34 asm void RawOutByte (unsigned long p_DataByte:__D0);
35 static uchar Inbyte(void);
36 static void OutByte(uchar p_DataByte);
37 static uchar ToggleOverdrive(void);
38 static void TogglePassthru(void);
39 static void TogglePassthru(void);
40 static uchar EnterPassthru(void);
41 static uchar ExitPassthru(void);
42 static uchar RomSearch(void);
43 uchar DOWReset(void);
44 static uchar DOWBit(uchar tbit);
45 uchar DOWByte(uchar bts);
46 static uchar DS1481Present(void);
47 static uchar CheckOD(void);
48 static uchar DS1481Comm(uchar DRegByte);
49 static uchar CheckBusy();
50 void FastSleep(long Delay);
51 //
52 asm void Sleep6us();
53 asm void SpinUSec(long uSecs:__D0);
54 //
55 static uchar SetupOk = FALSE;
56 static uchar Passthru = TRUE;
57 static uchar FailNext;
58 static uchar AccessGood;
59 static uchar TimeOut;
60 static uchar l0 = 0;
61 static uchar RomDta[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
62 static ushort pa_vals[] = {PALM_EXTERNAL_DS1481, PALM_INTERNAL_DS1481};
63 static ushort bpa = PALM_EXTERNAL_DS1481;
64 //
65 static uchar g_OverdriveOn = FALSE;
66 static uchar g_PowerOn = FALSE;
67 //
68 int gType = PARALLEL_DS1481; /* default to the parallel port */
69 //
70 /***********************************************************************
71 *
72 * read in a byte at visor's CS1 address
73 *
74 ***********************************************************************/
Sleep6us()75 asm void Sleep6us()
76 {
77 rts;
78 }
79 //
80 // These assembly routines gave me a little bit of trouble.
81 // Move.b works fine for RawOutByte but not for RawInByte.
82 // I kept getting the next-to-least significant byte in
83 // RawInByte. I found that Move.l gave me the correct
84 // results for this routine.
85 //
86 /***********************************************************************
87 *
88 * read in a byte at visor's CS1 address
89 *
90 ***********************************************************************/
RawInByte()91 asm unsigned long RawInByte ():__D0
92 {
93 movea.l #0x29000000, A0
94 move.l (A0), d0
95 // result is in d0
96 rts;
97 }
98 /***********************************************************************
99 *
100 * read in a byte at visor's CS1 address
101 *
102 ***********************************************************************/
InByte(void)103 static uchar InByte (void)
104 {
105 ulong l_Temp = 0;
106 /*
107 if(!g_PowerOn)
108 {
109 RawOutByte(0x080);
110 g_PowerOn = TRUE;
111 }
112 */
113 l_Temp = RawInByte();
114 return (uchar)(bpa? (l_Temp>>4): l_Temp);
115 }
116 /***********************************************************************
117 *
118 * write in a byte at visor's CS1 address
119 *
120 ***********************************************************************/
121 asm void RawOutByte (unsigned long p_DataByte:__D0)
122 {
123 movea.l #0x29000000, A0
124 move.b d0, (A0)
125 rts;
126 }
127 /***********************************************************************
128 *
129 * write in a byte at visor's CS1 address
130 *
131 ***********************************************************************/
OutByte(uchar p_DataByte)132 static void OutByte(uchar p_DataByte)
133 {
134 if(!g_PowerOn)
135 {
136 RawOutByte(0x080);
137 g_PowerOn = TRUE;
138 }
139
140 RawOutByte((ulong)((bpa? p_DataByte<<4: p_DataByte)|0x80));
141 }
142 ////////////////////////////////////////////////////////////////////////
143 ////////////////////////////////////////////////////////////////////////
FastSleep(long Delay)144 void FastSleep(long Delay)
145 {
146 Sleep(Delay);
147 }
148 ////////////////////////////////////////////////////////////////////////
Sleep(long p_Milliseconds)149 void Sleep(long p_Milliseconds)
150 {
151 long l_Centiseconds = (p_Milliseconds + 5) / 10;
152
153 if(l_Centiseconds == 0)
154 l_Centiseconds++;
155
156 SysTaskDelay(l_Centiseconds);
157 }
158 ////////////////////////////////////////////////////////////////////////
AdapterPowerManagement(uchar p_PowerOn)159 void AdapterPowerManagement(uchar p_PowerOn)
160 {
161 g_PowerOn = (uchar)(p_PowerOn? TRUE: FALSE);
162 RawOutByte((ulong)(p_PowerOn? 0x80: 0));
163 }
164 ////////////////////////////////////////////////////////////////////////
iBKeyOpen(void)165 uchar iBKeyOpen(void)
166 {
167 return keyopen();
168 }
keyopen(void)169 uchar far pascal keyopen(void)
170 {
171 ExitPassthru();
172
173 if(CheckOD())
174 OverdriveOff();
175
176 return TRUE;
177 }
178 ////////////////////////////////////////////////////////////////////////
iBKeyClose(void)179 uchar iBKeyClose(void)
180 {
181 return keyclose();
182 }
keyclose(void)183 uchar far pascal keyclose(void)
184 {
185 EnterPassthru();
186 return TRUE;
187 }
188 ////////////////////////////////////////////////////////////////////////
189 //
190 // No device driver is required for Palm operation, so dowcheck will
191 // simply return TRUE.
192 //
dowcheck(void)193 uchar far pascal dowcheck(void)
194 {
195 return TRUE;
196 }
197 ////////////////////////////////////////////////////////////////////////
TogglePassthru(void)198 static void TogglePassthru(void)
199 {
200 uchar i = 0;
201
202 for(i = 0; i < 4; i++)
203 ToggleOverdrive();
204
205 Sleep(20);
206 }
207 ////////////////////////////////////////////////////////////////////////
EnterPassthru(void)208 static uchar EnterPassthru(void)
209 {
210 Passthru = (uchar)!CheckBusy();
211
212 if(!Passthru)
213 {
214 TogglePassthru();
215 Passthru = (uchar)!CheckBusy();
216 }
217
218 return Passthru;
219 }
220 ////////////////////////////////////////////////////////////////////////
ExitPassthru(void)221 static uchar ExitPassthru(void)
222 {
223 Passthru = (uchar)!CheckBusy();
224
225 if(Passthru)
226 {
227 TogglePassthru();
228 Passthru = (uchar)!CheckBusy();
229 }
230
231 return (uchar)(!Passthru);
232 }
233 ////////////////////////////////////////////////////////////////////////
234 //
235 // This function sets the base port address.
236 //
iBSetup(uchar pn)237 uchar iBSetup(uchar pn)
238 {
239 return setup(pn);
240 }
setup(uchar pn)241 uchar far pascal setup(uchar pn)
242 {
243
244 // Initialize global flags
245 SetupOk = FailNext = AccessGood = FALSE;
246
247 // Reset RomSearch (first, next) algorithm
248 FailNext = FALSE;
249 l0 = 0;
250
251 // Make sure port number is valid
252 if(pn > 0 && pn < 3)
253 {
254 // This allows all other functions to execute
255 SetupOk = TRUE;
256 // Set base port address
257 bpa = pa_vals[pn - 1];
258 }
259 else
260 bpa = pa_vals[0]; // Set to default in case caller ignores FALSE return
261
262 // Return result of setup function
263 return SetupOk;
264 }
265 ////////////////////////////////////////////////////////////////////////
266 //
267 // Find next DOW part on selected LPT port
268 //
iBNext(void)269 uchar iBNext(void)
270 {
271 return next();
272 }
next(void)273 uchar far pascal next(void)
274 {
275 uchar tr;
276
277 if(SetupOk)
278 {
279 // See if last search found last button
280 if(FailNext)
281 {
282 FailNext = FALSE;
283 // Reset next function
284 l0 = 0;
285 }
286 else while((tr = RomSearch()) != 0)
287 {
288 // See if we should force failure
289 if(tr == 2)
290 FailNext = 1;
291
292 // Detect short circuit
293 if(!RomDta[0])
294 {
295
296 return FALSE;
297 }
298
299 AccessGood = TRUE;
300 return TRUE;
301 }
302 }
303
304 return FALSE;
305 }
306 ////////////////////////////////////////////////////////////////////////
307 //
308 // Find first DOW part on specified port
309 //
iBFirst(void)310 uchar iBFirst(void)
311 {
312 return first();
313 }
first(void)314 uchar far pascal first(void)
315 {
316 // Don't force a failure here
317 FailNext = FALSE;
318 // Point Rom Search algorithm to the top
319 l0 = 0;
320
321 // Go look for the first DOW part on the bus
322 return next();
323 }
324 ////////////////////////////////////////////////////////////////////////
325 //
326 // Strong access
327 //
iBAccess(void)328 uchar iBAccess(void)
329 {
330 return access();
331 }
access(void)332 uchar far pascal access(void)
333 {
334 uchar i, j;
335
336 // Assume failure
337 AccessGood = FALSE;
338
339 // Send reset pulse
340 if(DOWReset())
341 {
342 // ROM search command byte
343 DOWByte(0xF0);
344
345 // Byte loop
346 for(i = 0; i < 8; i++)
347 {
348 // Bit loop
349 for(j = 0; j < 8; j++)
350 {
351 if(((DOWBit(TRUE) << 1) | DOWBit(TRUE)) == 3)
352 return FALSE;
353
354 // Send write time slot
355 DOWBit((uchar) ((RomDta[i] >> j) & 1));
356 }
357 }
358
359 // Success if we made it through all the bits
360 AccessGood = TRUE;
361 }
362
363 return AccessGood;
364 }
365 ////////////////////////////////////////////////////////////////////////
366 //
367 // Transmit data to buttons on the selected LPT port
368 //
iBDataByte(uchar data)369 uchar iBDataByte(uchar data)
370 {
371 return databyte(data);
372 }
databyte(uchar br)373 uchar far pascal databyte(uchar br)
374 {
375 return (SetupOk && AccessGood) ? DOWByte(br) : br;
376 }
377 ////////////////////////////////////////////////////////////////////////
gndtest(void)378 uchar far pascal gndtest(void)
379 {
380 return SetupOk;
381 }
382 ////////////////////////////////////////////////////////////////////////
iBROMData(void)383 uchar *iBROMData(void)
384 {
385 return romdata();
386 }
romdata(void)387 uchar far * far pascal romdata(void)
388 {
389 // Return pointer to ROM Data buffer
390 return RomDta;
391 }
392 ////////////////////////////////////////////////////////////////////////
393 //
394 // This function performs a ROM search and finds one part on the DOW bus
395 // per call.
396 //
397 // Return values : 0 => No parts on bus or bus error
398 // 1 => A part was found and more are out there
399 // 2 => A part was found and it was last one on the bus
400 //
RomSearch(void)401 static uchar RomSearch(void)
402 {
403 uchar i = 0,
404 x = 0,
405 ld = l0;
406 uchar RomBit,
407 Mask;
408
409 // Reset DOW bus
410 if(DOWReset())
411 DOWByte(0xF0); // Send search command
412 else
413 {
414 return FALSE; // No DOW parts were found on bus
415 }
416
417 // While not done and not bus error
418 while((i++ < 64) && (x < 3))
419 {
420 // Get bit mask
421 Mask = (uchar)(1 << ((i - 1) % 8)) ;
422
423 // Get last pass bit
424 RomBit = (uchar)(RomDta[(i - 1) >> 3] & Mask ? TRUE : FALSE);
425
426 // Send read time slots
427 x = (uchar)(DOWBit(TRUE) << 1);
428 x |= DOWBit(TRUE);
429
430 // Is there a disagreement in this bit position
431 if(!x)
432 {
433 // Stay on old path or pick a new one ?
434 if(i >= ld)
435 RomBit = (uchar)(i == ld); // Send write 1 if at position of ld
436 // Save this value as temp last disagreement
437 if(!RomBit)
438 l0 = i;
439 }
440 else
441 RomBit = (uchar)((x & 1) ^ 1); // Get lsb of x and flip it
442
443 if(RomBit)
444 RomDta[(i - 1) >> 3] |= Mask; // Set bit in Rom Data byte
445 else
446 RomDta[(i - 1) >> 3] &= (uchar)((Mask ^ 0xFF)); // Clear bit in Rom Data byte
447
448 // Send write time slot
449 DOWBit(RomBit);
450 }
451
452 return (uchar)((x == 3) ? 0 : 1 + (ld == l0));
453 }
454 ////////////////////////////////////////////////////////////////////////
DOWReset(void)455 uchar DOWReset(void)
456 {
457 // Sampling a low => presence detected => success
458 return (uchar)(DS1481Comm(RESET) ^ 1);
459 }
460 ////////////////////////////////////////////////////////////////////////
iBDataBit(uchar bit)461 uchar iBDataBit(uchar bit)
462 {
463 return DOWBit(bit);
464 }
DOWBit(uchar tbit)465 static uchar DOWBit(uchar tbit)
466 {
467 // Return sampled value
468 return DS1481Comm((uchar)(tbit ? RWBIT : W0BIT));
469 }
470 ////////////////////////////////////////////////////////////////////////
DOWByte(uchar bts)471 uchar DOWByte(uchar bts)
472 {
473 uchar i,
474 brecv = 0;
475
476 // Call DOWBit 8 times to transfer entire byte
477 for(i = 0; i < 8; i++)
478 {
479 brecv >>= 1;
480 // Smush bit into byte
481 brecv |= (uchar)(DOWBit((uchar) (bts & 1)) ? 0x80 : 0);
482 bts >>= 1;
483 }
484
485 // Return result sampled on 1-wire bus
486 return brecv;
487 }
488 ////////////////////////////////////////////////////////////////////////
iBOverdriveOn(void)489 uchar iBOverdriveOn(void)
490 {
491 return OverdriveOn();
492 }
OverdriveOn(void)493 uchar far pascal OverdriveOn(void)
494 {
495
496 // Comment out code so that it is not done twice...jpe
497 // if(!DOWReset())
498 // {
499 //Sleep(500);
500
501 // return FALSE;
502 // }
503
504 // Put all parts in overdrive mode
505 // DOWByte(0x3C);
506
507 if(!(g_OverdriveOn = CheckOD()))
508 {
509 ToggleOverdrive();
510 //g_OverdriveOn = CheckOD();
511 }
512
513 Sleep(20);
514 return g_OverdriveOn;
515 }
516 ////////////////////////////////////////////////////////////////////////
iBOverdriveOff(void)517 uchar iBOverdriveOff(void)
518 {
519 return OverdriveOff();
520 }
OverdriveOff(void)521 uchar far pascal OverdriveOff(void)
522 {
523 // Turn overdrive off
524 if((g_OverdriveOn = CheckOD()))
525 {
526 ToggleOverdrive();
527 //g_OverdriveOn = CheckOD();
528 }
529
530 Sleep(20);
531 return (uchar)(g_OverdriveOn? FALSE: TRUE);
532 }
533 ////////////////////////////////////////////////////////////////////////
534 //
535 // Change state of overdrive ff in all 1481s on LPT port.
536 //
ToggleOverdrive(void)537 static uchar ToggleOverdrive(void)
538 {
539
540 // Disable interrupts
541 DisableInterrupts();
542
543 // Set initial state
544 OutByte(0xff);
545
546 // Set initial state - DClk, Res low
547 OutByte(0xf9);
548
549 // Drive chip select low
550 OutByte(0xf8);
551
552 // Drive pin 14 back high again !!!
553 OutByte(0xff);
554
555 // Allow interrupts back in
556 EnableInterrupts();
557
558 g_OverdriveOn = (uchar)~g_OverdriveOn;
559 return g_OverdriveOn;
560 }
561 ////////////////////////////////////////////////////////////////////////
DS1481Present(void)562 static uchar DS1481Present(void)
563 {
564 return (uchar)(CheckBusy() == TRUE);
565 }
566 ////////////////////////////////////////////////////////////////////////
DS1481Comm(uchar DRegByte)567 static uchar DS1481Comm(uchar DRegByte)
568 {
569 uchar DOWRes;
570 ushort MDelay;
571
572 DisableInterrupts();
573
574 OutByte(0xff);
575 Sleep6us();
576
577 // Set initial state of data lines
578 OutByte((uchar)(DRegByte | 1));
579 Sleep6us();
580
581 // Drive chip select low
582 OutByte((uchar)(DRegByte & 0xfe));
583
584 // Wait for DS1481 to issue busy signal
585 MDelay = 0;
586
587 while((InByte() & 1) && (MDelay++ < MAX_W))
588 {}
589
590 EnableInterrupts()
591
592 // Now we can reset the state of the data lines
593 OutByte(0xfe);
594
595 MDelay = 0;
596
597 while(!(InByte() & 1) && (MDelay++ < MAX_W))
598 {}
599
600 // Drive clk line low to get our bit
601 OutByte(0xfc);
602
603 // Get bit result
604 DOWRes = (uchar)((InByte() & 1) ? TRUE : FALSE);
605
606
607 // Drive ENI back high again !!!
608 OutByte(0xff);
609 return DOWRes;
610 }
611 ////////////////////////////////////////////////////////////////////////
612 // This function sends a WRITE1 and looks for the busy lines to go low.
613 // If a low is detected the timeslot is aborted and TRUE is returned.
614 //
615 // If the 1481 is in passthrough mode the busy lines will never go low.
616 //
617 // ASSUMPTIONS are all based empirically on Palm Handheld timing.
618 //
CheckBusy()619 static uchar CheckBusy()
620 {
621 uchar Busy;
622 int i;
623
624 DisableInterrupts();
625
626 OutByte(0xff);
627
628 // Set initial state of data lines
629 OutByte((uchar)(0xf7));
630
631 // Drive chip select low
632 OutByte((uchar)(0xf6));
633
634 // Wait for DS1481 to issue busy signal
635 for(i = 0; i < 10; i++)
636 {
637 Busy = (uchar)((InByte() & 1)? FALSE: TRUE);
638
639 if(Busy)
640 break;
641 }
642
643 OutByte(0xf4);
644
645 EnableInterrupts()
646
647 // Drive pin 14 back high again !!!
648 OutByte(0xff);
649
650 return Busy;
651 }
652 ////////////////////////////////////////////////////////////////////////
653 // This function sends a WRITE1 and looks for the busy lines to go low.
654 // If a low is detected the timeslot is aborted
655 //
656 // If the 1481 is in overdrive the WRITE1 is short and the second read
657 // should miss the busy signal.
658 //
659 // ASSUMPTIONS are all based empirically on Palm Handheld timing.
660 //
CheckOD()661 static uchar CheckOD()
662 {
663 uchar l_OverDrive;
664 int i;
665 ushort MDelay;
666
667 DisableInterrupts();
668
669 OutByte(0xff);
670
671 // set initial state of data lines for write 1
672 OutByte((uchar)(0xf7));
673
674 // drive chip select low
675 OutByte((uchar)(0xf6));
676
677 // wait for DS1481 to issue busy signal
678 MDelay = 0;
679
680 while((InByte() & 1) && (MDelay++ < MAX_W))
681 {}
682
683 // wait for DS1481 to release busy signal
684 // timeslot is on the order of 6 us for OD
685 // and 60 us for regular speed
686 for(i = 0; i < 2; i++)
687 {
688 Sleep6us();
689 l_OverDrive = (uchar)((InByte() & 1)? TRUE: FALSE);
690
691 if(l_OverDrive)
692 break;
693 }
694
695 EnableInterrupts()
696
697 // Drive pin 14 back high again !!!
698 OutByte(0xff);
699
700 return l_OverDrive;
701 }
702 ////////////////////////////////////////////////////////////////////////
703 /******************************************************************************
704 /*
705 /* Block I/O command. Transmit data in blocks of size PAR_BLOCK_SIZE.
706 /* Return received bytes in the same buffer.
707 /*
708 /******************************************************************************/
iBDataBlock(uchar * data,int count)709 uchar iBDataBlock(uchar *data, int count)
710 {
711 int i;
712
713 /* Byte-bang the thing */
714 for(i = 0; i < count; i++)
715 data[i] = iBDataByte(data[i]);
716
717 return TRUE;
718 }
719 ////////////////////////////////////////////////////////////////////////
SetAdapterType(uchar Type,char * type)720 uchar SetAdapterType(uchar Type, char *type)
721 {
722 if(Type != DS1410)
723 return FALSE;
724
725 gType = DS1410;
726 return TRUE;
727 }
728 ////////////////////////////////////////////////////////////////////////
SetAdapterSpeed(ulong speed)729 uchar SetAdapterSpeed(ulong speed)
730 {
731 return TRUE;
732 }
733 ////////////////////////////////////////////////////////////////////////
iBStream(uchar * arr,int length)734 uchar iBStream(uchar *arr,int length)
735 {
736 int i;
737 int AccessGood = FALSE;
738 uchar accessarray[9];
739
740 if (DOWReset())
741 {
742 AccessGood = TRUE;
743
744 /* Set up block for transmit */
745 accessarray[0] = 0x55;
746 for (i = 1;i < 9;i++)
747 accessarray[i] = RomDta[i-1];
748 /* Transmit block. */
749 iBDataBlock(accessarray,9);
750 iBDataBlock(arr,length);
751 }
752
753 return (uchar)AccessGood;
754 }
755 ////////////////////////////////////////////////////////////////////////
iBFastAccess(void)756 uchar iBFastAccess(void)
757 {
758 return iBAccess();
759 }
760 ////////////////////////////////////////////////////////////////////////
iBStrongAccess(void)761 uchar iBStrongAccess(void)
762 {
763 uchar i, j;
764 uchar mask = 0x80;
765 //uchar byte;
766 //uchar bit;
767 //uchar bytesend[24];
768
769 /* Assume failure */
770 AccessGood = FALSE;
771
772 /* Send reset pulse */
773 if (DOWReset())
774 {
775
776 /* ROM search command byte */
777 DOWByte(0xF0);
778
779
780 /* Byte loop */
781 for (i = 0; i < 8; i++)
782 {
783 /* Bit loop */
784 for (j = 0; j < 8; j++)
785 {
786 /* Send two read time slots */
787 if (((DOWBit(TRUE) << 1) | DOWBit(TRUE)) == 3)
788 return FALSE;
789
790 /* Send write time slot */
791 DOWBit((uchar) ((RomDta[i] >> j) & 1));
792 }
793 }
794
795 /* Success if we made it through all bits */
796 AccessGood = TRUE;
797 }
798
799 return AccessGood;
800 }
801 ////////////////////////////////////////////////////////////////////////
SetAdapter5VTime(uchar time)802 uchar SetAdapter5VTime(uchar time)
803 {
804 return TRUE;
805 }
806 ////////////////////////////////////////////////////////////////////////
Adapter5VPrime(void)807 uchar Adapter5VPrime(void)
808 {
809 return TRUE;
810 }
811 ////////////////////////////////////////////////////////////////////////
Adapter5VCancel(void)812 uchar Adapter5VCancel(void)
813 {
814 return TRUE;
815 }
816 ////////////////////////////////////////////////////////////////////////
817 ////////////////////////////////////////////////////////////////////////
818
819