halmodule.cc
1 // This is a component of AXIS, a front-end for emc 2 // Copyright 2004, 2005, 2006 Jeff Epler <jepler@unpythonic.net> and 3 // Chris Radek <chris@timeguy.com> 4 // 5 // This program is free software; you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation; either version 2 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with this program; if not, write to the Free Software 17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 19 #include <Python.h> 20 #include <structmember.h> 21 #include <string> 22 #include <map> 23 using namespace std; 24 25 #include "config.h" 26 #include "rtapi.h" 27 #include <rtapi_mutex.h> 28 #include "hal.h" 29 #include "hal_priv.h" 30 31 #if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) 32 typedef int Py_ssize_t; 33 #define PY_SSIZE_T_MAX INT_MAX 34 #define PY_SSIZE_T_MIN INT_MIN 35 #endif 36 37 #define EXCEPTION_IF_NOT_LIVE(retval) do { \ 38 if(self->hal_id <= 0) { \ 39 PyErr_SetString(PyExc_RuntimeError, "Invalid operation on closed HAL component"); \ 40 return retval; \ 41 } \ 42 } while(0) 43 44 PyObject *to_python(bool b) { 45 return PyBool_FromLong(b); 46 } 47 48 PyObject *to_python(unsigned u) { 49 if(u < LONG_MAX) return PyInt_FromLong(u); 50 return PyLong_FromUnsignedLong(u); 51 } 52 53 PyObject *to_python(int u) { 54 return PyInt_FromLong(u); 55 } 56 57 PyObject *to_python(double d) { 58 return PyFloat_FromDouble(d); 59 } 60 61 bool from_python(PyObject *o, double *d) { 62 if(PyFloat_Check(o)) { 63 *d = PyFloat_AsDouble(o); 64 return true; 65 } else if(PyInt_Check(o)) { 66 *d = PyInt_AsLong(o); 67 return true; 68 } else if(PyLong_Check(o)) { 69 *d = PyLong_AsDouble(o); 70 return !PyErr_Occurred(); 71 } 72 73 PyObject *tmp = PyNumber_Float(o); 74 if(!tmp) { 75 PyErr_Format(PyExc_TypeError, "Number expected, not %s", 76 o->ob_type->tp_name); 77 return false; 78 } 79 80 *d = PyFloat_AsDouble(tmp); 81 Py_DECREF(tmp); 82 return true; 83 } 84 85 bool from_python(PyObject *o, uint32_t *u) { 86 PyObject *tmp = 0; 87 long long l; 88 if(PyInt_Check(o)) { 89 l = PyInt_AsLong(o); 90 goto got_value; 91 } 92 93 tmp = PyLong_Check(o) ? o : PyNumber_Long(o); 94 if(!tmp) goto fail; 95 96 l = PyLong_AsLongLong(tmp); 97 if(PyErr_Occurred()) goto fail; 98 99 got_value: 100 if(l < 0 || l != (uint32_t)l) { 101 PyErr_Format(PyExc_OverflowError, "Value %lld out of range", l); 102 goto fail; 103 } 104 105 *u = l; 106 if(tmp != o) Py_XDECREF(tmp); 107 return true; 108 fail: 109 if(tmp != o) Py_XDECREF(tmp); 110 return false; 111 } 112 113 bool from_python(PyObject *o, int32_t *i) { 114 PyObject *tmp = 0; 115 long long l; 116 if(PyInt_Check(o)) { 117 l = PyInt_AsLong(o); 118 goto got_value; 119 } 120 121 tmp = PyLong_Check(o) ? o : PyNumber_Long(o); 122 if(!tmp) goto fail; 123 124 l = PyLong_AsLongLong(tmp); 125 if(PyErr_Occurred()) goto fail; 126 127 got_value: 128 if(l != (int32_t)l) { 129 PyErr_Format(PyExc_OverflowError, "Value %lld out of range", l); 130 goto fail; 131 } 132 133 *i = l; 134 if(tmp != o) Py_XDECREF(tmp); 135 return true; 136 fail: 137 if(tmp != o) Py_XDECREF(tmp); 138 return false; 139 } 140 141 union paramunion { 142 hal_bit_t b; 143 hal_u32_t u32; 144 hal_s32_t s32; 145 hal_float_t f; 146 }; 147 148 union pinunion { 149 void *v; 150 hal_bit_t *b; 151 hal_u32_t *u32; 152 hal_s32_t *s32; 153 hal_float_t *f; 154 }; 155 156 union halunion { 157 union pinunion pin; 158 union paramunion param; 159 }; 160 161 union haldirunion { 162 hal_pin_dir_t pindir; 163 hal_param_dir_t paramdir; 164 }; 165 166 struct halitem { 167 bool is_pin; 168 hal_type_t type; 169 union haldirunion dir; 170 union halunion *u; 171 }; 172 173 struct pyhalitem { 174 PyObject_HEAD 175 halitem pin; 176 char * name; 177 }; 178 179 static PyObject * pyhal_pin_new(halitem * pin, const char *name); 180 181 typedef std::map<std::string, struct halitem> itemmap; 182 183 typedef struct halobject { 184 PyObject_HEAD 185 int hal_id; 186 char *name; 187 char *prefix; 188 itemmap *items; 189 } halobject; 190 191 PyObject *pyhal_error_type = NULL; 192 193 static PyObject *pyrtapi_error(int code) { 194 PyErr_SetString(pyhal_error_type, strerror(-code)); 195 return NULL; 196 } 197 198 static PyObject *pyhal_error(int code) { 199 PyErr_SetString(pyhal_error_type, strerror(-code)); 200 return NULL; 201 } 202 203 static int pyhal_init(PyObject *_self, PyObject *args, PyObject *kw) { 204 char *name; 205 char *prefix = 0; 206 halobject *self = (halobject *)_self; 207 208 if(!PyArg_ParseTuple(args, "s|s:hal.component", &name, &prefix)) return -1; 209 210 self->items = new itemmap(); 211 212 self->hal_id = hal_init(name); 213 if(self->hal_id <= 0) { 214 pyhal_error(self->hal_id); 215 return -1; 216 } 217 218 self->name = strdup(name); 219 self->prefix = strdup(prefix ? prefix : name); 220 if(!self->name) { 221 PyErr_SetString(PyExc_MemoryError, "strdup(name) failed"); 222 return -1; 223 } 224 if(!self->prefix) { 225 PyErr_SetString(PyExc_MemoryError, "strdup(prefix) failed"); 226 return -1; 227 } 228 229 return 0; 230 } 231 232 static void pyhal_exit_impl(halobject *self) { 233 if(self->hal_id > 0) 234 hal_exit(self->hal_id); 235 self->hal_id = 0; 236 237 free(self->name); 238 self->name = 0; 239 240 free(self->prefix); 241 self->prefix = 0; 242 243 delete self->items; 244 self->items = 0; 245 } 246 247 static void pyhal_delete(PyObject *_self) { 248 halobject *self = (halobject *)_self; 249 pyhal_exit_impl(self); 250 self->ob_type->tp_free(self); 251 } 252 253 static int pyhal_write_common(halitem *pin, PyObject *value) { 254 if(!pin) return -1; 255 256 if(pin->is_pin) { 257 switch(pin->type) { 258 case HAL_BIT: 259 *pin->u->pin.b = PyObject_IsTrue(value); 260 break; 261 case HAL_FLOAT: { 262 double tmp; 263 if(!from_python(value, &tmp)) return -1; 264 *pin->u->pin.f = tmp; 265 break; 266 } 267 case HAL_U32: { 268 uint32_t tmp; 269 if(!from_python(value, &tmp)) return -1; 270 *pin->u->pin.u32 = tmp; 271 break; 272 } 273 case HAL_S32: { 274 int32_t tmp; 275 if(!from_python(value, &tmp)) return -1; 276 *pin->u->pin.s32 = tmp; 277 break; 278 } 279 default: 280 PyErr_Format(pyhal_error_type, "Invalid pin type %d", pin->type); 281 } 282 } else { 283 switch(pin->type) { 284 case HAL_BIT: 285 pin->u->param.b = PyObject_IsTrue(value); 286 break; 287 case HAL_FLOAT: { 288 double tmp; 289 if(!from_python(value, &tmp)) return -1; 290 pin->u->param.f = tmp; 291 break; 292 } 293 case HAL_U32: { 294 uint32_t tmp; 295 if(!from_python(value, &tmp)) return -1; 296 pin->u->param.u32 = tmp; 297 break; 298 } 299 case HAL_S32: 300 int32_t tmp; 301 if(!from_python(value, &tmp)) return -1; 302 pin->u->param.s32 = tmp; 303 break; 304 default: 305 PyErr_Format(pyhal_error_type, "Invalid pin type %d", pin->type); 306 } 307 } 308 return 0; 309 } 310 311 static PyObject *pyhal_read_common(halitem *item) { 312 if(!item) return NULL; 313 if(item->is_pin) { 314 switch(item->type) { 315 case HAL_BIT: return to_python(*(item->u->pin.b)); 316 case HAL_U32: return to_python(*(item->u->pin.u32)); 317 case HAL_S32: return to_python(*(item->u->pin.s32)); 318 case HAL_FLOAT: return to_python(*(item->u->pin.f)); 319 case HAL_TYPE_UNSPECIFIED: /* fallthrough */ ; 320 } 321 } else { 322 switch(item->type) { 323 case HAL_BIT: return to_python(item->u->param.b); 324 case HAL_U32: return to_python(item->u->param.u32); 325 case HAL_S32: return to_python(item->u->param.s32); 326 case HAL_FLOAT: return to_python(item->u->param.f); 327 case HAL_TYPE_UNSPECIFIED: /* fallthrough */ ; 328 } 329 } 330 PyErr_Format(pyhal_error_type, "Invalid item type %d", item->type); 331 return NULL; 332 } 333 334 static halitem *find_item(halobject *self, char *name) { 335 if(!name) return NULL; 336 337 itemmap::iterator i = self->items->find(name); 338 339 if(i == self->items->end()) { 340 PyErr_Format(PyExc_AttributeError, "Pin '%s' does not exist", name); 341 return NULL; 342 } 343 344 return &(i->second); 345 } 346 347 static PyObject * pyhal_create_param(halobject *self, char *name, hal_type_t type, hal_param_dir_t dir) { 348 char param_name[HAL_NAME_LEN+1]; 349 int res; 350 halitem param; 351 param.is_pin = 0; 352 353 if(type < HAL_BIT || type > HAL_U32) { 354 PyErr_Format(pyhal_error_type, "Invalid param type %d", type); 355 return NULL; 356 } 357 358 param.type = type; 359 param.dir.paramdir = dir; 360 param.u = (halunion*)hal_malloc(sizeof(halunion)); 361 if(!param.u) { 362 PyErr_SetString(PyExc_MemoryError, "hal_malloc failed"); 363 return NULL; 364 } 365 366 res = snprintf(param_name, sizeof(param_name), "%s.%s", self->prefix, name); 367 if(res > HAL_NAME_LEN || res < 0) { return pyhal_error(-EINVAL); } 368 res = hal_param_new(param_name, type, dir, (void*)param.u, self->hal_id); 369 if(res) return pyhal_error(res); 370 371 (*self->items)[name] = param; 372 373 return pyhal_pin_new(¶m, name); 374 } 375 376 377 static PyObject * pyhal_create_pin(halobject *self, char *name, hal_type_t type, hal_pin_dir_t dir) { 378 char pin_name[HAL_NAME_LEN+1]; 379 int res; 380 halitem pin; 381 pin.is_pin = 1; 382 383 if(type < HAL_BIT || type > HAL_U32) { 384 PyErr_Format(pyhal_error_type, "Invalid pin type %d", type); 385 return NULL; 386 } 387 388 pin.type = type; 389 pin.dir.pindir = dir; 390 pin.u = (halunion*)hal_malloc(sizeof(halunion)); 391 if(!pin.u) { 392 PyErr_SetString(PyExc_MemoryError, "hal_malloc failed"); 393 return NULL; 394 } 395 396 res = snprintf(pin_name, sizeof(pin_name), "%s.%s", self->prefix, name); 397 if(res > HAL_NAME_LEN || res < 0) { 398 PyErr_Format(pyhal_error_type, 399 "Invalid pin name length \"%s.%s\": max = %d characters", 400 self->prefix, name, HAL_NAME_LEN); 401 return NULL; 402 } 403 res = hal_pin_new(pin_name, type, dir, (void**)pin.u, self->hal_id); 404 if(res) return pyhal_error(res); 405 406 (*self->items)[name] = pin; 407 408 return pyhal_pin_new(&pin, name); 409 } 410 411 static PyObject *pyhal_new_param(PyObject *_self, PyObject *o) { 412 char *name; 413 int type, dir; 414 halobject *self = (halobject *)_self; 415 416 if(!PyArg_ParseTuple(o, "sii", &name, &type, &dir)) 417 return NULL; 418 EXCEPTION_IF_NOT_LIVE(NULL); 419 420 if (find_item(self, name)) { 421 PyErr_Format(PyExc_ValueError, "Duplicate item name '%s'", name); 422 return NULL; 423 } else { PyErr_Clear(); } 424 return pyhal_create_param(self, name, (hal_type_t)type, (hal_param_dir_t)dir); 425 } 426 427 428 static PyObject *pyhal_new_pin(PyObject *_self, PyObject *o) { 429 char *name; 430 int type, dir; 431 halobject *self = (halobject *)_self; 432 433 if(!PyArg_ParseTuple(o, "sii", &name, &type, &dir)) 434 return NULL; 435 EXCEPTION_IF_NOT_LIVE(NULL); 436 437 if (find_item(self, name)) { 438 PyErr_Format(PyExc_ValueError, "Duplicate item name '%s'", name); 439 return NULL; 440 } else { PyErr_Clear(); } 441 return pyhal_create_pin(self, name, (hal_type_t)type, (hal_pin_dir_t)dir); 442 } 443 444 static PyObject *pyhal_get_pin(PyObject *_self, PyObject *o) { 445 char *name; 446 halobject *self = (halobject *)_self; 447 448 if(!PyArg_ParseTuple(o, "s", &name)) 449 return NULL; 450 EXCEPTION_IF_NOT_LIVE(NULL); 451 452 halitem * pin = find_item(self, name); 453 if (!pin) 454 return NULL; 455 return pyhal_pin_new(pin, name); 456 } 457 458 static PyObject *pyhal_ready(PyObject *_self, PyObject *o) { 459 // hal_ready did not exist in EMC 2.0.x, make it a no-op 460 halobject *self = (halobject *)_self; 461 EXCEPTION_IF_NOT_LIVE(NULL); 462 int res = hal_ready(self->hal_id); 463 if(res) return pyhal_error(res); 464 Py_RETURN_NONE; 465 } 466 467 static PyObject *pyhal_exit(PyObject *_self, PyObject *o) { 468 halobject *self = (halobject *)_self; 469 pyhal_exit_impl(self); 470 Py_RETURN_NONE; 471 } 472 473 static PyObject *pyhal_repr(PyObject *_self) { 474 halobject *self = (halobject *)_self; 475 return PyString_FromFormat("<hal component %s(%d) with %d pins and params>", 476 self->name, self->hal_id, (int)self->items->size()); 477 } 478 479 static PyObject *pyhal_getattro(PyObject *_self, PyObject *attro) { 480 PyObject *result; 481 halobject *self = (halobject *)_self; 482 EXCEPTION_IF_NOT_LIVE(NULL); 483 484 result = PyObject_GenericGetAttr((PyObject*)self, attro); 485 if(result) return result; 486 487 PyErr_Clear(); 488 return pyhal_read_common(find_item(self, PyString_AsString(attro))); 489 } 490 491 static int pyhal_setattro(PyObject *_self, PyObject *attro, PyObject *v) { 492 halobject *self = (halobject *)_self; 493 EXCEPTION_IF_NOT_LIVE(-1); 494 return pyhal_write_common(find_item(self, PyString_AsString(attro)), v); 495 } 496 497 static Py_ssize_t pyhal_len(PyObject *_self) { 498 halobject* self = (halobject*)_self; 499 EXCEPTION_IF_NOT_LIVE(-1); 500 return self->items->size(); 501 } 502 503 static PyObject *pyhal_get_prefix(PyObject *_self, PyObject *args) { 504 halobject* self = (halobject*)_self; 505 if(!PyArg_ParseTuple(args, "")) return NULL; 506 EXCEPTION_IF_NOT_LIVE(NULL); 507 508 if(!self->prefix) 509 Py_RETURN_NONE; 510 511 return PyString_FromString(self->prefix); 512 } 513 514 515 static PyObject *pyhal_set_prefix(PyObject *_self, PyObject *args) { 516 char *newprefix; 517 halobject* self = (halobject*)_self; 518 if(!PyArg_ParseTuple(args, "s", &newprefix)) return NULL; 519 EXCEPTION_IF_NOT_LIVE(NULL); 520 521 if(self->prefix) 522 free(self->prefix); 523 self->prefix = strdup(newprefix); 524 525 if(!self->prefix) { 526 PyErr_SetString(PyExc_MemoryError, "strdup(prefix) failed"); 527 return NULL; 528 } 529 530 Py_RETURN_NONE; 531 } 532 533 static PyMethodDef hal_methods[] = { 534 {"setprefix", pyhal_set_prefix, METH_VARARGS, 535 "Set the prefix for newly created pins and parameters"}, 536 {"getprefix", pyhal_get_prefix, METH_VARARGS, 537 "Get the prefix for newly created pins and parameters"}, 538 {"newparam", pyhal_new_param, METH_VARARGS, 539 "Create a new parameter"}, 540 {"newpin", pyhal_new_pin, METH_VARARGS, 541 "Create a new pin"}, 542 {"getitem", pyhal_get_pin, METH_VARARGS, 543 "Get existing pin object"}, 544 {"exit", pyhal_exit, METH_NOARGS, 545 "Call hal_exit"}, 546 {"ready", pyhal_ready, METH_NOARGS, 547 "Call hal_ready"}, 548 {NULL}, 549 }; 550 551 static PyMappingMethods halobject_map = { 552 pyhal_len, 553 pyhal_getattro, 554 pyhal_setattro 555 }; 556 557 static 558 PyTypeObject halobject_type = { 559 PyObject_HEAD_INIT(NULL) 560 0, /*ob_size*/ 561 "hal.component", /*tp_name*/ 562 sizeof(halobject), /*tp_basicsize*/ 563 0, /*tp_itemsize*/ 564 pyhal_delete, /*tp_dealloc*/ 565 0, /*tp_print*/ 566 0, /*tp_getattr*/ 567 0, /*tp_setattr*/ 568 0, /*tp_compare*/ 569 pyhal_repr, /*tp_repr*/ 570 0, /*tp_as_number*/ 571 0, /*tp_as_sequence*/ 572 &halobject_map, /*tp_as_mapping*/ 573 0, /*tp_hash */ 574 0, /*tp_call*/ 575 0, /*tp_str*/ 576 pyhal_getattro, /*tp_getattro*/ 577 pyhal_setattro, /*tp_setattro*/ 578 0, /*tp_as_buffer*/ 579 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ 580 "HAL Component", /*tp_doc*/ 581 0, /*tp_traverse*/ 582 0, /*tp_clear*/ 583 0, /*tp_richcompare*/ 584 0, /*tp_weaklistoffset*/ 585 0, /*tp_iter*/ 586 0, /*tp_iternext*/ 587 hal_methods, /*tp_methods*/ 588 0, /*tp_members*/ 589 0, /*tp_getset*/ 590 0, /*tp_base*/ 591 0, /*tp_dict*/ 592 0, /*tp_descr_get*/ 593 0, /*tp_descr_set*/ 594 0, /*tp_dictoffset*/ 595 pyhal_init, /*tp_init*/ 596 0, /*tp_alloc*/ 597 PyType_GenericNew, /*tp_new*/ 598 0, /*tp_free*/ 599 0, /*tp_is_gc*/ 600 }; 601 602 static const char * pin_type2name(hal_type_t type) { 603 switch (type) { 604 case HAL_BIT: return "BIT"; 605 case HAL_S32: return "S32"; 606 case HAL_U32: return "U32"; 607 case HAL_FLOAT: return "FLOAT"; 608 default: return "unknown"; 609 } 610 } 611 612 static const char * pin_dir2name(hal_pin_dir_t type) { 613 switch (type) { 614 case HAL_IN: return "IN"; 615 case HAL_IO: return "IO"; 616 case HAL_OUT: return "OUT"; 617 default: return "unknown"; 618 } 619 } 620 621 static const char * param_dir2name(hal_param_dir_t type) { 622 switch (type) { 623 case HAL_RO: return "RO"; 624 case HAL_RW: return "RW"; 625 default: return "unknown"; 626 } 627 } 628 629 static PyObject *pyhalpin_repr(PyObject *_self) { 630 pyhalitem *pyself = (pyhalitem *) _self; 631 halitem *self = &pyself->pin; 632 633 const char * name = "(null)"; 634 if (pyself->name) name = pyself->name; 635 636 if (!self->is_pin) 637 return PyString_FromFormat("<hal param \"%s\" %s-%s>", name, 638 pin_type2name(self->type), param_dir2name(self->dir.paramdir)); 639 return PyString_FromFormat("<hal pin \"%s\" %s-%s>", name, 640 pin_type2name(self->type), pin_dir2name(self->dir.pindir)); 641 } 642 643 static int pyhalpin_init(PyObject *_self, PyObject *, PyObject *) { 644 PyErr_Format(PyExc_RuntimeError, 645 "Cannot be constructed directly"); 646 return -1; 647 } 648 649 static void pyhalpin_delete(PyObject *_self) { 650 pyhalitem *self = (pyhalitem *)_self; 651 652 if(self->name) free(self->name); 653 654 PyObject_Del(self); 655 } 656 657 static PyObject * pyhal_pin_set(PyObject * _self, PyObject * value) { 658 pyhalitem * self = (pyhalitem *) _self; 659 if (pyhal_write_common(&self->pin, value) == -1) 660 return NULL; 661 Py_RETURN_NONE; 662 } 663 664 static PyObject * pyhal_pin_get(PyObject * _self, PyObject *) { 665 pyhalitem * self = (pyhalitem *) _self; 666 return pyhal_read_common(&self->pin); 667 } 668 669 static PyObject * pyhal_pin_get_type(PyObject * _self, PyObject *) { 670 pyhalitem * self = (pyhalitem *) _self; 671 return PyInt_FromLong(self->pin.type); 672 } 673 674 static PyObject * pyhal_pin_get_dir(PyObject * _self, PyObject *) { 675 pyhalitem * self = (pyhalitem *) _self; 676 if (self->pin.is_pin) 677 return PyInt_FromLong(self->pin.dir.pindir); 678 else 679 return PyInt_FromLong(self->pin.dir.paramdir); 680 } 681 682 static PyObject * pyhal_pin_is_pin(PyObject * _self, PyObject *) { 683 pyhalitem * self = (pyhalitem *) _self; 684 return PyBool_FromLong(self->pin.is_pin); 685 } 686 687 static PyObject * pyhal_pin_get_name(PyObject * _self, PyObject *) { 688 pyhalitem * self = (pyhalitem *) _self; 689 if (!self->name) 690 Py_RETURN_NONE; 691 return PyString_FromString(self->name); 692 } 693 694 static PyMethodDef halpin_methods[] = { 695 {"set", pyhal_pin_set, METH_O, "Set item value"}, 696 {"get", pyhal_pin_get, METH_NOARGS, "Get item value"}, 697 {"get_type", pyhal_pin_get_type, METH_NOARGS, "Get item type"}, 698 {"get_dir", pyhal_pin_get_dir, METH_NOARGS, "Get item direction"}, 699 {"get_name", pyhal_pin_get_name, METH_NOARGS, "Get item name"}, 700 {"is_pin", pyhal_pin_is_pin, METH_NOARGS, "If item is pin or param"}, 701 {NULL}, 702 }; 703 704 static 705 PyTypeObject halpin_type = { 706 PyObject_HEAD_INIT(NULL) 707 0, /*ob_size*/ 708 "hal.item", /*tp_name*/ 709 sizeof(pyhalitem), /*tp_basicsize*/ 710 0, /*tp_itemsize*/ 711 pyhalpin_delete, /*tp_dealloc*/ 712 0, /*tp_print*/ 713 0, /*tp_getattr*/ 714 0, /*tp_setattr*/ 715 0, /*tp_compare*/ 716 pyhalpin_repr, /*tp_repr*/ 717 0, /*tp_as_number*/ 718 0, /*tp_as_sequence*/ 719 0, /*tp_as_mapping*/ 720 0, /*tp_hash */ 721 0, /*tp_call*/ 722 0, /*tp_str*/ 723 0, /*tp_getattro*/ 724 0, /*tp_setattro*/ 725 0, /*tp_as_buffer*/ 726 Py_TPFLAGS_DEFAULT, /*tp_flags*/ 727 "HAL Pin", /*tp_doc*/ 728 0, /*tp_traverse*/ 729 0, /*tp_clear*/ 730 0, /*tp_richcompare*/ 731 0, /*tp_weaklistoffset*/ 732 0, /*tp_iter*/ 733 0, /*tp_iternext*/ 734 halpin_methods, /*tp_methods*/ 735 0, /*tp_members*/ 736 0, /*tp_getset*/ 737 0, /*tp_base*/ 738 0, /*tp_dict*/ 739 0, /*tp_descr_get*/ 740 0, /*tp_descr_set*/ 741 0, /*tp_dictoffset*/ 742 pyhalpin_init, /*tp_init*/ 743 0, /*tp_alloc*/ 744 PyType_GenericNew, /*tp_new*/ 745 0, /*tp_free*/ 746 0, /*tp_is_gc*/ 747 }; 748 749 static PyObject * pyhal_pin_new(halitem * pin, const char * name) { 750 pyhalitem * pypin = PyObject_New(pyhalitem, &halpin_type); 751 if (!pypin) 752 return NULL; 753 pypin->pin = *pin; 754 if (name) 755 pypin->name = strdup(name); 756 else 757 pypin->name = NULL; 758 759 return (PyObject *) pypin; 760 } 761 762 PyObject *pin_has_writer(PyObject *self, PyObject *args) { 763 char *name; 764 if(!PyArg_ParseTuple(args, "s", &name)) return NULL; 765 if(!SHMPTR(0)) { 766 PyErr_Format(PyExc_RuntimeError, 767 "Cannot call before creating component"); 768 return NULL; 769 } 770 771 hal_pin_t *pin = halpr_find_pin_by_name(name); 772 if(!pin) { 773 PyErr_Format(PyExc_NameError, "Pin `%s' does not exist", name); 774 return NULL; 775 } 776 777 if(pin->signal) { 778 hal_sig_t *signal = (hal_sig_t*)SHMPTR(pin->signal); 779 return PyBool_FromLong(signal->writers > 0); 780 } 781 Py_INCREF(Py_False); 782 return Py_False; 783 } 784 785 786 PyObject *component_exists(PyObject *self, PyObject *args) { 787 char *name; 788 if(!PyArg_ParseTuple(args, "s", &name)) return NULL; 789 if(!SHMPTR(0)) { 790 PyErr_Format(PyExc_RuntimeError, 791 "Cannot call before creating component"); 792 return NULL; 793 } 794 795 return PyBool_FromLong(halpr_find_comp_by_name(name) != NULL); 796 } 797 798 PyObject *component_is_ready(PyObject *self, PyObject *args) { 799 char *name; 800 if(!PyArg_ParseTuple(args, "s", &name)) return NULL; 801 if(!SHMPTR(0)) { 802 PyErr_Format(PyExc_RuntimeError, 803 "Cannot call before creating component"); 804 return NULL; 805 } 806 807 return PyBool_FromLong(halpr_find_comp_by_name(name)->ready != 0); 808 } 809 810 PyObject *new_sig(PyObject *self, PyObject *args) { 811 char *name; 812 int type,retval; 813 if(!PyArg_ParseTuple(args, "si", &name,&type)) return NULL; 814 if(!SHMPTR(0)) { 815 PyErr_Format(PyExc_RuntimeError, 816 "Cannot call before creating component"); 817 return NULL; 818 } 819 //printf("INFO HALMODULE -- make signal -> %s type %d\n",name,(hal_type_t) type); 820 switch (type) { 821 case HAL_BIT: 822 retval = hal_signal_new(name, HAL_BIT); 823 break; 824 case HAL_S32: 825 retval = hal_signal_new(name, HAL_S32); 826 break; 827 case HAL_U32: 828 retval = hal_signal_new(name, HAL_U32); 829 break; 830 case HAL_FLOAT: 831 retval = hal_signal_new(name, HAL_FLOAT); 832 break; 833 default: { PyErr_Format(PyExc_RuntimeError, 834 "not a valid HAL signal type"); 835 return NULL;} 836 } 837 return PyBool_FromLong(retval != 0); 838 } 839 840 PyObject *connect(PyObject *self, PyObject *args) { 841 char *signame,*pinname; 842 if(!PyArg_ParseTuple(args, "ss", &pinname,&signame)) return NULL; 843 if(!SHMPTR(0)) { 844 PyErr_Format(PyExc_RuntimeError, 845 "Cannot call before creating component"); 846 return NULL; 847 } 848 //printf("INFO HALMODULE -- link sig %s to pin %s\n",signame,pinname); 849 return PyBool_FromLong(hal_link(pinname, signame) != 0); 850 } 851 852 static int set_common(hal_type_t type, void *d_ptr, char *value) { 853 // This function assumes that the mutex is held 854 int retval = 0; 855 double fval; 856 long lval; 857 unsigned long ulval; 858 char *cp = value; 859 860 switch (type) { 861 case HAL_BIT: 862 if ((strcmp("1", value) == 0) || (strcasecmp("TRUE", value) == 0)) { 863 *(hal_bit_t *) (d_ptr) = 1; 864 } else if ((strcmp("0", value) == 0) 865 || (strcasecmp("FALSE", value)) == 0) { 866 *(hal_bit_t *) (d_ptr) = 0; 867 } else { 868 869 retval = -EINVAL; 870 } 871 break; 872 case HAL_FLOAT: 873 fval = strtod ( value, &cp ); 874 if ((*cp != '\0') && (!isspace(*cp))) { 875 // invalid character(s) in string 876 877 retval = -EINVAL; 878 } else { 879 *((hal_float_t *) (d_ptr)) = fval; 880 } 881 break; 882 case HAL_S32: 883 lval = strtol(value, &cp, 0); 884 if ((*cp != '\0') && (!isspace(*cp))) { 885 // invalid chars in string 886 887 retval = -EINVAL; 888 } else { 889 *((hal_s32_t *) (d_ptr)) = lval; 890 } 891 break; 892 case HAL_U32: 893 ulval = strtoul(value, &cp, 0); 894 if ((*cp != '\0') && (!isspace(*cp))) { 895 // invalid chars in string 896 897 retval = -EINVAL; 898 } else { 899 *((hal_u32_t *) (d_ptr)) = ulval; 900 } 901 break; 902 default: 903 // Shouldn't get here, but just in case... 904 905 retval = -EINVAL; 906 } 907 return retval; 908 } 909 910 PyObject *set_p(PyObject *self, PyObject *args) { 911 char *name,*value; 912 int retval; 913 hal_param_t *param; 914 hal_pin_t *pin; 915 hal_type_t type; 916 void *d_ptr; 917 918 if(!PyArg_ParseTuple(args, "ss", &name,&value)) return NULL; 919 if(!SHMPTR(0)) { 920 PyErr_Format(PyExc_RuntimeError, 921 "Cannot call before creating component"); 922 return NULL; 923 } 924 //printf("INFO HALMODULE -- settting pin / param - name:%s value:%s\n",name,value); 925 // get mutex before accessing shared data 926 rtapi_mutex_get(&(hal_data->mutex)); 927 // search param list for name 928 param = halpr_find_param_by_name(name); 929 if (param == 0) { 930 pin = halpr_find_pin_by_name(name); 931 if(pin == 0) { 932 rtapi_mutex_give(&(hal_data->mutex)); 933 934 PyErr_Format(PyExc_RuntimeError, 935 "pin not found"); 936 return NULL; 937 } else { 938 // found it 939 type = pin->type; 940 if(pin->dir == HAL_OUT) { 941 rtapi_mutex_give(&(hal_data->mutex)); 942 943 PyErr_Format(PyExc_RuntimeError, 944 "pin not writable"); 945 return NULL; 946 } 947 if(pin->signal != 0) { 948 rtapi_mutex_give(&(hal_data->mutex)); 949 950 PyErr_Format(PyExc_RuntimeError, 951 "pin connected to signal"); 952 return NULL; 953 } 954 d_ptr = (void*)&pin->dummysig; 955 } 956 } else { 957 // found it 958 type = param->type; 959 /* is it read only? */ 960 if (param->dir == HAL_RO) { 961 rtapi_mutex_give(&(hal_data->mutex)); 962 963 PyErr_Format(PyExc_RuntimeError, 964 "param not writable"); 965 return NULL; 966 } 967 d_ptr = SHMPTR(param->data_ptr); 968 } 969 retval = set_common(type, d_ptr, value); 970 rtapi_mutex_give(&(hal_data->mutex)); 971 return PyBool_FromLong(retval != 0); 972 } 973 974 975 /*######################################*/ 976 /* Get a Pin, Param or signal value */ 977 PyObject *get_value(PyObject *self, PyObject *args) { 978 char *name; 979 hal_param_t *param; 980 hal_pin_t *pin; 981 hal_sig_t *sig; 982 hal_type_t type; 983 void *d_ptr; 984 985 if(!PyArg_ParseTuple(args, "s", &name)) return NULL; 986 if(!SHMPTR(0)) { 987 PyErr_Format(PyExc_RuntimeError, 988 "Cannot call before creating component"); 989 return NULL; 990 } 991 /* get mutex before accessing shared data */ 992 rtapi_mutex_get(&(hal_data->mutex)); 993 /* search param list for name */ 994 param = halpr_find_param_by_name(name); 995 if (param) { 996 /* found it */ 997 type = param->type; 998 d_ptr = SHMPTR(param->data_ptr); 999 rtapi_mutex_give(&(hal_data->mutex)); 1000 /* convert to python value */ 1001 switch(type) { 1002 case HAL_BIT: return PyBool_FromLong((long)*(hal_bit_t *)d_ptr); 1003 case HAL_U32: return Py_BuildValue("l", (unsigned long)*(hal_u32_t *)d_ptr); 1004 case HAL_S32: return Py_BuildValue("l", (long)*(hal_s32_t *)d_ptr); 1005 case HAL_FLOAT: return Py_BuildValue("f", (double)*(hal_float_t *)d_ptr); 1006 case HAL_TYPE_UNSPECIFIED: /* fallthrough */ ; 1007 } 1008 } 1009 /* not found, search pin list for name */ 1010 pin = halpr_find_pin_by_name(name); 1011 if(pin) { 1012 /* found it */ 1013 type = pin->type; 1014 if (pin->signal != 0) { 1015 sig = (hal_sig_t*)SHMPTR(pin->signal); 1016 d_ptr = SHMPTR(sig->data_ptr); 1017 } else { 1018 sig = 0; 1019 d_ptr = &(pin->dummysig); 1020 } 1021 rtapi_mutex_give(&(hal_data->mutex)); 1022 /* convert to python value */ 1023 switch(type) { 1024 case HAL_BIT: return PyBool_FromLong((long)*(hal_bit_t *)d_ptr); 1025 case HAL_U32: return Py_BuildValue("l", (unsigned long)*(hal_u32_t *)d_ptr); 1026 case HAL_S32: return Py_BuildValue("l", (long)*(hal_s32_t *)d_ptr); 1027 case HAL_FLOAT: return Py_BuildValue("f", (double)*(hal_float_t *)d_ptr); 1028 case HAL_TYPE_UNSPECIFIED: /* fallthrough */ ; 1029 } 1030 } 1031 sig = halpr_find_sig_by_name(name); 1032 if (sig != 0) { 1033 /* found it */ 1034 type = sig->type; 1035 d_ptr = SHMPTR(sig->data_ptr); 1036 rtapi_mutex_give(&(hal_data->mutex)); 1037 /* convert to python value */ 1038 switch(type) { 1039 case HAL_BIT: return PyBool_FromLong((long)*(hal_bit_t *)d_ptr); 1040 case HAL_U32: return Py_BuildValue("l", (unsigned long)*(hal_u32_t *)d_ptr); 1041 case HAL_S32: return Py_BuildValue("l", (long)*(hal_s32_t *)d_ptr); 1042 case HAL_FLOAT: return Py_BuildValue("f", (double)*(hal_float_t *)d_ptr); 1043 case HAL_TYPE_UNSPECIFIED: /* fallthrough */ ; 1044 } 1045 } 1046 /* error if here */ 1047 rtapi_mutex_give(&(hal_data->mutex)); 1048 PyErr_Format(PyExc_RuntimeError, 1049 "Can't set value: pin / param %s not found", name); 1050 return NULL; 1051 1052 } 1053 1054 1055 1056 1057 struct shmobject { 1058 PyObject_HEAD 1059 halobject *comp; 1060 int key; 1061 int shm_id; 1062 unsigned long size; 1063 void *buf; 1064 }; 1065 1066 static int pyshm_init(PyObject *_self, PyObject *args, PyObject *kw) { 1067 shmobject *self = (shmobject *)_self; 1068 self->comp = 0; 1069 self->shm_id = -1; 1070 1071 if(!PyArg_ParseTuple(args, "O!ik", 1072 &halobject_type, &self->comp, &self->key, &self->size)) 1073 return -1; 1074 1075 self->shm_id = rtapi_shmem_new(self->key, self->comp->hal_id, self->size); 1076 if(self->shm_id < 0) { 1077 self->comp = 0; 1078 self->size = 0; 1079 pyrtapi_error(self->shm_id); 1080 return -1; 1081 } 1082 1083 rtapi_shmem_getptr(self->shm_id, &self->buf); 1084 Py_INCREF(self->comp); 1085 1086 return 0; 1087 } 1088 1089 static void pyshm_delete(PyObject *_self) { 1090 shmobject *self = (shmobject *)_self; 1091 if(self->comp && self->shm_id > 0) 1092 rtapi_shmem_delete(self->shm_id, self->comp->hal_id); 1093 Py_XDECREF(self->comp); 1094 } 1095 1096 static Py_ssize_t shm_buffer(PyObject *_self, Py_ssize_t segment, void **ptrptr){ 1097 shmobject *self = (shmobject *)_self; 1098 if(ptrptr) *ptrptr = self->buf; 1099 return self->size; 1100 } 1101 static Py_ssize_t shm_segcount(PyObject *_self, Py_ssize_t *lenp) { 1102 shmobject *self = (shmobject *)_self; 1103 if(lenp) *lenp = self->size; 1104 return 1; 1105 } 1106 1107 static PyObject *pyshm_repr(PyObject *_self) { 1108 shmobject *self = (shmobject *)_self; 1109 return PyString_FromFormat("<shared memory buffer key=%08x id=%d size=%ld>", 1110 self->key, self->shm_id, (unsigned long)self->size); 1111 } 1112 1113 static PyObject *shm_setsize(PyObject *_self, PyObject *args) { 1114 shmobject *self = (shmobject *)_self; 1115 if(!PyArg_ParseTuple(args, "k", &self->size)) return NULL; 1116 Py_RETURN_NONE; 1117 } 1118 1119 static PyObject *shm_getbuffer(PyObject *_self, PyObject *o) { 1120 shmobject *self = (shmobject *)_self; 1121 return (PyObject*)PyBuffer_FromReadWriteObject((PyObject*)self, 0, self->size); 1122 } 1123 1124 static PyObject *set_msg_level(PyObject *_self, PyObject *args) { 1125 int level, res; 1126 if(!PyArg_ParseTuple(args, "i", &level)) return NULL; 1127 res = rtapi_set_msg_level(level); 1128 if(res) return pyhal_error(res); 1129 Py_RETURN_NONE; 1130 } 1131 1132 static PyObject *get_msg_level(PyObject *_self, PyObject *args) { 1133 return PyInt_FromLong(rtapi_get_msg_level()); 1134 } 1135 1136 static 1137 PyBufferProcs shmbuffer_procs = { 1138 shm_buffer, 1139 shm_buffer, 1140 shm_segcount, 1141 NULL 1142 }; 1143 1144 static PyMethodDef shm_methods[] = { 1145 {"getbuffer", shm_getbuffer, METH_NOARGS, 1146 "Get a writable buffer object for the shared memory segment"}, 1147 {"setsize", shm_setsize, METH_VARARGS, 1148 "Set the size of the shared memory segment"}, 1149 {NULL}, 1150 }; 1151 1152 static 1153 PyTypeObject shm_type = { 1154 PyObject_HEAD_INIT(NULL) 1155 0, /*ob_size*/ 1156 "hal.shm", /*tp_name*/ 1157 sizeof(shmobject), /*tp_basicsize*/ 1158 0, /*tp_itemsize*/ 1159 pyshm_delete, /*tp_dealloc*/ 1160 0, /*tp_print*/ 1161 0, /*tp_getattr*/ 1162 0, /*tp_setattr*/ 1163 0, /*tp_compare*/ 1164 pyshm_repr, /*tp_repr*/ 1165 0, /*tp_as_number*/ 1166 0, /*tp_as_sequence*/ 1167 0, /*tp_as_mapping*/ 1168 0, /*tp_hash */ 1169 0, /*tp_call*/ 1170 0, /*tp_str*/ 1171 0, /*tp_getattro*/ 1172 0, /*tp_setattro*/ 1173 &shmbuffer_procs, /*tp_as_buffer*/ 1174 // Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /*tp_flags*/ 1175 Py_TPFLAGS_DEFAULT, /*tp_flags*/ 1176 "HAL Shared Memory", /*tp_doc*/ 1177 0, /*tp_traverse*/ 1178 0, /*tp_clear*/ 1179 0, /*tp_richcompare*/ 1180 0, /*tp_weaklistoffset*/ 1181 0, /*tp_iter*/ 1182 0, /*tp_iternext*/ 1183 shm_methods, /*tp_methods*/ 1184 0, /*tp_members*/ 1185 0, /*tp_getset*/ 1186 0, /*tp_base*/ 1187 0, /*tp_dict*/ 1188 0, /*tp_descr_get*/ 1189 0, /*tp_descr_set*/ 1190 0, /*tp_dictoffset*/ 1191 pyshm_init, /*tp_init*/ 1192 0, /*tp_alloc*/ 1193 PyType_GenericNew, /*tp_new*/ 1194 0, /*tp_free*/ 1195 0, /*tp_is_gc*/ 1196 }; 1197 1198 struct streamobj { 1199 PyObject_HEAD 1200 hal_stream_t stream; 1201 PyObject *pyelt; 1202 halobject *comp; 1203 int key; 1204 bool creator; 1205 unsigned sampleno; 1206 }; 1207 1208 static int pystream_init(PyObject *_self, PyObject *args, PyObject *kw) { 1209 int depth=0; 1210 char *typestring=NULL; 1211 1212 streamobj *self = (streamobj *)_self; 1213 self->sampleno = 0; 1214 1215 // creating a new stream 1216 int r; 1217 if(PyTuple_GET_SIZE(args) == 4) 1218 r = PyArg_ParseTuple(args, "O!iis:hal.stream", 1219 &halobject_type, &self->comp, &self->key, &depth, &typestring); 1220 else 1221 r = PyArg_ParseTuple(args, "O!i|s:hal.stream", 1222 &halobject_type, &self->comp, &self->key, &typestring); 1223 1224 if(!r) return -1; 1225 1226 Py_XINCREF(self->comp); 1227 1228 if(depth) { 1229 self->creator = 1; 1230 r = hal_stream_create(&self->stream, self->comp->hal_id, 1231 self->key, depth, typestring); 1232 } else { 1233 self->creator = 0; 1234 r = hal_stream_attach(&self->stream, self->comp->hal_id, self->key, typestring); 1235 } 1236 if(r < 0) { errno = -r; PyErr_SetFromErrno(PyExc_IOError); return -1; } 1237 1238 int n = hal_stream_element_count(&self->stream); 1239 PyObject *t = PyString_FromStringAndSize(NULL, n); 1240 if(!t) { 1241 if(self->creator) 1242 hal_stream_destroy(&self->stream); 1243 else 1244 hal_stream_detach(&self->stream); 1245 return -1; 1246 } 1247 1248 char *tbuf = PyString_AsString(t); 1249 1250 for(int i=0; i<n; i++) { 1251 switch(hal_stream_element_type(&self->stream, i)) { 1252 case HAL_BIT: tbuf[i] = 'b'; break; 1253 case HAL_FLOAT: tbuf[i] = 'f'; break; 1254 case HAL_S32: tbuf[i] = 's'; break; 1255 case HAL_U32: tbuf[i] = 'u'; break; 1256 default: tbuf[i] = '?'; break; 1257 } 1258 } 1259 self->pyelt = t; 1260 1261 return 0; 1262 } 1263 1264 PyObject *stream_read(PyObject *_self, PyObject *unused) { 1265 streamobj *self = (streamobj *)_self; 1266 int n = PyString_Size(self->pyelt); 1267 hal_stream_data buf[n]; 1268 if(hal_stream_read(&self->stream, buf, &self->sampleno) < 0) 1269 Py_RETURN_NONE; 1270 1271 PyObject *r = PyTuple_New(n); 1272 if(!r) return 0; 1273 1274 for(int i=0; i<n; i++) { 1275 PyObject *o; 1276 switch(PyString_AS_STRING(self->pyelt)[i]) { 1277 case 'b': o = to_python(buf[i].b); break; 1278 case 'f': o = to_python(buf[i].f); break; 1279 case 's': o = to_python(buf[i].s); break; 1280 case 'u': o = to_python(buf[i].u); break; 1281 default: Py_INCREF(Py_None); o = Py_None; break; 1282 } 1283 if(!o) { 1284 Py_DECREF(r); 1285 return 0; 1286 } 1287 PyTuple_SET_ITEM(r, i, o); 1288 } 1289 return r; 1290 } 1291 1292 PyObject *stream_write(PyObject *_self, PyObject *args) { 1293 streamobj *self = (streamobj *)_self; 1294 PyObject *data; 1295 if(!PyArg_ParseTuple(args, "O!:hal.stream.write", &PyTuple_Type, &data)) 1296 return NULL; 1297 1298 int n = PyString_Size(self->pyelt); 1299 if(n < PyTuple_GET_SIZE(data)) { 1300 PyErr_SetString(PyExc_ValueError, "Too few elements to unpack"); 1301 return NULL; 1302 } 1303 if(n > PyTuple_GET_SIZE(data)) { 1304 PyErr_SetString(PyExc_ValueError, "Too many elements to unpack"); 1305 return NULL; 1306 } 1307 1308 hal_stream_data buf[n]; 1309 for(int i=0; i<n; i++) { 1310 PyObject *o = PyTuple_GET_ITEM(data, i); 1311 switch(PyString_AS_STRING(self->pyelt)[i]) { 1312 case 'b': buf[i].b = PyObject_IsTrue(o); break; 1313 case 'f': if(!from_python(o, &buf[i].f)) return NULL; break; 1314 case 's': if(!from_python(o, &buf[i].s)) return NULL; break; 1315 case 'u': if(!from_python(o, &buf[i].u)) return NULL; break; 1316 default: memset(&buf[i], 0, sizeof(buf[i])); break; 1317 } 1318 } 1319 int r = hal_stream_write(&self->stream, buf); 1320 if(r < 0) { 1321 errno = -r; PyErr_SetFromErrno(PyExc_IOError); return 0; 1322 } 1323 Py_RETURN_NONE; 1324 } 1325 1326 static PyMethodDef stream_methods[] = { 1327 {"read", stream_read, METH_NOARGS}, 1328 {"write", stream_write, METH_VARARGS}, 1329 {} 1330 }; 1331 1332 #define VFC(f) reinterpret_cast<void*>(f) 1333 1334 template<class T> 1335 PyObject *stream_getter(PyObject *_self, void *vfp) { 1336 streamobj *self = reinterpret_cast<streamobj*>(_self); 1337 typedef T (*F)(hal_stream_t*); 1338 F fn = reinterpret_cast<F>(vfp); 1339 T result = fn(&self->stream); 1340 return to_python(result); 1341 } 1342 1343 PyObject *stream_element_types(PyObject *_self, void *unused) { 1344 streamobj *self = reinterpret_cast<streamobj*>(_self); 1345 if(!self->pyelt) { 1346 } 1347 Py_INCREF(self->pyelt); 1348 return self->pyelt; 1349 } 1350 1351 // "deprecated conversion from string constant to 'char *'" occurs due to 1352 // missing const-qualifications in Python headers 1353 #pragma GCC diagnostic ignored "-Wwrite-strings" 1354 static PyMemberDef stream_members[] = { 1355 {"sampleno", T_UINT, offsetof(streamobj, sampleno), READONLY, 1356 "The number of the last successfully read sample"}, 1357 {} 1358 }; 1359 1360 static PyGetSetDef stream_getset[] = { 1361 {"readable", stream_getter<bool>, NULL, NULL, VFC(hal_stream_readable)}, 1362 {"writable", stream_getter<bool>, NULL, NULL, VFC(hal_stream_writable)}, 1363 {"depth", stream_getter<int>, NULL, NULL, VFC(hal_stream_depth)}, 1364 {"element_types", stream_element_types, NULL, NULL, NULL}, 1365 {"maxdepth", stream_getter<int>, NULL, NULL, VFC(hal_stream_maxdepth)}, 1366 {"num_underruns", stream_getter<int>, NULL, NULL, VFC(hal_stream_num_underruns)}, 1367 {"num_overruns", stream_getter<int>, NULL, NULL, VFC(hal_stream_num_overruns)}, 1368 {} 1369 }; 1370 #pragma GCC diagnostic warning "-Wwrite-strings" 1371 1372 static void pystream_delete(PyObject *_self) { 1373 streamobj *self = reinterpret_cast<streamobj*>(_self); 1374 if(self->creator) 1375 hal_stream_destroy(&self->stream); 1376 else 1377 hal_stream_detach(&self->stream); 1378 Py_XDECREF(self->pyelt); 1379 Py_XDECREF(self->comp); 1380 self->ob_type->tp_free(self); 1381 } 1382 1383 static PyObject *pystream_repr(PyObject *_self) { 1384 streamobj *self = reinterpret_cast<streamobj*>(_self); 1385 return PyString_FromFormat("<stream 0x%x%s>", self->key, 1386 self->creator ? " creator" : ""); 1387 } 1388 1389 static 1390 PyTypeObject stream_type = { 1391 PyObject_HEAD_INIT(NULL) 1392 0, /*ob_size*/ 1393 "hal.stream", /*tp_name*/ 1394 sizeof(streamobj), /*tp_basicsize*/ 1395 0, /*tp_itemsize*/ 1396 pystream_delete, /*tp_dealloc*/ 1397 0, /*tp_print*/ 1398 0, /*tp_getattr*/ 1399 0, /*tp_setattr*/ 1400 0, /*tp_compare*/ 1401 pystream_repr, /*tp_repr*/ 1402 0, /*tp_as_number*/ 1403 0, /*tp_as_sequence*/ 1404 0, /*tp_as_mapping*/ 1405 0, /*tp_hash */ 1406 0, /*tp_call*/ 1407 0, /*tp_str*/ 1408 0, /*tp_getattro*/ 1409 0, /*tp_setattro*/ 1410 0, /*tp_as_buffer*/ 1411 Py_TPFLAGS_DEFAULT, /*tp_flags*/ 1412 "HAL Stream", /*tp_doc*/ 1413 0, /*tp_traverse*/ 1414 0, /*tp_clear*/ 1415 0, /*tp_richcompare*/ 1416 0, /*tp_weaklistoffset*/ 1417 0, /*tp_iter*/ 1418 0, /*tp_iternext*/ 1419 stream_methods, /*tp_methods*/ 1420 stream_members, /*tp_members*/ 1421 stream_getset, /*tp_getset*/ 1422 0, /*tp_base*/ 1423 0, /*tp_dict*/ 1424 0, /*tp_descr_get*/ 1425 0, /*tp_descr_set*/ 1426 0, /*tp_dictoffset*/ 1427 pystream_init, /*tp_init*/ 1428 0, /*tp_alloc*/ 1429 PyType_GenericNew, /*tp_new*/ 1430 0, /*tp_free*/ 1431 0, /*tp_is_gc*/ 1432 }; 1433 1434 1435 PyMethodDef module_methods[] = { 1436 {"pin_has_writer", pin_has_writer, METH_VARARGS, 1437 "Return a FALSE value if a pin has no writers and TRUE if it does"}, 1438 {"component_exists", component_exists, METH_VARARGS, 1439 "Return a TRUE value if the named component exists"}, 1440 {"component_is_ready", component_is_ready, METH_VARARGS, 1441 "Return a TRUE value if the named component is ready"}, 1442 {"set_msg_level", set_msg_level, METH_VARARGS, 1443 "Set the RTAPI message level"}, 1444 {"get_msg_level", get_msg_level, METH_NOARGS, 1445 "Get the RTAPI message level"}, 1446 {"new_sig", new_sig, METH_VARARGS, 1447 ".new_sig('signal_name', type): Create a new signal with the specified name. 'type' is one of HAL_BIT, HAL_FLOAT, HAL_S32, or HAL_U32."}, 1448 {"connect", connect, METH_VARARGS, 1449 ".connect('pin_name', 'signal_name'): Connect the named pin to the named signal."}, 1450 {"set_p", set_p, METH_VARARGS, 1451 "set pin value"}, 1452 {"get_value", get_value, METH_VARARGS, 1453 ".get_value('name'}: Gets the pin, param or signal value"}, 1454 {NULL}, 1455 }; 1456 1457 const char *module_doc = "Interface to emc2's hal\n" 1458 "\n" 1459 "This module allows the creation of userspace HAL components in Python.\n" 1460 "This includes pins and parameters of the various HAL types.\n" 1461 "\n" 1462 "Typical usage:\n" 1463 "\n" 1464 "import hal, time\n" 1465 "h = hal.component(\"component-name\")\n" 1466 "# create pins and parameters with calls to h.newpin and h.newparam\n" 1467 "h.newpin(\"in\", hal.HAL_FLOAT, hal.HAL_IN)\n" 1468 "h.newpin(\"out\", hal.HAL_FLOAT, hal.HAL_OUT)\n" 1469 "h.ready() # mark the component as 'ready'\n" 1470 "\n" 1471 "try:\n" 1472 " while 1:\n" 1473 " # act on changed input pins; update values on output pins\n" 1474 " time.sleep(1)\n" 1475 " h['out'] = h['in']\n" 1476 "except KeyboardInterrupt: pass" 1477 "\n" 1478 "\n" 1479 "When the component is requested to exit with 'halcmd unload', a\n" 1480 "KeyboardInterrupt exception will be raised." 1481 ; 1482 1483 extern "C" 1484 void init_hal(void) { 1485 PyObject *m = Py_InitModule3("_hal", module_methods, 1486 module_doc); 1487 1488 pyhal_error_type = PyErr_NewException((char*)"hal.error", NULL, NULL); 1489 PyModule_AddObject(m, "error", pyhal_error_type); 1490 1491 PyType_Ready(&halobject_type); 1492 PyType_Ready(&shm_type); 1493 PyType_Ready(&halpin_type); 1494 PyType_Ready(&stream_type); 1495 PyModule_AddObject(m, "component", (PyObject*)&halobject_type); 1496 PyModule_AddObject(m, "shm", (PyObject*)&shm_type); 1497 PyModule_AddObject(m, "item", (PyObject*)&halpin_type); 1498 PyModule_AddObject(m, "stream", (PyObject*)&stream_type); 1499 1500 PyModule_AddIntConstant(m, "MSG_NONE", RTAPI_MSG_NONE); 1501 PyModule_AddIntConstant(m, "MSG_ERR", RTAPI_MSG_ERR); 1502 PyModule_AddIntConstant(m, "MSG_WARN", RTAPI_MSG_WARN); 1503 PyModule_AddIntConstant(m, "MSG_INFO", RTAPI_MSG_INFO); 1504 PyModule_AddIntConstant(m, "MSG_DBG", RTAPI_MSG_DBG); 1505 PyModule_AddIntConstant(m, "MSG_ALL", RTAPI_MSG_ALL); 1506 1507 PyModule_AddIntConstant(m, "HAL_BIT", HAL_BIT); 1508 PyModule_AddIntConstant(m, "HAL_FLOAT", HAL_FLOAT); 1509 PyModule_AddIntConstant(m, "HAL_S32", HAL_S32); 1510 PyModule_AddIntConstant(m, "HAL_U32", HAL_U32); 1511 1512 PyModule_AddIntConstant(m, "HAL_RO", HAL_RO); 1513 PyModule_AddIntConstant(m, "HAL_RW", HAL_RW); 1514 PyModule_AddIntConstant(m, "HAL_IN", HAL_IN); 1515 PyModule_AddIntConstant(m, "HAL_OUT", HAL_OUT); 1516 PyModule_AddIntConstant(m, "HAL_IO", HAL_IO); 1517 1518 PyModule_AddIntConstant(m, "is_sim", !rtapi_is_realtime()); 1519 PyModule_AddIntConstant(m, "is_rt", rtapi_is_realtime()); 1520 1521 PyModule_AddIntConstant(m, "is_kernelspace", rtapi_is_kernelspace()); 1522 PyModule_AddIntConstant(m, "is_userspace", !rtapi_is_kernelspace()); 1523 1524 PyModule_AddIntConstant(m, "streamer_base", 0x48535430); 1525 PyModule_AddIntConstant(m, "sampler_base", 0x48534130); 1526 1527 #ifdef RTAPI_KERNEL_VERSION 1528 PyModule_AddStringConstant(m, "kernel_version", RTAPI_KERNEL_VERSION); 1529 #endif 1530 1531 PyRun_SimpleString( 1532 "(lambda s=__import__('signal'):" 1533 "s.signal(s.SIGTERM, s.default_int_handler))()"); 1534 } 1535