// // Created by robin on 1/8/16. // UsbMouseDevice UsbMouse = UsbMouseDevice(); /* We use a simplifed keyboard report descriptor which does not support the * boot protocol. We don't allow setting status LEDs and but we do allow * simultaneous key presses. * The report descriptor has been created with usb.org's "HID Descriptor Tool" * which can be downloaded from http://www.usb.org/developers/hidpage/. * Redundant entries (such as LOGICAL_MINIMUM and USAGE_PAGE) have been omitted * for the second INPUT item. */ PROGMEM const char usbHidReportDescriptor[52] = { /* USB report descriptor, size must match usbconfig.h */ 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x02, // USAGE (Mouse) 0xa1, 0x01, // COLLECTION (Application) 0x09, 0x01, // USAGE (Pointer) 0xA1, 0x00, // COLLECTION (Physical) 0x05, 0x09, // USAGE_PAGE (Button) 0x19, 0x01, // USAGE_MINIMUM 0x29, 0x03, // USAGE_MAXIMUM 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 (Const,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 }; UsbMouseDevice::UsbMouseDevice() { PORTD = 0; // TODO: Only for USB pins? DDRD |= ~USBMASK; cli(); usbDeviceDisconnect(); usbDeviceConnect(); usbInit(); sei(); resetStatus(); } bool UsbMouseDevice::isUsbReady() { UsbMouse.update(); return usbInterruptIsReady(); } void UsbMouseDevice::move(char dx, char dy) { reportBuffer.dx += dx; reportBuffer.dy += dy; updateStatus(); } void UsbMouseDevice::moveWheel(char dy) { reportBuffer.dWheel += dy; updateStatus(); } void UsbMouseDevice::pressButton(char button) { reportBuffer.buttonMask |= button; updateStatus(); } void UsbMouseDevice::releaseButton(char button) { reportBuffer.buttonMask &= ~button; updateStatus(); } void UsbMouseDevice::setButtonState(char button, bool pressed) { if (pressed) { pressButton(button); } else { releaseButton(button); } } /*void UsbMouseDevice::clickButton(char button) { pressButton(button); while (!usbInterruptIsReady()) { } releaseButton(button); }*/ void UsbMouseDevice::updateStatus() { usbSetInterrupt((unsigned char*)(void *)&reportBuffer, sizeof(reportBuffer)); resetStatus(); } void UsbMouseDevice::resetStatus() { reportBuffer.buttonMask = 0; reportBuffer.dx = 0; reportBuffer.dy = 0; reportBuffer.dWheel = 0; } usbMsgLen_t usbFunctionSetup(uchar data[8]) { usbRequest_t *rq = (usbRequest_t*)(void*)data; /* The following requests are never used. But since they are required by * the specification, we implement them in this example. */ if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */ if(rq->bRequest == USBRQ_HID_GET_REPORT){ /* wValue: ReportType (highbyte), ReportID (lowbyte) */ /* we only have one report type, so don't look at wValue */ usbMsgPtr = (unsigned char*)(void *)&UsbMouse.reportBuffer; return sizeof(UsbMouse.reportBuffer); }else if(rq->bRequest == USBRQ_HID_GET_IDLE){ usbMsgPtr = &idleRate; return 1; }else if(rq->bRequest == USBRQ_HID_SET_IDLE){ idleRate = rq->wValue.bytes[1]; } }else{ /* no vendor specific requests implemented */ } return 0; /* default for not implemented requests: return no data back to host */ }