Hi, Guys.
I am developing a custom hardware keyboard using the ble_app_hids_keyboard example source code of SDK17.1.0.
The basic keyboard function works well.
And Caps Lock also works well on iPad.
After that, I implemented three additional functions, keyboard + mouse + consumer control, as in the link below.
However, when I connect it to iPad and test it, the basic keyboard function works well, but the Caps Lock function does not work.
That is, I disabled the iPad's Settings - General - Keyboard - Hardware Keyboard - [Switch Languages using Caps Lock].
Then, the Caps Lock function should work, but the custom board I am developing does not work, so only lowercase letters are entered.
It is the same source as the link above, but I do not know how to make Caps Lock work on iPad. Please help me.
In other words, when I add the mouse and consumer control, Caps Lock does not work on iPad. How can I fix this problem?
My source code is:
#define INPUT_REPORT_COUNT 4 /* Keyboard - Input */ #define INPUT_REPORT_KEYS_MAX_LEN 8 /**< Maximum length of the Input Report characteristic. */ #define INPUT_REPORT_KEYS_INDEX 0 /**< Index of Input Report. */ #define INPUT_REPORT_REF_KEYS_ID 1 /**< Id of reference to Keyboard Input Report. */ /* Keyboard - Output */ #define OUTPUT_REPORT_MAX_LEN 1 /**< Maximum length of Output Report. */ #define OUTPUT_REPORT_INDEX 0 /**< Index of Output Report. */ #define OUTPUT_REPORT_REF_ID 1 /**< Id of reference to Keyboard Output Report. */ /* Keyboard - Feature */ #define FEATURE_REPORT_MAX_LEN 2 /**< Maximum length of Feature Report. */ #define FEATURE_REPORT_INDEX 0 /**< Index of Feature Report. */ #define FEATURE_REPORT_REF_ID 1 /**< ID of reference to Keyboard Feature Report. */ /* Mouse - Buttons */ #define INPUT_REPORT_BUTTONS_LEN 3 /**< Length of Mouse Input Report containing button data. */ #define INPUT_REPORT_BUTTONS_INDEX 1 /**< Index of Mouse Input Report containing button data. */ #define INPUT_REPORT_REF_BUTTONS_ID 2 /**< Id of reference to Mouse Input Report containing button data. */ /* Mouse - Movement */ #define INPUT_REP_MOVEMENT_LEN 3 #define INPUT_REP_MOVEMENT_INDEX 2 /**< Index of Mouse Input Report containing movement data. */ #define INPUT_REP_REF_MOVEMENT_ID 3 /* Consumer Control */ #define INPUT_REPORT_CONSUMER_MAX_LEN 1 #define INPUT_REPORT_CONSUMER_INDEX 3 #define INPUT_REPORT_REF_CONSUMER_ID 4
static void hids_init(void) { ret_code_t err_code; ble_hids_init_t hids_init_obj; ble_hids_inp_rep_init_t * p_input_report; ble_hids_outp_rep_init_t * p_output_report; ble_hids_feature_rep_init_t * p_feature_report; uint8_t hid_info_flags; static ble_hids_inp_rep_init_t input_report_array[INPUT_REPORT_COUNT]; static ble_hids_outp_rep_init_t output_report_array[1]; static ble_hids_feature_rep_init_t feature_report_array[1]; static uint8_t report_map_data[] = { //////// Keyboard /////////////////////////////////////////////////////////// 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x06, // Usage (Keyboard) 0xA1, 0x01, // Collection (Application) 0x85, 0x01, // Report Id (1) 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 Size (8 bit) 0x95, 0x02, // Report Count (2) 0xB1, 0x02, // Feature (Data, Variable, Absolute) 0xC0, // End Collection (Application) /////// Mouse ////////////////////////////////////////////////////////////////// 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x02, // Usage (Mouse) 0xA1, 0x01, // Collection (Application) // Report ID 1: Mouse buttons + scroll/pan 0x85, 0x02, // Report Id 2 0x09, 0x01, // Usage (Pointer) 0xA1, 0x00, // Collection (Physical) 0x95, 0x05, // Report Count (3) 0x75, 0x01, // Report Size (1) 0x05, 0x09, // Usage Page (Buttons) 0x19, 0x01, // Usage Minimum (01) 0x29, 0x05, // Usage Maximum (05) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x81, 0x02, // Input (Data, Variable, Absolute) 0x95, 0x01, // Report Count (1) 0x75, 0x03, // Report Size (3) 0x81, 0x01, // Input (Constant) for padding 0x75, 0x08, // Report Size (8) 0x95, 0x01, // Report Count (1) 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x38, // Usage (Wheel) 0x15, 0x81, // Logical Minimum (-127) 0x25, 0x7F, // Logical Maximum (127) 0x81, 0x06, // Input (Data, Variable, Relative) 0x05, 0x0C, // Usage Page (Consumer) 0x0A, 0x38, 0x02, // Usage (AC Pan) 0x95, 0x01, // Report Count (1) 0x81, 0x06, // Input (Data,Value,Relative,Bit Field) 0xC0, // End Collection (Physical) // Report ID 2: Mouse motion 0x85, 0x03, // Report Id 3 0x09, 0x01, // Usage (Pointer) 0xA1, 0x00, // Collection (Physical) 0x75, 0x0C, // Report Size (12) 0x95, 0x02, // Report Count (2) 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x30, // Usage (X) 0x09, 0x31, // Usage (Y) 0x16, 0x01, 0xF8, // Logical maximum (2047) 0x26, 0xFF, 0x07, // Logical minimum (-2047) 0x81, 0x06, //0x02, //0x06 // Input (Data, Variable, Relative) 0xC0, // End Collection (Physical) 0xC0, // End Collection (Application) /////// Consumer Control ////////////////////////////////////////////////////////////////////// // Report ID 3: Advanced buttons 0x05, 0x0C, // Usage Page (Consumer) 0x09, 0x01, // Usage (Consumer Control) 0xA1, 0x01, // Collection (Application) 0x85, 0x04, // Report Id (4) 0x15, 0x00, // Logical minimum (0) 0x25, 0x01, // Logical maximum (1) 0x75, 0x01, // Report Size (1) 0x95, 0x01, // Report Count (1) 0x09, 0x70, // Usage (Display Brightness Decremanr) 0x81, 0x06, // Input (Data,Value,Relative,Bit Field) 0x09, 0x6F, // Usage (Display Brightness Incremanr) 0x81, 0x06, // Input (Data,Value,Relative,Bit Field) 0x09, 0xB6, // Usage (Scan Previous Track) 0x81, 0x06, // Input (Data,Value,Relative,Bit Field) 0x09, 0xCD, // Usage (Play/Pause) 0x81, 0x06, // Input (Data,Value,Relative,Bit Field) 0x09, 0xB5, // Usage (Scan Next Track) 0x81, 0x06, // Input (Data,Value,Relative,Bit Field) 0x09, 0xE2, // Usage (Volume Mute) 0x81, 0x06, // Input (Data,Value,Relative,Bit Field) 0x09, 0xEA, // Usage (Volume Down) 0x81, 0x06, // Input (Data,Value,Relative,Bit Field) 0x09, 0xE9, // Usage (Volume Up) 0x81, 0x06, // Input (Data,Value,Relative,Bit Field) 0xC0, // End Collection }; memset((void *)input_report_array, 0, sizeof(ble_hids_inp_rep_init_t) * INPUT_REPORT_COUNT); memset((void *)output_report_array, 0, sizeof(ble_hids_outp_rep_init_t)); memset((void *)feature_report_array, 0, sizeof(ble_hids_feature_rep_init_t)); // Initialize HID Service /* Keyboard */ p_input_report = &input_report_array[INPUT_REPORT_KEYS_INDEX]; //0 p_input_report->max_len = INPUT_REPORT_KEYS_MAX_LEN; //8 p_input_report->rep_ref.report_id = INPUT_REPORT_REF_KEYS_ID; //1 p_input_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_INPUT; //1 p_input_report->sec.cccd_wr = SEC_JUST_WORKS; p_input_report->sec.wr = SEC_JUST_WORKS; p_input_report->sec.rd = SEC_JUST_WORKS; p_output_report = &output_report_array[OUTPUT_REPORT_INDEX]; //0 p_output_report->max_len = OUTPUT_REPORT_MAX_LEN; //1 p_output_report->rep_ref.report_id = OUTPUT_REPORT_REF_ID; //1 p_output_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_OUTPUT; //2 p_output_report->sec.wr = SEC_JUST_WORKS; p_output_report->sec.rd = SEC_JUST_WORKS; p_feature_report = &feature_report_array[FEATURE_REPORT_INDEX]; //0 p_feature_report->max_len = FEATURE_REPORT_MAX_LEN; //2 p_feature_report->rep_ref.report_id = FEATURE_REPORT_REF_ID; //1 p_feature_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_FEATURE; //3 p_feature_report->sec.rd = SEC_JUST_WORKS; p_feature_report->sec.wr = SEC_JUST_WORKS; /* Mouse */ p_input_report = &input_report_array[INPUT_REPORT_BUTTONS_INDEX]; //1 p_input_report->max_len = INPUT_REPORT_BUTTONS_LEN; //3 p_input_report->rep_ref.report_id = INPUT_REPORT_REF_BUTTONS_ID; //2 p_input_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_INPUT; //1 p_input_report->sec.cccd_wr = SEC_JUST_WORKS; p_input_report->sec.wr = SEC_JUST_WORKS; p_input_report->sec.rd = SEC_JUST_WORKS; p_input_report = &input_report_array[INPUT_REP_MOVEMENT_INDEX]; //2 p_input_report->max_len = INPUT_REP_MOVEMENT_LEN; //3 p_input_report->rep_ref.report_id = INPUT_REP_REF_MOVEMENT_ID; //3 p_input_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_INPUT; //1 p_input_report->sec.cccd_wr = SEC_JUST_WORKS; p_input_report->sec.wr = SEC_JUST_WORKS; p_input_report->sec.rd = SEC_JUST_WORKS; /* Consumer Control */ p_input_report = &input_report_array[INPUT_REPORT_CONSUMER_INDEX]; //3 p_input_report->max_len = INPUT_REPORT_CONSUMER_MAX_LEN; //1 //2 *** p_input_report->rep_ref.report_id = INPUT_REPORT_REF_CONSUMER_ID; //4 p_input_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_INPUT; //1 p_input_report->sec.cccd_wr = SEC_JUST_WORKS; p_input_report->sec.wr = SEC_JUST_WORKS; p_input_report->sec.rd = SEC_JUST_WORKS; hid_info_flags = HID_INFO_FLAG_REMOTE_WAKE_MSK | HID_INFO_FLAG_NORMALLY_CONNECTABLE_MSK; memset(&hids_init_obj, 0, sizeof(hids_init_obj)); hids_init_obj.evt_handler = on_hids_evt; hids_init_obj.error_handler = service_error_handler; hids_init_obj.is_kb = true; hids_init_obj.is_mouse = true; hids_init_obj.inp_rep_count = INPUT_REPORT_COUNT; hids_init_obj.p_inp_rep_array = input_report_array; hids_init_obj.outp_rep_count = 1; hids_init_obj.p_outp_rep_array = output_report_array; hids_init_obj.feature_rep_count = 1; hids_init_obj.p_feature_rep_array = feature_report_array; hids_init_obj.rep_map.data_len = sizeof(report_map_data); hids_init_obj.rep_map.p_data = report_map_data; hids_init_obj.hid_information.bcd_hid = BASE_USB_HID_SPEC_VERSION; hids_init_obj.hid_information.b_country_code = 0; hids_init_obj.hid_information.flags = hid_info_flags; hids_init_obj.included_services_count = 0; hids_init_obj.p_included_services_array = NULL; hids_init_obj.rep_map.rd_sec = SEC_JUST_WORKS; hids_init_obj.hid_information.rd_sec = SEC_JUST_WORKS; hids_init_obj.boot_kb_inp_rep_sec.cccd_wr = SEC_JUST_WORKS; hids_init_obj.boot_kb_inp_rep_sec.rd = SEC_JUST_WORKS; hids_init_obj.boot_kb_outp_rep_sec.rd = SEC_JUST_WORKS; hids_init_obj.boot_kb_outp_rep_sec.wr = SEC_JUST_WORKS; hids_init_obj.boot_mouse_inp_rep_sec.cccd_wr = SEC_JUST_WORKS; hids_init_obj.boot_mouse_inp_rep_sec.wr = SEC_JUST_WORKS; hids_init_obj.boot_mouse_inp_rep_sec.rd = SEC_JUST_WORKS; hids_init_obj.protocol_mode_rd_sec = SEC_JUST_WORKS; hids_init_obj.protocol_mode_wr_sec = SEC_JUST_WORKS; hids_init_obj.ctrl_point_wr_sec = SEC_JUST_WORKS; err_code = ble_hids_init(&m_hids, &hids_init_obj); APP_ERROR_CHECK(err_code); }
Best Regards,