2 Copyright 2009, Ifcaro & volca
3 Licenced under Academic Free License version 3.0
4 Review OpenUsbLd README & LICENSE files for further details.
7 #include "include/usbld.h"
8 #include "include/util.h"
9 #include "include/ioman.h"
12 #define CONFIG_INDEX_OPL 0
13 #define CONFIG_INDEX_COMPAT 1
14 #define CONFIG_INDEX_DNAS 2
15 #define CONFIG_INDEX_VMC 3
16 #define CONFIG_INDEX_LAST 4
17 #define CONFIG_INDEX_APPS 5
18 #define CONFIG_INDEX_VMODE 6
20 static config_set_t configFiles
[CONFIG_FILE_NUM
];
21 static char configPath
[255] = "mc?:SYS-CONF/IPCONFIG.DAT";
23 static int strToColor(const char *string
, unsigned char *color
) {
29 if (!string
|| !*string
) return 0;
30 if (string
[0]!='#') return 0;
35 int fh
= fromHex(*string
);
37 color
[n
] = color
[n
] * 16 + fh
;
42 // Two characters per color
56 /// true if given a whitespace character
58 return c
== ' ' || c
== '\t';
61 static int splitAssignment(char* line
, char* key
, size_t keymax
, char* val
, size_t valmax
) {
63 for (;isWS(*line
); ++line
);
66 // If found, the text before is key, after is val.
67 // Otherwise malformed string is encountered
69 char* eqpos
= strchr(line
, '=');
72 // copy the name and the value
73 size_t keylen
= min(keymax
, eqpos
- line
);
75 strncpy(key
, line
, keylen
);
79 size_t vallen
= min(valmax
, strlen(line
) - (eqpos
- line
));
80 strncpy(val
, eqpos
, vallen
);
86 static int parsePrefix(char* line
, char* prefix
) {
88 // If found, the text before is key, after is val.
89 // Otherwise malformed string is encountered
90 char* colpos
= strchr(line
, ':');
92 if (colpos
&& colpos
!= line
) {
93 // copy the name and the value
94 strncpy(prefix
, line
, colpos
- line
);
102 static int configKeyValidate(const char* key
) {
103 if (strlen(key
) == 0)
106 return !strchr(key
, '=');
109 static struct config_value_t
* allocConfigItem(const char* key
, const char* val
) {
110 struct config_value_t
* it
= (struct config_value_t
*) malloc(sizeof(struct config_value_t
));
111 strncpy(it
->key
, key
, 32);
112 it
->key
[min(strlen(key
), 31)] = '\0';
113 strncpy(it
->val
, val
, 255);
114 it
->val
[min(strlen(val
), 254)] = '\0';
120 /// Low level key addition. Does not check for uniqueness.
121 static void addConfigValue(config_set_t
* configSet
, const char* key
, const char* val
) {
122 if (!configSet
->tail
) {
123 configSet
->head
= allocConfigItem(key
, val
);
124 configSet
->tail
= configSet
->head
;
126 configSet
->tail
->next
= allocConfigItem(key
, val
);
127 configSet
->tail
= configSet
->tail
->next
;
131 static struct config_value_t
* getConfigItemForName(config_set_t
* configSet
, const char* name
) {
132 struct config_value_t
* val
= configSet
->head
;
135 if (strncmp(val
->key
, name
, 32) == 0)
144 void configInit(char *prefix
) {
148 snprintf(configPath
, 255, "%s/IPCONFIG.DAT", prefix
);
152 snprintf(path
, 255, "%s/conf_opl.cfg", prefix
);
153 configAlloc(CONFIG_OPL
, &configFiles
[CONFIG_INDEX_OPL
], path
);
154 snprintf(path
, 255, "%s/conf_compatibility.cfg", prefix
);
155 configAlloc(CONFIG_COMPAT
, &configFiles
[CONFIG_INDEX_COMPAT
], path
);
156 snprintf(path
, 255, "%s/conf_dnas.cfg", prefix
);
157 configAlloc(CONFIG_DNAS
, &configFiles
[CONFIG_INDEX_DNAS
], path
);
158 snprintf(path
, 255, "%s/conf_vmc.cfg", prefix
);
159 configAlloc(CONFIG_VMC
, &configFiles
[CONFIG_INDEX_VMC
], path
);
160 snprintf(path
, 255, "%s/conf_last.cfg", prefix
);
161 configAlloc(CONFIG_LAST
, &configFiles
[CONFIG_INDEX_LAST
], path
);
162 snprintf(path
, 255, "%s/conf_apps.cfg", prefix
);
163 configAlloc(CONFIG_APPS
, &configFiles
[CONFIG_INDEX_APPS
], path
);
164 snprintf(path
, 255, "%s/conf_vmode.cfg", prefix
);
165 configAlloc(CONFIG_VMODE
, &configFiles
[CONFIG_INDEX_VMODE
], path
);
170 while(index
< CONFIG_FILE_NUM
) {
171 config_set_t
*configSet
= &configFiles
[index
];
173 configClear(configSet
);
174 free(configSet
->filename
);
175 configSet
->filename
= NULL
;
180 config_set_t
*configAlloc(int type
, config_set_t
*configSet
, char *fileName
) {
182 configSet
= (config_set_t
*) malloc(sizeof(config_set_t
));
184 configSet
->type
= type
;
185 configSet
->head
= NULL
;
186 configSet
->tail
= NULL
;
188 int length
= strlen(fileName
) + 1;
189 configSet
->filename
= (char*) malloc(length
* sizeof(char));
190 memcpy(configSet
->filename
, fileName
, length
);
192 configSet
->filename
= NULL
;
193 configSet
->modified
= 0;
197 void configFree(config_set_t
*configSet
) {
198 configClear(configSet
);
199 free(configSet
->filename
);
204 config_set_t
*configGetByType(int type
) {
206 while(index
< CONFIG_FILE_NUM
) {
207 config_set_t
*configSet
= &configFiles
[index
];
209 if (configSet
->type
== type
)
216 int configSetStr(config_set_t
* configSet
, const char* key
, const char* value
) {
217 if (!configKeyValidate(key
))
220 struct config_value_t
*it
= getConfigItemForName(configSet
, key
);
223 if (strncmp(it
->val
, value
, 255) != 0) {
224 strncpy(it
->val
, value
, 255);
225 it
->val
[min(strlen(value
), 254)] = '\0';
226 if (it
->key
[0] != '#')
227 configSet
->modified
= 1;
230 addConfigValue(configSet
, key
, value
);
232 configSet
->modified
= 1;
238 // sets the value to point to the value str in the config. Do not overwrite - it will overwrite the string in config
239 int configGetStr(config_set_t
* configSet
, const char* key
, char** value
) {
240 if (!configKeyValidate(key
))
243 struct config_value_t
*it
= getConfigItemForName(configSet
, key
);
252 int configSetInt(config_set_t
* configSet
, const char* key
, const int value
) {
254 snprintf(tmp
, 12, "%d", value
);
255 return configSetStr(configSet
, key
, tmp
);
258 int configGetInt(config_set_t
* configSet
, char* key
, int* value
) {
260 if (configGetStr(configSet
, key
, &valref
)) {
261 *value
= atoi(valref
);
268 int configSetColor(config_set_t
* configSet
, const char* key
, unsigned char* color
) {
270 snprintf(tmp
, 8, "#%02X%02X%02X", color
[0], color
[1], color
[2]);
271 return configSetStr(configSet
, key
, tmp
);
274 int configGetColor(config_set_t
* configSet
, const char* key
, unsigned char* color
) {
276 if (configGetStr(configSet
, key
, &valref
)) {
277 strToColor(valref
, color
);
284 int configRemoveKey(config_set_t
* configSet
, const char* key
) {
285 if (!configKeyValidate(key
))
288 struct config_value_t
* val
= configSet
->head
;
289 struct config_value_t
* prev
= NULL
;
292 if (strncmp(val
->key
, key
, 32) == 0) {
294 configSet
->modified
= 1;
296 if (val
== configSet
->tail
)
297 configSet
->tail
= prev
;
305 free(configSet
->head
);
306 configSet
->head
= val
;
317 void configReadIP() {
318 int fd
= openFile(configPath
, O_RDONLY
);
321 int size
= getFileSize(fd
);
322 fioRead(fd
, &ipconfig
, size
);
325 sscanf(ipconfig
, "%d.%d.%d.%d %d.%d.%d.%d %d.%d.%d.%d", &ps2_ip
[0], &ps2_ip
[1], &ps2_ip
[2], &ps2_ip
[3],
326 &ps2_netmask
[0], &ps2_netmask
[1], &ps2_netmask
[2], &ps2_netmask
[3],
327 &ps2_gateway
[0], &ps2_gateway
[1], &ps2_gateway
[2], &ps2_gateway
[3]);
333 void configWriteIP() {
334 int fd
= openFile(configPath
, O_WRONLY
| O_CREAT
);
337 sprintf(ipconfig
, "%d.%d.%d.%d %d.%d.%d.%d %d.%d.%d.%d\r\n", ps2_ip
[0], ps2_ip
[1], ps2_ip
[2], ps2_ip
[3],
338 ps2_netmask
[0], ps2_netmask
[1], ps2_netmask
[2], ps2_netmask
[3],
339 ps2_gateway
[0], ps2_gateway
[1], ps2_gateway
[2], ps2_gateway
[3]);
341 fioWrite(fd
, ipconfig
, strlen(ipconfig
));
346 void configGetDiscID(char* startup
, char* discID
) {
349 snprintf(gkey
, 255, "%s_discID", startup
);
350 if (configGetStr(&configFiles
[CONFIG_INDEX_DNAS
], gkey
, &valref
))
351 strncpy(discID
, valref
, 32);
356 void configSetDiscID(char* startup
, const char *discID
) {
358 snprintf(gkey
, 255, "%s_discID", startup
);
359 configSetStr(&configFiles
[CONFIG_INDEX_DNAS
], gkey
, discID
);
362 void configRemoveDiscID(char* startup
) {
364 snprintf(gkey
, 255, "%s_discID", startup
);
365 configRemoveKey(&configFiles
[CONFIG_INDEX_DNAS
], gkey
);
368 // dst has to have 5 bytes space
369 void configGetDiscIDBinary(char* startup
, void* dst
) {
374 snprintf(gkey
, 255, "%s_discID", startup
);
375 if (configGetStr(&configFiles
[CONFIG_INDEX_DNAS
], gkey
, &gid
)) {
376 // convert from hex to binary
379 while (*gid
&& p
< 10) {
382 while (dv
< 0 && *gid
) // skip spaces, etc
383 dv
= fromHex(*(gid
++));
388 *cdst
= *cdst
* 16 + dv
;
395 int configRead(config_set_t
* configSet
) {
396 file_buffer_t
* fileBuffer
= openFileBuffer(configSet
->filename
, O_RDONLY
, 0, 4096);
398 LOG("No config %s.\n", configSet
->filename
);
399 configSet
->modified
= 0;
404 unsigned int lineno
= 0;
407 memset(prefix
, 0, sizeof(prefix
));
409 while (readFileBuffer(fileBuffer
, &line
)) {
412 char key
[32], val
[255];
413 memset(key
, 0, sizeof(key
));
414 memset(val
, 0, sizeof(val
));
416 if (splitAssignment(line
, key
, sizeof(key
), val
, sizeof(val
))) {
417 /* if the line does not start with whitespace,
418 * the prefix ends and we have to reset it
421 memset(prefix
, 0, sizeof(prefix
));
423 // insert config value
426 char composedKey
[66];
428 snprintf(composedKey
, 65, "%s_%s", prefix
, key
);
429 composedKey
[65] = '\0';
431 configSetStr(configSet
, composedKey
, val
);
433 configSetStr(configSet
, key
, val
);
435 } else if (parsePrefix(line
, prefix
)) {
436 // prefix is set, that's about it
438 LOG("Malformed config file '%s' line %d: '%s'\n", configSet
->filename
, lineno
, line
);
441 closeFileBuffer(fileBuffer
);
442 configSet
->modified
= 0;
443 return configSet
->type
;
446 int configWrite(config_set_t
* configSet
) {
447 if (configSet
->modified
) {
448 file_buffer_t
* fileBuffer
= openFileBuffer(configSet
->filename
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0, 4096);
451 struct config_value_t
* cur
= configSet
->head
;
454 if ((cur
->key
[0] != '\0') && (cur
->key
[0] != '#')) {
455 snprintf(line
, 512, "%s=%s\r\n", cur
->key
, cur
->val
); // add windows CR+LF (0x0D 0x0A)
456 writeFileBuffer(fileBuffer
, line
, strlen(line
));
463 closeFileBuffer(fileBuffer
);
464 configSet
->modified
= 0;
472 void configClear(config_set_t
* configSet
) {
473 while (configSet
->head
) {
474 struct config_value_t
* cur
= configSet
->head
;
475 configSet
->head
= cur
->next
;
480 configSet
->head
= NULL
;
481 configSet
->tail
= NULL
;
482 configSet
->modified
= 1;
485 int configGetCompatibility(char* startup
, int mode
, int *dmaMode
) {
487 snprintf(gkey
, 255, "%s_%d", startup
, mode
);
489 unsigned int compatMode
;
490 if (!configGetInt(&configFiles
[CONFIG_INDEX_COMPAT
], gkey
, &compatMode
))
494 *dmaMode
= 7; // defaulting to UDMA 4
495 snprintf(gkey
, 255, "%s_DMA", startup
);
496 configGetInt(&configFiles
[CONFIG_INDEX_COMPAT
], gkey
, dmaMode
);
502 void configSetCompatibility(char* startup
, int mode
, int compatMode
, int dmaMode
) {
504 snprintf(gkey
, 255, "%s_%d", startup
, mode
);
505 if (compatMode
== 0) // means we want to delete the setting
506 configRemoveKey(&configFiles
[CONFIG_INDEX_COMPAT
], gkey
);
508 configSetInt(&configFiles
[CONFIG_INDEX_COMPAT
], gkey
, compatMode
);
511 snprintf(gkey
, 255, "%s_DMA", startup
);
512 if (dmaMode
== 7) // UDMA 4 is the default so don't save it (useless lines into the conf file)
513 configRemoveKey(&configFiles
[CONFIG_INDEX_COMPAT
], gkey
);
515 configSetInt(&configFiles
[CONFIG_INDEX_COMPAT
], gkey
, dmaMode
);
519 int configReadMulti(int types
) {
522 if (CONFIG_OPL
& types
)
526 while(index
< CONFIG_FILE_NUM
) {
527 config_set_t
*configSet
= &configFiles
[index
];
529 if (configSet
->type
& types
) {
530 configClear(configSet
);
531 result
|= configRead(configSet
);
539 int configWriteMulti(int types
) {
542 if ((CONFIG_OPL
& types
) && gIPConfigChanged
)
546 while(index
< CONFIG_FILE_NUM
) {
547 config_set_t
*configSet
= &configFiles
[index
];
549 if (configSet
->type
& types
)
550 result
+= configWrite(configSet
);
558 void configGetVMC(char* startup
, char* vmc
, int mode
, int slot
) {
561 snprintf(gkey
, 255, "%s_%d_%d", startup
, mode
, slot
);
562 if (configGetStr(&configFiles
[CONFIG_INDEX_VMC
], gkey
, &valref
))
563 strncpy(vmc
, valref
, 32);
568 void configSetVMC(char* startup
, const char* vmc
, int mode
, int slot
) {
571 configRemoveVMC(startup
, mode
, slot
);
574 snprintf(gkey
, 255, "%s_%d_%d", startup
, mode
, slot
);
575 configSetStr(&configFiles
[CONFIG_INDEX_VMC
], gkey
, vmc
);
578 void configRemoveVMC(char *startup
, int mode
, int slot
) {
580 snprintf(gkey
, 255, "%s_%d_%d", startup
, mode
, slot
);
581 configRemoveKey(&configFiles
[CONFIG_INDEX_VMC
], gkey
);