6
6
#include "qemu/timer.h"
7
7
#include "ui/console.h"
8
8
9
+ enum {
10
+ state_first ,
11
+ state_second ,
12
+ state_ready_for_read ,
13
+ state_internal_register_mode ,
14
+ state_internal_register_mode_data ,
15
+
16
+ state_read_buffer ,
17
+ state_read_point_buffer_ready ,
18
+ state_end ,
19
+ };
20
+
21
+
22
+ #define BUFFER_QUERY 0b100
23
+ #define BUFFER_POINT 0b111
24
+
9
25
#define TYPE_IT7259 "it7259"
10
26
#define IT7259 (obj ) OBJECT_CHECK(IT7259State, (obj), TYPE_IT7259)
11
27
12
28
typedef struct {
13
29
I2CSlave parent_obj ;
14
30
15
- int state ;
16
- uint8_t buffer ;
17
- int reserved ;
31
+ qemu_irq interrupt ;
32
+
33
+ int state ;
34
+ int pos ;
35
+ uint8_t buffer [256 ];
36
+ uint8_t buf ;
37
+ int reserved ;
18
38
uint8_t rw ;
19
39
uint8_t reg ;
40
+ bool isTouching ;
41
+ bool isChange ;
42
+ uint8_t x ;
43
+ uint8_t y ;
44
+ uint8_t register_addr ;
20
45
} IT7259State ;
21
46
22
- static int it7259_event (I2CSlave * i2c , enum i2c_event event )
23
- {
47
+
48
+ static void it7259_int_update (IT7259State * s ) {
49
+ if (s -> isChange ) {
50
+ qemu_irq_pulse (s -> interrupt );
51
+ }
52
+
53
+ }
54
+
55
+ static void it7259_reset (IT7259State * s ) {
56
+ s -> state = state_first ;
57
+ s -> pos = 0 ;
58
+ }
59
+
60
+ static void it7259_read (IT7259State * s ) {
61
+ if (s -> state == state_internal_register_mode_data ) {
62
+ s -> pos = 0 ;
63
+ } else if (s -> state == state_read_buffer ) {
64
+ s -> pos = 0 ;
65
+ if (s -> buf == BUFFER_QUERY ) {
66
+ s -> buffer [0 ] = 0 ;
67
+ s -> buffer [0 ] = s -> isTouching << 6 ;
68
+ s -> buffer [0 ] = s -> isChange << 7 ;
69
+ } else if (s -> buf == BUFFER_POINT ) {
70
+ memset (s -> buffer , 0 , sizeof (s -> buffer ));
71
+ s -> buffer [0 ] = 0b0000 << 4 | s -> isTouching << 3 | s -> isTouching << 0 ;
72
+ s -> buffer [1 ] = 0 ;
73
+ if (s -> isTouching ) {
74
+ s -> buffer [2 ] = s -> y ;
75
+ s -> buffer [3 ] = 0 ; // high bits of x/y
76
+ s -> buffer [4 ] = s -> x ;
77
+ s -> buffer [5 ] = 0x4 ; // Normal finger contact.
78
+ }
79
+ s -> isChange = false;
80
+ it7259_int_update (s );
81
+ } else {
82
+ assert (false);
83
+ }
84
+
85
+ s -> pos = 0 ;
86
+ s -> state = state_ready_for_read ;
87
+ } else { printf ("Unknown buffer: %d" , s -> buf ); }
88
+ }
89
+
90
+ static int it7259_event (I2CSlave * i2c , enum i2c_event event ) {
24
91
IT7259State * s = IT7259 (i2c );
25
92
93
+ printf ("[IT7259] event: %d\n" , event );
26
94
switch (event ) {
27
- case I2C_START_SEND :
28
- printf ( "[IT7259] START SEND\n" , event );
95
+ case I2C_START_RECV :
96
+ it7259_read ( s );
29
97
break ;
98
+ case I2C_START_SEND :
99
+ it7259_reset (s );
30
100
default :
31
101
case I2C_FINISH :
32
- case I2C_START_RECV :
33
- printf ("[IT7259] event %d\n" , event );
34
102
break ;
35
103
}
36
104
37
105
return 0 ;
38
106
}
39
107
40
- static uint8_t it7259_rx (I2CSlave * i2c )
41
- {
108
+ static uint8_t it7259_rx (I2CSlave * i2c ) {
42
109
IT7259State * s = IT7259 (i2c );
43
110
44
- assert (s -> state == 2 );
45
- s -> state = 0 ;
46
- switch (s -> reg ) {
47
- case 0x32 :
48
- return 0x59 ; // Device ID 2
49
- case 0x33 :
50
- return 0x72 ; // Device ID 1
111
+ if (s -> state == state_internal_register_mode_data ) {
112
+ // Only allow single reads
113
+ assert (s -> pos == 0 );
114
+ s -> pos ++ ;
115
+ switch (s -> register_addr ) {
116
+ case 0x32 :
117
+ return 0x59 ;
118
+ case 0x33 :
119
+ return 0x72 ;
120
+ default :
121
+ printf ("[IT7259] Read internal register: 0x%02X\n" , s -> register_addr );
122
+ break ;
123
+ }
124
+
125
+ } else {
126
+
127
+ assert (s -> state == state_ready_for_read );
128
+ printf ("[IT7259] read 0x%02X\n" , s -> buffer [s -> pos ]);
129
+ return s -> buffer [s -> pos ++ ];
51
130
}
52
131
53
- return 0 ;
132
+ return 0xFF ;
54
133
}
55
134
56
- static int it7259_tx (I2CSlave * i2c , uint8_t data )
57
- {
135
+ static int it7259_tx (I2CSlave * i2c , uint8_t data ) {
58
136
IT7259State * s = IT7259 (i2c );
59
137
60
- if (s -> state == 0 ) {
61
- s -> reserved = data & 0b1111 ;
62
- s -> buffer = (data >> 4 )& 0b111 ;
63
- s -> rw = data >>7 ;
64
- assert (s -> reserved == 0b0000 );
65
- assert (s -> buffer == 0b111 );
66
- assert (s -> rw == 0b0 );
67
- s -> state ++ ;
68
- } else if (s -> state == 1 ) {
69
- s -> reg = data ;
70
- s -> state ++ ;
138
+ printf ("[IT7259] write 0x%02X\n" , data );
139
+
140
+ if (s -> state == state_first ) {
141
+ uint8_t m = (data >> 4 & 0b1 );
142
+ uint8_t addr = (data >> 5 & 0b11 );
143
+ uint8_t rw = (data >> 7 & 0b1 );
144
+ if (addr == 0b11 && m == 0b1 ) {
145
+ assert (rw == 0b0 ); // Datasheet only uses 0x70 for the first byte
146
+ s -> state = state_internal_register_mode ;
147
+ } else {
148
+ s -> reserved = data & 0b11111 ;
149
+ s -> buf = (data >> 5 ) & 0b111 ;
150
+ // assert(s->reserved == 0b00000);
151
+ if (s -> buf == BUFFER_POINT || s -> buf == BUFFER_QUERY ) {
152
+ s -> state = state_read_buffer ;
153
+ } else {
154
+ printf ("[IT7259] Unknown buffer: %d\n" , s -> buf );
155
+ assert (false);
156
+ }
157
+ }
158
+ } else if (s -> state == state_internal_register_mode ) {
159
+ s -> register_addr = data ;
160
+ s -> state = state_internal_register_mode_data ;
161
+ } else {
162
+ s -> buffer [s -> pos ++ ] = data ;
71
163
}
72
164
73
- printf ("[IT7259] cmd: 0x%02X\n" , data );
165
+ return 0 ;
166
+ }
74
167
168
+ static void it7259_ts_event (void * opaque ,
169
+ int x , int y , int z , int buttons_state ) {
170
+ IT7259State * s = opaque ;
171
+
172
+
173
+ if (buttons_state & MOUSE_EVENT_LBUTTON ) {
174
+ if (!s -> isTouching ) {
175
+ s -> isTouching = true;
176
+ s -> isChange = true;
177
+ }
178
+ if (s -> x != x ) {
179
+ s -> isChange = true;
180
+ s -> x = (uint8_t ) ((float ) x / (float ) 0x7FFF * 176.0 );
181
+ }
182
+ if (s -> y != y ) {
183
+ s -> isChange = true;
184
+ s -> y = (uint8_t ) ((float ) y / (float ) 0x7FFF * 176.0 );
185
+ }
186
+ printf ("[it7259] Mouse: %d, %d\n" , s -> x , s -> y );
187
+ } else {
188
+ if (s -> isTouching ) {
189
+ s -> isTouching = false;
190
+ s -> isChange = true;
191
+ }
192
+ }
75
193
76
- return 0 ;
194
+ it7259_int_update ( s ) ;
77
195
}
78
196
79
- static void it7259_realize (DeviceState * dev , Error * * errp )
80
- {
197
+ static void it7259_realize (DeviceState * dev , Error * * errp ) {
81
198
IT7259State * s = IT7259 (dev );
199
+
200
+ qdev_init_gpio_out (dev , & s -> interrupt , 1 );
201
+
202
+ qemu_add_mouse_event_handler (it7259_ts_event , s , 1 , "amazfit-mouse" );
203
+ it7259_reset (s );
82
204
}
83
205
84
- static void it7259_class_init (ObjectClass * klass , void * data )
85
- {
206
+ static void it7259_class_init (ObjectClass * klass , void * data ) {
86
207
DeviceClass * dc = DEVICE_CLASS (klass );
87
208
I2CSlaveClass * k = I2C_SLAVE_CLASS (klass );
88
209
@@ -93,10 +214,10 @@ static void it7259_class_init(ObjectClass *klass, void *data)
93
214
}
94
215
95
216
static const TypeInfo it7259_info = {
96
- .name = TYPE_IT7259 ,
97
- .parent = TYPE_I2C_SLAVE ,
98
- .instance_size = sizeof (IT7259State ),
99
- .class_init = it7259_class_init ,
217
+ .name = TYPE_IT7259 ,
218
+ .parent = TYPE_I2C_SLAVE ,
219
+ .instance_size = sizeof (IT7259State ),
220
+ .class_init = it7259_class_init ,
100
221
};
101
222
102
223
static void it7259_register_types (void ) { type_register_static (& it7259_info ); }
0 commit comments