/alps/pcitool

To get this branch, use:
bzr branch http://darksoft.org/webbzr/alps/pcitool

« back to all changes in this revision

Viewing changes to pcilib/xml.c

  • Committer: Suren A. Chilingaryan
  • Date: 2016-03-08 01:15:51 UTC
  • Revision ID: csa@suren.me-20160308011551-z7qvf08s6daer4l2
Support XML configuration of device models

Show diffs side-by-side

added added

removed removed

Lines of Context:
49
49
#define REGISTERS_PATH ((xmlChar*)"./register")                                 /**< all standard registers nodes */
50
50
#define BIT_REGISTERS_PATH ((xmlChar*)"./field")                                /**< all bits registers nodes */
51
51
#define REGISTER_VIEWS_PATH ((xmlChar*)"./view")                                /**< supported register & field views */
52
 
#define TRANSFORM_VIEWS_PATH ((xmlChar*)"/model/transform")             /**< path to complete nodes of views */
 
52
#define TRANSFORM_VIEWS_PATH ((xmlChar*)"/model/transform")                     /**< path to complete nodes of views */
53
53
#define ENUM_VIEWS_PATH ((xmlChar*)"/model/enum")                               /**< path to complete nodes of views */
54
54
#define ENUM_ELEMENTS_PATH ((xmlChar*)"./name")                                 /**< all elements in the enum */
55
55
#define UNITS_PATH ((xmlChar*)"/model/unit")                                    /**< path to complete nodes of units */
56
 
#define UNIT_TRANSFORMS_PATH ((xmlChar*)"./transform")                  /**< all transforms of the unit */
57
 
 
 
56
#define UNIT_TRANSFORMS_PATH ((xmlChar*)"./transform")                          /**< all transforms of the unit */
58
57
 
59
58
 
60
59
static const char *pcilib_xml_bank_default_format = "0x%lx";
892
891
    return 0;
893
892
}
894
893
 
895
 
