diff --git a/apps/hid_keyboard/.gitignore b/apps/hid_keyboard/.gitignore
new file mode 100644
index 0000000..e0622e2
--- /dev/null
+++ b/apps/hid_keyboard/.gitignore
@@ -0,0 +1,8 @@
+MPLAB.X/nbproject/Makefile-genesis.properties
+MPLAB.X/nbproject/Makefile-*.mk
+MPLAB.X/nbproject/Package-*.bash
+MPLAB.X/nbproject/private/
+MPLAB.X/build/
+MPLAB.X/dist
+MPLAB.X/funclist
+MPLAB.X/disassembly/
diff --git a/apps/hid_keyboard/MPLAB.X/Makefile b/apps/hid_keyboard/MPLAB.X/Makefile
new file mode 100644
index 0000000..05a3fb1
--- /dev/null
+++ b/apps/hid_keyboard/MPLAB.X/Makefile
@@ -0,0 +1,108 @@
+#
+# There exist several targets which are by default empty and which can be
+# used for execution of your targets. These targets are usually executed
+# before and after some main targets. They are:
+#
+# .build-pre: called before 'build' target
+# .build-post: called after 'build' target
+# .clean-pre: called before 'clean' target
+# .clean-post: called after 'clean' target
+# .clobber-pre: called before 'clobber' target
+# .clobber-post: called after 'clobber' target
+# .all-pre: called before 'all' target
+# .all-post: called after 'all' target
+# .help-pre: called before 'help' target
+# .help-post: called after 'help' target
+#
+# Targets beginning with '.' are not intended to be called on their own.
+#
+# Main targets can be executed directly, and they are:
+#
+# build build a specific configuration
+# clean remove built files from a configuration
+# clobber remove all built files
+# all build all configurations
+# help print help mesage
+#
+# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
+# .help-impl are implemented in nbproject/makefile-impl.mk.
+#
+# Available make variables:
+#
+# CND_BASEDIR base directory for relative paths
+# CND_DISTDIR default top distribution directory (build artifacts)
+# CND_BUILDDIR default top build directory (object files, ...)
+# CONF name of current configuration
+# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration)
+# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration)
+# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration)
+# CND_PACKAGE_DIR_${CONF} directory of package (current configuration)
+# CND_PACKAGE_NAME_${CONF} name of package (current configuration)
+# CND_PACKAGE_PATH_${CONF} path to package (current configuration)
+#
+# NOCDDL
+
+
+# Environment
+MKDIR=mkdir
+CP=cp
+CCADMIN=CCadmin
+RANLIB=ranlib
+
+
+# build
+build: .build-post
+
+.build-pre:
+# Add your pre 'build' code here...
+
+.build-post: .build-impl
+# Add your post 'build' code here...
+
+
+# clean
+clean: .clean-post
+
+.clean-pre:
+# Add your pre 'clean' code here...
+
+.clean-post: .clean-impl
+# Add your post 'clean' code here...
+
+
+# clobber
+clobber: .clobber-post
+
+.clobber-pre:
+# Add your pre 'clobber' code here...
+
+.clobber-post: .clobber-impl
+# Add your post 'clobber' code here...
+
+
+# all
+all: .all-post
+
+.all-pre:
+# Add your pre 'all' code here...
+
+.all-post: .all-impl
+# Add your post 'all' code here...
+
+
+# help
+help: .help-post
+
+.help-pre:
+# Add your pre 'help' code here...
+
+.help-post: .help-impl
+# Add your post 'help' code here...
+
+
+
+# include project implementation makefile
+include nbproject/Makefile-impl.mk
+
+# include project make variables
+include nbproject/Makefile-variables.mk
diff --git a/apps/hid_keyboard/MPLAB.X/nbproject/configurations.xml b/apps/hid_keyboard/MPLAB.X/nbproject/configurations.xml
new file mode 100644
index 0000000..bf06841
--- /dev/null
+++ b/apps/hid_keyboard/MPLAB.X/nbproject/configurations.xml
@@ -0,0 +1,851 @@
+
+
+
+
+
+
+ ../../bootloader/firmware/gld/pic24fj64gb002-bootloader.gld
+ ../../bootloader/firmware/gld/pic24fj256da206-bootloader.gld
+
+
+
+ ../../../usb/src/usb.c
+ ../../../usb/include/usb.h
+ ../../../usb/src/usb_hal.h
+ ../../../usb/include/usb_ch9.h
+ ../../../usb/src/usb_hid.c
+ ../../../usb/include/usb_hid.h
+
+ ../usb_descriptors.c
+ ../main.c
+ ../usb_config.h
+
+
+ Makefile
+
+
+
+ ../../bootloader/firmware/gld
+ ../../../usb/src
+ ../../../usb/include
+
+ Makefile
+
+
+
+ localhost
+ PIC24FJ64GB002
+
+
+ ICD3PlatformTool
+ XC16
+ 1.11
+ 2
+
+
+
+
+
+
+
+ false
+
+
+
+
+ false
+
+ false
+
+ false
+ false
+ false
+
+ -
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ localhost
+ PIC24FJ64GB002
+
+
+ ICD3PlatformTool
+ XC16
+ 1.11
+ 2
+
+
+
+
+
+
+
+ false
+
+
+
+
+ false
+
+ false
+
+ false
+ false
+ false
+
+ -
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ localhost
+ PIC24FJ256DA206
+
+
+ ICD3PlatformTool
+ XC16
+ 1.11
+ 2
+
+
+
+
+
+
+
+ false
+
+
+
+
+ false
+
+ false
+
+ false
+ false
+ false
+
+ -
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ localhost
+ PIC24FJ256DA206
+
+
+ ICD3PlatformTool
+ XC16
+ 1.11
+ 2
+
+
+
+
+
+
+
+ false
+
+
+
+
+ false
+
+ false
+
+ false
+ false
+ false
+
+ -
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ localhost
+ PIC18F46J50
+
+
+ SKDEPIC18FJPlatformTool
+ XC8
+ 1.12
+ 2
+
+
+
+
+
+
+
+ false
+
+
+
+
+ false
+
+ false
+
+ false
+ false
+ false
+
+ -
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ localhost
+ PIC16F1459
+
+
+ PICkit3PlatformTool
+ XC8
+ 1.12
+ 2
+
+
+
+
+
+
+
+ false
+
+
+
+
+ false
+
+ false
+
+ false
+ false
+ false
+
+ -
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ localhost
+ PIC32MX460F512L
+
+
+ SKDEPIC32PlatformTool
+ XC32
+ 1.21
+ 2
+
+
+
+
+
+
+
+ false
+
+
+
+
+ false
+
+ false
+
+ false
+ false
+ false
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/hid_keyboard/MPLAB.X/nbproject/project.xml b/apps/hid_keyboard/MPLAB.X/nbproject/project.xml
new file mode 100644
index 0000000..9610953
--- /dev/null
+++ b/apps/hid_keyboard/MPLAB.X/nbproject/project.xml
@@ -0,0 +1,17 @@
+
+
+ com.microchip.mplab.nbide.embedded.makeproject
+
+
+ usb_stack_hid_keyboard_demo
+ d62999b6-148b-4401-bb2b-d1fe2348676c
+ 0
+ c
+
+ h
+ ISO-8859-1
+
+
+
+
+
diff --git a/apps/hid_keyboard/main.c b/apps/hid_keyboard/main.c
new file mode 100644
index 0000000..d0efb76
--- /dev/null
+++ b/apps/hid_keyboard/main.c
@@ -0,0 +1,310 @@
+/*
+ * USB HID Keyboard
+ *
+ * This file may be used by anyone for any purpose and may be used as a
+ * starting point making your own application using M-Stack.
+ *
+ * It is worth noting that M-Stack itself is not under the same license as
+ * this file.
+ *
+ * M-Stack is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. For details, see sections 7, 8, and 9
+ * of the Apache License, version 2.0 which apply to this file. If you have
+ * purchased a commercial license for this software from Signal 11 Software,
+ * your commerical license superceeds the information in this header.
+ *
+ * Alan Ott
+ * Signal 11 Software
+ * 2013-08-13
+ */
+
+#include "usb.h"
+#include
+#include
+#include "usb_config.h"
+#include "usb_ch9.h"
+#include "usb_hid.h"
+
+#ifdef __PIC32MX__
+ #include
+#endif
+
+#ifdef __PIC24FJ64GB002__
+_CONFIG1(WDTPS_PS16 & FWPSA_PR32 & WINDIS_OFF & FWDTEN_OFF & ICS_PGx1 & GWRP_OFF & GCP_OFF & JTAGEN_OFF)
+_CONFIG2(POSCMOD_NONE & I2C1SEL_PRI & IOL1WAY_OFF & OSCIOFNC_OFF & FCKSM_CSDCMD & FNOSC_FRCPLL & PLL96MHZ_ON & PLLDIV_NODIV & IESO_OFF)
+_CONFIG3(WPFP_WPFP0 & SOSCSEL_IO & WUTSEL_LEG & WPDIS_WPDIS & WPCFG_WPCFGDIS & WPEND_WPENDMEM)
+_CONFIG4(DSWDTPS_DSWDTPS3 & DSWDTOSC_SOSC & RTCOSC_SOSC & DSBOREN_OFF & DSWDTEN_OFF)
+
+#elif __PIC24FJ256DA206__
+_CONFIG1(WDTPS_PS32768 & FWPSA_PR128 & WINDIS_OFF & FWDTEN_OFF & ICS_PGx2 & GWRP_OFF & GCP_OFF & JTAGEN_OFF)
+_CONFIG2(POSCMOD_NONE & IOL1WAY_OFF & OSCIOFNC_ON & FCKSM_CSECMD & FNOSC_FRCPLL & PLL96MHZ_ON & PLLDIV_NODIV & IESO_OFF)
+_CONFIG3(WPFP_WPFP255 & SOSCSEL_SOSC & WUTSEL_LEG & ALTPMP_ALPMPDIS & WPDIS_WPDIS & WPCFG_WPCFGDIS & WPEND_WPENDMEM)
+
+#elif _18F46J50
+#pragma config PLLDIV = 3 /* 3 = Divide by 3. 12MHz crystal => 4MHz */
+#pragma config XINST = OFF
+#pragma config WDTEN = OFF
+#pragma config CPUDIV = OSC1
+#pragma config IESO = OFF
+#pragma config FCMEN = OFF
+#pragma config LPT1OSC = OFF
+#pragma config T1DIG = ON
+#pragma config OSC = ECPLL
+#pragma config DSWDTEN = OFF
+#pragma config IOL1WAY = OFF
+#pragma config WPDIS = OFF /* This pragma seems backwards */
+
+#elif _16F1459
+#pragma config FOSC = INTOSC
+#pragma config WDTE = OFF
+#pragma config PWRTE = OFF
+#pragma config MCLRE = ON
+#pragma config CP = OFF
+#pragma config BOREN = ON
+#pragma config CLKOUTEN = OFF
+#pragma config IESO = OFF
+#pragma config FCMEN = OFF
+#pragma config WRT = OFF
+#pragma config CPUDIV = NOCLKDIV
+#pragma config USBLSCLK = 48MHz
+#pragma config PLLMULT = 3x
+#pragma config PLLEN = ENABLED
+#pragma config STVREN = ON
+#pragma config BORV = LO
+#pragma config LPBOR = ON
+#pragma config LVP = OFF
+
+#elif __32MX460F512L__
+#pragma config DEBUG = OFF, ICESEL = ICS_PGx2, PWP = OFF, BWP = OFF, CP = OFF
+#pragma config FNOSC = PRIPLL, FSOSCEN = OFF, IESO = OFF, POSCMOD = HS, \
+ OSCIOFNC = OFF, FPBDIV = DIV_1, FCKSM = CSDCMD, WDTPS = PS1, \
+ FWDTEN = OFF
+#pragma config FPLLIDIV = DIV_2, FPLLMUL = MUL_15, UPLLIDIV = DIV_2, \
+ UPLLEN = ON, FPLLODIV = DIV_1
+
+#else
+ #error "Config flags for your device not defined"
+
+#endif
+
+#ifdef MULTI_CLASS_DEVICE
+static uint8_t hid_interfaces[] = { 0 };
+#endif
+
+int main(void)
+{
+#if defined(__PIC24FJ64GB002__) || defined(__PIC24FJ256DA206__)
+ unsigned int pll_startup_counter = 600;
+ CLKDIVbits.PLLEN = 1;
+ while(pll_startup_counter--);
+#elif _18F46J50
+ unsigned int pll_startup = 600;
+ OSCTUNEbits.PLLEN = 1;
+ while (pll_startup--)
+ ;
+#elif _16F1459
+ OSCCONbits.IRCF = 0b1111; /* 0b1111 = 16MHz HFINTOSC postscalar */
+
+ /* Enable Active clock-tuning from the USB */
+ ACTCONbits.ACTSRC = 1; /* 1=USB */
+ ACTCONbits.ACTEN = 1;
+#elif __32MX460F512L__
+ SYSTEMConfigPerformance(80000000);
+#endif
+
+
+/* Configure interrupts, per architecture */
+#ifdef USB_USE_INTERRUPTS
+ #if defined (_PIC18) || defined(_PIC14E)
+ INTCONbits.PEIE = 1;
+ INTCONbits.GIE = 1;
+ #elif __PIC32MX__
+ INTCONbits.MVEC = 1; /* Multi-vector interrupts */
+ IPC11bits.USBIP = 4; /* Interrupt priority, must set to != 0. */
+ __asm volatile("ei");
+ #endif
+#endif
+
+#ifdef MULTI_CLASS_DEVICE
+ hid_set_interface_list(hid_interfaces, sizeof(hid_interfaces));
+#endif
+ usb_init();
+
+ /* Setup keyboard keypress movement. This implementation sends back data
+ * for every IN packet.
+ */
+ uint8_t button = 0;
+
+ while (1) {
+ if (usb_is_configured() &&
+ !usb_in_endpoint_halted(1) &&
+ !usb_in_endpoint_busy(1)) {
+
+ unsigned char *buf = usb_get_in_buffer(1);
+
+ if(PORTAbits.RA3 != button){
+ button = PORTAbits.RA3;
+ buf[0] = (!button?0x03:0x00); // modifier (shift+ctrl)
+ buf[1] = 0x00; // reserved
+ buf[2] = (!button?0x1e:0x00); // key (1)
+ buf[3] = 0x00;
+ buf[4] = 0x00;
+ buf[5] = 0x00;
+ buf[6] = 0x00;
+ buf[7] = 0x00;
+ }
+ usb_send_in_buffer(1, 8);
+ }
+
+ #ifndef USB_USE_INTERRUPTS
+ usb_service();
+ #endif
+ }
+
+ return 0;
+}
+
+/* Callbacks. These function names are set in usb_config.h. */
+void app_set_configuration_callback(uint8_t configuration)
+{
+
+}
+
+uint16_t app_get_device_status_callback()
+{
+ return 0x0000;
+}
+
+void app_endpoint_halt_callback(uint8_t endpoint, bool halted)
+{
+
+}
+
+int8_t app_set_interface_callback(uint8_t interface, uint8_t alt_setting)
+{
+ return 0;
+}
+
+int8_t app_get_interface_callback(uint8_t interface)
+{
+ return 0;
+}
+
+void app_out_transaction_callback(uint8_t endpoint)
+{
+
+}
+
+void app_in_transaction_complete_callback(uint8_t endpoint)
+{
+
+}
+
+int8_t app_unknown_setup_request_callback(const struct setup_packet *setup)
+{
+ /* To use the HID device class, have a handler for unknown setup
+ * requests and call process_hid_setup_request() (as shown here),
+ * which will check if the setup request is HID-related, and will
+ * call the HID application callbacks defined in usb_hid.h. For
+ * composite devices containing other device classes, make sure
+ * MULTI_CLASS_DEVICE is defined in usb_config.h and call all
+ * appropriate device class setup request functions here.
+ */
+ return process_hid_setup_request(setup);
+}
+
+int16_t app_unknown_get_descriptor_callback(const struct setup_packet *pkt, const void **descriptor)
+{
+ return -1;
+}
+
+void app_start_of_frame_callback(void)
+{
+
+}
+
+void app_usb_reset_callback(void)
+{
+
+}
+
+/* HID Callbacks. See usb_hid.h for documentation. */
+
+static uint8_t report_buf[3];
+
+static void get_report_callback(bool transfer_ok, void *context)
+{
+ /* Nothing to do here really. It either succeeded or failed. If it
+ * failed, the host will ask for it again. It's nice to be on the
+ * device side in USB. */
+}
+
+int16_t app_get_report_callback(uint8_t interface, uint8_t report_type,
+ uint8_t report_id, const void **report,
+ usb_ep0_data_stage_callback *callback,
+ void **context)
+{
+ /* This isn't a composite device, so there's no need to check the
+ * interface here. Also, we know that there's only one report for
+ * this device, so there's no need to check report_type or report_id.
+ *
+ * Set report, callback, and context; and the USB stack will send
+ * the report, calling our callback (get_report_callback()) when
+ * it has finished.
+ */
+ *report = report_buf;
+ *callback = get_report_callback;
+ *context = NULL;
+ return sizeof(report_buf);
+}
+
+int8_t app_set_report_callback(uint8_t interface, uint8_t report_type,
+ uint8_t report_id)
+{
+ /* To handle Set_Report, call usb_start_receive_ep0_data_stage()
+ * here. See the documentation for HID_SET_REPORT_CALLBACK() in
+ * usb_hid.h. For this device though, there are no output or
+ * feature reports. */
+ return -1;
+}
+
+uint8_t app_get_idle_callback(uint8_t interface, uint8_t report_id)
+{
+ return 0;
+}
+
+int8_t app_set_idle_callback(uint8_t interface, uint8_t report_id,
+ uint8_t idle_rate)
+{
+ return -1;
+}
+
+int8_t app_get_protocol_callback(uint8_t interface)
+{
+ return 1;
+}
+
+int8_t app_set_protocol_callback(uint8_t interface, uint8_t report_id)
+{
+ return -1;
+}
+
+
+#ifdef _PIC14E
+void interrupt isr()
+{
+ usb_service();
+}
+#elif _PIC18
+
+#ifdef __XC8
+void interrupt high_priority isr()
+{
+ usb_service();
+}
+#elif _PICC18
+#error need to make ISR
+#endif
+
+#endif
diff --git a/apps/hid_keyboard/usb_config.h b/apps/hid_keyboard/usb_config.h
new file mode 100644
index 0000000..528acb2
--- /dev/null
+++ b/apps/hid_keyboard/usb_config.h
@@ -0,0 +1,101 @@
+/*
+ * USB HID Keyboard Configuration
+ *
+ * This file may be used by anyone for any purpose and may be used as a
+ * starting point making your own application using M-Stack.
+ *
+ * It is worth noting that M-Stack itself is not under the same license
+ * as this file.
+ *
+ * M-Stack is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. For details, see sections 7, 8, and 9
+ * of the Apache License, version 2.0 which apply to this file. If you have
+ * purchased a commercial license for this software from Signal 11 Software,
+ * your commerical license superceeds the information in this header.
+ *
+ * Alan Ott
+ * Signal 11 Software
+ * 2013-04-08
+ */
+
+#ifndef USB_CONFIG_H__
+#define USB_CONFIG_H__
+
+/* Number of endpoint numbers besides endpoint zero. It's worth noting that
+ and endpoint NUMBER does not completely describe an endpoint, but the
+ along with the DIRECTION does (eg: EP 1 IN). The #define below turns on
+ BOTH IN and OUT endpoints for endpoint numbers (besides zero) up to the
+ value specified. For example, setting NUM_ENDPOINT_NUMBERS to 2 will
+ activate endpoints EP 1 IN, EP 1 OUT, EP 2 IN, EP 2 OUT. */
+#define NUM_ENDPOINT_NUMBERS 1
+
+/* Only 8, 16, 32 and 64 are supported for endpoint zero length. */
+#define EP_0_LEN 8
+
+#define EP_1_OUT_LEN 8
+#define EP_1_IN_LEN 8
+
+#define NUMBER_OF_CONFIGURATIONS 1
+
+/* Ping-pong buffering mode. Valid values are:
+ PPB_NONE - Do not ping-pong any endpoints
+ PPB_EPO_OUT_ONLY - Ping-pong only endpoint 0 OUT
+ PPB_ALL - Ping-pong all endpoints
+ PPB_EPN_ONLY - Ping-pong all endpoints except 0
+*/
+#ifdef __PIC32MX__
+ /* PIC32MX only supports PPB_ALL */
+ #define PPB_MODE PPB_ALL
+#else
+ #define PPB_MODE PPB_NONE
+#endif
+
+/* Comment the following line to use polling USB operation. When using polling,
+ You are responsible for calling usb_service() periodically from your
+ application. */
+#define USB_USE_INTERRUPTS
+
+/* Uncomment if you have a composite device which has multiple different types
+ * of device classes. For example a device which has HID+CDC or
+ * HID+VendorDefined, but not a device which has multiple of the same class
+ * (such as HID+HID). Device class implementations have additional requirements
+ * for multi-class devices. See the documentation for each device class for
+ * details. */
+//#define MULTI_CLASS_DEVICE
+
+
+/* Objects from usb_descriptors.c */
+#define USB_DEVICE_DESCRIPTOR this_device_descriptor
+#define USB_CONFIG_DESCRIPTOR_MAP usb_application_config_descs
+#define USB_STRING_DESCRIPTOR_FUNC usb_application_get_string
+
+/* Optional callbacks from usb.c. Leave them commented if you don't want to
+ use them. For the prototypes and documentation for each one, see usb.h. */
+
+#define SET_CONFIGURATION_CALLBACK app_set_configuration_callback
+#define GET_DEVICE_STATUS_CALLBACK app_get_device_status_callback
+#define ENDPOINT_HALT_CALLBACK app_endpoint_halt_callback
+#define SET_INTERFACE_CALLBACK app_set_interface_callback
+#define GET_INTERFACE_CALLBACK app_get_interface_callback
+#define OUT_TRANSACTION_CALLBACK app_out_transaction_callback
+#define IN_TRANSACTION_COMPLETE_CALLBACK app_in_transaction_complete_callback
+#define UNKNOWN_SETUP_REQUEST_CALLBACK app_unknown_setup_request_callback
+#define UNKNOWN_GET_DESCRIPTOR_CALLBACK app_unknown_get_descriptor_callback
+#define START_OF_FRAME_CALLBACK app_start_of_frame_callback
+#define USB_RESET_CALLBACK app_usb_reset_callback
+
+/* HID Configuration functions. See usb_hid.h for documentation. */
+#define USB_HID_DESCRIPTOR_FUNC usb_application_get_hid_descriptor
+#define USB_HID_REPORT_DESCRIPTOR_FUNC usb_application_get_hid_report_descriptor
+//#define USB_HID_PHYSICAL_DESCRIPTOR_FUNC usb_application_get_hid_physical_descriptor
+
+/* HID Callbacks. See usb_hid.h for documentation. */
+#define HID_GET_REPORT_CALLBACK app_get_report_callback
+#define HID_SET_REPORT_CALLBACK app_set_report_callback
+#define HID_GET_IDLE_CALLBACK app_get_idle_callback
+#define HID_SET_IDLE_CALLBACK app_set_idle_callback
+#define HID_GET_PROTOCOL_CALLBACK app_get_protocol_callback
+#define HID_SET_PROTOCOL_CALLBACK app_set_protocol_callback
+
+#endif /* USB_CONFIG_H__ */
diff --git a/apps/hid_keyboard/usb_descriptors.c b/apps/hid_keyboard/usb_descriptors.c
new file mode 100644
index 0000000..b11ad1a
--- /dev/null
+++ b/apps/hid_keyboard/usb_descriptors.c
@@ -0,0 +1,300 @@
+/*
+ * USB Descriptors file
+ *
+ * This file may be used by anyone for any purpose and may be used as a
+ * starting point making your own application using M-Stack.
+ *
+ * It is worth noting that M-Stack itself is not under the same license as
+ * this file.
+ *
+ * M-Stack is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. For details, see sections 7, 8, and 9
+ * of the Apache License, version 2.0 which apply to this file. If you have
+ * purchased a commercial license for this software from Signal 11 Software,
+ * your commerical license superceeds the information in this header.
+ *
+ * Alan Ott
+ * Signal 11 Software
+ */
+
+#include "usb_config.h"
+#include "usb.h"
+#include "usb_ch9.h"
+#include "usb_hid.h"
+
+#ifdef __C18
+#define ROMPTR rom
+#else
+#define ROMPTR
+#endif
+
+/* Configuration Packet
+ *
+ * This packet contains a configuration descriptor, one or more interface
+ * descriptors, class descriptors(optional), and endpoint descriptors for a
+ * single configuration of the device. This struct is specific to the
+ * device, so the application will need to add any interfaces, classes and
+ * endpoints it intends to use. It is sent to the host in response to a
+ * GET_DESCRIPTOR[CONFIGURATION] request.
+ *
+ * While Most devices will only have one configuration, a device can have as
+ * many configurations as it needs. To have more than one, simply make as
+ * many of these structs as are required, one for each configuration.
+ *
+ * An instance of each configuration packet must be put in the
+ * usb_application_config_descs[] array below (which is #defined in
+ * usb_config.h) so that the USB stack can find it.
+ *
+ * See Chapter 9 of the USB specification from usb.org for details.
+ *
+ * It's worth noting that adding endpoints here does not automatically
+ * enable them in the USB stack. To use an endpoint, it must be declared
+ * here and also in usb_config.h.
+ *
+ * The configuration packet below is for the keyboard demo application.
+ * Yours will of course vary.
+ */
+struct configuration_1_packet {
+ struct configuration_descriptor config;
+ struct interface_descriptor interface;
+ struct hid_descriptor hid;
+ struct endpoint_descriptor ep;
+ struct endpoint_descriptor ep1_out;
+};
+
+
+/* Device Descriptor
+ *
+ * Each device has a single device descriptor describing the device. The
+ * format is described in Chapter 9 of the USB specification from usb.org.
+ * USB_DEVICE_DESCRIPTOR needs to be defined to the name of this object in
+ * usb_config.h. For more information, see USB_DEVICE_DESCRIPTOR in usb.h.
+ */
+const ROMPTR struct device_descriptor this_device_descriptor =
+{
+ sizeof(struct device_descriptor), // bLength
+ DESC_DEVICE, // bDescriptorType
+ 0x0200, // 0x0200 = USB 2.0, 0x0110 = USB 1.1
+ 0x00, // Device class
+ 0x00, // Device Subclass
+ 0x00, // Protocol.
+ EP_0_LEN, // bMaxPacketSize0
+ 0xA0A0, // Vendor
+ 0x0003, // Product
+ 0x0001, // device release (1.0)
+ 1, // Manufacturer
+ 2, // Product
+ 0, // Serial
+ NUMBER_OF_CONFIGURATIONS // NumConfigurations
+};
+
+/* HID Report descriptor. See the HID specification for more deatils. This
+ * is the keyboard example from the "HID Descriptor Tool" which can be downloaded
+ * from USB.org. */
+static const ROMPTR uint8_t keyboard_report_descriptor[] = {
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x06, // USAGE (Keyboard)
+ 0xa1, 0x01, // COLLECTION (Application)
+ 0x05, 0x07, // USAGE_PAGE (Keyboard)
+ 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
+ 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x25, 0x01, // LOGICAL_MAXIMUM (1)
+ 0x75, 0x01, // REPORT_SIZE (1)
+ 0x95, 0x08, // REPORT_COUNT (8)
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x81, 0x03, // INPUT (Cnst,Var,Abs)
+ 0x95, 0x05, // REPORT_COUNT (5)
+ 0x75, 0x01, // REPORT_SIZE (1)
+ 0x05, 0x08, // USAGE_PAGE (LEDs)
+ 0x19, 0x01, // USAGE_MINIMUM (Num Lock)
+ 0x29, 0x05, // USAGE_MAXIMUM (Kana)
+ 0x91, 0x02, // OUTPUT (Data,Var,Abs)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x75, 0x03, // REPORT_SIZE (3)
+ 0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
+ 0x95, 0x06, // REPORT_COUNT (6)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x25, 0x65, // LOGICAL_MAXIMUM (101)
+ 0x05, 0x07, // USAGE_PAGE (Keyboard)
+ 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
+ 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
+ 0x81, 0x00, // INPUT (Data,Ary,Abs)
+ 0xc0 // END_COLLECTION
+};
+
+/* Configuration Packet Instance
+ *
+ * This is an instance of the configuration_packet struct containing all the
+ * data describing a single configuration of this device. It is wise to use
+ * as much C here as possible, such as sizeof() operators, and #defines from
+ * usb_config.h. When stuff is wrong here, it can be difficult to track
+ * down exactly why, so it's good to get the compiler to do as much of it
+ * for you as it can.
+ */
+static const ROMPTR struct configuration_1_packet configuration_1 =
+{
+ {
+ // Members from struct configuration_descriptor
+ sizeof(struct configuration_descriptor),
+ DESC_CONFIGURATION,
+ sizeof(configuration_1), // wTotalLength (length of the whole packet)
+ 1, // bNumInterfaces
+ 1, // bConfigurationValue
+ 2, // iConfiguration (index of string descriptor)
+ 0b10000000,
+ 100/2, // 100/2 indicates 100mA
+ },
+
+ {
+ // Members from struct interface_descriptor
+ sizeof(struct interface_descriptor), // bLength;
+ DESC_INTERFACE,
+ 0x0, // InterfaceNumber
+ 0x0, // AlternateSetting
+ 0x2, // bNumEndpoints (num besides endpoint 0)
+ HID_INTERFACE_CLASS, // bInterfaceClass 3=HID, 0xFF=VendorDefined
+ 0x00, // bInterfaceSubclass (0=NoBootInterface for HID)
+ 0x00, // bInterfaceProtocol
+ 0x02, // iInterface (index of string describing interface)
+ },
+
+ {
+ // Members from struct hid_descriptor
+ sizeof(struct hid_descriptor),
+ DESC_HID,
+ 0x0101, // bcdHID
+ 0x0, // bCountryCode
+ 1, // bNumDescriptors
+ DESC_REPORT, // bDescriptorType2
+ sizeof(keyboard_report_descriptor), // wDescriptorLength
+ },
+
+ {
+ // Members of the Endpoint Descriptor (EP1 IN)
+ sizeof(struct endpoint_descriptor),
+ DESC_ENDPOINT,
+ 0x01 | 0x80, // endpoint #1 0x80=IN
+ EP_INTERRUPT, // bmAttributes
+ EP_1_IN_LEN, // wMaxPacketSize
+ 1, // bInterval in ms.
+ },
+
+ {
+ // Members of the Endpoint Descriptor (EP1 OUT)
+ sizeof(struct endpoint_descriptor),
+ DESC_ENDPOINT,
+ 0x01 /*| 0x00*/, // endpoint #1 0x00=OUT
+ EP_INTERRUPT, // bmAttributes
+ EP_1_OUT_LEN, // wMaxPacketSize
+ 1, // bInterval in ms.
+ },
+};
+
+/* String Descriptors
+ *
+ * String descriptors are optional. If strings are used, string #0 is
+ * required, and must contain the language ID of the other strings. See
+ * Chapter 9 of the USB specification from usb.org for more info.
+ *
+ * Strings are UTF-16 Unicode, and are not NULL-terminated, hence the
+ * unusual syntax.
+ */
+
+/* String index 0, only has one character in it, which is to be set to the
+ language ID of the language which the other strings are in. */
+static const ROMPTR struct {uint8_t bLength;uint8_t bDescriptorType; uint16_t lang; } str00 = {
+ sizeof(str00),
+ DESC_STRING,
+ 0x0409 // US English
+};
+
+static const ROMPTR struct {uint8_t bLength;uint8_t bDescriptorType; uint16_t chars[23]; } vendor_string = {
+ sizeof(vendor_string),
+ DESC_STRING,
+ {'S','i','g','n','a','l',' ','1','1',' ','S','o','f','t','w','a','r','e',' ','L','L','C','.'}
+};
+
+static const ROMPTR struct {uint8_t bLength;uint8_t bDescriptorType; uint16_t chars[17]; } product_string = {
+ sizeof(product_string),
+ DESC_STRING,
+ {'U','S','B',' ','K','e','y','b','o','a','r','d',' ','D','e','m','o'}
+};
+
+static const ROMPTR struct {uint8_t bLength;uint8_t bDescriptorType; uint16_t chars[11]; } interface_string = {
+ sizeof(interface_string),
+ DESC_STRING,
+ {'I','n','t','e','r','f','a','c','e',' ','1'}
+};
+
+/* Get String function
+ *
+ * This function is called by the USB stack to get a pointer to a string
+ * descriptor. If using strings, USB_STRING_DESCRIPTOR_FUNC must be defined
+ * to the name of this function in usb_config.h. See
+ * USB_STRING_DESCRIPTOR_FUNC in usb.h for information about this function.
+ * This is a function, and not simply a list or map, because it is useful,
+ * and advisable, to have a serial number string which may be read from
+ * EEPROM or somewhere that's not part of static program memory.
+ */
+int16_t usb_application_get_string(uint8_t string_number, const void **ptr)
+{
+ if (string_number == 0) {
+ *ptr = &str00;
+ return sizeof(str00);
+ }
+ else if (string_number == 1) {
+ *ptr = &vendor_string;
+ return sizeof(vendor_string);
+ }
+ else if (string_number == 2) {
+ *ptr = &product_string;
+ return sizeof(product_string);
+ }
+ else if (string_number == 3) {
+ /* This is where you might have code to do something like read
+ a serial number out of EEPROM and return it. */
+ return -1;
+ }
+
+ return -1;
+}
+
+/* Configuration Descriptor List
+ *
+ * This is the list of pointters to the device's configuration descriptors.
+ * The USB stack will read this array looking for descriptors which are
+ * requsted from the host. USB_CONFIG_DESCRIPTOR_MAP must be defined to the
+ * name of this array in usb_config.h. See USB_CONFIG_DESCRIPTOR_MAP in
+ * usb.h for information about this array. The order of the descriptors is
+ * not important, as the USB stack reads bConfigurationValue for each
+ * descriptor to know its index. Make sure NUMBER_OF_CONFIGURATIONS in
+ * usb_config.h matches the number of descriptors in this array.
+ */
+const struct configuration_descriptor *usb_application_config_descs[] =
+{
+ (struct configuration_descriptor*) &configuration_1,
+};
+STATIC_SIZE_CHECK_EQUAL(USB_ARRAYLEN(USB_CONFIG_DESCRIPTOR_MAP), NUMBER_OF_CONFIGURATIONS);
+STATIC_SIZE_CHECK_EQUAL(sizeof(USB_DEVICE_DESCRIPTOR), 18);
+
+/* HID Descriptor Function */
+int16_t usb_application_get_hid_descriptor(uint8_t interface, const void **ptr)
+{
+ /* Only one interface in this demo. The two-step assignment avoids an
+ * incorrect error in XC8 on PIC16. */
+ const void *p = &configuration_1.hid;
+ *ptr = p;
+ return sizeof(configuration_1.hid);
+}
+
+/** HID Report Descriptor Function */
+int16_t usb_application_get_hid_report_descriptor(uint8_t interface, const void **ptr)
+{
+ *ptr = keyboard_report_descriptor;
+ return sizeof(keyboard_report_descriptor);
+}