1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2012-01-03     Yi Qiu      first version
9  */
10 
11 #include <rtthread.h>
12 #include <drivers/usb_host.h>
13 #include "hid.h"
14 
15 #ifdef RT_USING_RTGUI
16 #include <rtgui/event.h>
17 #include <rtgui/rtgui_server.h>
18 #include "drv_lcd.h"
19 #endif
20 
21 #if defined(RT_USBH_HID) && defined(RT_USBH_HID_MOUSE)
22 
23 #define DBG_TAG    "usbhost.umouse"
24 #define DBG_LVL           DBG_INFO
25 #include <rtdbg.h>
26 
27 static struct uprotocal mouse_protocal;
28 
29 #ifdef RT_USING_RTGUI
30 #define LKEY_PRESS 0x01
31 #define RKEY_PRESS 0x02
32 #define MKEY_PRESS 0x04
33 #define MOUSE_SCALING 0x02
34 
35 static rt_bool_t lkey_down=RT_FALSE;
36 //static rt_bool_t rkey_down=RT_FALSE;
37 //static rt_bool_t mkey_down=RT_FALSE;
38 static struct rtgui_event_mouse emouse;
39 #endif
40 
rt_usbh_hid_mouse_callback(void * arg)41 static rt_err_t rt_usbh_hid_mouse_callback(void* arg)
42 {
43     struct uhid* hid;
44 #ifdef RT_USING_RTGUI
45     rt_uint16_t xoffset=0;
46     rt_uint16_t yoffset=0;
47 #endif
48     hid = (struct uhid*)arg;
49 
50     LOG_D("hid 0x%x 0x%x",
51                                 *(rt_uint32_t*)hid->buffer,
52                                 *(rt_uint32_t*)(&hid->buffer[4]));
53 #ifdef RT_USING_RTGUI
54     if(hid->buffer[1]!=0)
55     {
56         if(hid->buffer[1]>127)
57         {
58             xoffset=(256-hid->buffer[1])*MOUSE_SCALING;
59             if(emouse.x>xoffset)
60             {
61                 emouse.x-=xoffset;
62             }
63             else
64             {
65                 emouse.x=0;
66             }
67         }
68         else
69         {
70             xoffset=(hid->buffer[1])*MOUSE_SCALING;
71             if((emouse.x+xoffset)<480)
72             {
73                 emouse.x+=xoffset;
74             }
75             else
76             {
77                 emouse.x=480;
78             }
79         }
80     }
81     if(hid->buffer[2]!=0)
82     {
83 
84         if(hid->buffer[2]>127)
85         {
86             yoffset=(256-hid->buffer[2])*MOUSE_SCALING;
87             if(emouse.y>yoffset)
88             {
89                 emouse.y-=yoffset;
90             }
91             else
92             {
93                 emouse.y=0;
94             }
95         }
96         else
97         {
98             yoffset=hid->buffer[2]*MOUSE_SCALING;
99             if(emouse.y+yoffset<272)
100             {
101                 emouse.y+=yoffset;
102             }
103             else
104             {
105                 emouse.y=272;
106             }
107         }
108     }
109     if(xoffset!=0||yoffset!=0)
110     {
111         cursor_set_position(emouse.x,emouse.y);
112     }
113     if(hid->buffer[0]&LKEY_PRESS)
114     {
115         if(lkey_down==RT_FALSE)
116         {
117             // rt_kprintf("mouse left key press down\n");
118             emouse.button = (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN);
119             rtgui_server_post_event(&emouse.parent, sizeof(struct rtgui_event_mouse));
120             lkey_down=RT_TRUE;
121         }
122     }
123     else if(lkey_down==RT_TRUE)
124     {
125         // rt_kprintf("mouse left key press up\n");
126         emouse.button = (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_UP);
127         rtgui_server_post_event(&emouse.parent, sizeof(struct rtgui_event_mouse));
128         lkey_down=RT_FALSE;
129     }
130 #endif
131     return RT_EOK;
132 }
133 
134 static rt_thread_t mouse_thread;
mouse_task(void * param)135 static void mouse_task(void* param)
136 {
137     struct uhintf* intf = (struct uhintf*)param;
138     while (1)
139     {
140         if (rt_usb_hcd_pipe_xfer(intf->device->hcd, ((struct uhid*)intf->user_data)->pipe_in,
141             ((struct uhid*)intf->user_data)->buffer, ((struct uhid*)intf->user_data)->pipe_in->ep.wMaxPacketSize,
142             USB_TIMEOUT_BASIC) == 0)
143         {
144             break;
145         }
146 
147         rt_usbh_hid_mouse_callback(intf->user_data);
148     }
149 }
150 
151 
rt_usbh_hid_mouse_init(void * arg)152 static rt_err_t rt_usbh_hid_mouse_init(void* arg)
153 {
154     struct uhintf* intf = (struct uhintf*)arg;
155 
156     RT_ASSERT(intf != RT_NULL);
157 
158     rt_usbh_hid_set_protocal(intf, 0);
159 
160     rt_usbh_hid_set_idle(intf, 0, 0);
161 
162     mouse_thread = rt_thread_create("mouse0", mouse_task, intf, 1024, 8, 100);
163     rt_thread_startup(mouse_thread);
164 
165     LOG_D("start usb mouse");
166 #ifdef RT_USING_RTGUI
167     RTGUI_EVENT_MOUSE_BUTTON_INIT(&emouse);
168     emouse.wid = RT_NULL;
169     cursor_display(RT_TRUE);
170 #endif
171     return RT_EOK;
172 }
173 
174 /**
175  * This function will define the hid mouse protocal, it will be register to the protocal list.
176  *
177  * @return the keyboard protocal structure.
178  */
rt_usbh_hid_protocal_mouse(void)179 uprotocal_t rt_usbh_hid_protocal_mouse(void)
180 {
181     mouse_protocal.pro_id = USB_HID_MOUSE;
182 
183     mouse_protocal.init = rt_usbh_hid_mouse_init;
184     mouse_protocal.callback = rt_usbh_hid_mouse_callback;
185 
186     return &mouse_protocal;
187 }
188 
189 #endif
190 
191