// Device drivers may inherit from this base class, if they wish to receive | // Device drivers may inherit from this base class, if they wish to receive | ||||
// HID input data fully decoded by the USBHIDParser driver | // HID input data fully decoded by the USBHIDParser driver | ||||
class USBHIDInput { | class USBHIDInput { | ||||
public: | |||||
USBHIDInput(); | |||||
private: | private: | ||||
virtual bool claim_collection(Device_t *dev, uint32_t topusage); | 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_data(uint32_t usage, int32_t value); | ||||
virtual void hid_input_end(); | virtual void hid_input_end(); | ||||
virtual void disconnect_collection(Device_t *dev); | virtual void disconnect_collection(Device_t *dev); | ||||
void add_to_list(); | |||||
USBHIDInput *next; | USBHIDInput *next; | ||||
static USBHIDInput *list; | |||||
friend class USBHIDParser; | friend class USBHIDParser; | ||||
}; | }; | ||||
class USBHIDParser : public USBDriver { | class USBHIDParser : public USBDriver { | ||||
public: | public: | ||||
USBHIDParser(USBHost &host) { init(); } | USBHIDParser(USBHost &host) { init(); } | ||||
void driver_ready_for_hid_collection(USBHIDInput *driver); | |||||
static void driver_ready_for_hid_collection(USBHIDInput *driver); | |||||
protected: | protected: | ||||
enum { TOPUSAGE_LIST_LEN = 4 }; | enum { TOPUSAGE_LIST_LEN = 4 }; | ||||
enum { USAGE_LIST_LEN = 12 }; | enum { USAGE_LIST_LEN = 12 }; | ||||
private: | private: | ||||
Pipe_t *in_pipe; | Pipe_t *in_pipe; | ||||
Pipe_t *out_pipe; | Pipe_t *out_pipe; | ||||
static USBHIDInput *available_hid_drivers_list; | |||||
//uint32_t topusage_list[TOPUSAGE_LIST_LEN]; | //uint32_t topusage_list[TOPUSAGE_LIST_LEN]; | ||||
USBHIDInput *topusage_drivers[TOPUSAGE_LIST_LEN]; | USBHIDInput *topusage_drivers[TOPUSAGE_LIST_LEN]; | ||||
uint16_t in_size; | uint16_t in_size; | ||||
Transfer_t mytransfers[7] __attribute__ ((aligned(32))); | 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 { | class MouseController : public USBDriver { | ||||
public: | public: | ||||
MouseController(USBHost &host) { init(); } | MouseController(USBHost &host) { init(); } | ||||
Pipe_t mypipes[2] __attribute__ ((aligned(32))); | Pipe_t mypipes[2] __attribute__ ((aligned(32))); | ||||
Transfer_t mytransfers[4] __attribute__ ((aligned(32))); | Transfer_t mytransfers[4] __attribute__ ((aligned(32))); | ||||
}; | }; | ||||
#endif | |||||
#endif | #endif |
USBHub hub3(myusb); | USBHub hub3(myusb); | ||||
KeyboardController keyboard1(myusb); | KeyboardController keyboard1(myusb); | ||||
KeyboardController keyboard2(myusb); | KeyboardController keyboard2(myusb); | ||||
USBHIDParser hid1(myusb); | |||||
USBHIDParser hid2(myusb); | |||||
USBHIDParser hid3(myusb); | |||||
USBHIDParser hid4(myusb); | |||||
USBHIDParser hid5(myusb); | |||||
MouseController mouse1(myusb); | MouseController mouse1(myusb); | ||||
void setup() | 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() | void loop() | ||||
{ | { | ||||
myusb.Task(); | |||||
myusb.Task(); | |||||
if(mouse1.available()) { | if(mouse1.available()) { | ||||
Serial.print("buttons = "); | 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(", mouseX = "); | ||||
Serial.print(mouse1.getMouseX(),DEC); | |||||
Serial.print(mouse1.getMouseX()); | |||||
Serial.print(", mouseY = "); | 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(); | mouse1.mouseDataClear(); | ||||
} | } | ||||
delay(50); | |||||
} | } | ||||
// This is a list of all the drivers inherited from the USBHIDInput class. | // This is a list of all the drivers inherited from the USBHIDInput class. | ||||
// Unlike the list of USBDriver (managed in enumeration.cpp), drivers stay | // Unlike the list of USBDriver (managed in enumeration.cpp), drivers stay | ||||
// on this list even when they have claimed a top level collection. | // 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 { | } else { | ||||
USBHIDInput *last = list; | |||||
USBHIDInput *last = available_hid_drivers_list; | |||||
while (last->next) last = last->next; | while (last->next) last = last->next; | ||||
last->next = this; | |||||
last->next = driver; | |||||
} | } | ||||
} | } | ||||
// collection is returned, or NULL if no driver wants it. | // collection is returned, or NULL if no driver wants it. | ||||
USBHIDInput * USBHIDParser::find_driver(uint32_t topusage) | USBHIDInput * USBHIDParser::find_driver(uint32_t topusage) | ||||
{ | { | ||||
USBHIDInput *driver = USBHIDInput::list; | |||||
println("find_driver"); | |||||
USBHIDInput *driver = available_hid_drivers_list; | |||||
while (driver) { | while (driver) { | ||||
println(" driver ", (uint32_t)driver, HEX); | |||||
if (driver->claim_collection(device, topusage)) { | if (driver->claim_collection(device, topusage)) { | ||||
return driver; | return driver; | ||||
} | } | ||||
uint32_t topusage = 0; | uint32_t topusage = 0; | ||||
uint8_t topusage_index = 0; | uint8_t topusage_index = 0; | ||||
uint8_t collection_level = 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 usage_count = 0; | ||||
uint8_t report_id = 0; | uint8_t report_id = 0; | ||||
uint16_t report_size = 0; | uint16_t report_size = 0; | ||||
p += 2; | p += 2; | ||||
break; | break; | ||||
case 2: val = p[1] | (p[2] << 8); | case 2: val = p[1] | (p[2] << 8); | ||||
println("val16 = ", val, HEX); | |||||
p += 3; | p += 3; | ||||
break; | break; | ||||
case 3: val = p[1] | (p[2] << 8) | (p[3] << 16) | (p[4] << 24); | case 3: val = p[1] | (p[2] << 8) | (p[3] << 16) | (p[4] << 24); |
#include <Arduino.h> | #include <Arduino.h> | ||||
#include "USBHost_t36.h" // Read this header first for key info | #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() | void MouseController::init() | ||||
{ | { | ||||
contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t)); | contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t)); | ||||
println("descriptors[23] = ",descriptors[23]); | println("descriptors[23] = ",descriptors[23]); | ||||
println("packet size(mouse) = ", size); | println("packet size(mouse) = ", size); | ||||
// packey size seems to be 20 for (wireless type 2) or 6 bytes for wired | // 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 | if(packetSize == 6) packetSize = 8; // Minimum packet size needed is 8 | ||||
uint32_t interval = descriptors[24]; | uint32_t interval = descriptors[24]; | ||||
println("polling interval = ", interval); | println("polling interval = ", interval); | ||||
// | // | ||||
// Wireless Logitech mouse reports have byte 0 set to 0x02 indicating a type 2 report. | // 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 | // 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. | // report byte. | ||||
if(packetSize == 20) { | if(packetSize == 20) { | ||||
mouseY = 0; | mouseY = 0; | ||||
wheel = 0; | wheel = 0; | ||||
} | } | ||||
#endif | |||||