(in-package #:chatikbot) (defparameter +udmx-vendor-id+ #x16C0 "VOTI") (defparameter +udmx-product-id+ #x05DC "Obdev's free shared PID") (defparameter +udmx-req-set-single-channel+ 1 "usb request for cmd_SetSingleChannel: bmRequestType: ignored by device, should be USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT bRequest: cmd_SetSingleChannel wValue: value of channel to set [0 .. 255] wIndex: channel index to set [0 .. 511] wLength: ignored") (defparameter +udmx-req-set-channel-range+ 2 "usb request for cmd_SetChannelRange: bmRequestType: ignored by device, should be USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT bRequest: cmd_SetChannelRange wValue: number of channels to set [1 .. 512-wIndex] wIndex: index of first channel to set [0 .. 511] wLength: length of data, must be >= wValue") (defparameter +udmx-req-start-bootloader+ #xf8 "Start Bootloader for Software updates") (defparameter +udmx-err-bad-channel+ 1) (defparameter +udmx-err-bad-value+ 2) (defparameter +udmx-timeout+ 5000) (defparameter +udmx-manufacturer+ "www.anyma.ch") (defparameter +udmx-product+ "uDMX") (defun udmx-find-device () (loop for device in (cl-libusb:usb-get-devices-by-ids +udmx-vendor-id+ +udmx-product-id+) do (unwind-protect (progn (cl-libusb:usb-open device) (when (and (equal (cl-libusb:usb-get-string device :manufacturer) +udmx-manufacturer+) (equal (cl-libusb:usb-get-string device :product) +udmx-product+)) (return device))) (when (cl-libusb:usb-open-p device) (cl-libusb:usb-close device))))) (defparameter +udmx-request-type+ (logior (cffi:foreign-enum-value 'libusb-ffi::type :vendor) (cffi:foreign-enum-value 'libusb-ffi::recip :device) (cffi:foreign-enum-value 'libusb-ffi::endpoint :out))) (defun %udmx-set-single-channel (device channel value) (declare (type (integer 0 511) channel) (type (integer 0 255) value)) (static-vectors:with-static-vector (buffer 1) (cl-libusb:usb-control-msg device +udmx-request-type+ +udmx-req-set-single-channel+ value channel buffer +udmx-timeout+))) (defun %udmx-set-channel-range (device first-channel values) (declare (type (integer 0 511) first-channel)) (static-vectors:with-static-vector (buffer (length values) :initial-contents values) (cl-libusb:usb-control-msg device +udmx-request-type+ +udmx-req-set-channel-range+ (length buffer) first-channel buffer +udmx-timeout+))) (defun udmx-set-channel (device channel value &rest more-values) (unless (cl-libusb:usb-open-p device) (cl-libusb:usb-open device)) (loop for retries from 0 to 100 do (ignore-errors (return (values (if (consp more-values) (%udmx-set-channel-range device channel (cons value more-values)) (%udmx-set-single-channel device channel value)) retries))) finally (return (values nil retries))))