// vrpn_dreamcheeky.C: VRPN driver for Dream Cheeky USB roll-up drum kit #include <string.h> // for memset #include "vrpn_DreamCheeky.h" class VRPN_API vrpn_Connection; VRPN_SUPPRESS_EMPTY_OBJECT_WARNING() #if defined(VRPN_USE_HID) // USB vendor and product IDs for the models we support static const vrpn_uint16 DREAMCHEEKY_VENDOR = 6465; static const vrpn_uint16 USB_ROLL_UP_DRUM_KIT = 32801; vrpn_DreamCheeky::vrpn_DreamCheeky(vrpn_HidAcceptor *filter, const char *name, vrpn_Connection *c) : vrpn_HidInterface(filter) , vrpn_BaseClass(name, c) , _filter(filter) { vrpn_gettimeofday(&_timestamp, NULL); } vrpn_DreamCheeky::~vrpn_DreamCheeky() { delete _filter; } void vrpn_DreamCheeky::on_data_received(size_t bytes, vrpn_uint8 *buffer) { decodePacket(bytes, buffer); } vrpn_DreamCheeky_Drum_Kit::vrpn_DreamCheeky_Drum_Kit(const char *name, vrpn_Connection *c, bool debounce) : vrpn_DreamCheeky(_filter = new vrpn_HidProductAcceptor(DREAMCHEEKY_VENDOR, USB_ROLL_UP_DRUM_KIT), name, c) , vrpn_Button_Filter(name, c) , d_debounce(debounce) { vrpn_Button::num_buttons = 6; // Initialize the state of all the buttons memset(buttons, 0, sizeof(buttons)); memset(lastbuttons, 0, sizeof(lastbuttons)); } void vrpn_DreamCheeky_Drum_Kit::mainloop() { update(); server_mainloop(); vrpn_gettimeofday(&_timestamp, NULL); report_changes(); vrpn_Button::server_mainloop(); } void vrpn_DreamCheeky_Drum_Kit::report(void) { vrpn_Button::timestamp = _timestamp; vrpn_Button::report_changes(); } void vrpn_DreamCheeky_Drum_Kit::report_changes(void) { vrpn_Button::timestamp = _timestamp; vrpn_Button::report_changes(); } void vrpn_DreamCheeky_Drum_Kit::decodePacket(size_t bytes, vrpn_uint8 *buffer) { // The reports are each 8 bytes long. Since there is only one type of // report for this device, the report type is not included (stripped by // the HIDAPI driver). The bytes are 8 identical reports. // There is one byte per report, and it holds a binary encoding of // the buttons. Button 0 is in the LSB, and the others proceed up // the bit chain. Parse each report and then send any changes on. // need to send between each report so we don't miss a button press/release // all in one packet. size_t i, r; // Truncate the count to an even number of 8 bytes. This will // throw out any partial reports (which is not necessarily what // we want, because this will start us off parsing at the wrong // place if the rest of the report comes next, but it is not // clear how to handle that cleanly). bytes -= (bytes % 8); // Decode all full reports, each of which is 8 bytes long. for (i = 0; i < (bytes / 8); i++) { // If we're debouncing the buttons, then we set the button // to "pressed" if it has 4 or more pressed events in the // set of 8 and to "released" if it has less than 4. if (d_debounce) { int btn; for (btn = 0; btn < vrpn_Button::num_buttons; btn++) { unsigned count = 0; vrpn_uint8 mask = 1 << btn; for (r = 0; r < 8; r++) { // Skip the all-zeroes byte vrpn_uint8 *report = buffer + 9*i + r; count += ((*report & mask) != 0); } buttons[btn] = (count >= 4); vrpn_gettimeofday(&_timestamp, NULL); report_changes(); } // If we're not debouncing, then we report each button event // independently. }else { for (r = 0; r < 8; r++) { // Skip the all-zeroes byte vrpn_uint8 *report = buffer + 9*i + r; int btn; for (btn = 0; btn < vrpn_Button::num_buttons; btn++) { vrpn_uint8 mask = 1 << btn; buttons[btn] = ((*report & mask) != 0); } vrpn_gettimeofday(&_timestamp, NULL); report_changes(); } } } } #endif