1 /*********************************************************************
2  *
3  *   LPC Parts identification
4  *
5  *
6  *  Copyright (C) 2012 Nathael Pajani <nathael.pajani@nathael.net>
7  *
8  *  This program is free software: you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation, either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  *
21  *********************************************************************/
23 #include <stdint.h> /* uint64_t and uint32_t */
24 #include <stdlib.h> /* NULL */
25 #include <stddef.h> /* For offsetof */
26 #include <stdio.h>  /* perror(), fopen(), fclose() */
27 #include <errno.h>
29 #include "parts.h"
31 #define CONF_READ_BUF_SIZE 250
33 /* When looking for parts description in a file ee do allocate (malloc) two memory
34  *   chunks which we will never free.
35  * The user should free part_desc->name and part_desc when they are no more useful
36  */
37 struct part_desc* find_part_in_file(uint64_t dev_id, char* parts_file_name)
38 {
39         FILE* parts_file = NULL;
40         unsigned int i = 0;
41         unsigned int line = 0; /* Store current line number when reading file */
42         struct part_desc* part = malloc(sizeof(struct part_desc));
44         parts_file = fopen(parts_file_name, "r");
45         if (parts_file == NULL) {
46                 perror("Unable to open file to read LPC descriptions !");
47                 return NULL;
48         }
50         while (1) {
51                 char buf[CONF_READ_BUF_SIZE];
52                 char* endp = NULL;
53                 uint32_t* part_values = NULL;
54                 unsigned int nval = 0;
56                 if (fgets(buf, CONF_READ_BUF_SIZE, parts_file) == NULL) {
57                         printf("Part not found before end of parts description file.\n");
58                         goto out_err_1;
59                 }
60                 line++; /* Store current line number to help parts description file correction */
61                 if (buf[0] == '#' || buf[0] == '\n') {
62                         /* skip comments */
63                         continue;
64                 }
65                 part->part_id = strtoul(buf, &endp, 0);
66                 if (part->part_id != dev_id) {
67                         continue;
68                 }
69                 printf("Part ID 0x%08x found on line %d\n", (unsigned int)part->part_id, line);
70                 /* We found the right part ID, get all the data */
71                 part->name = malloc(PART_NAME_LENGTH);
72                 /* Part names must start with "LPC" */
73                 while ((*endp != '\0') && (*endp != 'L')) {
74                         endp++;
75                 }
76                 /* Copy part name */
77                 for (i = 0; i < PART_NAME_LENGTH; i++) {
78                         if (endp[i] == '\0') {
79                                 /* Hey, we need the part description after the name */
80                                 printf("Malformed parts description file at line %d, nothing after part name.\n", line);
81                                 goto out_err_2;
82                         }
83                         if (endp[i] == ',') {
84                                 break;
85                         }
86                         part->name[i] = endp[i];
87                 }
88                 if ((i == PART_NAME_LENGTH) && (endp[i] != ',')) {
89                         printf("Malformed parts description file at line %d, part name too long.\n", line);
90                                 goto out_err_2;
91                 }
92                 endp += i;
93                 /* Get all the values */
94                 nval = ((sizeof(struct part_desc) - offsetof(struct part_desc, flash_base)) / sizeof(uint32_t));
95                 part_values = &(part->flash_base); /* Use a table to read the data, we do not care of what the data is */
96                 for (i = 0; i < nval; i++) {
97                         errno = 0;
98                         part_values[i] = strtoul((endp + 1), &endp, 0);
99                         if ((part_values[i] == 0) && (errno == EINVAL)) {
100                                 printf("Malformed parts description file at line %d, error reading value %d\n", line, i);
101                                 goto out_err_2;
102                         }
103                 }
104                 /* Done, retrun the part ! */
105                 return part;
106         }
109 out_err_2:
110         free(part->name);
111 out_err_1:
112         free(part);
113         fclose(parts_file);
114         return NULL;