key_driver.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. #include "device/key_driver.h"
  2. #include "system/event.h"
  3. #include "system/init.h"
  4. #include "iokey.h"
  5. #include "adkey.h"
  6. #include "slidekey.h"
  7. #include "irkey.h"
  8. #include "touch_key.h"
  9. #include "system/timer.h"
  10. #include "asm/power_interface.h"
  11. #include "app_config.h"
  12. #include "rdec_key.h"
  13. #include "tent600_key.h"
  14. #if TCFG_KEY_TONE_EN
  15. #include "tone_player.h"
  16. #endif
  17. #if(TCFG_IRSENSOR_ENABLE == 1)
  18. #include "irSensor/ir_manage.h"
  19. #endif
  20. #define LOG_TAG_CONST KEY
  21. #define LOG_TAG "[KEY]"
  22. #define LOG_ERROR_ENABLE
  23. #define LOG_DEBUG_ENABLE
  24. #define LOG_INFO_ENABLE
  25. //#define LOG_DUMP_ENABLE
  26. //#define LOG_CLI_ENABLE
  27. #include "debug.h"
  28. #define KEY_EVENT_CLICK_ONLY_SUPPORT 1 //是否支持某些按键只响应单击事件
  29. #if TCFG_SPI_LCD_ENABLE
  30. #ifndef ALL_KEY_EVENT_CLICK_ONLY
  31. #define ALL_KEY_EVENT_CLICK_ONLY 1 //是否全部按键只响应单击事件
  32. #endif
  33. #else
  34. #ifndef ALL_KEY_EVENT_CLICK_ONLY
  35. #define ALL_KEY_EVENT_CLICK_ONLY 0 //是否全部按键只响应单击事件
  36. #endif
  37. #endif
  38. static volatile u8 is_key_active = 0;
  39. static volatile u8 key_poweron_flag = 0;
  40. extern u32 timer_get_ms(void);
  41. //=======================================================//
  42. // 按键值重新映射函数:
  43. // 用户可以实现该函数把一些按键值重新映射, 可用于组合键的键值重新映射
  44. //=======================================================//
  45. int __attribute__((weak)) key_event_remap(struct sys_event *e)
  46. {
  47. return true;
  48. }
  49. //=======================================================//
  50. // 设置按键开机标志位
  51. //=======================================================//
  52. void set_key_poweron_flag(u8 flag)
  53. {
  54. key_poweron_flag = flag;
  55. }
  56. //=======================================================//
  57. // 获取按键开机标志位
  58. //=======================================================//
  59. u8 get_key_poweron_flag(void)
  60. {
  61. return key_poweron_flag;
  62. }
  63. //=======================================================//
  64. // 清除按键开机标志位
  65. //=======================================================//
  66. void clear_key_poweron_flag(void)
  67. {
  68. key_poweron_flag = 0;
  69. }
  70. #if TCFG_SOFTOFF_WAKEUP_KEY_DRIVER_ENABLE
  71. static u8 key_scan_flag = 0, en_key_cnt = 0, en_key_cnt_flag = 1, nonsrc_wakeup_flag = 0, save_notify_flag = 0, key_wk_send_flag = 0;
  72. struct sys_event e_tmp;
  73. //=======================================================//
  74. // 清除保存的key_notify
  75. //=======================================================//
  76. void clear_save_key_notify(void)
  77. {
  78. save_notify_flag = 0;
  79. memset(&e_tmp, 0, sizeof(struct sys_event));
  80. }
  81. //=======================================================//
  82. // 设置软关机按键唤醒补充发键标志位
  83. //=======================================================//
  84. void set_key_wakeup_send_flag(u8 flag)
  85. {
  86. key_wk_send_flag = flag;
  87. if (save_notify_flag) {
  88. sys_event_notify(&e_tmp);
  89. clear_save_key_notify();
  90. }
  91. }
  92. //=======================================================//
  93. // 获取软关机按键唤醒补充发键标志位
  94. //=======================================================//
  95. u8 get_key_wakeup_send_flag(void)
  96. {
  97. return key_wk_send_flag;
  98. }
  99. //=======================================================//
  100. // 保存未初始化按键消息前推送的按键notify
  101. //=======================================================//
  102. void save_wakeup_key_notify(struct sys_event *event)
  103. {
  104. save_notify_flag = 1;
  105. e_tmp.type = event->type;
  106. e_tmp.arg = event->arg;
  107. e_tmp.u.key.init = event->u.key.init;
  108. e_tmp.u.key.type = event->u.key.type;
  109. e_tmp.u.key.event = event->u.key.event;
  110. e_tmp.u.key.value = event->u.key.value;
  111. e_tmp.u.key.tmr = event->u.key.tmr;
  112. }
  113. #endif
  114. //=======================================================//
  115. // 按键扫描函数: 扫描所有注册的按键驱动
  116. //=======================================================//
  117. static void key_driver_scan(void *_scan_para)
  118. {
  119. struct key_driver_para *scan_para = (struct key_driver_para *)_scan_para;
  120. u8 key_event = 0;
  121. u8 cur_key_value = NO_KEY;
  122. u8 key_value = 0;
  123. struct sys_event e;
  124. static u8 poweron_cnt = 0;
  125. //为了滤掉adkey与mic连在一起时电容充放电导致的开机按键误判,一般用于type-c耳机
  126. /* if (poweron_cnt <= 250) { */
  127. /* poweron_cnt++; */
  128. /* return; */
  129. /* } */
  130. cur_key_value = scan_para->get_value();
  131. /* if (cur_key_value != NO_KEY) { */
  132. /* printf(">>>cur_key_value: %d\n", cur_key_value); */
  133. /* } */
  134. #if TCFG_SOFTOFF_WAKEUP_KEY_DRIVER_ENABLE
  135. u8 wkup_src = get_wakeup_pnd();
  136. //按键唤醒后若未按下第二击,推出单击事件
  137. //key_driver初始化后未扫描到按键
  138. if (key_wk_send_flag && key_scan_flag == 0) {
  139. key_scan_flag = 1;
  140. //记住唤醒源——识别NO_KEY时的键值
  141. if (cur_key_value == NO_KEY) {
  142. if (wkup_src == TCFG_WAKEUP_PORT_POWER_SRC) { //唤醒口port1
  143. key_value = TCFG_IOKEY_POWER_ONE_PORT_VALUE;
  144. } else if (wkup_src == TCFG_WAKEUP_PORT_PREV_SRC) { //唤醒口port2
  145. key_value = TCFG_IOKEY_PREV_ONE_PORT_VALUE;
  146. } else if (wkup_src == TCFG_WAKEUP_PORT_NEXT_SRC) { //唤醒口port3
  147. key_value = TCFG_IOKEY_NEXT_ONE_PORT_VALUE;
  148. } else {
  149. nonsrc_wakeup_flag = 1;
  150. printf("wakeup source err is 0x%x !!!", wkup_src);
  151. return;
  152. }
  153. key_event = KEY_EVENT_CLICK; //单击
  154. goto _notify;
  155. }
  156. //初始化后扫描到了按键,但是未满足key_driver的单击事件推出,补充推出消息
  157. } else if (en_key_cnt && en_key_cnt <= (scan_para->filter_time + 1) && key_scan_flag == 1 && en_key_cnt_flag == 0) {
  158. en_key_cnt = 0;
  159. key_scan_flag = 0;
  160. }
  161. if (cur_key_value == NO_KEY) {
  162. en_key_cnt_flag = 0;
  163. } else {
  164. key_scan_flag = 1;
  165. if (en_key_cnt_flag) {
  166. en_key_cnt++;
  167. }
  168. }
  169. #endif
  170. if (cur_key_value != NO_KEY) {
  171. is_key_active = 35; //35*10Ms
  172. } else if (is_key_active) {
  173. is_key_active --;
  174. }
  175. //===== 按键消抖处理
  176. if (cur_key_value != scan_para->filter_value && scan_para->filter_time) { //当前按键值与上一次按键值如果不相等, 重新消抖处理, 注意filter_time != 0;
  177. scan_para->filter_cnt = 0; //消抖次数清0, 重新开始消抖
  178. scan_para->filter_value = cur_key_value; //记录上一次的按键值
  179. return; //第一次检测, 返回不做处理
  180. } //当前按键值与上一次按键值相等, filter_cnt开始累加;
  181. if (scan_para->filter_cnt < scan_para->filter_time) {
  182. scan_para->filter_cnt++;
  183. return;
  184. }
  185. //为了滤掉adkey与mic连在一起时电容充放电导致的按键误判,一般用于type-c耳机
  186. /* if ((cur_key_value != scan_para->last_key) && (scan_para->last_key != NO_KEY) && (cur_key_value != NO_KEY)) { */
  187. /* return; */
  188. /* } */
  189. //===== 按键消抖结束, 开始判断按键类型(单击, 双击, 长按, 多击, HOLD, (长按/HOLD)抬起)
  190. if (cur_key_value != scan_para->last_key) {
  191. if (cur_key_value == NO_KEY) { //cur_key = NO_KEY; last_key = valid_key -> 按键被抬起
  192. #if MOUSE_KEY_SCAN_MODE
  193. /* if (scan_para->press_cnt >= scan_para->long_time) { //长按/HOLD状态之后被按键抬起; */
  194. key_event = KEY_EVENT_UP;
  195. key_value = scan_para->last_key;
  196. goto _notify; //发送抬起消息
  197. /* } */
  198. #else
  199. #if TCFG_SOFTOFF_WAKEUP_KEY_DRIVER_ENABLE
  200. if (scan_para->press_cnt >= (scan_para->long_time - TCFG_LONGKEY_SUPPLEMENT_TIME)) //长按/HOLD状态之后被按键抬起, 补充长按时间;
  201. #else
  202. if (scan_para->press_cnt >= scan_para->long_time) //长按/HOLD状态之后被按键抬起;
  203. #endif
  204. {
  205. key_event = KEY_EVENT_UP;
  206. key_value = scan_para->last_key;
  207. goto _notify; //发送抬起消息
  208. }
  209. #endif
  210. scan_para->click_delay_cnt = 1; //按键等待下次连击延时开始
  211. } else { //cur_key = valid_key, last_key = NO_KEY -> 按键被按下
  212. scan_para->press_cnt = 1; //用于判断long和hold事件的计数器重新开始计时;
  213. if (cur_key_value != scan_para->notify_value) { //第一次单击/连击时按下的是不同按键, 单击次数重新开始计数
  214. #if TCFG_SOFTOFF_WAKEUP_KEY_DRIVER_ENABLE
  215. if ((en_key_cnt > scan_para->filter_time && en_key_cnt < scan_para->long_time) || key_wk_send_flag || nonsrc_wakeup_flag) {
  216. scan_para->click_cnt = 1;
  217. } else {
  218. scan_para->click_cnt = 2;
  219. }
  220. #else
  221. scan_para->click_cnt = 1;
  222. #endif
  223. scan_para->notify_value = cur_key_value;
  224. } else {
  225. scan_para->click_cnt++; //单击次数累加
  226. }
  227. }
  228. goto _scan_end; //返回, 等待延时时间到
  229. } else { //cur_key = last_key -> 没有按键按下/按键长按(HOLD)
  230. if (cur_key_value == NO_KEY) { //last_key = NO_KEY; cur_key = NO_KEY -> 没有按键按下
  231. if (scan_para->click_cnt > 0) { //有按键需要消息需要处理
  232. #if ALL_KEY_EVENT_CLICK_ONLY//彩屏方案支持单击
  233. key_event = KEY_EVENT_CLICK; //单击
  234. key_value = scan_para->notify_value;
  235. goto _notify;
  236. #endif
  237. #if KEY_EVENT_CLICK_ONLY_SUPPORT //是否支持某些按键只响应单击事件
  238. if (scan_para->notify_value & BIT(7)) { //BIT(7)按键特殊处理标志, 只发送单击事件, 也可以用于其它扩展
  239. key_event = KEY_EVENT_CLICK; //单击
  240. key_value = scan_para->notify_value;
  241. goto _notify;
  242. }
  243. #endif
  244. if (scan_para->click_delay_cnt > scan_para->click_delay_time) { //按键被抬起后延时到
  245. //TODO: 在此可以添加任意多击事件
  246. if (scan_para->click_cnt >= 5) {
  247. key_event = KEY_EVENT_FIRTH_CLICK; //五击
  248. } else if (scan_para->click_cnt >= 4) {
  249. key_event = KEY_EVENT_FOURTH_CLICK; //4击
  250. } else if (scan_para->click_cnt >= 3) {
  251. key_event = KEY_EVENT_TRIPLE_CLICK; //三击
  252. } else if (scan_para->click_cnt >= 2) {
  253. key_event = KEY_EVENT_DOUBLE_CLICK; //双击
  254. } else {
  255. key_event = KEY_EVENT_CLICK; //单击
  256. }
  257. key_value = scan_para->notify_value;
  258. goto _notify;
  259. } else { //按键抬起后等待下次延时时间未到
  260. scan_para->click_delay_cnt++;
  261. goto _scan_end; //按键抬起后延时时间未到, 返回
  262. }
  263. } else {
  264. goto _scan_end; //没有按键需要处理
  265. }
  266. } else { //last_key = valid_key; cur_key = valid_key, press_cnt累加用于判断long和hold
  267. scan_para->press_cnt++;
  268. #if TCFG_SOFTOFF_WAKEUP_KEY_DRIVER_ENABLE
  269. if (scan_para->press_cnt == (scan_para->long_time - TCFG_LONGKEY_SUPPLEMENT_TIME))
  270. #else
  271. if (scan_para->press_cnt == scan_para->long_time)
  272. #endif
  273. {
  274. key_event = KEY_EVENT_LONG;
  275. } else if (scan_para->press_cnt == scan_para->hold_time) {
  276. key_event = KEY_EVENT_HOLD;
  277. scan_para->press_cnt = scan_para->long_time;
  278. } else {
  279. goto _scan_end; //press_cnt没到长按和HOLD次数, 返回
  280. }
  281. //press_cnt没到长按和HOLD次数, 发消息
  282. key_value = cur_key_value;
  283. goto _notify;
  284. }
  285. }
  286. _notify:
  287. #if TCFG_IRSENSOR_ENABLE
  288. if (get_irSensor_event() == IR_SENSOR_EVENT_FAR) { //未佩戴的耳机不响应按键
  289. return;
  290. }
  291. #endif
  292. key_value &= ~BIT(7); //BIT(7) 用作按键特殊处理的标志
  293. e.type = SYS_KEY_EVENT;
  294. e.u.key.init = 1;
  295. e.u.key.type = scan_para->key_type;//区分按键类型
  296. e.u.key.event = key_event;
  297. e.u.key.value = key_value;
  298. e.u.key.tmr = timer_get_ms();
  299. scan_para->click_cnt = 0; //单击次数清0
  300. scan_para->notify_value = NO_KEY;
  301. e.arg = (void *)DEVICE_EVENT_FROM_KEY;
  302. /* printf("key_value: 0x%x, event: %d, key_poweron_flag: %d\n", key_value, key_event, key_poweron_flag); */
  303. if (key_poweron_flag) {
  304. if (key_event == KEY_EVENT_UP) {
  305. clear_key_poweron_flag();
  306. return;
  307. }
  308. return;
  309. }
  310. if (key_event_remap(&e)) {
  311. #if TCFG_SOFTOFF_WAKEUP_KEY_DRIVER_ENABLE
  312. if (key_wk_send_flag) {
  313. sys_event_notify(&e);
  314. } else {
  315. save_wakeup_key_notify(&e);
  316. }
  317. nonsrc_wakeup_flag = 0;
  318. #else
  319. sys_event_notify(&e);
  320. #endif
  321. #if TCFG_KEY_TONE_EN
  322. audio_key_tone_play();
  323. #endif
  324. }
  325. _scan_end:
  326. scan_para->last_key = cur_key_value;
  327. return;
  328. }
  329. //wakeup callback
  330. void key_active_set(u8 port)
  331. {
  332. /*要用按键宏包住,不用按键功能,唤醒后就再也不进睡眠*/
  333. #if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_TOUCH_KEY_ENABLE)
  334. is_key_active = 35; //35*10Ms
  335. #endif
  336. }
  337. //=======================================================//
  338. // 按键初始化函数: 初始化所有注册的按键驱动
  339. //=======================================================//
  340. int key_driver_init(void)
  341. {
  342. int err;
  343. #if TCFG_IOKEY_ENABLE
  344. extern const struct iokey_platform_data iokey_data;
  345. extern struct key_driver_para iokey_scan_para;
  346. err = iokey_init(&iokey_data);
  347. #ifdef TCFG_IOKEY_TIME_REDEFINE
  348. extern struct key_driver_para iokey_scan_user_para;
  349. if (err == 0) {
  350. sys_s_hi_timer_add((void *)&iokey_scan_user_para, key_driver_scan, iokey_scan_user_para.scan_time); //注册按键扫描定时器
  351. }
  352. #else
  353. if (err == 0) {
  354. sys_s_hi_timer_add((void *)&iokey_scan_para, key_driver_scan, iokey_scan_para.scan_time); //注册按键扫描定时器
  355. }
  356. #endif
  357. #endif
  358. #if TCFG_ADKEY_ENABLE
  359. #ifdef CONFIG_ICRECORDER_CASE_ENABLE
  360. extern multi_adkey_init(const struct adkey_platform_data * multi_adkey_data);
  361. extern const struct adkey_platform_data multi_adkey_data[];
  362. extern struct key_driver_para multi_adkey_scan_para;
  363. err = multi_adkey_init(multi_adkey_data);
  364. if (err == 0) {
  365. sys_s_hi_timer_add((void *)&multi_adkey_scan_para, key_driver_scan, multi_adkey_scan_para.scan_time); //注册按键扫描定时器
  366. }
  367. #else
  368. extern const struct adkey_platform_data adkey_data;
  369. extern struct key_driver_para adkey_scan_para;
  370. err = adkey_init(&adkey_data);
  371. if (err == 0) {
  372. sys_s_hi_timer_add((void *)&adkey_scan_para, key_driver_scan, adkey_scan_para.scan_time); //注册按键扫描定时器
  373. }
  374. #endif
  375. #endif
  376. #if TCFG_IRKEY_ENABLE
  377. extern const struct irkey_platform_data irkey_data;
  378. extern struct key_driver_para irkey_scan_para;
  379. err = irkey_init(&irkey_data);
  380. if (err == 0) {
  381. sys_s_hi_timer_add((void *)&irkey_scan_para, key_driver_scan, irkey_scan_para.scan_time); //注册按键扫描定时器
  382. }
  383. #endif
  384. #if TCFG_TOUCH_KEY_ENABLE
  385. extern const struct touch_key_platform_data touch_key_data;
  386. extern struct key_driver_para touch_key_scan_para;
  387. err = touch_key_init(&touch_key_data);
  388. if (err == 0) {
  389. sys_s_hi_timer_add((void *)&touch_key_scan_para, key_driver_scan, touch_key_scan_para.scan_time); //注册按键扫描定时器
  390. }
  391. #endif
  392. #if TCFG_ADKEY_RTCVDD_ENABLE
  393. extern const struct adkey_rtcvdd_platform_data adkey_rtcvdd_data;
  394. extern struct key_driver_para adkey_rtcvdd_scan_para;
  395. err = adkey_rtcvdd_init(&adkey_rtcvdd_data);
  396. if (err == 0) {
  397. sys_s_hi_timer_add((void *)&adkey_rtcvdd_scan_para, key_driver_scan, adkey_rtcvdd_scan_para.scan_time); //注册按键扫描定时器
  398. }
  399. #endif
  400. #if TCFG_RDEC_KEY_ENABLE
  401. extern const struct rdec_platform_data rdec_key_data;
  402. extern struct key_driver_para rdec_key_scan_para;
  403. err = rdec_key_init(&rdec_key_data);
  404. if (err == 0) {
  405. sys_s_hi_timer_add((void *)&rdec_key_scan_para, key_driver_scan, rdec_key_scan_para.scan_time); //注册按键扫描定时器
  406. }
  407. #endif
  408. #if TCFG_CTMU_TOUCH_KEY_ENABLE
  409. #include "asm/ctmu.h"
  410. extern const struct ctmu_touch_key_platform_data ctmu_touch_key_data;
  411. extern struct key_driver_para ctmu_touch_key_scan_para;
  412. extern int ctmu_touch_key_init(const struct ctmu_touch_key_platform_data * ctmu_touch_key_data);
  413. err = ctmu_touch_key_init(&ctmu_touch_key_data);
  414. if (err == 0) {
  415. sys_s_hi_timer_add((void *)&ctmu_touch_key_scan_para, key_driver_scan, ctmu_touch_key_scan_para.scan_time); //注册按键扫描定时器
  416. }
  417. #endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */
  418. #if TCFG_SLIDE_KEY_ENABLE
  419. extern const struct slidekey_platform_data slidekey_data;
  420. extern int slidekey_init(const struct slidekey_platform_data * slidekey_data);
  421. err = slidekey_init(&slidekey_data);
  422. if (err == 0) {
  423. }
  424. #endif//TCFG_SLIDE_KEY_ENABLE
  425. #if TCFG_6083_ADKEY_ENABLE
  426. extern int adkey_init_6083();
  427. err = adkey_init_6083();
  428. if (err == 0) {
  429. }
  430. #endif
  431. #if TCFG_TENT600_KEY_ENABLE
  432. extern const struct tent600_key_platform_data key_data ;
  433. extern struct key_driver_para tent600_key_scan_para;
  434. err = tent600_key_init(&key_data);
  435. if (err == 0) {
  436. sys_s_hi_timer_add((void *)&tent600_key_scan_para, key_driver_scan, tent600_key_scan_para.scan_time); //注册按键扫描定时器
  437. }
  438. #endif
  439. return 0;
  440. }
  441. static u8 key_idle_query(void)
  442. {
  443. return !is_key_active;
  444. }
  445. #if ((!TCFG_LP_TOUCH_KEY_ENABLE) && (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE))
  446. REGISTER_LP_TARGET(key_lp_target) = {
  447. .name = "key",
  448. .is_idle = key_idle_query,
  449. };
  450. #endif /* #if !TCFG_LP_TOUCH_KEY_ENABLE */
  451. #if (TCFG_SOFTOFF_WAKEUP_KEY_DRIVER_ENABLE && TCFG_IOKEY_ENABLE)
  452. //默认0,按键消息使能后置1,避免(软关机唤醒——发送按键消息)这段时间进入睡眠状态
  453. REGISTER_LP_TARGET(softoff_wake_key) = {
  454. .name = "softoff_wake_key",
  455. .is_idle = get_key_wakeup_send_flag,
  456. };
  457. #endif