Go Down

Topic: USB Absolute Mouse Mode (Read 20411 times) previous topic - next topic

Jardal

Absolute mouse mode for Digispark AtTiny85, range -127/+127

Path to file (on Linux):
.arduino15/packages/digistump/hardware/avr/1.6.7/libraries/DigisparkMouse/DigiMouse.h

(comments are gone due size limitations here)
Code: [Select]

#ifndef __DigiMouse_h__
#define __DigiMouse_h__

#define REPORT_SIZE 4

#include <Arduino.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/delay.h>
#include <string.h>
#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/wdt.h>

#include "usbdrv.h"
//#include "devdesc.h"
#include "oddebug.h"
#include "usbconfig.h"

static const uchar *rt_usbHidReportDescriptor = NULL;
static uchar rt_usbHidReportDescriptorSize = 0;
static const uchar *rt_usbDeviceDescriptor = NULL;
static uchar rt_usbDeviceDescriptorSize = 0;

#define MOUSEBTN_LEFT_MASK 0x01
#define MOUSEBTN_RIGHT_MASK 0x02
#define MOUSEBTN_MIDDLE_MASK 0x04

typedef uint8_t byte;

static unsigned char last_built_report[REPORT_SIZE];
static unsigned char last_sent_report[REPORT_SIZE];

uchar reportBuffer[REPORT_SIZE];

#define DIGIMOUSE_DEFAULT_REPORT_INTERVAL 20
static unsigned char must_report = 0;
static unsigned char idle_rate = DIGIMOUSE_DEFAULT_REPORT_INTERVAL / 4; // in units of 4ms
static unsigned long last_report_time = 0;


//#define ABSOLUTE_MOUSE_MODE


char usb_hasCommed = 0;

const PROGMEM unsigned char mouse_usbHidReportDescriptor[] = { /* USB report descriptor */
0x05, 0x01,
0x09, 0x02,
0xa1, 0x01,
0x09, 0x01,
0xa1, 0x00,
0x05, 0x09,
0x19, 0x01,
0x29, 0x03,
0x15, 0x00,
0x25, 0x01,
0x95, 0x03,
0x75, 0x01,
0x81, 0x02,
0x95, 0x01,
0x75, 0x05,
0x81, 0x01,
0x05, 0x01,
0x09, 0x30,
0x09, 0x31,

#ifdef ABSOLUTE_MOUSE_MODE
0x15, 0x81,
0x25, 0x7f,
0x75, 0x08,
0x95, 0x03,
0x81, 0x02,
#else
0x15, 0x81,
0x25, 0x7f,
0x75, 0x08,
0x95, 0x02,
0x81, 0x06,
#endif

0x09, 0x38,
0x95, 0x01,
0x81, 0x06,

0xc0,
0xc0
};


#define USBDESCR_DEVICE 1

const unsigned char usbDescrDevice[] PROGMEM = { /* USB device descriptor */
18, /* sizeof(usbDescrDevice): length of descriptor in bytes */
USBDESCR_DEVICE, /* descriptor type */
0x01, 0x01, /* USB version supported */
USB_CFG_DEVICE_CLASS,
USB_CFG_DEVICE_SUBCLASS,
0, /* protocol */
8, /* max packet size */
USB_CFG_VENDOR_ID, /* 2 bytes */
USB_CFG_DEVICE_ID, /* 2 bytes */
USB_CFG_DEVICE_VERSION, /* 2 bytes */
#if USB_CFG_VENDOR_NAME_LEN
1,
#els
0,
#endif
#if USB_CFG_DEVICE_NAME_LEN
2,
#els
0,
#endif
#if USB_CFG_SERIAL_NUMBER_LENGTH
3,
#els
0,
#end
1,
};


void buildReport(unsigned char *reportBuf) {
if (reportBuf != NULL) {
memcpy(reportBuf, last_built_report, REPORT_SIZE);
}

memcpy(last_sent_report, last_built_report, REPORT_SIZE);
}

void clearMove() {
// because we send deltas in movement, so when we send them, we clear them
last_built_report[1] = 0;
last_built_report[2] = 0;
last_built_report[3] = 0;
last_sent_report[1] = 0;
last_sent_report[2] = 0;
last_sent_report[3] = 0;
}






