]> git.friedersdorff.com Git - max/tmk_keyboard.git/commitdiff
add mouse function.
authortmk <nobody@nowhere>
Thu, 30 Sep 2010 05:17:01 +0000 (14:17 +0900)
committertmk <nobody@nowhere>
Thu, 30 Sep 2010 05:50:23 +0000 (14:50 +0900)
14 files changed:
.gitignore
Makefile
keymap.h
matrix.h
mykey.c
print.c
print.h
usb.c [moved from usb_device.c with 83% similarity]
usb.h [moved from usb_device.h with 95% similarity]
usb_debug.h
usb_keyboard.h
usb_keycodes.h [moved from usbkeycodes.h with 93% similarity]
usb_mouse.c [new file with mode: 0644]
usb_mouse.h [new file with mode: 0644]

index 293c4523908f07042e1436dc8e3c831060e79d5c..c25d41d2386b2d7b9977ca7321a15bed6aece68e 100644 (file)
@@ -7,3 +7,4 @@
 *.lst
 *.map
 *.sym
+tags
index c9c668d4157ec248ae1cd7c98b97e3f95432c71a..1fe3ffa2b10ac859da10260ce27b93838494f07d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -46,13 +46,14 @@ TARGET = mykey
 
 # List C source files here. (C dependencies are automatically generated.)
 SRC =  $(TARGET).c \
-       keymap.c \
-       matrix.c \
-       usb_device.c \
+       usb.c \
        usb_keyboard.c \
+       usb_mouse.c \
        usb_debug.c \
-       print.c \
-       jump_bootloader.c
+       keymap.c \
+       matrix.c \
+       jump_bootloader.c \
+       print.c
 
 
 # MCU name, you MUST set this to match the board you are using
index ac0cc5fea66bd64bfd777f8f0e819fdc15c7491b..6b95fb61f6e8595610cda068122153d50951b426 100644 (file)
--- a/keymap.h
+++ b/keymap.h
@@ -2,7 +2,7 @@
 #define KEYMAP_H 1
 
 #include <stdint.h>
-#include "usbkeycodes.h"
+#include "usb_keycodes.h"
 
 int get_layer(void);
 uint8_t get_keycode(int layer, int row, int col);
index d5290916b5bf5261787437e173a4d1848600fa9b..74b5f894b1173efc5e411409c4947fbbe604377b 100644 (file)
--- a/matrix.h
+++ b/matrix.h
@@ -1,3 +1,6 @@
+#ifndef MATRIX_H
+#define  MATRIX_H 1
+
 #include <stdbool.h>
 
 extern uint8_t *matrix;
@@ -8,3 +11,5 @@ uint8_t matrix_scan(void);
 bool matrix_is_modified(void);
 bool matrix_has_ghost(void);
 bool matrix_has_ghost_in_row(uint8_t row);
+
+#endif
diff --git a/mykey.c b/mykey.c
index 94cbbfb5a183fda226d1be862b3c71e3177597ec..a295b8c57d7b0a724baa65c4da1ef1bf26f590d1 100644 (file)
--- a/mykey.c
+++ b/mykey.c
@@ -30,7 +30,9 @@
 #include <avr/interrupt.h>
 #include <util/delay.h>
 
-#include "usb_device.h"
+#include "usb.h"
+#include "usb_keyboard.h"
+#include "usb_mouse.h"
 #include "print.h"
 #include "matrix.h"
 #include "keymap.h"
