Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge the new HID library and apps in to the master branch.

  • Loading branch information...
commit 439abc6df86b1e327f56fd44213a68002f5b324f 2 parents 199b5e0 + c5a5c79
@DavidEGrayson DavidEGrayson authored
View
1  apps/test_hid/options.mk
@@ -0,0 +1 @@
+APP_LIBS := dma.lib usb.lib usb_hid.lib wixel.lib gpio.lib
View
179 apps/test_hid/test_hid.c
@@ -0,0 +1,179 @@
+/* pinout:
+ *
+ * P0_0 = Left Mouse Button input
+ * P0_1 = Right Mouse Button input
+ */
+
+#include <wixel.h>
+#include <usb.h>
+#include <usb_hid.h>
+
+int32 CODE param_move_cursor = 0;
+int32 CODE param_move_mouse_wheel = 0;
+
+uint8 lastKeyCodeSent = 0;
+
+void updateLeds()
+{
+ usbShowStatusWithGreenLed();
+
+ LED_YELLOW(usbHidKeyboardOutput.leds & (1 << LED_CAPS_LOCK));
+
+ // To see the Num Lock or Caps Lock state, you can use these lines instead of the above:
+ //LED_YELLOW(usbHidKeyboardOutput.leds & (1 << LED_NUM_LOCK));
+ //LED_YELLOW(usbHidKeyboardOutput.leds & (1 << LED_SCROLL_LOCK));
+
+ // NOTE: Reading the Caps Lock, Num Lock, and Scroll Lock states might not work
+ // if the USB host is a Linux or Mac OS machine.
+}
+
+void updateMouseState()
+{
+ usbHidMouseInput.x = 0;
+ usbHidMouseInput.y = 0;
+
+ if (param_move_cursor)
+ {
+ uint8 direction = getMs() >> 9 & 3;
+ switch(direction)
+ {
+ case 0: usbHidMouseInput.x = 3; break;
+ case 1: usbHidMouseInput.y = 3; break;
+ case 2: usbHidMouseInput.x = -3; break;
+ case 3: usbHidMouseInput.y = -3; break;
+ }
+ }
+
+ if (param_move_mouse_wheel)
+ {
+ uint8 direction = getMs() >> 10 & 1;
+ if (direction)
+ {
+ usbHidMouseInput.wheel = -1;
+ }
+ else
+ {
+ usbHidMouseInput.wheel = 1;
+ }
+ }
+
+ usbHidMouseInput.buttons = 0;
+ if (!isPinHigh(0))
+ {
+ // The left mouse button is pressed.
+ usbHidMouseInput.buttons |= (1<<MOUSE_BUTTON_LEFT);
+ }
+ if (!isPinHigh(1))
+ {
+ // The right mouse button is pressed.
+ usbHidMouseInput.buttons |= (1<<MOUSE_BUTTON_RIGHT);
+ }
+
+ usbHidMouseInputUpdated = 1;
+}
+
+// See keyboardService for an example of how to use this function correctly.
+// Assumption: usbHidKeyboardInputUpdated == 0. Otherwise, this function
+// could clobber a keycode sitting in the buffer that has not been sent to
+// the computer yet.
+// Assumption: usbHidKeyBoardInput[1 through 5] are all zero.
+// Assumption: usbHidKeyboardInput.modifiers is 0.
+// NOTE: To send two identical characters, you must send a 0 in between.
+void sendKeyCode(uint8 keyCode)
+{
+ lastKeyCodeSent = keyCode;
+ usbHidKeyboardInput.keyCodes[0] = keyCode;
+
+ // Tell the HID library to send the new keyboard state to the computer.
+ usbHidKeyboardInputUpdated = 1;
+}
+
+// NOTE: This function only handles bouncing that occurs when the button is
+// going from the not-pressed to pressed state.
+BIT buttonGetSingleDebouncedPress()
+{
+ static BIT reportedThisButtonPress = 0;
+ static uint8 lastTimeButtonWasNotPressed = 0;
+
+ if (isPinHigh(2))
+ {
+ // The P0_2 "button" is not pressed.
+ reportedThisButtonPress = 0;
+ lastTimeButtonWasNotPressed = (uint8)getMs();
+ }
+ else if ((uint8)(getMs() - lastTimeButtonWasNotPressed) > 15)
+ {
+ // The P0_2 "button" has been pressed (or at least P0_2 is shorted
+ // to ground) for 15 ms.
+
+ if (!reportedThisButtonPress)
+ {
+ reportedThisButtonPress = 1;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void keyboardService()
+{
+ /* char CODE test[] = "!\"#$%&'()*+,-./0123456789:;<=>? "
+ "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ "
+ "`abcdefghijklmnopqrstuvwxyz{|}~"; */
+ char CODE greeting[] = "hello world ";
+ static uint8 charsLeftToSend = 0;
+ static char XDATA * nextCharToSend;
+
+ if (buttonGetSingleDebouncedPress() && charsLeftToSend == 0)
+ {
+ nextCharToSend = (char XDATA *)greeting;
+ charsLeftToSend = sizeof(greeting)-1;
+
+ // Uncomment the 'test' string above and the following line to test more characters.
+ //nextCharToSend = (char XDATA *)test; charsLeftToSend = sizeof(test)-1;
+ }
+
+ LED_RED(charsLeftToSend > 0);
+
+ // Feed data to the HID library, one character at a time.
+ if (charsLeftToSend && !usbHidKeyboardInputUpdated)
+ {
+ uint8 keyCode = usbHidKeyCodeFromAsciiChar(*nextCharToSend);
+
+ if (keyCode != 0 && keyCode == lastKeyCodeSent)
+ {
+ // If we need to send the same character twice in a row,
+ // send a 0 between them so the compute registers it as
+ // two different separate key strokes.
+ keyCode = 0;
+ }
+ else
+ {
+ nextCharToSend++;
+ charsLeftToSend--;
+ }
+
+ sendKeyCode(keyCode);
+ }
+
+ // Send a 0 to signal the release of the last key.
+ if (charsLeftToSend == 0 && lastKeyCodeSent != 0 && !usbHidKeyboardInputUpdated)
+ {
+ sendKeyCode(0);
+ }
+}
+
+void main()
+{
+ systemInit();
+ usbInit();
+
+ while(1)
+ {
+ updateLeds();
+ boardService();
+ usbHidService();
+ updateMouseState();
+ keyboardService();
+ }
+}
View
1  apps/wireless_tilt_mouse/options.mk
@@ -0,0 +1 @@
+APP_LIBS := dma.lib usb.lib wixel.lib adc.lib gpio.lib radio_mac.lib radio_queue.lib radio_registers.lib random.lib usb.lib usb_cdc_acm.lib
View
92 apps/wireless_tilt_mouse/wireless_tilt_mouse.c
@@ -0,0 +1,92 @@
+/* wireless_tilt_mouse app:
+ * Allows you to make a wireless tilt mouse using two Wixels, an accelerometer,
+ * and two pushbuttons (optional).
+ *
+ * One Wixel should be running the wireless_tilt_mouse_receiver app and be
+ * connected to a computer via USB. The other Wixel should be running this app,
+ * and be connected to the accelerometer and two optional pushbuttons.
+ *
+ * == Pinout ==
+ *
+ * P0_1 = Mouse Y analog input (controls vertical cursor speed)
+ * P0_2 = Mouse X analog input (controls horizontal cursor speed)
+ * P1_2 = left mouse button input (pulled high; low means button is pressed)
+ * P1_7 = left mouse button input (pulled high; low means button is pressed)
+ *
+ * == Parameters ==
+ * - invert_x: Default is 0. Set to 1 to invert the X axis movement.
+ * - invert_y: Default is 0. Set to 1 to invert the Y axis movement.
+ * - speed: Controls how fast the mouse moves. Default is 100.
+ */
+
+#include <wixel.h>
+#include <usb.h>
+#include <usb_com.h>
+#include <usb_hid_constants.h>
+#include <radio_queue.h>
+#include <math.h>
+
+#define TX_INTERVAL 10 // time between transmissions (ms)
+
+int32 CODE param_invert_x = 0;
+int32 CODE param_invert_y = 0;
+int32 CODE param_speed = 100;
+
+void updateLeds()
+{
+ usbShowStatusWithGreenLed();
+ LED_YELLOW(vinPowerPresent());
+}
+
+void txMouseState()
+{
+ uint8 XDATA * txBuf;
+ static uint8 lastTx = 0;
+
+ if ((uint8)(getMs() - lastTx) > TX_INTERVAL && (txBuf = radioQueueTxCurrentPacket()))
+ {
+ float fx, fy, multiplier;
+ int8 x, y;
+
+ fx = -((float)adcRead(2 | ADC_BITS_12) - 1024) / 128; // fx = Acceleration in X direction (floating point)
+ fy = ((float)adcRead(1 | ADC_BITS_12) - 1024) / 128; // fy = Acceleration in Y direction
+ multiplier = sqrtf(fx * fx + fy * fy) * param_speed/100;
+
+ // Compute the x and y mouse change values to send.
+ x = (int8)(fx * multiplier);
+ y = (int8)(fy * multiplier);
+ if (param_invert_x){ x = -x; }
+ if (param_invert_y){ y = -y; }
+
+ // Construct a packet and transmit it on the radio.
+ txBuf[0] = 3; // Packet length in bytes.
+ txBuf[1] = x;
+ txBuf[2] = y;
+ txBuf[3] = (!isPinHigh(12) << MOUSE_BUTTON_LEFT) | (!isPinHigh(17) << MOUSE_BUTTON_RIGHT);
+ radioQueueTxSendPacket();
+
+ lastTx = getMs();
+ }
+}
+
+void main()
+{
+ systemInit();
+ usbInit();
+
+ radioQueueInit();
+ randomSeedFromSerialNumber();
+
+ // disable pull-ups on accelerometer outputs
+ setDigitalInput(1, HIGH_IMPEDANCE);
+ setDigitalInput(2, HIGH_IMPEDANCE);
+
+ while(1)
+ {
+ updateLeds();
+ boardService();
+ usbComService();
+
+ txMouseState();
+ }
+}
View
1  apps/wireless_tilt_mouse_receiver/options.mk
@@ -0,0 +1 @@
+APP_LIBS := dma.lib usb.lib usb_hid.lib wixel.lib radio_mac.lib radio_queue.lib radio_registers.lib random.lib
View
47 apps/wireless_tilt_mouse_receiver/wireless_tilt_mouse_receiver.c
@@ -0,0 +1,47 @@
+#include <cc2511_map.h>
+#include <board.h>
+#include <time.h>
+
+#include <usb.h>
+#include <usb_hid.h>
+#include <adc.h>
+#include <gpio.h>
+#include <radio_queue.h>
+#include <random.h>
+
+void updateLeds()
+{
+ usbShowStatusWithGreenLed();
+}
+
+void rxMouseState(void)
+{
+ uint8 XDATA * rxBuf;
+
+ if (rxBuf = radioQueueRxCurrentPacket())
+ {
+ usbHidMouseInput.x = rxBuf[1];
+ usbHidMouseInput.y = rxBuf[2];
+ usbHidMouseInput.buttons = rxBuf[3];
+ usbHidMouseInputUpdated = 1;
+ radioQueueRxDoneWithPacket();
+ }
+}
+
+void main()
+{
+ systemInit();
+ usbInit();
+
+ radioQueueInit();
+ randomSeedFromSerialNumber();
+
+ while(1)
+ {
+ updateLeds();
+ boardService();
+ usbHidService();
+
+ rxMouseState();
+ }
+}
View
3  libraries/docs/overviews.dox
@@ -123,6 +123,9 @@ If you have a problem or question, feel free to ask us on the
- <b>usb_cdc_acm.lib (usb_com.h):</b> Implements the USB CDC ACM interface, which
allows the Wixel to appear as a virtual COM port when it is connected to a PC.
Depends on <b>usb.lib</b> and <b>wixel.lib</b>.
+- <b>usb_hid.lib (usb_hid.h):</b> Implements a USB Human Interface Device (HID)
+ which allows the Wixel to appear as both a Mouse and Keyboard when it is
+ connected to a PC. Depends on <b>usb.lib</b> and <b>wixel.lib</b>.
- <b>usb.lib (usb.h):</b> Sets up the USB module and responds to standard device
requests. This is a general purpose library that could be used to implement
many different kinds of USB device interfaces. Depends on <b>wixel.lib</b>.
View
21 libraries/include/usb.h
@@ -194,13 +194,13 @@ typedef struct USB_DESCRIPTOR_ENDPOINT // USB2.0 Table 9-13: Standard Endpoint D
extern enum USB_DEVICE_STATES XDATA usbDeviceState;
extern USB_SETUP_PACKET XDATA usbSetupPacket;
-void usbInit();
-void usbPoll();
+void usbInit(void);
+void usbPoll(void);
void usbControlRead(uint16 bytesCount, uint8 XDATA * source);
void usbControlWrite(uint16 bytesCount, uint8 XDATA * source);
-void usbControlAcknowledge();
-void usbControlStall();
+void usbControlAcknowledge(void);
+void usbControlStall(void);
void usbInitEndpointIn(uint8 endpointNumber, uint8 maxPacketSize);
void usbInitEndpointOut(uint8 endpointNumber, uint8 maxPacketSize);
@@ -213,7 +213,7 @@ void usbReadFifo(uint8 endpointNumber, uint8 count, uint8 XDATA * buffer);
*
* You can use this to know when it is time to turn
* off the peripherals and go in to a power-saving mode. */
-BIT usbSuspended();
+BIT usbSuspended(void);
/* TODO: document usbSleep
*
@@ -228,7 +228,7 @@ BIT usbSuspended();
* // Here you should re-enable the things that were disabled.
* }
*/
-void usbSleep();
+void usbSleep(void);
/*! usbSuspendMode: Direct access to this bit is provided for applications that
* need to use the P0 interrupt and want USB suspend mode to work. If you don't
@@ -279,7 +279,7 @@ extern volatile BIT usbSuspendMode;
*
* See #usbActivityFlag for more information on the flickering.
*/
-void usbShowStatusWithGreenLed();
+void usbShowStatusWithGreenLed(void);
/*! Libraries that directly access USB registers should set this bit to
* 1 whenever they read or write data from USB. This allows the
@@ -293,8 +293,9 @@ extern volatile BIT usbActivityFlag;
extern USB_DESCRIPTOR_DEVICE CODE usbDeviceDescriptor;
extern uint8 CODE usbStringDescriptorCount;
extern uint16 CODE * CODE usbStringDescriptors[];
-void usbCallbackSetupHandler();
-void usbCallbackInitEndpoints();
-void usbCallbackControlWriteHandler();
+void usbCallbackSetupHandler(void);
+void usbCallbackClassDescriptorHandler(void);
+void usbCallbackInitEndpoints(void);
+void usbCallbackControlWriteHandler(void);
#endif
View
145 libraries/include/usb_hid.h
@@ -0,0 +1,145 @@
+/*! \file usb_hid.h
+ * The <code>usb_hid.lib</code> library implements a composite USB device
+ * containing a keyboard interface and a mouse interface using the
+ * Human Interface Device (HID) class.
+ *
+ * You can find the specification of the USB HID device class in HID1_11.pdf,
+ * available for download from USB Implementers Forum at this url:
+ * http://www.usb.org/developers/hidpage
+ *
+ * A complete list of Usage tags used in HID reports, which define the format of
+ * the input and output data used by this library, can be found in Hut1_12.pdf
+ * on the same page.
+ *
+ * (A listing of all class specification documents is at
+ * http://www.usb.org/devclass_docs)
+ */
+
+#ifndef _USB_HID_H
+#define _USB_HID_H
+
+#include "usb_hid_constants.h"
+#include <cc2511_types.h>
+
+/*! \struct HID_KEYBOARD_OUT_REPORT
+ * This struct contains the \b output data sent in HID reports from the host to
+ * the \b keyboard interface.
+ * If the Wixel is connected to a Windows machine, you can use this struct to
+ * determine whether the Caps Lock, Num Lock, or Scroll Lock options are active.
+ * This might not work on Linux or Mac OS computers. */
+typedef struct HID_KEYBOARD_OUT_REPORT
+{
+ /*! Keyboard LED indicator data. Each bit contains the state of one
+ * indicator (1 = on, 0 = off), with the lowest bit representing Num Lock
+ * (usage ID 0x01) and the highest bit representing Do Not Disturb (usage ID
+ * 0x08) in the LED usage Page. See usb_hid_constants.h for the meaning
+ * of each bit. The keyboard's HID Report Descriptor is defined as
+ * <code>keyboardReportDescriptor</code> in usb_hid.c.
+ *
+ * Example usage:
+\code
+if (usbHidKeyboardOutput.leds & (1<<LED_CAPS_LOCK))
+{
+ // The Caps Lock LED is on.
+}
+\endcode
+ *
+ * This might not work on Linux or Mac OS computers.
+ */
+ uint8 leds;
+} HID_KEYBOARD_OUT_REPORT;
+
+/*! \struct HID_KEYBOARD_IN_REPORT
+ * This struct contains the \b input data sent in HID reports from the \b
+ * keyboard interface to the host. */
+typedef struct HID_KEYBOARD_IN_REPORT
+{
+ /*! Keyboard modifier key data: Each bit contains the state of one modifier
+ * key (1 = pressed, 0 = not pressed), with the lowest bit representing
+ * Left Control (usage ID 0xE0) and the highest bit representing Right GUI
+ * (usage ID 0xE7) in the Keyboard/Keypad usage page. See \ref
+ * usb_hid_constants.h for the meaning of each bit. The keyboard's HID
+ * Report Descriptor is defined as <code>keyboardReportDescriptor</code> in
+ * usb_hid.c. */
+ uint8 modifiers;
+ uint8 _reserved;
+ /*! Keyboard key code data: Each byte contains the key code of one key that
+ * is currently pressed (0 = no key). Up to 6 pressed keys at a time can be
+ * reported in this way. See \ref usb_hid_constants.h for possible key code
+ * values. The keyboard's HID Report Descriptor is defined as
+ * <code>keyboardReportDescriptor</code> in usb_hid.c. */
+ uint8 keyCodes[6];
+} HID_KEYBOARD_IN_REPORT;
+
+/*! \struct HID_MOUSE_IN_REPORT
+ * This struct contains the \b output data sent in HID reports from the host to
+ * the \b keyboard interface. */
+typedef struct HID_MOUSE_IN_REPORT
+{
+ /*! Mouse button data: Each bit contains the state of one button (1 =
+ * pressed, 0 = not pressed), with the lowest bit representing Button 1
+ * (usage ID 0x01) and the highest bit representing Button 8 (usage ID
+ * 0x08). Buttons 1, 2, and 3 usually correspond to the left, right, and
+ * middle buttons on a mouse, respectively. See \ref usb_hid_constants.h for
+ * the meaning of each bit. The mouse's HID Report Descriptor is defined as
+ * <code>mouseReportDescriptor</code> in usb_hid.c. */
+ uint8 buttons;
+ /*! Mouse X axis data: This byte contains an 8-bit signed value that
+ * represents a change (relative offset) in the horizontal position of the
+ * mouse cursor. */
+ int8 x;
+ /*! Mouse Y axis data: This byte contains an 8-bit signed value that
+ * represents a change (relative offset) in the vertical position of the
+ * mouse cursor. */
+ int8 y;
+ /*! Mouse wheel data: This byte contains an 8-bit signed value that
+ * represents a change (relative offset) in the position of the mouse wheel.
+ */
+ int8 wheel;
+} HID_MOUSE_IN_REPORT;
+
+/*! Contains \b output data received by the \b keyboard interface from the host.
+ * If the Wixel is connected to a Windows machine, you can use this variable to
+ * determine whether the Caps Lock, Num Lock, or Scroll Lock options are active.
+ * This might not work on Linux or Mac OS computers.
+ * See HID_KEYBOARD_OUT_REPORT for details. */
+extern HID_KEYBOARD_OUT_REPORT XDATA usbHidKeyboardOutput;
+
+/*! Contains \b input data to be sent from the \b keyboard interface to the host.
+ * You can use this variable to send key presses to the computer.
+ * After writing data to this struct, set #usbHidKeyboardInputUpdated to 1 to
+ * tell the HID library to send that data to the computer.
+ * See HID_KEYBOARD_IN_REPORT for details. */
+extern HID_KEYBOARD_IN_REPORT XDATA usbHidKeyboardInput;
+
+/*! Contains \b input data to be sent from the \b mouse interface to the host.
+ * You can use this variable to send X, Y and mouse wheel position changes to
+ * the computer and report the state of the mouse buttons.
+ * After writing data to this variable, set #usbHidMouseInputUpdated to 1 to
+ * tell the HID library to send that data to the computer.
+ * See HID_MOUSE_IN_REPORT for details. */
+extern HID_MOUSE_IN_REPORT XDATA usbHidMouseInput;
+
+/*! After writing data in #usbHidKeyboardInput, set this bit to trigger an HID
+ * report to be sent from the keyboard interface to the host. It is cleared
+ * by the library once the report is sent. */
+extern BIT usbHidKeyboardInputUpdated;
+
+/*! After writing data in #usbHidMouseInput, set this bit to trigger an HID
+ * report to be sent from the mouse interface to the host. It is cleared by the
+ * library once the report is sent. */
+extern BIT usbHidMouseInputUpdated;
+
+/*! This must be called regularly if you are implementing an HID device. */
+void usbHidService(void);
+
+/*! Converts an ASCII-encoded character in to the corresponding HID Key Code,
+ * suitable for the keyCodes array in HID_KEYBOARD_IN_REPORT.
+ * Note that many pairs of ASCII characters map to the same key code because
+ * they are on the same key.
+ * For example, both '4' and '$' map to 0x21 (KEY_4).
+ * To send a dollar sign to the computer, you must set the shift bit of the
+ * modifiers byte in the HID_KEYBOARD_IN_REPORT. */
+uint8 usbHidKeyCodeFromAsciiChar(char asciiChar);
+
+#endif
View
152 libraries/include/usb_hid_constants.h
@@ -0,0 +1,152 @@
+/*! \file usb_hid_constants.h
+ * This file contains definitions of constants used in HID reports sent by the
+ * <code>usb_hid.lib</code> library. These are Usage tags that are specified in
+ * in Hut1_12.pdf, available for download from USB Implementers Forum at this
+ * url:
+ * http://www.usb.org/developers/hidpage
+ */
+
+#ifndef USB_HID_CONSTANTS_H_
+#define USB_HID_CONSTANTS_H_
+
+// Bits in usbHidKeyboardOutput.leds
+#define LED_NUM_LOCK 0
+#define LED_CAPS_LOCK 1
+#define LED_SCROLL_LOCK 2
+#define LED_COMPOSE 3
+#define LED_KANA 4
+#define LED_POWER 5
+#define LED_SHIFT 6
+#define LED_DO_NOT_DISTURB 7
+
+// Bits in usbHidKeyboardInput.modifiers
+#define MODIFIER_CONTROL_LEFT 0
+#define MODIFIER_SHIFT_LEFT 1
+#define MODIFIER_ALT_LEFT 2
+#define MODIFIER_GUI_LEFT 3
+#define MODIFIER_CONTROL_RIGHT 4
+#define MODIFIER_SHIFT_RIGHT 5
+#define MODIFIER_ALT_RIGHT 6
+#define MODIFIER_GUI_RIGHT 7
+
+// Values for usbHidKeyboardInput.keyCodes
+// Only the key codes for common keys are defined here. See Hut1_12.pdf for a full list.
+#define KEY_NONE 0x00
+#define KEY_A 0x04
+#define KEY_B 0x05
+#define KEY_C 0x06
+#define KEY_D 0x07
+#define KEY_E 0x08
+#define KEY_F 0x09
+#define KEY_G 0x0A
+#define KEY_H 0x0B
+#define KEY_I 0x0C
+#define KEY_J 0x0D
+#define KEY_K 0x0E
+#define KEY_L 0x0F
+#define KEY_M 0x10
+#define KEY_N 0x11
+#define KEY_O 0x12
+#define KEY_P 0x13
+#define KEY_Q 0x14
+#define KEY_R 0x15
+#define KEY_S 0x16
+#define KEY_T 0x17
+#define KEY_U 0x18
+#define KEY_V 0x19
+#define KEY_W 0x1A
+#define KEY_X 0x1B
+#define KEY_Y 0x1C
+#define KEY_Z 0x1D
+#define KEY_1 0x1E
+#define KEY_2 0x1F
+#define KEY_3 0x20
+#define KEY_4 0x21
+#define KEY_5 0x22
+#define KEY_6 0x23
+#define KEY_7 0x24
+#define KEY_8 0x25
+#define KEY_9 0x26
+#define KEY_0 0x27
+#define KEY_RETURN 0x28
+#define KEY_ESCAPE 0x29
+#define KEY_BACKSPACE 0x2A
+#define KEY_TAB 0x2B
+#define KEY_SPACE 0x2C
+#define KEY_MINUS 0x2D
+#define KEY_EQUAL 0x2E
+#define KEY_BRACKET_LEFT 0x2F
+#define KEY_BRACKET_RIGHT 0x30
+#define KEY_BACKSLASH 0x31
+#define KEY_EUROPE_1 0x32
+#define KEY_SEMICOLON 0x33
+#define KEY_APOSTROPHE 0x34
+#define KEY_GRAVE 0x35
+#define KEY_COMMA 0x36
+#define KEY_PERIOD 0x37
+#define KEY_SLASH 0x38
+#define KEY_CAPS_LOCK 0x39
+#define KEY_F1 0x3A
+#define KEY_F2 0x3B
+#define KEY_F3 0x3C
+#define KEY_F4 0x3D
+#define KEY_F5 0x3E
+#define KEY_F6 0x3F
+#define KEY_F7 0x40
+#define KEY_F8 0x41
+#define KEY_F9 0x42
+#define KEY_F10 0x43
+#define KEY_F11 0x44
+#define KEY_F12 0x45
+#define KEY_PRINT_SCREEN 0x46
+#define KEY_SCROLL_LOCK 0x47
+#define KEY_PAUSE 0x48
+#define KEY_INSERT 0x49
+#define KEY_HOME 0x4A
+#define KEY_PAGE_UP 0x4B
+#define KEY_DELETE 0x4C
+#define KEY_END 0x4D
+#define KEY_PAGE_DOWN 0x4E
+#define KEY_ARROW_RIGHT 0x4F
+#define KEY_ARROW_LEFT 0x50
+#define KEY_ARROW_DOWN 0x51
+#define KEY_ARROW_UP 0x52
+#define KEY_NUM_LOCK 0x53
+#define KEY_KEYPAD_DIVIDE 0x54
+#define KEY_KEYPAD_MULTIPLY 0x55
+#define KEY_KEYPAD_SUBTRACT 0x56
+#define KEY_KEYPAD_ADD 0x57
+#define KEY_KEYPAD_ENTER 0x58
+#define KEY_KEYPAD_1 0x59
+#define KEY_KEYPAD_2 0x5A
+#define KEY_KEYPAD_3 0x5B
+#define KEY_KEYPAD_4 0x5C
+#define KEY_KEYPAD_5 0x5D
+#define KEY_KEYPAD_6 0x5E
+#define KEY_KEYPAD_7 0x5F
+#define KEY_KEYPAD_8 0x60
+#define KEY_KEYPAD_9 0x61
+#define KEY_KEYPAD_0 0x62
+#define KEY_KEYPAD_DECIMAL 0x63
+#define KEY_EUROPE_2 0x64
+#define KEY_APPLICATION 0x65
+#define KEY_POWER 0x66
+#define KEY_KEYPAD_EQUAL 0x67
+#define KEY_F13 0x68
+#define KEY_F14 0x69
+#define KEY_F15 0x6A
+#define KEY_CONTROL_LEFT 0xE0
+#define KEY_SHIFT_LEFT 0xE1
+#define KEY_ALT_LEFT 0xE2
+#define KEY_GUI_LEFT 0xE3
+#define KEY_CONTROL_RIGHT 0xE4
+#define KEY_SHIFT_RIGHT 0xE5
+#define KEY_ALT_RIGHT 0xE6
+#define KEY_GUI_RIGHT 0xE7
+
+// Bits in usbHidMouseInput.buttons
+#define MOUSE_BUTTON_LEFT 0
+#define MOUSE_BUTTON_RIGHT 1
+#define MOUSE_BUTTON_MIDDLE 2
+
+#endif /* USB_HID_CONSTANTS_H_ */
View
18 libraries/src/usb/usb.c
@@ -346,8 +346,15 @@ static void usbStandardDeviceRequestHandler()
}
default:
{
- // unknown type of descriptor
- return;
+ // see if the class recognizes the descriptor type; it should call usbControlRead if it does
+ usbCallbackClassDescriptorHandler();
+
+ if (controlTransferState == CONTROL_TRANSFER_STATE_NONE)
+ {
+ // unknown type of descriptor
+ return;
+ }
+ break;
}
}
@@ -413,6 +420,13 @@ static void usbStandardDeviceRequestHandler()
usbControlAcknowledge();
return;
}
+ case USB_REQUEST_GET_CONFIGURATION: // USB Spec 9.4.2 Get Configuration
+ {
+ // Assumption: there is only one configuration and its value is 1.
+ response[0] = (usbDeviceState == USB_STATE_CONFIGURED) ? 1 : 0;
+ usbControlRead(1, response);
+ return;
+ }
case USB_REQUEST_GET_INTERFACE: // USB Spec 9.4.4 Get Interface
{
// Assumption: the "alternate setting number" of each interface
View
5 libraries/src/usb_cdc_acm/usb_cdc_acm.c
@@ -268,6 +268,11 @@ void usbCallbackSetupHandler()
}
}
+void usbCallbackClassDescriptorHandler(void)
+{
+ // Not used by CDC ACM
+}
+
static void doNothing(void)
{
// Do nothing.
View
629 libraries/src/usb_hid/usb_hid.c
@@ -0,0 +1,629 @@
+// TODO: Add a function for converting chars to keycodes. The test_hid app
+// contains the start of such a function.
+// TODO: Don't use double-buffered USB endpoints. It just increases latency.
+
+#include <usb_hid.h>
+#include <usb.h>
+#include <board.h>
+#include <time.h>
+
+/* HID Library Configuration **************************************************/
+
+#define HID_DATA_ENDPOINT 1
+#define HID_IN_PACKET_SIZE 8
+#define HID_KEYBOARD_INTERFACE_NUMBER 0
+#define HID_MOUSE_INTERFACE_NUMBER 1
+
+#define HID_KEYBOARD_ENDPOINT 1
+#define HID_KEYBOARD_FIFO USBF1 // This must match HID_KEYBOARD_ENDPOINT!
+
+#define HID_MOUSE_ENDPOINT 2
+#define HID_MOUSE_FIFO USBF2 // This must match HID_MOUSE_ENDPOINT!
+
+/* HID Constants **************************************************************/
+
+// USB Class Code from HID 1.11 Section 4.1: The HID Class
+#define HID_CLASS 3
+
+// USB Subclass Code from HID 1.11 Section 4.2: Subclass
+#define HID_SUBCLASS_BOOT 1
+
+// USB Protocol Codes from HID 1.11 Section 4.3: Protocols
+#define HID_PROTOCOL_KEYBOARD 1
+#define HID_PROTOCOL_MOUSE 2
+
+// USB Descriptor types from HID 1.11 Section 7.1
+#define HID_DESCRIPTOR_TYPE_HID 0x21
+#define HID_DESCRIPTOR_TYPE_REPORT 0x22
+
+// Country Codes from HID 1.11 Section 6.2.1
+#define HID_COUNTRY_NOT_LOCALIZED 0
+
+// HID Report Items from HID 1.11 Section 6.2.2
+#define HID_USAGE_PAGE 0x05
+#define HID_USAGE 0x09
+#define HID_COLLECTION 0xA1
+#define HID_END_COLLECTION 0xC0
+#define HID_REPORT_COUNT 0x95
+#define HID_REPORT_SIZE 0x75
+#define HID_USAGE_MIN 0x19
+#define HID_USAGE_MAX 0x29
+#define HID_LOGICAL_MIN 0x15
+#define HID_LOGICAL_MAX 0x25
+#define HID_LOGICAL_MAX_2 0x26 // 2-byte data
+#define HID_INPUT 0x81
+#define HID_OUTPUT 0x91
+
+// HID Report Usage Pages from HID Usage Tables 1.12 Section 3, Table 1
+#define HID_USAGE_PAGE_GENERIC_DESKTOP 0x01
+#define HID_USAGE_PAGE_KEY_CODES 0x07
+#define HID_USAGE_PAGE_LEDS 0x08
+#define HID_USAGE_PAGE_BUTTONS 0x09
+
+// HID Report Usages from HID Usage Tables 1.12 Section 4, Table 6
+#define HID_USAGE_POINTER 0x01
+#define HID_USAGE_MOUSE 0x02
+#define HID_USAGE_KEYBOARD 0x06
+#define HID_USAGE_X 0x30
+#define HID_USAGE_Y 0x31
+#define HID_USAGE_WHEEL 0x38
+
+// HID Report Collection Types from HID 1.12 6.2.2.6
+#define HID_COLLECTION_PHYSICAL 0
+#define HID_COLLECTION_APPLICATION 1
+
+// HID Input/Output/Feature Item Data (attributes) from HID 1.11 6.2.2.5
+#define HID_ITEM_CONSTANT 0x1
+#define HID_ITEM_VARIABLE 0x2
+#define HID_ITEM_RELATIVE 0x4
+
+// Request Codes from HID 1.11 Section 7.2
+#define HID_REQUEST_GET_REPORT 0x1
+#define HID_REQUEST_GET_IDLE 0x2
+#define HID_REQUEST_GET_PROTOCOL 0x3
+#define HID_REQUEST_SET_REPORT 0x9
+#define HID_REQUEST_SET_IDLE 0xA
+#define HID_REQUEST_SET_PROTOCOL 0xB
+
+// Report Types from HID 1.11 Section 7.2.1
+#define HID_REPORT_TYPE_INPUT 1
+#define HID_REPORT_TYPE_OUTPUT 2
+#define HID_REPORT_TYPE_FEATURE 3
+
+// Protocols from HID 1.11 Section 7.2.5
+#define HID_PROTOCOL_BOOT 0
+#define HID_PROTOCOL_REPORT 1
+
+/* HID USB Descriptors ****************************************************/
+
+USB_DESCRIPTOR_DEVICE CODE usbDeviceDescriptor =
+{
+ sizeof(USB_DESCRIPTOR_DEVICE),
+ USB_DESCRIPTOR_TYPE_DEVICE,
+ 0x0200, // USB Spec Release Number in BCD format
+ 0, // Class Code: undefined (use class code info from Interface Descriptors)
+ 0, // Subclass code
+ 0, // Protocol
+ USB_EP0_PACKET_SIZE, // Max packet size for Endpoint 0
+ USB_VENDOR_ID_POLOLU, // Vendor ID
+ 0x2201, // Product ID
+ 0x0000, // Device release number in BCD format
+ 1, // Index of Manufacturer String Descriptor
+ 2, // Index of Product String Descriptor
+ 3, // Index of Serial Number String Descriptor
+ 1 // Number of possible configurations.
+};
+
+// keyboard report descriptor
+// HID 1.11 Section 6.2.2: Report Descriptor
+// Uses format compatible with keyboard boot interface report descriptor - see HID 1.11 Appendix B.1
+uint8 CODE keyboardReportDescriptor[]
+=
+{
+ HID_USAGE_PAGE, HID_USAGE_PAGE_GENERIC_DESKTOP,
+ HID_USAGE, HID_USAGE_KEYBOARD,
+ HID_COLLECTION, HID_COLLECTION_APPLICATION,
+
+ HID_REPORT_COUNT, 8, // 8 Modifier Keys
+ HID_REPORT_SIZE, 1,
+ HID_USAGE_PAGE, HID_USAGE_PAGE_KEY_CODES,
+ HID_USAGE_MIN, 0xE0, // Left Control
+ HID_USAGE_MAX, 0xE7, // Right GUI (Windows key) (highest defined usage ID)
+ HID_LOGICAL_MIN, 0,
+ HID_LOGICAL_MAX, 1,
+ HID_INPUT, HID_ITEM_VARIABLE,
+
+ HID_REPORT_COUNT, 1, // Reserved (1 byte)
+ HID_REPORT_SIZE, 8,
+ HID_INPUT, HID_ITEM_CONSTANT,
+
+ HID_REPORT_COUNT, 8, // 8 LEDs
+ HID_REPORT_SIZE, 1,
+ HID_USAGE_PAGE, HID_USAGE_PAGE_LEDS,
+ HID_USAGE_MIN, 0x1, // Num Lock
+ HID_USAGE_MAX, 0x8, // Do Not Disturb (TODO: use this as a bootloader signal?)
+ HID_OUTPUT, HID_ITEM_VARIABLE,
+
+ HID_REPORT_COUNT, 6, // 6 Key Codes
+ HID_REPORT_SIZE, 8,
+ HID_USAGE_PAGE, HID_USAGE_PAGE_KEY_CODES,
+ HID_USAGE_MIN, 0,
+ HID_USAGE_MAX, 231,
+ HID_LOGICAL_MIN, 0,
+ HID_LOGICAL_MAX_2, 231, 0, // Logical Maximum is signed, so we need to use an extra byte to make sure the highest bit is 0
+ HID_INPUT, 0,
+
+ HID_END_COLLECTION,
+};
+
+// mouse report descriptor
+// HID 1.11 Section 6.2.2: Report Descriptor
+// Uses format compatible with mouse boot interface report descriptor - see HID 1.11 Appendix B.2
+uint8 CODE mouseReportDescriptor[]
+=
+{
+ HID_USAGE_PAGE, HID_USAGE_PAGE_GENERIC_DESKTOP,
+ HID_USAGE, HID_USAGE_MOUSE,
+ HID_COLLECTION, HID_COLLECTION_APPLICATION,
+
+ HID_USAGE, HID_USAGE_POINTER,
+ HID_COLLECTION, HID_COLLECTION_PHYSICAL,
+
+ HID_REPORT_COUNT, 8, // 8 Mouse Buttons
+ HID_REPORT_SIZE, 1,
+ HID_USAGE_PAGE, HID_USAGE_PAGE_BUTTONS,
+ HID_USAGE_MIN, 1,
+ HID_USAGE_MAX, 8,
+ HID_LOGICAL_MIN, 0,
+ HID_LOGICAL_MAX, 1,
+ HID_INPUT, HID_ITEM_VARIABLE,
+
+ HID_REPORT_COUNT, 3, // 3 Axes (X, Y, wheel)
+ HID_REPORT_SIZE, 8,
+ HID_USAGE_PAGE, HID_USAGE_PAGE_GENERIC_DESKTOP,
+ HID_USAGE, HID_USAGE_X,
+ HID_USAGE, HID_USAGE_Y,
+ HID_USAGE, HID_USAGE_WHEEL,
+ HID_LOGICAL_MIN, -127,
+ HID_LOGICAL_MAX, 127,
+ HID_INPUT, (HID_ITEM_VARIABLE | HID_ITEM_RELATIVE),
+
+ HID_END_COLLECTION,
+
+ HID_END_COLLECTION,
+};
+
+CODE struct CONFIG1 {
+ USB_DESCRIPTOR_CONFIGURATION configuration;
+
+ USB_DESCRIPTOR_INTERFACE keyboard_interface;
+ uint8 keyboard_hid[9]; // HID Descriptor
+ USB_DESCRIPTOR_ENDPOINT keyboard_in;
+
+ USB_DESCRIPTOR_INTERFACE mouse_interface;
+ uint8 mouse_hid[9]; // HID Descriptor
+ USB_DESCRIPTOR_ENDPOINT mouse_in;
+} usbConfigurationDescriptor
+=
+{
+ { // Configuration Descriptor
+ sizeof(USB_DESCRIPTOR_CONFIGURATION),
+ USB_DESCRIPTOR_TYPE_CONFIGURATION,
+ sizeof(struct CONFIG1), // wTotalLength
+ 2, // bNumInterfaces
+ 1, // bConfigurationValue
+ 0, // iConfiguration
+ 0xC0, // bmAttributes: self powered (but may use bus power)
+ 50, // bMaxPower
+ },
+ { // Keyboard Interface
+ sizeof(USB_DESCRIPTOR_INTERFACE),
+ USB_DESCRIPTOR_TYPE_INTERFACE,
+ HID_KEYBOARD_INTERFACE_NUMBER, // bInterfaceNumber
+ 0, // bAlternateSetting
+ 1, // bNumEndpoints
+ HID_CLASS, // bInterfaceClass
+ HID_SUBCLASS_BOOT, // bInterfaceSubClass
+ HID_PROTOCOL_KEYBOARD, // bInterfaceProtocol
+ 4 // iInterface
+ },
+ {
+ sizeof(usbConfigurationDescriptor.keyboard_hid), // 9-byte HID Descriptor for keyboard (HID 1.11 Section 6.2.1)
+ HID_DESCRIPTOR_TYPE_HID,
+ 0x11, 0x01, // bcdHID. We conform to HID 1.11.
+ HID_COUNTRY_NOT_LOCALIZED, // bCountryCode
+ 1, // bNumDescriptors
+ HID_DESCRIPTOR_TYPE_REPORT, // bDescriptorType
+ sizeof(keyboardReportDescriptor), 0 // wDescriptorLength
+ },
+ { // Keyboard IN Endpoint
+ sizeof(USB_DESCRIPTOR_ENDPOINT),
+ USB_DESCRIPTOR_TYPE_ENDPOINT,
+ USB_ENDPOINT_ADDRESS_IN | HID_KEYBOARD_ENDPOINT, // bEndpointAddress
+ USB_TRANSFER_TYPE_INTERRUPT, // bmAttributes
+ HID_IN_PACKET_SIZE, // wMaxPacketSize
+ 10, // bInterval
+ },
+ { // Mouse Interface
+ sizeof(USB_DESCRIPTOR_INTERFACE),
+ USB_DESCRIPTOR_TYPE_INTERFACE,
+ HID_MOUSE_INTERFACE_NUMBER, // bInterfaceNumber
+ 0, // bAlternateSetting
+ 1, // bNumEndpoints
+ HID_CLASS, // bInterfaceClass
+ HID_SUBCLASS_BOOT, // bInterfaceSubClass
+ HID_PROTOCOL_MOUSE, // bInterfaceProtocol
+ 5 // iInterface
+ },
+ {
+ sizeof(usbConfigurationDescriptor.mouse_hid), // 9-byte HID Descriptor for mouse (HID 1.11 Section 6.2.1)
+ HID_DESCRIPTOR_TYPE_HID,
+ 0x11, 0x01, // bcdHID. We conform to HID 1.11.
+ HID_COUNTRY_NOT_LOCALIZED, // bCountryCode
+ 1, // bNumDescriptors
+ HID_DESCRIPTOR_TYPE_REPORT, // bDescriptorType
+ sizeof(mouseReportDescriptor), 0 // wDescriptorLength
+ },
+ { // Mouse IN Endpoint
+ sizeof(USB_DESCRIPTOR_ENDPOINT),
+ USB_DESCRIPTOR_TYPE_ENDPOINT,
+ USB_ENDPOINT_ADDRESS_IN | HID_MOUSE_ENDPOINT, // bEndpointAddress
+ USB_TRANSFER_TYPE_INTERRUPT, // bmAttributes
+ HID_IN_PACKET_SIZE, // wMaxPacketSize
+ 10, // bInterval
+ },
+};
+
+uint8 CODE usbStringDescriptorCount = 6;
+DEFINE_STRING_DESCRIPTOR(languages, 1, USB_LANGUAGE_EN_US)
+DEFINE_STRING_DESCRIPTOR(manufacturer, 18, 'P','o','l','o','l','u',' ','C','o','r','p','o','r','a','t','i','o','n')
+DEFINE_STRING_DESCRIPTOR(product, 5, 'W','i','x','e','l')
+DEFINE_STRING_DESCRIPTOR(keyboardName, 14, 'W','i','x','e','l',' ','K','e','y','b','o','a','r','d')
+DEFINE_STRING_DESCRIPTOR(mouseName, 11, 'W','i','x','e','l',' ','M','o','u','s','e')
+uint16 CODE * CODE usbStringDescriptors[] = { languages, manufacturer, product, serialNumberStringDescriptor, keyboardName, mouseName };
+
+/* HID structs and global variables *******************************************/
+
+HID_KEYBOARD_OUT_REPORT XDATA usbHidKeyboardOutput = {0};
+HID_KEYBOARD_IN_REPORT XDATA usbHidKeyboardInput = {0, 0, {0}};
+HID_MOUSE_IN_REPORT XDATA usbHidMouseInput = {0, 0, 0, 0};
+
+BIT usbHidKeyboardInputUpdated = 0;
+BIT usbHidMouseInputUpdated = 0;
+
+uint16 XDATA hidKeyboardIdleDuration = 500; // 0 to 1020 ms
+
+BIT hidKeyboardProtocol = HID_PROTOCOL_REPORT;
+BIT hidMouseProtocol = HID_PROTOCOL_REPORT;
+
+/* HID USB callbacks **********************************************************/
+// These functions are called by the low-level USB module (usb.c) when a USB
+// event happens that requires higher-level code to make a decision.
+
+void usbCallbackInitEndpoints(void)
+{
+ usbInitEndpointIn(HID_KEYBOARD_ENDPOINT, HID_IN_PACKET_SIZE);
+ usbInitEndpointIn(HID_MOUSE_ENDPOINT, HID_IN_PACKET_SIZE);
+}
+
+// Implements all the control transfers that are required by Appendix G of HID 1.11.
+void usbCallbackSetupHandler(void)
+{
+ static XDATA uint8 response;
+
+ if ((usbSetupPacket.bmRequestType & 0x7F) != 0x21) // Require Type==Class and Recipient==Interface.
+ return;
+
+ switch(usbSetupPacket.bRequest)
+ {
+ // required
+ case HID_REQUEST_GET_REPORT:
+ if ((usbSetupPacket.wValue >> 8) != HID_REPORT_TYPE_INPUT)
+ return;
+
+ switch (usbSetupPacket.wIndex)
+ {
+ case HID_KEYBOARD_INTERFACE_NUMBER:
+ usbControlRead(sizeof(usbHidKeyboardInput), (uint8 XDATA *)&usbHidKeyboardInput);
+ return;
+
+ case HID_MOUSE_INTERFACE_NUMBER:
+ usbControlRead(sizeof(usbHidMouseInput), (uint8 XDATA *)&usbHidMouseInput);
+ return;
+
+ default:
+ // unrecognized interface - stall
+ return;
+ }
+
+ // required for devices with Output reports
+ case HID_REQUEST_SET_REPORT:
+ if (usbSetupPacket.wIndex == HID_KEYBOARD_INTERFACE_NUMBER)
+ {
+ usbControlWrite(sizeof(usbHidKeyboardOutput), (uint8 XDATA *)&usbHidKeyboardOutput);
+ }
+ return;
+
+ // required for keyboards
+ case HID_REQUEST_GET_IDLE:
+ if (usbSetupPacket.wIndex == HID_KEYBOARD_INTERFACE_NUMBER)
+ {
+ response = hidKeyboardIdleDuration / 4; // value in request is in units of 4 ms
+ usbControlRead(1, (uint8 XDATA *)&response);
+ }
+ return;
+
+ // required for keyboards
+ case HID_REQUEST_SET_IDLE:
+ if (usbSetupPacket.wIndex == HID_KEYBOARD_INTERFACE_NUMBER)
+ {
+ hidKeyboardIdleDuration = (usbSetupPacket.wValue >> 8) * 4; // value in request is in units of 4 ms
+ usbControlAcknowledge();
+ }
+ return;
+
+
+ // required for boot devices
+ case HID_REQUEST_GET_PROTOCOL:
+ switch (usbSetupPacket.wIndex)
+ {
+ case HID_KEYBOARD_INTERFACE_NUMBER:
+ response = hidKeyboardProtocol;
+ usbControlRead(1, (uint8 XDATA *)&response);
+ return;
+
+ case HID_MOUSE_INTERFACE_NUMBER:
+ response = hidMouseProtocol;
+ usbControlRead(1, (uint8 XDATA *)&response);
+ return;
+
+ default:
+ // unrecognized interface - stall
+ return;
+ }
+
+ // required for boot devices
+ case HID_REQUEST_SET_PROTOCOL:
+ switch (usbSetupPacket.wIndex)
+ {
+ case HID_KEYBOARD_INTERFACE_NUMBER:
+ hidKeyboardProtocol = usbSetupPacket.wValue;
+ break;
+
+ case HID_MOUSE_INTERFACE_NUMBER:
+ hidMouseProtocol = usbSetupPacket.wValue;
+ break;
+
+ default:
+ // unrecognized interface - stall
+ return;
+ }
+ usbControlAcknowledge();
+ return;
+
+ default:
+ // unrecognized request - stall
+ return;
+ }
+}
+
+void usbCallbackClassDescriptorHandler(void)
+{
+ // Require Direction==Device-to-Host, Type==Standard, and Recipient==Interface. (HID 1.11 Section 7.1.1)
+ if (usbSetupPacket.bmRequestType != 0x81)
+ {
+ return;
+ }
+
+ switch (usbSetupPacket.wValue >> 8)
+ {
+ case HID_DESCRIPTOR_TYPE_HID:
+ // The host has requested the HID descriptor of a particular interface.
+ switch (usbSetupPacket.wIndex)
+ {
+ case HID_KEYBOARD_INTERFACE_NUMBER:
+ usbControlRead(sizeof(usbConfigurationDescriptor.keyboard_hid), (uint8 XDATA *)&usbConfigurationDescriptor.keyboard_hid);
+ return;
+
+ case HID_MOUSE_INTERFACE_NUMBER:
+ usbControlRead(sizeof(usbConfigurationDescriptor.mouse_hid), (uint8 XDATA *)&usbConfigurationDescriptor.mouse_hid);
+ return;
+ }
+ return;
+
+ case HID_DESCRIPTOR_TYPE_REPORT:
+ // The host has requested the Report Descriptor of a particular interface.
+ switch (usbSetupPacket.wIndex)
+ {
+ case HID_KEYBOARD_INTERFACE_NUMBER:
+ usbControlRead(sizeof(keyboardReportDescriptor), (uint8 XDATA *)&keyboardReportDescriptor);
+ return;
+
+ case HID_MOUSE_INTERFACE_NUMBER:
+ usbControlRead(sizeof(mouseReportDescriptor), (uint8 XDATA *)&mouseReportDescriptor);
+ return;
+ }
+ return;
+ }
+}
+
+void usbCallbackControlWriteHandler(void)
+{
+ // not used by usb_hid
+}
+
+/* Other HID Functions ********************************************************/
+
+void usbHidService(void)
+{
+ static uint16 XDATA hidKeyboardLastReportTime = 0;
+
+ usbPoll();
+
+ if (usbDeviceState != USB_STATE_CONFIGURED)
+ {
+ // We have not reached the Configured state yet, so we should not be touching the non-zero endpoints.
+ return;
+ }
+
+ USBINDEX = HID_KEYBOARD_ENDPOINT;
+ // Check if keyboard input has been updated OR if the idle period is nonzero and has expired.
+ if ((usbHidKeyboardInputUpdated || (hidKeyboardIdleDuration && ((uint16)(getMs() - hidKeyboardLastReportTime) > hidKeyboardIdleDuration))) && !(USBCSIL & USBCSIL_INPKT_RDY))
+ {
+ usbWriteFifo(HID_KEYBOARD_ENDPOINT, sizeof(usbHidKeyboardInput), (uint8 XDATA *)&usbHidKeyboardInput);
+ USBCSIL |= USBCSIL_INPKT_RDY;
+ usbHidKeyboardInputUpdated = 0; // reset updated flag
+ hidKeyboardLastReportTime = getMs();
+ }
+
+ USBINDEX = HID_MOUSE_ENDPOINT;
+ // Check if mouse input has been updated.
+ if (usbHidMouseInputUpdated && !(USBCSIL & USBCSIL_INPKT_RDY)) {
+ usbWriteFifo(HID_MOUSE_ENDPOINT, sizeof(usbHidMouseInput), (uint8 XDATA *)&usbHidMouseInput);
+ USBCSIL |= USBCSIL_INPKT_RDY;
+ usbHidMouseInputUpdated = 0; // reset updated flag
+ }
+}
+
+// Look-up table stored in code memory that we use to convert from ASCII
+// characters to HID key codes.
+uint8 CODE hidKeyCode[128] =
+{
+ 0, // 0x00 Null
+ 0, // 0x01
+ 0, // 0x02
+ 0, // 0x03
+ 0, // 0x04
+ 0, // 0x05
+ 0, // 0x06
+ 0, // 0x07
+ KEY_BACKSPACE, // 0x08 Backspace
+ KEY_TAB, // 0x09 Horizontal Tab
+ KEY_RETURN, // 0x0A Line Feed
+ 0, // 0x0B
+ 0, // 0x0C
+ KEY_RETURN, // 0x0D Carriage return
+ 0, // 0x0E
+ 0, // 0x0F
+ 0, // 0x10
+ 0, // 0x11
+ 0, // 0x12
+ 0, // 0x13
+ 0, // 0x14
+ 0, // 0x15
+ 0, // 0x16
+ 0, // 0x17
+ 0, // 0x18
+ 0, // 0x19
+ 0, // 0x1A
+ KEY_ESCAPE, // 0x1B Escape
+ 0, // 0x1C
+ 0, // 0x1D
+ 0, // 0x1E
+ 0, // 0x1F
+
+ KEY_SPACE, // 0x20
+ KEY_1, // 0x21 !
+ KEY_APOSTROPHE, // 0x22 "
+ KEY_3, // 0x23 #
+ KEY_4, // 0x24 $
+ KEY_5, // 0x25 %
+ KEY_7, // 0x26 &
+ KEY_APOSTROPHE, // 0x27 '
+ KEY_9, // 0x28 (
+ KEY_0, // 0x29 )
+ KEY_8, // 0x2A *
+ KEY_EQUAL, // 0x2B +
+ KEY_COMMA, // 0x2C ,
+ KEY_MINUS, // 0x2D -
+ KEY_PERIOD, // 0x2E .
+ KEY_SLASH, // 0x2F /
+ KEY_0, // 0x30 0
+ KEY_1, // 0x31 1
+ KEY_2, // 0x32 2
+ KEY_3, // 0x33 3
+ KEY_4, // 0x34 4
+ KEY_5, // 0x35 5
+ KEY_6, // 0x36 6
+ KEY_7, // 0x37 7
+ KEY_8, // 0x38 8
+ KEY_9, // 0x39 9
+ KEY_SEMICOLON, // 0x3A :
+ KEY_SEMICOLON, // 0x3B ;
+ KEY_COMMA, // 0x3C <
+ KEY_EQUAL, // 0x3D =
+ KEY_PERIOD, // 0x3E >
+ KEY_SLASH, // 0x3F ?
+
+ KEY_3, // 0x40 @
+ KEY_A, // 0x41 A
+ KEY_B, // 0x42 B
+ KEY_C, // 0x43 C
+ KEY_D, // 0x44 D
+ KEY_E, // 0x45 E
+ KEY_F, // 0x46 F
+ KEY_G, // 0x47 G
+ KEY_H, // 0x48 H
+ KEY_I, // 0x49 I
+ KEY_J, // 0x4A J
+ KEY_K, // 0x4B K
+ KEY_L, // 0x4C L
+ KEY_M, // 0x4D M
+ KEY_N, // 0x4E N
+ KEY_O, // 0x4F O
+ KEY_P, // 0x50 P
+ KEY_Q, // 0x51 Q
+ KEY_R, // 0x52 R
+ KEY_S, // 0x53 S
+ KEY_T, // 0x55 T
+ KEY_U, // 0x55 U
+ KEY_V, // 0x56 V
+ KEY_W, // 0x57 W
+ KEY_X, // 0x58 X
+ KEY_Y, // 0x59 Y
+ KEY_Z, // 0x5A Z
+ KEY_BRACKET_LEFT, // 0x5B [
+ KEY_BACKSLASH, // 0x5C '\'
+ KEY_BRACKET_RIGHT, // 0x5D ]
+ KEY_6, // 0x5E ^
+ KEY_MINUS, // 0x5F _
+
+ KEY_GRAVE, // 0x60 `
+ KEY_A, // 0x61 a
+ KEY_B, // 0x62 b
+ KEY_C, // 0x63 c
+ KEY_D, // 0x66 d
+ KEY_E, // 0x65 e
+ KEY_F, // 0x66 f
+ KEY_G, // 0x67 g
+ KEY_H, // 0x68 h
+ KEY_I, // 0x69 i
+ KEY_J, // 0x6A j
+ KEY_K, // 0x6B k
+ KEY_L, // 0x6C l
+ KEY_M, // 0x6D m
+ KEY_N, // 0x6E n
+ KEY_O, // 0x6F o
+ KEY_P, // 0x70 p
+ KEY_Q, // 0x71 q
+ KEY_R, // 0x72 r
+ KEY_S, // 0x73 s
+ KEY_T, // 0x75 t
+ KEY_U, // 0x75 u
+ KEY_V, // 0x76 v
+ KEY_W, // 0x77 w
+ KEY_X, // 0x78 x
+ KEY_Y, // 0x79 y
+ KEY_Z, // 0x7A z
+ KEY_BRACKET_LEFT, // 0x7B {
+ KEY_BACKSLASH, // 0x7C |
+ KEY_BRACKET_RIGHT, // 0x7D }
+ KEY_GRAVE, // 0x7E ~
+ KEY_DELETE // 0x7F Delete
+};
+
+uint8 usbHidKeyCodeFromAsciiChar(char asciiChar)
+{
+ if (asciiChar & 0x80){ return 0; }
+ return hidKeyCode[asciiChar];
+}
View
1  options.mk
@@ -0,0 +1 @@
+APP_LIBS := dma.lib usb.lib usb_hid.lib wixel.lib adc.lib gpio.lib
Please sign in to comment.
Something went wrong with that request. Please try again.