class DigiMouseDevice {
public:
DigiMouseDevice () {

rt_usbHidReportDescriptor = mouse_usbHidReportDescriptor;
rt_usbHidReportDescriptorSize = sizeof(mouse_usbHidReportDescriptor);
rt_usbDeviceDescriptor = usbDescrDevice;
rt_usbDeviceDescriptorSize = sizeof(usbDescrDevice);
}

void begin() {
cli();
usbDeviceDisconnect();
_delay_ms(200);
usbDeviceConnect();

usbInit();

sei();
last_report_time = millis();
}



void refresh() {
update();
}

void poll() {
update();
}


void update() {
usbPoll();

unsigned long time_since_last_report = millis() - last_report_time;
if (time_since_last_report >= (idle_rate * 4 /* in units of 4ms - usb spec stuff */)) {
last_report_time += idle_rate * 4;
must_report = 1;
}

if (memcmp(last_built_report, last_sent_report, REPORT_SIZE)) {
must_report = 1;
}

if (must_report) {
if (usbInterruptIsReady()) {
must_report = 0;
buildReport(reportBuffer); // put data into reportBuffer
clearMove(); // clear deltas
usbSetInterrupt(reportBuffer, REPORT_SIZE);
}
}
}

void delay(long milli) {
unsigned long last = millis();
while (milli > 0) {
unsigned long now = millis();
milli -= now - last;
last = now;
update();
}
}

void moveX(char deltaX) {
if (deltaX == -128) deltaX = -127;
last_built_report[1] = *(reinterpret_cast<unsigned char *>(&deltaX));
}

void moveY(char deltaY) {
if (deltaY == -128) deltaY = -127;
last_built_report[2] = *(reinterpret_cast<unsigned char *>(&deltaY));
}

void scroll(char deltaS) {
if (deltaS == -128) deltaS = -127;
last_built_report[3] = *(reinterpret_cast<unsigned char *>(&deltaS));
}

void move(char deltaX, char deltaY, char deltaS) {
if (deltaX == -128) deltaX = -127;
if (deltaY == -128) deltaY = -127;
if (deltaS == -128) deltaS = -127;
last_built_report[1] = *(reinterpret_cast<unsigned char *>(&deltaX));
last_built_report[2] = *(reinterpret_cast<unsigned char *>(&deltaY));
last_built_report[3] = *(reinterpret_cast<unsigned char *>(&deltaS));
}

void move(char deltaX, char deltaY, char deltaS, char buttons) {
if (deltaX == -128) deltaX = -127;
if (deltaY == -128) deltaY = -127;
if (deltaS == -128) deltaS = -127;
last_built_report[0] = buttons;
last_built_report[1] = *(reinterpret_cast<unsigned char *>(&deltaX));
last_built_report[2] = *(reinterpret_cast<unsigned char *>(&deltaY));
last_built_report[3] = *(reinterpret_cast<unsigned char *>(&deltaS));
}

void rightClick(){
last_built_report[0] = MOUSEBTN_RIGHT_MASK;
}

void leftClick(){
last_built_report[0] = MOUSEBTN_RIGHT_MASK;
}

void middleClick(){
last_built_report[0] = MOUSEBTN_RIGHT_MASK;
}

void setButtons(unsigned char buttons) {
last_built_report[0] = buttons;
}

void setValues(unsigned char values[]) {
memcpy(last_built_report, values, REPORT_SIZE);
}

//private: TODO: Make friend?
// what does this even mean? -- Bluebie
};

// create the global singleton DigiMouse
DigiMouseDevice DigiMouse = DigiMouseDevice();


#ifdef __cplusplus
extern "C"{
#endif
// USB_PUBLIC uchar usbFunctionSetup

uchar usbFunctionSetup(uchar data[8]) {
usbRequest_t *rq = (usbRequest_t *)data;

usbMsgPtr = reportBuffer;

if ((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) { /* class request type */
return REPORT_SIZE;
} else if (rq->bRequest == USBRQ_HID_GET_IDLE) {
usbMsgPtr = &idle_rate;
return 1;
} else if (rq->bRequest == USBRQ_HID_SET_IDLE) {
idle_rate = rq->wValue.bytes[1];
}
} else {
}
return 0;
}

uchar usbFunctionDescriptor(struct usbRequest *rq) {
if ((rq->bmRequestType & USBRQ_TYPE_MASK) != USBRQ_TYPE_STANDARD) {
return 0;
}

if (rq->bRequest == USBRQ_GET_DESCRIPTOR) {
switch (rq->wValue.bytes[1]) {
case USBDESCR_DEVICE:
usbMsgPtr = rt_usbDeviceDescriptor;
return rt_usbDeviceDescriptorSize;
break;

case USBDESCR_HID_REPORT:
usbMsgPtr = rt_usbHidReportDescriptor;
return rt_usbHidReportDescriptorSize;
break;
}
}

return 0;
}

#ifdef __cplusplus
} // extern "C"
#endif


#endif // __DigiMouse_h__

saibersingh

Hey there,
When i try to upload my code it shows an error...
Arduino: 1.8.1 (Mac OS X), Board: "Arduino Leonardo"

/private/var/folders/hn/flfx2mnd237974bkycxx4cyr0000gn/T/AppTranslocation/F9EEF18B-0923-4A05-BE90-F6FC217A14A7/d/Arduino.app/Contents/Java/hardware/arduino/avr/libraries/HID/src/HID.cpp:19:22: fatal error: platform.h: No such file or directory
 #include <platform.h>
                      ^
compilation terminated.
exit status 1
Error compiling for board Arduino Leonardo.

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Please Help me out ASAP I have a project to submit.
Thank you

Go Up