10ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel/*
20ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * Copyright 2012 The Android Open Source Project
30ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *
40ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * Licensed under the Apache License, Version 2.0 (the "License");
50ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * you may not use this file except in compliance with the License.
60ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * You may obtain a copy of the License at
70ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *
80ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *      http://www.apache.org/licenses/LICENSE-2.0
90ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *
100ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * Unless required by applicable law or agreed to in writing, software
110ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * distributed under the License is distributed on an "AS IS" BASIS,
120ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * See the License for the specific language governing permissions and
140ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * limitations under the License.
150ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel */
160ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
170ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel/******************************************************************************
180ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *
190ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *  Filename:      hci_smd.c
200ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *
210ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *  Description:   Contains vendor-specific userial functions
220ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *
230ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel ******************************************************************************/
240ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
250ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#define LOG_TAG "bt_vendor"
260ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
270ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include "bt_vendor_qcom.h"
280ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include "hci_smd.h"
29abb4fd870fa1a3dd91a71f6e0d33d6aaa44079c1Jiyong Park
30abb4fd870fa1a3dd91a71f6e0d33d6aaa44079c1Jiyong Park#include <errno.h>
31abb4fd870fa1a3dd91a71f6e0d33d6aaa44079c1Jiyong Park#include <fcntl.h>
32abb4fd870fa1a3dd91a71f6e0d33d6aaa44079c1Jiyong Park#include <stdio.h>
330ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <string.h>
34abb4fd870fa1a3dd91a71f6e0d33d6aaa44079c1Jiyong Park#include <termios.h>
35abb4fd870fa1a3dd91a71f6e0d33d6aaa44079c1Jiyong Park#include <unistd.h>
36abb4fd870fa1a3dd91a71f6e0d33d6aaa44079c1Jiyong Park
370ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <cutils/properties.h>
38abb4fd870fa1a3dd91a71f6e0d33d6aaa44079c1Jiyong Park#include <utils/Log.h>
390ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
400ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel/*****************************************************************************
410ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel**   Macros & Constants
420ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel*****************************************************************************/
430ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#define NUM_OF_DEVS 2
440ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelstatic char *s_pszDevSmd[] = {
450ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    "/dev/smd3",
460ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    "/dev/smd2"
470ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel};
480ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
490ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel/******************************************************************************
500ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel**  Externs
510ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel******************************************************************************/
520ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelextern int is_bt_ssr_hci;
530ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
540ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
550ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel/*****************************************************************************
560ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel**   Functions
570ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel*****************************************************************************/
580ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
590ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelint bt_hci_init_transport_id (int chId )
600ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel{
610ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  struct termios   term;
620ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  int fd = -1;
630ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  int retry = 0;
640ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  char ssrvalue[92]= {'\0'};
650ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
660ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  ssrvalue[0] = '0';
670ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  if(chId >= 2 || chId <0)
680ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel     return -1;
690ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
700ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  fd = open(s_pszDevSmd[chId], (O_RDWR | O_NOCTTY));
710ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
720ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  while ((-1 == fd) && (retry < 7)) {
730ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ALOGE("init_transport: Cannot open %s: %s\n. Retry after 2 seconds",
740ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        s_pszDevSmd[chId], strerror(errno));
750ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    usleep(2000000);
760ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    fd = open(s_pszDevSmd[chId], (O_RDWR | O_NOCTTY));
770ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    retry++;
780ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  }
790ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
800ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  if (-1 == fd)
810ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  {
820ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ALOGE("init_transport: Cannot open %s: %s\n",
830ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        s_pszDevSmd[chId], strerror(errno));
840ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    return -1;
850ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  }
860ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
870ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  /* Sleep (0.5sec) added giving time for the smd port to be successfully
880ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel     opened internally. Currently successful return from open doesn't
890ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel     ensure the smd port is successfully opened.
900ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel     TODO: Following sleep to be removed once SMD port is successfully
910ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel     opened immediately on return from the aforementioned open call */
920ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
930ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  property_get("bluetooth.isSSR", ssrvalue, "");
940ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
950ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  if(ssrvalue[0] == '1')
960ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  {
970ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel      /*reset the SSR flag */
980ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel      if(chId == 1)
990ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel      {
1000ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel          if(property_set("bluetooth.isSSR", "0") < 0)
1010ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel          {
1020ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel              ALOGE("SSR: hci_smd.c:SSR case : error in setting up property new\n ");
1030ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel          }
1040ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel          else
1050ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel          {
1060ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel              ALOGE("SSR: hci_smd.c:SSR case : Reset the SSr Flag new\n ");
1070ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel          }
1080ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel      }
1090ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel      ALOGE("hci_smd.c:IN SSR sleep for 500 msec New \n");
1100ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel      usleep(500000);
1110ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  }
1120ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1130ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  if (tcflush(fd, TCIOFLUSH) < 0)
1140ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  {
1150ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ALOGE("init_uart: Cannot flush %s\n", s_pszDevSmd[chId]);
1160ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    close(fd);
1170ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    return -1;
1180ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  }
1190ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1200ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  if (tcgetattr(fd, &term) < 0)
1210ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  {
1220ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ALOGE("init_uart: Error while getting attributes\n");
1230ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    close(fd);
1240ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    return -1;
1250ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  }
1260ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1270ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  cfmakeraw(&term);
1280ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1290ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  /* JN: Do I need to make flow control configurable, since 4020 cannot
1300ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel   * disable it?
1310ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel   */
1320ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  term.c_cflag |= (CRTSCTS | CLOCAL);
1330ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1340ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  if (tcsetattr(fd, TCSANOW, &term) < 0)
1350ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  {
1360ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ALOGE("init_uart: Error while getting attributes\n");
1370ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    close(fd);
1380ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    return -1;
1390ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  }
1400ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1410ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  ALOGI("Done intiailizing UART\n");
1420ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  return fd;
1430ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
1440ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1450ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelint bt_hci_init_transport(int *pFd)
1460ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel{
1470ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  int i = 0;
1480ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  int fd;
1490ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel  for(i=0; i < NUM_OF_DEVS; i++){
1500ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    fd = bt_hci_init_transport_id(i);
1510ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if(fd < 0 ){
1520ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel      return -1;
1530ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
1540ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    pFd[i] = fd;
1550ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel   }
1560ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel   return 0;
1570ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
1580ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1590ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelint bt_hci_deinit_transport(int *pFd)
1600ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel{
1610ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    close(pFd[0]);
1620ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    close(pFd[1]);
1630ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    return TRUE;
1640ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
165