How to add an 'extra' HID Mouse ?

Hi guys,

I'm playing around with a Leonardo and have the hid mouse example working but I would like to add an extra mouse so I can interface two trackballs as hid mouse controls.

Is this doable ? - If it is... then how ?

Would I have to give the mice different descriptors or would I get away with two of the same ?

I'm kind of guessing that I have to make a copy of the mouse library (and header ?) and rename them along with editing parts of the code.... perhaps call the 2nd one exMouse ? and then refer to it as such - Or am I missing the point ?

https://github.com/arduino-libraries/Mouse/blob/master/src/Mouse.h

https://github.com/arduino-libraries/Mouse/blob/master/src/Mouse.cpp

Any help or advise would be appreciated please, I've tried searching but struggling to find anything remotely similar or useful. I'm quite used to hacking together examples and building upon them but this is a little different.

Thanks, Colin

I’ve had a go at the libraries and tackled various errors and I now to my surprise get a successful compile with both Mouse and exMouse together in the example, however I’ve left my Leonardo in work, so will have more of an idea tomorrow !

Basically anything with Mouse I’ve renamed to exMouse and the ‘limit_xy’ has also been renamed to ‘exlimit_xy’ !!

I still feel I’m missing something obvious like making a slightly different hidReportDescriptor for the 2nd (exMouse) or I’m completely barking :frowning:

I enclose my hacked up library and header in line below. I’m prepared to be shot down in flames !!

Any advice appreciated,
Thanks, Colin

#####################

exMouse.cpp contains…

/*
exMouse.cpp

Copyright (c) 2015, Arduino LLC
Original code (pre-library): Copyright (c) 2011, Peter Barrett

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include “exMouse.h”

#if defined(_USING_HID)

static const uint8_t _hidReportDescriptor PROGMEM = {

// Mouse
0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 54
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x85, 0x01, // REPORT_ID (1)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x05, // REPORT_SIZE (5)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x09, 0x38, // USAGE (Wheel)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x03, // REPORT_COUNT (3)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
};

//================================================================================
//================================================================================
// Mouse

/* This function is for limiting the input value for x and y

  • axis to -127 <= x/y <= 127 since this is the allowed value
  • range for a USB HID device.
    */
    signed char exlimit_xy(int const xy)
    {
    if (xy < -127) return -127;
    else if(xy > 127) return 127;
    else return xy;
    }

exMouse_::exMouse_(void) : _buttons(0)
{
static HIDSubDescriptor node(_hidReportDescriptor, sizeof(_hidReportDescriptor));
HID().AppendDescriptor(&node);
}

void exMouse_::begin(void)
{
}

void exMouse_::end(void)
{
}

void exMouse_::click(uint8_t b)
{
_buttons = b;
move(0,0,0);
_buttons = 0;
move(0,0,0);
}

void exMouse_::move(int x, int y, signed char wheel)
{
uint8_t m[4];
m[0] = _buttons;
m[1] = exlimit_xy(x);
m[2] = exlimit_xy(y);
m[3] = wheel;
HID().SendReport(1,m,4);
}

void exMouse_::buttons(uint8_t b)
{
if (b != _buttons)
{
_buttons = b;
move(0,0,0);
}
}

void exMouse_::press(uint8_t b)
{
buttons(_buttons | b);
}

void exMouse_::release(uint8_t b)
{
buttons(_buttons & ~b);
}

bool exMouse_::isPressed(uint8_t b)
{
if ((b & _buttons) > 0)
return true;
return false;
}

exMouse_ exMouse;

#endif

##############################################################
##############################################################

and exMouse.h contains…

/*
exMouse.h

Copyright (c) 2015, Arduino LLC
Original code (pre-library): Copyright (c) 2011, Peter Barrett

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifndef exMOUSE_h
#define exMOUSE_h

#include “HID.h”

#if !defined(_USING_HID)

#warning “Using legacy HID core (non pluggable)”

#else

//================================================================================
//================================================================================
// Mouse

#define exMOUSE_LEFT 1
#define exMOUSE_RIGHT 2
#define exMOUSE_MIDDLE 4
#define exMOUSE_ALL (exMOUSE_LEFT | exMOUSE_RIGHT | exMOUSE_MIDDLE)

class exMouse_
{
private:
uint8_t buttons;
void buttons(uint8_t b);
public:
exMouse
(void);
void begin(void);
void end(void);
void click(uint8_t b = exMOUSE_LEFT);
void move(int x, int y, signed char wheel = 0);
void press(uint8_t b = exMOUSE_LEFT); // press LEFT by default
void release(uint8_t b = exMOUSE_LEFT); // release LEFT by default
bool isPressed(uint8_t b = exMOUSE_LEFT); // check LEFT by default
};
extern exMouse_ exMouse;

#endif
#endif

Ok, that didn't quite work and I got an exclamation mark on usb input device under the HID section in Windows device manager. The modified library seemed to work on its own so I had not broken anything.

I changed the Report_Id value in the exMouse and now have two mice showing up which appear to be working :-)

0x85, 0x02, // REPORT_ID (1) - This was 1

Next up.... time to add interupt driven encoders , some key strokes and an analogue joystick into the mix :-)