halcmd_commands.c
1 /* Copyright (C) 2007 Jeff Epler <jepler@unpythonic.net> 2 * Copyright (C) 2003 John Kasunich 3 * <jmkasunich AT users DOT sourceforge DOT net> 4 * 5 * Other contributers: 6 * Martin Kuhnle 7 * <mkuhnle AT users DOT sourceforge DOT net> 8 * Alex Joni 9 * <alex_joni AT users DOT sourceforge DOT net> 10 * Benn Lipkowitz 11 * <fenn AT users DOT sourceforge DOT net> 12 * Stephen Wille Padnos 13 * <swpadnos AT users DOT sourceforge DOT net> 14 * 15 * This program is free software; you can redistribute it and/or 16 * modify it under the terms of version 2 of the GNU General 17 * Public License as published by the Free Software Foundation. 18 * This library is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public 24 * License along with this library; if not, write to the Free Software 25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 26 * 27 * THE AUTHORS OF THIS LIBRARY ACCEPT ABSOLUTELY NO LIABILITY FOR 28 * ANY HARM OR LOSS RESULTING FROM ITS USE. IT IS _EXTREMELY_ UNWISE 29 * TO RELY ON SOFTWARE ALONE FOR SAFETY. Any machinery capable of 30 * harming persons must have provisions for completely removing power 31 * from all motors, etc, before persons enter any danger area. All 32 * machinery must be designed to comply with local and national safety 33 * codes, and the authors of this software can not, and do not, take 34 * any responsibility for such compliance. 35 * 36 * This code was written as part of the EMC HAL project. For more 37 * information, go to www.linuxcnc.org. 38 */ 39 40 #include "config.h" 41 #include "rtapi.h" /* RTAPI realtime OS API */ 42 #include "hal.h" /* HAL public API decls */ 43 #include "../hal_priv.h" /* private HAL decls */ 44 #include "halcmd_commands.h" 45 #include <rtapi_mutex.h> 46 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <ctype.h> 50 #include <string.h> 51 #include <sys/stat.h> 52 #include <sys/wait.h> 53 #include <unistd.h> 54 #include <fcntl.h> 55 #include <errno.h> 56 #include <time.h> 57 #include <fnmatch.h> 58 59 60 static int unloadrt_comp(char *mod_name); 61 static void print_comp_info(char **patterns); 62 static void print_pin_info(int type, char **patterns); 63 static void print_pin_aliases(char **patterns); 64 static void print_param_aliases(char **patterns); 65 static void print_sig_info(int type, char **patterns); 66 static void print_script_sig_info(int type, char **patterns); 67 static void print_param_info(int type, char **patterns); 68 static void print_funct_info(char **patterns); 69 static void print_thread_info(char **patterns); 70 static void print_comp_names(char **patterns); 71 static void print_pin_names(char **patterns); 72 static void print_sig_names(char **patterns); 73 static void print_param_names(char **patterns); 74 static void print_funct_names(char **patterns); 75 static void print_thread_names(char **patterns); 76 static void print_lock_status(); 77 static int count_list(int list_root); 78 static void print_mem_status(); 79 static const char *data_type(int type); 80 static const char *data_type2(int type); 81 static const char *pin_data_dir(int dir); 82 static const char *param_data_dir(int dir); 83 static const char *data_arrow1(int dir); 84 static const char *data_arrow2(int dir); 85 static char *data_value(int type, void *valptr); 86 static char *data_value2(int type, void *valptr); 87 static void save_comps(FILE *dst); 88 static void save_aliases(FILE *dst); 89 static void save_signals(FILE *dst, int only_unlinked); 90 static void save_links(FILE *dst, int arrows); 91 static void save_nets(FILE *dst, int arrows); 92 static void save_params(FILE *dst); 93 static void save_unconnected_input_pin_values(FILE *dst); 94 static void save_threads(FILE *dst); 95 static void print_help_commands(void); 96 97 static int tmatch(int req_type, int type) { 98 return req_type == -1 || type == req_type; 99 } 100 101 static int match(char **patterns, char *value) { 102 int i; 103 if(!patterns || !patterns[0] || !patterns[0][0]) return 1; 104 for(i=0; patterns[i] && *patterns[i]; i++) { 105 char *pattern = patterns[i]; 106 if(strncmp(pattern, value, strlen(pattern)) == 0) return 1; 107 if (fnmatch(pattern, value, 0) == 0) return 1; 108 } 109 return 0; 110 } 111 112 int do_lock_cmd(char *command) 113 { 114 int retval=0; 115 116 /* if command is blank or "all", want to lock everything */ 117 if ((command == NULL) || (strcmp(command, "all") == 0)) { 118 retval = hal_set_lock(HAL_LOCK_ALL); 119 } else if (strcmp(command, "none") == 0) { 120 retval = hal_set_lock(HAL_LOCK_NONE); 121 } else if (strcmp(command, "tune") == 0) { 122 retval = hal_set_lock(HAL_LOCK_LOAD & HAL_LOCK_CONFIG); 123 } else if (strcmp(command, "all") == 0) { 124 retval = hal_set_lock(HAL_LOCK_ALL); 125 } 126 127 if (retval == 0) { 128 /* print success message */ 129 halcmd_info("Locking completed"); 130 } else { 131 halcmd_error("Locking failed\n"); 132 } 133 return retval; 134 } 135 136 int do_unlock_cmd(char *command) 137 { 138 int retval=0; 139 140 /* if command is blank or "all", want to unlock everything */ 141 if ((command == NULL) || (strcmp(command, "all") == 0)) { 142 retval = hal_set_lock(HAL_LOCK_NONE); 143 } else if (strcmp(command, "all") == 0) { 144 retval = hal_set_lock(HAL_LOCK_NONE); 145 } else if (strcmp(command, "tune") == 0) { 146 retval = hal_set_lock(HAL_LOCK_LOAD & HAL_LOCK_CONFIG); 147 } 148 149 if (retval == 0) { 150 /* print success message */ 151 halcmd_info("Unlocking completed"); 152 } else { 153 halcmd_error("Unlocking failed\n"); 154 } 155 return retval; 156 } 157 158 int do_linkpp_cmd(char *first_pin_name, char *second_pin_name) 159 { 160 int retval; 161 hal_pin_t *first_pin, *second_pin; 162 static int dep_msg_printed = 0; 163 164 if ( dep_msg_printed == 0 ) { 165 halcmd_warning("linkpp command is deprecated, use 'net'\n"); 166 dep_msg_printed = 1; 167 } 168 rtapi_mutex_get(&(hal_data->mutex)); 169 /* check if the pins are there */ 170 first_pin = halpr_find_pin_by_name(first_pin_name); 171 second_pin = halpr_find_pin_by_name(second_pin_name); 172 if (first_pin == 0) { 173 /* first pin not found*/ 174 rtapi_mutex_give(&(hal_data->mutex)); 175 halcmd_error("pin '%s' not found\n", first_pin_name); 176 return -EINVAL; 177 } else if (second_pin == 0) { 178 rtapi_mutex_give(&(hal_data->mutex)); 179 halcmd_error("pin '%s' not found\n", second_pin_name); 180 return -EINVAL; 181 } 182 183 /* give the mutex, as the other functions use their own mutex */ 184 rtapi_mutex_give(&(hal_data->mutex)); 185 186 /* check that both pins have the same type, 187 don't want to create a sig, which after that won't be useful */ 188 if (first_pin->type != second_pin->type) { 189 halcmd_error("pins '%s' and '%s' not of the same type\n", 190 first_pin_name, second_pin_name); 191 return -EINVAL; 192 } 193 194 /* now create the signal */ 195 retval = hal_signal_new(first_pin_name, first_pin->type); 196 197 if (retval == 0) { 198 /* if it worked, link the pins to it */ 199 retval = hal_link(first_pin_name, first_pin_name); 200 201 if ( retval == 0 ) { 202 /* if that worked, link the second pin to the new signal */ 203 retval = hal_link(second_pin_name, first_pin_name); 204 } 205 } 206 if (retval < 0) { 207 halcmd_error("linkpp failed\n"); 208 } 209 return retval; 210 } 211 212 int do_linkps_cmd(char *pin, char *sig) 213 { 214 int retval; 215 216 retval = hal_link(pin, sig); 217 if (retval == 0) { 218 /* print success message */ 219 halcmd_info("Pin '%s' linked to signal '%s'\n", pin, sig); 220 } else { 221 halcmd_error("link failed\n"); 222 } 223 return retval; 224 } 225 226 int do_linksp_cmd(char *sig, char *pin) { 227 return do_linkps_cmd(pin, sig); 228 } 229 230 231 int do_unlinkp_cmd(char *pin) 232 { 233 int retval; 234 235 retval = hal_unlink(pin); 236 if (retval == 0) { 237 /* print success message */ 238 halcmd_info("Pin '%s' unlinked\n", pin); 239 } else { 240 halcmd_error("unlink failed\n"); 241 } 242 return retval; 243 } 244 245 int do_source_cmd(char *hal_filename) { 246 FILE *f = fopen(hal_filename, "r"); 247 char buf[MAX_CMD_LEN+1]; 248 int fd; 249 int result = 0; 250 int lineno_save = halcmd_get_linenumber(); 251 int linenumber = 1; 252 char *filename_save = strdup(halcmd_get_filename()); 253 254 if(!f) { 255 fprintf(stderr, "Could not open hal file '%s': %s\n", 256 hal_filename, strerror(errno)); 257 free(filename_save); 258 return -EINVAL; 259 } 260 fd = fileno(f); 261 fcntl(fd, F_SETFD, FD_CLOEXEC); 262 263 halcmd_set_filename(hal_filename); 264 265 while(1) { 266 char *readresult = fgets(buf, MAX_CMD_LEN, f); 267 halcmd_set_linenumber(linenumber++); 268 if(readresult == 0) { 269 if(feof(f)) break; 270 halcmd_error("Error reading file: %s\n", strerror(errno)); 271 result = -EINVAL; 272 break; 273 } 274 result = halcmd_parse_line(buf); 275 if(result != 0) break; 276 } 277 278 halcmd_set_linenumber(lineno_save); 279 halcmd_set_filename(filename_save); 280 free(filename_save); 281 fclose(f); 282 return result; 283 } 284 285 int do_start_cmd(void) { 286 int retval = hal_start_threads(); 287 if (retval == 0) { 288 /* print success message */ 289 halcmd_info("Realtime threads started\n"); 290 } 291 return retval; 292 } 293 294 int do_stop_cmd(void) { 295 int retval = hal_stop_threads(); 296 if (retval == 0) { 297 /* print success message */ 298 halcmd_info("Realtime threads stopped\n"); 299 } 300 return retval; 301 } 302 303 int do_echo_cmd(void) { 304 printf("Echo on\n"); 305 return 0; 306 } 307 int do_unecho_cmd(void) { 308 printf("Echo off\n"); 309 return 0; 310 } 311 int do_addf_cmd(char *func, char *thread, char **opt) { 312 char *position_str = opt ? opt[0] : NULL; 313 int position = -1; 314 int retval; 315 316 if(position_str && *position_str) position = atoi(position_str); 317 318 retval = hal_add_funct_to_thread(func, thread, position); 319 if(retval == 0) { 320 halcmd_info("Function '%s' added to thread '%s'\n", 321 func, thread); 322 } else { 323 halcmd_error("addf failed\n"); 324 } 325 return retval; 326 } 327 328 int do_alias_cmd(char *pinparam, char *name, char *alias) { 329 int retval; 330 331 if ( strcmp (pinparam, "pin" ) == 0 ) { 332 retval = hal_pin_alias(name, alias); 333 } else if ( strcmp (pinparam, "param" ) == 0 ) { 334 retval = hal_param_alias(name, alias); 335 } else { 336 retval = -EINVAL; 337 } 338 if(retval == 0) { 339 halcmd_info("%s '%s' aliased to '%s'\n", 340 pinparam, name, alias); 341 } else { 342 halcmd_error("alias failed\n"); 343 } 344 return retval; 345 } 346 347 int do_unalias_cmd(char *pinparam, char *name) { 348 int retval; 349 if (strcmp(pinparam, "pin") == 0) { 350 retval = hal_pin_alias(name, NULL); 351 } else if ( strcmp (pinparam, "param" ) == 0 ) { 352 retval = hal_param_alias(name, NULL); 353 } else { 354 return -EINVAL; 355 }; 356 if(retval == 0) { 357 halcmd_info("%s '%s' unaliased\n", 358 pinparam, name); 359 } else { 360 halcmd_error("unalias failed\n"); 361 } 362 return retval; 363 } 364 int do_delf_cmd(char *func, char *thread) { 365 int retval; 366 367 retval = hal_del_funct_from_thread(func, thread); 368 if(retval == 0) { 369 halcmd_info("Function '%s' removed from thread '%s'\n", 370 func, thread); 371 } else { 372 halcmd_error("delf failed\n"); 373 } 374 375 return retval; 376 } 377 378 static int preflight_net_cmd(char *signal, hal_sig_t *sig, char *pins[]) { 379 int i, type=-1, writers=0, bidirs=0, pincnt=0; 380 char *writer_name=0, *bidir_name=0; 381 /* if signal already exists, use its info */ 382 if (sig) { 383 type = sig->type; 384 writers = sig->writers; 385 bidirs = sig->bidirs; 386 } 387 388 if(writers || bidirs) 389 { 390 hal_pin_t *pin; 391 int next; 392 for(next = hal_data->pin_list_ptr; next; next=pin->next_ptr) 393 { 394 pin = SHMPTR(next); 395 if(SHMPTR(pin->signal) == sig && pin->dir == HAL_OUT) 396 writer_name = pin->name; 397 if(SHMPTR(pin->signal) == sig && pin->dir == HAL_IO) 398 bidir_name = writer_name = pin->name; 399 } 400 } 401 402 for(i=0; pins[i] && *pins[i]; i++) { 403 hal_pin_t *pin = 0; 404 pin = halpr_find_pin_by_name(pins[i]); 405 if(!pin) { 406 halcmd_error("Pin '%s' does not exist\n", 407 pins[i]); 408 return -ENOENT; 409 } 410 if(SHMPTR(pin->signal) == sig) { 411 /* Already on this signal */ 412 pincnt++; 413 continue; 414 } else if(pin->signal != 0) { 415 hal_sig_t *osig = SHMPTR(pin->signal); 416 halcmd_error("Pin '%s' was already linked to signal '%s'\n", 417 pin->name, osig->name); 418 return -EINVAL; 419 } 420 if (type == -1) { 421 /* no pre-existing type, use this pin's type */ 422 type = pin->type; 423 } 424 if(type != pin->type) { 425 halcmd_error( 426 "Signal '%s' of type '%s' cannot add pin '%s' of type '%s'\n", 427 signal, data_type2(type), pin->name, data_type2(pin->type)); 428 return -EINVAL; 429 } 430 if(pin->dir == HAL_OUT) { 431 if(writers || bidirs) { 432 dir_error: 433 halcmd_error( 434 "Signal '%s' can not add %s pin '%s', " 435 "it already has %s pin '%s'\n", 436 signal, pin_data_dir(pin->dir), pin->name, 437 bidir_name ? pin_data_dir(HAL_IO):pin_data_dir(HAL_OUT), 438 bidir_name ? bidir_name : writer_name); 439 return -EINVAL; 440 } 441 writer_name = pin->name; 442 writers++; 443 } 444 if(pin->dir == HAL_IO) { 445 if(writers) { 446 goto dir_error; 447 } 448 bidir_name = pin->name; 449 bidirs++; 450 } 451 pincnt++; 452 } 453 if(pincnt) 454 return 0; 455 halcmd_error("'net' requires at least one pin, none given\n"); 456 return -EINVAL; 457 } 458 459 int do_net_cmd(char *signal, char *pins[]) { 460 hal_sig_t *sig; 461 int i, retval; 462 463 rtapi_mutex_get(&(hal_data->mutex)); 464 /* see if signal already exists */ 465 sig = halpr_find_sig_by_name(signal); 466 467 /* verify that everything matches up (pin types, etc) */ 468 retval = preflight_net_cmd(signal, sig, pins); 469 if(retval < 0) { 470 rtapi_mutex_give(&(hal_data->mutex)); 471 return retval; 472 } 473 474 { 475 hal_pin_t *pin = halpr_find_pin_by_name(signal); 476 if(pin) { 477 halcmd_error( 478 "Signal name '%s' must not be the same as a pin. " 479 "Did you omit the signal name?\n", 480 signal); 481 rtapi_mutex_give(&(hal_data->mutex)); 482 return -ENOENT; 483 } 484 } 485 if(!sig) { 486 /* Create the signal with the type of the first pin */ 487 hal_pin_t *pin = halpr_find_pin_by_name(pins[0]); 488 rtapi_mutex_give(&(hal_data->mutex)); 489 if(!pin) { 490 return -ENOENT; 491 } 492 retval = hal_signal_new(signal, pin->type); 493 } else { 494 /* signal already exists */ 495 rtapi_mutex_give(&(hal_data->mutex)); 496 } 497 /* add pins to signal */ 498 for(i=0; retval == 0 && pins[i] && *pins[i]; i++) { 499 retval = do_linkps_cmd(pins[i], signal); 500 } 501 502 return retval; 503 } 504 505 #if 0 /* newinst deferred to version 2.2 */ 506 int do_newinst_cmd(char *comp_name, char *inst_name) { 507 hal_comp_t *comp = halpr_find_comp_by_name(comp_name); 508 509 if(!comp) { 510 halcmd_error( "No such component: %s\n", comp_name); 511 return -ENOENT; 512 } 513 if(!comp->make) { 514 halcmd_error( "%s does not support 'newinst'\n", comp_name); 515 return -ENOSYS; 516 } 517 if ( *inst_name == '\0' ) { 518 halcmd_error( "Must supply name for new instance\n"); 519 return -EINVAL; 520 } 521 522 #if defined(RTAPI_USPACE) 523 { 524 char *argv[MAX_TOK]; 525 int m = 0, result; 526 argv[m++] = EMC2_BIN_DIR "/rtapi_app"; 527 argv[m++] = "newinst"; 528 argv[m++] = comp_name; 529 argv[m++] = inst_name; 530 argv[m++] = 0; 531 result = hal_systemv(argv); 532 if(result != 0) { 533 halcmd_error( "newinst failed: %d\n", result); 534 return -EINVAL; 535 } 536 } 537 #else 538 { 539 FILE *f; 540 f = fopen("/proc/rtapi/hal/newinst", "w"); 541 if(!f) { 542 halcmd_error( "cannot open proc entry: %s\n", 543 strerror(errno)); 544 return -EINVAL; 545 } 546 547 rtapi_mutex_get(&(hal_data->mutex)); 548 549 while(hal_data->pending_constructor) { 550 struct timespec ts = {0, 100 * 1000 * 1000}; // 100ms 551 rtapi_mutex_give(&(hal_data->mutex)); 552 nanosleep(&ts, NULL); 553 rtapi_mutex_get(&(hal_data->mutex)); 554 } 555 strncpy(hal_data->constructor_prefix, inst_name, HAL_NAME_LEN); 556 hal_data->constructor_prefix[HAL_NAME_LEN]=0; 557 hal_data->pending_constructor = comp->make; 558 rtapi_mutex_give(&(hal_data->mutex)); 559 560 if(fputc(' ', f) == EOF) { 561 halcmd_error( "cannot write to proc entry: %s\n", 562 strerror(errno)); 563 fclose(f); 564 rtapi_mutex_get(&(hal_data->mutex)); 565 hal_data->pending_constructor = 0; 566 rtapi_mutex_give(&(hal_data->mutex)); 567 return -EINVAL; 568 } 569 if(fclose(f) != 0) { 570 halcmd_error( 571 "cannot close proc entry: %s\n", 572 strerror(errno)); 573 rtapi_mutex_get(&(hal_data->mutex)); 574 hal_data->pending_constructor = 0; 575 rtapi_mutex_give(&(hal_data->mutex)); 576 return -EINVAL; 577 } 578 579 while(hal_data->pending_constructor) { 580 struct timespec ts = {0, 100 * 1000 * 1000}; // 100ms 581 nanosleep(&ts, NULL); 582 } 583 } 584 #endif 585 rtapi_mutex_get(&hal_data->mutex); 586 { 587 hal_comp_t *inst = halpr_alloc_comp_struct(); 588 if (inst == 0) { 589 /* couldn't allocate structure */ 590 rtapi_mutex_give(&(hal_data->mutex)); 591 halcmd_error( 592 "insufficient memory for instance '%s'\n", inst_name); 593 return -ENOMEM; 594 } 595 inst->comp_id = comp->comp_id | 0x10000; 596 inst->mem_id = -1; 597 inst->type = 2; 598 inst->pid = 0; 599 inst->ready = 1; 600 inst->shmem_base = 0; 601 rtapi_snprintf(inst->name, sizeof(inst->name), "%s", inst_name); 602 /* insert new structure at head of list */ 603 inst->next_ptr = hal_data->comp_list_ptr; 604 hal_data->comp_list_ptr = SHMOFF(inst); 605 606 rtapi_mutex_give(&(hal_data->mutex)); 607 } 608 return 0; 609 } 610 #endif /* newinst deferred */ 611 612 int do_newsig_cmd(char *name, char *type) 613 { 614 int retval; 615 616 if (strcasecmp(type, "bit") == 0) { 617 retval = hal_signal_new(name, HAL_BIT); 618 } else if (strcasecmp(type, "float") == 0) { 619 retval = hal_signal_new(name, HAL_FLOAT); 620 } else if (strcasecmp(type, "u32") == 0) { 621 retval = hal_signal_new(name, HAL_U32); 622 } else if (strcasecmp(type, "s32") == 0) { 623 retval = hal_signal_new(name, HAL_S32); 624 } else if (strcasecmp(type, "port") == 0) { 625 retval = hal_signal_new(name, HAL_PORT); 626 } else { 627 halcmd_error("Unknown signal type '%s'\n", type); 628 retval = -EINVAL; 629 } 630 if (retval < 0) { 631 halcmd_error("newsig failed\n"); 632 } 633 return retval; 634 } 635 636 static int set_common(hal_type_t type, void *d_ptr, char *value) { 637 // This function assumes that the mutex is held 638 int retval = 0; 639 double fval; 640 long lval; 641 unsigned long ulval; 642 unsigned uval; 643 char *cp = value; 644 645 switch (type) { 646 case HAL_BIT: 647 if ((strcmp("1", value) == 0) || (strcasecmp("TRUE", value) == 0)) { 648 *(hal_bit_t *) (d_ptr) = 1; 649 } else if ((strcmp("0", value) == 0) 650 || (strcasecmp("FALSE", value)) == 0) { 651 *(hal_bit_t *) (d_ptr) = 0; 652 } else { 653 halcmd_error("value '%s' invalid for bit\n", value); 654 retval = -EINVAL; 655 } 656 break; 657 case HAL_FLOAT: 658 fval = strtod ( value, &cp ); 659 if ((*cp != '\0') && (!isspace(*cp))) { 660 /* invalid character(s) in string */ 661 halcmd_error("value '%s' invalid for float\n", value); 662 retval = -EINVAL; 663 } else { 664 *((hal_float_t *) (d_ptr)) = fval; 665 } 666 break; 667 case HAL_S32: 668 lval = strtol(value, &cp, 0); 669 if ((*cp != '\0') && (!isspace(*cp))) { 670 /* invalid chars in string */ 671 halcmd_error("value '%s' invalid for S32\n", value); 672 retval = -EINVAL; 673 } else { 674 *((hal_s32_t *) (d_ptr)) = lval; 675 } 676 break; 677 case HAL_U32: 678 ulval = strtoul(value, &cp, 0); 679 if ((*cp != '\0') && (!isspace(*cp))) { 680 /* invalid chars in string */ 681 halcmd_error("value '%s' invalid for U32\n", value); 682 retval = -EINVAL; 683 } else { 684 *((hal_u32_t *) (d_ptr)) = ulval; 685 } 686 break; 687 case HAL_PORT: 688 uval = strtoul(value, &cp, 0); 689 if ((*cp != '\0') && (!isspace(*cp))) { 690 halcmd_error("value '%s' invalid for PORT\n", value); 691 retval = -EINVAL; 692 } else { 693 if((*((hal_port_t*)d_ptr) != 0) && (hal_port_buffer_size(*((hal_port_t*)d_ptr)) > 0)) { 694 halcmd_error("port is already allocated with %u bytes.\n", hal_port_buffer_size(*((hal_port_t*)d_ptr))); 695 retval = -EINVAL; 696 } else { 697 *((hal_port_t*) (d_ptr)) = hal_port_alloc(uval); 698 } 699 } 700 break; 701 default: 702 /* Shouldn't get here, but just in case... */ 703 halcmd_error("bad type %d\n", type); 704 retval = -EINVAL; 705 } 706 return retval; 707 } 708 709 int do_setp_cmd(char *name, char *value) 710 { 711 int retval; 712 hal_param_t *param; 713 hal_pin_t *pin; 714 hal_type_t type; 715 void *d_ptr; 716 717 halcmd_info("setting parameter '%s' to '%s'\n", name, value); 718 /* get mutex before accessing shared data */ 719 rtapi_mutex_get(&(hal_data->mutex)); 720 /* search param list for name */ 721 param = halpr_find_param_by_name(name); 722 if (param == 0) { 723 pin = halpr_find_pin_by_name(name); 724 if(pin == 0) { 725 rtapi_mutex_give(&(hal_data->mutex)); 726 halcmd_error("parameter or pin '%s' not found\n", name); 727 return -EINVAL; 728 } else { 729 /* found it */ 730 type = pin->type; 731 if(pin->dir == HAL_OUT) { 732 rtapi_mutex_give(&(hal_data->mutex)); 733 halcmd_error("pin '%s' is not writable\n", name); 734 return -EINVAL; 735 } 736 if(pin->signal != 0) { 737 rtapi_mutex_give(&(hal_data->mutex)); 738 halcmd_error("pin '%s' is connected to a signal\n", name); 739 return -EINVAL; 740 } 741 // d_ptr = (void*)SHMPTR(pin->dummysig); 742 d_ptr = (void*)&pin->dummysig; 743 } 744 } else { 745 /* found it */ 746 type = param->type; 747 /* is it read only? */ 748 if (param->dir == HAL_RO) { 749 rtapi_mutex_give(&(hal_data->mutex)); 750 halcmd_error("param '%s' is not writable\n", name); 751 return -EINVAL; 752 } 753 d_ptr = SHMPTR(param->data_ptr); 754 } 755 756 retval = set_common(type, d_ptr, value); 757 758 rtapi_mutex_give(&(hal_data->mutex)); 759 if (retval == 0) { 760 /* print success message */ 761 if(param) { 762 halcmd_info("Parameter '%s' set to %s\n", name, value); 763 } else { 764 halcmd_info("Pin '%s' set to %s\n", name, value); 765 } 766 } else { 767 halcmd_error("setp failed\n"); 768 } 769 return retval; 770 771 } 772 773 int do_ptype_cmd(char *name) 774 { 775 hal_param_t *param; 776 hal_pin_t *pin; 777 hal_type_t type; 778 779 rtapi_print_msg(RTAPI_MSG_DBG, "getting parameter '%s'\n", name); 780 /* get mutex before accessing shared data */ 781 rtapi_mutex_get(&(hal_data->mutex)); 782 /* search param list for name */ 783 param = halpr_find_param_by_name(name); 784 if (param) { 785 /* found it */ 786 type = param->type; 787 halcmd_output("%s\n", data_type2(type)); 788 rtapi_mutex_give(&(hal_data->mutex)); 789 return 0; 790 } 791 792 /* not found, search pin list for name */ 793 pin = halpr_find_pin_by_name(name); 794 if(pin) { 795 /* found it */ 796 type = pin->type; 797 halcmd_output("%s\n", data_type2(type)); 798 rtapi_mutex_give(&(hal_data->mutex)); 799 return 0; 800 } 801 802 rtapi_mutex_give(&(hal_data->mutex)); 803 halcmd_error("pin or parameter '%s' not found\n", name); 804 return -EINVAL; 805 } 806 807 808 int do_getp_cmd(char *name) 809 { 810 hal_param_t *param; 811 hal_pin_t *pin; 812 hal_sig_t *sig; 813 hal_type_t type; 814 void *d_ptr; 815 816 rtapi_print_msg(RTAPI_MSG_DBG, "getting parameter '%s'\n", name); 817 /* get mutex before accessing shared data */ 818 rtapi_mutex_get(&(hal_data->mutex)); 819 /* search param list for name */ 820 param = halpr_find_param_by_name(name); 821 if (param) { 822 /* found it */ 823 type = param->type; 824 d_ptr = SHMPTR(param->data_ptr); 825 halcmd_output("%s\n", data_value2((int) type, d_ptr)); 826 rtapi_mutex_give(&(hal_data->mutex)); 827 return 0; 828 } 829 830 /* not found, search pin list for name */ 831 pin = halpr_find_pin_by_name(name); 832 if(pin) { 833 /* found it */ 834 type = pin->type; 835 if (pin->signal != 0) { 836 sig = SHMPTR(pin->signal); 837 d_ptr = SHMPTR(sig->data_ptr); 838 } else { 839 sig = 0; 840 d_ptr = &(pin->dummysig); 841 } 842 halcmd_output("%s\n", data_value2((int) type, d_ptr)); 843 rtapi_mutex_give(&(hal_data->mutex)); 844 return 0; 845 } 846 847 rtapi_mutex_give(&(hal_data->mutex)); 848 halcmd_error("pin or parameter '%s' not found\n", name); 849 return -EINVAL; 850 } 851 852 int do_sets_cmd(char *name, char *value) 853 { 854 int retval; 855 hal_sig_t *sig; 856 hal_type_t type; 857 void *d_ptr; 858 859 rtapi_print_msg(RTAPI_MSG_DBG, "setting signal '%s'\n", name); 860 /* get mutex before accessing shared data */ 861 rtapi_mutex_get(&(hal_data->mutex)); 862 /* search signal list for name */ 863 sig = halpr_find_sig_by_name(name); 864 if (sig == 0) { 865 rtapi_mutex_give(&(hal_data->mutex)); 866 halcmd_error("signal '%s' not found\n", name); 867 return -EINVAL; 868 } 869 /* found it - it have a writer? if it is a port we can set its buffer size */ 870 if ((sig->type != HAL_PORT) && (sig->writers > 0)) { 871 rtapi_mutex_give(&(hal_data->mutex)); 872 halcmd_error("signal '%s' already has writer(s)\n", name); 873 return -EINVAL; 874 } 875 /* no writer, so we can safely set it */ 876 type = sig->type; 877 d_ptr = SHMPTR(sig->data_ptr); 878 retval = set_common(type, d_ptr, value); 879 rtapi_mutex_give(&(hal_data->mutex)); 880 if (retval == 0) { 881 /* print success message */ 882 halcmd_info("Signal '%s' set to %s\n", name, value); 883 } else { 884 halcmd_error("sets failed\n"); 885 } 886 return retval; 887 888 } 889 890 int do_stype_cmd(char *name) 891 { 892 hal_sig_t *sig; 893 hal_type_t type; 894 895 rtapi_print_msg(RTAPI_MSG_DBG, "getting signal '%s'\n", name); 896 /* get mutex before accessing shared data */ 897 rtapi_mutex_get(&(hal_data->mutex)); 898 /* search signal list for name */ 899 sig = halpr_find_sig_by_name(name); 900 if (sig == 0) { 901 rtapi_mutex_give(&(hal_data->mutex)); 902 halcmd_error("signal '%s' not found\n", name); 903 return -EINVAL; 904 } 905 /* found it */ 906 type = sig->type; 907 halcmd_output("%s\n", data_type2(type)); 908 rtapi_mutex_give(&(hal_data->mutex)); 909 return 0; 910 } 911 912 int do_gets_cmd(char *name) 913 { 914 hal_sig_t *sig; 915 hal_type_t type; 916 void *d_ptr; 917 918 rtapi_print_msg(RTAPI_MSG_DBG, "getting signal '%s'\n", name); 919 /* get mutex before accessing shared data */ 920 rtapi_mutex_get(&(hal_data->mutex)); 921 /* search signal list for name */ 922 sig = halpr_find_sig_by_name(name); 923 if (sig == 0) { 924 rtapi_mutex_give(&(hal_data->mutex)); 925 halcmd_error("signal '%s' not found\n", name); 926 return -EINVAL; 927 } 928 /* found it */ 929 type = sig->type; 930 d_ptr = SHMPTR(sig->data_ptr); 931 halcmd_output("%s\n", data_value2((int) type, d_ptr)); 932 rtapi_mutex_give(&(hal_data->mutex)); 933 return 0; 934 } 935 936 static int get_type(char ***patterns) { 937 char *typestr = 0; 938 if(!(*patterns)) return -1; 939 if(!(*patterns)[0]) return -1; 940 if((*patterns)[0][0] != '-' || (*patterns)[0][1] != 't') return -1; 941 if((*patterns)[0][2]) { 942 typestr = &(*patterns)[0][2]; 943 *patterns += 1; 944 } else if((*patterns)[1][0]) { 945 typestr = (*patterns)[1]; 946 *patterns += 2; 947 } 948 if(!typestr) return -1; 949 if(strcmp(typestr, "float") == 0) return HAL_FLOAT; 950 if(strcmp(typestr, "bit") == 0) return HAL_BIT; 951 if(strcmp(typestr, "s32") == 0) return HAL_S32; 952 if(strcmp(typestr, "u32") == 0) return HAL_U32; 953 if(strcmp(typestr, "signed") == 0) return HAL_S32; 954 if(strcmp(typestr, "unsigned") == 0) return HAL_U32; 955 if(strcmp(typestr, "port") == 0) return HAL_PORT; 956 return -1; 957 } 958 959 int do_show_cmd(char *type, char **patterns) 960 { 961 962 if (rtapi_get_msg_level() == RTAPI_MSG_NONE) { 963 /* must be -Q, don't print anything */ 964 return 0; 965 } 966 if (!type || *type == '\0') { 967 /* print everything */ 968 print_comp_info(NULL); 969 print_pin_info(-1, NULL); 970 print_pin_aliases(NULL); 971 print_sig_info(-1, NULL); 972 print_param_info(-1, NULL); 973 print_param_aliases(NULL); 974 print_funct_info(NULL); 975 print_thread_info(NULL); 976 } else if (strcmp(type, "all") == 0) { 977 /* print everything, using the pattern */ 978 print_comp_info(patterns); 979 print_pin_info(-1, patterns); 980 print_pin_aliases(patterns); 981 print_sig_info(-1, patterns); 982 print_param_info(-1, patterns); 983 print_param_aliases(patterns); 984 print_funct_info(patterns); 985 print_thread_info(patterns); 986 } else if (strcmp(type, "comp") == 0) { 987 print_comp_info(patterns); 988 } else if (strcmp(type, "pin") == 0) { 989 int type = get_type(&patterns); 990 print_pin_info(type, patterns); 991 } else if (strcmp(type, "sig") == 0) { 992 int type = get_type(&patterns); 993 print_sig_info(type, patterns); 994 } else if (strcmp(type, "signal") == 0) { 995 int type = get_type(&patterns); 996 print_sig_info(type, patterns); 997 } else if (strcmp(type, "param") == 0) { 998 int type = get_type(&patterns); 999 print_param_info(type, patterns); 1000 } else if (strcmp(type, "parameter") == 0) { 1001 int type = get_type(&patterns); 1002 print_param_info(type, patterns); 1003 } else if (strcmp(type, "funct") == 0) { 1004 print_funct_info(patterns); 1005 } else if (strcmp(type, "function") == 0) { 1006 print_funct_info(patterns); 1007 } else if (strcmp(type, "thread") == 0) { 1008 print_thread_info(patterns); 1009 } else if (strcmp(type, "alias") == 0) { 1010 print_pin_aliases(patterns); 1011 print_param_aliases(patterns); 1012 } else { 1013 halcmd_error("Unknown 'show' type '%s'\n", type); 1014 return -1; 1015 } 1016 return 0; 1017 } 1018 1019 int do_list_cmd(char *type, char **patterns) 1020 { 1021 if ( !type) { 1022 halcmd_error("'list' requires type'\n"); 1023 return -1; 1024 } 1025 if (rtapi_get_msg_level() == RTAPI_MSG_NONE) { 1026 /* must be -Q, don't print anything */ 1027 return 0; 1028 } 1029 if (strcmp(type, "comp") == 0) { 1030 print_comp_names(patterns); 1031 } else if (strcmp(type, "pin") == 0) { 1032 print_pin_names(patterns); 1033 } else if (strcmp(type, "sig") == 0) { 1034 print_sig_names(patterns); 1035 } else if (strcmp(type, "signal") == 0) { 1036 print_sig_names(patterns); 1037 } else if (strcmp(type, "param") == 0) { 1038 print_param_names(patterns); 1039 } else if (strcmp(type, "parameter") == 0) { 1040 print_param_names(patterns); 1041 } else if (strcmp(type, "funct") == 0) { 1042 print_funct_names(patterns); 1043 } else if (strcmp(type, "function") == 0) { 1044 print_funct_names(patterns); 1045 } else if (strcmp(type, "thread") == 0) { 1046 print_thread_names(patterns); 1047 } else { 1048 halcmd_error("Unknown 'list' type '%s'\n", type); 1049 return -1; 1050 } 1051 return 0; 1052 } 1053 1054 int do_status_cmd(char *type) 1055 { 1056 1057 if (rtapi_get_msg_level() == RTAPI_MSG_NONE) { 1058 /* must be -Q, don't print anything */ 1059 return 0; 1060 } 1061 if ((type == NULL) || (strcmp(type, "all") == 0)) { 1062 /* print everything */ 1063 /* add other status functions here if/when they are defined */ 1064 print_lock_status(); 1065 print_mem_status(); 1066 } else if (strcmp(type, "lock") == 0) { 1067 print_lock_status(); 1068 } else if (strcmp(type, "mem") == 0) { 1069 print_mem_status(); 1070 } else { 1071 halcmd_error("Unknown 'status' type '%s'\n", type); 1072 return -1; 1073 } 1074 return 0; 1075 } 1076 1077 int do_loadrt_cmd(char *mod_name, char *args[]) 1078 { 1079 char arg_string[MAX_CMD_LEN+1]; 1080 int m=0, n=0, retval; 1081 hal_comp_t *comp; 1082 char *argv[MAX_TOK+3]; 1083 char *cp1; 1084 #if defined(RTAPI_USPACE) 1085 argv[m++] = "-Wn"; 1086 argv[m++] = mod_name; 1087 argv[m++] = EMC2_BIN_DIR "/rtapi_app"; 1088 argv[m++] = "load"; 1089 argv[m++] = mod_name; 1090 /* loop thru remaining arguments */ 1091 while ( args[n] && args[n][0] != '\0' ) { 1092 argv[m++] = args[n++]; 1093 } 1094 argv[m++] = NULL; 1095 retval = do_loadusr_cmd(argv); 1096 #else 1097 static char *rtmod_dir = EMC2_RTLIB_DIR; 1098 struct stat stat_buf; 1099 char mod_path[MAX_CMD_LEN+1]; 1100 1101 if (hal_get_lock()&HAL_LOCK_LOAD) { 1102 halcmd_error("HAL is locked, loading of modules is not permitted\n"); 1103 return -EPERM; 1104 } 1105 if ( (strlen(rtmod_dir)+strlen(mod_name)+5) > MAX_CMD_LEN ) { 1106 halcmd_error("Module path too long\n"); 1107 return -1; 1108 } 1109 1110 /* make full module name '<path>/<name>.o' */ 1111 { 1112 int r; 1113 r = snprintf(mod_path, sizeof(mod_path), "%s/%s%s", rtmod_dir, mod_name, MODULE_EXT); 1114 if (r < 0) { 1115 halcmd_error("error making module path for %s/%s%s\n", rtmod_dir, mod_name, MODULE_EXT); 1116 return -1; 1117 } else if (r >= sizeof(mod_path)) { 1118 // truncation! 1119 halcmd_error("module path too long (max %lu) for %s/%s%s\n", (unsigned long)sizeof(mod_path)-1, rtmod_dir, mod_name, MODULE_EXT); 1120 return -1; 1121 } 1122 } 1123 1124 /* is there a file with that name? */ 1125 if ( stat(mod_path, &stat_buf) != 0 ) { 1126 /* can't find it */ 1127 halcmd_error("Can't find module '%s' in %s\n", mod_name, rtmod_dir); 1128 return -1; 1129 } 1130 1131 argv[0] = EMC2_BIN_DIR "/linuxcnc_module_helper"; 1132 argv[1] = "insert"; 1133 argv[2] = mod_path; 1134 /* loop thru remaining arguments */ 1135 n = 0; 1136 m = 3; 1137 while ( args[n] && args[n][0] != '\0' ) { 1138 argv[m++] = args[n++]; 1139 } 1140 /* add a NULL to terminate the argv array */ 1141 argv[m] = NULL; 1142 1143 retval = hal_systemv(argv); 1144 #endif 1145 1146 if ( retval != 0 ) { 1147 halcmd_error("insmod for %s failed, returned %d\n" 1148 #if !defined(RTAPI_USPACE) 1149 "See the output of 'dmesg' for more information.\n" 1150 #endif 1151 , mod_name, retval ); 1152 return -1; 1153 } 1154 /* make the args that were passed to the module into a single string */ 1155 n = 0; 1156 arg_string[0] = '\0'; 1157 while ( args[n] && args[n][0] != '\0' ) { 1158 strncat(arg_string, args[n++], MAX_CMD_LEN); 1159 strncat(arg_string, " ", MAX_CMD_LEN); 1160 } 1161 /* allocate HAL shmem for the string */ 1162 cp1 = hal_malloc(strlen(arg_string)+1); 1163 if ( cp1 == NULL ) { 1164 halcmd_error("failed to allocate memory for module args\n"); 1165 return -1; 1166 } 1167 /* copy string to shmem */ 1168 strcpy (cp1, arg_string); 1169 /* get mutex before accessing shared data */ 1170 rtapi_mutex_get(&(hal_data->mutex)); 1171 /* search component list for the newly loaded component */ 1172 comp = halpr_find_comp_by_name(mod_name); 1173 if (comp == 0) { 1174 rtapi_mutex_give(&(hal_data->mutex)); 1175 halcmd_error("module '%s' not loaded\n", mod_name); 1176 return -EINVAL; 1177 } 1178 /* link args to comp struct */ 1179 comp->insmod_args = SHMOFF(cp1); 1180 rtapi_mutex_give(&(hal_data->mutex)); 1181 /* print success message */ 1182 halcmd_info("Realtime module '%s' loaded\n", mod_name); 1183 return 0; 1184 } 1185 1186 int do_delsig_cmd(char *mod_name) 1187 { 1188 int next, retval, retval1, n; 1189 hal_sig_t *sig; 1190 char sigs[MAX_EXPECTED_SIGS][HAL_NAME_LEN+1]; 1191 1192 /* check for "all" */ 1193 if ( strcmp(mod_name, "all" ) != 0 ) { 1194 retval = hal_signal_delete(mod_name); 1195 if (retval == 0) { 1196 /* print success message */ 1197 halcmd_info("Signal '%s' deleted'\n", mod_name); 1198 } 1199 return retval; 1200 } else { 1201 /* build a list of signal(s) to delete */ 1202 n = 0; 1203 rtapi_mutex_get(&(hal_data->mutex)); 1204 1205 next = hal_data->sig_list_ptr; 1206 while (next != 0) { 1207 sig = SHMPTR(next); 1208 /* we want to unload this signal, remember its name */ 1209 if ( n < ( MAX_EXPECTED_SIGS - 1 ) ) { 1210 strncpy(sigs[n], sig->name, HAL_NAME_LEN ); 1211 sigs[n][HAL_NAME_LEN] = '\0'; 1212 n++; 1213 } 1214 next = sig->next_ptr; 1215 } 1216 rtapi_mutex_give(&(hal_data->mutex)); 1217 sigs[n][0] = '\0'; 1218 1219 if ( sigs[0][0] == '\0' ) { 1220 /* desired signals not found */ 1221 halcmd_error("no signals found to be deleted\n"); 1222 return -1; 1223 } 1224 /* we now have a list of components, unload them */ 1225 n = 0; 1226 retval1 = 0; 1227 while ( sigs[n][0] != '\0' ) { 1228 retval = hal_signal_delete(sigs[n]); 1229 /* check for fatal error */ 1230 if ( retval < -1 ) { 1231 return retval; 1232 } 1233 /* check for other error */ 1234 if ( retval != 0 ) { 1235 retval1 = retval; 1236 } 1237 if (retval == 0) { 1238 /* print success message */ 1239 halcmd_info("Signal '%s' deleted'\n", 1240 sigs[n]); 1241 } 1242 n++; 1243 } 1244 } 1245 return retval1; 1246 } 1247 1248 int do_unloadusr_cmd(char *mod_name) 1249 { 1250 int next, all; 1251 hal_comp_t *comp; 1252 pid_t ourpid = getpid(); 1253 1254 /* check for "all" */ 1255 if ( strcmp(mod_name, "all" ) == 0 ) { 1256 all = 1; 1257 } else { 1258 all = 0; 1259 } 1260 /* build a list of component(s) to unload */ 1261 rtapi_mutex_get(&(hal_data->mutex)); 1262 next = hal_data->comp_list_ptr; 1263 while (next != 0) { 1264 comp = SHMPTR(next); 1265 if ( comp->type == 0 && comp->pid != ourpid) { 1266 /* found a userspace component besides us */ 1267 if ( all || ( strcmp(mod_name, comp->name) == 0 )) { 1268 /* we want to unload this component, send it SIGTERM */ 1269 kill(abs(comp->pid), SIGTERM); 1270 } 1271 } 1272 next = comp->next_ptr; 1273 } 1274 rtapi_mutex_give(&(hal_data->mutex)); 1275 return 0; 1276 } 1277 1278 1279 int do_unloadrt_cmd(char *mod_name) 1280 { 1281 int next, retval, retval1, n, all; 1282 hal_comp_t *comp; 1283 char comps[64][HAL_NAME_LEN+1]; 1284 1285 /* check for "all" */ 1286 if ( strcmp(mod_name, "all" ) == 0 ) { 1287 all = 1; 1288 } else { 1289 all = 0; 1290 } 1291 /* build a list of component(s) to unload */ 1292 n = 0; 1293 rtapi_mutex_get(&(hal_data->mutex)); 1294 next = hal_data->comp_list_ptr; 1295 while (next != 0) { 1296 comp = SHMPTR(next); 1297 if ( comp->type == 1 ) { 1298 /* found a realtime component */ 1299 if ( all || ( strcmp(mod_name, comp->name) == 0 )) { 1300 /* we want to unload this component, remember its name */ 1301 if ( n < 63 ) { 1302 strncpy(comps[n], comp->name, HAL_NAME_LEN ); 1303 comps[n][HAL_NAME_LEN] = '\0'; 1304 n++; 1305 } 1306 } 1307 } 1308 next = comp->next_ptr; 1309 } 1310 rtapi_mutex_give(&(hal_data->mutex)); 1311 /* mark end of list */ 1312 comps[n][0] = '\0'; 1313 if ( !all && ( comps[0][0] == '\0' )) { 1314 /* desired component not found */ 1315 halcmd_error("component '%s' is not loaded\n", mod_name); 1316 return -1; 1317 } 1318 /* we now have a list of components, unload them */ 1319 n = 0; 1320 retval1 = 0; 1321 while ( comps[n][0] != '\0' ) { 1322 // special case: initial prefix means it is not a real comp 1323 if (strstr(comps[n],HAL_PSEUDO_COMP_PREFIX) == comps[n] ) { 1324 n++; 1325 continue; 1326 } 1327 retval = unloadrt_comp(comps[n++]); 1328 /* check for fatal error */ 1329 if ( retval < -1 ) { 1330 return retval; 1331 } 1332 /* check for other error */ 1333 if ( retval != 0 ) { 1334 retval1 = retval; 1335 } 1336 } 1337 if (retval1 < 0) { 1338 halcmd_error("unloadrt failed\n"); 1339 } 1340 return retval1; 1341 } 1342 1343 static int unloadrt_comp(char *mod_name) 1344 { 1345 int retval; 1346 char *argv[4]; 1347 1348 #if defined(RTAPI_USPACE) 1349 argv[0] = EMC2_BIN_DIR "/rtapi_app"; 1350 argv[1] = "unload"; 1351 #else 1352 argv[0] = EMC2_BIN_DIR "/linuxcnc_module_helper"; 1353 argv[1] = "remove"; 1354 #endif 1355 argv[2] = mod_name; 1356 /* add a NULL to terminate the argv array */ 1357 argv[3] = NULL; 1358 1359 retval = hal_systemv(argv); 1360 1361 if ( retval != 0 ) { 1362 halcmd_error("rmmod failed, returned %d\n", retval); 1363 return -1; 1364 } 1365 /* print success message */ 1366 halcmd_info("Realtime module '%s' unloaded\n", 1367 mod_name); 1368 return 0; 1369 } 1370 1371 int do_unload_cmd(char *mod_name) { 1372 if(strcmp(mod_name, "all") == 0) { 1373 int res = do_unloadusr_cmd(mod_name); 1374 if(res) return res; 1375 return do_unloadrt_cmd(mod_name); 1376 } else { 1377 hal_comp_t *comp; 1378 int type = -1; 1379 rtapi_mutex_get(&(hal_data->mutex)); 1380 comp = halpr_find_comp_by_name(mod_name); 1381 if(comp) type = comp->type; 1382 rtapi_mutex_give(&(hal_data->mutex)); 1383 if(type == -1) { 1384 halcmd_error("component '%s' is not loaded\n", 1385 mod_name); 1386 return -1; 1387 } 1388 if(type == 1) return do_unloadrt_cmd(mod_name); 1389 else return do_unloadusr_cmd(mod_name); 1390 } 1391 } 1392 1393 static char *guess_comp_name(char *prog_name) 1394 { 1395 static char name[HAL_NAME_LEN+1]; 1396 char *last_slash = strrchr(prog_name, '/'); 1397 char *st = last_slash ? last_slash + 1 : prog_name; 1398 char *last_dot = strrchr(st, '.'); 1399 char *en = last_dot ? last_dot : prog_name + strlen(prog_name); 1400 size_t len = en-st; 1401 1402 snprintf(name, sizeof(name), "%.*s", (int)len, st); 1403 return name; 1404 } 1405 1406 static void reset_getopt_state() { 1407 /* 1408 1409 It turns out that it is not portable to reset the state of getopt, so that 1410 a different argv list can be parsed. 1411 1412 https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=192834 1413 1414 (though that thread ends with the bug being closed as fixed in lenny, it 1415 is not fixed or has regressed by debian jessie) 1416 */ 1417 1418 #ifdef __GNU_LIBRARY__ 1419 optind = 0; 1420 #else 1421 optind = 1; 1422 #endif 1423 1424 #ifdef HAVE_OPTRESET 1425 optreset = 1; 1426 #endif 1427 } 1428 1429 int do_loadusr_cmd(char *args[]) 1430 { 1431 int wait_flag, wait_comp_flag, ignore_flag; 1432 char *prog_name, *new_comp_name=NULL; 1433 char *argv[MAX_TOK+1]; 1434 int n, m, retval, status; 1435 pid_t pid; 1436 1437 int argc = 0; 1438 while(args[argc] && *args[argc]) argc++; 1439 args--; argc++; 1440 1441 if (hal_get_lock()&HAL_LOCK_LOAD) { 1442 halcmd_error("HAL is locked, loading of programs is not permitted\n"); 1443 return -EPERM; 1444 } 1445 wait_flag = 0; 1446 wait_comp_flag = 0; 1447 ignore_flag = 0; 1448 prog_name = NULL; 1449 1450 /* check for options (-w, -i, and/or -r) */ 1451 reset_getopt_state(); 1452 while (1) { 1453 int c = getopt(argc, args, "+wWin:"); 1454 if(c == -1) break; 1455 1456 switch(c) { 1457 case 'w': 1458 wait_flag = 1; break; 1459 case 'W': 1460 wait_comp_flag = 1; break; 1461 case 'i': 1462 ignore_flag = 1; break; 1463 case 'n': 1464 new_comp_name = optarg; break; 1465 default: 1466 return -EINVAL; 1467 break; 1468 } 1469 } 1470 /* get program and component name */ 1471 args += optind; 1472 prog_name = *args++; 1473 if (prog_name == 0) { return -EINVAL; } 1474 if(!new_comp_name) { 1475 new_comp_name = guess_comp_name(prog_name); 1476 } 1477 /* prepare to exec() the program */ 1478 argv[0] = prog_name; 1479 /* loop thru remaining arguments */ 1480 n = 0; 1481 m = 1; 1482 while ( args[n] && args[n][0] != '\0' ) { 1483 argv[m++] = args[n++]; 1484 } 1485 /* add a NULL to terminate the argv array */ 1486 argv[m] = NULL; 1487 /* start the child process */ 1488 pid = hal_systemv_nowait(argv); 1489 /* make sure we reconnected to the HAL */ 1490 if (comp_id < 0) { 1491 fprintf(stderr, "halcmd: hal_init() failed after fork: %d\n", 1492 comp_id ); 1493 exit(-1); 1494 } 1495 hal_ready(comp_id); 1496 if ( wait_comp_flag ) { 1497 int ready = 0, count=0, exited=0; 1498 hal_comp_t *comp = NULL; 1499 retval = 0; 1500 while(!ready && !exited) { 1501 /* sleep for 10mS */ 1502 struct timespec ts = {0, 10 * 1000 * 1000}; 1503 nanosleep(&ts, NULL); 1504 /* check for program ending */ 1505 retval = waitpid( pid, &status, WNOHANG ); 1506 if ( retval != 0 ) { 1507 exited = 1; 1508 if (WIFEXITED(status) && WEXITSTATUS(status)) { 1509 halcmd_error("waitpid failed %s %s\n",prog_name,new_comp_name); 1510 ready = 0; 1511 break; 1512 } 1513 } 1514 /* check for program becoming ready */ 1515 rtapi_mutex_get(&(hal_data->mutex)); 1516 comp = halpr_find_comp_by_name(new_comp_name); 1517 if(comp && comp->ready) { 1518 ready = 1; 1519 } 1520 rtapi_mutex_give(&(hal_data->mutex)); 1521 /* pacify the user */ 1522 count++; 1523 if(count == 200) { 1524 fprintf(stderr, "Waiting for component '%s' to become ready.", 1525 new_comp_name); 1526 fflush(stderr); 1527 } else if(count > 200 && count % 10 == 0) { 1528 fprintf(stderr, "."); 1529 fflush(stderr); 1530 } 1531 } 1532 if (count >= 100) { 1533 /* terminate pacifier */ 1534 fprintf(stderr, "\n"); 1535 } 1536 /* did it work? */ 1537 if (ready) { 1538 halcmd_info("Component '%s' ready\n", new_comp_name); 1539 } else { 1540 if ( retval < 0 ) { 1541 halcmd_error("\nwaitpid(%d) failed\n", pid); 1542 } else { 1543 halcmd_error("%s exited without becoming ready\n", prog_name); 1544 } 1545 return -1; 1546 } 1547 } 1548 if ( wait_flag ) { 1549 /* wait for child process to complete */ 1550 retval = waitpid ( pid, &status, 0 ); 1551 /* check result of waitpid() */ 1552 if ( retval < 0 ) { 1553 halcmd_error("waitpid(%d) failed\n", pid); 1554 return -1; 1555 } 1556 if ( WIFEXITED(status) == 0 ) { 1557 halcmd_error("program '%s' did not exit normally\n", prog_name ); 1558 return -1; 1559 } 1560 if ( ignore_flag == 0 ) { 1561 retval = WEXITSTATUS(status); 1562 if ( retval != 0 ) { 1563 halcmd_error("program '%s' failed, returned %d\n", prog_name, retval ); 1564 return -1; 1565 } 1566 } 1567 /* print success message */ 1568 halcmd_info("Program '%s' finished\n", prog_name); 1569 } else { 1570 /* print success message */ 1571 halcmd_info("Program '%s' started\n", prog_name); 1572 } 1573 return 0; 1574 } 1575 1576 1577 int do_waitusr_cmd(char *comp_name) 1578 { 1579 hal_comp_t *comp; 1580 int exited; 1581 1582 if (*comp_name == '\0') { 1583 halcmd_error("component name missing\n"); 1584 return -EINVAL; 1585 } 1586 rtapi_mutex_get(&(hal_data->mutex)); 1587 comp = halpr_find_comp_by_name(comp_name); 1588 if (comp == NULL) { 1589 rtapi_mutex_give(&(hal_data->mutex)); 1590 halcmd_info("component '%s' not found or already exited\n", comp_name); 1591 return 0; 1592 } 1593 if (comp->type != 0) { 1594 rtapi_mutex_give(&(hal_data->mutex)); 1595 halcmd_error("'%s' is not a userspace component\n", comp_name); 1596 return -EINVAL; 1597 } 1598 rtapi_mutex_give(&(hal_data->mutex)); 1599 /* let the user know what is going on */ 1600 halcmd_info("Waiting for component '%s'\n", comp_name); 1601 exited = 0; 1602 while(!exited) { 1603 /* sleep for 200mS */ 1604 struct timespec ts = {0, 200 * 1000 * 1000}; 1605 nanosleep(&ts, NULL); 1606 /* check for component still around */ 1607 rtapi_mutex_get(&(hal_data->mutex)); 1608 comp = halpr_find_comp_by_name(comp_name); 1609 if(comp == NULL) { 1610 exited = 1; 1611 } 1612 rtapi_mutex_give(&(hal_data->mutex)); 1613 } 1614 halcmd_info("Component '%s' finished\n", comp_name); 1615 return 0; 1616 } 1617 1618 1619 static void print_comp_info(char **patterns) 1620 { 1621 int next; 1622 hal_comp_t *comp; 1623 1624 if (scriptmode == 0) { 1625 halcmd_output("Loaded HAL Components:\n"); 1626 halcmd_output("ID Type %-*s PID State\n", HAL_NAME_LEN, "Name"); 1627 } 1628 rtapi_mutex_get(&(hal_data->mutex)); 1629 next = hal_data->comp_list_ptr; 1630 while (next != 0) { 1631 comp = SHMPTR(next); 1632 if ( match(patterns, comp->name) ) { 1633 if(comp->type == 2) { 1634 hal_comp_t *comp1 = halpr_find_comp_by_id(comp->comp_id & 0xffff); 1635 halcmd_output(" INST %s %s", 1636 comp1 ? comp1->name : "(unknown)", 1637 comp->name); 1638 } else { 1639 halcmd_output(" %5d %-4s %-*s", 1640 comp->comp_id, (comp->type ? "RT" : "User"), 1641 HAL_NAME_LEN, comp->name); 1642 if(comp->type == 0) { 1643 halcmd_output(" %5d %s", comp->pid, comp->ready > 0 ? 1644 "ready" : "initializing"); 1645 } else { 1646 halcmd_output(" %5s %s", "", comp->ready > 0 ? 1647 "ready" : "initializing"); 1648 } 1649 } 1650 halcmd_output("\n"); 1651 } 1652 next = comp->next_ptr; 1653 } 1654 rtapi_mutex_give(&(hal_data->mutex)); 1655 halcmd_output("\n"); 1656 } 1657 1658 static void print_pin_info(int type, char **patterns) 1659 { 1660 int next; 1661 hal_pin_t *pin; 1662 hal_comp_t *comp; 1663 hal_sig_t *sig; 1664 void *dptr; 1665 1666 if (scriptmode == 0) { 1667 halcmd_output("Component Pins:\n"); 1668 halcmd_output("Owner Type Dir Value Name\n"); 1669 } 1670 rtapi_mutex_get(&(hal_data->mutex)); 1671 next = hal_data->pin_list_ptr; 1672 while (next != 0) { 1673 pin = SHMPTR(next); 1674 if ( tmatch(type, pin->type) && match(patterns, pin->name) ) { 1675 comp = SHMPTR(pin->owner_ptr); 1676 if (pin->signal != 0) { 1677 sig = SHMPTR(pin->signal); 1678 dptr = SHMPTR(sig->data_ptr); 1679 } else { 1680 sig = 0; 1681 dptr = &(pin->dummysig); 1682 } 1683 if (scriptmode == 0) { 1684 halcmd_output(" %5d %5s %-3s %9s %s", 1685 comp->comp_id, 1686 data_type((int) pin->type), 1687 pin_data_dir((int) pin->dir), 1688 data_value((int) pin->type, dptr), 1689 pin->name); 1690 } else { 1691 halcmd_output("%s %s %s %s %s", 1692 comp->name, 1693 data_type((int) pin->type), 1694 pin_data_dir((int) pin->dir), 1695 data_value2((int) pin->type, dptr), 1696 pin->name); 1697 } 1698 if (sig == 0) { 1699 halcmd_output("\n"); 1700 } else { 1701 halcmd_output(" %s %s\n", data_arrow1((int) pin->dir), sig->name); 1702 } 1703 } 1704 next = pin->next_ptr; 1705 } 1706 rtapi_mutex_give(&(hal_data->mutex)); 1707 halcmd_output("\n"); 1708 } 1709 1710 static void print_pin_aliases(char **patterns) 1711 { 1712 int next; 1713 hal_oldname_t *oldname; 1714 hal_pin_t *pin; 1715 1716 if (scriptmode == 0) { 1717 halcmd_output("Pin Aliases:\n"); 1718 halcmd_output(" %-*s %s\n", HAL_NAME_LEN, "Alias", "Original Name"); 1719 } 1720 rtapi_mutex_get(&(hal_data->mutex)); 1721 next = hal_data->pin_list_ptr; 1722 while (next != 0) { 1723 pin = SHMPTR(next); 1724 if ( pin->oldname != 0 ) { 1725 /* name is an alias */ 1726 oldname = SHMPTR(pin->oldname); 1727 if ( match(patterns, pin->name) || match(patterns, oldname->name) ) { 1728 if (scriptmode == 0) { 1729 halcmd_output(" %-*s %s\n", HAL_NAME_LEN, pin->name, oldname->name); 1730 } else { 1731 halcmd_output(" %s %s\n", pin->name, oldname->name); 1732 } 1733 } 1734 } 1735 next = pin->next_ptr; 1736 } 1737 rtapi_mutex_give(&(hal_data->mutex)); 1738 halcmd_output("\n"); 1739 } 1740 1741 static void print_sig_info(int type, char **patterns) 1742 { 1743 int next; 1744 hal_sig_t *sig; 1745 void *dptr; 1746 hal_pin_t *pin; 1747 1748 if (scriptmode != 0) { 1749 print_script_sig_info(type, patterns); 1750 return; 1751 } 1752 halcmd_output("Signals:\n"); 1753 halcmd_output("Type Value Name (linked to)\n"); 1754 rtapi_mutex_get(&(hal_data->mutex)); 1755 next = hal_data->sig_list_ptr; 1756 while (next != 0) { 1757 sig = SHMPTR(next); 1758 if ( tmatch(type, sig->type) && match(patterns, sig->name) ) { 1759 dptr = SHMPTR(sig->data_ptr); 1760 halcmd_output("%s %s %s\n", data_type((int) sig->type), 1761 data_value((int) sig->type, dptr), sig->name); 1762 /* look for pin(s) linked to this signal */ 1763 pin = halpr_find_pin_by_sig(sig, 0); 1764 while (pin != 0) { 1765 halcmd_output(" %s %s\n", 1766 data_arrow2((int) pin->dir), pin->name); 1767 pin = halpr_find_pin_by_sig(sig, pin); 1768 } 1769 } 1770 next = sig->next_ptr; 1771 } 1772 rtapi_mutex_give(&(hal_data->mutex)); 1773 halcmd_output("\n"); 1774 } 1775 1776 static void print_script_sig_info(int type, char **patterns) 1777 { 1778 int next; 1779 hal_sig_t *sig; 1780 void *dptr; 1781 hal_pin_t *pin; 1782 1783 if (scriptmode == 0) { 1784 return; 1785 } 1786 rtapi_mutex_get(&(hal_data->mutex)); 1787 next = hal_data->sig_list_ptr; 1788 while (next != 0) { 1789 sig = SHMPTR(next); 1790 if ( tmatch(type, sig->type) && match(patterns, sig->name) ) { 1791 dptr = SHMPTR(sig->data_ptr); 1792 halcmd_output("%s %s %s", data_type((int) sig->type), 1793 data_value2((int) sig->type, dptr), sig->name); 1794 /* look for pin(s) linked to this signal */ 1795 pin = halpr_find_pin_by_sig(sig, 0); 1796 while (pin != 0) { 1797 halcmd_output(" %s %s", 1798 data_arrow2((int) pin->dir), pin->name); 1799 pin = halpr_find_pin_by_sig(sig, pin); 1800 } 1801 halcmd_output("\n"); 1802 } 1803 next = sig->next_ptr; 1804 } 1805 rtapi_mutex_give(&(hal_data->mutex)); 1806 halcmd_output("\n"); 1807 } 1808 1809 static void print_param_info(int type, char **patterns) 1810 { 1811 int next; 1812 hal_param_t *param; 1813 hal_comp_t *comp; 1814 1815 if (scriptmode == 0) { 1816 halcmd_output("Parameters:\n"); 1817 halcmd_output("Owner Type Dir Value Name\n"); 1818 } 1819 rtapi_mutex_get(&(hal_data->mutex)); 1820 next = hal_data->param_list_ptr; 1821 while (next != 0) { 1822 param = SHMPTR(next); 1823 if ( tmatch(type, param->type), match(patterns, param->name) ) { 1824 comp = SHMPTR(param->owner_ptr); 1825 if (scriptmode == 0) { 1826 halcmd_output(" %5d %5s %-3s %9s %s\n", 1827 comp->comp_id, data_type((int) param->type), 1828 param_data_dir((int) param->dir), 1829 data_value((int) param->type, SHMPTR(param->data_ptr)), 1830 param->name); 1831 } else { 1832 halcmd_output("%s %s %s %s %s\n", 1833 comp->name, data_type((int) param->type), 1834 param_data_dir((int) param->dir), 1835 data_value2((int) param->type, SHMPTR(param->data_ptr)), 1836 param->name); 1837 } 1838 } 1839 next = param->next_ptr; 1840 } 1841 rtapi_mutex_give(&(hal_data->mutex)); 1842 halcmd_output("\n"); 1843 } 1844 1845 static void print_param_aliases(char **patterns) 1846 { 1847 int next; 1848 hal_oldname_t *oldname; 1849 hal_param_t *param; 1850 1851 if (scriptmode == 0) { 1852 halcmd_output("Parameter Aliases:\n"); 1853 halcmd_output(" %-*s %s\n", HAL_NAME_LEN, "Alias", "Original Name"); 1854 } 1855 rtapi_mutex_get(&(hal_data->mutex)); 1856 next = hal_data->param_list_ptr; 1857 while (next != 0) { 1858 param = SHMPTR(next); 1859 if ( param->oldname != 0 ) { 1860 /* name is an alias */ 1861 oldname = SHMPTR(param->oldname); 1862 if ( match(patterns, param->name) || match(patterns, oldname->name) ) { 1863 if (scriptmode == 0) { 1864 halcmd_output(" %-*s %s\n", HAL_NAME_LEN, param->name, oldname->name); 1865 } else { 1866 halcmd_output(" %s %s\n", param->name, oldname->name); 1867 } 1868 } 1869 } 1870 next = param->next_ptr; 1871 } 1872 rtapi_mutex_give(&(hal_data->mutex)); 1873 halcmd_output("\n"); 1874 } 1875 1876 static void print_funct_info(char **patterns) 1877 { 1878 int next; 1879 hal_funct_t *fptr; 1880 hal_comp_t *comp; 1881 1882 if (scriptmode == 0) { 1883 halcmd_output("Exported Functions:\n"); 1884 halcmd_output("Owner CodeAddr Arg FP Users Name\n"); 1885 } 1886 rtapi_mutex_get(&(hal_data->mutex)); 1887 next = hal_data->funct_list_ptr; 1888 while (next != 0) { 1889 fptr = SHMPTR(next); 1890 if ( match(patterns, fptr->name) ) { 1891 comp = SHMPTR(fptr->owner_ptr); 1892 if (scriptmode == 0) { 1893 halcmd_output(" %05d %08lx %08lx %-3s %5d %s\n", 1894 comp->comp_id, 1895 (long)fptr->funct, 1896 (long)fptr->arg, (fptr->uses_fp ? "YES" : "NO"), 1897 fptr->users, fptr->name); 1898 } else { 1899 halcmd_output("%s %08lx %08lx %s %3d %s\n", 1900 comp->name, 1901 (long)fptr->funct, 1902 (long)fptr->arg, (fptr->uses_fp ? "YES" : "NO"), 1903 fptr->users, fptr->name); 1904 } 1905 } 1906 next = fptr->next_ptr; 1907 } 1908 rtapi_mutex_give(&(hal_data->mutex)); 1909 halcmd_output("\n"); 1910 } 1911 1912 static void print_thread_info(char **patterns) 1913 { 1914 int next_thread, n; 1915 hal_thread_t *tptr; 1916 hal_list_t *list_root, *list_entry; 1917 hal_funct_entry_t *fentry; 1918 hal_funct_t *funct; 1919 1920 if (scriptmode == 0) { 1921 halcmd_output("Realtime Threads:\n"); 1922 halcmd_output(" Period FP Name ( Time, Max-Time )\n"); 1923 } 1924 rtapi_mutex_get(&(hal_data->mutex)); 1925 next_thread = hal_data->thread_list_ptr; 1926 while (next_thread != 0) { 1927 tptr = SHMPTR(next_thread); 1928 if ( match(patterns, tptr->name) ) { 1929 /* note that the scriptmode format string has no \n */ 1930 char name[HAL_NAME_LEN+1]; 1931 hal_pin_t* pin; 1932 hal_sig_t *sig; 1933 void *dptr; 1934 1935 snprintf(name, sizeof(name), "%s.time",tptr->name); 1936 pin = halpr_find_pin_by_name(name); 1937 if (pin) { 1938 if (pin->signal != 0) { 1939 sig = SHMPTR(pin->signal); 1940 dptr = SHMPTR(sig->data_ptr); 1941 } else { 1942 sig = 0; 1943 dptr = &(pin->dummysig); 1944 } 1945 1946 halcmd_output(((scriptmode == 0) ? "%11ld %-3s %20s ( %8ld, %8ld )\n" 1947 : "%ld %s %s %8ld %ld"), 1948 tptr->period, 1949 (tptr->uses_fp ? "YES" : "NO"), 1950 tptr->name, 1951 (long)*(long*)dptr, 1952 (long)tptr->maxtime); 1953 } else { 1954 rtapi_print_msg(RTAPI_MSG_ERR, 1955 "unexpected: cannot find time pin for %s thread",tptr->name); 1956 } 1957 1958 1959 list_root = &(tptr->funct_list); 1960 list_entry = list_next(list_root); 1961 n = 1; 1962 while (list_entry != list_root) { 1963 /* print the function info */ 1964 fentry = (hal_funct_entry_t *) list_entry; 1965 funct = SHMPTR(fentry->funct_ptr); 1966 /* scriptmode only uses one line per thread, which contains: 1967 thread period, FP flag, name, then all functs separated by spaces */ 1968 if (scriptmode == 0) { 1969 halcmd_output(" %2d %s\n", n, funct->name); 1970 } else { 1971 halcmd_output(" %s", funct->name); 1972 } 1973 n++; 1974 list_entry = list_next(list_entry); 1975 } 1976 if (scriptmode != 0) { 1977 halcmd_output("\n"); 1978 } 1979 } 1980 next_thread = tptr->next_ptr; 1981 } 1982 rtapi_mutex_give(&(hal_data->mutex)); 1983 halcmd_output("\n"); 1984 } 1985 1986 static void print_comp_names(char **patterns) 1987 { 1988 int next; 1989 hal_comp_t *comp; 1990 1991 rtapi_mutex_get(&(hal_data->mutex)); 1992 next = hal_data->comp_list_ptr; 1993 while (next != 0) { 1994 comp = SHMPTR(next); 1995 if ( match(patterns, comp->name) ) { 1996 halcmd_output("%s ", comp->name); 1997 } 1998 next = comp->next_ptr; 1999 } 2000 rtapi_mutex_give(&(hal_data->mutex)); 2001 halcmd_output("\n"); 2002 } 2003 2004 static void print_pin_names(char **patterns) 2005 { 2006 int next; 2007 hal_pin_t *pin; 2008 2009 rtapi_mutex_get(&(hal_data->mutex)); 2010 next = hal_data->pin_list_ptr; 2011 while (next != 0) { 2012 pin = SHMPTR(next); 2013 if ( match(patterns, pin->name) ) { 2014 halcmd_output("%s ", pin->name); 2015 } 2016 next = pin->next_ptr; 2017 } 2018 rtapi_mutex_give(&(hal_data->mutex)); 2019 halcmd_output("\n"); 2020 } 2021 2022 static void print_sig_names(char **patterns) 2023 { 2024 int next; 2025 hal_sig_t *sig; 2026 2027 rtapi_mutex_get(&(hal_data->mutex)); 2028 next = hal_data->sig_list_ptr; 2029 while (next != 0) { 2030 sig = SHMPTR(next); 2031 if ( match(patterns, sig->name) ) { 2032 halcmd_output("%s ", sig->name); 2033 } 2034 next = sig->next_ptr; 2035 } 2036 rtapi_mutex_give(&(hal_data->mutex)); 2037 halcmd_output("\n"); 2038 } 2039 2040 static void print_param_names(char **patterns) 2041 { 2042 int next; 2043 hal_param_t *param; 2044 2045 rtapi_mutex_get(&(hal_data->mutex)); 2046 next = hal_data->param_list_ptr; 2047 while (next != 0) { 2048 param = SHMPTR(next); 2049 if ( match(patterns, param->name) ) { 2050 halcmd_output("%s ", param->name); 2051 } 2052 next = param->next_ptr; 2053 } 2054 rtapi_mutex_give(&(hal_data->mutex)); 2055 halcmd_output("\n"); 2056 } 2057 2058 static void print_funct_names(char **patterns) 2059 { 2060 int next; 2061 hal_funct_t *fptr; 2062 2063 rtapi_mutex_get(&(hal_data->mutex)); 2064 next = hal_data->funct_list_ptr; 2065 while (next != 0) { 2066 fptr = SHMPTR(next); 2067 if ( match(patterns, fptr->name) ) { 2068 halcmd_output("%s ", fptr->name); 2069 } 2070 next = fptr->next_ptr; 2071 } 2072 rtapi_mutex_give(&(hal_data->mutex)); 2073 halcmd_output("\n"); 2074 } 2075 2076 static void print_thread_names(char **patterns) 2077 { 2078 int next_thread; 2079 hal_thread_t *tptr; 2080 2081 rtapi_mutex_get(&(hal_data->mutex)); 2082 next_thread = hal_data->thread_list_ptr; 2083 while (next_thread != 0) { 2084 tptr = SHMPTR(next_thread); 2085 if ( match(patterns, tptr->name) ) { 2086 halcmd_output("%s ", tptr->name); 2087 } 2088 next_thread = tptr->next_ptr; 2089 } 2090 rtapi_mutex_give(&(hal_data->mutex)); 2091 halcmd_output("\n"); 2092 } 2093 2094 static void print_lock_status() 2095 { 2096 int lock; 2097 2098 lock = hal_get_lock(); 2099 2100 halcmd_output("HAL locking status:\n"); 2101 halcmd_output(" current lock value %d (%02x)\n", lock, lock); 2102 2103 if (lock == HAL_LOCK_NONE) 2104 halcmd_output(" HAL_LOCK_NONE - nothing is locked\n"); 2105 if (lock & HAL_LOCK_LOAD) 2106 halcmd_output(" HAL_LOCK_LOAD - loading of new components is locked\n"); 2107 if (lock & HAL_LOCK_CONFIG) 2108 halcmd_output(" HAL_LOCK_CONFIG - link and addf is locked\n"); 2109 if (lock & HAL_LOCK_PARAMS) 2110 halcmd_output(" HAL_LOCK_PARAMS - setting params is locked\n"); 2111 if (lock & HAL_LOCK_RUN) 2112 halcmd_output(" HAL_LOCK_RUN - running/stopping HAL is locked\n"); 2113 } 2114 2115 static int count_list(int list_root) 2116 { 2117 int n, next; 2118 2119 rtapi_mutex_get(&(hal_data->mutex)); 2120 next = list_root; 2121 n = 0; 2122 while (next != 0) { 2123 n++; 2124 next = *((int *) SHMPTR(next)); 2125 } 2126 rtapi_mutex_give(&(hal_data->mutex)); 2127 return n; 2128 } 2129 2130 static void print_mem_status() 2131 { 2132 int active, recycled, next; 2133 hal_pin_t *pin; 2134 hal_param_t *param; 2135 2136 halcmd_output("HAL memory status\n"); 2137 halcmd_output(" used/total shared memory: %ld/%d\n", (long)(HAL_SIZE - hal_data->shmem_avail), HAL_SIZE); 2138 // count components 2139 active = count_list(hal_data->comp_list_ptr); 2140 recycled = count_list(hal_data->comp_free_ptr); 2141 halcmd_output(" active/recycled components: %d/%d\n", active, recycled); 2142 // count pins 2143 active = count_list(hal_data->pin_list_ptr); 2144 recycled = count_list(hal_data->pin_free_ptr); 2145 halcmd_output(" active/recycled pins: %d/%d\n", active, recycled); 2146 // count parameters 2147 active = count_list(hal_data->param_list_ptr); 2148 recycled = count_list(hal_data->param_free_ptr); 2149 halcmd_output(" active/recycled parameters: %d/%d\n", active, recycled); 2150 // count aliases 2151 rtapi_mutex_get(&(hal_data->mutex)); 2152 next = hal_data->pin_list_ptr; 2153 active = 0; 2154 while (next != 0) { 2155 pin = SHMPTR(next); 2156 if ( pin->oldname != 0 ) active++; 2157 next = pin->next_ptr; 2158 } 2159 next = hal_data->param_list_ptr; 2160 while (next != 0) { 2161 param = SHMPTR(next); 2162 if ( param->oldname != 0 ) active++; 2163 next = param->next_ptr; 2164 } 2165 rtapi_mutex_give(&(hal_data->mutex)); 2166 recycled = count_list(hal_data->oldname_free_ptr); 2167 halcmd_output(" active/recycled aliases: %d/%d\n", active, recycled); 2168 // count signals 2169 active = count_list(hal_data->sig_list_ptr); 2170 recycled = count_list(hal_data->sig_free_ptr); 2171 halcmd_output(" active/recycled signals: %d/%d\n", active, recycled); 2172 // count functions 2173 active = count_list(hal_data->funct_list_ptr); 2174 recycled = count_list(hal_data->funct_free_ptr); 2175 halcmd_output(" active/recycled functions: %d/%d\n", active, recycled); 2176 // count threads 2177 active = count_list(hal_data->thread_list_ptr); 2178 recycled = count_list(hal_data->thread_free_ptr); 2179 halcmd_output(" active/recycled threads: %d/%d\n", active, recycled); 2180 } 2181 2182 /* Switch function for pin/sig/param type for the print_*_list functions */ 2183 static const char *data_type(int type) 2184 { 2185 const char *type_str; 2186 2187 switch (type) { 2188 case HAL_BIT: 2189 type_str = "bit "; 2190 break; 2191 case HAL_FLOAT: 2192 type_str = "float"; 2193 break; 2194 case HAL_S32: 2195 type_str = "s32 "; 2196 break; 2197 case HAL_U32: 2198 type_str = "u32 "; 2199 break; 2200 case HAL_PORT: 2201 type_str = "port "; 2202 break; 2203 default: 2204 /* Shouldn't get here, but just in case... */ 2205 type_str = "undef"; 2206 } 2207 return type_str; 2208 } 2209 2210 static const char *data_type2(int type) 2211 { 2212 const char *type_str; 2213 2214 switch (type) { 2215 case HAL_BIT: 2216 type_str = "bit"; 2217 break; 2218 case HAL_FLOAT: 2219 type_str = "float"; 2220 break; 2221 case HAL_S32: 2222 type_str = "s32"; 2223 break; 2224 case HAL_U32: 2225 type_str = "u32"; 2226 break; 2227 case HAL_PORT: 2228 type_str = "port"; 2229 break; 2230 default: 2231 /* Shouldn't get here, but just in case... */ 2232 type_str = "undef"; 2233 } 2234 return type_str; 2235 } 2236 2237 /* Switch function for pin direction for the print_*_list functions */ 2238 static const char *pin_data_dir(int dir) 2239 { 2240 const char *pin_dir; 2241 2242 switch (dir) { 2243 case HAL_IN: 2244 pin_dir = "IN"; 2245 break; 2246 case HAL_OUT: 2247 pin_dir = "OUT"; 2248 break; 2249 case HAL_IO: 2250 pin_dir = "I/O"; 2251 break; 2252 default: 2253 /* Shouldn't get here, but just in case... */ 2254 pin_dir = "???"; 2255 } 2256 return pin_dir; 2257 } 2258 2259 /* Switch function for param direction for the print_*_list functions */ 2260 static const char *param_data_dir(int dir) 2261 { 2262 const char *param_dir; 2263 2264 switch (dir) { 2265 case HAL_RO: 2266 param_dir = "RO"; 2267 break; 2268 case HAL_RW: 2269 param_dir = "RW"; 2270 break; 2271 default: 2272 /* Shouldn't get here, but just in case... */ 2273 param_dir = "??"; 2274 } 2275 return param_dir; 2276 } 2277 2278 /* Switch function for arrow direction for the print_*_list functions */ 2279 static const char *data_arrow1(int dir) 2280 { 2281 const char *arrow; 2282 2283 switch (dir) { 2284 case HAL_IN: 2285 arrow = "<=="; 2286 break; 2287 case HAL_OUT: 2288 arrow = "==>"; 2289 break; 2290 case HAL_IO: 2291 arrow = "<=>"; 2292 break; 2293 default: 2294 /* Shouldn't get here, but just in case... */ 2295 arrow = "???"; 2296 } 2297 return arrow; 2298 } 2299 2300 /* Switch function for arrow direction for the print_*_list functions */ 2301 static const char *data_arrow2(int dir) 2302 { 2303 const char *arrow; 2304 2305 switch (dir) { 2306 case HAL_IN: 2307 arrow = "==>"; 2308 break; 2309 case HAL_OUT: 2310 arrow = "<=="; 2311 break; 2312 case HAL_IO: 2313 arrow = "<=>"; 2314 break; 2315 default: 2316 /* Shouldn't get here, but just in case... */ 2317 arrow = "???"; 2318 } 2319 return arrow; 2320 } 2321 2322 /* Switch function to return var value for the print_*_list functions */ 2323 /* the value is printed in a 12 character wide field */ 2324 static char *data_value(int type, void *valptr) 2325 { 2326 char *value_str; 2327 static char buf[15]; 2328 2329 switch (type) { 2330 case HAL_BIT: 2331 if (*((char *) valptr) == 0) 2332 value_str = " FALSE"; 2333 else 2334 value_str = " TRUE"; 2335 break; 2336 case HAL_FLOAT: 2337 snprintf(buf, 14, "%12.7g", (double)*((hal_float_t *) valptr)); 2338 value_str = buf; 2339 break; 2340 case HAL_S32: 2341 snprintf(buf, 14, " %10ld", (long)*((hal_s32_t *) valptr)); 2342 value_str = buf; 2343 break; 2344 case HAL_U32: 2345 snprintf(buf, 14, " 0x%08lX", (unsigned long)*((hal_u32_t *) valptr)); 2346 value_str = buf; 2347 break; 2348 case HAL_PORT: 2349 snprintf(buf, 14, " %10u", hal_port_buffer_size(*((hal_port_t*) valptr))); 2350 value_str = buf; 2351 break; 2352 default: 2353 /* Shouldn't get here, but just in case... */ 2354 value_str = " undef "; 2355 } 2356 return value_str; 2357 } 2358 2359 /* Switch function to return var value in string form */ 2360 /* the value is printed as a packed string (no whitespace */ 2361 static char *data_value2(int type, void *valptr) 2362 { 2363 char *value_str; 2364 static char buf[15]; 2365 2366 switch (type) { 2367 case HAL_BIT: 2368 if (*((char *) valptr) == 0) 2369 value_str = "FALSE"; 2370 else 2371 value_str = "TRUE"; 2372 break; 2373 case HAL_FLOAT: 2374 snprintf(buf, 14, "%.7g", (double)*((hal_float_t *) valptr)); 2375 value_str = buf; 2376 break; 2377 case HAL_S32: 2378 snprintf(buf, 14, "%ld", (long)*((hal_s32_t *) valptr)); 2379 value_str = buf; 2380 break; 2381 case HAL_U32: 2382 snprintf(buf, 14, "%ld", (unsigned long)*((hal_u32_t *) valptr)); 2383 value_str = buf; 2384 break; 2385 case HAL_PORT: 2386 snprintf(buf, 14, "%u", hal_port_buffer_size(*((hal_port_t*) valptr))); 2387 value_str = buf; 2388 break; 2389 2390 default: 2391 /* Shouldn't get here, but just in case... */ 2392 value_str = "unknown_type"; 2393 } 2394 return value_str; 2395 } 2396 2397 int do_save_cmd(char *type, char *filename) 2398 { 2399 FILE *dst; 2400 2401 if (rtapi_get_msg_level() == RTAPI_MSG_NONE) { 2402 /* must be -Q, don't print anything */ 2403 return 0; 2404 } 2405 if (filename == NULL || *filename == '\0' ) { 2406 dst = stdout; 2407 } else { 2408 dst = fopen(filename, "w" ); 2409 if ( dst == NULL ) { 2410 halcmd_error("Can't open 'save' destination '%s'\n", filename); 2411 return -1; 2412 } 2413 } 2414 if (type == 0 || *type == '\0') { 2415 type = "all"; 2416 } 2417 if ( (strcmp(type, "all") == 0) 2418 || (strcmp(type, "allu") == 0) ) { 2419 /* save everything */ 2420 save_comps(dst); 2421 save_aliases(dst); 2422 save_signals(dst, 1); 2423 save_nets(dst, 3); 2424 save_params(dst); 2425 if (strcmp(type,"allu") == 0) { 2426 save_unconnected_input_pin_values(dst); 2427 } 2428 save_threads(dst); 2429 } else if (strcmp(type, "comp") == 0) { 2430 save_comps(dst); 2431 } else if (strcmp(type, "alias") == 0) { 2432 save_aliases(dst); 2433 } else if (strcmp(type, "sig") == 0) { 2434 save_signals(dst, 0); 2435 } else if (strcmp(type, "signal") == 0) { 2436 save_signals(dst, 0); 2437 } else if (strcmp(type, "sigu") == 0) { 2438 save_signals(dst, 1); 2439 } else if (strcmp(type, "link") == 0) { 2440 save_links(dst, 0); 2441 } else if (strcmp(type, "linka") == 0) { 2442 save_links(dst, 1); 2443 } else if (strcmp(type, "net") == 0) { 2444 save_nets(dst, 0); 2445 } else if (strcmp(type, "neta") == 0) { 2446 save_nets(dst, 1); 2447 } else if (strcmp(type, "netl") == 0) { 2448 save_nets(dst, 2); 2449 } else if (strcmp(type, "netla") == 0 || strcmp(type, "netal") == 0) { 2450 save_nets(dst, 3); 2451 } else if (strcmp(type, "param") == 0) { 2452 save_params(dst); 2453 } else if (strcmp(type, "parameter") == 0) { 2454 save_params(dst); 2455 } else if (strcmp(type, "thread") == 0) { 2456 save_threads(dst); 2457 } else if (strcmp(type, "unconnectedinpins") == 0) { 2458 save_unconnected_input_pin_values(dst); 2459 } else { 2460 halcmd_error("Unknown 'save' type '%s'\n", type); 2461 if (dst != stdout) fclose(dst); 2462 return -1; 2463 } 2464 if (dst != stdout) { 2465 fclose(dst); 2466 } 2467 return 0; 2468 } 2469 2470 static void save_comps(FILE *dst) 2471 { 2472 int next; 2473 hal_comp_t *comp; 2474 2475 fprintf(dst, "# components\n"); 2476 rtapi_mutex_get(&(hal_data->mutex)); 2477 2478 int ncomps = 0; 2479 next = hal_data->comp_list_ptr; 2480 while (next != 0) { 2481 comp = SHMPTR(next); 2482 if ( comp->type == 1 ) { 2483 ncomps ++; 2484 } 2485 next = comp->next_ptr; 2486 } 2487 2488 hal_comp_t *comps[ncomps], **compptr = comps; 2489 next = hal_data->comp_list_ptr; 2490 while(next != 0) { 2491 comp = SHMPTR(next); 2492 if ( comp->type == 1 ) { 2493 *compptr++ = SHMPTR(next); 2494 } 2495 next = comp->next_ptr; 2496 } 2497 2498 int i; 2499 for(i=ncomps; i--;) 2500 { 2501 comp = comps[i]; 2502 /* only print realtime components */ 2503 if ( comp->insmod_args == 0 ) { 2504 fprintf(dst, "#loadrt %s (not loaded by loadrt, no args saved)\n", comp->name); 2505 } else { 2506 fprintf(dst, "loadrt %s %s\n", comp->name, 2507 (char *)SHMPTR(comp->insmod_args)); 2508 } 2509 } 2510 #if 0 /* newinst deferred to version 2.2 */ 2511 next = hal_data->comp_list_ptr; 2512 while (next != 0) { 2513 comp = SHMPTR(next); 2514 if ( comp->type == 2 ) { 2515 hal_comp_t *comp1 = halpr_find_comp_by_id(comp->comp_id & 0xffff); 2516 fprintf(dst, "newinst %s %s\n", comp1->name, comp->name); 2517 } 2518 next = comp->next_ptr; 2519 } 2520 #endif 2521 rtapi_mutex_give(&(hal_data->mutex)); 2522 } 2523 2524 static void save_aliases(FILE *dst) 2525 { 2526 int next; 2527 hal_pin_t *pin; 2528 hal_param_t *param; 2529 hal_oldname_t *oldname; 2530 2531 fprintf(dst, "# pin aliases\n"); 2532 rtapi_mutex_get(&(hal_data->mutex)); 2533 next = hal_data->pin_list_ptr; 2534 while (next != 0) { 2535 pin = SHMPTR(next); 2536 if ( pin->oldname != 0 ) { 2537 /* name is an alias */ 2538 oldname = SHMPTR(pin->oldname); 2539 fprintf(dst, "alias pin %s %s\n", oldname->name, pin->name); 2540 } 2541 next = pin->next_ptr; 2542 } 2543 fprintf(dst, "# param aliases\n"); 2544 next = hal_data->param_list_ptr; 2545 while (next != 0) { 2546 param = SHMPTR(next); 2547 if ( param->oldname != 0 ) { 2548 /* name is an alias */ 2549 oldname = SHMPTR(param->oldname); 2550 fprintf(dst, "alias param %s %s\n", oldname->name, param->name); 2551 } 2552 next = param->next_ptr; 2553 } 2554 rtapi_mutex_give(&(hal_data->mutex)); 2555 } 2556 2557 static void save_signals(FILE *dst, int only_unlinked) 2558 { 2559 int next; 2560 hal_sig_t *sig; 2561 2562 fprintf(dst, "# signals\n"); 2563 rtapi_mutex_get(&(hal_data->mutex)); 2564 2565 for( next = hal_data->sig_list_ptr; next; next = sig->next_ptr) { 2566 sig = SHMPTR(next); 2567 if(only_unlinked && (sig->readers || sig->writers)) continue; 2568 fprintf(dst, "newsig %s %s\n", sig->name, data_type((int) sig->type)); 2569 } 2570 rtapi_mutex_give(&(hal_data->mutex)); 2571 } 2572 2573 static void save_links(FILE *dst, int arrow) 2574 { 2575 int next; 2576 hal_pin_t *pin; 2577 hal_sig_t *sig; 2578 const char *arrow_str; 2579 2580 fprintf(dst, "# links\n"); 2581 rtapi_mutex_get(&(hal_data->mutex)); 2582 next = hal_data->pin_list_ptr; 2583 while (next != 0) { 2584 pin = SHMPTR(next); 2585 if (pin->signal != 0) { 2586 sig = SHMPTR(pin->signal); 2587 if (arrow != 0) { 2588 arrow_str = data_arrow1((int) pin->dir); 2589 } else { 2590 arrow_str = "\0"; 2591 } 2592 fprintf(dst, "linkps %s %s %s\n", pin->name, arrow_str, sig->name); 2593 } 2594 next = pin->next_ptr; 2595 } 2596 rtapi_mutex_give(&(hal_data->mutex)); 2597 } 2598 2599 static void save_nets(FILE *dst, int arrow) 2600 { 2601 int next; 2602 hal_pin_t *pin; 2603 hal_sig_t *sig; 2604 const char *arrow_str; 2605 2606 fprintf(dst, "# nets\n"); 2607 rtapi_mutex_get(&(hal_data->mutex)); 2608 2609 for (next = hal_data->sig_list_ptr; next != 0; next = sig->next_ptr) { 2610 sig = SHMPTR(next); 2611 if(arrow == 3) { 2612 int state = 0, first = 1; 2613 2614 /* If there are no pins connected to this signal, do nothing */ 2615 pin = halpr_find_pin_by_sig(sig, 0); 2616 if(!pin) continue; 2617 2618 fprintf(dst, "net %s", sig->name); 2619 2620 /* Step 1: Output pin, if any */ 2621 2622 for(pin = halpr_find_pin_by_sig(sig, 0); pin; 2623 pin = halpr_find_pin_by_sig(sig, pin)) { 2624 if(pin->dir != HAL_OUT) continue; 2625 fprintf(dst, " %s", pin->name); 2626 state = 1; 2627 } 2628 2629 /* Step 2: I/O pins, if any */ 2630 for(pin = halpr_find_pin_by_sig(sig, 0); pin; 2631 pin = halpr_find_pin_by_sig(sig, pin)) { 2632 if(pin->dir != HAL_IO) continue; 2633 fprintf(dst, " "); 2634 if(state) { fprintf(dst, "=> "); state = 0; } 2635 else if(!first) { fprintf(dst, "<=> "); } 2636 fprintf(dst, "%s", pin->name); 2637 first = 0; 2638 } 2639 if(!first) state = 1; 2640 2641 /* Step 3: Input pins, if any */ 2642 for(pin = halpr_find_pin_by_sig(sig, 0); pin; 2643 pin = halpr_find_pin_by_sig(sig, pin)) { 2644 if(pin->dir != HAL_IN) continue; 2645 fprintf(dst, " "); 2646 if(state) { fprintf(dst, "=> "); state = 0; } 2647 fprintf(dst, "%s", pin->name); 2648 } 2649 2650 fprintf(dst, "\n"); 2651 } else if(arrow == 2) { 2652 /* If there are no pins connected to this signal, do nothing */ 2653 pin = halpr_find_pin_by_sig(sig, 0); 2654 if(!pin) continue; 2655 2656 fprintf(dst, "net %s", sig->name); 2657 pin = halpr_find_pin_by_sig(sig, 0); 2658 while (pin != 0) { 2659 fprintf(dst, " %s", pin->name); 2660 pin = halpr_find_pin_by_sig(sig, pin); 2661 } 2662 fprintf(dst, "\n"); 2663 } else { 2664 fprintf(dst, "newsig %s %s\n", 2665 sig->name, data_type((int) sig->type)); 2666 pin = halpr_find_pin_by_sig(sig, 0); 2667 while (pin != 0) { 2668 if (arrow != 0) { 2669 arrow_str = data_arrow2((int) pin->dir); 2670 } else { 2671 arrow_str = "\0"; 2672 } 2673 fprintf(dst, "linksp %s %s %s\n", 2674 sig->name, arrow_str, pin->name); 2675 pin = halpr_find_pin_by_sig(sig, pin); 2676 } 2677 } 2678 } 2679 rtapi_mutex_give(&(hal_data->mutex)); 2680 } 2681 2682 static void save_params(FILE *dst) 2683 { 2684 int next; 2685 hal_param_t *param; 2686 2687 fprintf(dst, "# parameter values\n"); 2688 rtapi_mutex_get(&(hal_data->mutex)); 2689 next = hal_data->param_list_ptr; 2690 while (next != 0) { 2691 param = SHMPTR(next); 2692 if (param->dir != HAL_RO) { 2693 /* param is writable, save its value */ 2694 fprintf(dst, "setp %s %s\n", param->name, 2695 data_value((int) param->type, SHMPTR(param->data_ptr))); 2696 } 2697 next = param->next_ptr; 2698 } 2699 rtapi_mutex_give(&(hal_data->mutex)); 2700 } 2701 2702 static void save_threads(FILE *dst) 2703 { 2704 int next_thread; 2705 hal_thread_t *tptr; 2706 hal_list_t *list_root, *list_entry; 2707 hal_funct_entry_t *fentry; 2708 hal_funct_t *funct; 2709 2710 fprintf(dst, "# realtime thread/function links\n"); 2711 rtapi_mutex_get(&(hal_data->mutex)); 2712 next_thread = hal_data->thread_list_ptr; 2713 while (next_thread != 0) { 2714 tptr = SHMPTR(next_thread); 2715 list_root = &(tptr->funct_list); 2716 list_entry = list_next(list_root); 2717 while (list_entry != list_root) { 2718 /* print the function info */ 2719 fentry = (hal_funct_entry_t *) list_entry; 2720 funct = SHMPTR(fentry->funct_ptr); 2721 fprintf(dst, "addf %s %s\n", funct->name, tptr->name); 2722 list_entry = list_next(list_entry); 2723 } 2724 next_thread = tptr->next_ptr; 2725 } 2726 rtapi_mutex_give(&(hal_data->mutex)); 2727 } 2728 2729 static void save_unconnected_input_pin_values(FILE *dst) 2730 { 2731 hal_pin_t *pin; 2732 void *dptr; 2733 int next; 2734 fprintf(dst, "# unconnected pin values\n"); 2735 for(next = hal_data->pin_list_ptr; next; next=pin->next_ptr) 2736 { 2737 pin = SHMPTR(next); 2738 if ( (pin->signal == 0) 2739 && ( (pin->dir == HAL_IN) || (pin->dir == HAL_IO) ) 2740 ) { 2741 dptr = &(pin->dummysig); 2742 fprintf(dst, "setp %s %s\n", 2743 pin->name, data_value((int) pin->type, dptr)); 2744 } 2745 } 2746 } 2747 2748 int do_setexact_cmd() { 2749 int retval = 0; 2750 rtapi_mutex_get(&(hal_data->mutex)); 2751 if(hal_data->base_period) { 2752 halcmd_error( 2753 "HAL_LIB: Cannot run 'setexact'" 2754 " after a thread has been created\n"); 2755 retval = -EINVAL; 2756 } else { 2757 halcmd_warning( 2758 "HAL_LIB: HAL will pretend that the exact" 2759 " base period requested is possible.\n" 2760 "This mode is not suitable for running real hardware.\n"); 2761 hal_data->exact_base_period = 1; 2762 } 2763 rtapi_mutex_give(&(hal_data->mutex)); 2764 return retval; 2765 } 2766 2767 int do_help_cmd(char *command) 2768 { 2769 if (!command) { 2770 print_help_commands(); 2771 } else if (strcmp(command, "help") == 0) { 2772 printf("If you need help to use 'help', then I can't help you.\n"); 2773 } else if (strcmp(command, "loadrt") == 0) { 2774 printf("loadrt modname [modarg(s)]\n"); 2775 printf(" Loads realtime HAL module 'modname', passing 'modargs'\n"); 2776 printf(" to the module.\n"); 2777 #if 0 /* newinst deferred to version 2.2 */ 2778 } else if (strcmp(command, "newinst") == 0) { 2779 printf("newinst modname instname\n"); 2780 printf(" Creates another instance of previously loaded module\n" ); 2781 printf(" 'modname', nameing it 'instname'.\n"); 2782 #endif 2783 } else if (strcmp(command, "unload") == 0) { 2784 printf("unload compname\n"); 2785 printf(" Unloads HAL module 'compname', whether user space or realtime.\n"); 2786 printf(" If 'compname' is 'all', unloads all components.\n"); 2787 } else if (strcmp(command, "waitusr") == 0) { 2788 printf("waitusr compname\n"); 2789 printf(" Waits for user space HAL module 'compname' to exit.\n"); 2790 } else if (strcmp(command, "unloadusr") == 0) { 2791 printf("unloadusr compname\n"); 2792 printf(" Unloads user space HAL module 'compname'. If 'compname'\n"); 2793 printf(" is 'all', unloads all userspace components.\n"); 2794 } else if (strcmp(command, "unloadrt") == 0) { 2795 printf("unloadrt modname\n"); 2796 printf(" Unloads realtime HAL module 'modname'. If 'modname'\n"); 2797 printf(" is 'all', unloads all realtime modules.\n"); 2798 } else if (strcmp(command, "loadusr") == 0) { 2799 printf("loadusr [options] progname [progarg(s)]\n"); 2800 printf(" Starts user space program 'progname', passing\n"); 2801 printf(" 'progargs' to it. Options are:\n"); 2802 printf(" -W wait for HAL component to become ready\n"); 2803 printf(" -Wn NAME wait for component named NAME to become ready\n"); 2804 printf(" -w wait for program to finish\n"); 2805 printf(" -i ignore program return value (use with -w)\n"); 2806 } else if ((strcmp(command, "linksp") == 0) || (strcmp(command,"linkps") == 0)) { 2807 printf("linkps pinname [arrow] signame\n"); 2808 printf("linksp signame [arrow] pinname\n"); 2809 printf(" Links pin 'pinname' to signal 'signame'. Both forms do\n"); 2810 printf(" the same thing. Use whichever makes sense. The optional\n"); 2811 printf(" 'arrow' can be '==>', '<==', or '<=>' and is ignored. It\n"); 2812 printf(" can be used in files to show the direction of data flow,\n"); 2813 printf(" but don't use arrows on the command line.\n"); 2814 } else if (strcmp(command, "linkpp") == 0) { 2815 printf("linkpp firstpin secondpin\n"); 2816 printf(" Creates a signal with the name of the first pin,\n"); printf(" then links both pins to the signal. \n"); 2817 } else if(strcmp(command, "net") == 0) { 2818 printf("net signame pinname ...\n"); 2819 printf("Creates 'signame' with the type of 'pinname' if it does not yet exist\n"); 2820 printf("And then links signame to each pinname specified.\n"); 2821 }else if (strcmp(command, "unlinkp") == 0) { 2822 printf("unlinkp pinname\n"); 2823 printf(" Unlinks pin 'pinname' if it is linked to any signal.\n"); 2824 } else if (strcmp(command, "lock") == 0) { 2825 printf("lock [all|tune|none]\n"); 2826 printf(" Locks HAL to some degree.\n"); 2827 printf(" none - no locking done.\n"); 2828 printf(" tune - some tuning is possible (setp & such).\n"); 2829 printf(" all - HAL completely locked.\n"); 2830 } else if (strcmp(command, "unlock") == 0) { 2831 printf("unlock [all|tune]\n"); 2832 printf(" Unlocks HAL to some degree.\n"); 2833 printf(" tune - some tuning is possible (setp & such).\n"); 2834 printf(" all - HAL completely unlocked.\n"); 2835 } else if (strcmp(command, "newsig") == 0) { 2836 printf("newsig signame type\n"); 2837 printf(" Creates a new signal called 'signame'. Type\n"); 2838 printf(" is 'bit', 'float', 'port', 'u32', or 's32'.\n"); 2839 } else if (strcmp(command, "delsig") == 0) { 2840 printf("delsig signame\n"); 2841 printf(" Deletes signal 'signame'. If 'signame is 'all',\n"); 2842 printf(" deletes all signals\n"); 2843 } else if (strcmp(command, "setp") == 0) { 2844 printf("setp paramname value\n"); 2845 printf("setp pinname value\n"); 2846 printf("paramname = value\n"); 2847 printf(" Sets parameter 'paramname' to 'value' (if writable).\n"); 2848 printf(" Sets pin 'pinname' to 'value' (if an unconnected input).\n"); 2849 printf(" 'setp' and '=' work the same, don't use '=' on the\n"); 2850 printf(" command line. 'value' may be a constant such as 1.234\n"); 2851 printf(" or TRUE, or a reference to an environment variable,\n"); 2852 #ifdef NO_INI 2853 printf(" using the syntax '$name'./n"); 2854 #else 2855 printf(" using the syntax '$name'. If option -i was given,\n"); 2856 printf(" 'value' may also be a reference to an ini file entry\n"); 2857 printf(" using the syntax '[section]name'.\n"); 2858 #endif 2859 } else if (strcmp(command, "sets") == 0) { 2860 printf("sets signame value\n"); 2861 printf(" Sets a non-port signal 'signame' to 'value' (if signal has no writers).\n"); 2862 printf(" If 'signame' is a port signal (that has not previously been allocated),\n"); 2863 printf(" then 'value' is the new maximum size in bytes of that port.\n"); 2864 } else if (strcmp(command, "getp") == 0) { 2865 printf("getp paramname\n"); 2866 printf("getp pinname\n"); 2867 printf(" Gets the value of parameter 'paramname' or pin 'pinname'.\n"); 2868 } else if (strcmp(command, "ptype") == 0) { 2869 printf("ptype paramname\n"); 2870 printf("ptype pinname\n"); 2871 printf(" Gets the type of parameter 'paramname' or pin 'pinname'.\n"); 2872 } else if (strcmp(command, "gets") == 0) { 2873 printf("gets signame\n"); 2874 printf(" Gets the value of signal 'signame'.\n"); 2875 printf(" If signal 'signame' is a port, returns the buffer size of that port.\n"); 2876 } else if (strcmp(command, "stype") == 0) { 2877 printf("stype signame\n"); 2878 printf(" Gets the type of signal 'signame'\n"); 2879 } else if (strcmp(command, "addf") == 0) { 2880 printf("addf functname threadname [position]\n"); 2881 printf(" Adds function 'functname' to thread 'threadname'. If\n"); 2882 printf(" 'position' is specified, adds the function to that spot\n"); 2883 printf(" in the thread, otherwise adds it to the end. Negative\n"); 2884 printf(" 'position' means position with respect to the end of the\n"); 2885 printf(" thread. For example '1' is start of thread, '-1' is the\n"); 2886 printf(" end of the thread, '-3' is third from the end.\n"); 2887 } else if (strcmp(command, "delf") == 0) { 2888 printf("delf functname threadname\n"); 2889 printf(" Removes function 'functname' from thread 'threadname'.\n"); 2890 } else if (strcmp(command, "show") == 0) { 2891 printf("show [type] [pattern]\n"); 2892 printf(" Prints info about HAL items of the specified type.\n"); 2893 printf(" 'type' is 'comp', 'pin', 'sig', 'param', 'funct',\n"); 2894 printf(" 'thread', or 'all'. If 'type' is omitted, it assumes\n"); 2895 printf(" 'all' with no pattern. If 'pattern' is specified\n"); 2896 printf(" it prints only those items whose names match the\n"); 2897 printf(" pattern, which may be a 'shell glob'.\n"); 2898 } else if (strcmp(command, "list") == 0) { 2899 printf("list type [pattern]\n"); 2900 printf(" Prints the names of HAL items of the specified type.\n"); 2901 printf(" 'type' is 'comp', 'pin', 'sig', 'param', 'funct', or\n"); 2902 printf(" 'thread'. If 'pattern' is specified it prints only\n"); 2903 printf(" those names that match the pattern, which may be a\n"); 2904 printf(" 'shell glob'.\n"); 2905 printf(" For 'sig', 'pin' and 'param', the first pattern may be\n"); 2906 printf(" -tdatatype where datatype is the data type (e.g., 'float')\n"); 2907 printf(" in this case, the listed pins, signals, or parameters\n"); 2908 printf(" are restricted to the given data type\n"); 2909 printf(" Names are printed on a single line, space separated.\n"); 2910 } else if (strcmp(command, "status") == 0) { 2911 printf("status [type]\n"); 2912 printf(" Prints status info about HAL.\n"); 2913 printf(" 'type' is 'lock', 'mem', or 'all'. \n"); 2914 printf(" If 'type' is omitted, it assumes\n"); 2915 printf(" 'all'.\n"); 2916 } else if (strcmp(command, "save") == 0) { 2917 printf("save [type] [filename]\n"); 2918 printf(" Prints HAL state to 'filename' (or stdout), as a series\n"); 2919 printf(" of HAL commands. State can later be restored by using\n"); 2920 printf(" \"halcmd -f filename\".\n"); 2921 printf(" Type can be 'comp', 'alias', 'sig[u]', 'signal', 'link[a]'\n"); 2922 printf(" 'net[a]', 'netl', 'netla', netal', 'param', 'parameter,\n"); 2923 printf(" 'unconnectedinpins', 'all, 'allu', or 'thread'.\n"); 2924 printf(" (A final 'a' character (like 'neta' means show arrows for pin direction.)\n"); 2925 printf(" If 'type' is 'allu'), does the equivalent of:\n"); 2926 printf(" 'comp', 'alias', 'sigu', 'netla', 'param', 'unconnectedinpins' and 'thread'.\n\n"); 2927 printf(" If 'type' is omitted (or type is 'all'), does the equivalent of:\n"); 2928 printf(" 'comp', 'alias', 'sigu', 'netla', 'param', and 'thread'.\n\n"); 2929 printf(" See the man page ($man halcmd) for save option details\n"); 2930 } else if (strcmp(command, "start") == 0) { 2931 printf("start\n"); 2932 printf(" Starts all realtime threads.\n"); 2933 } else if (strcmp(command, "stop") == 0) { 2934 printf("stop\n"); 2935 printf(" Stops all realtime threads.\n"); 2936 } else if (strcmp(command, "quit") == 0) { 2937 printf("quit\n"); 2938 printf(" Stop processing input and terminate halcmd (when\n"); 2939 printf(" reading from a file or stdin).\n"); 2940 } else if (strcmp(command, "exit") == 0) { 2941 printf("exit\n"); 2942 printf(" Stop processing input and terminate halcmd (when\n"); 2943 printf(" reading from a file or stdin).\n"); 2944 } else if (strcmp(command, "alias") == 0) { 2945 printf("alias type name alias\n"); 2946 printf(" Assigns \"alias\" as a second name for the pin or parameter\n"); 2947 printf(" \"name\". For most operations, an alias provides a second\n"); 2948 printf(" name that can be used to refer to a pin or parameter, both the\n"); 2949 printf(" original name and the alias will work.\n"); 2950 printf(" \"type\" must be pin or param\n"); 2951 printf(" \"name\" must be an existing name or alias of the specified type.\n"); 2952 } else if (strcmp(command, "unalias") == 0) { 2953 printf("unalias type name\n"); 2954 printf(" Removes any alias from the pin or parameter \"name\".\n"); 2955 printf(" \"type\" must be pin or param\n"); 2956 printf(" \"name\" must be an existing name or alias of the specified type.\n"); 2957 } else if (strcmp(command, "echo") == 0) { 2958 printf("echo\n"); 2959 printf("echo the commands from stdin to stderr\n"); 2960 printf("Useful for debugging scripted commands from a running program\n"); 2961 } else if (strcmp(command, "unecho") == 0) { 2962 printf("unecho\n"); 2963 printf("Turn off echo of commands from stdin to stdout\n"); 2964 2965 } else { 2966 printf("No help for unknown command '%s'\n", command); 2967 } 2968 return 0; 2969 } 2970 2971 2972 static void print_help_commands(void) 2973 { 2974 printf("Use 'help <command>' for more details about each command\n"); 2975 printf("Available commands:\n"); 2976 printf(" loadrt Load realtime module(s)\n"); 2977 printf(" loadusr Start user space program\n"); 2978 printf(" waitusr Waits for userspace component to exit\n"); 2979 printf(" unload Unload realtime module or terminate userspace component\n"); 2980 printf(" lock, unlock Lock/unlock HAL behaviour\n"); 2981 printf(" linkps Link pin to signal\n"); 2982 printf(" linksp Link signal to pin\n"); 2983 printf(" net Link a number of pins to a signal\n"); 2984 printf(" unlinkp Unlink pin\n"); 2985 printf(" newsig, delsig Create/delete a signal\n"); 2986 printf(" getp, gets Get the value of a pin, parameter or signal\n"); 2987 printf(" ptype, stype Get the type of a pin, parameter or signal\n"); 2988 printf(" setp, sets Set the value of a pin, parameter or signal\n"); 2989 printf(" addf, delf Add/remove function to/from a thread\n"); 2990 printf(" show Display info about HAL objects\n"); 2991 printf(" list Display names of HAL objects\n"); 2992 printf(" source Execute commands from another .hal file\n"); 2993 printf(" status Display status information\n"); 2994 printf(" save Print config as commands\n"); 2995 printf(" start, stop Start/stop realtime threads\n"); 2996 printf(" alias, unalias Add or remove pin or parameter name aliases\n"); 2997 printf(" echo, unecho Echo commands from stdin to stderr\n"); 2998 printf(" quit, exit Exit from halcmd\n"); 2999 }