| @@ -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 | |||
| @@ -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); | |||
| } | |||
| @@ -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); | |||
| @@ -24,6 +24,81 @@ | |||
| #include <Arduino.h> | |||
| #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 | |||