pcipywrap.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. #include "pcipywrap.h"
  2. #include "locking.h"
  3. char* full_log = NULL;
  4. /*!
  5. * \brief Wraping for vsnprintf function, that saves string to char*
  6. * \return saved from vsnprintf string
  7. */
  8. char* vmake_str(const char* msg, va_list vl)
  9. {
  10. char *buf;
  11. size_t sz;
  12. va_list vl_copy;
  13. va_copy(vl_copy, vl);
  14. sz = vsnprintf(NULL, 0, msg, vl);
  15. buf = (char *)malloc(sz + 1);
  16. if(!buf)
  17. {
  18. return NULL;
  19. }
  20. vsnprintf(buf, sz+1, msg, vl_copy);
  21. va_end(vl_copy);
  22. return buf;
  23. }
  24. /*!
  25. * \brief Wraping for vsnprintf function, that saves string to char*
  26. * \return saved from vsnprintf string
  27. */
  28. char* make_str(const char* msg, ...)
  29. {
  30. va_list vl;
  31. va_start(vl, msg);
  32. char *buf = vmake_str(msg, vl);
  33. va_end(vl);
  34. return buf;
  35. }
  36. /*!
  37. * \brief Version of pcilib_logger_t, that saves error text to Python exeption
  38. */
  39. void pcilib_print_error_to_py(void *arg, const char *file, int line,
  40. pcilib_log_priority_t prio, const char *msg,
  41. va_list va) {
  42. //wrap error message with file and line number
  43. char* buf_raw_msg = vmake_str(msg, va);
  44. char* buf_wrapped_message = make_str("%s [%s:%d]\n", buf_raw_msg, file, line);
  45. if(prio == PCILIB_LOG_ERROR)
  46. {
  47. if(!full_log)
  48. full_log = make_str("");
  49. //copy received message to log
  50. char* buf = full_log;
  51. full_log = make_str("%s%s", buf, buf_wrapped_message);
  52. free(buf);
  53. }
  54. else
  55. printf("%s", buf_wrapped_message);
  56. free(buf_wrapped_message);
  57. free(buf_raw_msg);
  58. }
  59. void set_python_exception(const char* msg, ...)
  60. {
  61. va_list vl;
  62. va_start(vl, msg);
  63. char *buf = vmake_str(msg, vl);
  64. char* wrapped_exeption;
  65. if(full_log)
  66. wrapped_exeption = make_str("%s\nprogramm error log:\n%s", buf, full_log);
  67. else
  68. wrapped_exeption = buf;
  69. free(full_log);
  70. full_log = NULL;
  71. PyErr_SetString(PyExc_Exception, wrapped_exeption);
  72. free(buf);
  73. if(full_log)
  74. free(wrapped_exeption);
  75. va_end(vl);
  76. }
  77. void redirect_logs_to_exeption()
  78. {
  79. pcilib_set_logger(pcilib_get_log_level(),
  80. pcilib_print_error_to_py,
  81. pcilib_get_logger_context());
  82. }
  83. /*!
  84. * \brief Wrap for PyDict_SetItem, with decrease reference counting after set.
  85. */
  86. void pcilib_pydict_set_item(PyObject* dict, PyObject* name, PyObject* value)
  87. {
  88. PyDict_SetItem(dict,
  89. name,
  90. value);
  91. Py_XDECREF(name);
  92. Py_XDECREF(value);
  93. }
  94. /*!
  95. * \brief Wrap for PyList_Append, with decrease reference counting after append.
  96. */
  97. void pcilib_pylist_append(PyObject* list, PyObject* value)
  98. {
  99. PyList_Append(list, value);
  100. Py_XDECREF(value);
  101. }
  102. void add_pcilib_value_to_dict(pcilib_t* ctx, PyObject* dict, pcilib_value_t* val, const char *name)
  103. {
  104. PyObject *py_val = (PyObject*)pcilib_get_value_as_pyobject(ctx, val, NULL);
  105. if(py_val)
  106. pcilib_pydict_set_item(dict,
  107. PyUnicode_FromString(name),
  108. py_val);
  109. else
  110. pcilib_pydict_set_item(dict,
  111. PyUnicode_FromString("defvalue"),
  112. PyUnicode_FromString("invalid"));
  113. }
  114. PyObject * pcilib_convert_property_info_to_pyobject(pcilib_t* ctx, pcilib_property_info_t listItem)
  115. {
  116. PyObject* pylistItem = PyDict_New();
  117. if(listItem.name)
  118. pcilib_pydict_set_item(pylistItem,
  119. PyUnicode_FromString("name"),
  120. PyUnicode_FromString(listItem.name));
  121. if(listItem.description)
  122. pcilib_pydict_set_item(pylistItem,
  123. PyUnicode_FromString("description"),
  124. PyUnicode_FromString(listItem.description));
  125. if(listItem.path)
  126. pcilib_pydict_set_item(pylistItem,
  127. PyUnicode_FromString("path"),
  128. PyUnicode_FromString(listItem.path));
  129. //serialize types
  130. const char* type = "invalid";
  131. switch(listItem.type)
  132. {
  133. case PCILIB_TYPE_INVALID:
  134. type = "invalid";
  135. break;
  136. case PCILIB_TYPE_STRING:
  137. type = "string";
  138. break;
  139. case PCILIB_TYPE_DOUBLE:
  140. type = "double";
  141. break;
  142. case PCILIB_TYPE_LONG :
  143. type = "long";
  144. break;
  145. default:
  146. break;
  147. }
  148. pcilib_pydict_set_item(pylistItem,
  149. PyUnicode_FromString("type"),
  150. PyUnicode_FromString(type));
  151. //serialize modes
  152. PyObject* modes = PyList_New(0);
  153. if((listItem.mode & PCILIB_ACCESS_R ) == PCILIB_REGISTER_R)
  154. pcilib_pylist_append(modes, PyUnicode_FromString("R"));
  155. if((listItem.mode & PCILIB_ACCESS_W ) == PCILIB_REGISTER_W)
  156. pcilib_pylist_append(modes, PyUnicode_FromString("W"));
  157. if((listItem.mode & PCILIB_ACCESS_RW ) == PCILIB_REGISTER_RW)
  158. pcilib_pylist_append(modes, PyUnicode_FromString("RW"));
  159. if((listItem.mode & PCILIB_REGISTER_INCONSISTENT) == PCILIB_REGISTER_INCONSISTENT)
  160. pcilib_pylist_append(modes, PyUnicode_FromString("NO_CHK"));
  161. pcilib_pydict_set_item(pylistItem,
  162. PyUnicode_FromString("mode"),
  163. modes);
  164. //serialize flags
  165. PyObject* flags = PyList_New(0);
  166. if((listItem.flags & PCILIB_LIST_FLAG_CHILDS ) == PCILIB_LIST_FLAG_CHILDS)
  167. pcilib_pylist_append(flags, PyUnicode_FromString("childs"));
  168. pcilib_pydict_set_item(pylistItem,
  169. PyUnicode_FromString("flags"),
  170. flags);
  171. if(listItem.unit)
  172. pcilib_pydict_set_item(pylistItem,
  173. PyUnicode_FromString("unit"),
  174. PyUnicode_FromString(listItem.unit));
  175. return pylistItem;
  176. }
  177. PyObject * pcilib_convert_register_info_to_pyobject(pcilib_t* ctx, pcilib_register_info_t listItem)
  178. {
  179. PyObject* pylistItem = PyDict_New();
  180. if(listItem.name)
  181. pcilib_pydict_set_item(pylistItem,
  182. PyUnicode_FromString("name"),
  183. PyUnicode_FromString(listItem.name));
  184. if(listItem.description)
  185. pcilib_pydict_set_item(pylistItem,
  186. PyUnicode_FromString("description"),
  187. PyUnicode_FromString(listItem.description));
  188. if(listItem.bank)
  189. pcilib_pydict_set_item(pylistItem,
  190. PyUnicode_FromString("bank"),
  191. PyUnicode_FromString(listItem.bank));
  192. //serialize modes
  193. PyObject* modes = PyList_New(0);
  194. if((listItem.mode & PCILIB_REGISTER_R) == PCILIB_REGISTER_R)
  195. pcilib_pylist_append(modes, PyUnicode_FromString("R"));
  196. if((listItem.mode & PCILIB_REGISTER_W) == PCILIB_REGISTER_W)
  197. pcilib_pylist_append(modes, PyUnicode_FromString("W"));
  198. if((listItem.mode & PCILIB_REGISTER_RW) == PCILIB_REGISTER_RW)
  199. pcilib_pylist_append(modes, PyUnicode_FromString("RW"));
  200. if((listItem.mode & PCILIB_REGISTER_W1C) == PCILIB_REGISTER_W1C)
  201. pcilib_pylist_append(modes, PyUnicode_FromString("W1C"));
  202. if((listItem.mode & PCILIB_REGISTER_RW1C) == PCILIB_REGISTER_RW1C)
  203. pcilib_pylist_append(modes, PyUnicode_FromString("RW1C"));
  204. if((listItem.mode & PCILIB_REGISTER_W1I) == PCILIB_REGISTER_W1I)
  205. pcilib_pylist_append(modes, PyUnicode_FromString("W1I"));
  206. if((listItem.mode & PCILIB_REGISTER_RW1I) == PCILIB_REGISTER_RW1I)
  207. pcilib_pylist_append(modes, PyUnicode_FromString("RW1I"));
  208. if((listItem.mode & PCILIB_REGISTER_INCONSISTENT) == PCILIB_REGISTER_INCONSISTENT)
  209. pcilib_pylist_append(modes, PyUnicode_FromString("NO_CHK"));
  210. pcilib_pydict_set_item(pylistItem,
  211. PyUnicode_FromString("mode"),
  212. modes);
  213. pcilib_value_t defval = {0};
  214. pcilib_set_value_from_register_value(ctx, &defval, listItem.defvalue);
  215. add_pcilib_value_to_dict(ctx, pylistItem, &defval, "defvalue");
  216. if(listItem.range)
  217. {
  218. pcilib_value_t minval = {0};
  219. pcilib_set_value_from_register_value(ctx, &minval, listItem.range->min);
  220. pcilib_value_t maxval = {0};
  221. pcilib_set_value_from_register_value(ctx, &maxval, listItem.range->max);
  222. PyObject* range = PyDict_New();
  223. add_pcilib_value_to_dict(ctx, range, &minval, "min");
  224. add_pcilib_value_to_dict(ctx, range, &maxval, "max");
  225. pcilib_pydict_set_item(pylistItem,
  226. PyUnicode_FromString("range"),
  227. range);
  228. }
  229. if(listItem.values)
  230. {
  231. PyObject* values = PyList_New(0);
  232. for (int j = 0; listItem.values[j].name; j++)
  233. {
  234. PyObject* valuesItem = PyDict_New();
  235. pcilib_value_t val = {0};
  236. pcilib_set_value_from_register_value(ctx, &val, listItem.values[j].value);
  237. pcilib_value_t min = {0};
  238. pcilib_set_value_from_register_value(ctx, &min, listItem.values[j].min);
  239. pcilib_value_t max = {0};
  240. pcilib_set_value_from_register_value(ctx, &max, listItem.values[j].max);
  241. add_pcilib_value_to_dict(ctx, valuesItem, &val, "value");
  242. add_pcilib_value_to_dict(ctx, valuesItem, &min, "min");
  243. add_pcilib_value_to_dict(ctx, valuesItem, &max, "max");
  244. if(listItem.values[j].name)
  245. pcilib_pydict_set_item(valuesItem,
  246. PyUnicode_FromString("name"),
  247. PyUnicode_FromString(listItem.values[j].name));
  248. if(listItem.values[j].description)
  249. {
  250. pcilib_pydict_set_item(valuesItem,
  251. PyUnicode_FromString("description"),
  252. PyUnicode_FromString(listItem.values[j].description));
  253. }
  254. pcilib_pylist_append(values, valuesItem);
  255. }
  256. pcilib_pydict_set_item(pylistItem,
  257. PyUnicode_FromString("values"),
  258. values);
  259. }
  260. return pylistItem;
  261. }
  262. pcipywrap *new_pcipywrap(const char* fpga_device, const char* model)
  263. {
  264. //opening device
  265. pcilib_t* ctx = pcilib_open(fpga_device, model);
  266. if(!ctx)
  267. {
  268. set_python_exception("Failed pcilib_open(%s, %s)", fpga_device, model);
  269. return NULL;
  270. }
  271. pcipywrap *self;
  272. self = (pcipywrap *) malloc(sizeof(pcipywrap));
  273. self->shared = 0;
  274. self->ctx = ctx;
  275. return self;
  276. }
  277. pcipywrap *create_pcipywrap(PyObject* ctx)
  278. {
  279. if(!PyCapsule_CheckExact(ctx))
  280. {
  281. set_python_exception("Incorrect ctx type. Only PyCapsule is allowed");
  282. return NULL;
  283. }
  284. pcipywrap *self;
  285. self = (pcipywrap *) malloc(sizeof(pcipywrap));
  286. self->shared = 1;
  287. self->ctx = PyCapsule_GetPointer(ctx, PyCapsule_GetName(ctx));
  288. return self;
  289. }
  290. void delete_pcipywrap(pcipywrap *self) {
  291. if(!self->shared)
  292. pcilib_close(self->ctx);
  293. free(self);
  294. }
  295. PyObject* pcipywrap_read_register(pcipywrap *self, const char *regname, const char *bank)
  296. {
  297. pcilib_value_t val = {0};
  298. pcilib_register_value_t reg_value;
  299. int err;
  300. err = pcilib_read_register(self->ctx, bank, regname, &reg_value);
  301. if(err)
  302. {
  303. set_python_exception("Failed pcilib_read_register");
  304. return NULL;
  305. }
  306. err = pcilib_set_value_from_register_value(self->ctx, &val, reg_value);
  307. if(err)
  308. {
  309. set_python_exception("Failed pcilib_set_value_from_register_value");
  310. return NULL;
  311. }
  312. return pcilib_get_value_as_pyobject(self->ctx, &val, NULL);
  313. }
  314. PyObject* pcipywrap_write_register(pcipywrap *self, PyObject* val, const char *regname, const char *bank)
  315. {
  316. pcilib_value_t val_internal = {0};
  317. pcilib_register_value_t reg_value;
  318. int err;
  319. err = pcilib_set_value_from_pyobject(self->ctx, &val_internal, val);
  320. if(err)
  321. {
  322. set_python_exception("Failed pcilib_set_value_from_pyobject");
  323. return NULL;
  324. }
  325. reg_value = pcilib_get_value_as_register_value(self->ctx, &val_internal, &err);
  326. if(err)
  327. {
  328. set_python_exception("Failed pcilib_set_value_from_pyobject, (error %i)", err);
  329. return NULL;
  330. }
  331. err = pcilib_write_register(self->ctx, bank, regname, reg_value);
  332. if(err)
  333. {
  334. set_python_exception("Failed pcilib_set_value_from_pyobject, (error %i)", err);
  335. return NULL;
  336. }
  337. return PyLong_FromLong((long)1);
  338. }
  339. PyObject* pcipywrap_get_property(pcipywrap *self, const char *prop)
  340. {
  341. int err;
  342. pcilib_value_t val = {0};
  343. err = pcilib_get_property(self->ctx, prop, &val);
  344. if(err)
  345. {
  346. set_python_exception("Failed pcilib_get_property, (error %i)", err);
  347. return NULL;
  348. }
  349. return pcilib_get_value_as_pyobject(self->ctx, &val, NULL);
  350. }
  351. PyObject* pcipywrap_set_property(pcipywrap *self, PyObject* val, const char *prop)
  352. {
  353. int err;
  354. pcilib_value_t val_internal = {0};
  355. err = pcilib_set_value_from_pyobject(self->ctx, &val_internal, val);
  356. if(err)
  357. {
  358. set_python_exception("pcilib_set_value_from_pyobject, (error %i)", err);
  359. return NULL;
  360. }
  361. err = pcilib_set_property(self->ctx, prop, &val_internal);
  362. if(err)
  363. {
  364. set_python_exception("pcilib_set_property, (error %i)", err);
  365. return NULL;
  366. }
  367. return PyLong_FromLong((long)1);
  368. }
  369. PyObject* pcipywrap_get_registers_list(pcipywrap *self, const char *bank)
  370. {
  371. pcilib_register_info_t *list = pcilib_get_register_list(self->ctx, bank, PCILIB_LIST_FLAGS_DEFAULT);
  372. if(!list) {
  373. set_python_exception("pcilib_get_register_list return NULL");
  374. return NULL;
  375. }
  376. PyObject* pyList = PyList_New(0);
  377. for(int i = 0; list[i].name; i++)
  378. {
  379. //serialize item attributes
  380. PyObject* pylistItem = pcilib_convert_register_info_to_pyobject(self->ctx, list[i]);
  381. pcilib_pylist_append(pyList, pylistItem);
  382. }
  383. pcilib_free_register_info(self->ctx, list);
  384. return pyList;
  385. }
  386. PyObject* pcipywrap_get_register_info(pcipywrap *self, const char* reg,const char *bank)
  387. {
  388. pcilib_register_info_t *info = pcilib_get_register_info(self->ctx, bank, reg, PCILIB_LIST_FLAGS_DEFAULT);
  389. if(!info)
  390. {
  391. return NULL;
  392. }
  393. PyObject* py_info = pcilib_convert_register_info_to_pyobject(self->ctx, info[0]);
  394. pcilib_free_register_info(self->ctx, info);
  395. return py_info;
  396. }
  397. PyObject* pcipywrap_get_property_list(pcipywrap *self, const char* branch)
  398. {
  399. pcilib_property_info_t *list = pcilib_get_property_list(self->ctx, branch, PCILIB_LIST_FLAGS_DEFAULT);
  400. PyObject* pyList = PyList_New(0);
  401. for(int i = 0; list[i].path; i++)
  402. {
  403. //serialize item attributes
  404. PyObject* pylistItem = pcilib_convert_property_info_to_pyobject(self->ctx, list[i]);
  405. pcilib_pylist_append(pyList, pylistItem);
  406. }
  407. pcilib_free_property_info(self->ctx, list);
  408. return pyList;
  409. }
  410. PyObject* pcipywrap_read_dma(pcipywrap *self, unsigned char dma, size_t size)
  411. {
  412. int err;
  413. void* buf = NULL;
  414. size_t real_size;
  415. err = pcilib_read_dma(self->ctx, dma, (uintptr_t)NULL, size, buf, &real_size);
  416. if(err)
  417. {
  418. set_python_exception("Failed pcilib_read_dma", err);
  419. return NULL;
  420. }
  421. PyObject* py_buf = PyByteArray_FromStringAndSize((const char*)buf, real_size);
  422. if(buf)
  423. free(buf);
  424. return py_buf;
  425. }
  426. PyObject* pcipywrap_lock_global(pcipywrap *self)
  427. {
  428. int err;
  429. err = pcilib_lock_global(self->ctx);
  430. if(err)
  431. {
  432. set_python_exception("Failed pcilib_lock_global");
  433. return NULL;
  434. }
  435. return PyLong_FromLong((long)1);
  436. }
  437. void pcipywrap_unlock_global(pcipywrap *self)
  438. {
  439. pcilib_unlock_global(self->ctx);
  440. return;
  441. }
  442. PyObject* lock(pcipywrap *self, const char *lock_id, pcilib_lock_flags_t flags)
  443. {
  444. pcilib_lock_t* lock = pcilib_get_lock(self->ctx,
  445. flags,
  446. lock_id);
  447. if(!lock)
  448. {
  449. set_python_exception("Failed pcilib_get_lock");
  450. return NULL;
  451. }
  452. int err = pcilib_lock(lock);
  453. if(err)
  454. {
  455. set_python_exception("Failed pcilib_lock");
  456. return NULL;
  457. }
  458. return PyLong_FromLong((long)1);
  459. }
  460. PyObject* pcipywrap_lock(pcipywrap *self, const char *lock_id)
  461. {
  462. return lock(self, lock_id, PCILIB_LOCK_FLAGS_DEFAULT);
  463. }
  464. PyObject* pcipywrap_lock_persistent(pcipywrap *self, const char *lock_id)
  465. {
  466. return lock(self, lock_id, PCILIB_LOCK_FLAG_PERSISTENT);
  467. }
  468. PyObject* try_lock(pcipywrap *self, const char *lock_id, pcilib_lock_flags_t flags)
  469. {
  470. pcilib_lock_t* lock = pcilib_get_lock(self->ctx,
  471. flags,
  472. lock_id);
  473. if(!lock)
  474. {
  475. set_python_exception("Failed pcilib_get_lock");
  476. return NULL;
  477. }
  478. int err = pcilib_try_lock(lock);
  479. if(err)
  480. {
  481. set_python_exception("Failed pcilib_try_lock");
  482. return NULL;
  483. }
  484. return PyLong_FromLong((long)1);
  485. }
  486. PyObject* pcipywrap_try_lock(pcipywrap *self, const char *lock_id)
  487. {
  488. return try_lock(self, lock_id, PCILIB_LOCK_FLAGS_DEFAULT);
  489. }
  490. PyObject* pcipywrap_try_lock_persistent(pcipywrap *self, const char *lock_id)
  491. {
  492. return try_lock(self, lock_id, PCILIB_LOCK_FLAG_PERSISTENT);
  493. }
  494. PyObject* unlock(pcipywrap *self, const char *lock_id, pcilib_lock_flags_t flags)
  495. {
  496. pcilib_lock_t* lock = pcilib_get_lock(self->ctx,
  497. flags,
  498. lock_id);
  499. if(!lock)
  500. {
  501. set_python_exception("Failed pcilib_get_lock");
  502. return NULL;
  503. }
  504. pcilib_unlock(lock);
  505. return PyLong_FromLong((long)1);
  506. }
  507. PyObject* pcipywrap_unlock(pcipywrap *self, const char *lock_id)
  508. {
  509. return unlock(self, lock_id, PCILIB_LOCK_FLAGS_DEFAULT);
  510. }
  511. PyObject* pcipywrap_unlock_persistent(pcipywrap *self, const char *lock_id)
  512. {
  513. return unlock(self, lock_id, PCILIB_LOCK_FLAG_PERSISTENT);
  514. }