1 /*
2 ********************************************************************************
3 *                                USB Hid Driver
4 *
5 *                (c) Copyright 2006-2010, All winners Co,Ld.
6 *                        All Right Reserved
7 *
8 * FileName      :  UsbMouse_DriftControl.c
9 *
10 * Author        :  Javen
11 *
12 * Date          :  2010.06.02
13 *
14 * Description   :  USB Mouse 去抖动算法.
15 *     1、所有鼠标事件信息添加到队列中
16 *     2、每隔5ms处理队列中的所事件有信息。
17 *     3、
18 *
19 * Others        :  NULL
20 *
21 * History:
22 *       <time>      <version >      <author>        <desc>
23 *      2010.07.16      1.0           Javen          build this file
24 *
25 ********************************************************************************
26 */
27 
28 //#include  "usb_host_config.h"
29 //#include  "usb_host_base_types.h"
30 #include "usb_os_platform.h"
31 #include "usb_host_common.h"
32 #include "error.h"
33 #include "HidSpec.h"
34 #include "Hid_i.h"
35 #include "HidFunDrv.h"
36 #include "UsbMouse.h"
37 #include "UsbMouse_DriftControl.h"
38 
39 /*
40 *******************************************************************************
41 *                     UsbMouse_AddToDriftArray
42 *
43 * Description:
44 *
45 *
46 * Parameters:
47 *
48 *
49 * Return value:
50 *
51 *
52 * note:
53 *
54 *
55 *******************************************************************************
56 */
UsbMouse_DriftTimeOut(void * parg)57 static void UsbMouse_DriftTimeOut(void *parg)
58 {
59     UsbMouseDriftControl_t *Drift = (UsbMouseDriftControl_t *)parg;
60     unsigned int cup_sr = 0;
61 
62     if(Drift == NULL){
63         hal_log_err("ERR: input error\n");
64         return ;
65     }
66 
67     /* 如果有可疑的点存在,就把可疑的点发出去 */
68     if(Drift->WaitEvent && Drift->DubiousMouseEvent.vaild) {
69         int val = 0;
70         ENTER_CRITICAL(cup_sr);
71         DMSG_MOUSE_TEST("TimeOut: DubiousCoordinate = %x\n", Drift->DubiousCoordinate);
72         memcpy(&Drift->CurrentMouseEvent, &Drift->DubiousMouseEvent, sizeof(UsbMouseEventUnit_t));
73         Drift->CurrentMouseEvent.vaild = 1;
74         EXIT_CRITICAL(cup_sr);
75 
76 //      UsbThreadWakeUp(Drift->ThreadSemi);
77         if (!hal_sem_getvalue(Drift->ThreadSemi, &val))
78         {
79             hal_sem_post(Drift->ThreadSemi);
80         }
81     }
82 
83     return;
84 }
85 
86 /*
87 *******************************************************************************
88 *                     UsbMouse_IsButtonEvent
89 *
90 * Description:
91 *
92 *
93 * Parameters:
94 *
95 *
96 * Return value:
97 *
98 *
99 * note:
100 *
101 *
102 *******************************************************************************
103 */
UsbMouse_IsButtonEvent(USBHMouseEvent_t * MouseEvent)104 static unsigned int UsbMouse_IsButtonEvent(USBHMouseEvent_t *MouseEvent)
105 {
106     return (MouseEvent->Button.LeftButton
107             || MouseEvent->Button.RightButton
108             || MouseEvent->Button.MiddleButton
109             || MouseEvent->Wheel);
110 }
111 
112 /*
113 *******************************************************************************
114 *                     UsbMouse_IsDubiousEvent
115 *
116 * Description:
117 *
118 *
119 * Parameters:
120 *
121 *
122 * Return value:
123 *
124 *
125 * note:
126 *
127 *
128 *******************************************************************************
129 */
UsbMouse_IsDubiousEvent(USBHMouseEvent_t * Event,UsbMouseDriftControl_t * Drift)130 static unsigned int UsbMouse_IsDubiousEvent(USBHMouseEvent_t *Event, UsbMouseDriftControl_t *Drift)
131 {
132     unsigned int Dubious = 0;
133 
134     /* 如果参考点PreMouseEvent不存在, 那么就不用怀疑本次的点 */
135     if(Drift->PreMouseEvent.vaild == 0){
136         return 0;
137     }
138 
139     /* 如果前后两次 X 坐标差值大于127, 那么就认为本次的坐标为可疑的坐标 */
140     if(absolute(Event->X - Drift->PreMouseEvent.MouseEvent.X) > USB_HID_MOUSE_DITHER_AREA){
141         usb_set_bit(1, (volatile uint32_t *)&Drift->DubiousCoordinate);
142         Dubious = 1;
143     }
144 
145     /* 如果前后两次 Y 坐标差值大于127, 那么就认为本次的坐标为可疑的坐标 */
146     if(absolute(Event->Y - Drift->PreMouseEvent.MouseEvent.Y) > USB_HID_MOUSE_DITHER_AREA){
147         usb_set_bit(2, (volatile uint32_t *)&Drift->DubiousCoordinate);
148         Dubious = 1;
149     }
150 
151     if(Dubious){
152         DMSG_MOUSE_TEST("DubiousCoordinate = %x\n", Drift->DubiousCoordinate);
153     }
154 
155     return Dubious;
156 }
157 
158 /* 判断X和Y是否都是正数或者是否都是负数 */
UsbMouse_IsAccord8(__s8 x,__s8 y)159 static __u32 UsbMouse_IsAccord8(__s8 x, __s8 y)
160 {
161     /* 是否都是负数 */
162     if(x <= 0 && y <= 0){
163         return 1;
164     }
165 
166     /* 是否都是正数 */
167     if(x >= 0 && y >= 0){
168         return 1;
169     }
170 
171     return 0;
172 }
173 
174 /*
175 *******************************************************************************
176 *                     UsbMouse_AddToDriftArray
177 *
178 * Description:
179 *     从3个鼠标数据中找出轨迹相同的两个, 然后取平均值。
180 *
181 * Parameters:
182 *
183 *
184 * Return value:
185 *
186 *
187 * note:
188 *
189 *******************************************************************************
190 */
UsbMouse_AdjustCoordinate(USBHMouseEvent_t * Event1,USBHMouseEvent_t * Event2,USBHMouseEvent_t * Event3,USBHMouseEvent_t * OutEvent)191 static int UsbMouse_AdjustCoordinate(USBHMouseEvent_t *Event1,
192                                        USBHMouseEvent_t *Event2,
193                                        USBHMouseEvent_t *Event3,
194                                        USBHMouseEvent_t *OutEvent)
195 {
196     /* 寻找 X 坐标上方向一致的点 */
197     if(UsbMouse_IsAccord8(Event1->X, Event2->X)
198        && UsbMouse_IsAccord8(Event1->X, Event3->X)){ /* 1,2,3都一致 */
199         OutEvent->X = (Event1->X / 3) + (Event2->X / 3) + (Event3->X / 3);
200     }else if(UsbMouse_IsAccord8(Event1->X, Event2->X)){  /* 1,2都是一致的 */
201         OutEvent->X = Event2->X;
202     }else if(UsbMouse_IsAccord8(Event1->X, Event3->X)){  /* 1,3都是一致的 */
203         OutEvent->X = Event3->X;
204     }else if(UsbMouse_IsAccord8(Event2->X, Event3->X)){  /* 2,3都是一致的 */
205         OutEvent->X = (Event2->X / 2) + (Event3->X / 2);
206     }else{  /* 1,2,3都不是一致的 */
207         OutEvent->X = (Event1->X / 3) + (Event2->X / 3) + (Event3->X / 3);
208     }
209 
210     /* 寻找 Y 坐标上方向一致的点 */
211     if(UsbMouse_IsAccord8(Event1->Y, Event2->Y)
212        && UsbMouse_IsAccord8(Event1->Y, Event3->Y)){ /* 1,2,3都一致 */
213         OutEvent->Y = (Event1->Y / 3) + (Event2->Y / 3) + (Event3->Y / 3);
214     }else if(UsbMouse_IsAccord8(Event1->Y, Event2->Y)){  /* 1,2都是一致的 */
215         OutEvent->Y = Event2->Y;
216     }else if(UsbMouse_IsAccord8(Event1->Y, Event3->Y)){  /* 1,3都是一致的 */
217         OutEvent->Y = Event3->Y;
218     }else if(UsbMouse_IsAccord8(Event2->Y, Event3->Y)){  /* 2,3都是一致的 */
219         OutEvent->Y = (Event2->Y / 2) + (Event3->Y / 2);
220     }else{  /* 1,2,3都不是一致的 */
221         OutEvent->Y = (Event1->Y / 3) + (Event2->Y / 3) + (Event3->Y / 3);
222     }
223 
224     return 0;
225 }
226 
227 /*
228 *******************************************************************************
229 *                     UsbMouse_AddToDriftArray
230 *
231 * Description:
232 *
233 *
234 * Parameters:
235 *
236 *
237 * Return value:
238 *
239 *
240 * note:
241 *
242 *   1、只有按键消息,直接发送给app。
243 *
244 *   2、只有wheel消息,直接发送给app。
245 *
246 *   3、只有坐标,就预测鼠标的轨迹,
247 *      如果本次的点A和上一次的点B相差太大,在规定时间内取下一次的点C作参考,
248 *      如果A和C相近,就丢掉B点,发送A点和C点给app;如果规定时间内没有鼠标事件,就把A点和B点给发给app。
249 *
250 *   4、如果按键、wheel、坐标参杂在一起,遇到按键或者wheel事件后,
251 *      把当前所有的点全部发给app,并且把下一次的按键抬起消息,也及时的发送出去。
252 *
253 *******************************************************************************
UsbMouse_AddToDriftArray(usbMouse_t * usbMouse,USBHMouseEvent_t * Event)254 */void UsbMouse_AddToDriftArray(usbMouse_t *usbMouse, USBHMouseEvent_t *Event)
255 {
256     int val = 0;
257     UsbMouseDriftControl_t *Drift = NULL;
258     unsigned int cup_sr = 0;
259 
260     if(usbMouse == NULL){
261         hal_log_err("ERR: input error\n");
262         return ;
263     }
264 
265     Drift = usbMouse->Extern;
266     if(Drift == NULL){
267         hal_log_err("ERR: Drift == NULL\n");
268         return ;
269     }
270 
271     /* 先前有按键按下, 这里遇到抬起键, 就给把本次消息发送给APP */
272     if(Drift->ButtonDown){
273         /* 如果本次还有按键消息, 就记录下来 */
274         if(UsbMouse_IsButtonEvent(Event)){
275             DMSG_MOUSE_TEST("Had send a button down event, then a new button event come\n");
276             Drift->ButtonDown = 1;
277         }else{
278             DMSG_MOUSE_TEST("Had send a button down event, then wait for button rise\n");
279             Drift->ButtonDown = 0;
280         }
281 
282         goto SendMsg;
283     }
284 
285     /* 有按键事件或者滚轮事件,就唤醒线程 */
286     if(UsbMouse_IsButtonEvent(Event)){
287         DMSG_MOUSE_TEST("have a button event\n");
288 
289         Drift->ButtonDown = 1;
290         goto SendMsg;
291     }
292 
293     /* 如果PreMouseEvent和dubiousMouseEvent都有效, 那么就直接比较 */
294     if(Drift->PreMouseEvent.vaild && Drift->DubiousMouseEvent.vaild){
295         ENTER_CRITICAL(cup_sr);
296         DMSG_MOUSE_TEST("------Pre------\n");
297         DMSG_MOUSE_TEST("DubiousCoordinate = %x\n", Drift->DubiousCoordinate);
298 
299         DMSG_MOUSE_TEST("Pre Button 1 = %d\n", Drift->PreMouseEvent.MouseEvent.Button.LeftButton);
300         DMSG_MOUSE_TEST("Pre Button 2 = %d\n", Drift->PreMouseEvent.MouseEvent.Button.RightButton);
301         DMSG_MOUSE_TEST("Pre Button 3 = %d\n", Drift->PreMouseEvent.MouseEvent.Button.MiddleButton);
302         DMSG_MOUSE_TEST("Pre Button 4 = %d\n", Drift->PreMouseEvent.MouseEvent.Button.Button4);
303         DMSG_MOUSE_TEST("Pre Button 5 = %d\n", Drift->PreMouseEvent.MouseEvent.Button.Button5);
304         DMSG_MOUSE_TEST("Pre Button 6 = %d\n", Drift->PreMouseEvent.MouseEvent.Button.Button6);
305         DMSG_MOUSE_TEST("Pre Button 7 = %d\n", Drift->PreMouseEvent.MouseEvent.Button.Button7);
306         DMSG_MOUSE_TEST("Pre Button 8 = %d\n", Drift->PreMouseEvent.MouseEvent.Button.Button8);
307 
308         DMSG_MOUSE_TEST("Pre X        = %d\n", Drift->PreMouseEvent.MouseEvent.X);
309         DMSG_MOUSE_TEST("Pre Y        = %d\n", Drift->PreMouseEvent.MouseEvent.Y);
310         DMSG_MOUSE_TEST("Pre Wheel    = %d\n", Drift->PreMouseEvent.MouseEvent.Wheel);
311         DMSG_MOUSE_TEST("\n");
312 
313         DMSG_MOUSE_TEST("\n");
314         DMSG_MOUSE_TEST("dubious Button 1 = %d\n", Drift->DubiousMouseEvent.MouseEvent.Button.LeftButton);
315         DMSG_MOUSE_TEST("dubious Button 2 = %d\n", Drift->DubiousMouseEvent.MouseEvent.Button.RightButton);
316         DMSG_MOUSE_TEST("dubious Button 3 = %d\n", Drift->DubiousMouseEvent.MouseEvent.Button.MiddleButton);
317         DMSG_MOUSE_TEST("dubious Button 4 = %d\n", Drift->DubiousMouseEvent.MouseEvent.Button.Button4);
318         DMSG_MOUSE_TEST("dubious Button 5 = %d\n", Drift->DubiousMouseEvent.MouseEvent.Button.Button5);
319         DMSG_MOUSE_TEST("dubious Button 6 = %d\n", Drift->DubiousMouseEvent.MouseEvent.Button.Button6);
320         DMSG_MOUSE_TEST("dubious Button 7 = %d\n", Drift->DubiousMouseEvent.MouseEvent.Button.Button7);
321         DMSG_MOUSE_TEST("dubious Button 8 = %d\n", Drift->DubiousMouseEvent.MouseEvent.Button.Button8);
322 
323         DMSG_MOUSE_TEST("dubious X        = %d\n", Drift->DubiousMouseEvent.MouseEvent.X);
324         DMSG_MOUSE_TEST("dubious Y        = %d\n", Drift->DubiousMouseEvent.MouseEvent.Y);
325         DMSG_MOUSE_TEST("dubious Wheel    = %d\n", Drift->DubiousMouseEvent.MouseEvent.Wheel);
326         DMSG_MOUSE_TEST("\n");
327 
328         DMSG_MOUSE_TEST("\n");
329         DMSG_MOUSE_TEST("Event Button 1 = %d\n", Event->Button.LeftButton);
330         DMSG_MOUSE_TEST("Event Button 2 = %d\n", Event->Button.RightButton);
331         DMSG_MOUSE_TEST("Event Button 3 = %d\n", Event->Button.MiddleButton);
332         DMSG_MOUSE_TEST("Event Button 4 = %d\n", Event->Button.Button4);
333         DMSG_MOUSE_TEST("Event Button 5 = %d\n", Event->Button.Button5);
334         DMSG_MOUSE_TEST("Event Button 6 = %d\n", Event->Button.Button6);
335         DMSG_MOUSE_TEST("Event Button 7 = %d\n", Event->Button.Button7);
336         DMSG_MOUSE_TEST("Event Button 8 = %d\n", Event->Button.Button8);
337 
338         DMSG_MOUSE_TEST("Event X        = %d\n", Event->X);
339         DMSG_MOUSE_TEST("Event Y        = %d\n", Event->Y);
340         DMSG_MOUSE_TEST("Event Wheel    = %d\n", Event->Wheel);
341         DMSG_MOUSE_TEST("------Pre------\n");
342 
343         EXIT_CRITICAL(cup_sr);
344 
345         /* 寻找同方向的两个点 */
346         /* X坐标可疑 */
347         UsbMouse_AdjustCoordinate(&Drift->PreMouseEvent.MouseEvent,
348                                   &Drift->DubiousMouseEvent.MouseEvent,
349                                   Event,
350                                   Event);
351 
352         Drift->DubiousMouseEvent.vaild = 0;
353         Drift->PreMouseEvent.vaild     = 0;
354 
355         goto SendMsg;
356     }else{
357         /* 判断本次坐标是否可疑? */
358         if(UsbMouse_IsDubiousEvent(Event, Drift) == 0){
359             goto SendMsg;
360         }else{
361             hal_log_info("a Dubious event\n");
362 
363             ENTER_CRITICAL(cup_sr);
364             memcpy(&Drift->DubiousMouseEvent.MouseEvent, Event, sizeof(USBHMouseEvent_t));
365             Drift->DubiousMouseEvent.vaild = 1;
366             Drift->WaitEvent = 1;
367             EXIT_CRITICAL(cup_sr);
368         }
369     }
370 
371     return;
372 
373 SendMsg:
374     ENTER_CRITICAL(cup_sr);
375     memcpy(&Drift->CurrentMouseEvent.MouseEvent, Event, sizeof(USBHMouseEvent_t));
376     Drift->CurrentMouseEvent.vaild = 1;
377     EXIT_CRITICAL(cup_sr);
378 
379 //  UsbThreadWakeUp(Drift->ThreadSemi);
380     if (!hal_sem_getvalue(Drift->ThreadSemi, &val))
381     {
382         hal_sem_post(Drift->ThreadSemi);
383     }
384 //  UsbThreadSleep(Drift->notify_complete);
385     hal_sem_wait(Drift->notify_complete);
386 
387     return;
388 }
389 
390 /*
391 *******************************************************************************
392 *                     UsbMouse_DriftControl
393 *
394 * Description:
395 *    鼠标去抖动
396 *
397 * Parameters:
398 *
399 *
400 * Return value:
401 *
402 *
403 * note:
404 *    无
405 *
406 *******************************************************************************
407 */
UsbMouse_DriftControl(UsbMouseDriftControl_t * Drift)408 static int UsbMouse_DriftControl(UsbMouseDriftControl_t *Drift)
409 {
410     int val = 0;
411     unsigned int cup_sr = 0;
412 
413     /* 清除等待标志 */
414     ENTER_CRITICAL(cup_sr);
415     Drift->WaitEvent = 0;
416     EXIT_CRITICAL(cup_sr);
417 
418     /* sent mouse event to system */
419     if(Drift->CurrentMouseEvent.vaild){
420         ENTER_CRITICAL(cup_sr);
421 
422         memcpy(&Drift->usbMouse->MouseEvent, &Drift->CurrentMouseEvent.MouseEvent, sizeof(USBHMouseEvent_t));
423         memcpy(&Drift->PreMouseEvent, &Drift->CurrentMouseEvent, sizeof(UsbMouseEventUnit_t));
424 
425         Drift->PreMouseEvent.vaild     = 1;
426         Drift->CurrentMouseEvent.vaild = 0;
427         Drift->DubiousMouseEvent.vaild = 0;
428 
429         DMSG_MOUSE_TEST("\n");
430         DMSG_MOUSE_TEST("msg Button 1 = %d\n", Drift->usbMouse->MouseEvent.Button.LeftButton);
431         DMSG_MOUSE_TEST("msg Button 2 = %d\n", Drift->usbMouse->MouseEvent.Button.RightButton);
432         DMSG_MOUSE_TEST("msg Button 3 = %d\n", Drift->usbMouse->MouseEvent.Button.MiddleButton);
433         DMSG_MOUSE_TEST("msg Button 4 = %d\n", Drift->usbMouse->MouseEvent.Button.Button4);
434         DMSG_MOUSE_TEST("msg Button 5 = %d\n", Drift->usbMouse->MouseEvent.Button.Button5);
435         DMSG_MOUSE_TEST("msg Button 6 = %d\n", Drift->usbMouse->MouseEvent.Button.Button6);
436         DMSG_MOUSE_TEST("msg Button 7 = %d\n", Drift->usbMouse->MouseEvent.Button.Button7);
437         DMSG_MOUSE_TEST("msg Button 8 = %d\n", Drift->usbMouse->MouseEvent.Button.Button8);
438 
439         DMSG_MOUSE_TEST("msg X        = %d\n", Drift->usbMouse->MouseEvent.X);
440         DMSG_MOUSE_TEST("msg Y        = %d\n", Drift->usbMouse->MouseEvent.Y);
441         DMSG_MOUSE_TEST("msg Wheel    = %d\n", Drift->usbMouse->MouseEvent.Wheel);
442         DMSG_MOUSE_TEST("\n");
443 
444         EXIT_CRITICAL(cup_sr);
445 
446         if(Drift->usbMouse->CallBack){
447             esKRNL_CallBack((__pCBK_t)Drift->usbMouse->CallBack, (void *)&Drift->usbMouse->MouseEvent);
448         }
449     }
450 
451 //  UsbThreadWakeUp(Drift->notify_complete);
452     if (!hal_sem_getvalue(Drift->ThreadSemi, &val))
453     {
454         hal_sem_post(Drift->ThreadSemi);
455     }
456 
457     return USB_ERR_SUCCESS;
458 }
459 
460 /*
461 *******************************************************************************
462 *                     UsbMouse_DriftThread
463 *
464 * Description:
465 *
466 *
467 * Parameters:
468 *
469 *
470 * Return value:
471 *
472 *
473 * note:
474 *    无
475 *
476 *******************************************************************************
477 */
UsbMouse_DriftThread(void * p_arg)478 static void UsbMouse_DriftThread(void *p_arg)
479 {
480     UsbMouseDriftControl_t *Drift = (UsbMouseDriftControl_t *)p_arg;
481 
482     if(Drift == NULL){
483         hal_log_err("ERR: input error\n");
484         return ;
485     }
486 
487 
488     hal_sem_post(Drift->notify_complete);
489 
490     while(1){
491         //--<1>--杀死线程
492 //      TryToKillThreadSelf("UsbMouse_DriftThread");
493 
494 //      /* sleep */
495 //      UsbThreadSleep(Drift->ThreadSemi);
496         kthread_stop(Drift->ThreadId);
497         hal_sem_wait(Drift->ThreadSemi);
498 
499         UsbMouse_DriftControl(Drift);
500     }
501 }
502 
503 /*
504 *******************************************************************************
505 *                     UsbMouse_DriftControl_Init
506 *
507 * Description:
508 *
509 *
510 * Parameters:
511 *
512 *
513 * Return value:
514 *
515 *
516 * note:
517 *
518 *
519 *******************************************************************************
520 */
UsbMouse_DriftControl_Init(usbMouse_t * usbMouse)521 int UsbMouse_DriftControl_Init(usbMouse_t *usbMouse)
522 {
523     int status = 0;
524     UsbMouseDriftControl_t *Drift;
525     unsigned int err = 0;
526 
527     Drift = hal_malloc(sizeof(UsbMouseDriftControl_t));
528     if(Drift == NULL){
529         hal_log_err("ERR: hal_malloc failed\n");
530         return USB_ERR_MALLOC_FAILED;
531     }
532 
533     memset(Drift, 0, sizeof(UsbMouseDriftControl_t));
534 
535     /* create thread */
536     Drift->ThreadSemi = hal_sem_create(0);
537     if(Drift->ThreadSemi == NULL){
538         hal_log_err("ERR: USB_OS_SemCreate ThreadSemi failed\n");
539         status = USB_ERR_CREATE_SIME_FAILED;
540         goto err0;
541     }
542 
543     Drift->notify_complete = hal_sem_create(0);
544     if(Drift->notify_complete == NULL){
545         hal_log_err("ERR: USB_OS_SemCreate notify_complete failed\n");
546         status = USB_ERR_CREATE_SIME_FAILED;
547         goto err1;
548     }
549 
550     /* Mouse Drift thread */
551     Drift->ThreadId = kthread_create((void *)UsbMouse_DriftThread,
552                                       (void *)Drift,
553                                       "UsbMouse_DriftThread");
554     if(Drift->ThreadId == OS_NO_ERR){
555         hal_log_err("ERR: create MainThreadId failed\n");
556         status = USB_ERR_CREATE_THREAD_FAILED;
557         goto err2;
558     }
559 
560     hal_sem_wait(Drift->notify_complete);
561 
562     /* create timer */
563     Drift->TimerHdle = osal_timer_create("UsbMouse_DriftControl", UsbMouse_DriftTimeOut, (void*)Drift,
564                     400, OSAL_TIMER_FLAG_PERIODIC);
565 
566     if(Drift->TimerHdle == NULL){
567         hal_log_err("ERR: create timer failed\n");
568         status = USB_ERR_CREATE_TIMER_FAILED;
569         goto err3;
570     }
571 
572     osal_timer_start(Drift->TimerHdle);
573 
574     /*  */
575     Drift->usbMouse = usbMouse;
576     usbMouse->Extern = Drift;
577 
578     return USB_ERR_SUCCESS;
579 
580 
581 err3:
582 //  UsbKillThread(Drift->ThreadId, NULL);
583     kthread_stop(Drift->ThreadId);
584 err2:
585     hal_sem_delete(Drift->notify_complete);
586     Drift->notify_complete = NULL;
587 
588 err1:
589     hal_sem_delete(Drift->ThreadSemi);
590     Drift->ThreadSemi = NULL;
591 
592 err0:
593     hal_free(Drift);
594 
595     return status;
596 }
597 
598 /*
599 *******************************************************************************
600 *                     UsbMouse_DriftControl_Exit
601 *
602 * Description:
603 *
604 *
605 * Parameters:
606 *
607 *
608 * Return value:
609 *
610 *
611 * note:
612 *
613 *
614 *******************************************************************************
615 */
UsbMouse_DriftControl_Exit(usbMouse_t * usbMouse)616 int UsbMouse_DriftControl_Exit(usbMouse_t *usbMouse)
617 {
618     UsbMouseDriftControl_t *Drift = NULL;
619     unsigned int err = 0;
620 
621     if(usbMouse == NULL){
622         hal_log_err("ERR: input error\n");
623         return USB_ERR_BAD_ARGUMENTS;
624     }
625 
626     Drift = usbMouse->Extern;
627     if(Drift == NULL){
628         hal_log_err("ERR: Drift == NULL\n");
629         return USB_ERR_BAD_ARGUMENTS;
630     }
631 
632     /* stop and kill timer */
633     osal_timer_stop(Drift->TimerHdle);
634     osal_timer_delete(Drift->TimerHdle);
635     Drift->TimerHdle = NULL;
636 
637     /* kill thread */
638 //  UsbKillThread(Drift->ThreadId, Drift->ThreadSemi);
639     kthread_stop(Drift->ThreadId);
640 
641     hal_sem_delete(Drift->ThreadSemi);
642     Drift->ThreadSemi = NULL;
643 
644     hal_sem_delete(Drift->notify_complete);
645     Drift->notify_complete = NULL;
646 
647     usbMouse->Extern = NULL;
648     hal_free(Drift);
649 
650     return USB_ERR_SUCCESS;
651 }
652 
653