/ src / hal / halmodule.cc
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(&param, 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