static int pcilib_xml_load_xsd_file(pcilib_t *ctx, char *xsd_filename, xmlSchemaPtr *schema, xmlSchemaValidCtxtPtr *validator) {
 
894
static int pcilib_xml_load_xsd_file(pcilib_t *ctx, const char *xsd_filename, xmlSchemaPtr *schema, xmlSchemaValidCtxtPtr *validator) {
896
895
    int err;
897
896
 
898
897
    xmlSchemaParserCtxtPtr ctxt;
923
922
    *validator  = xmlSchemaNewValidCtxt(*schema);
924
923
    if (!*validator) {
925
924
        xmlErrorPtr xmlerr = xmlGetLastError();
 
925
        xmlSchemaFree(*schema); *schema = NULL;
926
926
        if (xmlerr) pcilib_error("xmlSchemaNewValidCtxt reported error %d - %s", xmlerr->code, xmlerr->message);
927
927
        else pcilib_error("Failed to create a validation context");
928
928
        return PCILIB_ERROR_FAILED;
931
931
    err = xmlSchemaSetValidOptions(*validator, XML_SCHEMA_VAL_VC_I_CREATE);
932
932
    if (err) {
933
933
        xmlErrorPtr xmlerr = xmlGetLastError();
 
934
        xmlSchemaFreeValidCtxt(*validator); *validator = NULL;
 
935
        xmlSchemaFree(*schema); *schema = NULL;
934
936
        if (xmlerr) pcilib_error("xmlSchemaSetValidOptions reported error %d - %s", xmlerr->code, xmlerr->message);
935
937
        else pcilib_error("Failed to configure the validation context to populate default attributes");
936
938
        return PCILIB_ERROR_FAILED;
939
941
    return 0;
940
942
}
941
943
 
942
 
 
943
 
static int pcilib_xml_load_xsd(pcilib_t *ctx, char *model_dir) {
 
944
/*
 
945
static xmlDocPtr pcilib_xml_load_xml_file(pcilib_t *ctx, const char *xsd_filename, const char *xml_filename) {
 
946
    int err;
 
947
    xmlDocPtr doc;
 
948
    xmlSchemaPtr schema;
 
949
    xmlSchemaValidCtxtPtr validator;
 
950
    xmlParserCtxtPtr parser;
 
951
 
 
952
    err = pcilib_xml_load_xsd_file(ctx, xsd_filename, &schema, &validator);
 
953
    if (err) {
 
954
        pcilib_error("Error (%i) parsing the devices schema (%s)", err, xsd_filename);
 
955
        return NULL;
 
956
    }
 
957
 
 
958
    parser = xmlNewParserCtxt();
 
959
    if (!parser) {
 
960
        xmlErrorPtr xmlerr = xmlGetLastError();
 
961
        xmlSchemaFree(schema);
 
962
        xmlSchemaFreeValidCtxt(validator);
 
963
        if (xmlerr) pcilib_error("xmlNewParserCtxt reported error %d (%s)", xmlerr->code, xmlerr->message);
 
964
        else pcilib_error("Failed to create an XML parser context");
 
965
        return NULL;
 
966
    }
 
967
 
 
968
    doc = xmlCtxtReadFile(parser, xml_filename, NULL, 0);
 
969
    if (!doc) {
 
970
        xmlErrorPtr xmlerr = xmlGetLastError();
 
971
        xmlFreeParserCtxt(parser);
 
972
        xmlSchemaFree(schema);
 
973
        xmlSchemaFreeValidCtxt(validator);
 
974
        if (xmlerr) pcilib_error("Error parsing %s, xmlCtxtReadFile reported error %d - %s", xml_filename, xmlerr->code, xmlerr->message);
 
975
        else pcilib_error("Error parsing %s", xml_filename);
 
976
        return NULL;
 
977
    }
 
978
    
 
979
    err = xmlSchemaValidateDoc(validator, doc);
 
980
    if (err) {
 
981
        xmlErrorPtr xmlerr = xmlCtxtGetLastError(parser);
 
982
        xmlFreeDoc(doc);
 
983
        xmlFreeParserCtxt(parser);
 
984
        xmlSchemaFree(schema);
 
985
        xmlSchemaFreeValidCtxt(validator);
 
986
        if (xmlerr) pcilib_error("Error validating %s, xmlSchemaValidateDoc reported error %d - %s", xml_filename, xmlerr->code, xmlerr->message);
 
987
        else pcilib_error("Error validating %s", xml_filename);
 
988
        return NULL;
 
989
    }
 
990
 
 
991
    xmlFreeParserCtxt(parser);
 
992
    xmlSchemaFree(schema);
 
993
    xmlSchemaFreeValidCtxt(validator);
 
994
 
 
995
    return doc;
 
996
}
 
997
*/
 
998
 
 
999
static xmlXPathObjectPtr pcilib_xml_eval_xpath_expression(pcilib_t *ctx, xmlDocPtr doc, const xmlChar *query) {
 
1000
    xmlXPathContextPtr xpath;
 
1001
    xmlXPathObjectPtr nodes;
 
1002
 
 
1003
    xpath = xmlXPathNewContext(doc);
 
1004
    if (!xpath) {
 
1005
        xmlErrorPtr xmlerr = xmlGetLastError();
 
1006
        if (xmlerr) pcilib_error("xmlXpathNewContext reported error %d - %s", xmlerr->code, xmlerr->message);
 
1007
        else pcilib_error("Error creating XPath context");
 
1008
        return NULL;
 
1009
    }
 
1010
 
 
1011
    nodes = xmlXPathEvalExpression(query, xpath);
 
1012
    if (!nodes) {
 
1013
        xmlErrorPtr xmlerr = xmlGetLastError();
 
1014
        xmlXPathFreeContext(xpath);
 
1015
        if (xmlerr) pcilib_error("Failed to parse XPath expression %s, xmlXPathEvalExpression reported error %d - %s", query, xmlerr->code, xmlerr->message);
 
1016
        else pcilib_error("Failed to parse XPath expression %s", query);
 
1017
        return NULL;
 
1018
    }
 
1019
 
 
1020
    xmlXPathFreeContext(xpath);
 
1021
    return nodes;
 
1022
}
 
1023
 
 
1024
static int pcilib_xml_load_xsd(pcilib_t *ctx, const char *model_dir) {
944
1025
    int err;
945
1026
 
946
1027
    struct stat st;
969
1050
 
970
1051
 
971
1052
 
972
 
static xmlDocPtr pcilib_xml_load_file(pcilib_t *ctx, const char *path, const char *name) {
 
1053
static xmlDocPtr pcilib_xml_load_file(pcilib_t *ctx, xmlParserCtxtPtr parser, xmlSchemaValidCtxtPtr validator, const char *path, const char *name) {
973
1054
    int err;
974
1055
    char *full_name;
975
1056
    xmlDocPtr doc;
982
1063
 
983
1064
    sprintf(full_name, "%s/%s", path, name);
984
1065
 
985
 
    doc = xmlCtxtReadFile(ctx->xml.parser, full_name, NULL, 0);
 
1066
    doc = xmlCtxtReadFile(parser, full_name, NULL, 0);
986
1067
    if (!doc) {
987
 
        xmlErrorPtr xmlerr = xmlCtxtGetLastError(ctx->xml.parser);
 
1068
        xmlErrorPtr xmlerr = xmlCtxtGetLastError(parser);
988
1069
        if (xmlerr) pcilib_error("Error parsing %s, xmlCtxtReadFile reported error %d - %s", full_name, xmlerr->code, xmlerr->message);
989
1070
        else pcilib_error("Error parsing %s", full_name);
990
1071
        return NULL;
991
1072
    }
992
1073
 
993
 
    err = xmlSchemaValidateDoc(ctx->xml.parts_validator, doc);
 
1074
    err = xmlSchemaValidateDoc(validator, doc);
994
1075
    if (err) {
995
 
        xmlErrorPtr xmlerr = xmlCtxtGetLastError(ctx->xml.parser);
 
1076
        xmlErrorPtr xmlerr = xmlCtxtGetLastError(parser);
996
1077
        xmlFreeDoc(doc);
997
1078
        if (xmlerr) pcilib_error("Error validating %s, xmlSchemaValidateDoc reported error %d - %s", full_name, xmlerr->code, xmlerr->message);
998
1079
        else pcilib_error("Error validating %s", full_name);
1002
1083
    return doc;
1003
1084
}
1004
1085
 
 
1086
static xmlDocPtr pcilib_xml_load_model_file(pcilib_t *ctx, const char *path, const char *name) {
 
1087
    return pcilib_xml_load_file(ctx, ctx->xml.parser, ctx->xml.parts_validator, path, name);
 
1088
}
 
1089
 
 
1090
 
1005
1091
static int pcilib_process_xml_internal(pcilib_t *ctx, const char *model, const char *location) {
1006
1092
    int err;
1007
1093
 
1039
1125
        if ((len < 4)||(strcasecmp(file->d_name + len - 4, ".xml"))) continue;
1040
1126
        if (file->d_type != DT_REG) continue;
1041
1127
 
1042
 
        newdoc = pcilib_xml_load_file(ctx, model_path, file->d_name);
 
1128
        newdoc = pcilib_xml_load_model_file(ctx, model_path, file->d_name);
1043
1129
        if (!newdoc) {
1044
1130
            pcilib_error("Error processing XML file %s", file->d_name);
1045
1131
            continue;
1190
1276
        xmlMemoryDump();
1191
1277
    */
1192
1278
}
 
1279
 
 
1280
 
 
1281
char *pcilib_detect_xml_model(pcilib_t *ctx, unsigned int vendor_id, unsigned int device_id) {
 
1282
    int err;
 
1283
    char *model = NULL;
 
1284
    xmlSchemaPtr schema;                                /**< Pointer to the parsed xsd schema */
 
1285
    xmlSchemaValidCtxtPtr validator;                    /**< Pointer to the XML validation context */
 
1286
    xmlParserCtxtPtr parser;                            /**< Pointer to the XML parser context */
 
1287
 
 
1288
    DIR *rep;
 
1289
    struct dirent *file = NULL;
 
1290
    struct stat st;
 
1291
    const char *data_dir;
 
1292
    char *xsd_path, *xml_path;
 
1293
 
 
1294
    xmlXPathObjectPtr nodes;
 
1295
    xmlChar xpath_query[64];
 
1296
 
 
1297
    xmlStrPrintf(xpath_query, sizeof(xpath_query), (xmlChar*)"/devices/device[@vendor=%x and @device=%x]/@model", vendor_id, device_id);
 
1298
 
 
1299
    data_dir = getenv("PCILIB_DATA_DIR");
 
1300
    if (!data_dir) data_dir = PCILIB_DATA_DIR;
 
1301
 
 
1302
    xsd_path = (char*)alloca(strlen(data_dir) + 32);
 
1303
    xml_path = (char*)alloca(strlen(data_dir) + 32);
 
1304
    if ((!xsd_path)||(!xml_path)) {
 
1305
        pcilib_error("Error allocating stack memory");
 
1306
        return NULL;
 
1307
    }
 
1308
 
 
1309
    sprintf(xsd_path, "%s/devices.xsd", data_dir);
 
1310
    sprintf(xml_path, "%s/devices", data_dir);
 
1311
    if (stat(xsd_path, &st)||stat(xml_path, &st)) {
 
1312
        pcilib_info("No XML devices are defined, missing devices schema or list");
 
1313
        return NULL;
 
1314
    }
 
1315
 
 
1316
    parser = xmlNewParserCtxt();
 
1317
    if (!parser) {
 
1318
        xmlErrorPtr xmlerr = xmlGetLastError();
 
1319
        if (xmlerr) pcilib_error("xmlNewParserCtxt reported error %d (%s)", xmlerr->code, xmlerr->message);
 
1320
        else pcilib_error("Failed to create an XML parser context");
 
1321
        return NULL;
 
1322
    }
 
1323
 
 
1324
    err = pcilib_xml_load_xsd_file(ctx, xsd_path, &schema, &validator);
 
1325
    if (err) {
 
1326
        xmlFreeParserCtxt(parser);
 
1327
        pcilib_error("Error (%i) parsing the device schema (%s)", err, xsd_path);
 
1328
        return NULL;
 
1329
    }
 
1330
 
 
1331
    rep = opendir(xml_path);
 
1332
    if (!rep) goto cleanup;
 
1333
 
 
1334
    while ((model == NULL)&&((file = readdir(rep)) != NULL)) {
 
1335
        xmlDocPtr doc;
 
1336
        
 
1337
        size_t len = strlen(file->d_name);
 
1338
        if ((len < 4)||(strcasecmp(file->d_name + len - 4, ".xml"))) continue;
 
1339
        if (file->d_type != DT_REG) continue;
 
1340
 
 
1341
        doc = pcilib_xml_load_file(ctx, parser, validator, xml_path, file->d_name);
 
1342
        if (!doc) continue;
 
1343
 
 
1344
        nodes = pcilib_xml_eval_xpath_expression(ctx, doc, xpath_query);
 
1345
        if (!nodes) {
 
1346
            xmlFreeDoc(doc);
 
1347
            continue;
 
1348
        }
 
1349
 
 
1350
        if (!xmlXPathNodeSetIsEmpty(nodes->nodesetval)) {
 
1351
            xmlNodePtr node = nodes->nodesetval->nodeTab[0];
 
1352
            model = strdup((char*)node->children->content);
 
1353
        }
 
1354
 
 
1355
        xmlXPathFreeObject(nodes);
 
1356
        xmlFreeDoc(doc);
 
1357
    }
 
1358
    closedir(rep);
 
1359
 
 
1360
cleanup:    
 
1361
    xmlSchemaFree(schema);
 
1362
    xmlSchemaFreeValidCtxt(validator);
 
1363
    xmlFreeParserCtxt(parser);
 
1364
 
 
1365
    return model;
 
1366
}