From f58ed079a65502598de1ac9abf283dbf00cf30d1 Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Sun, 10 Sep 2017 03:48:10 -0700 Subject: [PATCH] Mouse using HID parser --- USBHost_t36.h | 40 ++++++++++++++++--- examples/Mouse/Mouse.ino | 31 +++++++++------ hid.cpp | 21 +++++----- mouse.cpp | 84 ++++++++++++++++++++++++++++++++++++++-- 4 files changed, 146 insertions(+), 30 deletions(-) diff --git a/USBHost_t36.h b/USBHost_t36.h index bb8365e..64c3430 100644 --- a/USBHost_t36.h +++ b/USBHost_t36.h @@ -402,16 +402,14 @@ private: // Device drivers may inherit from this base class, if they wish to receive // HID input data fully decoded by the USBHIDParser driver class USBHIDInput { -public: - USBHIDInput(); private: virtual bool claim_collection(Device_t *dev, uint32_t topusage); - virtual void hid_input_begin(uint32_t topusage, uint32_t type, int min, int max); + virtual void hid_input_begin(uint32_t topusage, uint32_t type, int lgmin, int lgmax); virtual void hid_input_data(uint32_t usage, int32_t value); virtual void hid_input_end(); virtual void disconnect_collection(Device_t *dev); + void add_to_list(); USBHIDInput *next; - static USBHIDInput *list; friend class USBHIDParser; }; @@ -498,7 +496,7 @@ private: class USBHIDParser : public USBDriver { public: USBHIDParser(USBHost &host) { init(); } - void driver_ready_for_hid_collection(USBHIDInput *driver); + static void driver_ready_for_hid_collection(USBHIDInput *driver); protected: enum { TOPUSAGE_LIST_LEN = 4 }; enum { USAGE_LIST_LEN = 12 }; @@ -517,6 +515,7 @@ protected: private: Pipe_t *in_pipe; Pipe_t *out_pipe; + static USBHIDInput *available_hid_drivers_list; //uint32_t topusage_list[TOPUSAGE_LIST_LEN]; USBHIDInput *topusage_drivers[TOPUSAGE_LIST_LEN]; uint16_t in_size; @@ -711,6 +710,35 @@ private: Transfer_t mytransfers[7] __attribute__ ((aligned(32))); }; +#if 1 +class MouseController : public USBHIDInput { +public: + MouseController(USBHost &host) { USBHIDParser::driver_ready_for_hid_collection(this); } + bool available() { return mouseEvent; } + void mouseDataClear(); + uint8_t getButtons() { return buttons; } + int getMouseX() { return mouseX; } + int getMouseY() { return mouseY; } + int getWheel() { return wheel; } + int getWheelH() { return wheelH; } +protected: + virtual bool claim_collection(Device_t *dev, uint32_t topusage); + virtual void hid_input_begin(uint32_t topusage, uint32_t type, int lgmin, int lgmax); + virtual void hid_input_data(uint32_t usage, int32_t value); + virtual void hid_input_end(); + virtual void disconnect_collection(Device_t *dev); +private: + Device_t *mydevice = NULL; + uint8_t collections_claimed = 0; + volatile bool mouseEvent = false; + uint8_t buttons = 0; + int mouseX = 0; + int mouseY = 0; + int wheel = 0; + int wheelH = 0; +}; + +#else class MouseController : public USBDriver { public: MouseController(USBHost &host) { init(); } @@ -743,5 +771,7 @@ private: Pipe_t mypipes[2] __attribute__ ((aligned(32))); Transfer_t mytransfers[4] __attribute__ ((aligned(32))); }; +#endif + #endif diff --git a/examples/Mouse/Mouse.ino b/examples/Mouse/Mouse.ino index f4361b3..4176946 100644 --- a/examples/Mouse/Mouse.ino +++ b/examples/Mouse/Mouse.ino @@ -10,33 +10,40 @@ USBHub hub2(myusb); USBHub hub3(myusb); KeyboardController keyboard1(myusb); KeyboardController keyboard2(myusb); +USBHIDParser hid1(myusb); +USBHIDParser hid2(myusb); +USBHIDParser hid3(myusb); +USBHIDParser hid4(myusb); +USBHIDParser hid5(myusb); MouseController mouse1(myusb); void setup() { - while (!Serial) ; // wait for Arduino Serial Monitor - Serial.println("USB Host Testing"); - myusb.begin(); - keyboard1.attachPress(OnPress); - keyboard2.attachPress(OnPress); + while (!Serial) ; // wait for Arduino Serial Monitor + Serial.println("USB Host Testing"); + myusb.begin(); + keyboard1.attachPress(OnPress); + keyboard2.attachPress(OnPress); } void loop() { - myusb.Task(); + myusb.Task(); if(mouse1.available()) { Serial.print("buttons = "); - Serial.print(mouse1.getButtons(),DEC); - Serial.print(", wheel = "); - Serial.print(mouse1.getWheel(),DEC); + Serial.print(mouse1.getButtons()); Serial.print(", mouseX = "); - Serial.print(mouse1.getMouseX(),DEC); + Serial.print(mouse1.getMouseX()); Serial.print(", mouseY = "); - Serial.println(mouse1.getMouseY(),DEC); + Serial.print(mouse1.getMouseY()); + Serial.print(", wheel = "); + Serial.print(mouse1.getWheel()); + Serial.print(", wheelH = "); + Serial.print(mouse1.getWheelH()); + Serial.println(); mouse1.mouseDataClear(); } - delay(50); } diff --git a/hid.cpp b/hid.cpp index 448dfdd..09ec1e1 100644 --- a/hid.cpp +++ b/hid.cpp @@ -288,17 +288,17 @@ void USBHIDParser::parse() // This is a list of all the drivers inherited from the USBHIDInput class. // Unlike the list of USBDriver (managed in enumeration.cpp), drivers stay // on this list even when they have claimed a top level collection. -USBHIDInput * USBHIDInput::list = NULL; +USBHIDInput * USBHIDParser::available_hid_drivers_list = NULL; -USBHIDInput::USBHIDInput() +void USBHIDParser::driver_ready_for_hid_collection(USBHIDInput *driver) { - next = NULL; - if (list == NULL) { - list = this; + driver->next = NULL; + if (available_hid_drivers_list == NULL) { + available_hid_drivers_list = driver; } else { - USBHIDInput *last = list; + USBHIDInput *last = available_hid_drivers_list; while (last->next) last = last->next; - last->next = this; + last->next = driver; } } @@ -307,8 +307,10 @@ USBHIDInput::USBHIDInput() // collection is returned, or NULL if no driver wants it. USBHIDInput * USBHIDParser::find_driver(uint32_t topusage) { - USBHIDInput *driver = USBHIDInput::list; + println("find_driver"); + USBHIDInput *driver = available_hid_drivers_list; while (driver) { + println(" driver ", (uint32_t)driver, HEX); if (driver->claim_collection(device, topusage)) { return driver; } @@ -367,7 +369,7 @@ void USBHIDParser::parse(uint16_t type_and_report_id, const uint8_t *data, uint3 uint32_t topusage = 0; uint8_t topusage_index = 0; uint8_t collection_level = 0; - uint8_t usage[USAGE_LIST_LEN] = {0, 0}; + uint16_t usage[USAGE_LIST_LEN] = {0, 0}; uint8_t usage_count = 0; uint8_t report_id = 0; uint16_t report_size = 0; @@ -392,6 +394,7 @@ void USBHIDParser::parse(uint16_t type_and_report_id, const uint8_t *data, uint3 p += 2; break; case 2: val = p[1] | (p[2] << 8); + println("val16 = ", val, HEX); p += 3; break; case 3: val = p[1] | (p[2] << 8) | (p[3] << 16) | (p[4] << 24); diff --git a/mouse.cpp b/mouse.cpp index b84c52a..79ed45c 100644 --- a/mouse.cpp +++ b/mouse.cpp @@ -24,6 +24,81 @@ #include #include "USBHost_t36.h" // Read this header first for key info +#if 1 + + +bool MouseController::claim_collection(Device_t *dev, uint32_t topusage) +{ + // only claim Desktop/Mouse + if (topusage != 0x10002) return false; + // only claim from one physical device + if (mydevice != NULL && dev != mydevice) return false; + mydevice = dev; + collections_claimed++; + return true; +} + +void MouseController::disconnect_collection(Device_t *dev) +{ + if (--collections_claimed == 0) { + mydevice = NULL; + } +} + +void MouseController::hid_input_begin(uint32_t topusage, uint32_t type, int lgmin, int lgmax) +{ + // TODO: check if absolute coordinates +} + +void MouseController::hid_input_data(uint32_t usage, int32_t value) +{ + //Serial.printf("Mouse: usage=%X, value=%d\n", usage, value); + uint32_t usage_page = usage >> 16; + usage &= 0xFFFF; + if (usage_page == 9 && usage >= 1 && usage <= 8) { + if (value == 0) { + buttons &= ~(1 << (usage -1)); + } else { + buttons |= (1 << (usage -1)); + } + } else if (usage_page == 1) { + switch (usage) { + case 0x30: + mouseX = value; + break; + case 0x31: + mouseY = value; + break; + case 0x32: // Apple uses this for horizontal scroll + wheelH = value; + break; + case 0x38: + wheel = value; + break; + } + } else if (usage_page == 12) { + if (usage == 0x238) { // Microsoft uses this for horizontal scroll + wheelH = value; + } + } +} + +void MouseController::hid_input_end() +{ + mouseEvent = true; +} + +void MouseController::mouseDataClear() { + mouseEvent = false; + buttons = 0; + mouseX = 0; + mouseY = 0; + wheel = 0; + wheelH = 0; +} + + +#else void MouseController::init() { contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t)); @@ -59,8 +134,8 @@ bool MouseController::claim(Device_t *dev, int type, const uint8_t *descriptors, println("descriptors[23] = ",descriptors[23]); println("packet size(mouse) = ", size); // packey size seems to be 20 for (wireless type 2) or 6 bytes for wired - packetSize = size; - if ((size != 20) && (size != 6)) return false; + packetSize = size; + if ((size != 20) && (size != 6)) return false; if(packetSize == 6) packetSize = 8; // Minimum packet size needed is 8 uint32_t interval = descriptors[24]; println("polling interval = ", interval); @@ -129,7 +204,7 @@ void MouseController::new_data(const Transfer_t *transfer) // // Wireless Logitech mouse reports have byte 0 set to 0x02 indicating a type 2 report. // Not sure what this really means yet but all bytes of the report packet are shifted - // ahead by one byte and there is a single byte that is always zero after the button + // ahead by one byte and there is a single byte that is always zero after the button // report byte. if(packetSize == 20) { @@ -155,4 +230,5 @@ void MouseController::mouseDataClear() { mouseY = 0; wheel = 0; } - +#endif +