tools/fsusb/rjlhex.c
author slime@unimatrix01.gamma-quadrant.de
Tue, 29 Jan 2008 22:31:52 +0100
changeset 2 2f55e5dd591d
permissions -rw-r--r--
inital checkin
     1 /*
     2 ** This file is part of fsusb_picdem
     3 **
     4 ** fsusb_picdem is free software; you can redistribute it and/or
     5 ** modify it under the terms of the GNU General Public License as
     6 ** published by the Free Software Foundation; either version 2 of the
     7 ** License, or (at your option) any later version.
     8 **
     9 ** fsusb_picdem is distributed in the hope that it will be useful, but
    10 ** WITHOUT ANY WARRANTY; without even the implied warranty of
    11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    12 ** General Public License for more details.
    13 **
    14 ** You should have received a copy of the GNU General Public License
    15 ** along with fsusb_picdem; if not, write to the Free Software
    16 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    17 ** 02110-1301, USA
    18 */
    19 
    20 
    21 #include <stdio.h>
    22 #include <stdlib.h>
    23 #include <string.h>
    24 #include <ctype.h>
    25 #include "rjlhex.h"
    26 
    27 
    28 
    29 /*
    30  * hex_open: Create a hex_file from a FILE *
    31  *
    32  * f is assumed to already be open for reading, with the
    33  *  pointer at the start of the file.
    34  */
    35 hex_file *hex_open(FILE *f)
    36 {
    37   hex_file *r;
    38 
    39   if(f==NULL) {
    40     return NULL;
    41   }
    42 
    43   r=malloc(sizeof(hex_file));
    44   if(r == NULL) {
    45     return NULL;
    46   }
    47 
    48   r->f=f;
    49   r->addr=0;
    50   return r;
    51 }
    52 
    53 
    54 /*
    55  * hex_raw_read: Create a hex_record from the next line of f
    56  *
    57  * f is assumed to already be open for reading, with the
    58  *  pointer at the start of the line to parse.
    59  */
    60 hex_record *hex_raw_read(FILE *f)
    61 {
    62   hex_record *r;
    63   hex_record *tempr;
    64   char *s=NULL;
    65   size_t ssize=0;
    66   char temps[10];
    67   int i;
    68   unsigned char check=0;
    69 
    70 
    71 
    72   if(f == NULL) {
    73     return NULL;
    74   }
    75 
    76   r=malloc(sizeof(hex_record));
    77   if(r == NULL) {
    78     return NULL;
    79   }
    80 
    81 
    82 
    83   getline(&s, &ssize, f);
    84 
    85   // :llaaaatt[dd...]cc
    86 
    87   // :
    88   if(strlen(s)<1 || s[0] != ':') {
    89     free(r);
    90     free(s);
    91     return NULL;
    92   }
    93 
    94 
    95 
    96   // ll
    97   if(strlen(s)<3 || !isxdigit(s[1]) || !isxdigit(s[2])) {
    98     free(r);
    99     free(s);
   100     return NULL;
   101   }
   102   sprintf(temps, "0x%c%c", s[1], s[2]);
   103   r->datlen=strtol(temps, NULL, 16);
   104   check += r->datlen;
   105 
   106 
   107 
   108   if(strlen(s) < r->datlen*2 + 11) {
   109     free(r);
   110     free(s);
   111     return NULL;
   112   }
   113 
   114   for(i=3;i<r->datlen*2+11;i++) {
   115     if(!isxdigit(s[i])) {
   116       free(r);
   117       free(s);
   118       return NULL;
   119     }
   120   }
   121   tempr=realloc(r, sizeof(hex_record) + r->datlen*2);
   122   if(tempr == NULL) {
   123     free(r);
   124     free(s);
   125     return NULL;
   126   }
   127   r=tempr;
   128 
   129 
   130 
   131   // aaaa
   132 
   133   sprintf(temps, "0x%c%c%c%c", s[3], s[4], s[5], s[6]);
   134   r->addr=strtol(temps, NULL, 16);
   135 
   136   sprintf(temps, "0x%c%c", s[3], s[4]);
   137   check+=strtol(temps, NULL, 16);
   138   sprintf(temps, "0x%c%c", s[5], s[6]);
   139   check+=strtol(temps, NULL, 16);
   140 
   141 
   142 
   143   // tt
   144 
   145   sprintf(temps, "0x%c%c", s[7], s[8]);
   146   r->type=strtol(temps, NULL, 16);
   147   check += r->type;
   148 
   149 
   150 
   151   // [dd...]
   152 
   153   for(i=0;i<r->datlen;i++) {
   154     sprintf(temps, "0x%c%c", s[9+2*i], s[10+2*i]);
   155     r->data[i]=strtol(temps, NULL, 16);
   156     check+=r->data[i];
   157   }
   158 
   159 
   160 
   161   // cc
   162   sprintf(temps, "0x%c%c", s[r->datlen*2+9], s[r->datlen*2+10]);
   163   r->checksum=strtol(temps, NULL, 16);
   164 
   165   //  printf("check is %x, 2c of check is %x\n", check, (unsigned char)(-((int)check)));
   166   //  printf("checksum wanted is %x\n", r->checksum);
   167 
   168   free(s);
   169 
   170   if((unsigned char)(-((int)check)) != r->checksum) {
   171     printf("hex_raw_read(): BAD CHECKSUM: got %x, wanted %x\n",
   172            (unsigned char)(-((int)check)), r->checksum);
   173     free(r);
   174     return NULL;
   175   }
   176 
   177   return r;
   178 
   179 }
   180 
   181 
   182 /*
   183  * hex_read: Return the next hex_record from f
   184  */
   185 hex_record *hex_read(hex_file *f)
   186 {
   187   hex_record *r;
   188 
   189 
   190 
   191   if(f == NULL) {
   192     return NULL;
   193   }
   194 
   195 
   196 
   197   r=hex_raw_read(f->f);
   198   if(r == NULL) {
   199     return NULL;
   200   }
   201 
   202 
   203 
   204   switch(r->type) {
   205   case 0: // data
   206     r->addr += f->addr;
   207     break;
   208 
   209 
   210   case 1: // EOF
   211     /*
   212      * Do nothing, although something could be done on these
   213      *
   214      * It'll only get more data past this on a funny file,
   215      *  and the assumption is that user-supplied files are usually ok
   216      *  (which may not be a good assumption)
   217      */
   218     break;
   219 
   220 
   221   case 2: // hex86 address
   222     f->addr = (r->data[0] << 12) + (r->data[1] << 4); // endianness?
   223     break;
   224 
   225 
   226   case 4: // hex386 address
   227     f->addr = (r->data[0] << 24) + (r->data[1] << 16); // endianness?
   228     break;
   229   }
   230 
   231 
   232 
   233   return r;
   234 }