Browse Source

Mouse using HID parser

main
PaulStoffregen 7 years ago
parent
commit
f58ed079a6
4 changed files with 146 additions and 30 deletions
  1. +35
    -5
      USBHost_t36.h
  2. +19
    -12
      examples/Mouse/Mouse.ino
  3. +12
    -9
      hid.cpp
  4. +80
    -4
      mouse.cpp

+ 35
- 5
USBHost_t36.h View File

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

+ 19
- 12
examples/Mouse/Mouse.ino View File

@@ -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);
}



+ 12
- 9
hid.cpp View File

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

+ 80
- 4
mouse.cpp View File

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


Loading…
Cancel
Save