I try to integrate Mult-touch(touch screen) and Keyboard feature in a single program, when I run this program, the phone side(Android8.0 based) can only receive Mult-touch information, it always can't get the key value at all.
my question is:
- is it possible to integrate Mult-touch and Keyboard feature in a single program based on a single 51822 board?
- if it's feasible, could you please to give some suggestions to implement it?
some developing detail is as follows:
Softdevice: s130_nrf51_2.0.1_softdevice.hex
SDK: nRF5_SDK_12.2.0_f012efa
HW: nRF51 DK
report_map_data[ ] = {
// ------ MULT_TOUCH_SUPPORT-----
0x05, 0x0D, // USAGE_PAGE(Digitizers)
0x09, 0x04, // USAGE (Touch Screen)
0xA1, 0x01, // COLLECTION(Application)
// define the maximum amount of fingers that the device supports
0x09, 0x55, // USAGE(Contact Count Maximum)
0x25, 0x02, // LOGICAL_MAXIMUM (2)
0xB1, 0x02, // FEATURE (Data,Var,Abs)
0x85, 0x01, // Report Id 1
// define the actual amount of fingers that are concurrently touching the screen
0x09, 0x54, // USAGE (Contact count)
0x95, 0x01, // REPORT_COUNT(1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
// declare a finger collection
0x09, 0x22, // USAGE (Finger)
0xA1, 0x02, // COLLECTION (Logical)
// declare an identifier for the finger
0x09, 0x51, // USAGE (Contact Identifier) //touch ID
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
// declare Tip Switch and In Range
0x09, 0x42, // USAGE (Tip Switch)
0x09, 0x32, // USAGE (In Range)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x02, // REPORT_COUNT(2)
0x81, 0x02, // INPUT (Data,Var,Abs)
// declare the remaining 6 bits of the first data byte as constant -> the driver will ignore them
0x95, 0x06, // REPORT_COUNT (6)
0x81, 0x03, // INPUT (Cnst,Ary,Abs)
// define absolute X and Y coordinates of 16 bit each (percent values multiplied with 100)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x16, 0x00, 0x00, // Logical Minimum (0)
0x26, 0x10, 0x27, // Logical Maximum (10000)
0x36, 0x00, 0x00, // Physical Minimum (0)
0x46, 0x10, 0x27, // Physical Maximum (10000)
0x66, 0x00, 0x00, // UNIT (None)
0x75, 0x10, // Report Size (16),
0x95, 0x02, // Report Count (2),
0x81, 0x02, // Input (Data,Var,Abs)
0xC0, // END_COLLECTION
// declare a finger collection
0xA1, 0x02, // COLLECTION (Logical)
0x05, 0x0D, // USAGE_PAGE(Digitizers)
// declare an identifier for the finger
0x09, 0x51, // USAGE (Contact Identifier) // touch ID
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
// declare Tip Switch and In Range
0x09, 0x42, // USAGE (Tip Switch)
0x09, 0x32, // USAGE (In Range)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x02, // REPORT_COUNT(2)
0x81, 0x02, // INPUT (Data,Var,Abs)
// declare the remaining 6 bits of the first data byte as constant -> the driver will ignore them
0x95, 0x06, // REPORT_COUNT (6)
0x81, 0x03, // INPUT (Cnst,Ary,Abs)
// define absolute X and Y coordinates of 16 bit each (percent values multiplied with 100)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x16, 0x00, 0x00, // Logical Minimum (0)
0x26, 0x10, 0x27, // Logical Maximum (10000)
0x36, 0x00, 0x00, // Physical Minimum (0)
0x46, 0x10, 0x27, // Physical Maximum (10000)
0x66, 0x00, 0x00, // UNIT (None)
0x75, 0x10, // Report Size (16),
0x95, 0x02, // Report Count (2),
0x81, 0x02, // Input (Data,Var,Abs)
0xC0, // END_COLLECTION
0xC0, // END_COLLECTION
// With this declaration a data packet must be sent as:
// byte 1 -> "contact count" (always == 1)
// byte 2 -> "contact identifier" (any value)
// byte 3 -> "Tip Switch" state (bit 0 = Tip Switch up/down, bit 1 = In Range)
// byte 4,5 -> absolute X coordinate (0...10000)
// byte 6,7 -> absolute Y coordinate (0...10000)
// byte 8 -> "contact identifier" (any value)
// byte 9 -> "Tip Switch" state (bit 0 = Tip Switch up/down, bit 1 = In Range)
// byte 10, 11 -> absolute X coordinate (0...10000)
// byte 12,13 -> absolute Y coordinate (0...10000)
// ------ KEYBOARD_SUPPORT-----
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x06, // Usage (Keyboard)
0xA1, 0x01, // Collection (Application)
0x85, 0x02, // Report ID 2
0x05, 0x07, // Usage Page (Key Codes)
0x19, 0xe0, // Usage Minimum (224)
0x29, 0xe7, // Usage Maximum (231)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x08, // Report Count (8)
0x81, 0x02, // Input (Data, Variable, Absolute)
0x95, 0x01, // Report Count (1)
0x75, 0x08, // Report Size (8)
0x81, 0x01, // Input (Constant) reserved byte(1)
0x95, 0x05, // Report Count (5)
0x75, 0x01, // Report Size (1)
0x05, 0x08, // Usage Page (Page# for LEDs)
0x19, 0x01, // Usage Minimum (1)
0x29, 0x05, // Usage Maximum (5)
0x91, 0x02, // Output (Data, Variable, Absolute), Led report
0x95, 0x01, // Report Count (1)
0x75, 0x03, // Report Size (3)
0x91, 0x01, // Output (Data, Variable, Absolute), Led report padding
0x95, 0x06, // Report Count (6)
0x75, 0x08, // Report Size (8)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x65, // Logical Maximum (101)
0x05, 0x07, // Usage Page (Key codes)
0x19, 0x00, // Usage Minimum (0)
0x29, 0x65, // Usage Maximum (101)
0x81, 0x00, // Input (Data, Array) Key array(6 bytes)
0x09, 0x05, // Usage (Vendor Defined)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Count (2)
0x95, 0x02, // Report Size (8 bit)
0xB1, 0x02, // Feature (Data, Variable, Absolute)
0xC0 // End Collection (Application)
};
I have verified report map data of Mult-touch and Keyboard separately, they are functional.
1. send Mult-touch information with the below code
static void mouse_moveto_2xy(uint8_t value,uint16_t x_delta,uint16_t y_delta,
uint16_t x2_delta,uint16_t y2_delta)
{
// With this declaration a data packet must be sent as:
// byte 1 -> "contact count" (always == 1)
// byte 2 -> "contact identifier" (any value)
// byte 3 -> "Tip Switch" state (bit 0 = Tip Switch up/down, bit 1 = In Range)
// byte 4,5 -> absolute X coordinate (0...10000)
// byte 6,7 -> absolute Y coordinate (0...10000)
uint8_t buffer[INPUT_REP_TOUCH_LEN];
uint32_t err_code;
APP_ERROR_CHECK_BOOL(INPUT_REP_TOUCH_LEN == 13);
x_delta = MIN(x_delta, 0x2710);
y_delta = MIN(y_delta, 0x2710);
buffer[0] = CONTACT_COUNT;
buffer[1] = 1;
buffer[2] = value;
buffer[3] = x_delta & 0x00ff;
buffer[4] = (x_delta>>8)&0x00ff;
buffer[5] = y_delta & 0x00ff;
buffer[6] = (y_delta>>8)&0x00ff;
buffer[7] = 2;
buffer[8] = value;
buffer[9] = x2_delta & 0x00ff;
buffer[10] = (x2_delta>>8)&0x00ff;
buffer[11] = y2_delta & 0x00ff;
buffer[12] = (y2_delta>>8)&0x00ff;
err_code = ble_hids_inp_rep_send(&m_hids,
INPUT_REP_TOUCH_INDEX,
INPUT_REP_TOUCH_LEN,
buffer);
if ((err_code != NRF_SUCCESS) &&
(err_code != NRF_ERROR_INVALID_STATE) &&
(err_code != BLE_ERROR_NO_TX_PACKETS) &&
(err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING))
{
APP_ERROR_HANDLER(err_code);
}
}
static void touch_emulation(bsp_event_t event)
{
static uint16_t touch_num = 8000;
static uint16_t touch_num2 = 2000;
switch (event)
{
case BSP_EVENT_KEY_1:
if (m_conn_handle != BLE_CONN_HANDLE_INVALID) {
mouse_moveto_2xy(1,touch_num,touch_num, touch_num2, touch_num2);
touch_num -= 100;
if(touch_num < 1000)
touch_num = 8000;
touch_num2 += 100;
if(touch_num2 > 8000)
touch_num2 = 1000;
}
break;
case BSP_EVENT_KEY_3:
if (m_conn_handle != BLE_CONN_HANDLE_INVALID) {
mouse_moveto_2xy(1,touch_num2,touch_num2, touch_num,touch_num);
touch_num -= 100;
if(touch_num < 1000)
touch_num = 8000;
touch_num2 += 100;
if(touch_num2 > 8000)
touch_num2 = 1000;
}
break;
default:
// mouse_moveto_2xy(0,5000,5000);
// touch_num=5000;
break;
}
}
2. send Key value with the below code
static void keys_send(uint8_t key_pattern_len, uint8_t * p_key_pattern)
{
uint32_t err_code;
uint16_t actual_len;
err_code = send_key_scan_press_release(&m_hids,
p_key_pattern,
key_pattern_len,
0,
&actual_len);
// An additional notification is needed for release of all keys, therefore check
// is for actual_len <= key_pattern_len and not actual_len < key_pattern_len.
if ((err_code == BLE_ERROR_NO_TX_PACKETS) && (actual_len <= key_pattern_len))
{
// Buffer enqueue routine return value is not intentionally checked.
// Rationale: Its better to have a a few keys missing than have a system
// reset. Recommendation is to work out most optimal value for
// MAX_BUFFER_ENTRIES to minimize chances of buffer queue full condition
UNUSED_VARIABLE(buffer_enqueue(&m_hids, p_key_pattern, key_pattern_len, actual_len));
}
if ((err_code != NRF_SUCCESS) &&
(err_code != NRF_ERROR_INVALID_STATE) &&
(err_code != BLE_ERROR_NO_TX_PACKETS) &&
(err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
)
{
APP_ERROR_HANDLER(err_code);
}
}