27 #define MAX_DISPLAY_COLUMN_WIDTH 80
28 #define RMH_PrintMsgWrapped(prefix, fmt, ...) RMHApp_PrintWrapped(app, RMH_LOG_MESSAGE, __FUNCTION__, __LINE__, prefix, fmt, ##__VA_ARGS__);
35 const RMHApp_API* RMHApp_FindHandler(
const RMHApp *app,
const char *apiName) {
37 for (i=0; i != app->handledAPIs.apiListSize; i++) {
38 if (strcasecmp(app->handledAPIs.apiList[i].apiName, apiName) == 0) {
39 return &app->handledAPIs.apiList[i];
44 for (i=0; i != app->handledAPIs.apiListSize; i++) {
45 if (!app->handledAPIs.apiList[i].apiAlias || strlen(app->handledAPIs.apiList[i].apiAlias) == 0)
continue;
47 char* alias=strdup(app->handledAPIs.apiList[i].apiAlias);
49 char *token = strtok(alias,
",");
51 if (strcasecmp(token, apiName) == 0) {
53 return &app->handledAPIs.apiList[i];
55 token = strtok(NULL,
",");
63 const RMH_API* RMHApp_FindAPI(
const RMHApp *app,
const char *apiName) {
65 for (i=0; i != app->allAPIs->apiListSize; i++) {
66 if (strcasecmp(app->allAPIs->apiList[i]->apiName, apiName) == 0) {
67 return app->allAPIs->apiList[i];
71 for (i=0; i != app->local.apiListSize; i++) {
72 if (strcasecmp(app->local.apiList[i]->apiName, apiName) == 0) {
73 return app->local.apiList[i];
80 RMH_Result RMHApp_FindSimilarAPIs(
const RMHApp *app,
const char *searchString,
RMH_APIList *closeMatch) {
83 closeMatch->apiListSize=0;
84 for (i=0; i != app->allAPIs->apiListSize; i++) {
85 RMH_API* api=app->allAPIs->apiList[i];
86 if (strcasestr(api->apiName, searchString) != NULL) {
87 closeMatch->apiList[closeMatch->apiListSize++]=api;
89 else if (strcasestr(api->apiDefinition, searchString) != NULL) {
90 closeMatch->apiList[closeMatch->apiListSize++]=api;
92 else if (strcasestr(api->apiDescription, searchString) != NULL) {
93 closeMatch->apiList[closeMatch->apiListSize++]=api;
95 else if (strcasestr(api->tags, searchString) != NULL) {
96 closeMatch->apiList[closeMatch->apiListSize++]=api;
99 for (j=0; j != api->apiNumParams; j++) {
100 if (strcasestr(api->apiParams[j].desc, searchString) != NULL) {
101 closeMatch->apiList[closeMatch->apiListSize++]=api;
107 return (closeMatch && closeMatch->apiListSize) ? RMH_SUCCESS : RMH_FAILURE;
114 void RMHApp_PrintWrapped(
RMHApp *app,
const RMH_LogLevel level,
const char *filename,
const uint32_t lineNumber,
const char *prefix,
const char *format, ...) {
116 va_start(args, format);
118 vasprintf (&
string, format, args);
122 char *lastBreak = string;
123 char *printEnd = string;
124 char *printStart=NULL;
125 char *lastFoundSpace=NULL;
126 int length = strlen(
string);
127 int maxWidth = MAX_DISPLAY_COLUMN_WIDTH - strlen(prefix);
133 if( !printStart && *printEnd !=
' ' ) printStart = printEnd;
134 if (*printEnd ==
'\0' || *printEnd ==
'\n')
break;
136 if( *printEnd ==
' ' ) lastFoundSpace=printEnd;
137 if ( printStart && lastFoundSpace && (printEnd >= printStart+maxWidth)) {
138 printEnd = lastFoundSpace;
145 if (printStart) RMH_PrintMsg(
"%s%s\n", prefix, printStart);
146 length -= printEnd-lastBreak;
147 lastBreak = printEnd;
156 RMH_Result RMHApp_PrintHelp(
RMHApp *app) {
157 RMH_PrintMsg(
"usage: rmh [-?|-h|--help] [-t|--trace] [-d|--debug] [-s|--search] [-l|--list]\n");
158 RMH_PrintMsg(
" <API> [<args>]\n");
160 RMH_PrintMsg(
" --help Print this help message\n");
161 RMH_PrintMsg(
" --list Print a list of all available RMH APIs\n");
162 RMH_PrintMsg(
" --debug Monitor MoCA driver level debug logs\n");
163 RMH_PrintMsg(
" --trace Enable API trace messages\n");
164 RMH_PrintMsg(
" --search Print a menu of all APIs matching the string passed as <API>\n");
166 RMH_PrintMsg(
"'rmh --help <API>' will show detailed information about what that API does\n");
168 RMH_PrintMsg(
"You can run 'rmh' with no parameters to see a menu of available APIs.\n");
175 RMH_Result RMHApp_PrintAPIHelp(
RMHApp *app,
const RMH_API* api) {
179 int rmh_args_written =0;
180 const RMHApp_API *apiHandler=RMHApp_FindHandler(app, api->apiName);
183 RMH_PrintMsg(
"****************************************\n");
184 RMH_PrintMsg(
"API:\n");
185 RMH_PrintMsg(
" %s\n\n", api->apiName);
187 RMH_PrintMsg(
"ALIAS:\n");
188 if (apiHandler && apiHandler->apiAlias) {
189 RMH_PrintMsg(
" %s\n\n", apiHandler->apiAlias);
192 RMH_PrintMsg(
" None\n\n");
195 if (api->apiDefinition) {
196 RMH_PrintMsg(
"DECLARATION:\n");
197 RMH_PrintMsg(
" %s\n\n", api->apiDefinition);
200 if (api->apiDescription) {
201 RMH_PrintMsg(
"DESCRIPTION:\n");
202 RMH_PrintMsgWrapped(
" ",
"%s\n\n", api->apiDescription);
206 for (i=0; i != api->apiNumParams; i++) {
207 if (api->apiParams[i].direction == RMH_INPUT_PARAM) {
209 RMH_PrintMsg(
"INPUT PARAMETERS:\n");
212 RMH_PrintMsg(
" <%s>\n", api->apiParams[i].name);
213 RMH_PrintMsgWrapped(
" ",
"%s\n\n", api->apiParams[i].desc);
214 if ((rmh_args_written != 0 || strstr(api->apiParams[i].type,
"RMH_Handle") == NULL) &&
215 (
sizeof(rmh_args)/
sizeof(rmh_args[0]) - rmh_args_written > 0))
217 rmh_args_written += sprintf( &rmh_args[rmh_args_written],
"<%s> ", api->apiParams[i].name);
222 for (i=0; i != api->apiNumParams; i++) {
223 if (api->apiParams[i].direction == RMH_OUTPUT_PARAM) {
225 RMH_PrintMsg(
"OUTPUT PARAMETERS:\n");
228 RMH_PrintMsg(
" <%s>\n", api->apiParams[i].name);
229 RMH_PrintMsgWrapped(
" ",
"%s\n\n", api->apiParams[i].desc);
234 RMH_PrintMsg(
"USAGE:\n");
235 RMH_PrintMsg(
" rmh %s %s\n\n", api->apiName, rmh_args);
237 RMH_PrintMsg(
"****************************************\n\n\n");
242 RMH_Result RMHApp_PrintList(
RMHApp *app,
const RMH_APIList *list,
const char *exitString) {
244 RMH_PrintMsg(
"\n\n");
245 RMH_PrintMsg(
"%02d. %s\n", 1, exitString);
247 for (i=0; i != list->apiListSize; i++) {
248 RMH_PrintMsg(
"%02d. %s\n", i+2, list->apiList[i]->apiName);
257 RMH_PrintMsg(
"\n\n");
258 RMH_PrintMsg(
"%02d. %s\n", 1,
"Exit");
259 RMH_PrintMsg(
"%02d. %s\n", 2,
"All APIs");
260 RMH_PrintMsg(
"%02d. %s\n", 3,
"SoC Unimplemented APIs");
261 RMH_PrintMsg(
"%02d. %s\n", 4,
"RMH Local APIs");
263 for (i=0; i != tagList->tagListSize; i++) {
264 RMH_PrintMsg(
"%02d. %s\n", i+5, tagList->tagList[i].apiListName);
275 static RMHApp* gIntApp=NULL;
277 void RMHApp_CleanupOnInt(
int sig) {
286 RMH_Result RMHApp_ExecuteMonitorDriverDebug(
RMHApp *app) {
288 signal(SIGINT, RMHApp_CleanupOnInt);
290 RMH_PrintMsg(
"Monitoring for callbacks and MoCA logs. Press enter to exit...\n");
292 RMH_PrintErr(
"Failed to set callback events! Unable to monitor\n");
297 RMH_PrintWrn(
"Failed to get driver log level. Assuming default!\n");
298 app->driverLogLevel = RMH_LOG_DEFAULT;
302 RMH_PrintErr(
"Failed to set log level to include RMH_LOG_DEBUG!\n");
312 RMH_Result RMHApp_ExecuteAPIList(
RMHApp *app,
const RMH_APIList *list,
const char *exitString) {
314 bool helpRequested =
false;
316 RMHApp_PrintList(app, list, exitString);
318 if (RMHApp_ReadMenuOption(app, &option,
true, &helpRequested) == RMH_SUCCESS) {
320 if ( option == 1 )
break;
323 if (list && option<list->apiListSize) {
325 const RMH_API* api = list->apiList[option];
326 if (app->argHelpRequested || helpRequested) {
327 RMHApp_PrintAPIHelp(app, api);
330 RMH_PrintMsg(
" ----------------------------------------------------------------------------\n");
331 RMH_PrintMsg(
"|%s\n", api->apiName);
332 RMH_PrintMsg(
"|----------------------------------------------------------------------------\n");
335 const RMHApp_API *apiHandler=RMHApp_FindHandler(app, api->apiName);
336 if (apiHandler == NULL) {
337 RMH_PrintErr(
"The RMH library supports '%s' however it has not been exposed in RMH!\n", api->apiName);
338 RMH_PrintErr(
"Please add a handler function for this API in the rmh test by using SET_API_HANDLER()\n");
342 ret = apiHandler->apiHandlerFunc(app, apiHandler->apiFunc);
344 if (ret != RMH_SUCCESS) {
348 RMH_PrintMsg(
" ----------------------------------------------------------------------------\n\n\n");
352 RMH_PrintErr(
"Invalid selection\n");
354 RMHApp_PrintList(app, list, exitString);
361 RMH_Result RMHApp_ExecuteCommand(
RMHApp *app) {
363 if (app->argPrintMatch) {
365 RMHApp_FindSimilarAPIs(app, app->argRunCommand, &closeMatch);
366 if (closeMatch.apiListSize == 0) {
367 RMH_PrintErr(
"RMH has no API named '%s' and no other API seem to be related to this\n", app->argRunCommand);
372 app->argRunCommand=NULL;
373 return RMHApp_ExecuteAPIList(app, &closeMatch,
"Exit");
377 const RMHApp_API* apiHandler=RMHApp_FindHandler(app, app->argRunCommand);
378 if (app->argHelpRequested) {
379 api = RMHApp_FindAPI(app, apiHandler ? apiHandler->apiName : app->argRunCommand);
381 RMH_PrintErr(
"RMH has no API named '%s'\n", app->argRunCommand);
384 return RMHApp_PrintAPIHelp(app, api);
387 if (apiHandler == NULL) {
388 api=RMHApp_FindAPI(app, app->argRunCommand);
390 RMH_PrintErr(
"RMH has no API named '%s'\n", app->argRunCommand);
393 RMH_PrintErr(
"RMH has supports the API '%s' however it has not been exposed in RMH. Please add a handler function for this API in the rmh test by using SET_API_HANDLER()\n", app->argRunCommand);
396 return apiHandler->apiHandlerFunc(app, apiHandler->apiFunc);
404 RMH_SetEventCallbacks(app->rmh, RMH_EVENT_LINK_STATUS_CHANGED | RMH_EVENT_MOCA_VERSION_CHANGED | RMH_EVENT_API_PRINT);
405 RMHApp_PrintTagList(app, tagList);
407 if (RMHApp_ReadMenuOption(app, &option,
false, NULL)==RMH_SUCCESS){
411 else if (option==2) {
412 RMHApp_ExecuteAPIList(app, app->allAPIs,
"Go back");
414 else if (option==3) {
415 RMHApp_ExecuteAPIList(app, app->unimplementedAPIs,
"Go back");
417 else if (option==4) {
418 RMHApp_ExecuteAPIList(app, &app->local,
"Go back");
422 if (tagList && option < tagList->tagListSize) {
423 RMHApp_ExecuteAPIList(app, &tagList->tagList[option],
"Go back");
427 RMH_PrintErr(
"Invalid selection\n");
429 RMHApp_PrintTagList(app, tagList);
438 void RMHApp_EventCallback(
const enum RMH_Event event,
const struct RMH_EventData *eventData,
void* userContext){
441 case RMH_EVENT_LINK_STATUS_CHANGED:
442 RMH_PrintMsg(
"\n%p: Link status changed to %s\n", userContext,
RMH_LinkStatusToString(eventData->RMH_EVENT_LINK_STATUS_CHANGED.status));
444 case RMH_EVENT_MOCA_VERSION_CHANGED:
445 RMH_PrintMsg(
"\n%p: MoCA Version Changed to %s\n", userContext,
RMH_MoCAVersionToString(eventData->RMH_EVENT_MOCA_VERSION_CHANGED.version));
447 case RMH_EVENT_API_PRINT:
448 RMH_PrintMsg(
"%s", eventData->RMH_EVENT_API_PRINT.logMsg);
450 case RMH_EVENT_DRIVER_PRINT:
451 RMH_PrintMsg(
"%s", eventData->RMH_EVENT_DRIVER_PRINT.logMsg);
454 RMH_PrintWrn(
"Unhandled MoCA event %u!\n", event);
460 RMH_Result RMHApp_ParseOptions(
RMHApp *app) {
461 RMHApp_ReadNextArg(app);
464 const char* option=RMHApp_ReadNextArg(app);
467 if (option[0] ==
'-') {
468 if (strcmp(option,
"-d") == 0 || strcmp(option,
"--debug") == 0) {
469 app->argMonitorDriverDebug =
true;
470 }
else if (strcmp(option,
"-t") == 0 || strcmp(option,
"--trace") == 0) {
471 app->apiLogLevel |= RMH_LOG_TRACE;
472 }
else if (strcmp(option,
"-?") == 0 || strcmp(option,
"-h") == 0 || strcmp(option,
"--help") == 0) {
473 app->argHelpRequested =
true;
474 }
else if (strcmp(option,
"-s") == 0 || strcmp(option,
"--search") == 0) {
475 app->argPrintMatch =
true;
476 }
else if (strcmp(option,
"-l") == 0 || strcmp(option,
"--list") == 0) {
477 app->argPrintApis =
true;
480 RMH_PrintWrn(
"Unknown option '%s'! Skipping\n", option);
485 app->argRunCommand = option;
498 int main(
int argc,
char *argv[])
504 memset(app, 0,
sizeof(*app));
505 app->apiLogLevel = RMH_LOG_DEFAULT;
508 RMHApp_ParseOptions(app);
512 RMH_PrintErr(
"Failed in RMH_Initialize!\n");
517 RMH_PrintErr(
"Failed to get list of all APIs!\n");
522 RMH_PrintErr(
"Failed to set the log level!\n");
526 RMH_PrintErr(
"Failed to set event callbacks!\n");
530 RMH_PrintErr(
"Failed to get list of all unimplemented APIs!\n");
534 RMH_PrintErr(
"Failed to get list of all API tags!\n");
537 RMHApp_RegisterAPIHandlers(app);
539 if (app->argRunCommand) {
540 result = RMHApp_ExecuteCommand(app);
542 else if (app->argPrintApis) {
544 for (i=0; i != app->allAPIs->apiListSize; i++) {
545 RMH_PrintMsg(
"%s\n", app->allAPIs->apiList[i]->apiName);
546 if (app->argHelpRequested) {
547 RMH_PrintMsgWrapped(
" ",
"%s\n\n", app->allAPIs->apiList[i]->apiDescription);
552 else if (app->argMonitorDriverDebug) {
553 result = RMHApp_ExecuteMonitorDriverDebug(app);
555 else if (app->argHelpRequested) {
556 result=RMHApp_PrintHelp(app);
559 result = RMHApp_ExecuteTagList(app, app->rmhAPITags);