__IRAM_CODE void btn_processPress(int val)
{
    int btn;
    struct evt_t evt;

    for(btn=0;btn<NB_BUTTONS;btn++)
    {
        if(BTN_NOT_PRESSED(val,btn)) /* the btn is NOT pressed */
        {
            nb_pressed[btn]=0;   /* reset nb_pressed */
            mx_press[btn] = current_repeatParam->init_delay;
            press_step[btn] = 0;
            /*if(btn==BTN_OFF)
                nb_off_press=0;   */ /* if off btn released -> reset nb_off_press */
        }
        else            /* the btn i is pressed */
        {    
            
            /*if(btn==BTN_OFF)  */  /* OFF btn pressed => check if we have to halt */
            /*{
                nb_off_press++;
                if(nb_off_press>MAX_OFF)
                {
                    printk("[OFF button] => halt\n");
                    halt_device();                    
                }
            }*/

            if(nb_pressed[btn]==0)
            {
#ifdef HAVE_FM_REMOTE
                if(!inHold)
                {
#endif
                    switch(press_step[btn])
                    {
                        case 0:
                            press_step[btn] = 1;
                            nb_pressed[btn] = current_repeatParam->init_delay;
                            break;
                        case 1:
                            press_step[btn] = 2;
                            nb_pressed[btn] = current_repeatParam->second_delay;
                            mx_press[btn] = current_repeatParam->second_delay;
                            break;
                        case 2:
                            mx_press[btn] -= current_repeatParam->dec_value;
                            if(mx_press[btn]<current_repeatParam->min_delay)
                                mx_press[btn]=current_repeatParam->min_delay;
                            nb_pressed[btn] = mx_press[btn];
                            break;
                        default:
                            press_step[btn] = 0;
                            mx_press[btn] = current_repeatParam->init_delay;
                    }
#if 0
                    if(lcd_get_state()==0)
                    {
                        /* the lcd is off => turn on and discard the event */
                        lcd_keyPress();
                        break;
                    }
                    else
                        lcd_launchTimer(); /* postpone the lcd timer */
                    halt_launchTimer(); /* postpone the poweroff timer */
#endif

                    if(!con_screenIsVisible())
                    {
                      if (val&BTMASK_F1 && btn+1==BTN_ON) con_screenSwitch();
                      
                      // post the event
                      evt.evt=btn+1;
                      evt.evt_class=BTN_CLASS;
                      evt.data=(void*)mx_press[btn];
                      evt_send(&evt);
                    }
                    else
                    {
                        switch(btn+1)
                        {
                            case BTN_ON:
                                con_screenSwitch();
                                break;
                            case BTN_OFF:
                                con_clear();
                                break;
                            case BTN_UP:
                                con_screenScroll(-1);
                                break;
                            case BTN_DOWN:
                                con_screenScroll(1);
                                break;
                        }
                    }


                    //printk("BTN %d pressed\n",btn);
#ifdef HAVE_FM_REMOTE
                }
                else
                {
                    //FM_putTmpText("** HOLD **",30);
                    printk("** HOLD **\n");
                }
#endif
            }
            else
                nb_pressed[btn]--;
        }
    }
}
static void *cap_osd_thread(void *data)
{
    char command[256];
    FILE *command_pipe;
    size_t read_size, offset;
    int window_id, x, y, w, h;
    int fd;
    int frame_width, frame_height;
    long long start_time, mid_time, end_time;

    while (!s_stopped) {
        start_time = get_current_time();
        if (s_request_time < start_time - 2000) {
            usleep(50*1000);
            continue;
        }

        if (get_active_window_info(&window_id, &x, &y, &w, &h) == false) {
            print_error("get_active_window_info() failed");
            continue;
        }

        if (is_nx1() || is_nx500()) {
            frame_width  = NX1_500_FRAME_WIDTH;
        } else { // NX300
            frame_width  = NX300_FRAME_WIDTH;
        }
        frame_height = FRAME_HEIGHT;

        if (is_nx1()) {
            if (w == 1024 && h == 768 && x == 720) { // NX1 EVF
                s_evf = true;
                snprintf(command, sizeof(command),
                         "xwd -id %d | "
                         "%s convert -size 1024x768+%d -depth 8 bgra:- "
                         "-scale x480 -background \"rgba(0,0,0,255)\" "
                         "-gravity center -extent 720x480 bgra:-",
                         window_id, get_chroot_command(), XWD_SKIP_BYTES);
            } else if (w == 720 && h == 480) {
                s_evf = false;
                snprintf(command, sizeof(command),
                         "xwd -id %d", window_id);
            } else {
                s_evf = false;
                snprintf(command, sizeof(command),
                         "xwd -root | "
                         "%s convert -size 1744x768+%d -depth 8 bgra:- "
                         "-crop 720x480+0+0 bgra:-",
                         get_chroot_command(), XWD_SKIP_BYTES);
            }
        } else if (is_nx500()) {
            if (w == 720 && h == 480 && lcd_get_state() == LCD_OFF) {
                snprintf(command, sizeof(command), "xwd -id %lu",
                         get_di_camera_app_window_id());
            } else {
                snprintf(command, sizeof(command), "xwd -root");
            }
        } else { // NX300
            if (w == 480 && h == 800) {
                snprintf(command, sizeof(command),
                         "xwd -id %d | "
                         "%s convert -size 480x800+%d -depth 8 bgra:- "
                         "-rotate 270 bgra:-",
                         window_id, get_chroot_command(), XWD_SKIP_BYTES);
            } else {
                snprintf(command, sizeof(command),
                         "xwd -root | "
                         "%s convert -size 480x800+%d -depth 8 bgra:- "
                         "-rotate 270 bgra:-",
                         get_chroot_command(), XWD_SKIP_BYTES);
            }
        }

        //print_log("command = %s", command);
        command_pipe = popen(command, "r");
        if (command_pipe == NULL) {
            print_error("popen() failed");
            usleep(50*1000);
            continue;
        }
        fd = fileno(command_pipe);

        read_size = 0;
        offset = 0;
        while (offset < sizeof(s_buffer)) {
            read_size = read(fd, s_buffer + offset, sizeof(s_buffer) - offset);
            if (read_size == -1) {
                print_error("read() failed");
                break;
            } else if (read_size == 0) {
                //print_log("read_size is 0");
                break;
            }
            offset += read_size;
        }
        if (offset > frame_width * frame_height * 4) {
            s_buffer_shift_bytes = offset - (frame_width * frame_height * 4);
            //print_log("shift bytes = %d", s_buffer_shift_bytes);
        } else if (offset < frame_width * frame_height * 4) {
            print_log("frame read failed! offset = %d", offset);
            pclose(command_pipe);
            continue;
        } else {
            s_buffer_shift_bytes = 0;
        }

        pclose(command_pipe);

        mid_time = get_current_time();

        update_osd_data(); // TODO: mutex lock?
        end_time = get_current_time();
        print_log("cap_osd_thread() time = %lld + %lld = %lld",
                mid_time - start_time,
                end_time - mid_time,
                end_time - start_time);
        //usleep(50*1000);
    }

    print_log("cap_osd_thread() terimanted.");

    return NULL;
}