Skip to content

Commit

Permalink
WIP: nested structs take 2
Browse files Browse the repository at this point in the history
Add support for parsing nested structs, struct pointers, and
dynamic/fixed arrays in structs.

Make the kernel generator support these.

This also adds a qmi_header struct and a qmi_elem_info array pointer to
each message struct, these can be used in conjunction with new helpers
in libqrtr to avoid requiring users to manually specify the message
type/id and correct elem_info array.

TODO: some kind of versioning or other method of enabling/disabling the
extra properties.

NOTE: this breaks the accessor generator which now segfaults, cause TBD
  • Loading branch information
calebccff committed Sep 12, 2022
1 parent 0105cf4 commit 1dae75d
Show file tree
Hide file tree
Showing 3 changed files with 342 additions and 34 deletions.
139 changes: 129 additions & 10 deletions kernel.c
@@ -1,5 +1,8 @@
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "qmic.h"

Expand All @@ -9,7 +12,7 @@ static const char *sz_native_types[] = {
[TYPE_U32] = "uint32_t",
[TYPE_U64] = "uint64_t",
};

static const char *sz_data_types[] = {
[TYPE_U8] = "QMI_UNSIGNED_1_BYTE",
[TYPE_U16] = "QMI_UNSIGNED_2_BYTE",
Expand All @@ -25,6 +28,11 @@ static void emit_struct_definition(FILE *fp, const char *package,
fprintf(fp, "struct %s_%s {\n", package, qs->name);

list_for_each_entry(qsm, &qs->members, node) {
if (qsm->is_ptr) {
fprintf(fp, "\t%s %s_len;\n",
sz_native_types[qsm->array_len_type],
qsm->name);
}
switch (qsm->type) {
case TYPE_U8:
case TYPE_U16:
Expand All @@ -36,6 +44,10 @@ static void emit_struct_definition(FILE *fp, const char *package,
fprintf(fp, "\tuint32_t %s_len;\n", qsm->name);
fprintf(fp, "\tchar %s[256];\n", qsm->name);
break;
case TYPE_STRUCT:
fprintf(fp, "\tstruct %s_%s %s%s;\n", package, qsm->qmi_struct->name,
qsm->is_ptr ? "*" : "", qsm->name);
break;
}
}

Expand All @@ -47,14 +59,52 @@ static void emit_struct_native_ei(FILE *fp, const char *package,
struct qmi_struct *qs,
struct qmi_struct_member *qsm)
{
fprintf(fp, "\t{\n"
"\t\t.data_type = %4$s,\n"
"\t\t.elem_len = 1,\n"
"\t\t.elem_size = sizeof(%5$s),\n"
"\t\t.offset = offsetof(struct %1$s_%2$s, %3$s),\n"
"\t},\n",
package, qs->name, qsm->name,
sz_data_types[qsm->type], sz_native_types[qsm->type]);
if (qsm->array_fixed)
fprintf(fp, "\t{\n"
"\t\t.data_type = %4$s,\n"
"\t\t.elem_len = %6$d,\n"
"\t\t.array_type = STATIC_ARRAY,\n"
"\t\t.elem_size = sizeof(%5$s),\n"
"\t\t.offset = offsetof(struct %1$s_%2$s, %3$s),\n"
"\t},\n",
package, qs->name, qsm->name,
sz_data_types[qsm->type], sz_native_types[qsm->type],
qsm->array_size);
else
fprintf(fp, "\t{\n"
"\t\t.data_type = %4$s,\n"
"\t\t.elem_len = 1,\n"
"\t\t.elem_size = sizeof(%5$s),\n"
"\t\t.offset = offsetof(struct %1$s_%2$s, %3$s),\n"
"\t},\n",
package, qs->name, qsm->name,
sz_data_types[qsm->type], sz_native_types[qsm->type]);
}

static void emit_struct_nested_ei(FILE *fp, const char *package,
struct qmi_struct *qs,
struct qmi_struct_member *qsm)
{
if (qsm->is_ptr) {
fprintf(fp, "\t{\n"
"\t\t.data_type = QMI_STRUCT,\n"
"\t\t.elem_len = 255,\n"
"\t\t.array_type = VAR_LEN_ARRAY,\n"
"\t\t.elem_size = sizeof(struct %1$s_%2$s),\n"
"\t\t.offset = offsetof(struct %1$s_%2$s, %3$s),\n"
"\t\t.ei_array = %1$s_%4$s_ei,\n"
"\t},\n",
package, qs->name, qsm->name, qsm->qmi_struct->name);
} else {
fprintf(fp, "\t{\n"
"\t\t.data_type = QMI_STRUCT,\n"
"\t\t.elem_len = 1,\n"
"\t\t.elem_size = sizeof(struct %1$s_%2$s),\n"
"\t\t.offset = offsetof(struct %1$s_%2$s, %3$s),\n"
"\t\t.ei_array = %1$s_%4$s_ei,\n"
"\t},\n",
package, qs->name, qsm->name, qsm->qmi_struct->name);
}
}

static void emit_struct_ei(FILE *fp, const char *package, struct qmi_struct *qs)
Expand All @@ -64,6 +114,15 @@ static void emit_struct_ei(FILE *fp, const char *package, struct qmi_struct *qs)
fprintf(fp, "struct qmi_elem_info %s_%s_ei[] = {\n", package, qs->name);

list_for_each_entry(qsm, &qs->members, node) {
if (qsm->is_ptr)
fprintf(fp, "\t{\n"
"\t\t.data_type = QMI_DATA_LEN,\n"
"\t\t.elem_len = 1,\n"
"\t\t.elem_size = sizeof(%4$s),\n"
"\t\t.offset = offsetof(struct %1$s_%2$s, %3$s_len),\n"
"\t},\n",
package, qs->name, qsm->name,
sz_native_types[qsm->array_len_type]);
switch (qsm->type) {
case TYPE_U8:
case TYPE_U16:
Expand All @@ -80,6 +139,9 @@ static void emit_struct_ei(FILE *fp, const char *package, struct qmi_struct *qs)
"\t},\n",
package, qs->name, qsm->name);
break;
case TYPE_STRUCT:
emit_struct_nested_ei(fp, package, qs, qsm);
break;
}
}

Expand Down Expand Up @@ -132,6 +194,8 @@ static void emit_msg_struct(FILE *fp, const char *package, struct qmi_message *q
struct qmi_message_member *qmm;

fprintf(fp, "struct %1$s_%2$s {\n", package, qm->name);
fprintf(fp, "\tstruct qmi_header qmi_header;\n");
fprintf(fp, "\tstruct qmi_elem_info **ei;\n");

list_for_each_entry(qmm, &qm->members, node) {
switch (qmm->type) {
Expand All @@ -155,6 +219,56 @@ static void emit_msg_struct(FILE *fp, const char *package, struct qmi_message *q
fprintf(fp, "\n");
}

static void emit_msg_initialiser(FILE *fp, const char *package,
struct qmi_message *qm)
{
struct qmi_message_member *qmm;
int initialiser_len = strlen(package) + strlen(qm->name) + 15; // "_, _INITIALIZER"
char *upper;
char *p = upper = memalloc(initialiser_len+1);

snprintf(upper, initialiser_len, "%s_%s_NEW", package, qm->name);
while (*p) {
*p = toupper(*p);
p++;
}

fprintf(fp, "#define %1$s ({ \\\n"
" struct %2$s_%3$s *ptr = malloc(sizeof(struct %2$s_%3$s)); \\\n"
" ptr->qmi_header->type = %4$d; ptr->qmi_header->msg_id = 0x%5$04x; \\\n"
" ptr->ei = &%2$s_%3$s_ei; ptr })\n",
upper, package, qm->name, qm->type, qm->msg_id);

snprintf(upper, initialiser_len, "%s_%s_INITIALIZER", package, qm->name);
p = upper;
while (*p) {
*p = toupper(*p);
p++;
}

fprintf(fp, "#define %s { { %d, 0, 0x%04x, 0 }, &%s_%s_ei", upper,
qm->type, qm->msg_id, package, qm->name);

list_for_each_entry(qmm, &qm->members, node) {
switch (qmm->type) {
case TYPE_U8:
case TYPE_U16:
case TYPE_U32:
case TYPE_U64:
fprintf(fp, ", 0");
break;
case TYPE_STRING:
fprintf(fp, ", 0, NULL");
break;
case TYPE_STRUCT:
fprintf(fp, ", {}");
break;
}
}

fprintf(fp, " }\n");
}

static void emit_native_ei(FILE *fp, const char *package, struct qmi_message *qm,
struct qmi_message_member *qmm)
{
Expand Down Expand Up @@ -336,6 +450,11 @@ void kernel_emit_h(FILE *fp, const char *package)

guard_header(fp, package);
emit_h_file_header(fp);

list_for_each_entry(qm, &qmi_messages, node)
emit_elem_info_array_decl(fp, package, qm);
fprintf(fp, "\n");

qmi_const_header(fp);

list_for_each_entry(qs, &qmi_structs, node)
Expand All @@ -345,7 +464,7 @@ void kernel_emit_h(FILE *fp, const char *package)
emit_msg_struct(fp, package, qm);

list_for_each_entry(qm, &qmi_messages, node)
emit_elem_info_array_decl(fp, package, qm);
emit_msg_initialiser(fp, package, qm);
fprintf(fp, "\n");

guard_footer(fp);
Expand Down

0 comments on commit 1dae75d

Please sign in to comment.