main.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /* Name: main.c
  2. * Project: hid-mouse, a very simple HID example
  3. * Author: Christian Starkjohann
  4. * Creation Date: 2008-04-07
  5. * Tabsize: 4
  6. * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
  7. * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
  8. * This Revision: $Id: main.c 692 2008-11-07 15:07:40Z cs $
  9. */
  10. /*
  11. This example should run on most AVRs with only little changes. No special
  12. hardware resources except INT0 are used. You may have to change usbconfig.h for
  13. different I/O pins for USB. Please note that USB D+ must be the INT0 pin, or
  14. at least be connected to INT0 as well.
  15. We use VID/PID 0x046D/0xC00E which is taken from a Logitech mouse. Don't
  16. publish any hardware using these IDs! This is for demonstration only!
  17. */
  18. #include <avr/io.h>
  19. #include <avr/wdt.h>
  20. #include <avr/interrupt.h> /* for sei() */
  21. #include <util/delay.h> /* for _delay_ms() */
  22. #include <avr/pgmspace.h> /* required by usbdrv.h */
  23. #include "usbdrv.h"
  24. #include "oddebug.h" /* This is also an example for using debug macros */
  25. /* ------------------------------------------------------------------------- */
  26. /* ----------------------------- USB interface ----------------------------- */
  27. /* ------------------------------------------------------------------------- */
  28. PROGMEM char usbHidReportDescriptor[52] = { /* USB report descriptor, size must match usbconfig.h */
  29. 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
  30. 0x09, 0x02, // USAGE (Mouse)
  31. 0xa1, 0x01, // COLLECTION (Application)
  32. 0x09, 0x01, // USAGE (Pointer)
  33. 0xA1, 0x00, // COLLECTION (Physical)
  34. 0x05, 0x09, // USAGE_PAGE (Button)
  35. 0x19, 0x01, // USAGE_MINIMUM
  36. 0x29, 0x03, // USAGE_MAXIMUM
  37. 0x15, 0x00, // LOGICAL_MINIMUM (0)
  38. 0x25, 0x01, // LOGICAL_MAXIMUM (1)
  39. 0x95, 0x03, // REPORT_COUNT (3)
  40. 0x75, 0x01, // REPORT_SIZE (1)
  41. 0x81, 0x02, // INPUT (Data,Var,Abs)
  42. 0x95, 0x01, // REPORT_COUNT (1)
  43. 0x75, 0x05, // REPORT_SIZE (5)
  44. 0x81, 0x03, // INPUT (Const,Var,Abs)
  45. 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
  46. 0x09, 0x30, // USAGE (X)
  47. 0x09, 0x31, // USAGE (Y)
  48. 0x09, 0x38, // USAGE (Wheel)
  49. 0x15, 0x81, // LOGICAL_MINIMUM (-127)
  50. 0x25, 0x7F, // LOGICAL_MAXIMUM (127)
  51. 0x75, 0x08, // REPORT_SIZE (8)
  52. 0x95, 0x03, // REPORT_COUNT (3)
  53. 0x81, 0x06, // INPUT (Data,Var,Rel)
  54. 0xC0, // END_COLLECTION
  55. 0xC0, // END COLLECTION
  56. };
  57. /* This is the same report descriptor as seen in a Logitech mouse. The data
  58. * described by this descriptor consists of 4 bytes:
  59. * . . . . . B2 B1 B0 .... one byte with mouse button states
  60. * X7 X6 X5 X4 X3 X2 X1 X0 .... 8 bit signed relative coordinate x
  61. * Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 .... 8 bit signed relative coordinate y
  62. * W7 W6 W5 W4 W3 W2 W1 W0 .... 8 bit signed relative coordinate wheel
  63. */
  64. typedef struct{
  65. uchar buttonMask;
  66. char dx;
  67. char dy;
  68. char dWheel;
  69. }report_t;
  70. static report_t reportBuffer;
  71. static int sinus = 7 << 6, cosinus = 0;
  72. static uchar idleRate; /* repeat rate for keyboards, never used for mice */
  73. /* The following function advances sin/cos by a fixed angle
  74. * and stores the difference to the previous coordinates in the report
  75. * descriptor.
  76. * The algorithm is the simulation of a second order differential equation.
  77. */
  78. static void advanceCircleByFixedAngle(void)
  79. {
  80. char d;
  81. #define DIVIDE_BY_64(val) (val + (val > 0 ? 32 : -32)) >> 6 /* rounding divide */
  82. reportBuffer.dx = d = DIVIDE_BY_64(cosinus);
  83. sinus += d;
  84. reportBuffer.dy = d = DIVIDE_BY_64(sinus);
  85. cosinus -= d;
  86. }
  87. /* ------------------------------------------------------------------------- */
  88. usbMsgLen_t usbFunctionSetup(uchar data[8])
  89. {
  90. usbRequest_t *rq = (void *)data;
  91. /* The following requests are never used. But since they are required by
  92. * the specification, we implement them in this example.
  93. */
  94. if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */
  95. DBG1(0x50, &rq->bRequest, 1); /* debug output: print our request */
  96. if(rq->bRequest == USBRQ_HID_GET_REPORT){ /* wValue: ReportType (highbyte), ReportID (lowbyte) */
  97. /* we only have one report type, so don't look at wValue */
  98. usbMsgPtr = (void *)&reportBuffer;
  99. return sizeof(reportBuffer);
  100. }else if(rq->bRequest == USBRQ_HID_GET_IDLE){
  101. usbMsgPtr = &idleRate;
  102. return 1;
  103. }else if(rq->bRequest == USBRQ_HID_SET_IDLE){
  104. idleRate = rq->wValue.bytes[1];
  105. }
  106. }else{
  107. /* no vendor specific requests implemented */
  108. }
  109. return 0; /* default for not implemented requests: return no data back to host */
  110. }
  111. /* ------------------------------------------------------------------------- */
  112. int main(void)
  113. {
  114. uchar i;
  115. wdt_enable(WDTO_1S);
  116. /* Even if you don't use the watchdog, turn it off here. On newer devices,
  117. * the status of the watchdog (on/off, period) is PRESERVED OVER RESET!
  118. */
  119. DBG1(0x00, 0, 0); /* debug output: main starts */
  120. /* RESET status: all port bits are inputs without pull-up.
  121. * That's the way we need D+ and D-. Therefore we don't need any
  122. * additional hardware initialization.
  123. */
  124. odDebugInit();
  125. usbInit();
  126. usbDeviceDisconnect(); /* enforce re-enumeration, do this while interrupts are disabled! */
  127. i = 0;
  128. while(--i){ /* fake USB disconnect for > 250 ms */
  129. wdt_reset();
  130. _delay_ms(1);
  131. }
  132. usbDeviceConnect();
  133. sei();
  134. DBG1(0x01, 0, 0); /* debug output: main loop starts */
  135. for(;;){ /* main event loop */
  136. DBG1(0x02, 0, 0); /* debug output: main loop iterates */
  137. wdt_reset();
  138. usbPoll();
  139. if(usbInterruptIsReady()){
  140. /* called after every poll of the interrupt endpoint */
  141. advanceCircleByFixedAngle();
  142. DBG1(0x03, 0, 0); /* debug output: interrupt report prepared */
  143. usbSetInterrupt((void *)&reportBuffer, sizeof(reportBuffer));
  144. }
  145. }
  146. return 0;
  147. }
  148. /* ------------------------------------------------------------------------- */