1 //---------------------------------------------------------------------------
2 // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
18 // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 // OTHER DEALINGS IN THE SOFTWARE.
21 //
22 // Except as contained in this notice, the name of Dallas Semiconductor
23 // shall not be used except as stated in the Dallas Semiconductor
24 // Branding Policy.
25 //--------------------------------------------------------------------------
26 //
27 //  mbAppReg.c - Reads and writes to memory locations for the AppReg memory bank.
28 //  version 1.00
29 //
30 
31 // Include Files
32 #include "ownet.h"
33 #include "mbappreg.h"
34 
35 // External functions
36 extern SMALLINT owBlock(int,int,uchar *,int);
37 extern void     setcrc8(int,uchar);
38 extern uchar    docrc8(int,uchar);
39 extern SMALLINT owReadByte(int);
40 extern SMALLINT owWriteByte(int,int);
41 extern void     msDelay(int);
42 extern void     owSerialNum(int,uchar *,int);
43 extern SMALLINT owAccess(int);
44 extern void     setcrc16(int,ushort);
45 extern ushort   docrc16(int,ushort);
46 
47 
48 // Local functions
49 SMALLINT readStatus(int portnum, uchar *extra);
50 // OTP Local functions
51 SMALLINT lockPageAppReg();
52 SMALLINT isPageLockedAppReg();
53 SMALLINT redirectPageAppReg();
54 SMALLINT isPageRedirectedAppReg();
55 SMALLINT getRedirectPageAppReg();
56 SMALLINT lockRedirectPageAppReg();
57 
58 // General command defines
59 #define READ_MEMORY_COMMAND  0xC3
60 #define WRITE_MEMORY_COMMAND 0x99
61 #define COPY_LOCK_COMMAND    0x5A
62 #define READ_STATUS_COMMAND  0x66
63 #define VALIDATION_KEY       0xA5
64 #define LOCKED_FLAG          0xFC
65 // Local defines
66 #define SIZE                 8
67 #define PAGE_LENGTH          8
68 
69 // Global variables
70 char     *bankDescriptionAR     = "Application register, non-volatile when locked.";
71 SMALLINT  writeVerificationAR    = TRUE;
72 SMALLINT  generalPurposeMemoryAR = TRUE;
73 SMALLINT  readWriteAR            = TRUE;
74 SMALLINT  writeOnceAR            = FALSE;
75 SMALLINT  readOnlyAR             = FALSE;
76 SMALLINT  nonVolatileAR          = FALSE;
77 SMALLINT  needsProgramPulseAR    = FALSE;
78 SMALLINT  needsPowerDeliveryAR   = TRUE;
79 SMALLINT  hasExtraInfoAR         = TRUE;
80 SMALLINT  extraInfoLengthAR      = 1;
81 char     *extraInfoDescAR       = "Page Locked Flag";
82 SMALLINT  pageAutoCRCAR          = FALSE;
83 SMALLINT  canRedirectPageAR      = FALSE;
84 SMALLINT  canLockPageAR          = TRUE;
85 SMALLINT  canLockRedirecPageAR   = FALSE;
86 
87 
88 /**
89  * Read  memory in the current bank with no CRC checking (device or
90  * data). The resulting data from this API may or may not be what is on
91  * the 1-Wire device.  It is recommends that the data contain some kind
92  * of checking (CRC) like in the readPagePackeAppRegt() method or have
93  * the 1-Wire device provide the CRC as in readPageCRCAppReg().  readPageCRCAppReg()
94  * however is not supported on all memory types, see 'hasPageAutoCRCAppReg()'.
95  * If neither is an option then this method could be called more
96  * then once to at least verify that the same thing is read consistantly.
97  *
98  * bank     to tell what memory bank of the ibutton to use.
99  * portnum  the port number of the port being used for the
100  *          1-Wire Network.
101  * SNum     the serial number for the part that the read is
102  *          to be done on.
103  * str_add  starting physical address
104  * rd_cont  if 'true' then device read is continued without
105  *          re-selecting.  This can only be used if the new
106  *          read() continious where the last one led off
107  *          and it is inside a 'beginExclusive/endExclusive'
108  *          block.
109  * buff     byte array to place read data into
110  * len      length in bytes to read
111  *
112  * @return 'true' if the read was complete
113  */
readAppReg(SMALLINT bank,int portnum,uchar * SNum,int str_add,SMALLINT rd_cont,uchar * buff,int len)114 SMALLINT readAppReg(SMALLINT bank, int portnum, uchar *SNum, int str_add,
115                     SMALLINT rd_cont, uchar *buff, int len)
116 {
117    uchar raw_buf[2];
118    int i;
119 
120    // check if read exceeds memory
121    if((str_add + len) > PAGE_LENGTH)
122    {
123       OWERROR(OWERROR_READ_OUT_OF_RANGE);
124       return FALSE;
125    }
126 
127    owSerialNum(portnum,SNum,FALSE);
128 
129    // select the device
130    if (!owAccess(portnum))
131    {
132       OWERROR(OWERROR_DEVICE_SELECT_FAIL);
133       return FALSE;
134    }
135 
136    // start the read
137    raw_buf[0] = READ_MEMORY_COMMAND;
138    raw_buf[1] = str_add & 0xFF;
139 
140    if(!owBlock(portnum,FALSE,raw_buf,2))
141    {
142       OWERROR(OWERROR_BLOCK_FAILED);
143       return FALSE;
144    }
145 
146    for(i=0;i<len;i++)
147       buff[i] = 0xFF;
148 
149    if(!owBlock(portnum,FALSE,buff,len))
150    {
151       OWERROR(OWERROR_BLOCK_FAILED);
152       return FALSE;
153    }
154 
155    return TRUE;
156 }
157 
158 /**
159  * Write  memory in the current bank.  It is recommended that
160  * when writing  data that some structure in the data is created
161  * to provide error free reading back with readAppReg().  Or the
162  * method 'writePagePacketAppReg()' could be used which automatically
163  * wraps the data in a length and CRC.
164  *
165  * When using on Write-Once devices care must be taken to write into
166  * into empty space.  If writeAppReg() is used to write over an unlocked
167  * page on a Write-Once device it will fail.
168  *
169  * bank     to tell what memory bank of the ibutton to use.
170  * portnum  the port number of the port being used for the
171  *          1-Wire Network.
172  * SNum     the serial number for the part that the write is
173  *          to be done on.
174  * str_add  starting address
175  * buff     byte array containing data to write
176  * len      length in bytes to write
177  *
178  * @return 'true' if the write was complete.
179  */
writeAppReg(SMALLINT bank,int portnum,uchar * SNum,int str_add,uchar * buff,int len)180 SMALLINT writeAppReg(SMALLINT bank, int portnum, uchar *SNum,
181                      int str_add, uchar *buff, int len)
182 {
183    uchar raw_buf[64];
184    int i;
185 
186    // return if nothing to do
187    if (len == 0)
188       return TRUE;
189 
190    // check if power delivery is available
191 /*   if(!owDeliverPower())
192    {
193       OWERROR(OWERROR_NO_POWER_DELIVERY);
194       return FALSE;
195    }*/
196 
197    // check if write exceeds memory
198    if ((str_add + len) > PAGE_LENGTH)
199    {
200       OWERROR(OWERROR_WRITE_OUT_OF_RANGE);
201       return FALSE;
202    }
203 
204    owSerialNum(portnum,SNum,FALSE);
205 
206    // select the device
207    if (!owAccess(portnum))
208    {
209       OWERROR(OWERROR_DEVICE_SELECT_FAIL);
210       return FALSE;
211    }
212 
213    // start the write
214    raw_buf[0] = WRITE_MEMORY_COMMAND;
215    raw_buf[1] = str_add & 0xFF;
216 
217    for(i=0;i<len;i++)
218       raw_buf[i+2] = buff[i];
219 
220    if(!owBlock(portnum,FALSE,raw_buf,len+2))
221    {
222       OWERROR(OWERROR_BLOCK_FAILED);
223       return FALSE;
224    }
225 
226    // check for write verification
227    if(writeVerificationAR)
228    {
229       // read back
230       readAppReg(bank,portnum,SNum,str_add,TRUE,raw_buf,len);
231 
232       // compare
233       for(i=0;i<len;i++)
234       {
235          if(raw_buf[i] != buff[i])
236          {
237             OWERROR(OWERROR_READ_BACK_INCORRECT);
238             return FALSE;
239          }
240       }
241    }
242 
243    return TRUE;
244 }
245 
246 /**
247  * Read  page in the current bank with no
248  * CRC checking (device or data). The resulting data from this API
249  * may or may not be what is on the 1-Wire device.  It is recommends
250  * that the data contain some kind of checking (CRC) like in the
251  * readPagePacketAppReg() method or have the 1-Wire device provide the
252  * CRC as in readPageCRCAppReg().  readPageCRCAppReg() however is not
253  * supported on all memory types, see 'hasPageAutoCRCAppReg()'.
254  * If neither is an option then this method could be called more
255  * then once to at least verify that the same thing is read consistantly.
256  *
257  * bank     to tell what memory bank of the ibutton to use.
258  * portnum  the port number of the port being used for the
259  *          1-Wire Network.
260  * SNum     the serial number for the part.
261  * page     the page to read
262  * rd_cont  if 'true' then device read is continued without
263  *          re-selecting.  This can only be used if the new
264  *          read() continious where the last one led off
265  *          and it is inside a 'beginExclusive/endExclusive'
266  *          block.
267  * buff     byte array containing data that was read.
268  * len      length in bytes to write
269  *
270  * @return - returns '0' if the read page wasn't completed.
271  *                   '1' if the operation is complete.
272  */
readPageAppReg(SMALLINT bank,int portnum,uchar * SNum,int page,SMALLINT rd_cont,uchar * buff)273 SMALLINT readPageAppReg(SMALLINT bank, int portnum, uchar *SNum, int page,
274                         SMALLINT rd_cont, uchar *buff)
275 {
276    // check if for valid page
277    if(page != 0)
278    {
279       OWERROR(OWERROR_INVALID_PAGE_NUMBER);
280       return FALSE;
281    }
282 
283    // do the read
284    if(!readAppReg(bank,portnum,SNum,page*PAGE_LENGTH,
285        TRUE,buff,PAGE_LENGTH))
286       return FALSE;
287 
288    return TRUE;
289 }
290 
291 /**
292  * Read  page with extra information in the current bank with no
293  * CRC checking (device or data). The resulting data from this API
294  * may or may not be what is on the 1-Wire device.  It is recommends
295  * that the data contain some kind of checking (CRC) like in the
296  * readPagePacketAppReg() method or have the 1-Wire device provide the
297  * CRC as in readPageCRCAppReg().  readPageCRCAppReg() however is not
298  * supported on all memory types, see 'hasPageAutoCRCAppReg()'.
299  * If neither is an option then this method could be called more
300  * then once to at least verify that the same thing is read consistantly.
301  * See the method 'hasExtraInfoAppReg()' for a description of the optional
302  * extra information some devices have.
303  *
304  * bank     to tell what memory bank of the ibutton to use.
305  * portnum  the port number of the port being used for the
306  *          1-Wire Network.
307  * SNum     the serial number for the part.
308  * page     the page to read
309  * rd_cont  if 'true' then device read is continued without
310  *          re-selecting.  This can only be used if the new
311  *          read() continious where the last one led off
312  *          and it is inside a 'beginExclusive/endExclusive'
313  *          block.
314  * buff     byte array containing data that was read
315  * len      length in bytes to write
316  * extra    the extra information
317  *
318  * @return - returns '0' if the read page wasn't completed with extra info.
319  *                   '1' if the operation is complete.
320  */
readPageExtraAppReg(SMALLINT bank,int portnum,uchar * SNum,int page,SMALLINT rd_cont,uchar * buff,uchar * extra)321 SMALLINT readPageExtraAppReg(SMALLINT bank, int portnum, uchar *SNum, int page,
322                              SMALLINT rd_cont, uchar *buff, uchar *extra)
323 {
324    if(page != 0)
325    {
326       OWERROR(OWERROR_INVALID_PAGE_NUMBER);
327       return FALSE;
328    }
329 
330    // read the page data
331    if(!readAppReg(bank,portnum,SNum,page*PAGE_LENGTH,
332        TRUE,buff,PAGE_LENGTH))
333       return FALSE;
334 
335    // read the extra information (status)
336    if(!readStatus(portnum,extra))
337    {
338       OWERROR(OWERROR_READ_STATUS_NOT_COMPLETE);
339       return FALSE;
340    }
341 
342    return TRUE;
343 }
344 
345 /**
346  * Read  page with extra information in the current bank with no
347  * CRC checking (device or data). The resulting data from this API
348  * may or may not be what is on the 1-Wire device.  It is recommends
349  * that the data contain some kind of checking (CRC) like in the
350  * readPagePacket() method or have the 1-Wire device provide the
351  * CRC as in readPageCRC().  readPageCRC() however is not
352  * supported on all memory types, see 'hasPageAutoCRC()'.
353  * If neither is an option then this method could be called more
354  * then once to at least verify that the same thing is read consistantly.
355  * See the method 'haveExtraInfo()' for a description of the optional
356  * extra information some devices have.
357  *
358  * bank     to tell what memory bank of the ibutton to use.
359  * portnum  the port number of the port being used for the
360  *          1-Wire Network.
361  * SNum     the serial number for the part.
362  * page     the page to read
363  * buff     byte array containing data that was read.
364  * extra    the extra information
365  *
366  * @return - returns '0' if the read page wasn't completed with extra info.
367  *                   '1' if the operation is complete.
368  */
readPageExtraCRCAppReg(SMALLINT bank,int portnum,uchar * SNum,int page,uchar * read_buff,uchar * extra)369 SMALLINT readPageExtraCRCAppReg(SMALLINT bank, int portnum, uchar *SNum, int page,
370                                 uchar *read_buff, uchar *extra)
371 {
372    // read the page data
373    if(!readAppReg(bank,portnum,SNum,page*PAGE_LENGTH,
374                   TRUE,read_buff,PAGE_LENGTH))
375       return FALSE;
376 
377    // read the extra information (status)
378    if(!readStatus(portnum,extra))
379    {
380       OWERROR(OWERROR_READ_STATUS_NOT_COMPLETE);
381       return FALSE;
382    }
383 
384    return TRUE;
385 }
386 
387 /**
388  * Read a complete memory page with CRC verification provided by the
389  * device.  Not supported by all devices.  See the method
390  * 'hasPageAutoCRCAppReg()'.
391  *
392  * bank     to tell what memory bank of the ibutton to use.
393  * portnum  the port number of the port being used for the
394  *          1-Wire Network.
395  * SNum     the serial number for the part.
396  * page     the page to read
397  * buff     byte array containing data that was read
398  *
399  * @return - returns '0' if the read page wasn't completed.
400  *                   '1' if the operation is complete.
401  */
readPageCRCAppReg(SMALLINT bank,int portnum,uchar * SNum,int str_add,uchar * buff)402 SMALLINT readPageCRCAppReg(SMALLINT bank, int portnum, uchar *SNum,
403                            int str_add, uchar *buff)
404 {
405    OWERROR(OWERROR_CRC_NOT_SUPPORTED);
406    return FALSE;
407 }
408 
409 /**
410  * Read a Universal Data Packet.
411  *
412  * The Universal Data Packet always starts on page boundaries but
413  * can end anywhere in the page.  The structure specifies the length of
414  * data bytes not including the length byte and the CRC16 bytes.
415  * There is one length byte. The CRC16 is first initialized to
416  * the page number.  This provides a check to verify the page that
417  * was intended is being read.  The CRC16 is then calculated over
418  * the length and data bytes.  The CRC16 is then inverted and stored
419  * low byte first followed by the high byte.  This is structure is
420  * used by this method to verify the data but is not returned, only
421  * the data payload is returned.
422  *
423  * bank     to tell what memory bank of the ibutton to use.
424  * portnum  the port number of the port being used for the
425  *          1-Wire Network.
426  * SNum     the serial number for the part.
427  * page     the page to read
428  * rd_cont  if 'true' then device read is continued without
429  *          re-selecting.  This can only be used if the new
430  *          read() continious where the last one led off
431  *          and it is inside a 'beginExclusive/endExclusive'
432  *          block.
433  * buff     byte array containing data that was read.
434  * len      length of the packet
435  *
436  * @return - returns '0' if the read page packet wasn't completed
437  *                   '1' if the operation is complete.
438  */
readPagePacketAppReg(SMALLINT bank,int portnum,uchar * SNum,int page,SMALLINT rd_cont,uchar * buff,int * len)439 SMALLINT readPagePacketAppReg(SMALLINT bank, int portnum, uchar *SNum, int page,
440                               SMALLINT rd_cont, uchar *buff, int *len)
441 {
442    uchar raw_buf[PAGE_LENGTH];
443    ushort lastcrc16;
444    int i;
445 
446    // read the entire page data
447    readAppReg(bank,portnum,SNum,page,rd_cont,raw_buf,PAGE_LENGTH);
448 
449    // check if length is realistic
450    if((raw_buf[0] > (PAGE_LENGTH - 2)) || (raw_buf[0] <= 0))
451    {
452       OWERROR(OWERROR_INVALID_PACKET_LENGTH);
453       return FALSE;
454    }
455 
456    // verify the CRC is correct
457    setcrc16(portnum,(ushort)((getStartingAddressAppReg(bank,SNum)/PAGE_LENGTH) + page));
458    for(i=0;i<(raw_buf[0]+3);i++)
459       lastcrc16 = docrc16(portnum,raw_buf[i]);
460 
461    if(lastcrc16 == 0xB001)
462    {
463       *len = (int) raw_buf[0];
464 
465       // extract the data out of the packet
466       for(i=1;i<raw_buf[0]+1;i++)
467          buff[i-1] = raw_buf[i];
468    }
469    else
470    {
471       OWERROR(OWERROR_CRC_FAILED);
472       return FALSE;
473    }
474 
475    return TRUE;
476 }
477 
478 /**
479  * Read a Universal Data Packet and extra information.  See the
480  * method 'readPagePacketAppReg()' for a description of the packet structure.
481  * See the method 'hasExtraInfoAppReg()' for a description of the optional
482  * extra information some devices have.
483  *
484  * bank     to tell what memory bank of the ibutton to use.
485  * portnum  the port number of the port being used for the
486  *          1-Wire Network.
487  * SNum     the serial number for the part.
488  * page     the page to read
489  * rd_cont  if 'true' then device read is continued without
490  *          re-selecting.  This can only be used if the new
491  *          read() continious where the last one led off
492  *          and it is inside a 'beginExclusive/endExclusive'
493  *          block.
494  * buff     byte array containing data that was read.
495  * len      length of the packet
496  * extra    extra information
497  *
498  * @return - returns '0' if the read page packet wasn't completed
499  *                   '1' if the operation is complete.
500  */
readPagePacketExtraAppReg(SMALLINT bank,int portnum,uchar * SNum,int page,SMALLINT rd_cont,uchar * buff,int * len,uchar * extra)501 SMALLINT readPagePacketExtraAppReg(SMALLINT bank, int portnum, uchar *SNum,
502                                    int page, SMALLINT rd_cont, uchar *buff,
503                                    int *len, uchar *extra)
504 {
505    uchar raw_buf[32];
506    int i;
507    ushort lastcrc16;
508 
509    // check if current bank is not scratchpad bank, or not page 0
510    if(!hasExtraInfoAppReg(bank,SNum))
511    {
512       OWERROR(OWERROR_EXTRA_INFO_NOT_SUPPORTED);
513       return FALSE;
514    }
515 
516    // read the entire page data
517    readAppReg(bank,portnum,SNum,page*PAGE_LENGTH,
518                TRUE,raw_buf,PAGE_LENGTH);
519 
520    // check if length is realistic
521    if((raw_buf[0] > (PAGE_LENGTH - 2)) || (raw_buf[0] <= 0))
522    {
523       OWERROR(OWERROR_INVALID_PACKET_LENGTH);
524       return FALSE;
525    }
526 
527    // verify the CRC is correct
528    setcrc16(portnum,(ushort) ((getStartingAddressAppReg(bank,SNum)/PAGE_LENGTH) + page));
529    for(i=0;i<(raw_buf[0]+3);i++)
530       lastcrc16 = docrc16(portnum,raw_buf[i]);
531 
532    if(lastcrc16 == 0xB001)
533    {
534       *len = (int) raw_buf[0];
535 
536       if(!readStatus(portnum,extra))
537       {
538          OWERROR(OWERROR_READ_STATUS_NOT_COMPLETE);
539          return FALSE;
540       }
541 
542       // extract the data out of the packet
543       for(i=1;i<raw_buf[0]+1;i++)
544          buff[i-1] = raw_buf[i];
545    }
546    else
547    {
548       OWERROR(OWERROR_CRC_FAILED);
549       return FALSE;
550    }
551 
552    return TRUE;
553 }
554 
555 /**
556  * Write a Universal Data Packet.  See the method 'readPagePacketAppReg()'
557  * for a description of the packet structure.
558  *
559  * bank     to tell what memory bank of the ibutton to use.
560  * portnum  the port number of the port being used for the
561  *          1-Wire Network.
562  * SNum     the serial number for the part.
563  * page     the page the packet is being written to.
564  * rd_cont  if 'true' then device read is continued without
565  *          re-selecting.  This can only be used if the new
566  *          read() continious where the last one led off
567  *          and it is inside a 'beginExclusive/endExclusive'
568  *          block.
569  * buff     byte array containing data that to write.
570  * len      length of the packet
571  *
572  * @return - returns '0' if the write page packet wasn't completed
573  *                   '1' if the operation is complete.
574  */
writePagePacketAppReg(SMALLINT bank,int portnum,uchar * SNum,int page,uchar * buff,int len)575 SMALLINT writePagePacketAppReg(SMALLINT bank, int portnum, uchar *SNum,
576                                int page, uchar *buff, int len)
577 {
578    uchar raw_buf[PAGE_LENGTH];
579    ushort crc;
580    int i;
581 
582    // make sure length does not exceed max
583    if((len > (PAGE_LENGTH - 2)) || (len <= 0))
584    {
585       OWERROR(OWERROR_PACKET_LENGTH_EXCEEDS_PAGE);
586       return FALSE;
587    }
588 
589    raw_buf[0] = (uchar) len + 3;
590 
591    for(i=0;i<len;i++)
592       raw_buf[i+1] = buff[i];
593 
594    setcrc16(portnum,(ushort) ((getStartingAddressAppReg(bank,SNum)/PAGE_LENGTH) + page));
595    for(i=0;i<len+1;i++)
596       crc = docrc16(portnum,raw_buf[i]);
597 
598    raw_buf[len + 1] = ~crc & 0xFF;
599    raw_buf[len + 2] = ((~crc & 0xFFFF) >> 8) & 0xFF;
600 
601    // write the packet, return result
602    if(!writeAppReg(bank,portnum,SNum,page*PAGE_LENGTH,raw_buf,len + 3))
603       return FALSE;
604 
605    return TRUE;
606 }
607 
608 /**
609  * Query to get the number of pages in current memory bank.
610  *
611  * bank     to tell what memory bank of the ibutton to use.
612  * SNum     the serial number for the part.
613  *
614  * @return  number of pages in current memory bank
615  */
getNumberPagesAppReg(SMALLINT bank,uchar * SNum)616 SMALLINT getNumberPagesAppReg(SMALLINT bank, uchar *SNum)
617 {
618    return 1;
619 }
620 
621 /**
622  * Query to get the memory bank size in bytes.
623  *
624  * bank     to tell what memory bank of the ibutton to use.
625  * SNum     the serial number for the part.
626  *
627  * @return  memory bank size in bytes.
628  */
getSizeAppReg(SMALLINT bank,uchar * SNum)629 int getSizeAppReg(SMALLINT bank, uchar *SNum)
630 {
631    return SIZE;
632 }
633 
634 /**
635  * Query to get the starting physical address of this bank.  Physical
636  * banks are sometimes sub-divided into logical banks due to changes
637  * in attributes.
638  *
639  * bank     to tell what memory bank of the ibutton to use.
640  * SNum     the serial number for the part.
641  *
642  * @return  physical starting address of this logical bank.
643  */
getStartingAddressAppReg(SMALLINT bank,uchar * SNum)644 int getStartingAddressAppReg(SMALLINT bank, uchar *SNum)
645 {
646    return 0;
647 }
648 
649 /**
650  * Query to get  page length in bytes in current memory bank.
651  *
652  * bank     to tell what memory bank of the ibutton to use.
653  * SNum     the serial number for the part.
654  *
655  * @return   page length in bytes in current memory bank
656  */
getPageLengthAppReg(SMALLINT bank,uchar * SNum)657 SMALLINT getPageLengthAppReg(SMALLINT bank, uchar *SNum)
658 {
659    return PAGE_LENGTH;
660 }
661 
662 /**
663  * Query to see get a string description of the current memory bank.
664  *
665  * bank     to tell what memory bank of the ibutton to use.
666  * SNum     the serial number for the part.
667  *
668  * @return  String containing the memory bank description
669  */
getBankDescriptionAppReg(SMALLINT bank,uchar * SNum)670 char *getBankDescriptionAppReg(SMALLINT bank, uchar *SNum)
671 {
672    return bankDescriptionAR;
673 }
674 
675 /**
676  * Query to see if the current memory bank is general purpose
677  * user memory.  If it is NOT then it is Memory-Mapped and writing
678  * values to this memory will affect the behavior of the 1-Wire
679  * device.
680  *
681  * bank     to tell what memory bank of the ibutton to use.
682  * SNum     the serial number for the part.
683  *
684  * @return  'true' if current memory bank is general purpose
685  */
isGeneralPurposeMemoryAppReg(SMALLINT bank,uchar * SNum)686 SMALLINT isGeneralPurposeMemoryAppReg(SMALLINT bank, uchar *SNum)
687 {
688    return generalPurposeMemoryAR;
689 }
690 
691 /**
692  * Query to see if current memory bank is read/write.
693  *
694  * bank     to tell what memory bank of the ibutton to use.
695  * SNum     the serial number for the part.
696  *
697  * @return  'true' if current memory bank is read/write
698  */
isReadWriteAppReg(SMALLINT bank,int portnum,uchar * SNum)699 SMALLINT isReadWriteAppReg(SMALLINT bank, int portnum, uchar *SNum)
700 {
701    return readWriteAR;
702 }
703 
704 /**
705  * Query to see if current memory bank is read only.
706  *
707  * @return  'true' if current memory bank can only be read
708  */
isReadOnlyAppReg(SMALLINT bank,int portnum,uchar * SNum)709 SMALLINT isReadOnlyAppReg(SMALLINT bank, int portnum, uchar *SNum)
710 {
711    return readOnlyAR;
712 }
713 
714 /**
715  * Query to see if current memory bank is write write once such
716  * as with EPROM technology.
717  *
718  * bank     to tell what memory bank of the ibutton to use.
719  * SNum     the serial number for the part.
720  *
721  * @return  'true' if current memory bank can only be written once
722  */
isWriteOnceAppReg(SMALLINT bank,int portnum,uchar * SNum)723 SMALLINT isWriteOnceAppReg(SMALLINT bank, int portnum, uchar *SNum)
724 {
725    return writeOnceAR;
726 }
727 
728 /**
729  * Query to see if current memory bank non-volatile.  Memory is
730  * non-volatile if it retains its contents even when removed from
731  * the 1-Wire network.
732  *
733  * bank     to tell what memory bank of the ibutton to use.
734  * SNum     the serial number for the part.
735  *
736  * @return  'true' if current memory bank non volatile.
737  */
isNonVolatileAppReg(SMALLINT bank,uchar * SNum)738 SMALLINT isNonVolatileAppReg(SMALLINT bank, uchar *SNum)
739 {
740    return nonVolatileAR;
741 }
742 
743 /**
744  * Query to see if current memory bank pages need the adapter to
745  * have a 'ProgramPulse' in order to write to the memory.
746  *
747  * bank     to tell what memory bank of the ibutton to use.
748  * SNum     the serial number for the part.
749  *
750  * @return  'true' if writing to the current memory bank pages
751  *                 requires a 'ProgramPulse'.
752  */
needsProgramPulseAppReg(SMALLINT bank,uchar * SNum)753 SMALLINT needsProgramPulseAppReg(SMALLINT bank, uchar *SNum)
754 {
755    return needsProgramPulseAR;
756 }
757 
758 /**
759  * Query to see if current memory bank pages need the adapter to
760  * have a 'PowerDelivery' feature in order to write to the memory.
761  *
762  * bank     to tell what memory bank of the ibutton to use.
763  * SNum     the serial number for the part.
764  *
765  * @return  'true' if writing to the current memory bank pages
766  *                 requires 'PowerDelivery'.
767  */
needsPowerDeliveryAppReg(SMALLINT bank,uchar * SNum)768 SMALLINT needsPowerDeliveryAppReg(SMALLINT bank, uchar *SNum)
769 {
770    return needsPowerDeliveryAR;
771 }
772 
773 /**
774  * Checks to see if this memory bank's pages deliver extra
775  * information outside of the normal data space,  when read.  Examples
776  * of this may be a redirection byte, counter, tamper protection
777  * bytes, or SHA-1 result.  If this method returns true then the
778  * methods with an 'extraInfo' parameter can be used.
779  *
780  * bank     to tell what memory bank of the ibutton to use.
781  * SNum     the serial number for the part.
782  *
783  * @return  true if reading the this memory bank's
784  *               pages provides extra information
785  */
hasExtraInfoAppReg(SMALLINT bank,uchar * SNum)786 SMALLINT hasExtraInfoAppReg(SMALLINT bank, uchar *SNum)
787 {
788    return hasExtraInfoAR;
789 }
790 
791 /**
792  * Query to get the length in bytes of extra information that
793  * is read when read a page in the current memory bank.  See
794  * 'hasExtraInfoAppReg()'.
795  *
796  * bank     to tell what memory bank of the ibutton to use.
797  * SNum     the serial number for the part.
798  *
799  * @return  number of bytes in Extra Information read when reading
800  *          pages in the current memory bank.
801  */
getExtraInfoLengthAppReg(SMALLINT bank,uchar * SNum)802 SMALLINT getExtraInfoLengthAppReg(SMALLINT bank, uchar *SNum)
803 {
804    return extraInfoLengthAR;
805 }
806 
807 /**
808  * Query to get a string description of what is contained in
809  * the Extra Informationed return when reading pages in the current
810  * memory bank.  See 'hasExtraInfoAppReg()'.
811  *
812  * bank     to tell what memory bank of the ibutton to use.
813  * SNum     the serial number for the part.
814  *
815  * @return string describing extra information.
816  */
getExtraInfoDescAppReg(SMALLINT bank,uchar * SNum)817 char *getExtraInfoDescAppReg(SMALLINT bank, uchar *SNum)
818 {
819    return extraInfoDescAR;
820 }
821 
822 /**
823  * Query to see if current memory bank pages can be read with
824  * the contents being verified by a device generated CRC.
825  * This is used to see if the 'ReadPageCRCAppReg()' can be used.
826  *
827  * bank     to tell what memory bank of the ibutton to use.
828  * SNum     the serial number for the part.
829  *
830  * @return  'true' if current memory bank can be read with self
831  *          generated CRC.
832  */
hasPageAutoCRCAppReg(SMALLINT bank,uchar * SNum)833 SMALLINT hasPageAutoCRCAppReg(SMALLINT bank, uchar *SNum)
834 {
835    return pageAutoCRCAR;
836 }
837 
838 /**
839  * Query to get Maximum data page length in bytes for a packet
840  * read or written in the current memory bank.  See the 'ReadPagePacket()'
841  * and 'WritePagePacket()' methods.  This method is only usefull
842  * if the current memory bank is general purpose memory.
843  *
844  * @return  max packet page length in bytes in current memory bank
845  */
getMaxPacketDataLengthAppReg(SMALLINT bank,uchar * SNum)846 SMALLINT getMaxPacketDataLengthAppReg(SMALLINT bank, uchar *SNum)
847 {
848    return PAGE_LENGTH - 3;
849 }
850 
851 //--------
852 //-------- OTPMemoryBank query methods
853 //--------
854 
855 /**
856  * Query to see if current memory bank pages can be redirected
857  * to another pages.  This is mostly used in Write-Once memory
858  * to provide a means to update.
859  *
860  * bank     to tell what memory bank of the ibutton to use.
861  * SNum     the serial number for the part.
862  *
863  * @return  'true' if current memory bank pages can be redirected
864  *          to a new page.
865  */
canRedirectPageAppReg(SMALLINT bank,uchar * SNum)866 SMALLINT canRedirectPageAppReg(SMALLINT bank, uchar *SNum)
867 {
868    return FALSE;
869 }
870 
871 /**
872  * Query to see if current memory bank pages can be locked.  A
873  * locked page would prevent any changes to the memory.
874  *
875  * bank     to tell what memory bank of the ibutton to use.
876  * SNum     the serial number for the part.
877  *
878  * @return  'true' if current memory bank pages can be redirected
879  *          to a new page.
880  */
canLockPageAppReg(SMALLINT bank,uchar * SNum)881 SMALLINT canLockPageAppReg(SMALLINT bank, uchar *SNum)
882 {
883    return TRUE;
884 }
885 
886 /**
887  * Query to see if current memory bank pages can be locked from
888  * being redirected.  This would prevent a Write-Once memory from
889  * being updated.
890  *
891  * bank     to tell what memory bank of the ibutton to use.
892  * SNum     the serial number for the part.
893  *
894  * @return  'true' if current memory bank pages can be locked from
895  *          being redirected to a new page.
896  */
canLockRedirectPageAppReg(SMALLINT bank,uchar * SNum)897 SMALLINT canLockRedirectPageAppReg(SMALLINT bank, uchar *SNum)
898 {
899    return FALSE;
900 }
901 
902 //--------
903 //-------- OTPMemoryBank I/O methods
904 //--------
905 
906 /**
907  * Lock the specifed page in the current memory bank.  Not supported
908  * by all devices.  See the method 'canLockPage()'.
909  *
910  * portnum  the port number of the port being used for the
911  *          1-Wire Network.
912  * SNum     the serial number for the part.
913  * page     the page to be used.
914  *
915  * @return 'true' if page is locked.
916  */
lockPageAppReg(SMALLINT portnum,int page,uchar * SNum)917 SMALLINT lockPageAppReg(SMALLINT portnum, int page, uchar *SNum)
918 {
919 
920    // select the device
921    owSerialNum(portnum,SNum,FALSE);
922    if (!owAccess(portnum))
923    {
924       OWERROR(OWERROR_DEVICE_SELECT_FAIL);
925       return FALSE;
926    }
927 
928    // do the copy/lock sequence
929    owWriteByte(portnum,COPY_LOCK_COMMAND);
930    owWriteByte(portnum,VALIDATION_KEY);
931 
932    // read back to verify
933    if(!isPageLockedAppReg(portnum,page,SNum))
934    {
935       OWERROR(OWERROR_READ_BACK_NOT_VALID);
936       return FALSE;
937    }
938 
939    return TRUE;
940 }
941 
942 /**
943  * Query to see if the specified page is locked.
944  * See the method 'canLockPage()'.
945  *
946  * portnum  the port number of the port being used for the
947  *          1-Wire Network.
948  * SNum     the serial number for the part.
949  * page     the page to be used.
950  *
951  * @return 'true' if page is locked.
952  */
isPageLockedAppReg(int portnum,int page,uchar * SNum)953 SMALLINT isPageLockedAppReg(int portnum, int page, uchar *SNum)
954 {
955    uchar extra[2];
956 
957    // check if for valid page
958    if(page != 0)
959    {
960       OWERROR(OWERROR_INVALID_PAGE_NUMBER);
961       return FALSE;
962    }
963 
964    // read status and return result
965    if(!readStatus(portnum,&extra[0]))
966    {
967       OWERROR(OWERROR_READ_STATUS_NOT_COMPLETE);
968       return FALSE;
969    }
970 
971    if(extra[0] == LOCKED_FLAG)
972       return TRUE;
973 
974    return FALSE;
975 }
976 
977 /**
978  * Redirect the specifed page in the current memory bank to a new page.
979  * Not supported by all devices.  See the method 'canRedirectPage()'.
980  *
981  * portnum  the port number of the port being used for the
982  *          1-Wire Network.
983  * SNum     the serial number for the part.
984  * page     the page to be used.
985  *
986  * @return 'true' if page is redirected.
987  */
redirectPageAppReg(int portnum,int page,int newPage,uchar * SNum)988 SMALLINT redirectPageAppReg(int portnum, int page, int newPage, uchar *SNum)
989 {
990    OWERROR(OWERROR_PAGE_REDIRECTION_NOT_SUPPORTED);
991    return FALSE;
992 }
993 
994 /**
995  * Gets the page redirection of the specified page.
996  * Not supported by all devices.
997  *
998  * portnum  the port number of the port being used for the
999  *          1-Wire Network.
1000  * SNum     the serial number for the part.
1001  * page     the page to be used.
1002  *
1003  * @return where the redirected page is.
1004  */
getRedirectedPageAppReg(int portnum,int page,uchar * SNum)1005 SMALLINT getRedirectedPageAppReg(int portnum, int page, uchar *SNum)
1006 {
1007    return 0;
1008 }
1009 
1010 /**
1011  * Lock the redirection option for the specifed page in the current
1012  * memory bank. Not supported by all devices.  See the method
1013  * 'canLockRedirectPage()'.
1014  *
1015  * portnum  the port number of the port being used for the
1016  *          1-Wire Network.
1017  * SNum     the serial number for the part.
1018  * page     the page to be used.
1019  *
1020  * @return  'true' if redirected page is locked.
1021  */
lockRedirectPageAppReg(int portnum,int page,uchar * SNum)1022 SMALLINT lockRedirectPageAppReg(int portnum, int page, uchar *SNum)
1023 {
1024    // only needs to be implemented if supported by hardware
1025    OWERROR(OWERROR_LOCK_REDIRECTION_NOT_SUPPORTED);
1026    return FALSE;
1027 }
1028 
1029 /**
1030  * Query to see if the specified page has redirection locked.
1031  * Not supported by all devices.  See the method 'canRedirectPage()'.
1032  *
1033  * portnum  the port number of the port being used for the
1034  *          1-Wire Network.
1035  * SNum     the serial number for the part.
1036  * page     the page to be used.
1037  *
1038  * @return  return 'true' if redirection is locked for this page
1039  */
isRedirectPageLockedAppReg(int portnum,int page,uchar * SNum)1040 SMALLINT isRedirectPageLockedAppReg(int portnum, int page, uchar *SNum)
1041 {
1042    return FALSE;
1043 }
1044 
1045 //--------
1046 //-------- Bank specific methods
1047 //--------
1048 
1049 /**
1050  * Read the status register for this memory bank.
1051  *
1052  * portnum  the port number of the port being used for the
1053  *          1-Wire Network.
1054  * extra    the extra information
1055  *
1056  * @return  'true' if the status was read.
1057  *
1058  */
readStatus(int portnum,uchar * extra)1059 SMALLINT readStatus(int portnum, uchar *extra)
1060 {
1061    // select the device
1062    if(!owAccess(portnum))
1063    {
1064       OWERROR(OWERROR_DEVICE_SELECT_FAIL);
1065       return FALSE;
1066    }
1067 
1068    // do the read status sequence
1069    if(!owWriteByte(portnum,READ_STATUS_COMMAND))
1070       return FALSE;
1071 
1072    // validation key
1073    if(!owWriteByte(portnum,0x00))
1074       return FALSE;
1075 
1076    extra[0] = owReadByte(portnum);
1077 
1078    return TRUE;
1079 }