udmx.lisp 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. (in-package #:chatikbot)
  2. (defparameter +udmx-vendor-id+ #x16C0 "VOTI")
  3. (defparameter +udmx-product-id+ #x05DC "Obdev's free shared PID")
  4. (defparameter +udmx-req-set-single-channel+ 1 "usb request for cmd_SetSingleChannel:
  5. bmRequestType: ignored by device, should be USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT
  6. bRequest: cmd_SetSingleChannel
  7. wValue: value of channel to set [0 .. 255]
  8. wIndex: channel index to set [0 .. 511]
  9. wLength: ignored")
  10. (defparameter +udmx-req-set-channel-range+ 2 "usb request for cmd_SetChannelRange:
  11. bmRequestType: ignored by device, should be USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT
  12. bRequest: cmd_SetChannelRange
  13. wValue: number of channels to set [1 .. 512-wIndex]
  14. wIndex: index of first channel to set [0 .. 511]
  15. wLength: length of data, must be >= wValue")
  16. (defparameter +udmx-req-start-bootloader+ #xf8 "Start Bootloader for Software updates")
  17. (defparameter +udmx-err-bad-channel+ 1)
  18. (defparameter +udmx-err-bad-value+ 2)
  19. (defparameter +udmx-timeout+ 5000)
  20. (defparameter +udmx-manufacturer+ "www.anyma.ch")
  21. (defparameter +udmx-product+ "uDMX")
  22. (defun udmx-find-device ()
  23. (loop for device in (cl-libusb:usb-get-devices-by-ids +udmx-vendor-id+ +udmx-product-id+)
  24. do (unwind-protect
  25. (progn
  26. (cl-libusb:usb-open device)
  27. (when (and (equal (cl-libusb:usb-get-string device :manufacturer) +udmx-manufacturer+)
  28. (equal (cl-libusb:usb-get-string device :product) +udmx-product+))
  29. (return device)))
  30. (when (cl-libusb:usb-open-p device)
  31. (cl-libusb:usb-close device)))))
  32. (defparameter +udmx-request-type+
  33. (logior (cffi:foreign-enum-value 'libusb-ffi::type :vendor)
  34. (cffi:foreign-enum-value 'libusb-ffi::recip :device)
  35. (cffi:foreign-enum-value 'libusb-ffi::endpoint :out)))
  36. (defun %udmx-set-single-channel (device channel value)
  37. (declare (type (integer 0 511) channel)
  38. (type (integer 0 255) value))
  39. (static-vectors:with-static-vector (buffer 1)
  40. (cl-libusb:usb-control-msg device +udmx-request-type+ +udmx-req-set-single-channel+
  41. value channel buffer +udmx-timeout+)))
  42. (defun %udmx-set-channel-range (device first-channel values)
  43. (declare (type (integer 0 511) first-channel))
  44. (static-vectors:with-static-vector (buffer (length values) :initial-contents values)
  45. (cl-libusb:usb-control-msg device +udmx-request-type+ +udmx-req-set-channel-range+
  46. (length buffer) first-channel buffer +udmx-timeout+)))
  47. (defun udmx-set-channel (device channel value &rest more-values)
  48. (unless (cl-libusb:usb-open-p device)
  49. (cl-libusb:usb-open device))
  50. (loop for retries from 0 to 100
  51. do (ignore-errors
  52. (return (values (if (consp more-values)
  53. (%udmx-set-channel-range device channel (cons value more-values))
  54. (%udmx-set-single-channel device channel value))
  55. retries)))
  56. finally (return (values nil retries))))