userial_linux.c revision 0eb7353a4877b921c2d4b9226ecad2d1cc672dcb
1/******************************************************************************
2 *
3 *  Copyright (C) 1999-2012 Broadcom Corporation
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#include "OverrideLog.h"
20#include <string.h>
21#include "gki.h"
22#include "nfc_hal_api.h"
23#include "nfc_hal_int.h"
24#include "userial.h"
25#include "nfc_target.h"
26
27#include <pthread.h>
28#include <termios.h>
29#include <fcntl.h>
30#include <errno.h>
31#include <stdio.h>
32#include <gki_int.h>
33#include "hcidefs.h"
34#include <poll.h>
35#include "upio.h"
36#include "bcm2079x.h"
37#include "config.h"
38
39#define HCISU_EVT                           EVENT_MASK(APPL_EVT_0)
40#define MAX_ERROR                           10
41#define default_transport                   "/dev/bcm2079x"
42
43#define NUM_RESET_ATTEMPTS                  5
44#define NFC_WAKE_ASSERTED_ON_POR            UPIO_OFF
45
46#ifndef BTE_APPL_MAX_USERIAL_DEV_NAME
47#define BTE_APPL_MAX_USERIAL_DEV_NAME           (256)
48#endif
49extern UINT8 appl_trace_level;
50
51/* Mapping of USERIAL_PORT_x to linux */
52extern UINT32 ScrProtocolTraceFlag;
53static tUPIO_STATE current_nfc_wake_state = UPIO_OFF;
54int uart_port  = 0;
55int isLowSpeedTransport = 0;
56int nfc_wake_delay = 0;
57int nfc_write_delay = 0;
58int gPowerOnDelay = 300;
59static int gPrePowerOffDelay = 0;    // default value
60static int gPostPowerOffDelay = 0;     // default value
61static pthread_mutex_t close_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
62
63char userial_dev[BTE_APPL_MAX_USERIAL_DEV_NAME+1];
64char power_control_dev[BTE_APPL_MAX_USERIAL_DEV_NAME+1];
65tSNOOZE_MODE_CONFIG gSnoozeModeCfg = {
66    NFC_HAL_LP_SNOOZE_MODE_SPI_I2C,     /* Sleep Mode (0=Disabled 1=UART 8=SPI/I2C) */
67    NFC_HAL_LP_IDLE_THRESHOLD_HOST,     /* Idle Threshold Host */
68    NFC_HAL_LP_IDLE_THRESHOLD_HC,       /* Idle Threshold HC */
69    NFC_HAL_LP_ACTIVE_LOW,              /* NFC Wake active mode (0=ActiveLow 1=ActiveHigh) */
70    NFC_HAL_LP_ACTIVE_HIGH              /* Host Wake active mode (0=ActiveLow 1=ActiveHigh) */
71};
72
73UINT8 bcmi2cnfc_client_addr = 0;
74UINT8 bcmi2cnfc_read_multi_packets = 0;
75
76#define USERIAL_Debug_verbose     ((ScrProtocolTraceFlag & 0x80000000) == 0x80000000)
77
78#include <sys/socket.h>
79
80#define LOG_TAG "USERIAL_LINUX"
81
82static UINT8 spi_negotiation[10] = { 0xF0, /* CMD */
83                                    0x00, /* SPI PARM Negotiation */
84                                    0x01, /* SPI Version */
85                                    0x00, /* SPI Mode:0, SPI_INT active low */
86                                    0x00, /* 8Bit, MSB first, Little Endian byte order */
87                                    0x00, /* Reserved */
88                                    0xFF, /* Sleep timeout Lower Byte */
89                                    0xFF, /* Sleep timeout Upper Byte */
90                                    0x00, /* Reserved */
91                                    0x00 /* Reserved */
92};
93static UINT8 spi_nego_res[20];
94
95#include <ctype.h>
96
97#define USING_BRCM_USB TRUE
98
99/* use tc interface to change baudrate instead of close/open sequence which can fail on some platforms
100 * due to tx line movement when opeing/closing the UART. the 43xx do not like this. */
101#ifndef USERIAL_USE_TCIO_BAUD_CHANGE
102#define USERIAL_USE_TCIO_BAUD_CHANGE FALSE
103#endif
104
105#ifndef USERIAL_USE_IO_BT_WAKE
106#define USERIAL_USE_IO_BT_WAKE FALSE
107#endif
108
109/* this are the ioctl values used for bt_wake ioctl via UART driver. you may need to redefine at for
110 * you platform! Logically they need to be unique and not colide with existing uart ioctl's.
111 */
112#ifndef USERIAL_IO_BT_WAKE_ASSERT
113#define USERIAL_IO_BT_WAKE_ASSERT   0x8003
114#endif
115#ifndef USERIAL_IO_BT_WAKE_DEASSERT
116#define USERIAL_IO_BT_WAKE_DEASSERT 0x8004
117#endif
118#ifndef USERIAL_IO_BT_WAKE_GET_ST
119#define USERIAL_IO_BT_WAKE_GET_ST   0x8005
120#endif
121
122/* the read limit in this current implementation depends on the GKI_BUF3_SIZE
123 * It would be better to use some ring buffer from the USERIAL_Read() is reading
124 * instead of putting it into GKI buffers.
125 */
126#define READ_LIMIT (USERIAL_POOL_BUF_SIZE-BT_HDR_SIZE)
127/*
128 * minimum buffer size requirement to read a full sized packet from NFCC = 255 + 4 byte header
129 */
130#define MIN_BUFSIZE 259
131#define     POLL_TIMEOUT    1000
132/* priority of the reader thread */
133#define USERIAL_READ_TRHEAD_PRIO 90
134/* time (ms) to wait before trying to allocate again a GKI buffer */
135#define NO_GKI_BUFFER_RECOVER_TIME 100
136#define MAX_SERIAL_PORT (USERIAL_PORT_15 + 1)
137
138extern void dumpbin(const char* data, int size);
139extern UINT8 *scru_dump_hex (UINT8 *p, char *p_title, UINT32 len, UINT32 trace_layer, UINT32 trace_type);
140
141static pthread_t      worker_thread1 = 0;
142
143typedef struct  {
144    volatile unsigned long bt_wake_state;
145    int             sock;
146    tUSERIAL_CBACK      *ser_cb;
147    UINT16      baud;
148    UINT8       data_bits;
149    UINT16      parity;
150    UINT8       stop_bits;
151    UINT8       port;
152    tUSERIAL_OPEN_CFG open_cfg;
153    int         sock_power_control;
154    int         client_device_address;
155    struct timespec write_time;
156} tLINUX_CB;
157
158static tLINUX_CB linux_cb;  /* case of multipel port support use array : [MAX_SERIAL_PORT] */
159
160void userial_close_thread(UINT32 params);
161
162static UINT8 device_name[BTE_APPL_MAX_USERIAL_DEV_NAME+1];
163static int   bSerialPortDevice = FALSE;
164static int _timeout = POLL_TIMEOUT;
165static BOOLEAN is_close_thread_is_waiting = FALSE;
166
167
168int   perf_log_every_count = 0;
169typedef struct {
170    const char* label;
171    long    lapse;
172    long    bytes;
173    long    count;
174    long    overhead;
175} tPERF_DATA;
176
177/*******************************************************************************
178**
179** Function         perf_reset
180**
181** Description      reset performance measurement data
182**
183** Returns          none
184**
185*******************************************************************************/
186void perf_reset(tPERF_DATA* t)
187{
188    t->count =
189    t->bytes =
190    t->lapse = 0;
191}
192
193/*******************************************************************************
194**
195** Function         perf_log
196**
197** Description      produce a log entry of cvurrent performance data
198**
199** Returns          none
200**
201*******************************************************************************/
202void perf_log(tPERF_DATA* t)
203{
204    // round to nearest ms
205    // t->lapse += 500;
206    // t->lapse /= 1000;
207    if (t->lapse)
208    {
209        if (t->bytes)
210            ALOGD( "%s:%s, bytes=%ld, lapse=%ld (%d.%02d kbps) (bus data rate %d.%02d kbps) overhead %d(%d percent)\n",
211                    __func__,
212                    t->label, t->bytes, t->lapse,
213                    (int)(8 * t->bytes / t->lapse), (int)(800 * t->bytes / (t->lapse)) % 100,
214                    (int)(9 * (t->bytes + t->count * t->overhead) / t->lapse), (int)(900 * (t->bytes + t->count * t->overhead) / (t->lapse)) % 100,
215                    (int)(t->count * t->overhead), (int)(t->count * t->overhead * 100 / t->bytes)
216                    );
217        else
218            ALOGD( "%s:%s, lapse=%ld (average %ld)\n", __func__,
219                    t->label, t->lapse, (int)t->lapse / t->count
220                    );
221    }
222    perf_reset(t);
223}
224
225/*******************************************************************************
226**
227** Function         perf_update
228**
229** Description      update perforamnce measurement data
230**
231** Returns          none
232**
233*******************************************************************************/
234void perf_update(tPERF_DATA* t, long lapse, long bytes)
235{
236    if (!perf_log_every_count)
237        return;
238    // round to nearest ms
239    lapse += 500;
240    lapse /= 1000;
241    t->count++;
242    t->bytes += bytes;
243    t->lapse += lapse;
244    if (t->count == perf_log_every_count)
245        perf_log(t);
246}
247
248static tPERF_DATA   perf_poll = {"USERIAL_Poll", 0, 0, 0, 0};
249static tPERF_DATA   perf_read = {"USERIAL_Read", 0, 0, 0, 9};
250static tPERF_DATA   perf_write = {"USERIAL_Write", 0, 0, 0, 3};
251static tPERF_DATA   perf_poll_2_poll = {"USERIAL_Poll_to_Poll", 0, 0, 0, 0};
252static clock_t      _poll_t0 = 0;
253
254static UINT32 userial_baud_tbl[] =
255{
256    300,        /* USERIAL_BAUD_300          0 */
257    600,        /* USERIAL_BAUD_600          1 */
258    1200,       /* USERIAL_BAUD_1200         2 */
259    2400,       /* USERIAL_BAUD_2400         3 */
260    9600,       /* USERIAL_BAUD_9600         4 */
261    19200,      /* USERIAL_BAUD_19200        5 */
262    57600,      /* USERIAL_BAUD_57600        6 */
263    115200,     /* USERIAL_BAUD_115200       7 */
264    230400,     /* USERIAL_BAUD_230400       8 */
265    460800,     /* USERIAL_BAUD_460800       9 */
266    921600,     /* USERIAL_BAUD_921600       10 */
267    1000000,    /* USERIAL_BAUD_1M           11 */
268    1500000,    /* USERIAL_BAUD_1_5M         12 */
269    2000000,    /* USERIAL_BAUD_2M           13 */
270    3000000,    /* USERIAL_BAUD_3M           14 */
271    4000000     /* USERIAL_BAUD_4M           15 */
272};
273
274/*******************************************************************************
275**
276** Function         wake_state
277**
278** Description      return current state of NFC_WAKE gpio
279**
280** Returns          GPIO value to wake NFCC
281**
282*******************************************************************************/
283static inline int wake_state()
284{
285    return ((gSnoozeModeCfg.nfc_wake_active_mode == NFC_HAL_LP_ACTIVE_HIGH) ? UPIO_ON : UPIO_OFF);
286}
287
288/*******************************************************************************
289**
290** Function         sleep_state
291**
292** Description      return current state of NFC_WAKE gpio
293**
294** Returns          GPIO value to allow NFCC to goto sleep
295**
296*******************************************************************************/
297static inline int sleep_state()
298{
299    return ((gSnoozeModeCfg.nfc_wake_active_mode == NFC_HAL_LP_ACTIVE_HIGH) ? UPIO_OFF : UPIO_ON);
300}
301
302/*******************************************************************************
303**
304** Function         isWake
305**
306** Description      return current state of NFC_WAKE gpio based on the active mode setting
307**
308** Returns          asserted_state if it's awake, deasserted_state if it's allowed to sleep
309**
310*******************************************************************************/
311static inline int isWake(int state)
312{
313    int     asserted_state = ((gSnoozeModeCfg.nfc_wake_active_mode == NFC_HAL_LP_ACTIVE_HIGH) ? UPIO_ON : UPIO_OFF);
314    return (state != -1) ?
315        state == asserted_state :
316        current_nfc_wake_state == asserted_state;
317}
318
319/*******************************************************************************
320**
321** Function           setWriteDelay
322**
323** Description        Record a delay for the next write operation
324**
325** Input Parameter    delay in milliseconds
326**
327** Comments           use this function to register a delay before next write,
328**                    This is used in three instances: power up delay, wake delay
329**                    and write delay
330**
331*******************************************************************************/
332static void setWriteDelay(int delay)
333{
334    if (delay <= 0) {
335        // Set a minimum delay of 5ms between back-to-back writes
336        delay = 5;
337    }
338
339    clock_gettime(CLOCK_MONOTONIC, &linux_cb.write_time);
340    if (delay > 1000)
341    {
342        linux_cb.write_time.tv_sec += delay / 1000;
343        delay %= 1000;
344    }
345    unsigned long write_delay = delay * 1000 * 1000;
346    linux_cb.write_time.tv_nsec += write_delay;
347    if (linux_cb.write_time.tv_nsec > 1000*1000*1000)
348    {
349        linux_cb.write_time.tv_nsec -= 1000*1000*1000;
350        linux_cb.write_time.tv_sec++;
351    }
352}
353
354/*******************************************************************************
355**
356** Function           doWriteDelay
357**
358** Description        Execute a delay as registered in setWriteDelay()
359**
360** Output Parameter   none
361**
362** Returns            none
363**
364** Comments           This function calls GKI_Delay to execute a delay to fulfill
365**                    the delay registered earlier.
366**
367*******************************************************************************/
368static void doWriteDelay()
369{
370    struct timespec now;
371    clock_gettime(CLOCK_MONOTONIC, &now);
372    long delay = 0;
373
374    if (now.tv_sec > linux_cb.write_time.tv_sec)
375        return;
376    else if (now.tv_sec == linux_cb.write_time.tv_sec)
377    {
378        if (now.tv_nsec > linux_cb.write_time.tv_nsec)
379            return;
380        delay = (linux_cb.write_time.tv_nsec - now.tv_nsec) / 1000000;
381    }
382    else
383        delay = (linux_cb.write_time.tv_sec - now.tv_sec) * 1000 + linux_cb.write_time.tv_nsec / 1000000 - now.tv_nsec / 1000000;
384
385    if (delay > 0 && delay < 1000)
386    {
387        ALOGD_IF((appl_trace_level>=BT_TRACE_LEVEL_DEBUG), "doWriteDelay() delay %ld ms", delay);
388        GKI_delay(delay);
389    }
390}
391
392/*******************************************************************************
393**
394** Function         create_signal_fds
395**
396** Description      create a socketpair for read thread to use
397**
398** Returns          file descriptor
399**
400*******************************************************************************/
401
402static int signal_fds[2];
403static inline int create_signal_fds(struct pollfd* set)
404{
405    if (signal_fds[0] == 0 && socketpair(AF_UNIX, SOCK_STREAM, 0, signal_fds) < 0)
406    {
407        ALOGE("%s create_signal_sockets:socketpair failed, errno: %d", __func__, errno);
408        return -1;
409    }
410    set->fd = signal_fds[0];
411    return signal_fds[0];
412}
413
414/*******************************************************************************
415**
416** Function         close_signal_fds
417**
418** Description      close the socketpair
419**
420** Returns          none
421**
422*******************************************************************************/
423static inline void close_signal_fds()
424{
425    close(signal_fds[0]);
426    signal_fds[0] = 0;
427
428    close(signal_fds[1]);
429    signal_fds[1] = 0;
430}
431
432/*******************************************************************************
433**
434** Function         send_wakeup_signal
435**
436** Description      send a one byte data to the socket as signal to the read thread
437**                  for it to stop
438**
439** Returns          number of bytes sent, or error no
440**
441*******************************************************************************/
442static inline int send_wakeup_signal()
443{
444    char sig_on = 1;
445    ALOGD("%s: Sending signal to %d", __func__, signal_fds[1]);
446    return send(signal_fds[1], &sig_on, sizeof(sig_on), 0);
447}
448
449/*******************************************************************************
450**
451** Function         reset_signal
452**
453** Description      read the one byte data from the socket
454**
455** Returns          received data
456**
457*******************************************************************************/
458static inline int reset_signal()
459{
460    char sig_recv = 0;
461    ALOGD("%s: Receiving signal from %d", __func__, signal_fds[0]);
462    recv(signal_fds[0], &sig_recv, sizeof(sig_recv), MSG_WAITALL);
463    return (int)sig_recv;
464}
465
466/*******************************************************************************
467**
468** Function         is_signaled
469**
470** Description      test if there's data waiting on the socket
471**
472** Returns          TRUE is data is available
473**
474*******************************************************************************/
475static inline int is_signaled(struct pollfd* set)
476{
477    return ((set->revents & POLLIN) == POLLIN) || ((set->revents & POLLRDNORM) == POLLRDNORM) ;
478}
479
480/******************************************************************************/
481
482typedef unsigned char uchar;
483
484BUFFER_Q Userial_in_q;
485
486/*******************************************************************************
487 **
488 ** Function           USERIAL_GetLineSpeed
489 **
490 ** Description        This function convert USERIAL baud to line speed.
491 **
492 ** Output Parameter   None
493 **
494 ** Returns            line speed
495 **
496 *******************************************************************************/
497UDRV_API extern UINT32 USERIAL_GetLineSpeed(UINT8 baud)
498{
499    return (baud <= USERIAL_BAUD_4M) ?
500            userial_baud_tbl[baud-USERIAL_BAUD_300] : 0;
501}
502
503/*******************************************************************************
504 **
505 ** Function           USERIAL_GetBaud
506 **
507 ** Description        This function convert line speed to USERIAL baud.
508 **
509 ** Output Parameter   None
510 **
511 ** Returns            line speed
512 **
513 *******************************************************************************/
514UDRV_API extern UINT8 USERIAL_GetBaud(UINT32 line_speed)
515{
516    UINT8 i;
517    for (i = USERIAL_BAUD_300; i <= USERIAL_BAUD_921600; i++)
518    {
519        if (userial_baud_tbl[i-USERIAL_BAUD_300] == line_speed)
520            return i;
521    }
522
523    return USERIAL_BAUD_AUTO;
524}
525
526/*******************************************************************************
527**
528** Function           USERIAL_Init
529**
530** Description        This function initializes the  serial driver.
531**
532** Output Parameter   None
533**
534** Returns            Nothing
535**
536*******************************************************************************/
537
538UDRV_API void    USERIAL_Init(void * p_cfg)
539{
540    ALOGI(__FUNCTION__);
541
542    memset(&linux_cb, 0, sizeof(linux_cb));
543    linux_cb.sock = -1;
544    linux_cb.ser_cb = NULL;
545    linux_cb.sock_power_control = -1;
546    linux_cb.client_device_address = 0;
547    GKI_init_q(&Userial_in_q);
548    return;
549}
550
551/*******************************************************************************
552 **
553 ** Function           my_read
554 **
555 ** Description        This function read a packet from driver.
556 **
557 ** Output Parameter   None
558 **
559 ** Returns            number of bytes in the packet or error code
560 **
561 *******************************************************************************/
562int my_read(int fd, uchar *pbuf, int len)
563{
564    struct pollfd fds[2];
565
566    int n = 0;
567    int ret = 0;
568    int count = 0;
569    int offset = 0;
570    clock_t t1, t2;
571
572    if (!isLowSpeedTransport && _timeout != POLL_TIMEOUT)
573        ALOGD_IF((appl_trace_level>=BT_TRACE_LEVEL_DEBUG), "%s: enter, pbuf=%lx, len = %d\n", __func__, (unsigned long)pbuf, len);
574    memset(pbuf, 0, len);
575    /* need to use select in order to avoid collistion between read and close on same fd */
576    /* Initialize the input set */
577    fds[0].fd = fd;
578    fds[0].events = POLLIN | POLLERR | POLLRDNORM;
579    fds[0].revents = 0;
580
581    create_signal_fds(&fds[1]);
582    fds[1].events = POLLIN | POLLERR | POLLRDNORM;
583    fds[1].revents = 0;
584    t1 = clock();
585    n = poll(fds, 2, _timeout);
586    t2 = clock();
587    perf_update(&perf_poll, t2 - t1, 0);
588    if (_poll_t0)
589        perf_update(&perf_poll_2_poll, t2 - _poll_t0, 0);
590
591    _poll_t0 = t2;
592    /* See if there was an error */
593    if (n < 0)
594    {
595        ALOGD( "select failed; errno = %d\n", errno);
596        return -errno;
597    }
598    else if (n == 0)
599        return -EAGAIN;
600
601    if (is_signaled(&fds[1]))
602    {
603        ALOGD( "%s: exit signal received\n", __func__);
604        reset_signal();
605        return -1;
606    }
607    if (!bSerialPortDevice || len < MIN_BUFSIZE)
608        count = len;
609    else
610        count = 1;
611    do {
612        t2 = clock();
613        ret = read(fd, pbuf+offset, (size_t)count);
614        if (ret > 0)
615            perf_update(&perf_read, clock()-t2, ret);
616
617        if (ret <= 0 || !bSerialPortDevice || len < MIN_BUFSIZE)
618            break;
619
620        if (isLowSpeedTransport)
621            goto done;
622
623        if (offset == 0)
624        {
625            if (pbuf[offset] == HCIT_TYPE_NFC)
626                count = 3;
627            else if (pbuf[offset] == HCIT_TYPE_EVENT)
628                count = 2;
629            else
630            {
631                ALOGD( "%s: unknown HCIT type header pbuf[%d] = %x\n", __func__, offset, pbuf[offset]);
632                break;
633            }
634            offset = 1;
635        }
636        else if (offset == 1)
637        {
638            offset += count;
639            count = pbuf[offset-1];
640        }
641        else
642        {
643            offset += ret;
644            count -= ret;
645        }
646        if (count == 0)
647        {
648            ret = offset;
649            break;
650        }
651    } while (count > 0);
652 #if VALIDATE_PACKET
653/*
654 * vallidate the packet structure
655 */
656    if (ret > 0 && len >= MIN_BUFSIZE)
657    {
658        count = 0;
659        while (count < ret)
660        {
661            if (pbuf[count] == HCIT_TYPE_NFC)
662            {
663                if (USERIAL_Debug_verbose)
664                    scru_dump_hex(pbuf+count, NULL, pbuf[count+3]+4, 0, 0);
665                count += pbuf[count+3]+4;
666            }
667            else if (pbuf[count] == HCIT_TYPE_EVENT)
668            {
669                if (USERIAL_Debug_verbose)
670                    scru_dump_hex(pbuf+count, NULL, pbuf[count+2]+3, 0, 0);
671                count += pbuf[count+2]+3;
672            }
673            else
674            {
675                ALOGD( "%s: unknown HCIT type header pbuf[%d] = %x, remain %d bytes\n", __func__, count, pbuf[count], ret-count);
676                scru_dump_hex(pbuf+count, NULL, ret - count, 0, 0);
677                break;
678            }
679        } /* while*/
680    }
681#endif
682done:
683    if (!isLowSpeedTransport)
684        ALOGD_IF((appl_trace_level>=BT_TRACE_LEVEL_DEBUG), "%s: return %d(0x%x) bytes, errno=%d count=%d, n=%d, timeout=%d\n", __func__,
685            ret, ret, errno, count, n, _timeout);
686    if (_timeout == POLL_TIMEOUT)
687        _timeout = -1;
688    return ret;
689}
690extern BOOLEAN gki_chk_buf_damage(void *p_buf);
691static int sRxLength = 0;
692
693/*******************************************************************************
694 **
695 ** Function           userial_read_thread
696 **
697 ** Description        entry point of read thread.
698 **
699 ** Output Parameter   None
700 **
701 ** Returns            0
702 **
703 *******************************************************************************/
704UINT32 userial_read_thread(UINT32 arg)
705{
706    int rx_length;
707    int error_count = 0;
708    int bErrorReported = 0;
709    int iMaxError = MAX_ERROR;
710    BT_HDR *p_buf = NULL;
711
712    worker_thread1 = pthread_self();
713
714    ALOGD( "start userial_read_thread, id=%lx", worker_thread1);
715    _timeout = POLL_TIMEOUT;
716
717    for (;linux_cb.sock > 0;)
718    {
719        BT_HDR *p_buf;
720        UINT8 *current_packet;
721
722        if ((p_buf = (BT_HDR *) GKI_getpoolbuf( USERIAL_POOL_ID ) )!= NULL)
723        {
724            p_buf->offset = 0;
725            p_buf->layer_specific = 0;
726
727            current_packet = (UINT8 *) (p_buf + 1);
728            rx_length = my_read(linux_cb.sock, current_packet, READ_LIMIT);
729
730        }
731        else
732        {
733            ALOGE( "userial_read_thread(): unable to get buffer from GKI p_buf = %p poolid = %d\n", p_buf, USERIAL_POOL_ID);
734            rx_length = 0;  /* paranoia setting */
735            GKI_delay( NO_GKI_BUFFER_RECOVER_TIME );
736            continue;
737        }
738        if (rx_length > 0)
739        {
740            bErrorReported = 0;
741            error_count = 0;
742            iMaxError = 3;
743            if (rx_length > sRxLength)
744                sRxLength = rx_length;
745            p_buf->len = (UINT16)rx_length;
746            GKI_enqueue(&Userial_in_q, p_buf);
747            if (!isLowSpeedTransport)
748                ALOGD_IF((appl_trace_level>=BT_TRACE_LEVEL_DEBUG), "userial_read_thread(): enqueued p_buf=%p, count=%d, length=%d\n",
749                            p_buf, Userial_in_q.count, rx_length);
750
751            if (linux_cb.ser_cb != NULL)
752                (*linux_cb.ser_cb)(linux_cb.port, USERIAL_RX_READY_EVT, (tUSERIAL_EVT_DATA *)p_buf);
753
754            GKI_send_event(USERIAL_HAL_TASK, HCISU_EVT);
755        }
756        else
757        {
758            GKI_freebuf( p_buf );
759            if (rx_length == -EAGAIN)
760                continue;
761            else if (rx_length == -1)
762            {
763                ALOGD( "userial_read_thread(): exiting\n");
764                break;
765            }
766            else if (rx_length == 0 && !isWake(-1))
767                continue;
768            ++error_count;
769            if (rx_length <= 0 && ((error_count > 0) && ((error_count % iMaxError) == 0)))
770            {
771                if (bErrorReported == 0)
772                {
773                    ALOGE( "userial_read_thread(): my_read returned (%d) error count = %d, errno=%d return USERIAL_ERR_EVT\n",
774                            rx_length, error_count, errno);
775                    if (linux_cb.ser_cb != NULL)
776                        (*linux_cb.ser_cb)(linux_cb.port, USERIAL_ERR_EVT, (tUSERIAL_EVT_DATA *)p_buf);
777
778                    GKI_send_event(USERIAL_HAL_TASK, HCISU_EVT);
779                    ++bErrorReported;
780                }
781                if (sRxLength == 0)
782                {
783                    ALOGE( "userial_read_thread(): my_read returned (%d) error count = %d, errno=%d exit read thread\n",
784                            rx_length, error_count, errno);
785                    break;
786                }
787            }
788        }
789    } /* for */
790
791    ALOGD( "userial_read_thread(): freeing GKI_buffers\n");
792    while ((p_buf = (BT_HDR *) GKI_dequeue (&Userial_in_q)) != NULL)
793    {
794        GKI_freebuf(p_buf);
795        ALOGD("userial_read_thread: dequeued buffer from Userial_in_q\n");
796    }
797
798    GKI_exit_task (GKI_get_taskid ());
799    ALOGD( "USERIAL READ: EXITING TASK\n");
800
801    return 0;
802}
803
804/*******************************************************************************
805 **
806 ** Function           userial_to_tcio_baud
807 **
808 ** Description        helper function converts USERIAL baud rates into TCIO conforming baud rates
809 **
810 ** Output Parameter   None
811 **
812 ** Returns            TRUE - success
813 **                    FALSE - unsupported baud rate, default of 115200 is used
814 **
815 *******************************************************************************/
816BOOLEAN userial_to_tcio_baud(UINT8 cfg_baud, UINT32 * baud)
817{
818    if (cfg_baud == USERIAL_BAUD_600)
819        *baud = B600;
820    else if (cfg_baud == USERIAL_BAUD_1200)
821        *baud = B1200;
822    else if (cfg_baud == USERIAL_BAUD_9600)
823        *baud = B9600;
824    else if (cfg_baud == USERIAL_BAUD_19200)
825        *baud = B19200;
826    else if (cfg_baud == USERIAL_BAUD_57600)
827        *baud = B57600;
828    else if (cfg_baud == USERIAL_BAUD_115200)
829        *baud = B115200 | CBAUDEX;
830    else if (cfg_baud == USERIAL_BAUD_230400)
831        *baud = B230400;
832    else if (cfg_baud == USERIAL_BAUD_460800)
833        *baud = B460800;
834    else if (cfg_baud == USERIAL_BAUD_921600)
835        *baud = B921600;
836    else if (cfg_baud == USERIAL_BAUD_1M)
837        *baud = B1000000;
838    else if (cfg_baud == USERIAL_BAUD_2M)
839        *baud = B2000000;
840    else if (cfg_baud == USERIAL_BAUD_3M)
841        *baud = B3000000;
842    else if (cfg_baud == USERIAL_BAUD_4M)
843        *baud = B4000000;
844    else
845    {
846        ALOGE( "USERIAL_Open: unsupported baud idx %i", cfg_baud );
847        *baud = B115200;
848        return FALSE;
849    }
850    return TRUE;
851}
852
853#if (USERIAL_USE_IO_BT_WAKE==TRUE)
854/*******************************************************************************
855 **
856 ** Function           userial_io_init_bt_wake
857 **
858 ** Description        helper function to set the open state of the bt_wake if ioctl
859 **                    is used. it should not hurt in the rfkill case but it might
860 **                    be better to compile it out.
861 **
862 ** Returns            none
863 **
864 *******************************************************************************/
865void userial_io_init_bt_wake( int fd, unsigned long * p_wake_state )
866{
867    /* assert BT_WAKE for ioctl. should NOT hurt on rfkill version */
868    ioctl( fd, USERIAL_IO_BT_WAKE_ASSERT, NULL);
869    ioctl( fd, USERIAL_IO_BT_WAKE_GET_ST, p_wake_state );
870    if ( *p_wake_state == 0)
871        ALOGI("\n***userial_io_init_bt_wake(): Ooops, asserted BT_WAKE signal, but still got BT_WAKE state == to %d\n",
872             *p_wake_state );
873
874    *p_wake_state = 1;
875}
876#endif
877
878/*******************************************************************************
879**
880** Function           USERIAL_Open
881**
882** Description        Open the indicated serial port with the given configuration
883**
884** Output Parameter   None
885**
886** Returns            Nothing
887**
888*******************************************************************************/
889UDRV_API void USERIAL_Open(tUSERIAL_PORT port, tUSERIAL_OPEN_CFG *p_cfg, tUSERIAL_CBACK *p_cback)
890{
891    UINT32 baud = 0;
892    UINT8 data_bits = 0;
893    UINT16 parity = 0;
894    UINT8 stop_bits = 0;
895    struct termios termios;
896    const char ttyusb[] = "/dev/ttyUSB";
897    const char devtty[] = "/dev/tty";
898    unsigned long num = 0;
899    int     ret = 0;
900
901    ALOGI("USERIAL_Open(): enter");
902
903    //if userial_close_thread() is waiting to run; let it go first;
904    //let it finish; then continue this function
905    while (TRUE)
906    {
907        pthread_mutex_lock(&close_thread_mutex);
908        if (is_close_thread_is_waiting)
909        {
910            pthread_mutex_unlock(&close_thread_mutex);
911            ALOGI("USERIAL_Open(): wait for close-thread");
912            sleep (1);
913        }
914        else
915            break;
916    }
917
918    // restore default power off delay settings incase they were changed in userial_set_poweroff_delays()
919    gPrePowerOffDelay = 0;
920    gPostPowerOffDelay = 0;
921
922    if ( !GetStrValue ( NAME_TRANSPORT_DRIVER, userial_dev, sizeof ( userial_dev ) ) )
923        strcpy ( userial_dev, default_transport );
924    if ( GetNumValue ( NAME_UART_PORT, &num, sizeof ( num ) ) )
925        uart_port = num;
926    if ( GetNumValue ( NAME_LOW_SPEED_TRANSPORT, &num, sizeof ( num ) ) )
927        isLowSpeedTransport = num;
928    if ( GetNumValue ( NAME_NFC_WAKE_DELAY, &num, sizeof ( num ) ) )
929        nfc_wake_delay = num;
930    if ( GetNumValue ( NAME_NFC_WRITE_DELAY, &num, sizeof ( num ) ) )
931        nfc_write_delay = num;
932    if ( GetNumValue ( NAME_PERF_MEASURE_FREQ, &num, sizeof ( num ) ) )
933        perf_log_every_count = num;
934    if ( GetNumValue ( NAME_POWER_ON_DELAY, &num, sizeof ( num ) ) )
935        gPowerOnDelay = num;
936    if ( GetNumValue ( NAME_PRE_POWER_OFF_DELAY, &num, sizeof ( num ) ) )
937        gPrePowerOffDelay = num;
938    if ( GetNumValue ( NAME_POST_POWER_OFF_DELAY, &num, sizeof ( num ) ) )
939        gPostPowerOffDelay = num;
940    ALOGI("USERIAL_Open() device: %s port=%d, uart_port=%d WAKE_DELAY(%d) WRITE_DELAY(%d) POWER_ON_DELAY(%d) PRE_POWER_OFF_DELAY(%d) POST_POWER_OFF_DELAY(%d)",
941            (char*)userial_dev, port, uart_port, nfc_wake_delay, nfc_write_delay, gPowerOnDelay, gPrePowerOffDelay,
942            gPostPowerOffDelay);
943    GetStrValue( NAME_SNOOZE_MODE_CFG, (char*)&gSnoozeModeCfg, sizeof(gSnoozeModeCfg) );
944
945    strcpy((char*)device_name, (char*)userial_dev);
946    sRxLength = 0;
947    _poll_t0 = 0;
948
949    if ((strncmp(userial_dev, ttyusb, sizeof(ttyusb)-1) == 0) ||
950        (strncmp(userial_dev, devtty, sizeof(devtty)-1) == 0) )
951    {
952        if (uart_port >= MAX_SERIAL_PORT)
953        {
954            ALOGD( "Port > MAX_SERIAL_PORT\n");
955            goto done_open;
956        }
957        bSerialPortDevice = TRUE;
958        sprintf((char*)device_name, "%s%d", (char*)userial_dev, uart_port);
959        ALOGI("USERIAL_Open() using device_name: %s ", (char*)device_name);
960        if (!userial_to_tcio_baud(p_cfg->baud, &baud))
961            goto done_open;
962
963        if (p_cfg->fmt & USERIAL_DATABITS_8)
964            data_bits = CS8;
965        else if (p_cfg->fmt & USERIAL_DATABITS_7)
966            data_bits = CS7;
967        else if (p_cfg->fmt & USERIAL_DATABITS_6)
968            data_bits = CS6;
969        else if (p_cfg->fmt & USERIAL_DATABITS_5)
970            data_bits = CS5;
971        else
972            goto done_open;
973
974        if (p_cfg->fmt & USERIAL_PARITY_NONE)
975            parity = 0;
976        else if (p_cfg->fmt & USERIAL_PARITY_EVEN)
977            parity = PARENB;
978        else if (p_cfg->fmt & USERIAL_PARITY_ODD)
979            parity = (PARENB | PARODD);
980        else
981            goto done_open;
982
983        if (p_cfg->fmt & USERIAL_STOPBITS_1)
984            stop_bits = 0;
985        else if (p_cfg->fmt & USERIAL_STOPBITS_2)
986            stop_bits = CSTOPB;
987        else
988            goto done_open;
989    }
990    else
991        strcpy((char*)device_name, (char*)userial_dev);
992
993    {
994        ALOGD("%s Opening %s\n",  __FUNCTION__, device_name);
995        if ((linux_cb.sock = open((char*)device_name, O_RDWR | O_NOCTTY )) == -1)
996        {
997            ALOGI("%s unable to open %s",  __FUNCTION__, device_name);
998            GKI_send_event(NFC_HAL_TASK, NFC_HAL_TASK_EVT_TERMINATE);
999            goto done_open;
1000        }
1001        ALOGD( "sock = %d\n", linux_cb.sock);
1002        if (GetStrValue ( NAME_POWER_CONTROL_DRIVER, power_control_dev, sizeof ( power_control_dev ) ) &&
1003            power_control_dev[0] != '\0')
1004        {
1005            if (strcmp(power_control_dev, userial_dev) == 0)
1006                linux_cb.sock_power_control = linux_cb.sock;
1007            else
1008            {
1009                if ((linux_cb.sock_power_control = open((char*)power_control_dev, O_RDWR | O_NOCTTY )) == -1)
1010                {
1011                    ALOGI("%s unable to open %s",  __FUNCTION__, power_control_dev);
1012                }
1013            }
1014        }
1015        if ( bSerialPortDevice )
1016        {
1017            tcflush(linux_cb.sock, TCIOFLUSH);
1018            tcgetattr(linux_cb.sock, &termios);
1019
1020            termios.c_cflag &= ~(CSIZE | PARENB);
1021            termios.c_cflag = CLOCAL|CREAD|data_bits|stop_bits|parity;
1022            if (!parity)
1023                termios.c_cflag |= IGNPAR;
1024            // termios.c_cflag &= ~CRTSCTS;
1025            termios.c_oflag = 0;
1026            termios.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
1027            termios.c_iflag &= ~(BRKINT | ICRNL | INLCR | ISTRIP | IXON | IGNBRK | PARMRK | INPCK);
1028            termios.c_lflag = 0;
1029            termios.c_iflag = 0;
1030            cfsetospeed(&termios, baud);
1031            cfsetispeed(&termios, baud);
1032
1033            termios.c_cc[VTIME] = 0;
1034            termios.c_cc[VMIN] = 1;
1035            tcsetattr(linux_cb.sock, TCSANOW, &termios);
1036
1037            tcflush(linux_cb.sock, TCIOFLUSH);
1038
1039#if (USERIAL_USE_IO_BT_WAKE==TRUE)
1040            userial_io_init_bt_wake( linux_cb.sock, &linux_cb.bt_wake_state );
1041#endif
1042            GKI_delay(gPowerOnDelay);
1043        }
1044        else
1045        {
1046            USERIAL_PowerupDevice(port);
1047        }
1048    }
1049
1050    linux_cb.ser_cb     = p_cback;
1051    linux_cb.port = port;
1052    memcpy(&linux_cb.open_cfg, p_cfg, sizeof(tUSERIAL_OPEN_CFG));
1053    GKI_create_task ((TASKPTR)userial_read_thread, USERIAL_HAL_TASK, (INT8*)"USERIAL_HAL_TASK", 0, 0, (pthread_cond_t*)NULL, NULL);
1054
1055
1056#if (defined USERIAL_DEBUG) && (USERIAL_DEBUG == TRUE)
1057    ALOGD( "Leaving USERIAL_Open\n");
1058#endif
1059
1060#if (SERIAL_AMBA == TRUE)
1061    /* give 20ms time for reader thread */
1062    GKI_delay(20);
1063#endif
1064
1065done_open:
1066    pthread_mutex_unlock(&close_thread_mutex);
1067    ALOGI("USERIAL_Open(): exit");
1068    return;
1069}
1070
1071/*******************************************************************************
1072**
1073** Function           USERIAL_Read
1074**
1075** Description        Read data from a serial port using byte buffers.
1076**
1077** Output Parameter   None
1078**
1079** Returns            Number of bytes actually read from the serial port and
1080**                    copied into p_data.  This may be less than len.
1081**
1082*******************************************************************************/
1083
1084static BT_HDR *pbuf_USERIAL_Read = NULL;
1085
1086UDRV_API UINT16  USERIAL_Read(tUSERIAL_PORT port, UINT8 *p_data, UINT16 len)
1087{
1088    UINT16 total_len = 0;
1089    UINT16 copy_len = 0;
1090    UINT8 * current_packet = NULL;
1091
1092#if (defined USERIAL_DEBUG) && (USERIAL_DEBUG == TRUE)
1093    ALOGD( "%s ++ len=%d pbuf_USERIAL_Read=%p, p_data=%p\n", __func__, len, pbuf_USERIAL_Read, p_data);
1094#endif
1095    do
1096    {
1097        if (pbuf_USERIAL_Read != NULL)
1098        {
1099            current_packet = ((UINT8 *)(pbuf_USERIAL_Read + 1)) + (pbuf_USERIAL_Read->offset);
1100
1101            if ((pbuf_USERIAL_Read->len) <= (len - total_len))
1102                copy_len = pbuf_USERIAL_Read->len;
1103            else
1104                copy_len = (len - total_len);
1105
1106            memcpy((p_data + total_len), current_packet, copy_len);
1107
1108            total_len += copy_len;
1109
1110            pbuf_USERIAL_Read->offset += copy_len;
1111            pbuf_USERIAL_Read->len -= copy_len;
1112
1113            if (pbuf_USERIAL_Read->len == 0)
1114            {
1115                GKI_freebuf(pbuf_USERIAL_Read);
1116                pbuf_USERIAL_Read = NULL;
1117            }
1118        }
1119
1120        if (pbuf_USERIAL_Read == NULL && (total_len < len))
1121            pbuf_USERIAL_Read = (BT_HDR *)GKI_dequeue(&Userial_in_q);
1122
1123    } while ((pbuf_USERIAL_Read != NULL) && (total_len < len));
1124
1125#if (defined USERIAL_DEBUG) && (USERIAL_DEBUG == TRUE)
1126    ALOGD( "%s: returned %d bytes", __func__, total_len);
1127#endif
1128    return total_len;
1129}
1130
1131/*******************************************************************************
1132**
1133** Function           USERIAL_Readbuf
1134**
1135** Description        Read data from a serial port using GKI buffers.
1136**
1137** Output Parameter   Pointer to a GKI buffer which contains the data.
1138**
1139** Returns            Nothing
1140**
1141** Comments           The caller of this function is responsible for freeing the
1142**                    GKI buffer when it is finished with the data.  If there is
1143**                    no data to be read, the value of the returned pointer is
1144**                    NULL.
1145**
1146*******************************************************************************/
1147
1148UDRV_API void    USERIAL_ReadBuf(tUSERIAL_PORT port, BT_HDR **p_buf)
1149{
1150
1151}
1152
1153/*******************************************************************************
1154**
1155** Function           USERIAL_WriteBuf
1156**
1157** Description        Write data to a serial port using a GKI buffer.
1158**
1159** Output Parameter   None
1160**
1161** Returns            TRUE  if buffer accepted for write.
1162**                    FALSE if there is already a buffer being processed.
1163**
1164** Comments           The buffer will be freed by the serial driver.  Therefore,
1165**                    the application calling this function must not free the
1166**                    buffer.
1167**
1168*******************************************************************************/
1169
1170UDRV_API BOOLEAN USERIAL_WriteBuf(tUSERIAL_PORT port, BT_HDR *p_buf)
1171{
1172    return FALSE;
1173}
1174
1175/*******************************************************************************
1176**
1177** Function           USERIAL_Write
1178**
1179** Description        Write data to a serial port using a byte buffer.
1180**
1181** Output Parameter   None
1182**
1183** Returns            Number of bytes actually written to the transport.  This
1184**                    may be less than len.
1185**
1186*******************************************************************************/
1187UDRV_API UINT16  USERIAL_Write(tUSERIAL_PORT port, UINT8 *p_data, UINT16 len)
1188{
1189    int ret = 0, total = 0;
1190    int i = 0;
1191    clock_t t;
1192
1193    /* Ensure we wake up the chip before writing to it */
1194    if (!isWake(UPIO_ON))
1195        UPIO_Set(UPIO_GENERAL, NFC_HAL_LP_NFC_WAKE_GPIO, UPIO_OFF);
1196
1197    ALOGD_IF((appl_trace_level>=BT_TRACE_LEVEL_DEBUG), "USERIAL_Write: (%d bytes)", len);
1198    pthread_mutex_lock(&close_thread_mutex);
1199
1200    doWriteDelay();
1201    t = clock();
1202    while (len != 0 && linux_cb.sock != -1)
1203    {
1204        ret = write(linux_cb.sock, p_data + total, len);
1205        if (ret < 0)
1206        {
1207            ALOGE("USERIAL_Write len = %d, ret = %d, errno = %d", len, ret, errno);
1208            break;
1209        }
1210        else
1211        {
1212            ALOGD_IF((appl_trace_level>=BT_TRACE_LEVEL_DEBUG), "USERIAL_Write len = %d, ret = %d", len, ret);
1213        }
1214
1215        total += ret;
1216        len -= ret;
1217    }
1218    perf_update(&perf_write, clock() - t, total);
1219
1220    /* register a delay for next write */
1221    setWriteDelay(total * nfc_write_delay / 1000);
1222
1223    pthread_mutex_unlock(&close_thread_mutex);
1224
1225    return ((UINT16)total);
1226}
1227
1228/*******************************************************************************
1229**
1230** Function           userial_change_rate
1231**
1232** Description        change naud rate
1233**
1234** Output Parameter   None
1235**
1236** Returns            None
1237**
1238*******************************************************************************/
1239void userial_change_rate(UINT8 baud)
1240{
1241#if defined (USING_BRCM_USB) && (USING_BRCM_USB == FALSE)
1242    struct termios termios;
1243#endif
1244#if (USERIAL_USE_TCIO_BAUD_CHANGE==TRUE)
1245    UINT32 tcio_baud;
1246#endif
1247
1248#if defined (USING_BRCM_USB) && (USING_BRCM_USB == FALSE)
1249    tcflush(linux_cb.sock, TCIOFLUSH);
1250
1251    tcgetattr(linux_cb.sock, &termios);
1252
1253    cfmakeraw(&termios);
1254    cfsetospeed(&termios, baud);
1255    cfsetispeed(&termios, baud);
1256
1257    termios.c_cflag |= (CLOCAL | CREAD | CRTSCTS | stop_bits);
1258
1259    tcsetattr(linux_cb.sock, TCSANOW, &termios);
1260    tcflush(linux_cb.sock, TCIOFLUSH);
1261
1262#else
1263#if (USERIAL_USE_TCIO_BAUD_CHANGE==FALSE)
1264    fprintf(stderr, "userial_change_rate: Closing UART Port\n");
1265    ALOGI("userial_change_rate: Closing UART Port\n");
1266    USERIAL_Close(linux_cb.port);
1267
1268    GKI_delay(50);
1269
1270    /* change baud rate in settings - leave everything else the same  */
1271    linux_cb.open_cfg.baud = baud;
1272
1273    ALOGD( "userial_change_rate: Attempting to reopen the UART Port at 0x%08x\n", (unsigned int)USERIAL_GetLineSpeed(baud));
1274    ALOGI("userial_change_rate: Attempting to reopen the UART Port at %i\n", (unsigned int)USERIAL_GetLineSpeed(baud));
1275
1276    USERIAL_Open(linux_cb.port, &linux_cb.open_cfg, linux_cb.ser_cb);
1277#else /* amba uart */
1278    fprintf(stderr, "userial_change_rate(): changeing baud rate via TCIO \n");
1279    ALOGI( "userial_change_rate: (): changeing baud rate via TCIO \n");
1280    /* change baud rate in settings - leave everything else the same  */
1281    linux_cb.open_cfg.baud = baud;
1282    if (!userial_to_tcio_baud(linux_cb.open_cfg.baud, &tcio_baud))
1283        return;
1284
1285    tcflush(linux_cb.sock, TCIOFLUSH);
1286
1287    /* get current settings. they should be fine besides baud rate we want to change */
1288    tcgetattr(linux_cb.sock, &termios);
1289
1290    /* set input/output baudrate */
1291    cfsetospeed(&termios, tcio_baud);
1292    cfsetispeed(&termios, tcio_baud);
1293    tcsetattr(linux_cb.sock, TCSANOW, &termios);
1294
1295    tcflush(linux_cb.sock, TCIOFLUSH);
1296#endif
1297#endif   /* USING_BRCM_USB  */
1298}
1299
1300/*******************************************************************************
1301**
1302** Function           userial_close_port
1303**
1304** Description        close the transport driver
1305**
1306** Returns            Nothing
1307**
1308*******************************************************************************/
1309void userial_close_port( void )
1310{
1311    USERIAL_Close(linux_cb.port);
1312}
1313
1314/*******************************************************************************
1315**
1316** Function           USERIAL_Ioctl
1317**
1318** Description        Perform an operation on a serial port.
1319**
1320** Output Parameter   The p_data parameter is either an input or output depending
1321**                    on the operation.
1322**
1323** Returns            Nothing
1324**
1325*******************************************************************************/
1326
1327UDRV_API void    USERIAL_Ioctl(tUSERIAL_PORT port, tUSERIAL_OP op, tUSERIAL_IOCTL_DATA *p_data)
1328{
1329#if (defined LINUX_OS) && (LINUX_OS == TRUE)
1330    USB_SCO_CONTROL ioctl_data;
1331
1332    /* just ignore port parameter as we are using USB in this case  */
1333#endif
1334
1335    switch (op)
1336    {
1337    case USERIAL_OP_FLUSH:
1338        break;
1339    case USERIAL_OP_FLUSH_RX:
1340        break;
1341    case USERIAL_OP_FLUSH_TX:
1342        break;
1343    case USERIAL_OP_BAUD_WR:
1344        ALOGI( "USERIAL_Ioctl: Received USERIAL_OP_BAUD_WR on port: %d, ioctl baud%i\n", port, p_data->baud);
1345        linux_cb.port = port;
1346        userial_change_rate(p_data->baud);
1347        break;
1348
1349    default:
1350        break;
1351    }
1352
1353    return;
1354}
1355
1356
1357/*******************************************************************************
1358**
1359** Function         USERIAL_SetPowerOffDelays
1360**
1361** Description      Set power off delays used during USERIAL_Close().  The
1362**                  values in the conf. file setting override these if set.
1363**
1364** Returns          None.
1365**
1366*******************************************************************************/
1367UDRV_API void USERIAL_SetPowerOffDelays(int pre_poweroff_delay, int post_poweroff_delay)
1368{
1369    gPrePowerOffDelay = pre_poweroff_delay;
1370    gPostPowerOffDelay = post_poweroff_delay;
1371}
1372
1373/*******************************************************************************
1374**
1375** Function           USERIAL_Close
1376**
1377** Description        Close a serial port
1378**
1379** Output Parameter   None
1380**
1381** Returns            Nothing
1382**
1383*******************************************************************************/
1384UDRV_API void    USERIAL_Close(tUSERIAL_PORT port)
1385{
1386    pthread_attr_t attr;
1387    pthread_t      close_thread;
1388
1389    ALOGD ("%s: enter", __FUNCTION__);
1390    // check to see if thread is already running
1391    if (pthread_mutex_trylock(&close_thread_mutex) == 0)
1392    {
1393        // mutex aquired so thread is not running
1394        is_close_thread_is_waiting = TRUE;
1395        pthread_mutex_unlock(&close_thread_mutex);
1396
1397        // close transport in a new thread so we don't block the caller
1398        // make thread detached, no other thread will join
1399        pthread_attr_init(&attr);
1400        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1401        pthread_create( &close_thread, &attr, (void *)userial_close_thread,(void*)port);
1402        pthread_attr_destroy(&attr);
1403    }
1404    else
1405    {
1406        // mutex not aquired to thread is already running
1407        ALOGD( "USERIAL_Close(): already closing \n");
1408    }
1409    ALOGD ("%s: exit", __FUNCTION__);
1410}
1411
1412
1413/*******************************************************************************
1414**
1415** Function         userial_close_thread
1416**
1417** Description      Thread to close USERIAL
1418**
1419** Returns          None.
1420**
1421*******************************************************************************/
1422void userial_close_thread(UINT32 params)
1423{
1424    tUSERIAL_PORT port = (tUSERIAL_PORT )params;
1425    BT_HDR                  *p_buf = NULL;
1426    int result;
1427
1428    ALOGD( "%s: closing transport (%d)\n", __FUNCTION__, linux_cb.sock);
1429    pthread_mutex_lock(&close_thread_mutex);
1430    is_close_thread_is_waiting = FALSE;
1431
1432    if (linux_cb.sock <= 0)
1433    {
1434        ALOGD( "%s: already closed (%d)\n", __FUNCTION__, linux_cb.sock);
1435        pthread_mutex_unlock(&close_thread_mutex);
1436        return;
1437    }
1438
1439    send_wakeup_signal();
1440    result = pthread_join( worker_thread1, NULL );
1441    if ( result < 0 )
1442        ALOGE( "%s: pthread_join() FAILED: result: %d", __FUNCTION__, result );
1443    else
1444        ALOGD( "%s: pthread_join() joined: result: %d", __FUNCTION__, result );
1445
1446    if (linux_cb.sock_power_control > 0)
1447    {
1448        result = ioctl(linux_cb.sock_power_control, BCMNFC_WAKE_CTL, sleep_state());
1449        ALOGD("%s: Delay %dms before turning off the chip", __FUNCTION__, gPrePowerOffDelay);
1450        GKI_delay(gPrePowerOffDelay);
1451        result = ioctl(linux_cb.sock_power_control, BCMNFC_POWER_CTL, 0);
1452        ALOGD("%s: Delay %dms after turning off the chip", __FUNCTION__, gPostPowerOffDelay);
1453        GKI_delay(gPostPowerOffDelay);
1454    }
1455    result = close(linux_cb.sock);
1456    if (result<0)
1457        ALOGD("%s: close return %d", __FUNCTION__, result);
1458
1459    if (linux_cb.sock_power_control > 0 && linux_cb.sock_power_control != linux_cb.sock)
1460    result = close(linux_cb.sock_power_control);
1461    if (result<0)
1462        ALOGD("%s: close return %d", __FUNCTION__, result);
1463
1464    linux_cb.sock_power_control = -1;
1465    linux_cb.sock = -1;
1466
1467    close_signal_fds();
1468    pthread_mutex_unlock(&close_thread_mutex);
1469    ALOGD("%s: exiting", __FUNCTION__);
1470}
1471
1472/*******************************************************************************
1473**
1474** Function           USERIAL_Feature
1475**
1476** Description        Check whether a feature of the serial API is supported.
1477**
1478** Output Parameter   None
1479**
1480** Returns            TRUE  if the feature is supported
1481**                    FALSE if the feature is not supported
1482**
1483*******************************************************************************/
1484
1485UDRV_API BOOLEAN USERIAL_Feature(tUSERIAL_FEATURE feature)
1486{
1487    switch (feature)
1488    {
1489    case USERIAL_FEAT_PORT_1:
1490    case USERIAL_FEAT_PORT_2:
1491    case USERIAL_FEAT_PORT_3:
1492    case USERIAL_FEAT_PORT_4:
1493
1494    case USERIAL_FEAT_BAUD_600:
1495    case USERIAL_FEAT_BAUD_1200:
1496    case USERIAL_FEAT_BAUD_9600:
1497    case USERIAL_FEAT_BAUD_19200:
1498    case USERIAL_FEAT_BAUD_57600:
1499    case USERIAL_FEAT_BAUD_115200:
1500
1501    case USERIAL_FEAT_STOPBITS_1:
1502    case USERIAL_FEAT_STOPBITS_2:
1503
1504    case USERIAL_FEAT_PARITY_NONE:
1505    case USERIAL_FEAT_PARITY_EVEN:
1506    case USERIAL_FEAT_PARITY_ODD:
1507
1508    case USERIAL_FEAT_DATABITS_5:
1509    case USERIAL_FEAT_DATABITS_6:
1510    case USERIAL_FEAT_DATABITS_7:
1511    case USERIAL_FEAT_DATABITS_8:
1512
1513    case USERIAL_FEAT_FC_HW:
1514    case USERIAL_FEAT_BUF_BYTE:
1515
1516    case USERIAL_FEAT_OP_FLUSH_RX:
1517    case USERIAL_FEAT_OP_FLUSH_TX:
1518        return TRUE;
1519    default:
1520        return FALSE;
1521    }
1522
1523    return FALSE;
1524}
1525
1526/*****************************************************************************
1527**
1528** Function         UPIO_Set
1529**
1530** Description
1531**      This function sets one or more GPIO devices to the given state.
1532**      Multiple GPIOs of the same type can be masked together to set more
1533**      than one GPIO. This function can only be used on types UPIO_LED and
1534**      UPIO_GENERAL.
1535**
1536** Input Parameters:
1537**      type    The type of device.
1538**      pio     Indicates the particular GPIOs.
1539**      state   The desired state.
1540**
1541** Output Parameter:
1542**      None.
1543**
1544** Returns:
1545**      None.
1546**
1547*****************************************************************************/
1548UDRV_API void UPIO_Set(tUPIO_TYPE type, tUPIO pio, tUPIO_STATE new_state)
1549{
1550    int     ret;
1551    if (type == UPIO_GENERAL)
1552    {
1553        if (pio == NFC_HAL_LP_NFC_WAKE_GPIO)
1554        {
1555            if (new_state == UPIO_ON || new_state == UPIO_OFF)
1556            {
1557                if (linux_cb.sock_power_control > 0)
1558                {
1559                    ALOGD("%s: ioctl, state=%d", __func__, new_state);
1560                    ret = ioctl(linux_cb.sock_power_control, BCMNFC_WAKE_CTL, new_state);
1561                    if (isWake(new_state) && nfc_wake_delay > 0 && new_state != current_nfc_wake_state)
1562                    {
1563                        ALOGD("%s: ioctl, old state=%d, insert delay for %d ms", __func__, current_nfc_wake_state, nfc_wake_delay);
1564                        setWriteDelay(nfc_wake_delay);
1565                    }
1566                    current_nfc_wake_state = new_state;
1567                }
1568            }
1569        }
1570    }
1571}
1572
1573/*****************************************************************************
1574**
1575** Function         setReadPacketSize
1576**
1577** Description
1578**      This function sets the packetSize to the driver.
1579**      this enables faster read operation of NCI/HCI responses
1580**
1581** Input Parameters:
1582**      len     number of bytes to read per operation.
1583**
1584** Output Parameter:
1585**      None.
1586**
1587** Returns:
1588**      None.
1589**
1590*****************************************************************************/
1591void setReadPacketSize(int len)
1592{
1593    int ret;
1594    ALOGD("%s: ioctl, len=%d", __func__, len);
1595    ret = ioctl(linux_cb.sock, BCMNFC_READ_FULL_PACKET, len);
1596}
1597
1598
1599UDRV_API BOOLEAN USERIAL_IsClosed()
1600{
1601    return (linux_cb.sock == -1) ? TRUE : FALSE;
1602}
1603
1604UDRV_API void USERIAL_PowerupDevice(tUSERIAL_PORT port)
1605{
1606    int ret = -1;
1607    unsigned long num = 0;
1608    unsigned int resetSuccess = 0;
1609    unsigned int numTries = 0;
1610    unsigned char spi_negotiation[64];
1611    int delay = gPowerOnDelay;
1612    ALOGD("%s: enter", __FUNCTION__);
1613
1614    if ( GetNumValue ( NAME_READ_MULTI_PACKETS, &num, sizeof ( num ) ) )
1615        bcmi2cnfc_read_multi_packets = num;
1616
1617    if (bcmi2cnfc_read_multi_packets > 0)
1618        ioctl(linux_cb.sock, BCMNFC_READ_MULTI_PACKETS, bcmi2cnfc_read_multi_packets);
1619
1620    while (!resetSuccess && numTries < NUM_RESET_ATTEMPTS) {
1621        if (numTries++ > 0) {
1622            ALOGW("BCM2079x: retrying reset, attempt %d/%d", numTries, NUM_RESET_ATTEMPTS);
1623        }
1624        if (linux_cb.sock_power_control > 0)
1625        {
1626            current_nfc_wake_state = NFC_WAKE_ASSERTED_ON_POR;
1627            ioctl(linux_cb.sock_power_control, BCMNFC_WAKE_CTL, NFC_WAKE_ASSERTED_ON_POR);
1628            ioctl(linux_cb.sock_power_control, BCMNFC_POWER_CTL, 0);
1629            GKI_delay(10);
1630            ret = ioctl(linux_cb.sock_power_control, BCMNFC_POWER_CTL, 1);
1631        }
1632
1633        ret = GetStrValue ( NAME_SPI_NEGOTIATION, (char*)spi_negotiation, sizeof ( spi_negotiation ) );
1634        if (ret > 0 && spi_negotiation[0] > 0 && spi_negotiation[0] < sizeof ( spi_negotiation ) - 1)
1635        {
1636            int len = spi_negotiation[0];
1637            /* Wake control is not available: Start SPI negotiation*/
1638            USERIAL_Write(port, &spi_negotiation[1], len);
1639            USERIAL_Read(port, spi_negotiation, sizeof ( spi_negotiation ));
1640        }
1641
1642        if ( GetNumValue ( NAME_CLIENT_ADDRESS, &num, sizeof ( num ) ) )
1643            bcmi2cnfc_client_addr = num & 0xFF;
1644        if (bcmi2cnfc_client_addr != 0 &&
1645            0x07 < bcmi2cnfc_client_addr &&
1646            bcmi2cnfc_client_addr < 0x78)
1647        {
1648            /* Delay needed after turning on chip */
1649            GKI_delay(delay);
1650            ALOGD( "Change client address to %x\n", bcmi2cnfc_client_addr);
1651            ret = ioctl(linux_cb.sock, BCMNFC_CHANGE_ADDR, bcmi2cnfc_client_addr);
1652            if (!ret) {
1653                resetSuccess = 1;
1654                linux_cb.client_device_address = bcmi2cnfc_client_addr;
1655                /* Delay long enough for address change */
1656                delay = 100;
1657            }
1658        } else {
1659            resetSuccess = 1;
1660        }
1661    }
1662
1663    if (!resetSuccess) {
1664        ALOGE("BCM2079x: failed to initialize NFC controller");
1665    }
1666
1667    GKI_delay(delay);
1668    ALOGD("%s: exit", __FUNCTION__);
1669}
1670