@@ -50,16 +52,9 @@ uint16_t idle_count=0;
 
 int main(void)
 {
-    bool modified = false;
-    bool has_ghost = false;
-    uint8_t key_index = 0;
-
     // set for 16 MHz clock
     CPU_PRESCALE(0);
 
-    matrix_init();
-
-
     // Initialize the USB, and then wait for the host to set configuration.
     // If the Teensy is powered without a PC connected to the USB port,
     // this will wait forever.
@@ -78,99 +73,85 @@ int main(void)
     TCCR0B = 0x05;
     TIMSK0 = (1<<TOIE0);
 
+
+    matrix_init();
     print("firmware 0.2 for t.m.k.\n");
 
+    bool modified = false;
+    bool has_ghost = false;
+    int key_index = 0;
     int loop_count = 0;
+    int layer = 0;
     while (1) {
-        int layer = 0;
-
         matrix_scan();
         layer = get_layer();
-
         modified = matrix_is_modified();
         has_ghost = matrix_has_ghost();
 
-        // doesnt send keys during ghost occurs
-        if (modified && !has_ghost) {
-            key_index = 0;
-            keyboard_modifier_keys = 0;
-            for (int i = 0; i < 6; i++) keyboard_keys[i] = KB_NO;
+        // print matrix state for debug
+        if (modified) {
+            print_matrix();
 
-            for (int row = 0; row < MATRIX_ROWS; row++) {
-                for (int col = 0; col < MATRIX_COLS; col++) {
-                    if (matrix[row] & 1<<col) continue;
-
-                    uint8_t code = get_keycode(layer, row, col);
-                    if (code == KB_NO) {
-                        continue;
-                    } else if (KB_LCTRL <= code && code <= KB_RGUI) {
-                        // modifier keycode: 0xE0-0xE7
-                        keyboard_modifier_keys |= 1<<(code & 0x07);
-                    } else {
-                        if (key_index < 6)
-                            keyboard_keys[key_index] = code;
-                        key_index++;
-                    }
+            // LED flush
+            DDRD |= 1<<PD6;
+            PORTD |= 1<<PD6;
+        }
+
+        // set matrix state to keyboard_keys, keyboard_modifier_keys
+        key_index = 0;
+        keyboard_modifier_keys = 0;
+        for (int i = 0; i < 6; i++) keyboard_keys[i] = KB_NO;
+        for (int row = 0; row < MATRIX_ROWS; row++) {
+            for (int col = 0; col < MATRIX_COLS; col++) {
+                if (matrix[row] & 1<<col) continue;
+
+                uint8_t code = get_keycode(layer, row, col);
+                if (code == KB_NO) {
+                    continue;
+                } else if (KB_LCTRL <= code && code <= KB_RGUI) {
+                    // modifier keycode: 0xE0-0xE7
+                    keyboard_modifier_keys |= 1<<(code & 0x07);
+                } else {
+                    if (key_index < 6)
+                        keyboard_keys[key_index] = code;
+                    key_index++;
                 }
             }
+        }
 
-            // run bootloader when 4 left modifier keys down
+        if (!has_ghost)  {
+            // when 4 left modifier keys down
             if (keyboard_modifier_keys == (MOD_LCTRL | MOD_LSHIFT | MOD_LALT | MOD_LGUI)) {
                 // cancel all keys
                 keyboard_modifier_keys = 0;
                 for (int i = 0; i < 6; i++) keyboard_keys[i] = KB_NO;
                 usb_keyboard_send();
 
+                /*
                 print("jump to bootloader...\n");
                 _delay_ms(1000);
                 jump_bootloader();
-            }
+                */
 
-            if (key_index > 6) {
-                //Rollover
-            }
+                // mouse
+                print("usb_mouse_move\n");
+                usb_mouse_move(10, 0, 0);
 
-            usb_keyboard_send();
-
-
-            // variables shared with interrupt routines must be
-            // accessed carefully so the interrupt routine doesn't
-            // try to use the variable in the middle of our access
-            cli();
-            //idle_count = 0;
-            sei();
-        }
-
-        // print matrix state for debug
-        if (modified) {
-            print_matrix();
-
-            // LED flush
-            DDRD |= 1<<PD6;
-            PORTD |= 1<<PD6;
-        }
+                _delay_ms(100);
+                continue;
+            }
 
-/*
-        // print counts for debug
-        if ((loop_count % 0x1000) == 0) {
-            //print(".");
-            print("idle_count: "); phex((idle_count & 0xFF00) >> 8); phex(idle_count & 0xFF); print("\n");
-            print("loop_count: "); phex((loop_count & 0xFF00) >> 8); phex(loop_count & 0xFF); print("\n");
-            print_matrix();
-        }
 
-        // teensy LED flush for debug
-        if ((loop_count & 0x100) == 0) {
-            DDRD |= 1<<PD6;
-            PORTD |= 1<<PD6;
+            // send keys to host
+            if (modified) {
+                if (key_index > 6) {
+                    //Rollover
+                }
+                usb_keyboard_send();
+            }
         }
-*/
-
-        // now the current pins will be the previous, and
-        // wait a short delay so we're not highly sensitive
-        // to mechanical "bounce".
-        _delay_ms(2);
         loop_count++;
+        _delay_ms(2);
     }
 }
 
diff --git a/print.c b/print.c
index 8e46decac4304f70a876fe018ce346faf129e312..5395fa3480227a3a7724fd7a1c901bce402ca168 100644 (file)
--- a/print.c
+++ b/print.c
@@ -25,7 +25,6 @@
 
 #include <avr/io.h>
 #include <avr/pgmspace.h>
-
 #include "print.h"
 
 void print_P(const char *s)
diff --git a/print.h b/print.h
index 9a42462754b05f6cbdf75dabeef74e9e4ee91312..d61e5de3e096101975f126ff8863925e80bee1a9 100644 (file)
--- a/print.h
+++ b/print.h
@@ -1,5 +1,5 @@
-#ifndef print_h__
-#define print_h__
+#ifndef PRINT_H__
+#define PRINT_H__ 1
 
 #include <avr/pgmspace.h>
 #include "usb_debug.h"
similarity index 83%
rename from usb_device.c
rename to usb.c
index 1d790f043c7038960b7c319e8f763f8033bf4ee2..c910a977ed47d86ca24947145caa5cbb4c3655d6 100644 (file)
+++ b/usb.c
  * THE SOFTWARE.
  */
 
+#include <avr/io.h>
 #include <avr/pgmspace.h>
 #include <avr/interrupt.h>
-#include "usb_device.h"
+#include "usb.h"
 #include "usb_keyboard.h"
+#include "usb_mouse.h"
 #include "usb_debug.h"
 
 
 
 #define ENDPOINT0_SIZE         32
 
+// 0:control endpoint is enabled automatically by controller.
 static const uint8_t PROGMEM endpoint_config_table[] = {
-       0,
-       0,
-       1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER,
-       1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER
+       // enable, UECFG0X(type, direction), UECFG1X(size, bank, allocation)
+       1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER, // 1
+       1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(MOUSE_SIZE)    | MOUSE_BUFFER,    // 2
+       1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER, // 3
+        0, // 4
+        0, // 5
+        0, // 6
 };
 
 
@@ -138,6 +144,36 @@ static uint8_t PROGMEM keyboard_hid_report_desc[] = {
         0xc0                 // End Collection
 };
 
+// Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
+static uint8_t PROGMEM mouse_hid_report_desc[] = {
+       0x05, 0x01,                     // Usage Page (Generic Desktop)
+       0x09, 0x02,                     // Usage (Mouse)
+       0xA1, 0x01,                     // Collection (Application)
+       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, Variable, Absolute)
+       0x95, 0x01,                     //   Report Count (1)
+       0x75, 0x05,                     //   Report Size (5)
+       0x81, 0x03,                     //   Input (Constant)
+       0x05, 0x01,                     //   Usage Page (Generic Desktop)
+       0x09, 0x30,                     //   Usage (X)
+       0x09, 0x31,                     //   Usage (Y)
+       0x15, 0x81,                     //   Logical Minimum (-127)
+       0x25, 0x7F,                     //   Logical Maximum (127)
+       0x75, 0x08,                     //   Report Size (8),
+       0x95, 0x02,                     //   Report Count (2),
+       0x81, 0x06,                     //   Input (Data, Variable, Relative)
+       0x09, 0x38,                     //   Usage (Wheel)
+       0x95, 0x01,                     //   Report Count (1),
+       0x81, 0x06,                     //   Input (Data, Variable, Relative)
+       0xC0                            // End Collection
+};
+
 static uint8_t PROGMEM debug_hid_report_desc[] = {
        0x06, 0x31, 0xFF,                       // Usage Page 0xFF31 (vendor defined)
        0x09, 0x74,                             // Usage 0x74
@@ -151,20 +187,22 @@ static uint8_t PROGMEM debug_hid_report_desc[] = {
        0xC0                                    // end collection
 };
 
-#define CONFIG1_DESC_SIZE        (9+9+9+7+9+9+7)
+#define CONFIG1_DESC_SIZE        (9+(9+9+7)+(9+9+7)+(9+9+7))
 #define KEYBOARD_HID_DESC_OFFSET (9+9)
-#define DEBUG_HID_DESC_OFFSET    (9+9+9+7+9)
+#define MOUSE_HID_DESC_OFFSET    (9+(9+9+7)+9)
+#define DEBUG_HID_DESC_OFFSET    (9+(9+9+7)+(9+9+7)+9)
 static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
        // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
        9,                                      // bLength;
        2,                                      // bDescriptorType;
        LSB(CONFIG1_DESC_SIZE),                 // wTotalLength
        MSB(CONFIG1_DESC_SIZE),
-       2,                                      // bNumInterfaces
+       3,                                      // bNumInterfaces
        1,                                      // bConfigurationValue
        0,                                      // iConfiguration
        0xC0,                                   // bmAttributes
        50,                                     // bMaxPower
+
        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
        9,                                      // bLength
        4,                                      // bDescriptorType
@@ -175,7 +213,7 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
        0x01,                                   // bInterfaceSubClass (0x01 = Boot)
        0x01,                                   // bInterfaceProtocol (0x01 = Keyboard)
        0,                                      // iInterface
-       // HID interface descriptor, HID 1.11 spec, section 6.2.1
+       // HID descriptor, HID 1.11 spec, section 6.2.1
        9,                                      // bLength
        0x21,                                   // bDescriptorType
        0x11, 0x01,                             // bcdHID
@@ -191,6 +229,34 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
        0x03,                                   // bmAttributes (0x03=intr)
        KEYBOARD_SIZE, 0,                       // wMaxPacketSize
        1,                                      // bInterval
+
+       // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+       9,                                      // bLength
+       4,                                      // bDescriptorType
+       MOUSE_INTERFACE,                        // bInterfaceNumber
+       0,                                      // bAlternateSetting
+       1,                                      // bNumEndpoints
+       0x03,                                   // bInterfaceClass (0x03 = HID)
+       0x01,                                   // bInterfaceSubClass (0x01 = Boot)
+       0x02,                                   // bInterfaceProtocol (0x02 = Mouse)
+       0,                                      // iInterface
+       // HID descriptor, HID 1.11 spec, section 6.2.1
+       9,                                      // bLength
+       0x21,                                   // bDescriptorType
+       0x11, 0x01,                             // bcdHID
+       0,                                      // bCountryCode
+       1,                                      // bNumDescriptors
+       0x22,                                   // bDescriptorType
+       sizeof(mouse_hid_report_desc),          // wDescriptorLength
+       0,
+       // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+       7,                                      // bLength
+       5,                                      // bDescriptorType
+       MOUSE_ENDPOINT | 0x80,                  // bEndpointAddress
+       0x03,                                   // bmAttributes (0x03=intr)
+       4, 0,                                   // wMaxPacketSize
+       1,                                      // bInterval
+
        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
        9,                                      // bLength
        4,                                      // bDescriptorType
@@ -201,7 +267,7 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
        0x00,                                   // bInterfaceSubClass
        0x00,                                   // bInterfaceProtocol
        0,                                      // iInterface
-       // HID interface descriptor, HID 1.11 spec, section 6.2.1
+       // HID descriptor, HID 1.11 spec, section 6.2.1
        9,                                      // bLength
        0x21,                                   // bDescriptorType
        0x11, 0x01,                             // bcdHID
@@ -259,6 +325,9 @@ static struct descriptor_list_struct {
        {0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
        {0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9},
         // HID REPORT
+       {0x2200, MOUSE_INTERFACE, mouse_hid_report_desc, sizeof(mouse_hid_report_desc)},
+       {0x2100, MOUSE_INTERFACE, config1_descriptor+MOUSE_HID_DESC_OFFSET, 9},
+        // HID REPORT
        {0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)},
        {0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9},
         // STRING descriptor
@@ -470,7 +539,7 @@ ISR(USB_COM_vect)
                        usb_configuration = wValue;
                        usb_send_in();
                        cfg = endpoint_config_table;
-                       for (i=1; i<5; i++) {
+                       for (i=1; i<=6; i++) {
                                UENUM = i;
                                en = pgm_read_byte(cfg++);
                                UECONX = en;
@@ -479,7 +548,7 @@ ISR(USB_COM_vect)
                                        UECFG1X = pgm_read_byte(cfg++);
                                }
                        }
-                       UERST = 0x1E;
+                       UERST = 0x7E;
                        UERST = 0;
                        return;
                }
@@ -571,6 +640,32 @@ ISR(USB_COM_vect)
                                }
                        }
                }
