//--------------------------------------------------------------------------- // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // Except as contained in this notice, the name of Dallas Semiconductor // shall not be used except as stated in the Dallas Semiconductor // Branding Policy. //-------------------------------------------------------------------------- // // owFile.c - Contains the main file functions for the 1-Wire Public Domain // Kit // // version 1.00 // #include #include #include "owfile.h" #include "rawmem.h" // External Function Prototypes extern SMALLINT ExtendedRead_Page(int portnum, uchar *SNum, uchar *buff, PAGE_TYPE pg); extern SMALLINT owAccess(int); extern SMALLINT Read_Page(int portnum, uchar *SNum, uchar *buff, uchar flag, PAGE_TYPE *pg, int *len); extern SMALLINT Write_Page(int portnum, uchar *SNum, uchar *buff, PAGE_TYPE page, int len); extern SMALLINT ExtWrite(int portnum, uchar *SNum, uchar strt_page, uchar *file, int fllen, uchar *BM); extern SMALLINT ExtRead(int portnum, uchar *SNum, uchar *file, int start_page, int maxlen, uchar del, uchar *BM, int *fl_len); extern void owSerialNum(int,uchar *,SMALLINT); extern SMALLINT isJob(int,uchar *); extern SMALLINT isJobWritten(int,uchar *,PAGE_TYPE); extern SMALLINT setJobWritten(int,uchar *,PAGE_TYPE,SMALLINT); extern SMALLINT getOrigBM(int,uchar *,uchar *); extern SMALLINT setProgramJob(int,uchar *,uchar,int); extern SMALLINT getProgramJob(int,uchar *,uchar *,int); extern SMALLINT redirectPage(SMALLINT,int,uchar *,int,int); extern SMALLINT WriteJobByte(int, uchar *, PAGE_TYPE, short, uchar, short); extern SMALLINT TerminatePage(int, uchar *, short, uchar *); extern void owClearError(void); // function prototypes for this module to be exported SMALLINT owFirstFile(int, uchar *, FileEntry *); SMALLINT owNextFile(int, uchar *, FileEntry *); SMALLINT owOpenFile(int, uchar *, FileEntry *,short *); SMALLINT owCreateFile(int, uchar *, int *, short *, FileEntry *); SMALLINT owCloseFile(int, uchar *, short); SMALLINT owReadFile(int, uchar *, short, uchar *, int,int *); SMALLINT owRemoveDir(int, uchar *, FileEntry *); SMALLINT owWriteFile(int, uchar *, short , uchar *, int ); SMALLINT owDeleteFile(int, uchar *, FileEntry *); SMALLINT owFormat(int, uchar *); SMALLINT owAttribute(int, uchar *, short, FileEntry *); SMALLINT owReNameFile(int, uchar *, short, FileEntry *); SMALLINT owChangeDirectory(int, uchar *, DirectoryPath *); SMALLINT owCreateDir(int, uchar *, FileEntry *); DirectoryPath owGetCurrentDir(int, uchar *); SMALLINT owWriteAddFile(int,uchar *,short,short,short,uchar *,int *); SMALLINT owTerminateAddFile(int,uchar *,FileEntry *); // utility function prototypes for this module SMALLINT ReadBitMap(int, uchar *, uchar *); SMALLINT WriteBitMap(int, uchar *, uchar *); SMALLINT ReadNumEntry(int, uchar *, short , FileEntry *, PAGE_TYPE *); SMALLINT GetMaxWrite(int, uchar *, uchar *); SMALLINT FindDirectoryInfo(int, uchar *, PAGE_TYPE *, FileInfo *); SMALLINT ValidRom(int, uchar *); SMALLINT BitMapChange(int, uchar *, uchar, uchar, uchar *); SMALLINT Valid_FileName(FileEntry *); void FindEmpties(int, uchar *, uchar *, PAGE_TYPE *, PAGE_TYPE *); int maxPages(int, uchar *); void ChangeRom(int portnum, uchar *SNum); PAGE_TYPE getLastPage(int, uchar *); // Globals uchar LastFile; // 1 FileInfo Han[5]; // 60 CurrentDirectory CD; // 69 uchar Internal; // 1 // Page_WR in file layer PAGE_TYPE LastPage; // 1 uchar FPage; // 1 ushort buflen; // 2 uchar pgcnt; // 1 char mxpgs; // 1 char BadRec; // 1 uchar current[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //-------------------------------------------------------------------------- // Create a sub-directory. Note that a sub-directory is created empty // and only an empty sub-directory can be removed. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // DirName the file information that is to be created. // // Returns: 1(SUCCESS) : Operation successful // 0(FAILURE) : error // SMALLINT owCreateDir(int portnum, uchar *SNum, FileEntry *DirName) { uchar nwdir[] = { 0xAA, 0, 'R', 'O', 'O', 'T', 0, 0 }; short i; PAGE_TYPE pg; SMALLINT bytes_written = 0; DirectoryPath reset; // check for a valid session device if(!ValidRom(portnum,SNum)) return FALSE; if(!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // check to see if filename passed is valid if (!Valid_FileName(DirName)) { OWERROR(OWERROR_XBAD_FILENAME); return FALSE; } // get the starting page if(CD.ne == 0) pg = 0; else pg = CD.Entry[CD.ne-1].page; // check to see if there is any room for another sub-directory if(CD.ne == 10) { OWERROR(OWERROR_XUNABLE_TO_CREATE_DIR); return FALSE; } // fill the file handle 4 for (i = 0; i < 4; i++) Han[4].Name[i] = DirName->Name[i]; Han[4].Ext = 0x7F; Han[4].Read = FALSE; // create the new sub-directory page // search through directory to verify file not found if(FindDirectoryInfo(portnum,SNum,&pg,&Han[4])) { OWERROR(OWERROR_REPEAT_FILE); return FALSE; } // if starting page is not 0 then is not default root so change if (pg != 0) { for (i = 0; i < 4; i++) nwdir[i+2] = CD.Entry[CD.ne-1].name[i]; nwdir[6] = CD.Entry[CD.ne-1].page; } // Set the internal flag Internal = TRUE; // use the writefile command to accomplish this task if(!owWriteFile(portnum,SNum,4,nwdir,FILE_NAME_LEN)) return FALSE; // turn off the shorternal flag Internal = FALSE; // check success of write if(bytes_written < 0) return FALSE; // reset current directory reset.Ref = '0'; reset.NumEntries = 0; owChangeDirectory(portnum,SNum,&reset); return TRUE; } //-------------------------------------------------------------------------- // Remove a sub-directory. Note that a sub-directory is created empty // and only an empty sub-directory can be removed. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // DirName the file information that is to be removed. // // Returns: 1(SUCCESS) : Operation successful // 0(FAILURE) : error // SMALLINT owRemoveDir(int portnum, uchar *SNum, FileEntry *DirName) { uchar buf[64],BM[32],pgbuf[32],p,jobBM[32]; short e,i,j; PAGE_TYPE pg = CD.Entry[CD.ne-2].page; PAGE_TYPE rpg,tpg; int len = 0; uchar pgjobstat; SMALLINT bank = 1; DirectoryPath reset; // check for a valid session device if(!ValidRom(portnum,SNum)) return FALSE; if(!owAccess(portnum)) { OWERROR(OWERROR_DEVICE_SELECT_FAIL); return FALSE; } // check to see if filename passed is valid if (!Valid_FileName(DirName)) { OWERROR(OWERROR_XBAD_FILENAME); return FALSE; } // fill the file handle 4 for (i = 0; i < 4; i++) Han[4].Name[i] = DirName->Name[i]; Han[4].Ext = 0x7F; Han[4].Read = FALSE; // search through directory to verify file not found if(!FindDirectoryInfo(portnum,SNum,&pg,&Han[4])) { OWERROR(OWERROR_FILE_NOT_FOUND); return FALSE; } if(!Read_Page(portnum,SNum,&buf[0],REGMEM,&Han[4].Spage,&len)) return FALSE; // check for empty if ((len != 8) || (buf[len-1] != 0)) { OWERROR(OWERROR_DIRECTORY_NOT_EMPTY); return FALSE; } // Set the internal flag Internal = TRUE; // use the deletefile command to accomplish this task // check for special case of extension 100 if(Han[4].Ext == 100 && (!owIsWriteOnce(bank,portnum,SNum))) { OWERROR(OWERROR_WRONG_TYPE); return FALSE; } // check to see if this entry is read only if (Han[4].Attrib == 0x01 && Han[4].Ext != 0x7F) { OWERROR(OWERROR_READ_ONLY); return FALSE; } // check existing open files with same the name // automatically close the file for (i = 0; i < 4; i++) { if(Han[i].Name[0] != 0) { for (j = 0; j < 4; j++) if ((Han[i].Name[j] & 0x7F) != Han[4].Name[j]) break; if (j == 4 && ((Han[i].Ext & 0x7F) == Han[4].Ext)) { Han[i].Name[0] = 0; // release the handle break; } } } // get the bitmap so that it can be adjusted if(!ReadBitMap(portnum,SNum,&BM[0])) return FALSE; // check for addfile if (Han[4].Ext == 100) { tpg = Han[4].Spage; for (i = 0; i < 256; i++) { // read a page in the file if(!ExtendedRead_Page(portnum,SNum,&pgbuf[0],tpg)) return FALSE; // check if only in buffer // or non written buffered eprom page if(isJob(portnum,SNum)) { // see if page set to write but has not started yet pgjobstat = isJobWritten(portnum,SNum,tpg); if ((pgjobstat == PJOB_ADD) && (pgjobstat != PJOB_START)) { // clear the job if(!setJobWritten(portnum,SNum,tpg,PJOB_NONE)) return FALSE; // clear this page in the bitmap if clear in original if(!getOrigBM(portnum,SNum,&jobBM[0])) return FALSE; if(!(jobBM[tpg/8] & (0x01 << (tpg%8)))) if(!BitMapChange(portnum,SNum,(uchar)tpg,0,&BM[0])) return FALSE; } } // get continuation pointer tpg = pgbuf[29]; if (tpg == 0xFF) break; } } // regular file else { // read the file to eliminate the bits in the bitmap if(!ExtRead(portnum,SNum,&buf[0],Han[4].Spage,-1,TRUE,&BM[0],&len)) return FALSE; } // read the directory page to see what the situation is if(!Read_Page(portnum,SNum,&buf[0],REGMEM,&Han[4].Dpage,&len)) return FALSE; // check for inappropriate directory length if ((len-1) % 7) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } // get number of entries e = len / 7; // check for condition that this is last enty in a directory packet if (e == 1) { // remember the current pages pointer p = buf[len-1]; // read the previous page to change its continuation pointer if(!Read_Page(portnum,SNum,&buf[0],REGMEM,&Han[4].PDpage,&len)) return FALSE; // set the prev dir page cont ptr to current page cont ptr buf[len-1] = p; // clear this page in the bitmap if(!BitMapChange(portnum,SNum,Han[4].Dpage,0,&BM[0])) return FALSE; // set the page number to write rpg = Han[4].PDpage; } // must keep this page and just remove the entry else { // remember the current pages pointer p = buf[len-1]; // shift directory page over to remove the entry for (i = Han[4].Offset; i < (len - 7); i++) buf[i] = buf[i+7]; // reduce the lenght of the directory page by 1 entry len -= 7; // set the continuation page buf[len-1] = p; // set the page number to write rpg = Han[4].Dpage; } // write the directory page needed if(!Write_Page(portnum,SNum,&buf[0],rpg,len)) return FALSE; else { if(!BitMapChange(portnum,SNum,Han[4].Spage,0,&BM[0])) return FALSE; } // update the bitmap if(!WriteBitMap(portnum,SNum,&BM[0])) return FALSE; // turn off the internal flag Internal = FALSE; // reset current directory reset.Ref = '0'; reset.NumEntries = 0; owChangeDirectory(portnum,SNum,&reset); return TRUE; } //-------------------------------------------------------------------------- // Write a file by reference to a hnd. Buffer and // length are provided. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // hnd the handle of the file // buf the information to write to the file // len the len of the information to be written // // Returns: TRUE File Write successful // FALSE File Write a failure // SMALLINT owWriteFile(int portnum, uchar *SNum, short hnd, uchar *buf, int len) { uchar BM[32],dbuf[32],tbuf[32]; short i,j,mavail; int dlen,templen; PAGE_TYPE next,avail,tpg,dpg,pg; FileEntry Dmmy; uchar *ptr; SMALLINT bank; FileInfo Info; int new_entry = TRUE; // check device type if(!ValidRom(portnum,SNum)) return FALSE; // check to see if handle valid number if ((hnd > 3 || hnd < 0) && (Internal == FALSE)) { OWERROR(OWERROR_HANDLE_NOT_EXIST); return FALSE; } // check to see if hnd provided is valid file reference if (!Han[hnd].Name[0]) { OWERROR(OWERROR_HANDLE_NOT_USED); return FALSE; } bank = getBank(portnum,SNum,Han[hnd].Spage,REGMEM); // check to see if hnd is a write reference if(owIsReadOnly(bank,portnum,SNum)) { OWERROR(OWERROR_READ_ONLY); return FALSE; } // check if this is an addfile if (Han[hnd].Ext == 100) { templen = len; if(!owWriteAddFile(portnum,SNum,hnd,APPEND,0,buf,&templen)) return FALSE; } // get the bitmap to find empties and to adjust if(!ReadBitMap(portnum,SNum,&BM[0])) return FALSE; // check to see if file to write is too long (not take into account directory) if((Han[hnd].Ext == 101) || (Han[hnd].Ext == 102)) { // check if longer then page or some other file already got the page if ((len > 28) || (BM[Han[hnd].Spage / 8] & (0x01 << (Han[hnd].Spage % 8)))) { OWERROR(OWERROR_OUT_OF_SPACE); return FALSE; } } mavail = GetMaxWrite(portnum,SNum,&BM[0]); if (mavail == 0 || len > mavail) { OWERROR(OWERROR_OUT_OF_SPACE); return FALSE; } // try to find an empty spot in the directory if(!ReadNumEntry(portnum,SNum,-1,&Dmmy,&dpg)) return FALSE; // read the directory page indicated to see if it has space or is the last tpg = (uchar)dpg; if(!Read_Page(portnum,SNum,&dbuf[0],REGMEM,&tpg,&dlen)) return FALSE; for(i=0;i<4;i++) Info.Name[i] = Han[hnd].Name[i]; Info.Ext = Han[hnd].Ext; // special case for first directory page i = 7; // check to see if first dir page is a valid dir if ((dbuf[0] != 0xAA) && (dbuf[1] != 0) && (dlen > 29)) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } else if((dbuf[0] != 0xAA) || (dbuf[1] != 0)) { i = 0; } // loop through each directory entry to find FInfo for (;i < dlen; i += 7) { for (j = 0; j < 4; j++) // compare file name if ((toupper(dbuf[i+j]) != Info.Name[j]) && !((dbuf[i+j] == 0x20) && (Info.Name[j] == 0xCC))) break; if ((j != 4) || ((dbuf[i+4] & 0x7F) != Info.Ext)) continue; // loop if not match // number of pages //dbuf[i+6] = (Internal) ? 0 : ((len / 28) + ((len % 28) ? 1 : 0)); Han[hnd].Spage = dbuf[i+5]; Han[hnd].Ext = dbuf[i+4] & 0x7F; Han[hnd].NumPgs = (len/28) + ((len % 28) ? 1 : 0); dbuf[i+6] = Han[hnd].NumPgs; Han[hnd].Attrib = (dbuf[i+4] & 0x80) ? 1 : 0; if(Han[hnd].Ext == 0x7F) Han[hnd].Attrib <<= 1; Han[hnd].Dpage = (uchar) dpg; Han[hnd].Offset = (uchar) i; // spage_index = i+5; new_entry = FALSE; } // in light of the directory page read check space again if (dlen == 29) mavail-= 28; if (mavail <= 0 || len > mavail) { OWERROR(OWERROR_OUT_OF_SPACE); return FALSE; } // Record where the file begins if((Han[hnd].Ext != 101) && (Han[hnd].Ext != 102) && (new_entry)) { FindEmpties(portnum,SNum,&BM[0],&avail,&next); Han[hnd].Spage = avail; } // write the file in the available space if((Han[hnd].Ext == 101) || (Han[hnd].Ext == 102)) // Monitary file exception { // copy the data in to a temp buffer and add a continuation pointer for (i = 0; i < len; i++) tbuf[i] = buf[i]; tbuf[i] = 0; // write the page if(!Write_Page(portnum,SNum,&tbuf[0],Han[hnd].Spage,(len+1))) return FALSE; // set the bitmap page taken if(!BitMapChange(portnum,SNum,Han[hnd].Spage,1,&BM[0])) return FALSE; } else { if(!ExtWrite(portnum,SNum,Han[hnd].Spage,&buf[0],len,&BM[0])) return FALSE; } if(new_entry) { // construct the new directory entry Han[hnd].NumPgs = (Internal) ? 0 : ((len / 28) + ((len % 28) ? 1 : 0)); // don't allow external zero number of pages unless a directory if ((!Han[hnd].NumPgs) && (Han[hnd].Ext != 0x7F)) Han[hnd].NumPgs = 1; Han[hnd].Attrib = 0; // get an empty page FindEmpties(portnum,SNum,&BM[0],&avail,&next); // check to see if need to write a new directory page if (dlen == 29) { // write the new page if(!Write_Page(portnum,SNum,(uchar *) &Han[hnd],avail,8)) return FALSE; // set the bitmap to account for this new directory page if(!BitMapChange(portnum,SNum,avail,1,&BM[0])) return FALSE; // change the exhisting directory page continuation pointer dbuf[dlen-1] = avail; } // add the new directory entry to exhisting directory page else { // remember the continuation pointer pg = dbuf[dlen-1]; // get a pointer shorto the handle ptr = (uchar *) &Han[hnd]; // loop to add the new entry for (i = 0; i < 7; i++) dbuf[dlen-1+i] = ptr[i]; // adjust the length of the directory page dlen += 7; // correct the continuation pointer dbuf[dlen-1] = pg; } } // special case of dir page == 0 and local bitmap if ((dpg == 0) && (dbuf[2] & 0x80)) { // update the local bitmap for (i = 0; i < 2; i++) dbuf[3+i] = BM[i]; dbuf[5] = 0; dbuf[6] = 0; } // non page 0 or non local bitmap else { // write the bitmap if(!WriteBitMap(portnum,SNum,&BM[0])) return FALSE; } // now rewrite the directory page if(new_entry) { if(!Write_Page(portnum,SNum,&dbuf[0],dpg,dlen)) return FALSE; } else { if(!Write_Page(portnum,SNum,&dbuf[0],tpg,dlen)) return FALSE; } // free the file handle if(len != 0) Han[hnd].Name[0] = 0; return TRUE; } //-------------------------------------------------------------------------- // Deletes an indicated file. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // flname the name and information of the file to delete // // return: TRUE : file deleted // FALSE : error // SMALLINT owDeleteFile(int portnum, uchar *SNum, FileEntry *flname) { short e,i,j; uchar BM[32],buf[32],p; uchar pgbuf[34]; int len,err; PAGE_TYPE pg = 0,tpg; FileInfo Info; SMALLINT bank = 1; DirectoryPath reset; uchar pgjobstat; uchar jobBM[32]; // check device type if(!ValidRom(portnum,SNum)) return FALSE; // check to see if filename passed is valid if ((Valid_FileName(flname) == FALSE) || (((flname->Ext & 0x7F) == 0x7F) && (Internal == FALSE))) { OWERROR(OWERROR_XBAD_FILENAME); return FALSE; } // check for special case of extension 100 if(flname->Ext == 100 && (!owIsWriteOnce(bank,portnum,SNum))) { OWERROR(OWERROR_WRONG_TYPE); return FALSE; } // depending on the directory set the first page to look for entry pg = (CD.ne == 0) ? 0 : CD.Entry[CD.ne-1].page; // copy filename over to info packet for (i = 0; i < 4; i++) Info.Name[i] = flname->Name[i]; Info.Ext = flname->Ext; // check directory list to find the location of the file name if(!FindDirectoryInfo(portnum,SNum,&pg,&Info)) { OWERROR(OWERROR_FILE_NOT_FOUND); return FALSE; } // check to see if this entry is read only if (Info.Attrib == 0x01 && Info.Ext != 0x7F) { OWERROR(OWERROR_READ_ONLY); return FALSE; } // check existing open files with same the name (3.10) // automatically close the file for (i = 0; i < 4; i++) { if(Han[i].Name[0] != 0) { for (j = 0; j < 4; j++) if ((Han[i].Name[j] & 0x7F) != flname->Name[j]) break; if (j == 4 && ((Han[i].Ext & 0x7F) == flname->Ext)) { Han[i].Name[0] = 0; // release the handle break; } } } // get the bitmap so that it can be adjusted if(!ReadBitMap(portnum,SNum,BM)) return FALSE; // check for addfile if (Info.Ext == 100) { tpg = Info.Spage; for (i = 0; i < 256; i++) { // read a page in the file if(!ExtendedRead_Page(portnum,SNum,&pgbuf[0],tpg)) return FALSE; // check if only in buffer // or non written buffered eprom page if(isJob(portnum,SNum)) { // see if page set to write but has not started yet pgjobstat = isJobWritten(portnum,SNum,tpg); if ((pgjobstat == PJOB_ADD) && (pgjobstat != PJOB_START)) { // clear the job if(!setJobWritten(portnum,SNum,tpg,PJOB_NONE)) return FALSE; // clear this page in the bitmap if clear in original if(!getOrigBM(portnum,SNum,&jobBM[0])) return FALSE; if(!(jobBM[tpg/8] & (0x01 << (tpg%8)))) if(!BitMapChange(portnum,SNum,(uchar)tpg,0,&BM[0])) return FALSE; } } // get continuation pointer tpg = pgbuf[29]; if (tpg == 0xFF) break; } } // regular file else { owClearError(); // read the file to eliminate the bits in the bitmap if(!ExtRead(portnum,SNum,&buf[0],Info.Spage,-1,TRUE,BM,&len)) { if(!BitMapChange(portnum,SNum,Info.Spage,0,BM)) return FALSE; err = owGetErrorNum(); if(err != OWERROR_INVALID_PACKET_LENGTH) { OWERROR(err); return FALSE; } } } // read the directory page to see what the situation is if(!Read_Page(portnum,SNum,&buf[0],REGMEM,&Info.Dpage,&len)) return FALSE; // check for inappropriate directory length if ((len-1) % 7) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } // get number of entries e = len / 7; // check for condition that this is last enty in a directory packet if (e == 1) { // remember the current pages pointer p = buf[len-1]; // read the previous page to change its continuation pointer if(!Read_Page(portnum,SNum,&buf[0],REGMEM,&Info.PDpage,&len)) return FALSE; // set the prev dir page cont ptr to current page cont ptr buf[len-1] = p; // clear this page in the bitmap if(!BitMapChange(portnum,SNum,Info.Dpage,0,BM)) return FALSE; // set the page number to write pg = Info.PDpage; } // must keep this page and just remove the entry else { // remember the current pages pointer p = buf[len-1]; // shift directory page over to remove the entry for (i = Info.Offset; i < (len - 7); i++) buf[i] = buf[i+7]; // reduce the lenght of the directory page by 1 entry len -= 7; // set the continuation page buf[len-1] = p; // set the page number to write pg = Info.Dpage; } // write the directory page needed if(!Write_Page(portnum,SNum,&buf[0],pg,len)) return FALSE; else { if(!BitMapChange(portnum,SNum,Info.Spage,0,&BM[0])) return FALSE; } // update the bitmap if(!WriteBitMap(portnum,SNum,BM)) return FALSE; // reset current directory reset.Ref = '0'; reset.NumEntries = 0; owChangeDirectory(portnum,SNum,&reset); return TRUE; } //-------------------------------------------------------------------------- // Changes the attributes of a file. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // attr the attribute to change // flname the file name on which the attribute is to be changed // // return: TRUE : file attribute changed // FALSE : error // SMALLINT owAttribute(int portnum, uchar *SNum, short attr, FileEntry *flname) { uchar buf[32]; short i; PAGE_TYPE pg=0; FileInfo Info; int len; // check device type if(!ValidRom(portnum,SNum)) return FALSE; // check to see if filename passed is valid if (!Valid_FileName(flname)) { OWERROR(OWERROR_XBAD_FILENAME); return FALSE; } // check to see if this attribute is supported if ((((flname->Ext & 0x7F) == 0x7F) && ((attr != 0x02) && (attr != 0))) || (((flname->Ext & 0x7F) != 0x7F) && ((attr != 0x01) && (attr != 0))) ) { OWERROR(OWERROR_FUNC_NOT_SUP); return FALSE; } // depending on the directory set the first page to look for entry pg = (CD.ne == 0) ? 0 : CD.Entry[CD.ne-1].page; // copy filename over to info packet for (i = 0; i < 4; i++) Info.Name[i] = flname->Name[i]; Info.Ext = flname->Ext; // check directory list to find the location of the name if(!FindDirectoryInfo(portnum,SNum,&pg,&Info)) return FALSE; // check to see if the attribute already matches the entry if (Info.Attrib == attr) return TRUE; // read the directory page that the entry to change is in if(!Read_Page(portnum,SNum,&buf[0],REGMEM,&Info.Dpage,&len)) return FALSE; // exchange the new attribute for the old if (attr) buf[4+Info.Offset] |= 0x80; // set attr bit else buf[4+Info.Offset] = (buf[4+Info.Offset] | 0x80) ^ 0x80; // clear attr bit // write back the directory page with the new name if(!Write_Page(portnum,SNum,&buf[0],Info.Dpage,len)) return FALSE; return TRUE; } //-------------------------------------------------------------------------- // Change the name of a file that has been opened with the file handle // 'hnd'. The new name in 'flname'. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // hnd the handle of the file to rename // flname the renamed file name // // return: TRUE : filename changed // FALSE : error // SMALLINT owReNameFile(int portnum, uchar *SNum, short hnd, FileEntry *flname) { uchar buf[32]; short i,j; PAGE_TYPE pg = 0; FileInfo Info; int len; SMALLINT bank; // check device type if(!ValidRom(portnum,SNum)) return FALSE; // check to see if handle valid number if (hnd > 3 || hnd < 0) { OWERROR(OWERROR_HANDLE_NOT_EXIST); return FALSE; } // check to see if filename passed is valid if (!Valid_FileName(flname) || (flname->Ext & 0x80) || (flname->Ext > 100) || ((flname->Ext == 100) && (Han[hnd].Ext != 100)) || ((flname->Ext != 100) && (Han[hnd].Ext == 100)) ) { OWERROR(OWERROR_XBAD_FILENAME); return FALSE; } // check to see if hnd provided is valid file reference if (!Han[hnd].Name[0]) { OWERROR(OWERROR_HANDLE_NOT_USED); return FALSE; } bank = getBank(portnum,SNum,Han[hnd].Spage,REGMEM); // check to see if hnd is a write reference if(owIsReadOnly(bank,portnum,SNum)) { OWERROR(OWERROR_READ_ONLY); return FALSE; } // depending on the directory set the first page to look for entry pg = (CD.ne == 0) ? 0 : CD.Entry[CD.ne-1].page; // copy filename over to NewFile for (i = 0; i < 4; i++) Info.Name[i] = flname->Name[i]; Info.Ext = flname->Ext; // check directory list to see if new name is already in list if(FindDirectoryInfo(portnum,SNum,&pg,&Info)) { // file name already exists Han[hnd].Name[0] = 0; // release the handle return FALSE; } // read the directory page that the entry to change is in if(!Read_Page(portnum,SNum,&buf[0],REGMEM,&Han[hnd].Dpage,&len)) return FALSE; // exchange the new name for the old for (j = 0; j < 4; j++) buf[j+Han[hnd].Offset] = flname->Name[j]; buf[Han[hnd].Offset+4] = flname->Ext; // check to keep attribute the same as old if (Han[hnd].Attrib) buf[Han[hnd].Offset+4] |= 0x80; // write back the directory page with the new name if(!Write_Page(portnum,SNum,&buf[0],Han[hnd].Dpage,len)) return FALSE; Han[hnd].Name[0] = 0; // release handle on success return TRUE; } //-------------------------------------------------------------------------- // Read a file by reference to a handle. Buffer and // max length are provided. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // hnd the handle of the file // buf the information to that was read // maxlen the max length of the buffer that stores the // read data // fl_len the len of the data read // // return: TRUE : file read // FLASE : error // SMALLINT owReadFile(int portnum, uchar *SNum, short hnd, uchar *buf, int maxlen, int *fl_len) { short len,i; uchar BM[32],pg; uchar pgbuf[64]; SMALLINT bank; // check device type if(!ValidRom(portnum,SNum)) return FALSE; // check to see if handle valid number if (hnd > 3 || hnd < 0) { OWERROR(OWERROR_HANDLE_NOT_EXIST); return FALSE; } // check to see if hnd provided is valid file reference if (!Han[hnd].Name[0]) { OWERROR(OWERROR_HANDLE_NOT_USED); return FALSE; } bank = getBank(portnum,SNum,Han[hnd].Spage,REGMEM); // check to see if hnd is a write reference if(owIsReadOnly(bank,portnum,SNum)) { OWERROR(OWERROR_READ_ONLY); return FALSE; } // check for open 'add' file exception // 'add' file read using TMExtendedReadPage if (((Han[hnd].Ext == 100) && (Han[hnd].NumPgs == 0)) || (Han[hnd].Ext == 101) || (Han[hnd].Ext == 102)) { pg = Han[hnd].Spage; len = 0; for (;;) { for(i=0;i<32;i++) pgbuf[i] = 0xFF; // read a page in the file if(!ExtendedRead_Page(portnum,SNum,&pgbuf[0],pg)) return FALSE; // Monitary File if((Han[hnd].Ext == 101) || (Han[hnd].Ext == 102)) { if ((pgbuf[0] > 29) || ((pgbuf[0] + 7) > maxlen)) { OWERROR(OWERROR_BUFFER_TOO_SMALL); return FALSE; } // copy the counter/tamper to the end of the expected data for (i = 0; i < owGetExtraInfoLength(bank,SNum); i++) buf[i+pgbuf[0]-1] = pgbuf[i+32]; break; } // AddFile else { if ((len + 28) > maxlen) { OWERROR(OWERROR_BUFFER_TOO_SMALL); return FALSE; } for (i = 1; i <= 28; i++) buf[len++] = pgbuf[i]; pg = pgbuf[29]; if (pg == 0xFF) { for(i=29;i>0;i--) if(pgbuf[i] != 0xFF) { *fl_len = len - (29-i-1); break; } if(i == 0) *fl_len = len - 28; return TRUE; } } } } // if not a non-terminated addfile if (!((Han[hnd].Ext == 100) && (Han[hnd].NumPgs == 0))) { if(!ExtRead(portnum,SNum,&buf[0],Han[hnd].Spage,maxlen,FALSE,BM,fl_len)) return FALSE; } return TRUE; } //-------------------------------------------------------------------------- // Opens a file by first verifying that the file exists on the device and // to assign a handle. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // flname the name of the file and info. to open // hnd the assigned handle // // return: TRUE : file found // FALSE : error // SMALLINT owOpenFile(int portnum, uchar *SNum, FileEntry *flname, short *hnd) { short i,hn; PAGE_TYPE pg = 0; SMALLINT bank = 1; // check device type if(!ValidRom(portnum,SNum)) return FALSE; // check to see if filename passed is valid if (!Valid_FileName(flname) || ((flname->Ext & 0x7F) > 102)) { OWERROR(OWERROR_XBAD_FILENAME); return FALSE; } // check for special case of extension 100 (2.10) if (((flname->Ext == 100) && (!owIsWriteOnce(bank,portnum,SNum))) || ((flname->Ext == 101) && ((SNum[0] == 0x1A) || (SNum[0] == 0x1C) || (SNum[0] == 0x1D))) ) { OWERROR(OWERROR_WRONG_TYPE); return FALSE; } // find a handle for (i = 0; i < 4; i++) if(Han[i].Name[0] == 0) { hn = i; break; } else if((Han[i].Name[0] != 0) && (i == 3)) { OWERROR(OWERROR_HANDLE_NOT_AVAIL); return FALSE; } // depending on the directory set the first page to look for entry pg = (CD.ne == 0) ? 0 : CD.Entry[CD.ne-1].page; // copy the filename to the open handle for (i = 0; i < 4; i++) Han[hn].Name[i] = flname->Name[i]; Han[hn].Ext = flname->Ext & 0x7F; // search through directory to find file to open if(!FindDirectoryInfo(portnum,SNum,&pg,&Han[hn])) { Han[hn].Name[0] = 0; // release the handle OWERROR(OWERROR_FILE_NOT_FOUND); return FALSE; } // set the read flag Han[hn].Read = 1; // setting extra information flname->Spage = Han[hn].Spage; flname->NumPgs = Han[hn].NumPgs; // return the handle number *hnd = hn; return TRUE; } //-------------------------------------------------------------------------- // Formats a touch memory. Supports local and remote bitmap. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // // return: TURE : touch memory formatted // FALSE : error // SMALLINT owFormat(int portnum, uchar *SNum) { uchar nwdir[] = { 0xAA, 0, 0x80, 0x01, 0, 0, 0, 0 }; uchar bm[34],temp_buff[34]; short cnt; int i,j,len; int maxP; SMALLINT bank = 1; PAGE_TYPE bitmap,eprom,next,last=0; // check device type if(!ValidRom(portnum,SNum)) return FALSE; // invalidate current directory of device on this com port CD.ne = 0; maxP = maxPages(portnum,SNum); // check for file bitmap if ((maxP > 32) || (owIsWriteOnce(bank,portnum,SNum))) { // tweek the standard directory for remote bitmap nwdir[2] = 0x00; // bitmap control byte nwdir[3] = 0x00; // reset bitmap if((SNum[0] == 0x0A) || (SNum[0] == 0x0C) || (SNum[0] == 0x21)) { bitmap = 1; nwdir[5] = bitmap; // page address of bitmap } else if((SNum[0] == 0x0B) || (SNum[0] == 0x0F) || (SNum[0] == 0x13)) { bitmap = 8; nwdir[5] = bitmap; // page address of bitmap } else { bitmap = 0; nwdir[5] = bitmap; } // get eprom exception if ((!owIsWriteOnce(bank,portnum,SNum)) || (SNum[0]== 0x21) || (SNum[0] == 0x14)) nwdir[6] = (maxP > 223) ? 2 : 1; // pages in bitmap else { cnt = ((maxP + 1) / 8) + (((maxP + 1) % 8) ? 1 : 0); nwdir[6] = (cnt / 8) + ((cnt % 8) ? 1 : 0); } // zero the bitmap for (i = 0; i < 34; i++) bm[i] = 0; // set the pages to be used in the bitmap if((!owIsWriteOnce(bank,portnum,SNum)) || (SNum[0]== 0x21) || (SNum[0] == 0x14)) // nvram so bitmap is in regular space bm[0] = (nwdir[6] == 1) ? 0x03 : 0x07; else // must be an eprom so bitmap does not take up regular memory space bm[0] = 0x01; // write a null in page 0 before anything else if(!Write_Page(portnum,SNum,&nwdir[0],0,0)) return FALSE; // depending on type, bitmap may be in different places if((!owIsWriteOnce(bank,portnum,SNum)) || (SNum[0] == 0x14) || (SNum[0] == 0x18) || (SNum[0] == 0x23)) { // calculate length and continuation pointers if (bm[0] == 0x07) { // set the continuation pointer bm[28] = bitmap + 1; // set length i = 29; } else // set length i = (maxP + 1)/8 + 1; // write the first bitmap page if(!Write_Page(portnum,SNum,bm,bitmap,i)) return FALSE; // optionally write the second bitmap page if (bm[0] == 0x07) { i = (maxP + 1)/8 - 27; if(!Write_Page(portnum,SNum,&bm[29],(PAGE_TYPE) (bitmap+1),i)) return FALSE; } } // eprom so set page 0 in bitmap // not set bitmap on format else { // set the page 0 just in case it has not been set if(!ReadBitMap(portnum,SNum,bm)) return FALSE; // try to clear all possible buffer pages for (i = 0; i < maxP; i++) if(!BitMapChange(portnum,SNum,(uchar)i,0,bm)) return FALSE; if(!BitMapChange(portnum,SNum,0,1,bm)) return FALSE; if(!WriteBitMap(portnum,SNum,bm)) return FALSE; } } if(owIsWriteOnce(bank,portnum,SNum)) { bank = 0; eprom = 0; if(Read_Page(portnum,SNum,&temp_buff[0],REGMEM,&eprom,&len)) { if((eprom != 0) && (last == 0)) last = eprom; FindEmpties(portnum,SNum,bm,&eprom,&next); if(owReadPage(bank,portnum,SNum,eprom,FALSE,&temp_buff[0])) { for(j=0;j 0) { FE->Name[0] = '.'; FE->Name[1] = ' '; FE->Name[2] = ' '; FE->Name[3] = ' '; FE->Ext = 0x7F; FE->Spage = CD.Entry[CD.ne-1].page; FE->NumPgs = 0; FE->Attrib = CD.Entry[CD.ne-1].attrib; // attempt to read the bitmap if(!ReadBitMap(portnum,SNum,&FE->BM[0])) return FALSE; } // not sub-directory else { // read the part of the directory to find the first file if(!ReadNumEntry(portnum,SNum,1,FE,&pg)) return FALSE; } LastFile += 1; // update the file counter return FIRST_FOUND; // don't know how many now so return max } //-------------------------------------------------------------------------- // Find next file and put it shorto the string DirEnt. // // Find first file and copy it into string DirEnt. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // FE the infomation of the first file/dir found // // return: TRUE : file found // FALSE : no file found, error // SMALLINT owNextFile(int portnum, uchar *SNum, FileEntry *FE) { PAGE_TYPE pg,page; // check for a first reference if (!LastFile) return owFirstFile(portnum,SNum,FE); // check device type if(!ValidRom(portnum,SNum)) return FALSE; // check to see if the directory is valid pg = (CD.ne == 0) ? 0 : CD.Entry[CD.ne-1].page;; // check to see if in a sub-directory, if yes and LastFile = 1 then return '..' if ((CD.ne > 0) && (LastFile == 1)) { FE->Name[0] = '.'; FE->Name[1] = '.'; FE->Name[2] = ' '; FE->Name[3] = ' '; FE->Ext = 0x7F; // check for root exception for previous directory if (CD.ne == 1) { FE->Spage = 0; FE->Attrib = 0; } // must be at least 2 levels deep so previous is not root else { FE->Spage = CD.Entry[CD.ne-2].page; FE->Attrib = CD.Entry[CD.ne-2].attrib; } FE->NumPgs = 0; // attempt to read the bitmap if(!ReadBitMap(portnum,SNum,&FE->BM[0])) return FALSE; } // not (sub-directory and not back reference) else { // read the part of the directory to find the next file // figure the entry number if in sub-directory pg = (CD.ne > 0) ? LastFile - 1 : LastFile + 1; owClearError(); if(!ReadNumEntry(portnum,SNum,pg,FE,&page)) { if(owGetErrorNum() == OWERROR_FILE_NOT_FOUND) { LastFile = 0; // reset the file counter return FALSE; } else if(!owHasErrors()) { LastFile = 0; return FALSE; } else return FALSE; } } LastFile += 1; // update the file counter return TRUE; } // owGetCurrentDir // // Get the current directory path // Find first file and copy it into string DirEnt. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // FE the infomation of the first file/dir found // // returns the current directory path // DirectoryPath owGetCurrentDir(int portnum, uchar *SNum) { DirectoryPath retpath; int i,j; retpath.NumEntries = CD.ne; // set the number of directory levels retpath.Ref = '\\'; // symbol for root // loop to copy each entry for (i = 0; i < CD.ne; i++) for (j = 0; j < 4; j++) retpath.Entries[i][j] = CD.Entry[i].name[j]; return retpath; } //-------------------------------------------------------------------------- // owChangeDirectory // // Set or read the current directory. The 'Operation' flag tells what the // operation will be. If 'Operation' is 1 then the working directory is read. // // Find first file and copy it into string DirEnt. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // CDBuf the directory to change to // // return: 1 : directory set or read successfully // <0 : tmex error // // SMALLINT owChangeDirectory(int portnum, uchar *SNum, DirectoryPath *CDBuf) { short i,j; uchar ROM[8]; CurrentDirectory TCD; uchar pg=0; FileInfo fbuf; // check device type if(!ValidRom(portnum,SNum)) return FALSE; // check to see if new directory is a reference from current directory if (CDBuf->Ref == '.') TCD = CD; // copy current directory // else starting from root with an empty directory else TCD.ne = 0; // loop through new directory and verify each level for (i = 0; i < CDBuf->NumEntries; i++) { // check for a back reference if (CDBuf->Entries[i][0] == '.' && CDBuf->Entries[i][1] == '.') { // reference TCD back a level if possible if (TCD.ne > 0) TCD.ne--; else { OWERROR(OWERROR_INVALID_DIRECTORY); return FALSE; } } // check for non-current reference else if (!(CDBuf->Entries[i][0] == '.')) //) { // add the forward reference to TCD for (j = 0; j < 4; j++) { TCD.Entry[TCD.ne].name[j] = toupper(CDBuf->Entries[i][j]); fbuf.Name[j] = TCD.Entry[TCD.ne].name[j]; // also copy to temp buffer } TCD.Entry[TCD.ne].page = 0; // zero the page reference fbuf.Ext = 0x7F; // set the extention to directory // read the current level to verify new level is valid pg = (TCD.ne > 0) ? TCD.Entry[TCD.ne-1].page : 0; // search through the next layer for the entry if(!FindDirectoryInfo(portnum,SNum,&pg,&fbuf)) { OWERROR(OWERROR_INVALID_DIRECTORY); return FALSE; } // remember the page that this level starts on TCD.Entry[TCD.ne].page = fbuf.Spage; // also remember the attribute of the directory TCD.Entry[TCD.ne].attrib = fbuf.Attrib; // since this level is a success go to next TCD.ne++; } } // success CD = TCD; // get the current ROM ROM[0] = 0; owSerialNum(portnum,&ROM[0],TRUE); // set the rom for (i = 0; i < 8; i++) CD.DRom[i] = ROM[i]; return TRUE; } //-------------------------------------------------------------------------- // Create a file by first verifying that the file does not exist on the // device and to assign a handle to it for writing. // // Find first file and copy it into string DirEnt. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // maxwrite the max that can be written // hnd the handle of the file created // flname the name and information for the file // // return: TRUE : file created // FALSE : error // SMALLINT owCreateFile(int portnum, uchar *SNum, int *maxwrite, short *hnd, FileEntry *flname) { short hn,flag,j; uchar i; PAGE_TYPE pg = 0,avail,next; uchar BM[32],pgbuf[52]; SMALLINT bank = 1; int maxP; // check device type if(!ValidRom(portnum,SNum)) return FALSE; // check to see if filename passed is valid if (!Valid_FileName(flname) || (flname->Ext > 102)) { OWERROR(OWERROR_XBAD_FILENAME); return FALSE; } // check for special case of extension 100 if ((flname->Ext == 100) && (!owIsWriteOnce(bank,portnum,SNum))) { OWERROR(OWERROR_WRONG_TYPE); return FALSE; } // check for special case of extension 101 if ((flname->Ext == 101) && ((SNum[0] != 0x1A) || (SNum[0] != 0x1C) || (SNum[0] != 0x1D))) { OWERROR(OWERROR_WRONG_TYPE); return FALSE; } // check existing open files to with same name for (i = 0; i < 4; i++) { if (Han[i].Name[0] != 0) { for (j = 0; j < 4; j++) if ((Han[i].Name[j] & 0x7F) != flname->Name[j]) break; if (j == 4 && ((Han[i].Ext & 0x7F) == flname->Ext)) { OWERROR(OWERROR_REPEAT_FILE); // file already exists return FALSE; } } } hn = -1; // find a handle for (i = 0; i < 4; i++) if (Han[i].Name[0] == 0) { hn = i; break; } if(hn == -1) { OWERROR(OWERROR_HANDLE_NOT_AVAIL); return FALSE; } // depending on the directory set the first page to look for entry pg = (CD.ne == 0) ? 0 : CD.Entry[CD.ne-1].page; // copy the filename to the open handle for (i = 0; i < 4; i++) Han[hn].Name[i] = flname->Name[i]; Han[hn].Ext = flname->Ext; // clear other parts of structure (3.10) Han[hn].Spage = 0; Han[hn].NumPgs = 0; Han[hn].Attrib = 0; // search through directory to find file to open owClearError(); if(!FindDirectoryInfo(portnum,SNum,&pg,&Han[hn])) { if(owGetErrorNum() == OWERROR_FILE_NOT_FOUND) { Han[hn].Name[0] = 0; return FALSE; } } else { Han[hn].Name[0] = 0; OWERROR(OWERROR_REPEAT_FILE); return FALSE; } // clear the read flag Han[hn].Read = 0; // read the bitmap to calculate the maxwrite if(!ReadBitMap(portnum,SNum,BM)) { Han[hn].Name[0] = 0; return FALSE; } maxP = maxPages(portnum,SNum); // if monitary file if((flname->Ext == 101) || (flname->Ext == 102)) { // fill all pages except monitary pages if(SNum[0] == 0x18) { flag = 8; } else { flag = (maxP+1) / 4; if (flag < 3) flag = 3; } for (i = 0; i <= (maxP - flag); i++) if(!BitMapChange(portnum,SNum,i,1,BM)) { Han[hn].Name[0] = 0; return FALSE; } // also set any pages used in open (101) files for (i = 0; i < 4; i++) if ((Han[i].Name[0] != 0) && ((Han[i].Ext == 101) || (Han[i].Ext == 102)) && (hn != i)) if(!BitMapChange(portnum,SNum,Han[i].Spage,1,BM)) { Han[hn].Name[0] = 0; return FALSE; } // check if any space flag = GetMaxWrite(portnum,SNum,BM); if (flag < 28) { Han[hn].Name[0] = 0; // release the handle OWERROR(OWERROR_OUT_OF_SPACE); // return error code return FALSE; } // get a page FindEmpties(portnum,SNum,BM,&avail,&next); flname->Spage = avail; // for user to use Han[hn].Spage = avail; // for driver // read the page to get the counter for user if(!ExtendedRead_Page(portnum,SNum,&pgbuf[0],avail)) { Han[hn].Name[0] = 0; return FALSE; } // copy the counter/tamper into the bitmap for user if(SNum[0] == 0x18) { for (i = 0; i < 8; i++) flname->BM[i] = pgbuf[i+32]; } else if((SNum[0] == 0x33) || (SNum[0] == 0xB3)) { for (i = 0; i < 8; i++) flname->BM[i] = 0x00; } *maxwrite = 28; } else { // count empty pages in bitmap flag = GetMaxWrite(portnum,SNum,BM); if (flag > 28) flag -=28; *maxwrite = flag; } pgbuf[0] = 0xAA; pgbuf[1] = 0; if(!owWriteFile(portnum,SNum,hn,&pgbuf[0],0)) { Han[hn].Name[0] = 0; return FALSE; } // return the handle number *hnd = hn; return TRUE; } //-------------------------------------------------------------------------- // Close a file by freeing up its handle. // // Find first file and copy it into string DirEnt. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // hnd the handle of the file to close // // return: TRUE : file closed // FALSE : error // SMALLINT owCloseFile(int portnum, uchar *SNum, short hnd) { // check that the handle is in the correct range if ((hnd < 4) && (hnd >= 0) && (Han[hnd].Name[0] != 0)) Han[hnd].Name[0] = 0; //zero first byte of handle area else { OWERROR(OWERROR_HANDLE_NOT_EXIST); return FALSE; // error for handle does not exist } return TRUE; } //-------------------------------------------------------------------------- // Search throuch the directory of the device for the entry 'flname' and // return the page number to the caller. Also copy shorto standard 'FileInfo' // format at DirEntry. // // Find first file and copy it into string DirEnt. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // pg the next or current page // FInfo the file information that was gotten // // returns: // TRUE : directory page number was found // FALSE : error // SMALLINT FindDirectoryInfo(int portnum, uchar *SNum, PAGE_TYPE *pg, FileInfo *FInfo) { short i,j; uchar pgbuf[30]; PAGE_TYPE tpg,ppage,spg; int flag = 0; // start previouse page as current page ppage = *pg; spg = *pg; // loop to search through directory pages do { // read a page in the directory tpg = *pg; if(!Read_Page(portnum,SNum,&pgbuf[0],REGMEM,&tpg,&flag)) return FALSE; // if have a good read then search inside page for EntNum if (flag > 0) { // special case for first directory page i = 0; if (*pg == spg) { i = 7; // check to see if first dir page is a valid dir if (pgbuf[0] != 0xAA || pgbuf[1] != 0) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } } // loop through each directory entry to find FInfo for (;i < flag; i += 7) { for (j = 0; j < 4; j++) // compare file name if ((toupper(pgbuf[i+j]) != FInfo->Name[j]) && !((pgbuf[i+j] == 0x20) && (FInfo->Name[j] == 0xCC))) break; if ((j != 4) || ((pgbuf[i+4] & 0x7F) != FInfo->Ext)) continue; // loop if not match // must be a match at this poshort // get the extension FInfo->Ext = pgbuf[i+4] & 0x7F; // get the start page FInfo->Spage = pgbuf[i+5]; // number of pages FInfo->NumPgs = pgbuf[i+6]; // get the readonly/hidden flag FInfo->Attrib = (pgbuf[i+4] & 0x80) ? 1 : 0; // shift attribute if his hidded flag if (FInfo->Ext == 0x7F) FInfo->Attrib <<= 1; // remember the page entry found FInfo->Dpage = *pg; // remember the offset of entry in directory FInfo->Offset = (uchar)i; // previouse directory page FInfo->PDpage = ppage; // return the current page number return TRUE; } // poshort to next page ppage = *pg; *pg = pgbuf[flag-1]; } else return FALSE; // return error } while(*pg); // return failure to find directory entry return FALSE; } //-------------------------------------------------------------------------- // Read the directory to find the EntNum entry and load its value shorto // the FileEntry. If the entry number 'EntNum' is -1 then instead of looking // for an entry number, this function is looking for empty directory place. // If an empty place is not found then the last page of the directory is // returned. // // Find first file and copy it into string DirEnt. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // EntNum the entry number // FEntry the file entry number information // pg the page for the data // // Returns: // TRUE : entry found // FALSE : error // SMALLINT ReadNumEntry(int portnum, uchar *SNum, short EntNum, FileEntry *FEntry, PAGE_TYPE *pg) { uchar pgbuf[30]; int firstpg; short EntCnt=0,i,j,tw; int len = 0; // set the entry to null FEntry->Name[0] = 0; // check to see if CD is still valid and get the starting page of working dir *pg = (CD.ne == 0) ? 0 : CD.Entry[CD.ne-1].page; firstpg = TRUE; // loop to search through directory pages do { // read a page in the directory if(!Read_Page(portnum,SNum,&pgbuf[0],REGMEM,pg,&len)) return FALSE; // special case for first directory page tw = 0; if (firstpg) { firstpg = FALSE; tw = 1; // check to see if first dir page is a valid dir if (pgbuf[0] != 0xAA || pgbuf[1] != 0 || len < 7) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } } // check to see if searching for an empty spot if (EntNum == -1) { // if the length is less then 4*7+1 or last page if ((len < 29) || (pgbuf[len-1] == 0)) return TRUE; // return the page number spot found on } // check to see if EntNum is in this page else if ((EntCnt + (len / 7) - tw) >= EntNum) { // then get it j = (EntNum - EntCnt + tw - 1) * 7; // copy the name,extension,startpage,numpages,attributes for (i = 0; i < 4; i++) FEntry->Name[i] = pgbuf[j+i]; FEntry->Ext = pgbuf[j+4] & 0x7F; FEntry->Spage = pgbuf[j+5]; FEntry->NumPgs = pgbuf[j+6]; FEntry->Attrib = (pgbuf[j+4] & 0x80) ? 1 : 0; if (FEntry->Ext == 0x7F) FEntry->Attrib <<= 1; break; } // get the pointer to the next page *pg = pgbuf[len-1]; // for the end of the list of dir and files if(*pg == 0) { OWERROR(OWERROR_FILE_NOT_FOUND); return FALSE; } // increment the EntCnt EntCnt += ((len / 7) - tw); } while (*pg && (len > 0)); // attempt to read the bitmap if(!ReadBitMap(portnum,SNum,&FEntry->BM[0])) return FALSE; // check status if (!FEntry->Name[0]) { if (!*pg) { OWERROR(OWERROR_FILE_NOT_FOUND); return FALSE; } else { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } } return TRUE; } //-------------------------------------------------------------------------- // Write the bitmap for the current device from the Bmap buffer. // The bitmap could be local or remote. The first page of the device // is read to determine the Bitmap type and location. // // Find first file and copy it into string DirEnt. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // Bmap the bitmap to be written // // Return: TRUE : bitmap written successfully // FALSE : error // // SMALLINT WriteBitMap(int portnum, uchar *SNum, uchar *Bmap) { short i,j,b,flag; int len,maxP,mBcnt; uchar pgbuf[32]; PAGE_TYPE pg = 0,tpg; SMALLINT bank = 1; // depending on type, bitmap may be in different places if(!owIsWriteOnce(bank,portnum,SNum)) { // read the first page to get local bitmap or address of bitmap file if(!Read_Page(portnum,SNum,&pgbuf[0],REGMEM,&pg,&len)) return FALSE; // make sure is a directory if (pgbuf[0] != 0xAA || pgbuf[1] != 0x00) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } maxP = maxPages(portnum,SNum); // get the number of bytes in bitmap b = maxP / 8; b += ((maxP % 8) ? 1 : 0); // check for local bitmap if (pgbuf[2] & 0x80) { // check for impossible number of pages local if (maxP > 32) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } // first zero out the existing bitmap for (i = 3; i <= 6; i++) pgbuf[i] = 0; // copy the new bitmap over for (i = 0; i < b; i++) pgbuf[i+3] = Bmap[i]; } // remote bitmap else // (2.00Bug) else was missing in 2.00 { tpg = pgbuf[5]; // remote bitmap location maxP = maxPages(portnum,SNum); // check for 2 page bitmap if(maxP > 224) { // 2 pages so read the first page to get continuation if(!Read_Page(portnum,SNum,&pgbuf[0],REGMEM,&tpg,&len)) return FALSE; // sanity check if (len != 29) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } // get the continuation page pg = pgbuf[len-1]; // check and copy over flag = 0; for (i = 0; i < (len-1); i++) { if (pgbuf[i] != Bmap[i]) { flag = 1; pgbuf[i] = Bmap[i]; } } // write back the first bitmap page if it has changed if (flag) { // write the first page of the bitmap if(!Write_Page(portnum,SNum,&pgbuf[0],tpg,len)) return FALSE; } // create the second page for (i = 0; i < (b-28); i++) pgbuf[i] = Bmap[i+28]; pgbuf[i] = 0; // end continuation page pointer // set the new length len = b-27; } else // (2.00Bug) this else and code for 1 page bitmap files was missing { pg = pgbuf[5]; // remote bitmap location // copy the new bitmap over for (i = 0; i < b; i++) pgbuf[i] = Bmap[i]; len = b + 1; // get the correct length pgbuf[b] = 0; // end continuation page pointer } } // loop to write a page of the bitmap if(!Write_Page(portnum,SNum,&pgbuf[0],pg,len)) return FALSE; } // Else this is a an program job else { // is there a job that has been opened then read from buffer and not the part if(isJob(portnum,SNum)) { maxP = maxPages(portnum,SNum);; // bitmap is in the status memory // get number of status bytes needed mBcnt = (maxP / 8) + (((maxP % 8) > 0) ? 1 : 0); // loop to copy from the programjob buffer for(i=0;i> j) & 0x01)) if(!setJobWritten(portnum,SNum,(PAGE_TYPE)(i*8+j),PJOB_NONE)) return FALSE; } } return TRUE; } else { // error condition, should never happen here OWERROR(OWERROR_NO_PROGRAM_JOB); return FALSE; } } return TRUE; } //-------------------------------------------------------------------------- // Read the bitmap from the current device and place it in the Bmap buffer. // The bitmap could be local or remote. The first page of the device // is read to determine the Bitmap type and location. // // Find first file and copy it into string DirEnt. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // Bmap the returned bit map // // Return: TRUE : bitmap read // FALSE : error // // SMALLINT ReadBitMap(int portnum, uchar *SNum, uchar *Bmap) { short i,j,l,flag,mBcnt; uchar pgbuf[32],tpg=0,pg; SMALLINT bank = 1; int page = 0; int len = 0; int maxP = 0; // depending on type, bitmap may be in different places if (!owIsWriteOnce(bank,page,SNum)) { // read the first page to get local bitmap or address of bitmap file if(!Read_Page(portnum,SNum,&pgbuf[0],REGMEM,&tpg,&len)) return FALSE; // make sure is a directory if (pgbuf[0] != 0xAA || pgbuf[1] != 0x00) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } // check for local bitmap if (pgbuf[2] & 0x80) { // its local, but does this make sense for this size of device maxP = maxPages(portnum,SNum); if(maxP > 32) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } // clear out bitmap for(i = 0; i <= len-1; i++) Bmap[i] = 0; // copy over the local bitmap for(i = 0; i <= maxP/8; i++) Bmap[i] = pgbuf[i+3]; // return true return TRUE; } // must be remote else { pg = pgbuf[5]; // remote bitmap location // read the first page of the bitmap if(!Read_Page(portnum,SNum,&pgbuf[0],REGMEM,&pg,&len)) return FALSE; maxP = maxPages(portnum,SNum); // check size and continuation pointers to make sure they are valid if (((maxP > 224) && ((len != 29) || (pgbuf[len-1] == 0))) || ((maxP <= 224) && (((maxP+1)/8 != (len - 1)) || (pgbuf[len-1] != 0)) )) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } // copy bitmap over to the buffer for (i = 0; i < (len-1); i++) Bmap[i] = pgbuf[i]; // check to see if need a second bitmap page if (pgbuf[len-1]) { // get the page number from the continuation pointer pg = pgbuf[len-1]; // read the second page of the bitmap if(!Read_Page(portnum,SNum,&pgbuf[0],REGMEM,&pg,&len)) return FALSE; // check if size of rest of bitmap makes sense if ((27 + len) != ((maxP+1)/8)) { OWERROR(OWERROR_FILE_READ_ERR); return FALSE; } // copy rest of bitmap to buffer for (i = 0; i < (len-1); i++) Bmap[28+i] = pgbuf[i]; return TRUE; } return TRUE; } } // DS1982/DS2405A type program else if(owIsWriteOnce(bank,page,SNum)) { if((SNum[0] == 0x0B) || (SNum[0] == 0x0F)) { maxP = maxPages(portnum,SNum); mBcnt = ((maxP+1) / 8) + ((((maxP+1) % 8) > 0) ? 1 : 0); l = (mBcnt / 8) + (((mBcnt % 8) > 0) ? 1 : 0); // check for the an Program Job flag = FALSE; if(isJob(portnum,SNum)) { // loop to copy from the programjob buffer if(!getProgramJob(portnum,SNum,&Bmap[0],mBcnt)) return FALSE; flag = TRUE; } // read from the part if (!flag) { // loop through the number of bitmap pages for (i = 0; i < l; i++) { // read stat mem page tpg = i + 8; if(!Read_Page(portnum,SNum,&pgbuf[0],STATUSMEM,&tpg,&len)) return FALSE; // check results if (len == 8) { // copy bitmap read shorto buffer for (j = 0; j < 8; j++) if (j <= mBcnt) Bmap[j + i * 8] = ~pgbuf[j]; else break; // quit the loop because done } else return FALSE; } } return TRUE; } else { // is there a job that has been opened then read from buffer and not the part if(isJob(portnum,SNum)) { // to copy from the programjob buffer if(!getProgramJob(portnum,SNum,&Bmap[0],1)) return FALSE; return TRUE; } tpg = 0; // bitmap is in the status memory page 0, byte if(!Read_Page(portnum,SNum,&pgbuf[0],STATUSMEM,&tpg,&len)) return FALSE; // check result of status read if (len == 8) { Bmap[0] = (~(pgbuf[0] >> 4)) & 0x0F; return TRUE; } } } else OWERROR(OWERROR_WRONG_TYPE); return FALSE; } //-------------------------------------------------------------------------- // Calculate and return the numbers of bytes available to write in the // current device. Note that the value is adjusted for the contingency // that the addition of a new file in the directory may make the directory // a page longer. // SMALLINT GetMaxWrite(int portnum, uchar *SNum, uchar *BM) { uchar t=0; short bcnt=0,cnt=0,i; int maxP = 0; maxP = maxPages(portnum,SNum); // loop through each page bit for (i = 0; i <= maxP; i++) { // check if it is time to get the next bm byte if ((i % 8) == 0) t = BM[bcnt++]; // check for empty pages if (!(t & 0x01)) cnt++; // look at next page t >>= 1; } // don't take shorto acount the effect of a new directory page return (cnt*28); } //-------------------------------------------------------------------------- // Check to see if the serial number being used is the current one. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // // returns 'true' if it is the current serial number // otherwise 'false' // SMALLINT ValidRom(int portnum,uchar *SNum) { int i; uchar check[8]; if(current[0] == 0x00) { for(i=0;i<8;i++) current[i] = SNum[i]; owSerialNum(portnum,&SNum[0],FALSE); } else { owSerialNum(portnum,&check[0],TRUE); for(i=0;i<8;i++) if(check[i] != SNum[i]) return FALSE; } return TRUE; } //-------------------------------------------------------------------------- // Do bit manipulation to the provided bitmap. Change the 'BitNum' bit to // the 'State'. This function needs Handle and D to check the max page // number and see if clearing a bit is possible (Eprom). // // Find first file and copy it into string DirEnt. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // BitNum the bit number to be changed // State the state of the bit to be changed to // BM the pointer to the bit map that is changed // // This function returns: // TRUE : operation is ok for this device // FALSE : could not do operation because incompatible with // device type // SMALLINT BitMapChange(int portnum, uchar *SNum, uchar BitNum, uchar State, uchar *BM) { PAGE_TYPE maxP; SMALLINT bank = 1; int page = 0; maxP = maxPages(portnum,SNum); // check for a not possible request if(BitNum > maxP) { OWERROR(OWERROR_TOO_LARGE_BITNUM); return FALSE; } // check for the clearing of an eprom device (not possible) if(owIsWriteOnce(bank,page,SNum)) { if (State == 0) { // check if only in buffer // or non written buffered eprom page if(isJob(portnum,SNum)) { // see if page set to write but has not started yet if ((isJobWritten(portnum,SNum,BitNum) == PJOB_WRITE) && ((isJobWritten(portnum,SNum,BitNum) & PJOB_START) != PJOB_START) ) { if(!setJobWritten(portnum,SNum,BitNum,PJOB_NONE)) return FALSE; BM[BitNum / 8] = (BM[BitNum / 8] | (0x01 << (BitNum % 8))) ^ (0x01 << (BitNum % 8)); } } else return TRUE; } else BM[BitNum / 8] |= (0x01 << (BitNum % 8)); } // NVRAM else { // depending on the state do the opertion if (State) BM[BitNum / 8] |= (0x01 << (BitNum % 8)); else BM[BitNum / 8] = (BM[BitNum / 8] | (0x01 << (BitNum % 8))) ^ (0x01 << (BitNum % 8)); } return TRUE; } //-------------------------------------------------------------------------- // Function to decide if the filename passed to it is valid in TMEX. // SMALLINT Valid_FileName(FileEntry *flname) { uchar i; // loop to check if filename is valid and convert to upper case for (i = 0; i < 4; i++) if (!isalnum(flname->Name[i]) && !strrchr(" !#$%&'-@^_`{}~",flname->Name[i])) return FALSE; else flname->Name[i] = toupper(flname->Name[i]); // convert to upper case return TRUE; } //-------------------------------------------------------------------------- // Function to search through the provided bitmap 'BM' and return the // first 'avail'able page and the 'next' available page. // void FindEmpties(int portnum, uchar *SNum, uchar *BM, PAGE_TYPE *avail, PAGE_TYPE *next) { uchar First=1,t=0,i,bcnt=0; int tmp_pgs = maxPages(portnum,SNum); // loop through all of the pages in the bitmap for (i = 0; i <= tmp_pgs; i++) { // check if it is time to get the next bm byte if ((i % 8) == 0) t = BM[bcnt++]; // check for empty pages if (!(t & 0x01)) { if (First) { *avail = i; First = 0; } else { *next = i; return; } } // look at next page t >>= 1; } } //-------------------------------------------------------------------------- // This function returns the maximum number of pages that can be used for // the file I/O operations. // // portnum the port number of the port being used for the // 1-Wire Network. // SNum the serial number for the part that the read is // to be done on. // // This function returns: The number of pages for File I/O // // int maxPages(int portnum, uchar *SNum) { SMALLINT bank = 1; SMALLINT i; int tmp_pgs = 0; if(owIsWriteOnce(bank,portnum,SNum)) { for(i=0;i=0 File Write successful return number of bytes written // <0 File Write a failure, TMEX error // SMALLINT owWriteAddFile(int portnum, uchar *SNum, short hnd, short operation, short offset, uchar *buf, int *len) { uchar BM[32],pgbuf[34]; int i,cnt=0,mavail,dlen,offcnt,ppage,spg; short spot,op; PAGE_TYPE next,avail,tpg,pg,dpg; FileEntry Dmmy; uchar *ptr; // check device type if(!ValidRom(portnum,SNum)) return FALSE; // check to see if handle valid number if (hnd > 3 || hnd < 0) { OWERROR(OWERROR_HANDLE_NOT_EXIST); return FALSE; } // check to see that hnd is valid if (!Han[hnd].Name[0]) { OWERROR(OWERROR_HANDLE_NOT_USED); return FALSE; } // check to see if extension is 100 if(Han[hnd].Ext != 100) { OWERROR(OWERROR_FUNC_NOT_SUP); return FALSE; } // check to see if the file is aleady terminated if(Han[hnd].NumPgs != 0) { OWERROR(OWERROR_ADDFILE_TERMINATED); return FALSE; } // get the bitmap to find empties if needed if(!ReadBitMap(portnum,SNum,&BM[0])) return FALSE; // get current empty space on device mavail = GetMaxWrite(portnum,SNum,&BM[0]); // check to see if this is a new file or an existing file // file already exist if(Han[hnd].Read == 1) { // start at starting page of the opened file pg = Han[hnd].Spage; ppage = pg; spg = pg; offcnt = -1; // loop to search through file pages for(;;) { // read a page in the file if(!owReadPageExtraCRC(0,portnum,SNum,pg,&pgbuf[0],&pgbuf[32])) return FALSE; // check for an already terminated file if (pgbuf[0] != 0xFF) { OWERROR(OWERROR_ADDFILE_TERMINATED); return FALSE; } // append if (operation == APPEND) { // check to see if this is the last page if (pgbuf[29] == 0xFF) { for (spot = 28; spot >= 0; spot--) if (pgbuf[spot] != 0xFF) break; if (spot <= 0) spot = 1; else spot++; // 'spot' is the spot to append to on page 'pg' break; } } // offset else { // loop to look for the spot for (spot = 1; spot <= 28; spot++) { if (++offcnt == offset) break; } // check to see if got to the offset point or out of pages if (offcnt == offset || pgbuf[29] == 0xFF) break; } // then try the next page in the chain pg = pgbuf[29]; } } // file is new so have to add to directory else { // try to find an empty spot in the directory if(!ReadNumEntry(portnum,SNum,-1,&Dmmy,&dpg)) return FALSE; // read the directory page indicated to see if it has space or is the last // loop while error during read up to 3 count cnt = 0; tpg = (uchar)dpg; if(!Read_Page(portnum,SNum,&pgbuf[0],REGMEM,&tpg,&dlen)) return FALSE; // in light of the directory page read check space again if (dlen == 29) mavail -= 28; if (mavail < 0 || *len > mavail) { OWERROR(OWERROR_OUT_OF_SPACE); return FALSE; } // Record where the file begins FindEmpties(portnum,SNum,&BM[0],&avail,&next); Han[hnd].Spage = avail; // set the bitmap to claim this page if(!BitMapChange(portnum,SNum,avail,1,&BM[0])) return FALSE; // construct the new directory entry Han[hnd].NumPgs = 0; Han[hnd].Attrib = 0; // check to see if need to write a new directory page if (dlen == 29) { // get an empty page for the new directory page FindEmpties(portnum,SNum,&BM[0],&avail,&next); // write the new page if(!Write_Page(portnum,SNum,(uchar *) &Han[hnd],avail,8)) return FALSE; // set the bitmap to account for this new directory page if(!BitMapChange(portnum,SNum,avail,1,&BM[0])) return FALSE; // change the exhisting directory page continuation pointer pgbuf[dlen-1] = avail; } // add the new directory entry to exhisting directory page else { // remember the continuation pointer pg = pgbuf[dlen-1]; // get a pointer into the handle ptr = (uchar *) &Han[hnd]; // loop to add the new entry for (i = 0; i < 7; i++) pgbuf[dlen-1+i] = ptr[i]; // adjust the length of the directory page dlen += 7; // correct the continuation pointer pgbuf[dlen-1] = pg; } // special case of dir page == 0 and local bitmap if ((dpg == 0) && (pgbuf[2] & 0x80)) { // update the local bitmap for (i = 0; i < 2; i++) pgbuf[3+i] = BM[i]; pgbuf[5] = 0; pgbuf[6] = 0; } // non page 0 or non local bitmap else { // write the bitmap if(!WriteBitMap(portnum,SNum,&BM[0])) return FALSE; } // now rewrite the directory page if(!Write_Page(portnum,SNum,&pgbuf[0],dpg,dlen)) return FALSE; pg = Han[hnd].Spage; spot = 1; offcnt = 0; } // check to see if need to add some blank pages (except for pointer) if (operation == 0 && offcnt != offset) { // start on 'pg' and add pages until get to offset for (;;) { // loop to look for the spot for (; spot <= 28; spot++) { if (offcnt == offset) break; offcnt++; } // check to see if got to the offset point or out of pages if (offcnt == offset) break; // else get another page FindEmpties(portnum,SNum,&BM[0],&avail,&next); // decrement the number of pages available mavail -= 28; if (mavail < 0 || avail == 0xFF) { OWERROR(OWERROR_OUT_OF_SPACE); return FALSE; } // write the pointer byte if(!WriteJobByte(portnum,SNum,pg,29,avail,0)) return FALSE; // set bitmap to claim that new page if(!BitMapChange(portnum,SNum,avail,1,&BM[0])) return FALSE; pg = avail; spot = 1; offcnt++; } } // Now should be able to write data at 'spot' on page 'pg' if((*len != 0) && (Han[hnd].Ext == 100)) { cnt = 0; for (;;) { // get the 'zeros' flag op = (operation == APPEND) ? 0 : 1; // set bitmap to claim the page if(!BitMapChange(portnum,SNum,pg,1,&BM[0])) return FALSE; // loop to write the rest of the page or until done for (; spot <= 28; spot++) { // write a byte to the program job list if(!WriteJobByte(portnum,SNum,pg,spot,buf[cnt++],op)) return FALSE; // check to see if done if (cnt >= *len) { // first write the bitmap before ending with success if(!WriteBitMap(portnum,SNum,&BM[0])) return FALSE; // reset read flag so could read file now Han[hnd].Read = 1; return TRUE; } } // data more than one page. spot = 1; FindEmpties(portnum,SNum,&BM[0],&avail,&next); if(!WriteJobByte(portnum,SNum,pg,29,avail,0)) return FALSE; pg = avail; } } else { if(!BitMapChange(portnum,SNum,pg,1,&BM[0])) return FALSE; else if(!setJobWritten(portnum,SNum,pg,PJOB_ADD)) return FALSE; return TRUE; } // set the redirection byte // else get another page FindEmpties(portnum,SNum,&BM[0],&avail,&next); // decrement the number of pages available mavail -= 28; if (mavail < 0 || avail == 0xFF) { OWERROR(OWERROR_OUT_OF_SPACE); return FALSE; } // write the pointer byte if(!WriteJobByte(portnum,SNum,pg,29,avail,0)) return FALSE; pg = avail; spot = 1; return TRUE; } //-------------------------------------------------------------------------- // Terminate an 'add' file by adding the length and CRC16 bytes to each // page. // // return: 1(SUCCESS) : 'add' file terminated // >0 : tmex error // SMALLINT owTerminateAddFile(int portnum, uchar *SNum, FileEntry *flname) { short i,j; uchar pgbuf[34],buf[32],pgcnt; PAGE_TYPE pg=0; int flag; FileInfo Info; // check device type if(!ValidRom(portnum,SNum)) return FALSE; // check to see if filename passed is valid if ((Valid_FileName(flname) == 0) || ((flname->Ext & 0x7F) != 100)) { OWERROR(OWERROR_XBAD_FILENAME); return FALSE; } // check existing open files with same the name (3.10) // automatically close the file for (i = 0; i < 4; i++) { if (Han[i].Name[0] != 0) { for (j = 0; j < 4; j++) if ((Han[i].Name[j] & 0x7F) != flname->Name[j]) break; if (j == 4 && ((Han[i].Ext & 0x7F) == flname->Ext)) { Han[i].Name[0] = 0; // release the handle break; } } } // depending on the directory set the first page to look for entry if(CD.ne == 0) pg = 0; else pg = CD.Entry[CD.ne-1].page; // copy filename over to info packet for (i = 0; i < 4; i++) Info.Name[i] = flname->Name[i]; Info.Ext = flname->Ext; // check directory list to find the location of the file name if(!FindDirectoryInfo(portnum,SNum,&pg,&Info)) return FALSE; // check to see if the file is aleady terminated if (Info.NumPgs != 0) { OWERROR(OWERROR_ADDFILE_TERMINATED); return FALSE; } pg = Info.Spage; pgcnt = 0; for (;;) { // loop while error during read up to 3 count if(!owReadPageExtraCRC(0,portnum,SNum,pg,&pgbuf[0],&pgbuf[32])) return FALSE; // read success, check to see if already terminated if (pgbuf[0] != 0xFF || pgbuf[30] != 0xFF || pgbuf[31] != 0xFF || pgbuf[32] != 0xFF) { OWERROR(OWERROR_ADDFILE_TERMINATED); return FALSE; } // count the page pgcnt++; // terminte the page in the program job if(!TerminatePage(portnum,SNum,pg,&pgbuf[0])) return FALSE; // check for end of file if (pgbuf[29] == 0xFF) { // write the last page pointer to 0 if(!WriteJobByte(portnum,SNum,pg,29,0x00,0)) return FALSE; break; } // get the next page in the list pg = pgbuf[29]; } // read the directory page that the entry to change length if(!Read_Page(portnum,SNum,&buf[0],REGMEM,&Info.Dpage,&flag)) return FALSE; // set the number of pages in the buffer for the file buf[Info.Offset+6] = pgcnt; // write back the directory page with the new name if(!Write_Page(portnum,SNum,&buf[0],Info.Dpage,flag)) return FALSE; return TRUE; }