1+ /*
2+ * Goodix 5110 driver for libfprint
3+ *
4+ * Copyright (C) 2021 Alexander Meiler <[email protected] > 5+ *
6+ * This library is free software; you can redistribute it and/or
7+ * modify it under the terms of the GNU Lesser General Public
8+ * License as published by the Free Software Foundation; either
9+ * version 2.1 of the License, or (at your option) any later version.
10+ *
11+ * This library is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+ * Lesser General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU Lesser General Public
17+ * License along with this library; if not, write to the Free Software
18+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19+ */
20+
21+ #define FP_COMPONENT "goodix5110"
22+
23+ #include "drivers_api.h"
24+ #include "goodix5110.h"
25+
26+ struct _FpiDeviceGoodix
27+ {
28+ FpImageDevice parent ;
29+
30+ /* device config */
31+ // unsigned short dev_type;
32+ char * fw_ver ;
33+ // void (*process_frame) (unsigned short *raw_frame,
34+ // GSList ** frames);
35+ /* end device config */
36+
37+ /* commands */
38+ const struct goodix_cmd * cmd ;
39+ int cmd_timeout ;
40+ /* end commands */
41+
42+ /* state */
43+ gboolean active ;
44+ gboolean deactivating ;
45+ unsigned char * last_read ;
46+ // unsigned char calib_atts_left;
47+ // unsigned char calib_status;
48+ unsigned short * background ;
49+ // unsigned char frame_width;
50+ // unsigned char frame_height;
51+ // unsigned char raw_frame_height;
52+ // int num_frames;
53+ // GSList *frames;
54+ /* end state */
55+ };
56+ G_DEFINE_TYPE (FpiDeviceGoodix , fpi_device_goodix , FP_TYPE_IMAGE_DEVICE );
57+
58+ static void
59+ goodix_cmd_done (FpiSsm * ssm )
60+ {
61+ G_DEBUG_HERE ();
62+ fpi_ssm_next_state (ssm );
63+ }
64+
65+ static void
66+ goodix_cmd_read (FpiSsm * ssm , FpDevice * dev , int response_len )
67+ {
68+ FpiDeviceGoodix * self = FPI_DEVICE_GOODIX (dev );
69+ FpiUsbTransfer * transfer ;
70+ GCancellable * cancellable = NULL ;
71+ //int response_len = self->cmd->response_len;
72+
73+ G_DEBUG_HERE ();
74+
75+ if (self -> cmd -> response_len == GOODIX_CMD_SKIP_READ )
76+ {
77+ fp_dbg ("skipping read, not expecting anything" );
78+ goodix_cmd_done (ssm );
79+ return ;
80+ }
81+
82+ g_clear_pointer (& self -> last_read , g_free );
83+
84+ transfer = fpi_usb_transfer_new (dev );
85+ transfer -> ssm = ssm ;
86+ transfer -> short_is_error = TRUE;
87+
88+ fpi_usb_transfer_fill_bulk (transfer ,
89+ GOODIX_EP_CMD_IN ,
90+ response_len );
91+
92+ fpi_usb_transfer_submit (transfer , self -> cmd_timeout , cancellable , goodix_cmd_cb , NULL );
93+ }
94+
95+ static void
96+ goodix_cmd_cb (FpiUsbTransfer * transfer , FpDevice * dev ,
97+ gpointer user_data , GError * error )
98+ {
99+ FpiSsm * ssm = transfer -> ssm ;
100+ FpiDeviceGoodix * self = FPI_DEVICE_GOODIX (dev );
101+
102+ G_DEBUG_HERE ();
103+
104+ if (error )
105+ {
106+ /* XXX: In the cancellation case we used to not
107+ * mark the SSM as failed?! */
108+ fpi_ssm_mark_failed (transfer -> ssm , error );
109+ return ;
110+ }
111+
112+ /* XXX: We used to reset the device in error cases! */
113+ if (transfer -> endpoint & FPI_USB_ENDPOINT_IN )
114+ {
115+ /* just finished receiving */
116+ self -> last_read = g_memdup (transfer -> buffer , transfer -> actual_length );
117+ //fp_dbg("%lu", transfer->actual_length);
118+ if (self -> cmd -> cmd == read_fw .cmd )
119+ {
120+ if (transfer -> actual_length == self -> cmd -> response_len )
121+ {
122+ // We got ACK, now wait for the firmware string packet
123+ G_DEBUG_HERE ();
124+ goodix_cmd_read (ssm , dev , self -> cmd -> response_len_2 );
125+ }
126+ else
127+ {
128+ // Reading the firmware version
129+ self -> fw_ver = g_memdup (& self -> last_read [7 ], self -> cmd -> response_len_2 );
130+ G_DEBUG_HERE ();
131+ goodix_cmd_done (ssm );
132+ }
133+ }
134+ else
135+ {
136+ goodix_cmd_done (ssm );
137+ }
138+ }
139+ else
140+ {
141+ /* just finished sending */
142+ G_DEBUG_HERE ();
143+ goodix_cmd_read (ssm , dev , self -> cmd -> response_len );
144+ }
145+ }
146+
147+ static void
148+ goodix_run_cmd (FpiSsm * ssm ,
149+ FpDevice * dev ,
150+ const struct goodix_cmd * cmd ,
151+ int cmd_timeout )
152+ {
153+ FpiDeviceGoodix * self = FPI_DEVICE_GOODIX (dev );
154+ FpiUsbTransfer * transfer ;
155+ GCancellable * cancellable = NULL ;
156+
157+ self -> cmd = cmd ;
158+
159+ transfer = fpi_usb_transfer_new (dev );
160+ transfer -> ssm = ssm ;
161+ transfer -> short_is_error = TRUE;
162+
163+ fpi_usb_transfer_fill_bulk_full (transfer ,
164+ GOODIX_EP_CMD_OUT ,
165+ (guint8 * ) cmd -> cmd ,
166+ GOODIX_CMD_LEN ,
167+ NULL );
168+
169+ fpi_usb_transfer_submit (transfer ,
170+ cmd_timeout ,
171+ cancellable ,
172+ goodix_cmd_cb ,
173+ NULL );
174+ }
175+
176+ /* ------------------------------------------------------------------------------- */
177+
178+ /* ---- ACTIVE SECTION START ---- */
179+
180+ enum activate_states {
181+ ACTIVATE_NOP1 ,
182+ ACTIVATE_ENABLE_CHIP ,
183+ ACTIVATE_NOP2 ,
184+ ACTIVATE_GET_FW_VER ,
185+ ACTIVATE_VERIFY_FW_VER ,
186+ ACTIVATE_NUM_STATES
187+ };
188+
189+ static void
190+ activate_run_state (FpiSsm * ssm , FpDevice * dev )
191+ {
192+ FpiDeviceGoodix * self = FPI_DEVICE_GOODIX (dev );
193+
194+ G_DEBUG_HERE ();
195+
196+ switch (fpi_ssm_get_cur_state (ssm ))
197+ {
198+ // NOP seems to do nothing, but the Windows driver does it in places too
199+ case ACTIVATE_NOP1 :
200+ case ACTIVATE_NOP2 :
201+ goodix_run_cmd (ssm , dev , & nop , GOODIX_CMD_TIMEOUT );
202+ break ;
203+
204+ case ACTIVATE_ENABLE_CHIP :
205+ goodix_run_cmd (ssm , dev , & enable_chip , GOODIX_CMD_TIMEOUT );
206+ break ;
207+
208+ case ACTIVATE_GET_FW_VER :
209+ goodix_run_cmd (ssm , dev , & read_fw , GOODIX_CMD_TIMEOUT );
210+ break ;
211+
212+ case ACTIVATE_VERIFY_FW_VER :
213+ if (strcmp (self -> fw_ver , GOODIX_FIRMWARE_VERSION_SUPPORTED ) == 0 )
214+ {
215+ // The firmware version supports the 0xF2 command to directly read from the MCU SRAM
216+ fpi_ssm_mark_completed (ssm );
217+ }
218+ else
219+ {
220+ // The firmware version is unsupported
221+ fpi_ssm_mark_failed (ssm , fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL , "Unsupported firmware!" ));
222+ }
223+ }
224+ }
225+
226+ static void
227+ activate_complete (FpiSsm * ssm , FpDevice * dev , GError * error )
228+ {
229+ FpImageDevice * idev = FP_IMAGE_DEVICE (dev );
230+
231+ G_DEBUG_HERE ();
232+
233+ fpi_image_device_activate_complete (idev , error );
234+
235+ }
236+
237+ static void
238+ goodix_activate (FpImageDevice * dev )
239+ {
240+ FpiDeviceGoodix * self = FPI_DEVICE_GOODIX (dev );
241+
242+ G_DEBUG_HERE ();
243+ goodix_dev_reset_state (self );
244+
245+ FpiSsm * ssm =
246+ fpi_ssm_new (FP_DEVICE (dev ), activate_run_state ,
247+ ACTIVATE_NUM_STATES );
248+
249+ fpi_ssm_start (ssm , activate_complete );
250+ }
251+
252+ /* ---- ACTIVE SECTION END ---- */
253+
254+ /* ------------------------------------------------------------------------------- */
255+
256+ /* ---- DEV SECTION START ---- */
257+
258+ static void
259+ dev_init (FpImageDevice * dev )
260+ {
261+ GError * error = NULL ;
262+ // FpiDeviceGoodix *self;
263+
264+ G_DEBUG_HERE ();
265+
266+ if (!g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev )), 0 , 0 , & error ))
267+ {
268+ fpi_image_device_open_complete (dev , error );
269+ return ;
270+ }
271+
272+ // self = FPI_DEVICE_GOODIX (dev);
273+
274+ fpi_image_device_open_complete (dev , NULL );
275+ }
276+
277+ static void
278+ goodix_dev_reset_state (FpiDeviceGoodix * goodixdev )
279+ {
280+ G_DEBUG_HERE ();
281+
282+ goodixdev -> cmd = NULL ;
283+ goodixdev -> cmd_timeout = GOODIX_CMD_TIMEOUT ;
284+
285+ g_free (goodixdev -> last_read );
286+ goodixdev -> last_read = NULL ;
287+ }
288+
289+ static void
290+ dev_deinit (FpImageDevice * dev )
291+ {
292+ GError * error = NULL ;
293+ FpiDeviceGoodix * self = FPI_DEVICE_GOODIX (dev );
294+
295+ G_DEBUG_HERE ();
296+
297+ goodix_dev_reset_state (self );
298+ g_free (self -> background );
299+ g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev )),
300+ 0 , 0 , & error );
301+ fpi_image_device_close_complete (dev , error );
302+ }
303+
304+ static void
305+ dev_activate (FpImageDevice * dev )
306+ {
307+ G_DEBUG_HERE ();
308+ goodix_activate (dev );
309+ }
310+
311+ static void
312+ dev_change_state (FpImageDevice * dev , FpiImageDeviceState state )
313+ {
314+ //FpiDeviceGoodix *self = FPI_DEVICE_GOODIX (dev);
315+
316+ G_DEBUG_HERE ();
317+ }
318+
319+ static void
320+ dev_deactivate (FpImageDevice * dev )
321+ {
322+ FpiDeviceGoodix * self = FPI_DEVICE_GOODIX (dev );
323+
324+ G_DEBUG_HERE ();
325+
326+ if (!self -> active )
327+ /* The device is inactive already, complete the operation immediately. */
328+ fpi_image_device_deactivate_complete (dev , NULL );
329+ else
330+ /* The device is not yet inactive, flag that we are deactivating (and
331+ * need to signal back deactivation).
332+ * Note that any running capture will be cancelled already if needed. */
333+ self -> deactivating = TRUE;
334+ }
335+
336+ /* ---- DEV SECTION END ---- */
337+
338+ /* ------------------------------------------------------------------------------- */
339+
340+ /* ---- FPI SECTION START ---- */
341+
342+ static void
343+ fpi_device_goodix_init (FpiDeviceGoodix * self )
344+ {
345+ // nothing to be done here, move along
346+ }
347+
348+ static void
349+ fpi_device_goodix_class_init (FpiDeviceGoodixClass * class )
350+ {
351+ FpDeviceClass * dev_class = FP_DEVICE_CLASS (class );
352+ FpImageDeviceClass * img_class = FP_IMAGE_DEVICE_CLASS (class );
353+
354+ dev_class -> id = "goodix" ;
355+ dev_class -> full_name = "Goodix 5110 Fingerprint Sensor" ;
356+ dev_class -> type = FP_DEVICE_TYPE_USB ;
357+ dev_class -> id_table = goodix_id_table ;
358+ dev_class -> scan_type = FP_SCAN_TYPE_SWIPE ;
359+
360+ img_class -> img_open = dev_init ;
361+ img_class -> img_close = dev_deinit ;
362+ img_class -> activate = dev_activate ;
363+ img_class -> deactivate = dev_deactivate ;
364+ img_class -> change_state = dev_change_state ;
365+
366+ // ToDo
367+ img_class -> bz3_threshold = 24 ;
368+ }
369+
370+ /* ---- FPI SECTION END ---- */
0 commit comments