/*-----------------------------------------------------------------------------------------------*\ \*-----------------------------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define AVM_EVENT_INTERNAL #include #include #include #define CONFIG_AVM_PUSH_BUTTON_GPIO (8) #define AVM_EVENT_PUSH_BUTTON_SAMPLE_TIME 250 /*--- #define AVM_EVENT_PUSH_BUTTON_SAMPLE_TIME 5000 ---*/ #define MSEC(x) ((HZ * (x)) / 1000) /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static struct _avm_event_push_button_state { void *handle; unsigned long long jiffies_64; unsigned int value; struct timer_list timer; } Button; extern int avm_event_enable_push_button; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #if 0 static void blabla(char* text) { volatile unsigned int *gpio_ctrl = (unsigned int*)AVALANCHE_GPIO_ENBL; volatile unsigned int *gpio_dir = (unsigned int*)AVALANCHE_GPIO_DIR; volatile unsigned int *gpio_in = (unsigned int*)AVALANCHE_GPIO_DATA_IN; unsigned int state; state = avalanche_gpio_in_bit(CONFIG_AVM_PUSH_BUTTON_GPIO) ? avm_event_push_button_gpio_low : avm_event_push_button_gpio_high; printk("[%s] gpio_ctrl=0x%x with mask 0x%x 0x%x\n", text, *gpio_ctrl, 1 << CONFIG_AVM_PUSH_BUTTON_GPIO, *gpio_ctrl & (1 << CONFIG_AVM_PUSH_BUTTON_GPIO)); printk("[%s] gpio_dir=0x%x with mask 0x%x 0x%x\n", text, *gpio_dir, 1 << CONFIG_AVM_PUSH_BUTTON_GPIO, *gpio_dir & (1 << CONFIG_AVM_PUSH_BUTTON_GPIO)); printk("[%s] gpio_in=0x%x with mask 0x%x 0x%x\n", text, *gpio_in, 1 << CONFIG_AVM_PUSH_BUTTON_GPIO, *gpio_in & (1 << CONFIG_AVM_PUSH_BUTTON_GPIO)); printk("[%s] GPIO %u is %s ", text, CONFIG_AVM_PUSH_BUTTON_GPIO, state ? "avm_event_push_button_gpio_high" : "avm_event_push_button_gpio_low"); printk("[%s] Button.value %s\n", text, Button.value ? "avm_event_push_button_gpio_high" : "avm_event_push_button_gpio_low"); } #endif /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void avm_event_push_button_timer_handler(unsigned long Data) { unsigned int state; del_timer(&(Button.timer)); state = avm_gpio_in_bit(CONFIG_AVM_PUSH_BUTTON_GPIO) ? avm_event_push_button_gpio_low : avm_event_push_button_gpio_high; /*--- blabla("avm_event_push_button_timer_handler"); ---*/ /*--- new button pressed ---*/ if(state == avm_event_push_button_gpio_high && Button.value == avm_event_push_button_gpio_low) { /*--- printk("[A]"); ---*/ Button.jiffies_64 = jiffies_64; Button.value = avm_event_push_button_gpio_high; printk("Button presses: GPIO=%u time=%u\n", CONFIG_AVM_PUSH_BUTTON_GPIO, (unsigned int)Button.jiffies_64); } /*--- new button released ---*/ if(state == avm_event_push_button_gpio_low && Button.value == avm_event_push_button_gpio_high) { struct _avm_event_push_button *event; /*--- printk("[B]"); ---*/ event = (struct _avm_event_push_button *)kmalloc(sizeof(struct _avm_event_push_button), GFP_ATOMIC); if(event) { event->id = avm_event_id_push_button; event->pressed = (unsigned int)(jiffies_64 - Button.jiffies_64); if(event->pressed < MSEC(2000)) { event->key = avm_event_push_button_key_1; } else if(event->pressed < MSEC(8000)) { event->key = avm_event_push_button_key_2; } else { event->key = avm_event_push_button_key_3; } event->pressed *= 10; Button.value = avm_event_push_button_gpio_low; avm_event_source_trigger(Button.handle, avm_event_id_push_button, sizeof(struct _avm_event_push_button), event); printk("Button released: GPIO=%u presses=%u key=%s\n", CONFIG_AVM_PUSH_BUTTON_GPIO, (unsigned int)event->pressed, event->key == avm_event_push_button_key_1 ? "avm_event_push_button_key_1" : event->key == avm_event_push_button_key_2 ? "avm_event_push_button_key_2" : event->key == avm_event_push_button_key_3 ? "avm_event_push_button_key_3" : "unknown" ); } } Button.timer.function = avm_event_push_button_timer_handler; Button.timer.data = -1; Button.timer.expires = jiffies + MSEC(AVM_EVENT_PUSH_BUTTON_SAMPLE_TIME); add_timer(&(Button.timer)); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void avm_event_push_button_notify(void *Context, enum _avm_event_id id) { struct _avm_event_push_button *event; event = (struct _avm_event_push_button *)kmalloc(sizeof(struct _avm_event_push_button), GFP_ATOMIC); if(event == NULL) return; event->id = avm_event_id_push_button; event->key = avm_gpio_in_bit(CONFIG_AVM_PUSH_BUTTON_GPIO) ? avm_event_push_button_gpio_low : avm_event_push_button_gpio_high; event->pressed = 0; avm_event_source_trigger(Button.handle, avm_event_id_push_button, sizeof(struct _avm_event_push_button), event); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void avm_event_push_button_init(void) { if(avm_event_enable_push_button == 0) return; avm_gpio_ctrl(CONFIG_AVM_PUSH_BUTTON_GPIO, GPIO_PIN, GPIO_INPUT_PIN); Button.handle = avm_event_source_register("push_button", (unsigned long long)1 << avm_event_id_push_button,avm_event_push_button_notify, (void *)0); Button.value = avm_event_push_button_gpio_low; Button.jiffies_64 = jiffies_64; init_timer(&(Button.timer)); Button.timer.function = avm_event_push_button_timer_handler; Button.timer.data = -1; Button.timer.expires = jiffies + MSEC(AVM_EVENT_PUSH_BUTTON_SAMPLE_TIME); add_timer(&(Button.timer)); /*--- blabla("avm_event_push_button_init"); ---*/ } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void avm_event_push_button_deinit(void) { if(avm_event_enable_push_button == 0) return; del_timer(&Button.timer); avm_event_source_release(Button.handle); }