Source file: /~heha/ewa/Motor/Maxmaus9.zip/usblib/usbdhidmouse.cpp

// TITLE: USB HID Mouse device class driver
#include "usbdhidmouse.h"
#include <usb.h>
extern "C" {
#include <debug.h>	// ASSERT
}

namespace usb{

// report descriptor
static const uint8_t ReportDesc[] = {
  0x05,1,	// UsagePage(GENERIC_DESKTOP)
  0x09,2,	// Usage(MOUSE),
  0xA1,1,	// Collection(APPLICATION)
   0x09,1,	// Usage(POINTER)
   0xA1,0,	// Collection(Physical)
// buttons
    0x05,9,	// UsagePage(BUTTONS)
    0x19,1,	// UsageMinimum(1)
    0x29,3,	// UsageMaximum(3)
    0x15,0,	// LogicalMinimum(0)
    0x25,1,	// LogicalMaximum(1)
    0x75,1,	// ReportSize(1)
    0x95,3,	// ReportCount(3)
    0x81,2,	// Input(VAR,ABS)
    0x75,5,	// ReportSize(5)
    0x95,1,	// ReportCount(1)
    0x81,3, 	// Input(CONST|ARY|ABS)
// X and Y axis
    0x05,1,	// UsagePage(GENERIC_DESKTOP)
    0x09,0x30,	// Usage(X),
    0x09,0x31,	// Usage(Y),
    0x15,(uint8_t)-127,	// LogicalMinimum(-127)
    0x25,127,	// LogicalMaximum(127)
    0x75,8,	// ReportSize(8)
    0x95,2,	// ReportCount(2)
    0x81,6,	// Input(DATA|VAR|REL)
   0xC0,	//  EndCollection
  0xC0,		//  EndCollection
};

// Device Descriptor
static const uint8_t DeviceDesc[] = {
  18,		// Size of this structure.
  1,		// Type of this structure = DTYPE_DEVICE
  USB2(0x110),	// USB version 1.1
  0,		// USB Device Class
  0,		// USB Device Sub-class
  0,		// USB Device protocol
  64,		// Maximum packet size for default pipe.
  USB2(0x1CBE),	// Vendor ID = Texas Instruments
  USB2(0),	// Product ID = TI Mouse
  USB2(0x100),	// Device Version BCD.
  1,		// Manufacturer string identifier.
  2,		// Product string identifier.
  0,		// Product serial number.
  1,		// Number of configurations.
};

// configuration descriptor.
static const uint8_t ConfigDesc[] = {
  9,		// bLength
  2,		// USB_DTYPE_CONFIGURATION
  USB2(9+9+9+7),	// The total size of this full structure.
  1,		// bNumInterfaces
  1,		// bConfigurationValue
  0,		// iConfiguration
  0xC0,		// Bus Powered, Self Powered, remote wake up.
  50,		// The maximum power in 2mA increments.
// Interface Descriptor.
  9,                          // Size of the interface descriptor.
  4,	//USB_DTYPE_INTERFACE,        // Type of this descriptor.
  0,	// The index for this interface.
  0,	// The alternate setting for this interface.
  1,	// The number of endpoints used by this interface.
  3,	// USB_CLASS_HID,              // interface class
  0,	// interface sub-class.
  0,	// interface protocol for the sub-class specified above.
  0,	// The string index for this interface.
// HID descriptor
  9,		// bLength
  0x21,		// bDescriptorType = DTYPE_HID
  USB2(0x111),	// bcdHID (version 1.11 compliant)
  0,		// bCountryCode (not localized)
  1,		// bNumDescriptors
  0x22,		// Report descriptor = DTYPE_REPORT
  USB2(sizeof ReportDesc),  // Size of report descriptor
// Interrupt IN endpoint descriptor
  7,		// The size of the endpoint descriptor.
  5,		//USB_DTYPE_ENDPOINT,         // Descriptor type is an endpoint.
  0x81,		// EP1IN
  0x03,		// Endpoint is an interrupt endpoint.
  USB2(64),	// The maximum packet size.
  16,		// The polling interval for this endpoint.
};

bool tHIDMouseDevice::cbRequestHandler(const tRequest&rq) {
  switch (rq.wRequest()) {
    case 0x01A1: if (	// GET_REPORT, class-specific, target=interface
      rq.wIndexL == 0		// Interface 0
   && rq.wValueH == 0x01	// report_type = INPUT
   && rq.wValueL == 0) {	// report_id
    USBDevEndpointDataAck(USB_BASE, USB_EP_0, true);
    SendDataEP0(inrep,3,rq);
    return true;
    }break;
    case 0x06A1: return cbGetDescriptor(rq);
  }
  return tDevice::cbRequestHandler(rq);	// chain down
}

static void buildStringDesc(uint8_t d[256],const char*s) {
  uint8_t*p=d+1;
  *p++=3;
  wchar_t c;
  while ((c=*s++)) {
    if (c&0x80) {
      if (c&0x20) {	// 3-Byte-UTF-8
        c<<=6;
        c|=*s++&0x3F;
      }else c&=0x3F;	// 2-Byte-UTF-8
      c<<=6;
      c|=*s++&0x3F;
    }
    *p++=c&0xFF;
    *p++=c>>8&0xFF;
  }
  ASSERT(p-d<256);
  *d=p-d;
}

bool tHIDMouseDevice::cbGetDescriptor(const tRequest&rq) {
  switch (rq.wValueH) {
    case 1: {	// device descriptor
      SendDataEP0(DeviceDesc, sizeof DeviceDesc, rq);
    }return true;
    case 2: {	// configuration descriptor
      SendDataEP0(ConfigDesc, sizeof ConfigDesc, rq);
    }return true;
    case 3: {
      uint8_t sd[256];
      switch (rq.wValueL) {	// string descriptor
// Bug+Workaround: C++2000 unterstützt weder L"\x0409" noch L"\u0409" richtig, nimmt nur Low-Byte
// Bug+Workaround: C++2000 unterstützt kein L"Ä", speichert UTF-8, daher UTF-8-Strings
        case 0: buildStringDesc(sd,"\xD0\x87"); break;	// 0x0407 deutsch
        case 1: buildStringDesc(sd,"Texas Instruments"); break;
        case 2: buildStringDesc(sd,"Mausbeispiel: ÄÖÜäöüß"); break;
        default: return false;
      }
      SendDataEP0(sd,sd[0],rq);
    }return true;
    case 0x21: {
      SendDataEP0(ConfigDesc+9+9, 9, rq);
    }return true;
    case 0x22: {
      SendDataEP0(ReportDesc, sizeof ReportDesc, rq);
    }return true;
  }
  return tDevice::cbGetDescriptor(rq);
}

bool tHIDMouseDevice::StateChange(uint8_t Buttons, int8_t DeltaX, int8_t DeltaY) {
  inrep[0]=Buttons;
  inrep[1]=(uint8_t)DeltaX;
  inrep[2]=(uint8_t)DeltaY;
  return SendReport(inrep,3);
}

bool tHIDMouseDevice::SendReport(uint8_t *data, unsigned len) {
  int32_t i32Retcode = USBEndpointDataPut(USB_BASE,USB_EP_1,data,len);
  if (!i32Retcode) {
    i32Retcode = USBEndpointDataSend(USB_BASE,USB_EP_1,USB_TRANS_IN);
  }
  return i32Retcode==0;
}

}
Detected encoding: UTF-80