xref: /aosp_15_r20/external/wmediumd/util/wmediumd_gen_config.c (revision 621120a22a0cd8ba80b131fe8bcb37c86ff453e3)
1*621120a2SAndroid Build Coastguard Worker #include <ctype.h>
2*621120a2SAndroid Build Coastguard Worker #include <errno.h>
3*621120a2SAndroid Build Coastguard Worker #include <getopt.h>
4*621120a2SAndroid Build Coastguard Worker #include <libconfig.h>
5*621120a2SAndroid Build Coastguard Worker #include <limits.h>
6*621120a2SAndroid Build Coastguard Worker #include <stdbool.h>
7*621120a2SAndroid Build Coastguard Worker #include <stdint.h>
8*621120a2SAndroid Build Coastguard Worker #include <stdio.h>
9*621120a2SAndroid Build Coastguard Worker #include <stdlib.h>
10*621120a2SAndroid Build Coastguard Worker #include <string.h>
11*621120a2SAndroid Build Coastguard Worker 
12*621120a2SAndroid Build Coastguard Worker #define MAC_ADDR_LEN 6
13*621120a2SAndroid Build Coastguard Worker #define STR_MAC_ADDR_LEN 17
14*621120a2SAndroid Build Coastguard Worker 
15*621120a2SAndroid Build Coastguard Worker #define OPENWRT_MAC_ADDR_1 "42:00:00:00:00:00"
16*621120a2SAndroid Build Coastguard Worker #define OPENWRT_MAC_ADDR_2 "42:00:00:00:01:00"
17*621120a2SAndroid Build Coastguard Worker 
18*621120a2SAndroid Build Coastguard Worker #define TX_POWER_DEFAULT 10
19*621120a2SAndroid Build Coastguard Worker 
20*621120a2SAndroid Build Coastguard Worker #define APPEND_LAST -1
21*621120a2SAndroid Build Coastguard Worker 
22*621120a2SAndroid Build Coastguard Worker #define DEFAULT_RADIO_COUNT 2
23*621120a2SAndroid Build Coastguard Worker #define DEFAULT_CUTTLEFISH_INSTANCE_COUNT 64
24*621120a2SAndroid Build Coastguard Worker #define DEFAULT_MAC_PREFIX 5554
25*621120a2SAndroid Build Coastguard Worker 
26*621120a2SAndroid Build Coastguard Worker #define PREVENT_MULTIPLE_OPTION(var, zero_val)                             \
27*621120a2SAndroid Build Coastguard Worker   do {                                                                     \
28*621120a2SAndroid Build Coastguard Worker     if ((var) != (zero_val)) {                                             \
29*621120a2SAndroid Build Coastguard Worker       fprintf(stderr, "Error - cannot use option '%c' multiple times\n\n", \
30*621120a2SAndroid Build Coastguard Worker               opt);                                                        \
31*621120a2SAndroid Build Coastguard Worker       print_help(-1);                                                      \
32*621120a2SAndroid Build Coastguard Worker     }                                                                      \
33*621120a2SAndroid Build Coastguard Worker   } while (0)
34*621120a2SAndroid Build Coastguard Worker 
35*621120a2SAndroid Build Coastguard Worker // Adds MAC addresses for cuttlefish. Addresses will be 02:XX:XX:YY:YY:00
36*621120a2SAndroid Build Coastguard Worker // where
37*621120a2SAndroid Build Coastguard Worker //  - XX:XX prefix. enumerated from `mac_prefix`(default: 5554) to
38*621120a2SAndroid Build Coastguard Worker //          `mac_prefix` + `instance_count`(default: 16) - 1
39*621120a2SAndroid Build Coastguard Worker //  - YY:YY radio index. enumerated from 0 to `radios`(default: 2) - 1
add_cuttlefish_mac_addresses(config_setting_t * ids,int mac_prefix,int instance_count,int radios)40*621120a2SAndroid Build Coastguard Worker int add_cuttlefish_mac_addresses(config_setting_t *ids, int mac_prefix,
41*621120a2SAndroid Build Coastguard Worker                                  int instance_count, int radios) {
42*621120a2SAndroid Build Coastguard Worker   for (int instance_num = 0; instance_num < instance_count; ++instance_num) {
43*621120a2SAndroid Build Coastguard Worker     char iface_id[STR_MAC_ADDR_LEN + 1] = {
44*621120a2SAndroid Build Coastguard Worker         0,
45*621120a2SAndroid Build Coastguard Worker     };
46*621120a2SAndroid Build Coastguard Worker     uint8_t mac[MAC_ADDR_LEN] = {
47*621120a2SAndroid Build Coastguard Worker         0,
48*621120a2SAndroid Build Coastguard Worker     };
49*621120a2SAndroid Build Coastguard Worker     uint32_t instance_mac_prefix = mac_prefix + instance_num;
50*621120a2SAndroid Build Coastguard Worker 
51*621120a2SAndroid Build Coastguard Worker     mac[0] = 0x02;
52*621120a2SAndroid Build Coastguard Worker     mac[1] = (instance_mac_prefix >> 8) & 0xff;
53*621120a2SAndroid Build Coastguard Worker     mac[2] = instance_mac_prefix & 0xff;
54*621120a2SAndroid Build Coastguard Worker 
55*621120a2SAndroid Build Coastguard Worker     for (int radio_num = 0; radio_num < radios; ++radio_num) {
56*621120a2SAndroid Build Coastguard Worker       mac[3] = (radio_num >> 8) & 0xff;
57*621120a2SAndroid Build Coastguard Worker       mac[4] = radio_num;
58*621120a2SAndroid Build Coastguard Worker 
59*621120a2SAndroid Build Coastguard Worker       snprintf(iface_id, sizeof(iface_id), "%02x:%02x:%02x:%02x:%02x:%02x",
60*621120a2SAndroid Build Coastguard Worker                mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
61*621120a2SAndroid Build Coastguard Worker 
62*621120a2SAndroid Build Coastguard Worker       config_setting_set_string_elem(ids, APPEND_LAST, iface_id);
63*621120a2SAndroid Build Coastguard Worker     }
64*621120a2SAndroid Build Coastguard Worker   }
65*621120a2SAndroid Build Coastguard Worker 
66*621120a2SAndroid Build Coastguard Worker   return 0;
67*621120a2SAndroid Build Coastguard Worker }
68*621120a2SAndroid Build Coastguard Worker 
add_cuttlefish_path_loss_model(config_setting_t * model,int instance_count)69*621120a2SAndroid Build Coastguard Worker int add_cuttlefish_path_loss_model(config_setting_t *model,
70*621120a2SAndroid Build Coastguard Worker                                    int instance_count) {
71*621120a2SAndroid Build Coastguard Worker   config_setting_t *type =
72*621120a2SAndroid Build Coastguard Worker       config_setting_add(model, "type", CONFIG_TYPE_STRING);
73*621120a2SAndroid Build Coastguard Worker   config_setting_set_string(type, "path_loss");
74*621120a2SAndroid Build Coastguard Worker 
75*621120a2SAndroid Build Coastguard Worker   config_setting_t *model_name =
76*621120a2SAndroid Build Coastguard Worker       config_setting_add(model, "model_name", CONFIG_TYPE_STRING);
77*621120a2SAndroid Build Coastguard Worker   config_setting_set_string(model_name, "free_space");
78*621120a2SAndroid Build Coastguard Worker 
79*621120a2SAndroid Build Coastguard Worker   config_setting_t *positions =
80*621120a2SAndroid Build Coastguard Worker       config_setting_add(model, "positions", CONFIG_TYPE_LIST);
81*621120a2SAndroid Build Coastguard Worker   config_setting_t *tx_powers =
82*621120a2SAndroid Build Coastguard Worker       config_setting_add(model, "tx_powers", CONFIG_TYPE_ARRAY);
83*621120a2SAndroid Build Coastguard Worker 
84*621120a2SAndroid Build Coastguard Worker   for (int idx = 0; idx < instance_count; ++idx) {
85*621120a2SAndroid Build Coastguard Worker     config_setting_t *position =
86*621120a2SAndroid Build Coastguard Worker         config_setting_add(positions, NULL, CONFIG_TYPE_LIST);
87*621120a2SAndroid Build Coastguard Worker     config_setting_set_float_elem(position, APPEND_LAST, 0.0);
88*621120a2SAndroid Build Coastguard Worker     config_setting_set_float_elem(position, APPEND_LAST, 0.0);
89*621120a2SAndroid Build Coastguard Worker 
90*621120a2SAndroid Build Coastguard Worker     config_setting_set_float_elem(tx_powers, APPEND_LAST, TX_POWER_DEFAULT);
91*621120a2SAndroid Build Coastguard Worker   }
92*621120a2SAndroid Build Coastguard Worker 
93*621120a2SAndroid Build Coastguard Worker   return 0;
94*621120a2SAndroid Build Coastguard Worker }
95*621120a2SAndroid Build Coastguard Worker 
valid_mac_addr(const char * mac_addr)96*621120a2SAndroid Build Coastguard Worker bool valid_mac_addr(const char *mac_addr) {
97*621120a2SAndroid Build Coastguard Worker   if (strlen(mac_addr) != STR_MAC_ADDR_LEN) return false;
98*621120a2SAndroid Build Coastguard Worker 
99*621120a2SAndroid Build Coastguard Worker   if (mac_addr[2] != ':' || mac_addr[5] != ':' || mac_addr[8] != ':' ||
100*621120a2SAndroid Build Coastguard Worker       mac_addr[11] != ':' || mac_addr[14] != ':') {
101*621120a2SAndroid Build Coastguard Worker     return false;
102*621120a2SAndroid Build Coastguard Worker   }
103*621120a2SAndroid Build Coastguard Worker 
104*621120a2SAndroid Build Coastguard Worker   for (int i = 0; i < STR_MAC_ADDR_LEN; ++i) {
105*621120a2SAndroid Build Coastguard Worker     if ((i - 2) % 3 == 0) continue;
106*621120a2SAndroid Build Coastguard Worker     char c = mac_addr[i];
107*621120a2SAndroid Build Coastguard Worker 
108*621120a2SAndroid Build Coastguard Worker     if (isupper(c)) {
109*621120a2SAndroid Build Coastguard Worker       c = tolower(c);
110*621120a2SAndroid Build Coastguard Worker     }
111*621120a2SAndroid Build Coastguard Worker 
112*621120a2SAndroid Build Coastguard Worker     if ((c < '0' || c > '9') && (c < 'a' || c > 'f')) return false;
113*621120a2SAndroid Build Coastguard Worker   }
114*621120a2SAndroid Build Coastguard Worker 
115*621120a2SAndroid Build Coastguard Worker   return true;
116*621120a2SAndroid Build Coastguard Worker }
117*621120a2SAndroid Build Coastguard Worker 
print_help(int exit_code)118*621120a2SAndroid Build Coastguard Worker void print_help(int exit_code) {
119*621120a2SAndroid Build Coastguard Worker   printf("wmediumd_gen_config - wmediumd config generator\n");
120*621120a2SAndroid Build Coastguard Worker   printf(
121*621120a2SAndroid Build Coastguard Worker       "wmediumd_gen_config [-h] [-n count] [-r count] [-p prefix] [-m "
122*621120a2SAndroid Build Coastguard Worker       "MAC_ADDR] [-o "
123*621120a2SAndroid Build Coastguard Worker       "PATH]\n");
124*621120a2SAndroid Build Coastguard Worker   printf("  -h              print help and exit\n");
125*621120a2SAndroid Build Coastguard Worker   printf(
126*621120a2SAndroid Build Coastguard Worker       "  -n count        cuttlefish instance count for adding pre-defined mac "
127*621120a2SAndroid Build Coastguard Worker       "address\n");
128*621120a2SAndroid Build Coastguard Worker   printf(
129*621120a2SAndroid Build Coastguard Worker       "  -r count        radio count of each cuttlefish instance (default: "
130*621120a2SAndroid Build Coastguard Worker       "2)\n");
131*621120a2SAndroid Build Coastguard Worker   printf(
132*621120a2SAndroid Build Coastguard Worker       "  -p prefix       set prefix for cuttlefish mac address (default: "
133*621120a2SAndroid Build Coastguard Worker       "5554)\n");
134*621120a2SAndroid Build Coastguard Worker   printf(
135*621120a2SAndroid Build Coastguard Worker       "                  second and third byte of mac address will be set to "
136*621120a2SAndroid Build Coastguard Worker       "prefix\n");
137*621120a2SAndroid Build Coastguard Worker   printf("                    ex) -p 5554    ex) -p 0x15b2\n");
138*621120a2SAndroid Build Coastguard Worker   printf("  -m MAC_ADDR     add mac address as pre-defined mac address\n");
139*621120a2SAndroid Build Coastguard Worker   printf("                    ex) -m 02:15:b2:00:00:00\n");
140*621120a2SAndroid Build Coastguard Worker   printf(
141*621120a2SAndroid Build Coastguard Worker       "  -o PATH         if specified, output result to file (default: "
142*621120a2SAndroid Build Coastguard Worker       "stdout)\n");
143*621120a2SAndroid Build Coastguard Worker   printf("\n");
144*621120a2SAndroid Build Coastguard Worker 
145*621120a2SAndroid Build Coastguard Worker   exit(exit_code);
146*621120a2SAndroid Build Coastguard Worker }
147*621120a2SAndroid Build Coastguard Worker 
parse_count_option(const char * value,int opt)148*621120a2SAndroid Build Coastguard Worker int parse_count_option(const char *value, int opt) {
149*621120a2SAndroid Build Coastguard Worker   char *parse_end_token;
150*621120a2SAndroid Build Coastguard Worker 
151*621120a2SAndroid Build Coastguard Worker   int result = strtol(value, &parse_end_token, 10);
152*621120a2SAndroid Build Coastguard Worker 
153*621120a2SAndroid Build Coastguard Worker   if ((result == LONG_MAX && errno == ERANGE) || optarg == parse_end_token ||
154*621120a2SAndroid Build Coastguard Worker       result <= 0) {
155*621120a2SAndroid Build Coastguard Worker     fprintf(stderr, "Error - Invalid count value '%s' at option '%c'\n\n",
156*621120a2SAndroid Build Coastguard Worker             value, opt);
157*621120a2SAndroid Build Coastguard Worker     return -1;
158*621120a2SAndroid Build Coastguard Worker   }
159*621120a2SAndroid Build Coastguard Worker 
160*621120a2SAndroid Build Coastguard Worker   return result;
161*621120a2SAndroid Build Coastguard Worker }
162*621120a2SAndroid Build Coastguard Worker 
parse_prefix_option(const char * value,int opt)163*621120a2SAndroid Build Coastguard Worker int parse_prefix_option(const char *value, int opt) {
164*621120a2SAndroid Build Coastguard Worker   char *parse_end_token;
165*621120a2SAndroid Build Coastguard Worker   int base = 10;
166*621120a2SAndroid Build Coastguard Worker 
167*621120a2SAndroid Build Coastguard Worker   if (strlen(value) >= 2 && value[0] == '0' && value[1] == 'x') {
168*621120a2SAndroid Build Coastguard Worker     value += 2;
169*621120a2SAndroid Build Coastguard Worker     base = 16;
170*621120a2SAndroid Build Coastguard Worker   }
171*621120a2SAndroid Build Coastguard Worker 
172*621120a2SAndroid Build Coastguard Worker   int result = strtol(value, &parse_end_token, base);
173*621120a2SAndroid Build Coastguard Worker 
174*621120a2SAndroid Build Coastguard Worker   if ((result == LONG_MAX && errno == ERANGE) || optarg == parse_end_token ||
175*621120a2SAndroid Build Coastguard Worker       result < 0) {
176*621120a2SAndroid Build Coastguard Worker     fprintf(stderr, "Error - Invalid prefix value '%s' at option '%c'\n\n",
177*621120a2SAndroid Build Coastguard Worker             value, opt);
178*621120a2SAndroid Build Coastguard Worker     return -1;
179*621120a2SAndroid Build Coastguard Worker   }
180*621120a2SAndroid Build Coastguard Worker 
181*621120a2SAndroid Build Coastguard Worker   if (result > 0xffff) {
182*621120a2SAndroid Build Coastguard Worker     fprintf(
183*621120a2SAndroid Build Coastguard Worker         stderr,
184*621120a2SAndroid Build Coastguard Worker         "Error - Prefix value should not be greater than 0xffff(65535) \n\n");
185*621120a2SAndroid Build Coastguard Worker     return -1;
186*621120a2SAndroid Build Coastguard Worker   }
187*621120a2SAndroid Build Coastguard Worker 
188*621120a2SAndroid Build Coastguard Worker   return result;
189*621120a2SAndroid Build Coastguard Worker }
190*621120a2SAndroid Build Coastguard Worker 
main(int argc,char ** argv)191*621120a2SAndroid Build Coastguard Worker int main(int argc, char **argv) {
192*621120a2SAndroid Build Coastguard Worker   config_t cfg;
193*621120a2SAndroid Build Coastguard Worker 
194*621120a2SAndroid Build Coastguard Worker   config_init(&cfg);
195*621120a2SAndroid Build Coastguard Worker 
196*621120a2SAndroid Build Coastguard Worker   config_setting_t *root = config_root_setting(&cfg);
197*621120a2SAndroid Build Coastguard Worker   config_setting_t *ifaces =
198*621120a2SAndroid Build Coastguard Worker       config_setting_add(root, "ifaces", CONFIG_TYPE_GROUP);
199*621120a2SAndroid Build Coastguard Worker 
200*621120a2SAndroid Build Coastguard Worker   config_setting_t *count =
201*621120a2SAndroid Build Coastguard Worker       config_setting_add(ifaces, "count", CONFIG_TYPE_INT);
202*621120a2SAndroid Build Coastguard Worker   config_setting_t *ids = config_setting_add(ifaces, "ids", CONFIG_TYPE_ARRAY);
203*621120a2SAndroid Build Coastguard Worker 
204*621120a2SAndroid Build Coastguard Worker   config_setting_set_string_elem(ids, APPEND_LAST, OPENWRT_MAC_ADDR_1);
205*621120a2SAndroid Build Coastguard Worker   config_setting_set_string_elem(ids, APPEND_LAST, OPENWRT_MAC_ADDR_2);
206*621120a2SAndroid Build Coastguard Worker 
207*621120a2SAndroid Build Coastguard Worker   FILE *output = stdout;
208*621120a2SAndroid Build Coastguard Worker   char *out_path = NULL;
209*621120a2SAndroid Build Coastguard Worker   int opt;
210*621120a2SAndroid Build Coastguard Worker   int cuttlefish_instance_count = -1;
211*621120a2SAndroid Build Coastguard Worker   int radio_count = -1;
212*621120a2SAndroid Build Coastguard Worker   int mac_prefix = -1;
213*621120a2SAndroid Build Coastguard Worker 
214*621120a2SAndroid Build Coastguard Worker   while ((opt = getopt(argc, argv, "hn:p:r:m:o:")) != -1) {
215*621120a2SAndroid Build Coastguard Worker     switch (opt) {
216*621120a2SAndroid Build Coastguard Worker       case ':':
217*621120a2SAndroid Build Coastguard Worker         fprintf(stderr, "Error - Option '%c' needs a value\n\n", optopt);
218*621120a2SAndroid Build Coastguard Worker         print_help(-1);
219*621120a2SAndroid Build Coastguard Worker         break;
220*621120a2SAndroid Build Coastguard Worker       case 'h':
221*621120a2SAndroid Build Coastguard Worker         print_help(0);
222*621120a2SAndroid Build Coastguard Worker         break;
223*621120a2SAndroid Build Coastguard Worker       case 'n':
224*621120a2SAndroid Build Coastguard Worker         PREVENT_MULTIPLE_OPTION(cuttlefish_instance_count, -1);
225*621120a2SAndroid Build Coastguard Worker 
226*621120a2SAndroid Build Coastguard Worker         cuttlefish_instance_count = parse_count_option(optarg, opt);
227*621120a2SAndroid Build Coastguard Worker 
228*621120a2SAndroid Build Coastguard Worker         if (cuttlefish_instance_count < 0) {
229*621120a2SAndroid Build Coastguard Worker           print_help(-1);
230*621120a2SAndroid Build Coastguard Worker         }
231*621120a2SAndroid Build Coastguard Worker         break;
232*621120a2SAndroid Build Coastguard Worker       case 'p':
233*621120a2SAndroid Build Coastguard Worker         PREVENT_MULTIPLE_OPTION(mac_prefix, -1);
234*621120a2SAndroid Build Coastguard Worker 
235*621120a2SAndroid Build Coastguard Worker         mac_prefix = parse_prefix_option(optarg, opt);
236*621120a2SAndroid Build Coastguard Worker 
237*621120a2SAndroid Build Coastguard Worker         if (mac_prefix < 0) {
238*621120a2SAndroid Build Coastguard Worker           print_help(-1);
239*621120a2SAndroid Build Coastguard Worker         }
240*621120a2SAndroid Build Coastguard Worker         break;
241*621120a2SAndroid Build Coastguard Worker       case 'r':
242*621120a2SAndroid Build Coastguard Worker         PREVENT_MULTIPLE_OPTION(radio_count, -1);
243*621120a2SAndroid Build Coastguard Worker 
244*621120a2SAndroid Build Coastguard Worker         radio_count = parse_count_option(optarg, opt);
245*621120a2SAndroid Build Coastguard Worker 
246*621120a2SAndroid Build Coastguard Worker         if (radio_count < 0) {
247*621120a2SAndroid Build Coastguard Worker           print_help(-1);
248*621120a2SAndroid Build Coastguard Worker         }
249*621120a2SAndroid Build Coastguard Worker         break;
250*621120a2SAndroid Build Coastguard Worker       case 'm':
251*621120a2SAndroid Build Coastguard Worker         if (!valid_mac_addr(optarg)) {
252*621120a2SAndroid Build Coastguard Worker           fprintf(stderr, "Error - '%s' is not a valid mac address\n\n",
253*621120a2SAndroid Build Coastguard Worker                   optarg);
254*621120a2SAndroid Build Coastguard Worker           print_help(-1);
255*621120a2SAndroid Build Coastguard Worker         }
256*621120a2SAndroid Build Coastguard Worker 
257*621120a2SAndroid Build Coastguard Worker         config_setting_set_string_elem(ids, APPEND_LAST, optarg);
258*621120a2SAndroid Build Coastguard Worker         break;
259*621120a2SAndroid Build Coastguard Worker       case 'o':
260*621120a2SAndroid Build Coastguard Worker         PREVENT_MULTIPLE_OPTION(out_path, NULL);
261*621120a2SAndroid Build Coastguard Worker 
262*621120a2SAndroid Build Coastguard Worker         out_path = strdup(optarg);
263*621120a2SAndroid Build Coastguard Worker         break;
264*621120a2SAndroid Build Coastguard Worker       case '?':
265*621120a2SAndroid Build Coastguard Worker         fprintf(stderr, "Error - Unknown option '%c'\n\n", optopt);
266*621120a2SAndroid Build Coastguard Worker         print_help(-1);
267*621120a2SAndroid Build Coastguard Worker         break;
268*621120a2SAndroid Build Coastguard Worker     }
269*621120a2SAndroid Build Coastguard Worker   }
270*621120a2SAndroid Build Coastguard Worker 
271*621120a2SAndroid Build Coastguard Worker   /* Use default values if not specified */
272*621120a2SAndroid Build Coastguard Worker 
273*621120a2SAndroid Build Coastguard Worker   if (radio_count == -1) {
274*621120a2SAndroid Build Coastguard Worker     radio_count = DEFAULT_RADIO_COUNT;
275*621120a2SAndroid Build Coastguard Worker   }
276*621120a2SAndroid Build Coastguard Worker 
277*621120a2SAndroid Build Coastguard Worker   if (cuttlefish_instance_count == -1) {
278*621120a2SAndroid Build Coastguard Worker     cuttlefish_instance_count = DEFAULT_CUTTLEFISH_INSTANCE_COUNT;
279*621120a2SAndroid Build Coastguard Worker   }
280*621120a2SAndroid Build Coastguard Worker 
281*621120a2SAndroid Build Coastguard Worker   if (mac_prefix == -1) {
282*621120a2SAndroid Build Coastguard Worker     mac_prefix = DEFAULT_MAC_PREFIX;
283*621120a2SAndroid Build Coastguard Worker   }
284*621120a2SAndroid Build Coastguard Worker 
285*621120a2SAndroid Build Coastguard Worker   if (add_cuttlefish_mac_addresses(ids, mac_prefix, cuttlefish_instance_count,
286*621120a2SAndroid Build Coastguard Worker                                    radio_count) < 0) {
287*621120a2SAndroid Build Coastguard Worker     fprintf(stderr, "Error - Failed to add cuttlefish mac address\n\n");
288*621120a2SAndroid Build Coastguard Worker     print_help(-1);
289*621120a2SAndroid Build Coastguard Worker   }
290*621120a2SAndroid Build Coastguard Worker 
291*621120a2SAndroid Build Coastguard Worker   config_setting_t *model =
292*621120a2SAndroid Build Coastguard Worker       config_setting_add(root, "model", CONFIG_TYPE_GROUP);
293*621120a2SAndroid Build Coastguard Worker   add_cuttlefish_path_loss_model(model, config_setting_length(ids));
294*621120a2SAndroid Build Coastguard Worker 
295*621120a2SAndroid Build Coastguard Worker   config_setting_set_int(count, config_setting_length(ids));
296*621120a2SAndroid Build Coastguard Worker 
297*621120a2SAndroid Build Coastguard Worker   if (out_path != NULL) {
298*621120a2SAndroid Build Coastguard Worker     FILE *out_file = fopen(out_path, "w");
299*621120a2SAndroid Build Coastguard Worker 
300*621120a2SAndroid Build Coastguard Worker     if (out_file == NULL) {
301*621120a2SAndroid Build Coastguard Worker       perror("fopen");
302*621120a2SAndroid Build Coastguard Worker       fprintf(stderr, "Error - Cannot open '%s'\n\n", out_path);
303*621120a2SAndroid Build Coastguard Worker       return -1;
304*621120a2SAndroid Build Coastguard Worker     }
305*621120a2SAndroid Build Coastguard Worker 
306*621120a2SAndroid Build Coastguard Worker     output = out_file;
307*621120a2SAndroid Build Coastguard Worker   }
308*621120a2SAndroid Build Coastguard Worker 
309*621120a2SAndroid Build Coastguard Worker   config_write(&cfg, output);
310*621120a2SAndroid Build Coastguard Worker 
311*621120a2SAndroid Build Coastguard Worker   if (out_path != NULL) {
312*621120a2SAndroid Build Coastguard Worker     free(out_path);
313*621120a2SAndroid Build Coastguard Worker   }
314*621120a2SAndroid Build Coastguard Worker 
315*621120a2SAndroid Build Coastguard Worker   config_destroy(&cfg);
316*621120a2SAndroid Build Coastguard Worker 
317*621120a2SAndroid Build Coastguard Worker   return 0;
318*621120a2SAndroid Build Coastguard Worker }
319