@@ -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 | |||