+               if (wIndex == MOUSE_INTERFACE) {
+                       if (bmRequestType == 0xA1) {
+                               if (bRequest == HID_GET_REPORT) {
+                                       usb_wait_in_ready();
+                                       UEDATX = mouse_buttons;
+                                       UEDATX = 0;
+                                       UEDATX = 0;
+                                       UEDATX = 0;
+                                       usb_send_in();
+                                       return;
+                               }
+                               if (bRequest == HID_GET_PROTOCOL) {
+                                       usb_wait_in_ready();
+                                       UEDATX = mouse_protocol;
+                                       usb_send_in();
+                                       return;
+                               }
+                       }
+                       if (bmRequestType == 0x21) {
+                               if (bRequest == HID_SET_PROTOCOL) {
+                                       mouse_protocol = wValue;
+                                       usb_send_in();
+                                       return;
+                               }
+                       }
+               }
                if (wIndex == DEBUG_INTERFACE) {
                        if (bRequest == HID_GET_REPORT && bmRequestType == 0xA1) {
                                len = wLength;
similarity index 95%
rename from usb_device.h
rename to usb.h
index 233e439f4e59660703765d82011d21613d531238..c1347f10ddc99f96ae836d541c50e8649c1a6111 100644 (file)
+++ b/usb.h
@@ -1,10 +1,8 @@
-#ifndef USB_DEVICE_H
-#define  USB_DEVICE_H 1
+#ifndef USB_H
+#define  USB_H 1
 
 #include <stdint.h>
 #include <avr/io.h>
-#include "usb_keyboard.h"
-#include "usb_debug.h"
 
 
 void usb_init(void);                   // initialize everything
index acc6716cdebcfc072d05537b56a3e3c9278125a3..65ad05b04a2bc8f1b658b4b6f585d6afe5418d6b 100644 (file)
@@ -2,11 +2,11 @@
 #define  USB_DEBUG_H 1
 
 #include <stdint.h>
-#include "usb_device.h"
+#include "usb.h"
 
 
-#define DEBUG_INTERFACE                1
-#define DEBUG_TX_ENDPOINT      4
+#define DEBUG_INTERFACE                2
+#define DEBUG_TX_ENDPOINT      3
 #define DEBUG_TX_SIZE          32
 #define DEBUG_TX_BUFFER                EP_DOUBLE_BUFFER
 
index cd8ec4a9d19b41753784402d6f3db1aaed15e9c9..90c2c5af62ca3f83a6b7fa889e1fd8bc64e30c54 100644 (file)
@@ -2,11 +2,11 @@
 #define  USB_KEYBOARD_H 1
 
 #include <stdint.h>
-#include "usb_device.h"
+#include "usb.h"
 
 
 #define KEYBOARD_INTERFACE     0
-#define KEYBOARD_ENDPOINT      3
+#define KEYBOARD_ENDPOINT      1
 #define KEYBOARD_SIZE          8
 #define KEYBOARD_BUFFER                EP_DOUBLE_BUFFER
 
similarity index 93%
rename from usbkeycodes.h
rename to usb_keycodes.h
index b0e705836369bf9bb984f1661984e89398094caa..95160398d86ca5b98b202c966d7e7a8c49fa9a9e 100644 (file)
@@ -1,5 +1,8 @@
-/* Some modified from Keyboard Upgrade 0.3.0
- * 2010/08/22
+/* 
+ * Key codes from HID Keyboard/Keypad Page
+ * http://www.usb.org/developers/devclass_docs/Hut1_12.pdf
+ *
+ * Based on Keyboard Upgrade v0.3.0 http://github.com/rhomann/kbupgrade
  */
 /*
  * Keyboard Upgrade -- Firmware for homebrew computer keyboard controllers.
  * MA  02110-1301  USA
  */
 
-#ifndef USBKEYCODES_H
-#define USBKEYCODES_H
+#ifndef USB_KEYCODES_H
+#define USB_KEYCODES_H
+
 
-/*
- * The USB keycodes are enumerated here - the first part is simply
- * an enumeration of the allowed scan-codes used for USB HID devices.
- */
-/*
- * see 10 Keyboard/Keypad Page(0x07)
- * http://www.usb.org/developers/devclass_docs/Hut1_12.pdf
- */
 enum keycodes {
     KB_NO = 0,
     KB_ROLL_OVER,
@@ -265,11 +261,11 @@ enum keycodes {
     KB_RALT,            /* 0x40 */
     KB_RGUI,            /* 0x80 */
 
-    /* function keys */
+    /* extensions for internal use */
     FN_0 = 0xF0,
     FN_1,
     FN_2,
     FN_3,
 };
 
-#endif /* USBKEYCODES_H */
+#endif /* USB_KEYCODES_H */
diff --git a/usb_mouse.c b/usb_mouse.c
new file mode 100644 (file)
index 0000000..539f2ed
--- /dev/null
@@ -0,0 +1,62 @@
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include "usb_mouse.h"
+
+
+// which buttons are currently pressed
+uint8_t mouse_buttons=0;
+
+// protocol setting from the host.  We use exactly the same report
+// either way, so this variable only stores the setting since we
+// are required to be able to report which setting is in use.
+uint8_t mouse_protocol=1;
+
+
+// Set the mouse buttons.  To create a "click", 2 calls are needed,
+// one to push the button down and the second to release it
+int8_t usb_mouse_buttons(uint8_t left, uint8_t middle, uint8_t right)
+{
+       uint8_t mask=0;
+
+       if (left) mask |= 1;
+       if (middle) mask |= 4;
+       if (right) mask |= 2;
+       mouse_buttons = mask;
+       return usb_mouse_move(0, 0, 0);
+}
+
+// Move the mouse.  x, y and wheel are -127 to 127.  Use 0 for no movement.
+int8_t usb_mouse_move(int8_t x, int8_t y, int8_t wheel)
+{
+       uint8_t intr_state, timeout;
+
+       if (!usb_configured()) return -1;
+       if (x == -128) x = -127;
+       if (y == -128) y = -127;
+       if (wheel == -128) wheel = -127;
+       intr_state = SREG;
+       cli();
+       UENUM = MOUSE_ENDPOINT;
+       timeout = UDFNUML + 50;
+       while (1) {
+               // are we ready to transmit?
+               if (UEINTX & (1<<RWAL)) break;
+               SREG = intr_state;
+               // has the USB gone offline?
+               if (!usb_configured()) return -1;
+               // have we waited too long?
+               if (UDFNUML == timeout) return -1;
+               // get ready to try checking again
+               intr_state = SREG;
+               cli();
+               UENUM = MOUSE_ENDPOINT;
+       }
+       UEDATX = mouse_buttons;
+       UEDATX = x;
+       UEDATX = y;
+       UEDATX = wheel;
+       UEINTX = 0x3A;
+       SREG = intr_state;
+       return 0;
+}
+
diff --git a/usb_mouse.h b/usb_mouse.h
new file mode 100644 (file)
index 0000000..f1f3977
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef USB_MOUSE_H
+#define  USB_MOUSE_H 1
+
+#include <stdint.h>
+#include "usb.h"
+
+
+#define MOUSE_INTERFACE                1
+#define MOUSE_ENDPOINT         2
+#define MOUSE_SIZE             8
+#define MOUSE_BUFFER           EP_DOUBLE_BUFFER
+
+extern uint8_t mouse_buttons;
+extern uint8_t mouse_protocol;
+
+
+int8_t usb_mouse_buttons(uint8_t left, uint8_t middle, uint8_t right);
+int8_t usb_mouse_move(int8_t x, int8_t y, int8_t wheel);
+
+#endif