blob: 2e2666f9f03f04ed736486821bd14be51692bae9 [file] [log] [blame]
Shad Ansari2f7f9be2017-06-07 13:34:53 -07001/*
2<:copyright-BRCM:2016:DUAL/GPL:standard
3
4 Broadcom Proprietary and Confidential.(c) 2016 Broadcom
5 All Rights Reserved
6
7Unless you and Broadcom execute a separate written software license
8agreement governing use of this software, this software is licensed
9to you under the terms of the GNU General Public License version 2
10(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
11with the following added to such license:
12
13 As a special exception, the copyright holders of this software give
14 you permission to link this software with independent modules, and
15 to copy and distribute the resulting executable under terms of your
16 choice, provided that you also meet, for each linked independent
17 module, the terms and conditions of the license of that module.
18 An independent module is a module which is not derived from this
19 software. The special exception does not apply to any modifications
20 of the software.
21
22Not withstanding the above, under no circumstances may you combine
23this software in any way with any other Broadcom software provided
24under a license other than the GPL, without Broadcom's express prior
25written consent.
26
27:>
28 */
29
30#include <bcmos_system.h>
31#include <bcmcli.h>
32#include <bcmolt_api.h>
33#include <bcmolt_model_types.h>
34#include <bcmos_types.h>
35
36#include "bcm_api_cli.h"
37#include "bcm_api_cli_helpers.h"
38#include "bcm_api_cli_handlers.h"
39#ifdef BCM_SUBSYSTEM_HOST
40#include <bcmolt_dev_selector.h>
41#endif
42
43#define APICLI_CAST_DISCARD_CONST(p, type) (type)((long)(p))
44
45/* bool enum table */
46static bcmcli_enum_val bool_enum[] =
47{
48 { .name = "yes", .val = 1 },
49 { .name = "no", .val = 0 },
50 BCMCLI_ENUM_LAST
51};
52
53static bcmcli_type_descr bool_type_descr = {
54 .name = "bool",
55 .descr = "Boolean",
56 .base_type = BCMOLT_BASE_TYPE_ID_ENUM,
57 .size = sizeof(bcmos_bool),
58 .x = {.e = bool_enum}
59};
60
61/* parameter data */
62typedef struct
63{
64 const bcmcli_prop_descr *prop; /* property */
65 const bcmcli_field_descr *field; /* field or NULL */
66 const bcmcli_field_descr *array_fd; /* array field descriptor or NULL */
67 uint16_t offset; /* offset from the beginning of the property */
68 uint16_t array_fd_offset; /* offset of array_fd from the beginning of the property */
69 bcmolt_mgt_group group; /* management group */
70} apicli_parm_data;
71
72typedef enum
73{
74 API_CLI_FLAGS_NONE = 0,
75 API_CLI_FLAGS_IGNORE_FIELDS = 1 << 0,
76 API_CLI_FLAGS_MULTI = 1 << 1
77} api_cli_flags;
78
79/* Operation: set, get, modify */
80typedef enum
81{
82 API_CLI_OPER_SET,
83 API_CLI_OPER_GET,
84 API_CLI_OPER_MODIFY,
85} api_cli_oper;
86
87/* Current session */
88static bcmcli_session *current_session;
89
90/* Current system mode */
91static bcmolt_system_mode current_system_mode;
92
93/* Parent directory */
94static bcmcli_entry *api_parent_dir;
95
96/*
97 * helpers
98 */
99
100/* calculate number of fields in type */
101static uint32_t _api_cli_get_num_fields_in_type(const bcmcli_type_descr *td)
102{
103 uint16_t f;
104 uint32_t nf = 0;
105
106
107 switch (td->base_type)
108 {
109 case BCMOLT_BASE_TYPE_ID_STRUCT:
110 {
111 if (!td->x.s.num_fields)
112 return 0;
113 BUG_ON(!td->x.s.fields);
114 for (f = 0; f < td->x.s.num_fields; f++)
115 {
116 nf += _api_cli_get_num_fields_in_type(td->x.s.fields[f].type);
117 }
118 break;
119 }
120
121 case BCMOLT_BASE_TYPE_ID_UNION:
122 {
123 /* Union. Count only common fields */
124 nf = td->x.u.num_common_fields;
125 break;
126 }
127
128 case BCMOLT_BASE_TYPE_ID_ARR_FIXED:
129 {
130 nf = _api_cli_get_num_fields_in_type(td->x.arr_fixed.elem_type);
131 break;
132 }
133
134 case BCMOLT_BASE_TYPE_ID_ARR_DYN:
135 {
136 nf = _api_cli_get_num_fields_in_type(td->x.arr_dyn.elem_type);
137 break;
138 }
139
140 default:
141 {
142 nf = 1;
143 break;
144 }
145 }
146
147 return nf;
148}
149
150/* calculate number of property fields for given object+group+subgroup+access. simple property=single field */
151static bcmos_errno _api_cli_get_num_fields_in_group(bcmolt_obj_id o, bcmolt_mgt_group group, uint16_t subgroup,
152 bcmolt_prop_access_id access_level, uint32_t *nfields)
153{
154 uint32_t nf = 0;
155 int i;
156 bcmos_errno rc = BCM_ERR_OK;
157
158 for (i = 0; rc != BCM_ERR_RANGE; i++)
159 {
160 const bcmcli_prop_descr *pd;
161 rc = api_cli_object_property(o, group, subgroup, i, &pd);
162 if (rc == BCM_ERR_OK && (pd->access & access_level))
163 {
164 /* Calculate number of fields if write access. Count only properties for read access */
165 if ((access_level & BCMOLT_PROP_ACCESS_ID_W) != 0)
166 {
167 BUG_ON(!pd->type);
168 nf += _api_cli_get_num_fields_in_type(pd->type);
169 }
170 else
171 {
172 ++nf;
173 }
174 }
175 }
176 *nfields = nf;
177
178 return BCM_ERR_OK;
179}
180
181/*
182 * Command handlers
183 */
184
185static bcmos_errno _apicli_objects_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
186{
187 int rc;
188 bcmolt_obj_id o;
189 const char *name, *descr;
190
191 bcmcli_print(session, "System Object Types:\n");
192 bcmcli_print(session, "=======================================\n");
193 bcmcli_print(session, "Id Name Description\n");
194 bcmcli_print(session, "=======================================\n");
195 for (o = 0; o < BCMOLT_OBJ_ID__NUM_OF; o++)
196 {
197
198 if (current_system_mode < BCMOLT_SYSTEM_MODE__NUM_OF && !bcmolt_object_is_supported(current_system_mode, o))
199 continue;
200
201 rc = api_cli_object_name(o, &name, &descr);
202 if (!rc)
203 bcmcli_print(session, "%.4d %-22s %s\n", o, name, descr);
204 }
205
206 return 0;
207}
208
209static bcmos_errno _apicli_set_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
210{
211 return bcmolt_cli_api_call(current_device, BCMOLT_MGT_GROUP_CFG, BCMOLT_MSG_TYPE_SET, session);
212}
213
214static bcmos_errno _apicli_get_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
215{
216 return bcmolt_cli_api_call(current_device, BCMOLT_MGT_GROUP_CFG, BCMOLT_MSG_TYPE_GET, session);
217}
218
219static bcmos_errno _apicli_clear_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
220{
221 return bcmolt_cli_api_call(current_device, BCMOLT_MGT_GROUP_CFG, BCMOLT_MSG_TYPE_CLEAR, session);
222}
223
224static bcmos_errno _apicli_stat_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
225{
226 return bcmolt_cli_api_call(current_device, BCMOLT_MGT_GROUP_STAT, BCMOLT_MSG_TYPE_GET, session);
227}
228
229static bcmos_errno _apicli_oper_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
230{
231 return bcmolt_cli_api_call(current_device, BCMOLT_MGT_GROUP_OPER, BCMOLT_MSG_TYPE_SET, session);
232}
233
234static bcmos_errno _apicli_send_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
235{
236 return bcmolt_cli_api_call(current_device, BCMOLT_MGT_GROUP_PROXY, BCMOLT_MSG_TYPE_SET, session);
237}
238
239static bcmos_errno _apicli_stat_cfg_set_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
240{
241 return bcmolt_cli_api_call(current_device, BCMOLT_MGT_GROUP_STAT_CFG, BCMOLT_MSG_TYPE_SET, session);
242}
243
244static bcmos_errno _apicli_stat_cfg_get_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
245{
246 return bcmolt_cli_api_call(current_device, BCMOLT_MGT_GROUP_STAT_CFG, BCMOLT_MSG_TYPE_GET, session);
247}
248
249static bcmos_errno _apicli_auto_cfg_set_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
250{
251 return bcmolt_cli_api_call(current_device, BCMOLT_MGT_GROUP_AUTO_CFG, BCMOLT_MSG_TYPE_SET, session);
252}
253
254static bcmos_errno _apicli_auto_cfg_get_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
255{
256 return bcmolt_cli_api_call(current_device, BCMOLT_MGT_GROUP_AUTO_CFG, BCMOLT_MSG_TYPE_GET, session);
257}
258
259static bcmos_errno _apicli_auto_cfg_get_multi_handler(
260 bcmcli_session *session,
261 const bcmcli_cmd_parm parm[],
262 uint16_t nparms)
263{
264 return bcmolt_cli_api_call(current_device, BCMOLT_MGT_GROUP_CFG, BCMOLT_MSG_TYPE_GET_MULTI, session);
265}
266
267/*
268 * Init-time helpers
269 */
270
271/* map to CLI type */
272static bcmos_errno _api_cli_map_type(const bcmcli_type_descr *td, const bcmcli_type_descr *array_td, bcmcli_cmd_parm *cmd_parm)
273{
274 apicli_parm_data *parm_data = cmd_parm->user_data;
275 bcmos_errno rc = BCM_ERR_OK;
276
277 /* Map type */
278 switch(td->base_type)
279 {
280 case BCMOLT_BASE_TYPE_ID_SNUM:
281 cmd_parm->type = BCMCLI_PARM_NUMBER;
282 break;
283 case BCMOLT_BASE_TYPE_ID_UNUM:
284 cmd_parm->type = BCMCLI_PARM_UNUMBER;
285 break;
286 case BCMOLT_BASE_TYPE_ID_UNUM_HEX:
287 cmd_parm->type = BCMCLI_PARM_HEX;
288 break;
289 case BCMOLT_BASE_TYPE_ID_BOOL:
290 cmd_parm->type = BCMCLI_PARM_ENUM;
291 cmd_parm->enum_table = bool_enum;
292 break;
293 case BCMOLT_BASE_TYPE_ID_FLOAT:
294 cmd_parm->type = td->size == sizeof(double) ? BCMCLI_PARM_DOUBLE : BCMCLI_PARM_FLOAT;
295 break;
296 case BCMOLT_BASE_TYPE_ID_STRING:
297 cmd_parm->type = BCMCLI_PARM_STRING;
298 break;
299 case BCMOLT_BASE_TYPE_ID_IPV4:
300 cmd_parm->type = BCMCLI_PARM_IP;
301 break;
302 case BCMOLT_BASE_TYPE_ID_MAC:
303 cmd_parm->type = BCMCLI_PARM_MAC;
304 break;
305 case BCMOLT_BASE_TYPE_ID_ENUM:
306 cmd_parm->type = BCMCLI_PARM_ENUM;
307 cmd_parm->enum_table = td->x.e;
308 break;
309 case BCMOLT_BASE_TYPE_ID_ENUM_MASK:
310 cmd_parm->type = BCMCLI_PARM_ENUM_MASK;
311 cmd_parm->enum_table = td->x.e;
312 break;
313 default:
314 bcmcli_print(current_session, "*** can't map type %s (%d)\n", td->name, (int)td->base_type);
315 rc = BCM_ERR_NOT_SUPPORTED;
316 break;
317 }
318
319 /* Map uint8_t array to buffer if it is independent (not structure field) */
320 if (array_td &&
321 td->size == 1 &&
322 (td->base_type == BCMOLT_BASE_TYPE_ID_UNUM || td->base_type == BCMOLT_BASE_TYPE_ID_UNUM_HEX) &&
323 (parm_data->array_fd == parm_data->field || !parm_data->field))
324 {
325 cmd_parm->type = BCMCLI_PARM_BUFFER;
326 }
327
328 return rc;
329}
330
331/* allocate memory for name and description and copy to to parm */
332static bcmos_errno _api_cli_copy_parm_name(bcmcli_cmd_parm *parm, const char *name, const char *descr)
333{
334 parm->name = bcmos_alloc(strlen(name) + 1);
335 parm->description = bcmos_alloc(strlen(descr) + 1);
336 if ((parm->name == NULL) || (parm->description == NULL))
337 {
338 /* Successful allocation if any will be released by common cleanup
339 * along with the rest of dynamic parameter fields */
340 return BCM_ERR_NOMEM;
341 }
342 strcpy(APICLI_CAST_DISCARD_CONST(parm->name, void *), name);
343 strcpy(APICLI_CAST_DISCARD_CONST(parm->description, void *), descr);
344 return BCM_ERR_OK;
345}
346
347/* populate single parameter */
348static int _api_cli_populate_parm1(const bcmcli_prop_descr *pd, const bcmcli_field_descr *fd, const bcmcli_type_descr *td,
349 const bcmcli_field_descr *array_fd, uint32_t offset, uint32_t array_fd_offset,
350 bcmcli_cmd_parm *cmd_parm, uint32_t cmd_flags, char *name, char *help)
351{
352 apicli_parm_data *parm_data = cmd_parm->user_data;
353 int rc;
354
355 parm_data->prop = pd;
356 parm_data->field = fd;
357 parm_data->offset = offset;
358 parm_data->array_fd = array_fd;
359 parm_data->array_fd_offset = array_fd_offset;
360
361 rc = _api_cli_copy_parm_name(cmd_parm, name, help);
362 if (rc)
363 {
364 return rc;
365 }
366 cmd_parm->flags = cmd_flags;
367 if (td->min_val != td->max_val || td->min_val)
368 {
369 cmd_parm->flags |= BCMCLI_PARM_FLAG_RANGE;
370 cmd_parm->low_val = td->min_val;
371 cmd_parm->hi_val = td->max_val;
372 }
373 rc = _api_cli_map_type(td, array_fd ? array_fd->type : NULL, cmd_parm);
374 if (rc < 0)
375 {
376 return rc;
377 }
378
379 /* Arrays require more work.
380 * - Calculate size. Known for fixed arrays, hard-coded max for dynamic
381 * - Allocate either buffer or array of values based on CLI parameter type
382 * - Calculate offset from the beginning of array entry
383 */
384 if (array_fd)
385 {
386 uint32_t array_size;
387
388 if (array_fd->type->base_type == BCMOLT_BASE_TYPE_ID_ARR_FIXED)
389 {
390 array_size = array_fd->type->x.arr_fixed.size;
391 }
392 else
393 {
394 array_size = array_fd->type->x.arr_dyn.max_size;
395 }
396 if (!array_size)
397 {
398 bcmcli_print(current_session, "*** Error in %s array descriptor. Size is not set.\n", array_fd->name);
399 return BCM_ERR_INTERNAL;
400 }
401 if (cmd_parm->type == BCMCLI_PARM_BUFFER)
402 {
403 rc = bcmolt_buf_alloc(&cmd_parm->value.buffer, array_size, BCMOLT_BUF_ENDIAN_FIXED);
404 if (rc)
405 {
406 return rc;
407 }
408 }
409 else
410 {
411 cmd_parm->values = bcmos_calloc(sizeof(bcmcli_parm_value) * array_size);
412 if (!cmd_parm->values)
413 {
414 return BCM_ERR_NOMEM;
415 }
416 cmd_parm->max_array_size = array_size;
417 }
418 }
419
420 return 1;
421}
422
423
424/* populate name buf and help buf */
425static void _api_cli_populate_name_help(const bcmcli_field_descr *fld, char *name_buf0, char *help_buf0,
426 char *name_buf, char *help_buf)
427{
428 name_buf[0] = 0;
429 help_buf[0] = 0;
430 bcmcli_strncpy(name_buf, name_buf0, APICLI_MAX_PARM_NAME_LENGTH);
431 if (strlen(name_buf))
432 bcmcli_strncat(name_buf, ".", APICLI_MAX_PARM_NAME_LENGTH);
433 bcmcli_strncat(name_buf, fld->cli_name ? fld->cli_name : fld->name, APICLI_MAX_PARM_NAME_LENGTH);
434 bcmcli_strncpy(help_buf, help_buf0, APICLI_MAX_PARM_HELP_LENGTH);
435 bcmcli_strncat(help_buf, " - ", APICLI_MAX_PARM_HELP_LENGTH);
436 bcmcli_strncat(help_buf, fld->descr ? fld->descr : fld->name, APICLI_MAX_PARM_HELP_LENGTH);
437}
438
439/* Allocate CLI parameter array. Set up parm->data */
440static bcmcli_cmd_parm *_api_cli_parm_alloc(int nparms)
441{
442 uint32_t size;
443 bcmcli_cmd_parm *parms;
444 apicli_parm_data *parm_data;
445 int i;
446
447 /* Allocate parameter table and populate it */
448 size = (sizeof(bcmcli_cmd_parm) + sizeof(apicli_parm_data)) * (nparms + 1);
449 parms = bcmos_calloc(size);
450 if (!parms)
451 return NULL;
452
453 /* Associate parameter_data structs with parameters */
454 parm_data = (apicli_parm_data *)(parms + nparms + 1);
455 for (i = 0; i < nparms; i++)
456 {
457 parms[i].user_data = &parm_data[i];
458 }
459 return parms;
460}
461
462/* clone enum table */
463static bcmcli_enum_val *_api_cli_clone_enum_table(bcmcli_cmd_parm *parm)
464{
465 bcmcli_enum_val *org_table = parm->enum_table;
466 bcmcli_enum_val *val = org_table;
467 bcmcli_enum_val *clone_table = org_table;
468 int i, n;
469
470 BUG_ON(parm->type != BCMCLI_PARM_ENUM);
471 while (val && val->name)
472 {
473 ++val;
474 }
475 n = val - org_table;
476
477 clone_table = bcmos_calloc(sizeof(bcmcli_enum_val) * (n + 1));
478 if (!clone_table)
479 {
480 return NULL;
481 }
482 for (i = 0; i < n; i++)
483 {
484 clone_table[i].name = org_table[i].name;
485 clone_table[i].val = org_table[i].val;
486 }
487 return clone_table;
488}
489
490
491/* populate CLI parameter(s) from a single property. Can be multiple parameters
492 * if property contains multiple fields.
493 * Returns number of parameters populated >= 0 or error < 0
494 */
495static int _api_cli_populate_parms_from_property(const bcmcli_prop_descr *pd, const bcmcli_field_descr *fd,
496 const bcmcli_field_descr *array_fd, uint32_t offset, uint32_t array_fd_offset, bcmcli_cmd_parm *parms,
497 bcmolt_prop_access_id access_level, uint32_t cmd_flags, char *name_buf0, char *help_buf0)
498{
499 const bcmcli_type_descr *td = fd ? fd->type : pd->type;
500 uint32_t nf = 0;
501 char name_buf[APICLI_MAX_PARM_NAME_LENGTH];
502 char help_buf[APICLI_MAX_PARM_HELP_LENGTH];
503 int rc = 0;
504
505 /* At top level take name from property */
506 if (td == pd->type)
507 {
508 /* In case there's a global prefix */
509 char *top_name_buf = name_buf0;
510 uint32_t top_name_buf_len = APICLI_MAX_PARM_NAME_LENGTH;
511 uint32_t prefix_len = strlen(name_buf0);
512 if (prefix_len > 0)
513 {
514 top_name_buf += prefix_len;
515 top_name_buf_len -= prefix_len;
516 }
517
518 bcmcli_strncpy(top_name_buf, pd->cli_name ? pd->cli_name : pd->name, top_name_buf_len);
519 bcmcli_strncpy(help_buf0, pd->descr ? pd->descr : pd->name, APICLI_MAX_PARM_HELP_LENGTH);
520 }
521
522 /* For read access we only mark whether read property or not. It is not field-by-field operation */
523 if (access_level == BCMOLT_PROP_ACCESS_ID_R)
524 {
525 td = &bool_type_descr;
526 }
527
528 /* In case of arrays we should
529 * - check that there is no array in array. It is not supported
530 * - store array type descriptor FFU and replace the "current" type descriptor with element type
531 * - reset offset because for array fields it should be calculated from array base rather than property
532 */
533 if (td->base_type == BCMOLT_BASE_TYPE_ID_ARR_DYN || td->base_type == BCMOLT_BASE_TYPE_ID_ARR_FIXED)
534 {
535 if (array_fd)
536 {
537 bcmcli_print(current_session, "*** %s in %s: arrays-in-arrays are not supported\n", pd->name, array_fd->name);
538 return BCM_ERR_NOT_SUPPORTED;
539 }
540 /* store array type and fetch element type */
541 array_fd = fd ? fd : (const bcmcli_field_descr *)pd;
542 if (td->base_type == BCMOLT_BASE_TYPE_ID_ARR_DYN)
543 {
544 td = td->x.arr_dyn.elem_type;
545 }
546 else
547 {
548 td = td->x.arr_fixed.elem_type;
549 }
550 array_fd_offset = offset;
551 offset = 0;
552 }
553
554 if (td->base_type == BCMOLT_BASE_TYPE_ID_STRUCT)
555 {
556 uint16_t f;
557 if (!td->x.s.num_fields)
558 return 0;
559 BUG_ON(!td->x.s.fields);
560 for (f = 0; f < td->x.s.num_fields; f++)
561 {
562 const bcmcli_field_descr *fld = &td->x.s.fields[f];
563 _api_cli_populate_name_help(fld, name_buf0, help_buf0, name_buf, help_buf);
564 rc = _api_cli_populate_parms_from_property(pd, fld, array_fd, offset+fld->offset,
565 array_fd_offset, &parms[nf], access_level, cmd_flags, name_buf, help_buf);
566 if (rc > 0)
567 nf += rc;
568 }
569 }
570 else if (td->base_type == BCMOLT_BASE_TYPE_ID_UNION)
571 {
572 /* Union */
573 uint16_t f;
574 const bcmcli_field_descr *fld;
575 bcmcli_cmd_parm *sel_parm;
576 apicli_parm_data *sel_data;
577 bcmcli_enum_val *e;
578
579 if (!td->x.u.num_common_fields)
580 return 0;
581 BUG_ON(!td->x.u.common_fields);
582
583 /* Populate parameters preceding the union selector */
584 for (f = 0; f < td->x.u.classifier_idx; f++)
585 {
586 fld = &td->x.u.common_fields[f];
587 _api_cli_populate_name_help(fld, name_buf0, help_buf0, name_buf, help_buf);
588 rc = _api_cli_populate_parms_from_property(pd, fld, array_fd,
589 offset+fld->offset, array_fd_offset, &parms[nf], access_level, cmd_flags, name_buf, help_buf);
590 if (rc > 0)
591 nf += rc;
592 }
593
594 /* Now populate parameter for selector */
595 sel_parm = &parms[nf];
596 fld = &td->x.u.common_fields[f];
597 _api_cli_populate_name_help(fld, name_buf0, help_buf0, name_buf, help_buf);
598 rc = _api_cli_populate_parms_from_property(pd, fld, array_fd,
599 offset+fld->offset, array_fd_offset, sel_parm, access_level, cmd_flags, name_buf, help_buf);
600 if (rc > 0)
601 nf += rc;
602 /* Clone enum table in order to allow modifying it */
603 if (rc >= 1)
604 {
605 sel_parm->enum_table = _api_cli_clone_enum_table(sel_parm);
606 if (!sel_parm->enum_table)
607 {
608 rc = BCM_ERR_NOMEM;
609 }
610 }
611
612 /* Now set-up selector */
613 sel_parm->flags |= BCMCLI_PARM_FLAG_SELECTOR;
614 sel_data = sel_parm->user_data;
615 e = sel_parm->enum_table;
616 while (e && e->name && rc >= 0)
617 {
618 fld = &td->x.u.union_fields[e - sel_parm->enum_table];
619 if (fld->type)
620 {
621 int np = _api_cli_get_num_fields_in_type(fld->type);
622 int i;
623
624 e->parms = _api_cli_parm_alloc(np);
625 if (!e->parms)
626 {
627 rc = BCM_ERR_NOMEM;
628 break;
629 }
630 for (i = 0; i < np; i++)
631 {
632 apicli_parm_data *data = e->parms[i].user_data;
633 data->group = sel_data->group;
634 }
635 /* Collapse substructure name */
636 if (fld->type->base_type == BCMOLT_BASE_TYPE_ID_STRUCT ||
637 fld->type->base_type == BCMOLT_BASE_TYPE_ID_UNION)
638 {
639 bcmcli_strncpy(name_buf, name_buf0, sizeof(name_buf));
640 bcmcli_strncpy(help_buf, help_buf0, sizeof(help_buf));
641 }
642 else
643 {
644 _api_cli_populate_name_help(fld, name_buf0, help_buf0, name_buf, help_buf);
645 }
646 rc = _api_cli_populate_parms_from_property(pd, fld, array_fd,
647 offset+fld->offset, array_fd_offset, e->parms, access_level, cmd_flags, name_buf, help_buf);
648 }
649 ++e;
650 }
651
652 /* Finally populate parameters following the selector parameter */
653 for (f = td->x.u.classifier_idx + 1; f < td->x.u.num_common_fields && rc >= 0; f++)
654 {
655 fld = &td->x.u.common_fields[f];
656 _api_cli_populate_name_help(fld, name_buf0, help_buf0, name_buf, help_buf);
657 rc = _api_cli_populate_parms_from_property(pd, fld, array_fd,
658 offset+fld->offset, array_fd_offset, &parms[nf], access_level, cmd_flags, name_buf, help_buf);
659 if (rc > 0)
660 nf += rc;
661 }
662 }
663 else
664 {
665 /* Finally! Simple type that maps to a single CLI parameter */
666 nf = _api_cli_populate_parm1(pd, fd, td, array_fd, offset, array_fd_offset,
667 &parms[0], cmd_flags, name_buf0, help_buf0);
668 }
669 return (rc >= 0) ? nf : rc;
670}
671
672/* populate CLI parameter table */
673static int _api_cli_populate_parms(
674 bcmolt_obj_id o,
675 bcmolt_mgt_group group,
676 uint16_t subgroup,
677 bcmolt_prop_access_id access_level,
678 bcmcli_cmd_parm *parms,
679 uint32_t cmd_flags,
680 const char *prefix)
681{
682 int nf = 0;
683 int i;
684 bcmos_errno rc = BCM_ERR_OK;
685
686 for (i = 0; rc != BCM_ERR_RANGE; i++)
687 {
688 const bcmcli_prop_descr *pd;
689 char name_buf[APICLI_MAX_PARM_NAME_LENGTH] = "";
690 char help_buf[APICLI_MAX_PARM_HELP_LENGTH] = "";
691
692 strncpy(name_buf, prefix, APICLI_MAX_PARM_NAME_LENGTH-1);
693 name_buf[APICLI_MAX_PARM_NAME_LENGTH-1] = 0;
694
695 rc = api_cli_object_property(o, group, subgroup, i, &pd);
696 if (rc == BCM_ERR_OK && (pd->access & access_level))
697 {
698 rc = _api_cli_populate_parms_from_property(pd, NULL, NULL, 0, 0, &parms[nf],
699 access_level, cmd_flags, name_buf, help_buf);
700 if (rc > 0)
701 nf += rc;
702 }
703 }
704 return nf;
705}
706
707
708/* compact selector table. squeeze out values that don't have parameter table attached */
709static void _api_cli_compact_selector(bcmcli_enum_val *selector, int size)
710{
711 int i, j;
712
713 for (i = 0; i < size; i++)
714 {
715 if (!selector[i].parms)
716 {
717 for ( j = i + 1; j < size && !selector[j].parms; j ++)
718 ;
719 if (j < size)
720 {
721 memcpy(&selector[i], &selector[j], sizeof(bcmcli_enum_val));
722 memset(&selector[j], 0, sizeof(bcmcli_enum_val));
723 }
724 else
725 {
726 memset(&selector[i], 0, sizeof(bcmcli_enum_val));
727 }
728 }
729 }
730}
731
732/* Free CLI parameters. both name and description are allocated dynamically */
733static void _api_cli_free_parms(bcmcli_cmd_parm *parms)
734{
735 bcmcli_cmd_parm *p = parms;
736
737 while (p->name)
738 {
739 if ((p->flags & BCMCLI_PARM_FLAG_SELECTOR))
740 {
741 /* Remove selector table */
742 bcmcli_enum_val *sel = p->enum_table;
743 if (sel)
744 {
745 bcmcli_enum_val *e = sel;
746 while(e->name)
747 {
748 if (e->parms)
749 {
750 _api_cli_free_parms(e->parms);
751 }
752 ++e;
753 }
754 bcmos_free(sel);
755 }
756 }
757 if (p->description)
758 bcmos_free(APICLI_CAST_DISCARD_CONST(p->description, void *));
759 if (p->name)
760 bcmos_free(APICLI_CAST_DISCARD_CONST(p->name, void *));
761 if (p->max_array_size && p->values)
762 bcmos_free(p->values);
763 if (p->value.buffer.start)
764 bcmolt_buf_free(&p->value.buffer);
765
766 ++p;
767 }
768 bcmos_free(parms);
769}
770
771static uint8_t _apicli_get_num_cmd_parms(bcmolt_mgt_group group, api_cli_flags flags)
772{
773 if (group == BCMOLT_MGT_GROUP_STAT)
774 return 2; /* object + stat ID */
775 else if (group == BCMOLT_MGT_GROUP_CFG && (flags & API_CLI_FLAGS_MULTI) != API_CLI_FLAGS_NONE)
776 return 3; /* object + max msgs + invert flag */
777 else
778 return 1; /* object */
779}
780
781/* Read generated info and add CLI command */
782static bcmos_errno _api_cli_add(bcmcli_entry *dir, const char *cmd_name, const char *cmd_descr,
783 bcmolt_mgt_group group, bcmolt_prop_access_id access_level, bcmcli_cmd_cb cmd_handler, api_cli_flags flags)
784{
785 bcmcli_cmd_extra_parm cmd_extras = { .free_parms = _api_cli_free_parms };
786 bcmcli_cmd_parm *cmd_parms;
787 bcmcli_enum_val *obj_selector;
788 bcmolt_obj_id o;
789 bcmos_errno rc = BCM_ERR_OK;
790 uint32_t cmd_flags = 0;
791 uint8_t num_cmd_parms = _apicli_get_num_cmd_parms(group, flags);
792 int n_obj;
793 int i;
794
795 /* Command flags: parameters in the following groups are optional */
796 if (group == BCMOLT_MGT_GROUP_CFG || group == BCMOLT_MGT_GROUP_STAT || group == BCMOLT_MGT_GROUP_AUTO_CFG)
797 cmd_flags = BCMCLI_PARM_FLAG_OPTIONAL;
798
799 /* command parameters are:
800 * - object_name (selector)
801 * - object_key_fields
802 * - object_per_group_fields filtered by access
803 * Therefore, there is 1 top-level enum parameter (object type) with per-value parameter tables
804 * In the case of operations or proxy messages, there is also a top-level enum parameter for the oper/proxy name
805 */
806
807 /* Allocate enum table based on max number of objects. Will be compacted in the end */
808 cmd_parms = bcmos_calloc(sizeof(bcmcli_cmd_parm) * (num_cmd_parms + 1));
809 if (!cmd_parms)
810 return BCM_ERR_NOMEM;
811
812 /* Allocate enough space for all object entries as well as a terminator entry (which is left NULL) */
813 obj_selector = bcmos_calloc(sizeof(bcmcli_enum_val) * (BCMOLT_OBJ_ID__NUM_OF + 1));
814 if (!obj_selector)
815 goto nomem_cleanup;
816
817 /* Allocate parameter table */
818 n_obj = 0;
819 for (o = 0; o < BCMOLT_OBJ_ID__NUM_OF; o++)
820 {
821 uint32_t nkeyfields = 0;
822 uint32_t nfields = 0;
823 uint32_t nfilterfields = 0;
824 uint32_t size;
825 uint16_t s;
826 uint16_t subgroup_count = api_cli_get_subgroup_count(o, group);
827 bcmcli_enum_val *sub_selector;
828
829 if (!bcmolt_object_is_supported(current_system_mode, o) && o != BCMOLT_OBJ_ID_DEVICE)
830 continue;
831
832 if (subgroup_count == 0)
833 continue;
834
835 obj_selector[n_obj].val = o;
836 rc = api_cli_object_name(o, &obj_selector[n_obj].name, NULL);
837 if (rc)
838 continue;
839
840 /* Get number of key fields and save it */
841 if (group == BCMOLT_MGT_GROUP_AUTO_CFG)
842 {
843 nkeyfields = 0;
844 }
845 else
846 {
847 _api_cli_get_num_fields_in_group(o, BCMOLT_MGT_GROUP_KEY, 0, BCMOLT_PROP_ACCESS_ID_W, &nkeyfields);
848 }
849
850 /* Allocate subgroup enum table */
851 sub_selector = bcmos_calloc(sizeof(bcmcli_enum_val) * (subgroup_count + 1));
852 if (!sub_selector)
853 goto nomem_cleanup;
854
855 /* Allocate single subgroup command parameter */
856 size = sizeof(bcmcli_cmd_parm) * 2;
857 obj_selector[n_obj].parms = bcmos_calloc(size);
858 if (!obj_selector[n_obj].parms)
859 {
860 bcmos_free(sub_selector);
861 goto nomem_cleanup;
862 }
863
864 /* Setup single subgroup command parameter */
865 obj_selector[n_obj].parms[0].type = BCMCLI_PARM_ENUM;
866 obj_selector[n_obj].parms[0].flags = BCMCLI_PARM_FLAG_SELECTOR;
867 obj_selector[n_obj].parms[0].enum_table = sub_selector;
868 rc = _api_cli_copy_parm_name(&obj_selector[n_obj].parms[0],
869 "sub",
870 "Subgroup (specific operation / proxy msg)");
871 if (rc)
872 goto nomem_cleanup;
873
874 for (s = 0; s < subgroup_count; ++s)
875 {
876 const char *sub_name;
877 bcmcli_cmd_parm *parm_ptr;
878
879 /* Get name of specific subgroup */
880 rc = api_cli_object_subgroup_name(o, group, s, &sub_name, NULL);
881 if (rc)
882 continue;
883
884 /* Setup entry in subgroup enum table */
885 sub_selector[s].name = sub_name;
886 sub_selector[s].val = s;
887
888 /* Get number of group fields */
889 rc = _api_cli_get_num_fields_in_group(o, group, s, access_level, &nfields);
890 if (rc)
891 continue;
892
893 /* For multi-object GET messages, populate the filter fields just like a SET (except that all read-only
894 fields are also settable) */
895 if ((flags & API_CLI_FLAGS_MULTI) != API_CLI_FLAGS_NONE)
896 {
897 rc = _api_cli_get_num_fields_in_group(o, group, s, BCMOLT_PROP_ACCESS_ID_RW, &nfilterfields);
898 if (rc)
899 continue;
900 }
901
902
903 if ((flags & API_CLI_FLAGS_IGNORE_FIELDS) != API_CLI_FLAGS_NONE)
904 {
905 nfilterfields = 0;
906 nfields = 0;
907 }
908
909
910 /* Allocate parameter table and populate it */
911 sub_selector[s].parms = _api_cli_parm_alloc(nfields + nkeyfields + nfilterfields);
912 if (!sub_selector[s].parms)
913 {
914 rc = BCM_ERR_NOMEM;
915 goto nomem_cleanup;
916 }
917 for (i = 0; i < nkeyfields + nfields + nfilterfields; i++)
918 {
919 apicli_parm_data *parm_data = sub_selector[s].parms[i].user_data;
920 parm_data->group = (i < nkeyfields) ? BCMOLT_MGT_GROUP_KEY : group;
921 }
922
923 parm_ptr = sub_selector[s].parms;
924 if (nkeyfields)
925 {
926 rc = _api_cli_populate_parms(o, BCMOLT_MGT_GROUP_KEY, 0, BCMOLT_PROP_ACCESS_ID_W, parm_ptr, 0, "");
927 if (rc < 0)
928 goto nomem_cleanup;
929 parm_ptr += rc;
930 }
931 if (nfilterfields)
932 {
933 rc = _api_cli_populate_parms(o, group, s, BCMOLT_PROP_ACCESS_ID_RW, parm_ptr, cmd_flags, "filter.");
934 if (rc < 0)
935 goto nomem_cleanup;
936 parm_ptr += rc;
937 }
938 if (nfields)
939 {
940 rc = _api_cli_populate_parms(o, group, s, access_level, parm_ptr, cmd_flags, "");
941 if (rc < 0)
942 goto nomem_cleanup;
943 parm_ptr += rc;
944 }
945 }
946
947 /* Compact sub_selector enum. Removes holes (values without parameter table) */
948 _api_cli_compact_selector(sub_selector, subgroup_count);
949
950 /* If the group type doesn't support subgroups, remove the subgroup param entry */
951 if (group == BCMOLT_MGT_GROUP_CFG || group == BCMOLT_MGT_GROUP_STAT || group == BCMOLT_MGT_GROUP_AUTO_CFG)
952 {
953 /* Free the memory associated with the (single) subgroup param */
954 bcmos_free(APICLI_CAST_DISCARD_CONST(obj_selector[n_obj].parms[0].name, void *));
955 bcmos_free(APICLI_CAST_DISCARD_CONST(obj_selector[n_obj].parms[0].description, void *));
956 bcmos_free(obj_selector[n_obj].parms);
957 /* Assign the subgroup params to the root object params */
958 obj_selector[n_obj].parms = sub_selector[0].parms;
959 bcmos_free(sub_selector);
960 }
961
962 ++n_obj; /* number of configured objects */
963 }
964
965 /* Compact obj_selector enum. Removes holes (values without parameter table) */
966 _api_cli_compact_selector(obj_selector, BCMOLT_OBJ_ID__NUM_OF);
967
968 /* Add a 'clear on read' to stats group */
969 if (group == BCMOLT_MGT_GROUP_STAT)
970 {
971 cmd_parms[0].type = BCMCLI_PARM_ENUM;
972 cmd_parms[0].enum_table = bool_enum;
973 rc = _api_cli_copy_parm_name(&cmd_parms[0], "clear", "clear on read");
974 if (rc)
975 goto nomem_cleanup;
976 }
977
978 /* Add 'max number of messages to read' and 'invert filter' to cfg get_multi msgs */
979 if (group == BCMOLT_MGT_GROUP_CFG && (flags & API_CLI_FLAGS_MULTI) != API_CLI_FLAGS_NONE)
980 {
981 cmd_parms[0].type = BCMCLI_PARM_UNUMBER;
982 rc = _api_cli_copy_parm_name(&cmd_parms[0], "max_msgs", "max number of API GET messages to receive per call");
983 if (rc)
984 goto nomem_cleanup;
985
986 cmd_parms[1].type = BCMCLI_PARM_ENUM;
987 cmd_parms[1].enum_table = bool_enum;
988 rc = _api_cli_copy_parm_name(&cmd_parms[1], "filter_invert", "invert filter (select objects that don't match)");
989 if (rc)
990 goto nomem_cleanup;
991 }
992
993 /* We are ready to add this command */
994 cmd_parms[num_cmd_parms - 1].type = BCMCLI_PARM_ENUM;
995 cmd_parms[num_cmd_parms - 1].flags = BCMCLI_PARM_FLAG_SELECTOR;
996 cmd_parms[num_cmd_parms - 1].enum_table = obj_selector;
997 rc = _api_cli_copy_parm_name(&cmd_parms[num_cmd_parms - 1], "object", "Object Type");
998 if (rc)
999 goto nomem_cleanup;
1000 rc = bcmcli_cmd_add(dir, cmd_name, cmd_handler, cmd_descr,
1001 (access_level == BCMOLT_PROP_ACCESS_ID_W) ? BCMCLI_ACCESS_ADMIN : BCMCLI_ACCESS_GUEST,
1002 &cmd_extras, cmd_parms);
1003 if (rc)
1004 goto nomem_cleanup;
1005 return 0;
1006
1007nomem_cleanup:
1008 if (obj_selector)
1009 {
1010 for (o = 0; o < BCMOLT_OBJ_ID__NUM_OF; o++)
1011 {
1012 if (obj_selector[o].parms)
1013 _api_cli_free_parms(obj_selector[o].parms);
1014 }
1015 bcmos_free(obj_selector);
1016 }
1017 bcmos_free(cmd_parms);
1018 return rc;
1019}
1020
1021#ifdef BCM_SUBSYSTEM_HOST
1022
1023/* Current device change indication */
1024static void _api_cli_device_change_ind(bcmcli_session *session, bcmolt_devid dev)
1025{
1026 api_cli_set_commands(session);
1027}
1028
1029#ifdef LINUX_USER_SPACE
1030
1031static bcmcli_session *_apicli_log;
1032static FILE *_apicli_log_file;
1033
1034static int _apicli_log_write_cb(bcmcli_session *session, const char *buf, uint32_t size)
1035{
1036 if (_apicli_log_file == NULL || buf == NULL)
1037 return BCM_ERR_INTERNAL;
1038 fwrite(buf, 1, size, _apicli_log_file);
1039 fflush(_apicli_log_file);
1040 return BCM_ERR_OK;
1041}
1042
1043/* Enable/disable API logging
1044 * BCMCLI_MAKE_PARM("file", "Log file. Use \"-\" to disable logging", BCMCLI_PARM_STRING, 0));
1045 */
1046static bcmos_errno _apicli_log_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
1047{
1048 const char *fname = parm[0].value.string;
1049 bcmcli_session_parm session_params =
1050 {
1051 .write = _apicli_log_write_cb,
1052 .name = "api_log"
1053 };
1054 bcmos_errno rc;
1055 time_t start_time;
1056
1057 /* Close existing log session if any */
1058 if (_apicli_log)
1059 {
1060 bcmcli_log_set(BCMCLI_LOG_NONE, NULL);
1061 bcmcli_session_close(_apicli_log);
1062 fclose(_apicli_log_file);
1063 _apicli_log = NULL;
1064 _apicli_log_file = NULL;
1065 }
1066
1067 if (!strcmp(fname, "-"))
1068 return BCM_ERR_OK;
1069
1070 /* Starting a new log session */
1071 _apicli_log_file = fopen(fname, "a");
1072 if (_apicli_log_file == NULL)
1073 {
1074 bcmcli_print(session, "Can't open file %s for logging\n", fname);
1075 return BCM_ERR_PARM;
1076 }
1077 rc = bcmcli_session_open_user(&session_params, &_apicli_log);
1078 if (rc)
1079 {
1080 fclose(_apicli_log_file);
1081 _apicli_log_file = NULL;
1082 bcmcli_print(session, "Can't open log session. Error %s\n", bcmos_strerror(rc));
1083 return rc;
1084 }
1085 time(&start_time);
1086 bcmcli_log_set(BCMCLI_LOG_C_COMMENT, _apicli_log);
1087 bcmcli_log("/* API logging session started. %s */\n", ctime(&start_time));
1088 return BCM_ERR_OK;
1089}
1090#endif /* #ifdef LINUX_USER_SPACE */
1091
1092#endif /* #ifdef BCM_SUBSYSTEM_HOST */
1093
1094static void api_cli_find_del_cmd(bcmcli_entry *dir, const char *cmd_name)
1095{
1096 bcmcli_entry *cmd;
1097 cmd = bcmcli_cmd_find(dir, cmd_name);
1098 if (cmd)
1099 {
1100 bcmcli_token_destroy(cmd);
1101 }
1102}
1103
1104/* Unregisters commands and directories */
1105static void api_cli_del_commands(bcmcli_session *session)
1106{
1107 bcmcli_entry *dir;
1108
1109 dir = bcmcli_dir_find(api_parent_dir, "api");
1110 if (!dir)
1111 {
1112 return;
1113 }
1114 api_cli_find_del_cmd(dir, "set");
1115 api_cli_find_del_cmd(dir, "get");
1116 api_cli_find_del_cmd(dir, "multiget");
1117 api_cli_find_del_cmd(dir, "clear");
1118 api_cli_find_del_cmd(dir, "modify");
1119 api_cli_find_del_cmd(dir, "stat");
1120 api_cli_find_del_cmd(dir, "oper");
1121 api_cli_find_del_cmd(dir, "send");
1122 api_cli_find_del_cmd(dir, "saset");
1123 api_cli_find_del_cmd(dir, "saget");
1124 api_cli_find_del_cmd(dir, "acset");
1125 api_cli_find_del_cmd(dir, "acget");
1126 api_cli_find_del_cmd(dir, "objects");
1127#ifdef BCM_SUBSYSTEM_HOST
1128 api_cli_find_del_cmd(dir, "log");
1129#endif
1130}
1131
1132/* Registers commands and directories */
1133static bcmos_errno api_cli_add_commands(bcmcli_session *session)
1134{
1135 bcmcli_entry *api_dir;
1136 bcmos_errno rc;
1137
1138 if ((api_dir = bcmcli_dir_find(api_parent_dir, "api")) == NULL)
1139 {
1140 api_dir = bcmcli_dir_add(api_parent_dir, "api", "Maple API", BCMCLI_ACCESS_GUEST, NULL);
1141 if (api_dir == NULL)
1142 {
1143 bcmcli_session_print(session, "Can't create api directory\n");
1144 return BCM_ERR_INTERNAL;
1145 }
1146 }
1147
1148 current_session = session;
1149 bcmolt_system_mode_get(current_device, &current_system_mode);
1150
1151 /* Now generate and add commands */
1152 rc = _api_cli_add(api_dir, "set", "Set object configuration", BCMOLT_MGT_GROUP_CFG,
1153 BCMOLT_PROP_ACCESS_ID_W, _apicli_set_handler, API_CLI_FLAGS_NONE);
1154 rc = rc ? rc : _api_cli_add(api_dir, "get", "Get object configuration", BCMOLT_MGT_GROUP_CFG,
1155 BCMOLT_PROP_ACCESS_ID_R, _apicli_get_handler, API_CLI_FLAGS_NONE);
1156 rc = rc ? rc : _api_cli_add(api_dir, "clear", "Clear object configuration", BCMOLT_MGT_GROUP_CFG,
1157 BCMOLT_PROP_ACCESS_ID_R, _apicli_clear_handler, API_CLI_FLAGS_IGNORE_FIELDS);
1158 rc = rc ? rc : _api_cli_add(api_dir, "stat", "Get statistics", BCMOLT_MGT_GROUP_STAT, BCMOLT_PROP_ACCESS_ID_R,
1159 _apicli_stat_handler, API_CLI_FLAGS_NONE);
1160 rc = rc ? rc : _api_cli_add(api_dir, "oper", "Initiate Operation", BCMOLT_MGT_GROUP_OPER,
1161 BCMOLT_PROP_ACCESS_ID_W, _apicli_oper_handler, API_CLI_FLAGS_NONE);
1162 rc = rc ? rc : _api_cli_add(api_dir, "send", "Send message to ONU", BCMOLT_MGT_GROUP_PROXY,
1163 BCMOLT_PROP_ACCESS_ID_W, _apicli_send_handler, API_CLI_FLAGS_NONE);
1164 rc = rc ? rc : _api_cli_add(api_dir, "saset", "Set statistic alarm configuration",
1165 BCMOLT_MGT_GROUP_STAT_CFG, BCMOLT_PROP_ACCESS_ID_W, _apicli_stat_cfg_set_handler, API_CLI_FLAGS_NONE);
1166 rc = rc ? rc : _api_cli_add(api_dir, "saget", "Get statistic alarm configuration",
1167 BCMOLT_MGT_GROUP_STAT_CFG, BCMOLT_PROP_ACCESS_ID_R, _apicli_stat_cfg_get_handler, API_CLI_FLAGS_IGNORE_FIELDS);
1168 rc = rc ? rc : _api_cli_add(api_dir, "acset", "Set autonomous message configuration",
1169 BCMOLT_MGT_GROUP_AUTO_CFG, BCMOLT_PROP_ACCESS_ID_W, _apicli_auto_cfg_set_handler, API_CLI_FLAGS_NONE);
1170 rc = rc ? rc : _api_cli_add(api_dir, "acget", "Get autonomous message configuration",
1171 BCMOLT_MGT_GROUP_AUTO_CFG, BCMOLT_PROP_ACCESS_ID_R, _apicli_auto_cfg_get_handler, API_CLI_FLAGS_NONE);
1172 rc = rc ? rc : _api_cli_add(api_dir, "multiget", "Get configuration for multiple objects",
1173 BCMOLT_MGT_GROUP_CFG, BCMOLT_PROP_ACCESS_ID_R, _apicli_auto_cfg_get_multi_handler, API_CLI_FLAGS_MULTI);
1174
1175 /* List all system objects */
1176 rc = rc ? rc : bcmcli_cmd_add(api_dir, "objects", _apicli_objects_handler,
1177 "Object Types", BCMCLI_ACCESS_GUEST, NULL, NULL);
1178
1179#if defined(BCM_SUBSYSTEM_HOST) && defined(LINUX_USER_SPACE)
1180 BCMCLI_MAKE_CMD(api_dir, "log", "Log API calls", _apicli_log_handler,
1181 BCMCLI_MAKE_PARM("file", "Log file. Use \"-\" to disable logging", BCMCLI_PARM_STRING, 0));
1182#endif
1183
1184 return rc;
1185}
1186
1187/* Update API CLI commands for the current device */
1188bcmos_errno api_cli_set_commands(bcmcli_session *session)
1189{
1190 bcmos_errno rc;
1191 api_cli_del_commands(session);
1192 rc = api_cli_add_commands(session);
1193 return rc;
1194}
1195
1196/* Init API CLI commands for the current device */
1197bcmos_errno api_cli_init(bcmcli_entry *parent_dir, bcmcli_session *session)
1198{
1199 bcmos_errno rc;
1200
1201 api_parent_dir = parent_dir;
1202
1203 rc = api_cli_set_commands(session);
1204
1205#ifdef BCM_SUBSYSTEM_HOST
1206 /* Subscribe for device change indication */
1207 rc = rc ? rc : bcmolt_dev_sel_ind_register(_api_cli_device_change_ind);
1208#endif
1209
1210 return rc;
1211}