From 3061ecca3d0fdfb87dabbf5f63c9e06c2a30f53a Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Thu, 23 Aug 2018 17:08:59 +0200 Subject: o Initial import. --- .../main_mouse_keyboard_emulator.c | 417 +++++++++++++++++++++ 1 file changed, 417 insertions(+) create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/examples/proprietary_rf/gzll/gzp_desktop_emulator/main_mouse_keyboard_emulator.c (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/examples/proprietary_rf/gzll/gzp_desktop_emulator/main_mouse_keyboard_emulator.c') diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/examples/proprietary_rf/gzll/gzp_desktop_emulator/main_mouse_keyboard_emulator.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/examples/proprietary_rf/gzll/gzp_desktop_emulator/main_mouse_keyboard_emulator.c new file mode 100644 index 0000000..b3eb994 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/examples/proprietary_rf/gzll/gzp_desktop_emulator/main_mouse_keyboard_emulator.c @@ -0,0 +1,417 @@ +/** + * Copyright (c) 2012 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * This project can be used as a starting point for developing a nRF5x series + * mouse or keyboard using Gazell for communicating with a legacy nRF24LU1 + * USB dongle. It can communicate "out of the box" with the + * Dongle reference design and the nRFreadySimplePairing.exe application, + * that can be found in the nRFready Desktop v1.2.3. + * + * This project sends mouse movement packets to the USB dongle when pin 1 + * is low (button connected to pin 1 pressed) and sends the 'a' keyboard + * character to the USB dongle when pin 2 goes from high to low (button + * connected to pin 2 pressed). + */ + +#include +#include "nrf_gzll.h" +#include "nrf_gzp.h" +#include "bsp.h" +#include "nordic_common.h" +#include "nrf_gzllde_params.h" +#include "mouse_sensor_emulator.h" +#include "keyboard_emulator.h" +#include "nrf_gzll_error.h" + + +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +#include "nrf_log_default_backends.h" + +/*****************************************************************************/ +/** @name Configuration */ +/*****************************************************************************/ +#define SEND_KEYBOARD_DATA_BUTTON_ID 0 ///< GPIO pin for reading from a button to emulate a keypress. +#define SEND_MOUSE_DATA_BUTTON_ID 1 ///< GPIO pin for reading from a button to emulate a mouse movement. + + +/*****************************************************************************/ +/** @name Static (internal) functions. */ +/*****************************************************************************/ + +/** + * Checks to see whether the mouse sensor has data to send. If so, adds this + * to the (unencrypted) Gazell TX FIFO on pipe NRFR_MOUSE_EP. + */ +static void read_mouse_and_send(void); + + +/** + * Checks to see whether the mouse sensor has data and send unencrypted. + * + * If so, adds this to the (unencrypted) Gazell TX FIFO on pipe NRFR_MOUSE_EP. + */ + +/** + * Checks to see whether the keyboard has data and send encrypted. + * + * If the Device does net yet have the system address it will try to + * obtain it. After obtaining the system address it will attempt to obtain + * the Host ID. + * The keyboard data is discarded if pairing is not successful. + * It may take a few attempts to obtain the Host ID as this may not be + * yet generated at the Host. + */ +static void read_keyboard_and_send(void); + +/** + * Send a Host ID request and process the response. + * + * If the request was rejected or failed (i.e. timed out), system_addr_received + * will be reset and the pairing process will begin on the next keypress. + * + * If the request was received, subsequent keyboard data will be transmitted + * on an encrypted link. + * + * If teh request is still pending, nothing is done. Further keypresses + * will initiate another + * + * @return The result of the Host ID request. + */ +static gzp_id_req_res_t send_host_id_req(void); +/** @} */ + +static void error_report(void); + +static bool host_id_received = false; ///< Host ID received. +static bool system_addr_received = false; ///< System address receivedfrom Host. +static bool dyn_key_ok = false; ///< Dynamic key is up to date. + +static bool prev_host_id_received = true; ///< Host ID received. +static bool prev_system_addr_received = true; ///< System address receivedfrom Host. +static bool prev_dyn_key_ok = true; ///< Dynamic key is up to date. + + +/*****************************************************************************/ +/** + * @brief Main function. + * + * @return ANSI required int return type. + */ +/*****************************************************************************/ + + +int main() +{ + bool result_value = false; + uint32_t err_code; + +// lint -save -e514 Unusual use of a boolean expression (use of &= assignment). + + UNUSED_VARIABLE(bsp_init(BSP_INIT_BUTTONS, NULL)); + + err_code = NRF_LOG_INIT(NULL); + APP_ERROR_CHECK(err_code); + + NRF_LOG_DEFAULT_BACKENDS_INIT(); + + NRF_LOG_INFO("Desktop emulator example"); + NRF_LOG_FLUSH(); + + // Initialize and enable "mouse sensor" + result_value = mouse_sensor_init(MOUSE_SENSOR_SAMPLE_PERIOD_8_MS); + APP_ERROR_CHECK_BOOL(result_value); + + mouse_sensor_enable(); + + // Initialize and enable Gazell + result_value = nrf_gzll_init(NRF_GZLL_MODE_DEVICE); + GAZELLE_ERROR_CODE_CHECK(result_value); + + // Ensure Gazell parameters are configured. + nrf_gzll_set_max_tx_attempts(150); + + result_value = nrf_gzll_set_device_channel_selection_policy( + NRF_GZLLDE_DEVICE_CHANNEL_SELECTION_POLICY); + GAZELLE_ERROR_CODE_CHECK(result_value); + + result_value = nrf_gzll_set_timeslot_period(NRF_GZLLDE_RXPERIOD_DIV_2); + GAZELLE_ERROR_CODE_CHECK(result_value); + + result_value = nrf_gzll_set_sync_lifetime(0); // Asynchronous mode, more efficient for pairing. + GAZELLE_ERROR_CODE_CHECK(result_value); + + switch (gzp_get_pairing_status()) + { + case -2: + host_id_received = false; + system_addr_received = false; + break; + + case -1: + host_id_received = false; + system_addr_received = true; + break; + + default: + host_id_received = true; + system_addr_received = true; + } + + gzp_init(); + + result_value = nrf_gzll_enable(); + GAZELLE_ERROR_CODE_CHECK(result_value); + + while (1) + { + // If BUTTON_SEND_MOUSE_DATA button is pressed. + if ( bsp_button_is_pressed(SEND_MOUSE_DATA_BUTTON_ID)) + { + read_mouse_and_send(); + } + + // If BUTTON_SEND_KEYBOARD_DATA button is pressed + if (bsp_button_is_pressed(SEND_KEYBOARD_DATA_BUTTON_ID)) + { + read_keyboard_and_send(); + } + + error_report(); + + } +// lint -restore +} + + +void mouse_sensor_new_sample_generated_cb() +{ + /* + This callback is called every time the mouse sensor + generates a new sample. We could select to add mouse packets to the + TX FIFO here. + */ +} + + +static void read_mouse_and_send(void) +{ +// lint -save -e514 Unusual use of a boolean expression (use of &= assignment). + bool mouse_send_ok; + + // If the "mouse sensor" has data ready for read-out. + if (mouse_sensor_data_is_ready()) + { + uint8_t mouse_packet[NRFR_MOUSE_MOV_PACKET_LENGTH]; + + // Get packet from "mouse sensor". + if (mouse_sensor_read(mouse_packet)) + { + // Wait in case the FIFOs are full. + while (!nrf_gzll_ok_to_add_packet_to_tx_fifo(NRFR_MOUSE_EP)) + ; + + // Add mouse packet to the mouse pipe's TX FIFO. + mouse_send_ok = nrf_gzll_add_packet_to_tx_fifo(NRFR_MOUSE_EP, + mouse_packet, + NRFR_MOUSE_MOV_PACKET_LENGTH); + if (mouse_send_ok) + { + NRF_LOG_INFO("Mouse sent OK"); + } + else + { + NRF_LOG_INFO("Mouse sent FAILED"); + } + + NRF_LOG_FLUSH(); + } + } + + +// lint -restore +} + + +static void read_keyboard_and_send(void) +{ + uint8_t keyboard_packet[NRFR_KEYBOARD_PACKET_LENGTH]; + + // "Scan" keyboard. + keyboard_get_non_empty_packet(keyboard_packet); + + // Send address request if required. + if (!host_id_received && !system_addr_received) + { + system_addr_received = gzp_address_req_send(); + } + + /* Send Host ID request if required. This may take a few attempts + * as the Host may require some time to generate the Host ID. */ + if (!host_id_received && system_addr_received ) + { + while (send_host_id_req() == GZP_ID_RESP_PENDING) + ; + } + + /* After receiving the Host ID we send one packet in order + * to update the dynamic key. + */ + if (host_id_received && !dyn_key_ok) + { + bool keyboard_send_ok = true; + keyboard_send_ok = gzp_crypt_data_send(keyboard_packet, + NRFR_KEYBOARD_PACKET_LENGTH); + + if (!keyboard_send_ok) + { + host_id_received = false; + } + else + { + dyn_key_ok = true; + } + } + + /* If we have the Host ID and dynamic key we can transmit encrypted data. + */ + if (host_id_received && dyn_key_ok) + { + bool keyboard_send_ok = true; + keyboard_send_ok = gzp_crypt_data_send(keyboard_packet, + NRFR_KEYBOARD_PACKET_LENGTH); + + if (keyboard_send_ok) + { + NRF_LOG_INFO("Keyboard sent OK"); + } + else + { + NRF_LOG_INFO("Keyboard sent FAILED"); + } + + if (keyboard_send_ok) + { + // Wait until button is released. + while (bsp_button_is_pressed(SEND_KEYBOARD_DATA_BUTTON_ID)) + { + } + + // Send empty keyboard packet to release all keys. + keyboard_get_empty_packet(keyboard_packet); + keyboard_send_ok = gzp_crypt_data_send(keyboard_packet, NRFR_KEYBOARD_PACKET_LENGTH); + } + + if (!keyboard_send_ok) + { + dyn_key_ok = false; + } + + NRF_LOG_FLUSH(); + } + +} + + +static gzp_id_req_res_t send_host_id_req(void) +{ + gzp_id_req_res_t id_resp; + + // Try sending "Host ID" request + id_resp = gzp_id_req_send(); + + switch (id_resp) + { + case GZP_ID_RESP_REJECTED: + case GZP_ID_RESP_FAILED: + host_id_received = false; + system_addr_received = false; + break; + + case GZP_ID_RESP_GRANTED: + host_id_received = true; + system_addr_received = true; + break; + + case GZP_ID_RESP_PENDING: + default: + break; + } + + return id_resp; +} + + +static void error_report(void) +{ + if (~system_addr_received & prev_system_addr_received) + { + prev_system_addr_received = false; + NRF_LOG_INFO("System address not received"); + } + else if (system_addr_received) + { + prev_system_addr_received = true; + } + + if (~host_id_received & prev_host_id_received) + { + prev_host_id_received = false; + NRF_LOG_INFO("Host ID not received"); + } + else if (host_id_received) + { + prev_host_id_received = true; + } + + if (~dyn_key_ok & prev_dyn_key_ok) + { + prev_dyn_key_ok = false; + NRF_LOG_INFO("Dyn Key not received"); + } + else if (dyn_key_ok) + { + prev_dyn_key_ok = true; + } + + NRF_LOG_FLUSH(); +} + + -- cgit v1.2.3