1 /** ----------------------------------------------------------------------
2  *
3  * Copyright (C) 2013 ST Microelectronics S.A.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *
18  ----------------------------------------------------------------------*/
19 
20 #include <assert.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <limits.h>
24 #include <linux/input.h> /* not required for all builds */
25 #include <poll.h>
26 #include <pthread.h>
27 #include <stdint.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/ioctl.h>
32 #include <unistd.h>
33 
34 #include "android_logmsg.h"
35 #include "halcore.h"
36 #include "halcore_private.h"
37 #include "hal_config.h"
38 
39 #define ST21NFC_MAGIC 0xEA
40 
41 #define ST21NFC_GET_WAKEUP _IOR(ST21NFC_MAGIC, 0x01, unsigned int)
42 #define ST21NFC_PULSE_RESET _IOR(ST21NFC_MAGIC, 0x02, unsigned int)
43 #define ST21NFC_SET_POLARITY_RISING _IOR(ST21NFC_MAGIC, 0x03, unsigned int)
44 #define ST21NFC_SET_POLARITY_FALLING _IOR(ST21NFC_MAGIC, 0x04, unsigned int)
45 #define ST21NFC_SET_POLARITY_HIGH _IOR(ST21NFC_MAGIC, 0x05, unsigned int)
46 #define ST21NFC_SET_POLARITY_LOW _IOR(ST21NFC_MAGIC, 0x06, unsigned int)
47 #define ST21NFC_RECOVERY _IOR(ST21NFC_MAGIC, 0x08, unsigned int)
48 #define ST21NFC_CLK_ENABLE _IOR(ST21NFC_MAGIC, 0x11, unsigned int)
49 #define ST21NFC_CLK_DISABLE _IOR(ST21NFC_MAGIC, 0x12, unsigned int)
50 #define ST21NFC_CLK_STATE _IOR(ST21NFC_MAGIC, 0x13, unsigned int)
51 
52 #define LINUX_DBGBUFFER_SIZE 300
53 
54 static int fidI2c = 0;
55 static int cmdPipe[2] = {0, 0};
56 static int notifyResetRequest = 0;
57 static bool recovery_mode = false;
58 
59 static struct pollfd event_table[3];
60 static pthread_t threadHandle = (pthread_t)NULL;
61 pthread_mutex_t i2ctransport_mtx = PTHREAD_MUTEX_INITIALIZER;
62 
63 unsigned long hal_ctrl_clk = 0;
64 unsigned long hal_activerw_timer = 0;
65 
66 /**************************************************************************************************
67  *
68  *                                      Private API Declaration
69  *
70  **************************************************************************************************/
71 
72 static int i2cSetPolarity(int fid, bool low, bool edge);
73 static int i2cResetPulse(int fid);
74 static int SetToRecoveryMode(int fid);
75 static int i2cRead(int fid, uint8_t* pvBuffer, int length);
76 static int i2cGetGPIOState(int fid);
77 static int i2cWrite(int fd, const uint8_t* pvBuffer, int length);
78 
79 /**************************************************************************************************
80  *
81  *                                      Public API Entry-Points
82  *
83  **************************************************************************************************/
84 
85 /**
86  * Worker thread for I2C data processing.
87  * On exit of this thread, destroy the HAL thread instance.
88  * @param arg  Handle of the HAL layer
89  */
I2cWorkerThread(void * arg)90 static void* I2cWorkerThread(void* arg) {
91   bool closeThread = false;
92   HALHANDLE hHAL = (HALHANDLE)arg;
93   STLOG_HAL_D("echo thread started...\n");
94   bool readOk = false;
95   int eventNum = (notifyResetRequest <= 0) ? 2 : 3;
96   bool reseting = false;
97 
98   do {
99     event_table[0].fd = fidI2c;
100     event_table[0].events = POLLIN;
101     event_table[0].revents = 0;
102 
103     event_table[1].fd = cmdPipe[0];
104     event_table[1].events = POLLIN;
105     event_table[1].revents = 0;
106 
107     event_table[2].fd = notifyResetRequest;
108     event_table[2].events = POLLPRI;
109     event_table[2].revents = 0;
110 
111     STLOG_HAL_V("echo thread go to sleep...\n");
112 
113     int poll_status = poll(event_table, eventNum, -1);
114 
115     if (-1 == poll_status) {
116       poll_status = errno;
117       STLOG_HAL_E("error in poll call : %d - %s\n", poll_status,
118                   strerror(poll_status));
119       if ((poll_status == EINTR) || (poll_status == EAGAIN)) continue;
120 
121       // other errors, we stop.
122       break;
123     }
124 
125     if (event_table[0].revents & POLLIN) {
126       STLOG_HAL_V("echo thread wakeup from chip...\n");
127       uint8_t buffer[300];
128       int count = 0;
129 
130       do {
131         if (recovery_mode) {
132           break;
133         }
134         // load first four bytes:
135         int bytesRead = i2cRead(fidI2c, buffer, 3);
136 
137         if (bytesRead == 3) {
138           if ((buffer[0] != 0x7E) && (buffer[1] != 0x7E)) {
139             readOk = true;
140           } else {
141             if (buffer[1] != 0x7E) {
142               STLOG_HAL_W(
143                   "Idle data: 2nd byte is 0x%02x\n, reading next 2 bytes",
144                   buffer[1]);
145               buffer[0] = buffer[1];
146               buffer[1] = buffer[2];
147               bytesRead = i2cRead(fidI2c, buffer + 2, 1);
148               if (bytesRead == 1) {
149                 readOk = true;
150               }
151             } else if (buffer[2] != 0x7E) {
152               STLOG_HAL_W("Idle data: 3rd byte is 0x%02x\n, reading next  byte",
153                           buffer[2]);
154               buffer[0] = buffer[2];
155               bytesRead = i2cRead(fidI2c, buffer + 1, 2);
156               if (bytesRead == 2) {
157                 readOk = true;
158               }
159             } else {
160               STLOG_HAL_W("received idle data\n");
161             }
162           }
163 
164           if (readOk == true) {
165             int remaining = buffer[2];
166             bytesRead = 0;
167             if (remaining != 0) {
168               // read and pass to HALCore
169               bytesRead = i2cRead(fidI2c, buffer + 3, remaining);
170             }
171             if (bytesRead == remaining) {
172               DispHal("RX DATA", buffer, 3 + bytesRead);
173               HalSendUpstream(hHAL, buffer, 3 + bytesRead);
174             } else {
175               readOk = false;
176               STLOG_HAL_E("! didn't read expected bytes from i2c\n");
177             }
178           }
179 
180         } else {
181           STLOG_HAL_E("! didn't read 3 requested bytes from i2c\n");
182         }
183 
184         readOk = false;
185         memset(buffer, 0xca, sizeof(buffer));
186         /* read while we have data available, up to 2 times then allow writes */
187       } while ((i2cGetGPIOState(fidI2c) == 1) && (count++ < 2));
188     }
189 
190     if (event_table[1].revents & POLLIN) {
191       STLOG_HAL_V("thread received command.. \n");
192 
193       char cmd = 0;
194       read(cmdPipe[0], &cmd, 1);
195 
196       switch (cmd) {
197         case 'X':
198           STLOG_HAL_D("received close command\n");
199           closeThread = true;
200           break;
201 
202         case 'W': {
203           size_t length;
204           uint8_t buffer[MAX_BUFFER_SIZE];
205           STLOG_HAL_V("received write command\n");
206           read(cmdPipe[0], &length, sizeof(length));
207           if (length <= MAX_BUFFER_SIZE) {
208             read(cmdPipe[0], buffer, length);
209             i2cWrite(fidI2c, buffer, length);
210           } else {
211             STLOG_HAL_E(
212                 "! received bigger data than expected!! Data not transmitted "
213                 "to NFCC \n");
214             size_t bytes_read = 1;
215             // Read all the data to empty but do not use it as not expected
216             while ((bytes_read > 0) && (length > 0)) {
217               bytes_read = read(cmdPipe[0], buffer, MAX_BUFFER_SIZE);
218               length = length - bytes_read;
219             }
220           }
221         } break;
222       }
223     }
224 
225     if (event_table[2].revents & POLLPRI && eventNum > 2) {
226       STLOG_HAL_W("thread received reset request command.. \n");
227       char reset[10];
228       int byte;
229       reset[9] = '\0';
230       lseek(notifyResetRequest, 0, SEEK_SET);
231       byte = read(notifyResetRequest, &reset, sizeof(reset));
232       if (byte < 10) {
233         reset[byte] = '\0';
234       }
235       if (byte > 0 && reset[0] =='1' && reseting == false) {
236         STLOG_HAL_E("trigger NFCC reset.. \n");
237         reseting = true;
238         i2cResetPulse(fidI2c);
239       }
240     }
241   } while (!closeThread);
242 
243   // Stop here if we got a serious error above.
244   assert(closeThread);
245 
246   close(fidI2c);
247   close(cmdPipe[0]);
248   close(cmdPipe[1]);
249   if (notifyResetRequest > 0) {
250     close(notifyResetRequest);
251   }
252 
253   HalDestroy(hHAL);
254   STLOG_HAL_D("thread exit\n");
255   return 0;
256 }
257 
258 /**
259  * Put command into queue for worker thread to process it.
260  * @param x Command 'X' to close I2C layer or 'W' to write data down to I2C
261  * layer followed by data frame
262  * @param len Size of command or data
263  * @return
264  */
I2cWriteCmd(const uint8_t * x,size_t len)265 int I2cWriteCmd(const uint8_t* x, size_t len) {
266   return write(cmdPipe[1], x, len);
267 }
268 
269 /**
270  * Initialize the I2C layer.
271  * @param dev NFC NCI device context, NFC callbacks for control/data, HAL handle
272  * @param callb HAL Core callback upon reception on I2C
273  * @param pHandle HAL context handle
274  */
I2cOpenLayer(void * dev,HAL_CALLBACK callb,HALHANDLE * pHandle)275 bool I2cOpenLayer(void* dev, HAL_CALLBACK callb, HALHANDLE* pHandle) {
276   uint32_t NoDbgFlag = HAL_FLAG_DEBUG;
277   char nfc_dev_node[64];
278   char nfc_reset_req_node[128];
279 
280   /*Read device node path*/
281   if (!GetStrValue(NAME_ST_NFC_DEV_NODE, (char *)nfc_dev_node,
282                    sizeof(nfc_dev_node))) {
283     STLOG_HAL_D("Open /dev/st21nfc\n");
284     strcpy(nfc_dev_node, "/dev/st21nfc");
285   }
286   /*Read nfcc reset request sysfs*/
287   if (GetStrValue(NAME_ST_NFC_RESET_REQ_SYSFS, (char *)nfc_reset_req_node,
288                   sizeof(nfc_reset_req_node))) {
289     STLOG_HAL_D("Open %s\n", nfc_reset_req_node);
290     notifyResetRequest = open(nfc_reset_req_node, O_RDONLY);
291     if (notifyResetRequest < 0) {
292       STLOG_HAL_E("unable to open %s (%s) \n", nfc_reset_req_node, strerror(errno));
293     }
294   }
295 
296   (void)pthread_mutex_lock(&i2ctransport_mtx);
297 
298   fidI2c = open(nfc_dev_node, O_RDWR);
299   if (fidI2c < 0) {
300     STLOG_HAL_W("unable to open %s (%s) \n", nfc_dev_node, strerror(errno));
301     (void)pthread_mutex_unlock(&i2ctransport_mtx);
302     return false;
303   }
304 
305   GetNumValue(NAME_STNFC_CONTROL_CLK, &hal_ctrl_clk, sizeof(hal_ctrl_clk));
306   GetNumValue(NAME_STNFC_ACTIVERW_TIMER, &hal_activerw_timer,
307               sizeof(hal_activerw_timer));
308 
309   if (hal_ctrl_clk) {
310     if (ioctl(fidI2c, ST21NFC_CLK_DISABLE, NULL) < 0) {
311       char msg[LINUX_DBGBUFFER_SIZE];
312       strerror_r(errno, msg, LINUX_DBGBUFFER_SIZE);
313       STLOG_HAL_E("ST21NFC_CLK_DISABLE failed errno %d(%s)", errno, msg);
314     }
315   }
316   i2cSetPolarity(fidI2c, false, false);
317   i2cResetPulse(fidI2c);
318 
319   if ((pipe(cmdPipe) == -1)) {
320     STLOG_HAL_W("unable to open cmdpipe\n");
321     (void)pthread_mutex_unlock(&i2ctransport_mtx);
322     return false;
323   }
324 
325   *pHandle = HalCreate(dev, callb, NoDbgFlag);
326 
327   if (!*pHandle) {
328     STLOG_HAL_E("failed to create NFC HAL Core \n");
329     (void)pthread_mutex_unlock(&i2ctransport_mtx);
330     return false;
331   }
332 
333   (void)pthread_mutex_unlock(&i2ctransport_mtx);
334 
335   return (pthread_create(&threadHandle, NULL, I2cWorkerThread, *pHandle) == 0);
336 }
337 
338 /**
339  * Terminates the I2C layer.
340  */
I2cCloseLayer()341 void I2cCloseLayer() {
342   uint8_t cmd = 'X';
343   int ret;
344   ALOGD("%s: enter\n", __func__);
345 
346   (void)pthread_mutex_lock(&i2ctransport_mtx);
347 
348   if (threadHandle == (pthread_t)NULL) {
349     (void)pthread_mutex_unlock(&i2ctransport_mtx);
350     return;
351   }
352 
353   I2cWriteCmd(&cmd, sizeof(cmd));
354   /* wait for terminate */
355   ret = pthread_join(threadHandle, (void**)NULL);
356   if (ret != 0) {
357     ALOGE("%s: failed to wait for thread (%d)", __func__, ret);
358   }
359   threadHandle = (pthread_t)NULL;
360   (void)pthread_mutex_unlock(&i2ctransport_mtx);
361 }
362 
363 /**
364  * Terminates the I2C layer.
365  */
I2cResetPulse()366 void I2cResetPulse() {
367   ALOGD("%s: enter\n", __func__);
368 
369   (void)pthread_mutex_lock(&i2ctransport_mtx);
370 
371   i2cResetPulse(fidI2c);
372   (void)pthread_mutex_unlock(&i2ctransport_mtx);
373 }
I2cRecovery()374 void I2cRecovery() {
375   ALOGD("%s: enter\n", __func__);
376 
377   (void)pthread_mutex_lock(&i2ctransport_mtx);
378   recovery_mode = true;
379   SetToRecoveryMode(fidI2c);
380   recovery_mode = false;
381   (void)pthread_mutex_unlock(&i2ctransport_mtx);
382 }
383 /**************************************************************************************************
384  *
385  *                                      Private API Definition
386  *
387  **************************************************************************************************/
388 /**
389  * Call the st21nfc driver to adjust wake-up polarity.
390  * @param fid File descriptor for NFC device
391  * @param low Polarity (HIGH or LOW)
392  * @param edge Polarity (RISING or FALLING)
393  * @return Result of IOCTL system call (0 if ok)
394  */
i2cSetPolarity(int fid,bool low,bool edge)395 static int i2cSetPolarity(int fid, bool low, bool edge) {
396   int result;
397   unsigned int io_code;
398 
399   if (low) {
400     if (edge) {
401       io_code = ST21NFC_SET_POLARITY_FALLING;
402     } else {
403       io_code = ST21NFC_SET_POLARITY_LOW;
404     }
405 
406   } else {
407     if (edge) {
408       io_code = ST21NFC_SET_POLARITY_RISING;
409     } else {
410       io_code = ST21NFC_SET_POLARITY_HIGH;
411     }
412   }
413 
414   if (-1 == (result = ioctl(fid, io_code, NULL))) {
415     result = -1;
416   }
417 
418   return result;
419 } /* i2cSetPolarity*/
420 
421 /**
422  * Call the st21nfc driver to generate a 30ms pulse on RESET line.
423  * @param fid File descriptor for NFC device
424  * @return Result of IOCTL system call (0 if ok)
425  */
i2cResetPulse(int fid)426 static int i2cResetPulse(int fid) {
427   int result;
428 
429   if (-1 == (result = ioctl(fid, ST21NFC_PULSE_RESET, NULL))) {
430     result = -1;
431   }
432   STLOG_HAL_D("! i2cResetPulse!!, result = %d", result);
433   return result;
434 } /* i2cResetPulse*/
435 
436 /**
437  * Call the st21nfc driver to generate pulses on RESET line to get a recovery.
438  * @param fid File descriptor for NFC device
439  * @return Result of IOCTL system call (0 if ok)
440  */
SetToRecoveryMode(int fid)441 static int SetToRecoveryMode(int fid) {
442   int result;
443 
444   if (-1 == (result = ioctl(fid, ST21NFC_RECOVERY, NULL))) {
445     result = -1;
446   }
447   STLOG_HAL_D("! SetToRecoveryMode!!, result = %d", result);
448   return result;
449 } /* SetToRecoveryMode*/
450 
451 /**
452  * Write data to st21nfc, on failure do max 3 retries.
453  * @param fid File descriptor for NFC device
454  * @param pvBuffer Data to write
455  * @param length Data size
456  * @return 0 if bytes written, -1 if error
457  */
i2cWrite(int fid,const uint8_t * pvBuffer,int length)458 static int i2cWrite(int fid, const uint8_t* pvBuffer, int length) {
459   int retries = 0;
460   int result = 0;
461   int halfsecs = 0;
462   int clk_state = -1;
463   char msg[LINUX_DBGBUFFER_SIZE];
464 
465   if ((hal_ctrl_clk || hal_activerw_timer) && length >= 4 &&
466       pvBuffer[0] == 0x20 && pvBuffer[1] == 0x09) {
467     if (hal_activerw_timer && (pvBuffer[3] == 0x01 || pvBuffer[3] == 0x03)) {
468       // screen off cases
469       hal_wrapper_set_state(HAL_WRAPPER_STATE_SET_ACTIVERW_TIMER);
470     }
471     if (hal_ctrl_clk && 0 > (clk_state = ioctl(fid, ST21NFC_CLK_STATE, NULL))) {
472       strerror_r(errno, msg, LINUX_DBGBUFFER_SIZE);
473       STLOG_HAL_E("ST21NFC_CLK_STATE failed errno %d(%s)", errno, msg);
474       clk_state = -1;
475     }
476     STLOG_HAL_D("ST21NFC_CLK_STATE = %d", clk_state);
477     if (clk_state == 1 && (pvBuffer[3] == 0x01 || pvBuffer[3] == 0x03)) {
478       // screen off cases
479       if (ioctl(fid, ST21NFC_CLK_DISABLE, NULL) < 0) {
480         strerror_r(errno, msg, LINUX_DBGBUFFER_SIZE);
481         STLOG_HAL_E("ST21NFC_CLK_DISABLE failed errno %d(%s)", errno, msg);
482       } else if (0 > (clk_state = ioctl(fid, ST21NFC_CLK_STATE, NULL))) {
483         strerror_r(errno, msg, LINUX_DBGBUFFER_SIZE);
484         STLOG_HAL_E("ST21NFC_CLK_STATE failed errno %d(%s)", errno, msg);
485         clk_state = -1;
486       }
487       if (clk_state != 0) {
488         STLOG_HAL_E("CLK_DISABLE STATE ERROR clk_state = %d", clk_state);
489       }
490     } else if (clk_state == 0 && (pvBuffer[3] == 0x02 || pvBuffer[3] == 0x00)) {
491       // screen on cases
492       if (ioctl(fid, ST21NFC_CLK_ENABLE, NULL) < 0) {
493         strerror_r(errno, msg, LINUX_DBGBUFFER_SIZE);
494         STLOG_HAL_E("ST21NFC_CLK_ENABLE failed errno %d(%s)", errno, msg);
495       } else if (0 > (clk_state = ioctl(fid, ST21NFC_CLK_STATE, NULL))) {
496         strerror_r(errno, msg, LINUX_DBGBUFFER_SIZE);
497         STLOG_HAL_E("ST21NFC_CLK_STATE failed errno %d(%s)", errno, msg);
498         clk_state = -1;
499       }
500       if (clk_state != 1) {
501         STLOG_HAL_E("CLK_ENABLE STATE ERROR clk_state = %d", clk_state);
502       }
503     }
504   }
505 
506 redo:
507   while (retries < 3) {
508     result = write(fid, pvBuffer, length);
509 
510     if (result < 0) {
511 
512       strerror_r(errno, msg, LINUX_DBGBUFFER_SIZE);
513       STLOG_HAL_W("! i2cWrite!!, errno is '%s'", msg);
514       usleep(4000);
515       retries++;
516     } else if (result > 0) {
517       result = 0;
518       return result;
519     } else {
520       STLOG_HAL_W("write on i2c failed, retrying\n");
521       usleep(4000);
522       retries++;
523     }
524   }
525   /* If we're here, we failed to write to NFCC. Retry after 500ms because some
526   CPUs have shown such long unavailability sometimes */
527   if (halfsecs < 10) {
528     usleep(500000);
529     retries = 0;
530     halfsecs++;
531     goto redo;
532   }
533   /* The CLF did not recover, give up */
534   return -1;
535 } /* i2cWrite */
536 
537 /**
538  * Read data from st21nfc, on failure do max 3 retries.
539  *
540  * @param fid File descriptor for NFC device
541  * @param pvBuffer Buffer where to copy read data
542  * @param length Data size to read
543  * @return Length of read data, -1 if error
544  */
i2cRead(int fid,uint8_t * pvBuffer,int length)545 static int i2cRead(int fid, uint8_t* pvBuffer, int length) {
546   int retries = 0;
547   int result = -1;
548 
549   while ((retries < 3) && (result < 0)) {
550     result = read(fid, pvBuffer, length);
551 
552     if (result == -1) {
553       int e = errno;
554       if (e == EAGAIN) {
555         /* File is nonblocking, and no data is available.
556          * This is not an error condition!
557          */
558         result = 0;
559         STLOG_HAL_D(
560             "## i2cRead - got EAGAIN. No data available. return 0 bytes");
561       } else {
562         /* unexpected result */
563         char msg[LINUX_DBGBUFFER_SIZE];
564         strerror_r(e, msg, LINUX_DBGBUFFER_SIZE);
565         STLOG_HAL_W("## i2cRead returns %d errno %d (%s)", result, e, msg);
566       }
567     }
568 
569     if (result < 0) {
570       if (retries < 3) {
571         /* delays are different and increasing for the three retries. */
572         static const uint8_t delayTab[] = {2, 3, 5};
573         int delay = delayTab[retries];
574 
575         retries++;
576         STLOG_HAL_W("## i2cRead retry %d/3 in %d milliseconds.", retries,
577                     delay);
578         usleep(delay * 1000);
579         continue;
580       }
581     }
582   }
583   return result;
584 } /* i2cRead */
585 
586 /**
587  * Get the activation status of wake-up pin from st21nfc.
588  *  The decision 'active' depends on selected polarity.
589  *  The decision is handled inside the driver(st21nfc).
590  * @param fid File descriptor for NFC device
591  * @return
592  *  Result < 0:     Error condition
593  *  Result > 0:     Pin active
594  *  Result = 0:     Pin not active
595  */
i2cGetGPIOState(int fid)596 static int i2cGetGPIOState(int fid) {
597   int result;
598 
599   if (-1 == (result = ioctl(fid, ST21NFC_GET_WAKEUP, NULL))) {
600     result = -1;
601   }
602 
603   return result;
604 } /* i2cGetGPIOState */
605