This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

hid phone camera control

Use the media control's volume up / down keys to control the camera shooting of your Android camera. How to achieve continuous shooting?

How to achieve the function of camera focusing through hid?

In the HID universal descriptor, the three functions of ZOOM IN, ZOOM OUT, and switching of the front and back cameras are only valid for Huawei phones, and cannot control the three functions of Xiaomi phones and Apple phone cameras. How to solve them?

  • Hi,

     

    A HID key function is consumed by the OS itself, so it depends on what the OS allows

    Use the media control's volume up / down keys to control the camera shooting of your Android camera. How to achieve continuous shooting?

    I am not sure there is a specific command for continuous shooting. You can work around that by sending the same command in a interval.

     

    How to achieve the function of camera focusing through hid?

     Focus normally requires that you focus on a given area.Unfortunately, we do not have a list of what input commands the different camera apps accept.

     

    In the HID universal descriptor, the three functions of ZOOM IN, ZOOM OUT, and switching of the front and back cameras are only valid for Huawei phones, and cannot control the three functions of Xiaomi phones and Apple phone cameras. How to solve them?

     A typical zoom on a mouse is normally "CTRL+scroll" (either scroll up or down). However; it depends on what the OS also allows in terms of HID devices, here with an example on iOS behavior:

    https://forums.developer.apple.com/thread/45989

     

    Kind regards,

    Håkon

  • Hi ,

    I have been researching how to use the hid to realize the camera function of the mobile phone for two weeks. I used the touch descriptor, but it only works on Android phones, not on Apple phones. why?
    Here is my code:

    #define MOVEMENT_SPEED                  5                                           /**< Number of pixels by which the cursor is moved each time a button is pushed. */
    #define INPUT_REPORT_COUNT              2                                           /**< Number of input reports in this application. */
    #define INPUT_REP_DIGITIZER_LEN         10
    #define INPUT_REP_DIGITIZER_INDEX       0
    #define INPUT_REP_REF_DIGITIZER_ID      1                                           /**< Id of reference to Mouse Input Report containing media player data. */
    
    
    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;
        uint8_t                   hid_info_flags;
    
        static ble_hids_inp_rep_init_t inp_rep_array[INPUT_REPORT_COUNT];
        static uint8_t rep_map_data[] =
        {
    #if 1
            0x05, 0x0D,        // Usage Page (Digitizer)
            0x09, 0x04,        // Usage (Touch Screen)
            0xA1, 0x01,        // Collection (Application)
            0x85, 0x01,        // Report Id 1
            0x09, 0x22,        // Usage (Finger)
            0xA1, 0x02,        // Collection (Logical)
            0x09, 0x42,        // Usage (Tip Switch)
            0x15, 0x00,        // Logical Minimum (0)
            0x25, 0x01,        // Logical Maximum (1)
            0x75, 0x01,        // Report Size (1)
            0x95, 0x01,        // Report Count (1)
            0x81, 0x02,        // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
            0x09, 0x30,        // Usage (Tip Pressure)
            0x25, 0x7F,        // Logical Maximum (127)
            0x75, 0x07,        // Report Size (7)
            0x95, 0x01,        // Report Count (1)
            0x81, 0x02,        // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
            0x09, 0x51,        // Usage (0x51 - Contact identifier)
            0x26, 0xFF, 0x00,  // Logical Maximum (255)
            0x75, 0x08,        // Report Size (8)
            0x95, 0x01,        // Report Count (1)
            0x81, 0x02,        // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
            0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
            0x09, 0x30,        // Usage (X)
            0x09, 0x31,        // Usage (Y)
            0x26, 0xFF, 0x7F,  // Logical Maximum (32767)
            0x65, 0x00,        // Unit (None)
            0x75, 0x10,        // Report Size (16)
            0x95, 0x02,        // Report Count (2)
            0x81, 0x02,        // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
            0xC0,              // End Collection
    				
            0x05, 0x0D,        // Usage Page (Digitizer)
            0x27, 0xFF, 0xFF, 0x00, 0x00,  //   Logical Maximum (65534)
            0x09, 0x56,        // Usage (0x56 - Scan Time)
            0x75, 0x10,        // Report Size (16)
            0x95, 0x01,        // Report Count (1)
            0x81, 0x02,        // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
            0x09, 0x54,        // Usage (0x54 - Contact count)
            0x25, 0x05,        // Logical Maximum (5)
            0x75, 0x08,        // Report Size (8)
            0x95, 0x01,        // Report Count (1)
            0x81, 0x02,        // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
            0x05, 0x0D,        // Usage Page (Digitizer)
            0x09, 0x55,        // Usage (0x55 - Contact point maximum)
            0x25, 0x0A,        // Logical Maximum (10)
            0x75, 0x08,        // Report Size (8)
            0x95, 0x01,        // Report Count (1)
            0xB1, 0x02,        // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
            0xC0               // End Collection  
    
    #endif
    
        };
    
        memset(inp_rep_array, 0, sizeof(inp_rep_array));
        // Initialize HID Service.
        #if 0
        p_input_report                      = &inp_rep_array[INPUT_REP_BUTTONS_INDEX];
        p_input_report->max_len             = INPUT_REP_BUTTONS_LEN;
        p_input_report->rep_ref.report_id   = INPUT_REP_REF_BUTTONS_ID;
        p_input_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_INPUT;
    
        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                      = &inp_rep_array[INPUT_REP_MOVEMENT_INDEX];
        p_input_report->max_len             = INPUT_REP_MOVEMENT_LEN;
        p_input_report->rep_ref.report_id   = INPUT_REP_REF_MOVEMENT_ID;
        p_input_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_INPUT;
    
        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;
        #endif
    #if 1
        p_input_report                      = &inp_rep_array[INPUT_REP_DIGITIZER_INDEX];
        p_input_report->max_len             = INPUT_REP_DIGITIZER_LEN;
        p_input_report->rep_ref.report_id   = INPUT_REP_REF_DIGITIZER_ID;
        p_input_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_INPUT;
    
        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;
    #endif
        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                          = false;
        hids_init_obj.is_mouse                       = true;
        hids_init_obj.inp_rep_count                  = INPUT_REPORT_COUNT;
        hids_init_obj.p_inp_rep_array                = inp_rep_array;
        hids_init_obj.outp_rep_count                 = 0;
        hids_init_obj.p_outp_rep_array               = NULL;
        hids_init_obj.feature_rep_count              = 0;
        hids_init_obj.p_feature_rep_array            = NULL;
        hids_init_obj.rep_map.data_len               = sizeof(rep_map_data);
        hids_init_obj.rep_map.p_data                 = rep_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_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);
    }
    
    
    typedef PACKED_STRUCT
    {
        uint8_t  tip_switch : 1;
        uint8_t  tip_pressure : 7;
        uint8_t  contact_id;
        uint16_t x;
        uint16_t y;
        uint16_t scan_time;
        uint8_t  contact_count;
        uint8_t  contact_count_max;
    }digitizer_report_t;
    
    void digitizer_send(uint8_t id, uint8_t c_count, uint16_t x, uint16_t y, bool tip_down)
    {
        digitizer_report_t report = {0};
            
        report.tip_switch = (tip_down > 0) ? 1 : 0;
        report.tip_pressure = (tip_down > 0) ? 127 : 0;
        report.contact_id = id;
        report.x = x;
        report.y = y;
        report.scan_time = 0x64;
        report.contact_count = c_count;
        report.contact_count_max = 6;
        uint32_t err_code;
        err_code = ble_hids_inp_rep_send(&m_hids,
                                         INPUT_REP_DIGITIZER_INDEX,
                                         INPUT_REP_DIGITIZER_LEN,
                                         (uint8_t *)&report,
                                         m_conn_handle); 
        //APP_ERROR_CHECK(err_code);
    		if ((err_code != NRF_SUCCESS) &&
    				(err_code != NRF_ERROR_INVALID_STATE) &&
    				(err_code != NRF_ERROR_RESOURCES) &&
    				(err_code != NRF_ERROR_BUSY) &&
    				(err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING))
        {
            APP_ERROR_HANDLER(err_code);
        }
    }
    
    static void bsp_event_handler(bsp_event_t event)
    {
        ret_code_t err_code;
        digitizer_report_t dig_rep;
        static uint16_t test_x = 10000;
        static uint16_t test_y = 20000;
        static uint32_t test_counter = 0;
    
        switch (event)
        {
            case BSP_EVENT_SLEEP:
                sleep_mode_enter();
                break;
    
            case BSP_EVENT_DISCONNECT:
                err_code = sd_ble_gap_disconnect(m_conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                if (err_code != NRF_ERROR_INVALID_STATE)
                {
                    APP_ERROR_CHECK(err_code);
                }
                break;
    
            case BSP_EVENT_WHITELIST_OFF:
                if (m_conn_handle == BLE_CONN_HANDLE_INVALID)
                {
                    err_code = ble_advertising_restart_without_whitelist(&m_advertising);
                    if (err_code != NRF_ERROR_INVALID_STATE)
                    {
                        APP_ERROR_CHECK(err_code);
                    }
                }
                break;
    
            case BSP_EVENT_KEY_3:
                NRF_LOG_INFO("Running test no: %i", test_counter);
                switch(test_counter++)
                {
                    case 0:
                        digitizer_send(0, 1, 5000, 10000, true);
    										digitizer_send3(1, 2, 7000, 5000, true);
                        break;
                    case 1:
                        digitizer_send(0, 1, 5000, 10000, false);
    										digitizer_send3(1, 2, 7000, 5000, false);
    										test_counter = 0;
                        break;
    
                break;
    
            default:
                break;
        }
    }
    

    I used Apple 5s (ios10.4) and Apple 6s (ios12.3) for testing. The test application was Test MultiTouch; the test results were all failed.

  • Hi,

     

    Are you certain that it is supported by iOS? Per this thread, you might want to double-check in the accessory interface specification to see if its supported:

    https://devzone.nordicsemi.com/f/nordic-q-a/42198/why-hid-touch-device-can-works-on-android-but-can-t-work-on-ios-nrf52832-ble_app_hids_keyboard-example-sdk-13-0-0-s132

     

    Kind regards,

    Håkon

  • Supported.
    There are touch hid on the market to operate iphone camera.

  • I would recommend that you contact apple and ask about how to this feature.

     

    Kind regards,

    Håkon

Related