Example #1
0
void
CancelVibrate(const WindowIdentifier &id)
{
  HAL_LOG(("CancelVibrate: Sending to parent process."));

  WindowIdentifier newID(id);
  newID.AppendProcessID();
  Hal()->SendCancelVibrate(newID.AsArray(), GetTabChildFrom(newID.GetWindow()));
}
void
SetProcessPriority(int aPid,
                   ProcessPriority aPriority,
                   ProcessCPUPriority aCPUPriority,
                   uint32_t aBackgroundLRU)
{
  HAL_LOG("FallbackProcessPriority - SetProcessPriority(%d, %s, %u)\n",
          aPid, ProcessPriorityToString(aPriority, aCPUPriority),
          aBackgroundLRU);
}
void
SetFMRadioFrequency(const uint32_t frequency)
{
  struct v4l2_frequency freq = {0};
  freq.type = V4L2_TUNER_RADIO;
  freq.frequency = (frequency * 10000) / 625;

  int rc = ioctl(sRadioFD, VIDIOC_S_FREQUENCY, &freq);
  if (rc < 0)
    HAL_LOG(("Could not set radio frequency"));
}
Example #4
0
void
Vibrate(const nsTArray<uint32_t>& pattern, const WindowIdentifier &id)
{
  HAL_LOG("Vibrate: Sending to parent process.");

  AutoTArray<uint32_t, 8> p(pattern);

  WindowIdentifier newID(id);
  newID.AppendProcessID();
  Hal()->SendVibrate(p, newID.AsArray(), TabChild::GetFrom(newID.GetWindow()));
}
Example #5
0
void
AdjustSystemClock(int64_t aDeltaMilliseconds)
{
  int fd;
  struct timespec now;

  if (aDeltaMilliseconds == 0) {
    return;
  }

  // Preventing context switch before setting system clock
  sched_yield();
  clock_gettime(CLOCK_REALTIME, &now);
  now.tv_sec += (time_t)(aDeltaMilliseconds / 1000LL);
  now.tv_nsec += (long)((aDeltaMilliseconds % 1000LL) * NsecPerMsec);
  if (now.tv_nsec >= NsecPerSec) {
    now.tv_sec += 1;
    now.tv_nsec -= NsecPerSec;
  }

  if (now.tv_nsec < 0) {
    now.tv_nsec += NsecPerSec;
    now.tv_sec -= 1;
  }

  do {
    fd = open("/dev/alarm", O_RDWR);
  } while (fd == -1 && errno == EINTR);
  ScopedClose autoClose(fd);
  if (fd < 0) {
    HAL_LOG(("Failed to open /dev/alarm: %s", strerror(errno)));
    return;
  }

  if (ioctl(fd, ANDROID_ALARM_SET_RTC, &now) < 0) {
    HAL_LOG(("ANDROID_ALARM_SET_RTC failed: %s", strerror(errno)));
    return;
  }

  hal::NotifySystemTimeChange(hal::SYS_TIME_CHANGE_CLOCK);
}
Example #6
0
void
GetCurrentBatteryInformation(hal::BatteryInformation *aBatteryInfo)
{
  static const int BATTERY_NOT_CHARGING = 0;
  static const int BATTERY_CHARGING_USB = 1;
  static const int BATTERY_CHARGING_AC  = 2;

  FILE *capacityFile = fopen("/sys/class/power_supply/battery/capacity", "r");
  double capacity = dom::battery::kDefaultLevel * 100;
  if (capacityFile) {
    fscanf(capacityFile, "%lf", &capacity);
    fclose(capacityFile);
  }

  FILE *chargingFile = fopen("/sys/class/power_supply/battery/charging_source", "r");
  int chargingSrc = BATTERY_CHARGING_USB;
  bool done = false;
  if (chargingFile) {
    fscanf(chargingFile, "%d", &chargingSrc);
    fclose(chargingFile);
    done = true;
  }

  if (!done) {
    // toro devices support
    chargingFile = fopen("/sys/class/power_supply/battery/status", "r");
    if (chargingFile) {
      char status[16];
      char *str = fgets(status, sizeof(status), chargingFile);
      if (str && (!strcmp(str, "Charging\n") || !strcmp(str, "Full\n"))) {
        // no way here to know if we're charging from USB or AC.
        chargingSrc = BATTERY_CHARGING_USB;
      } else {
        chargingSrc = BATTERY_NOT_CHARGING;
      }
      fclose(chargingFile);
      done = true;
    }
  }

  #ifdef DEBUG
  if (chargingSrc != BATTERY_NOT_CHARGING &&
      chargingSrc != BATTERY_CHARGING_USB &&
      chargingSrc != BATTERY_CHARGING_AC) {
    HAL_LOG(("charging_source contained unknown value: %d", chargingSrc));
  }
  #endif

  aBatteryInfo->level() = capacity / 100;
  aBatteryInfo->charging() = (chargingSrc == BATTERY_CHARGING_USB ||
                              chargingSrc == BATTERY_CHARGING_AC);
  aBatteryInfo->remainingTime() = dom::battery::kUnknownRemainingTime;
}
void
FMRadioSeek(const hal::FMRadioSeekDirection& aDirection)
{
  struct v4l2_hw_freq_seek seek = {0};
  seek.type = V4L2_TUNER_RADIO;
  seek.seek_upward = aDirection == hal::FMRadioSeekDirection::FM_RADIO_SEEK_DIRECTION_UP;
  int rc = ioctl(sRadioFD, VIDIOC_S_HW_FREQ_SEEK, &seek);
  if (rc < 0) {
    HAL_LOG(("Could not initiate hardware seek"));
    return;
  }
}
uint32_t
GetFMRadioSignalStrength()
{
  struct v4l2_tuner tuner = {0};
  int rc = ioctl(sRadioFD, VIDIOC_G_TUNER, &tuner);
  if (rc < 0) {
    HAL_LOG(("Could not query fm radio for signal strength"));
    return 0;
  }

  return tuner.signal;
}
Example #9
0
bool
EnableAlarm()
{
  MOZ_ASSERT(!sAlarmData);

  int alarmFd = open("/dev/alarm", O_RDWR);
  if (alarmFd < 0) {
    HAL_LOG(("Failed to open alarm device: %s.", strerror(errno)));
    return false;
  }

  nsAutoPtr<AlarmData> alarmData(new AlarmData(alarmFd));

  struct sigaction actions;
  memset(&actions, 0, sizeof(actions));
  sigemptyset(&actions.sa_mask);
  actions.sa_flags = 0;
  actions.sa_handler = ShutDownAlarm;
  if (sigaction(SIGUSR1, &actions, NULL)) {
    HAL_LOG(("Failed to set SIGUSR1 signal for alarm-watcher thread."));
    return false;
  }

  pthread_attr_t attr;
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

  int status = pthread_create(&sAlarmFireWatcherThread, &attr, WaitForAlarm, alarmData.get());
  if (status) {
    alarmData = NULL;
    HAL_LOG(("Failed to create alarm watcher thread. Status: %d.", status));
    return false;
  }

  pthread_attr_destroy(&attr);

  // The thread owns this now.  We only hold a pointer.
  sAlarmData = alarmData.forget();
  return true;
}
Example #10
0
double
GetScreenBrightness()
{
  char buf[32];
  ReadFromFile(screenBrightnessFilename, buf);

  errno = 0;
  unsigned long val = strtoul(buf, NULL, 10);
  if (errno) {
    HAL_LOG(("Cannot parse contents of %s; expected an unsigned "
             "int, but contains \"%s\".",
             screenBrightnessFilename, buf));
    return 1;
  }

  if (val > 255) {
    HAL_LOG(("Got out-of-range brightness %d, truncating to 1.0", val));
    val = 255;
  }

  return val / 255.0;
}
Example #11
0
bool
SetAlarm(int32_t aSeconds, int32_t aNanoseconds)
{
  if (!sAlarmData) {
    HAL_LOG(("We should have enabled the alarm."));
    return false;
  }

  struct timespec ts;
  ts.tv_sec = aSeconds;
  ts.tv_nsec = aNanoseconds;

  // currently we only support RTC wakeup alarm type
  const int result = ioctl(sAlarmData->mFd, ANDROID_ALARM_SET(ANDROID_ALARM_RTC_WAKEUP), &ts);

  if (result < 0) {
    HAL_LOG(("Unable to set alarm: %s.", strerror(errno)));
    return false;
  }

  return true;
}
Example #12
0
uint32_t
GetFMRadioFrequency()
{
  if (!sRadioEnabled)
    return 0;

  struct v4l2_frequency freq;
  int rc = ioctl(sRadioFD, VIDIOC_G_FREQUENCY, &freq);
  if (rc < 0) {
    HAL_LOG(("Could not get radio frequency"));
    return 0;
  }

  return (freq.frequency * 625) / 10000;
}
Example #13
0
void
GetFMRadioSettings(hal::FMRadioSettings* aInfo)
{
  if (!sRadioEnabled) {
    return;
  }

  struct v4l2_tuner tuner = {0};
  int rc = ioctl(sRadioFD, VIDIOC_G_TUNER, &tuner);
  if (rc < 0) {
    HAL_LOG(("Could not query fm radio for settings"));
    return;
  }

  aInfo->upperLimit() = (tuner.rangehigh * 625) / 10000;
  aInfo->lowerLimit() = (tuner.rangelow * 625) / 10000;
}
Example #14
0
void
DisableRDS()
{
  if (!sRadioEnabled || !sRDSEnabled)
    return;

  int rc = setControl(V4L2_CID_RDS_RECEPTION, false);
  if (rc < 0) {
    HAL_LOG("Could not disable RDS reception (%d)", rc);
  }

  sRDSEnabled = false;

  write(sRDSPipeFD, "x", 1);

  pthread_join(sRDSThread, nullptr);

  close(sRDSPipeFD);
}
Example #15
0
void
SetFMRadioFrequency(const uint32_t frequency)
{
  struct v4l2_frequency freq = {0};
  freq.type = V4L2_TUNER_RADIO;
  freq.frequency = (frequency * 10000) / 625;

  int rc = ioctl(sRadioFD, VIDIOC_S_FREQUENCY, &freq);
  if (rc < 0)
    HAL_LOG("Could not set radio frequency");

  if (sMsmFMMode && rc >= 0)
    return;

  NS_DispatchToMainThread(new RadioUpdate(hal::FM_RADIO_OPERATION_TUNE,
                                          rc < 0 ?
                                          hal::FM_RADIO_OPERATION_STATUS_FAIL :
                                          hal::FM_RADIO_OPERATION_STATUS_SUCCESS));
}
Example #16
0
void
SetScreenBrightness(double brightness)
{
  // Don't use De Morgan's law to push the ! into this expression; we want to
  // catch NaN too.
  if (!(0 <= brightness && brightness <= 1)) {
    HAL_LOG(("SetScreenBrightness: Dropping illegal brightness %f.",
             brightness));
    return;
  }

  // Convert the value in [0, 1] to an int between 0 and 255, then write to a
  // string.
  int val = static_cast<int>(round(brightness * 255));
  char str[4];
  DebugOnly<int> numChars = snprintf(str, sizeof(str), "%d", val);
  MOZ_ASSERT(numChars < static_cast<int>(sizeof(str)));

  WriteToFile(screenBrightnessFilename, str);
}
Example #17
0
void
DisableFMRadio()
{
  if (!sRadioEnabled)
    return;

  sRadioEnabled = false;

  // Tavarua specific start
  int rc = setControl(V4L2_CID_PRIVATE_TAVARUA_STATE, FM_OFF);
  if (rc < 0) {
    HAL_LOG(("Unable to turn off radio"));
  }
  // Tavarua specific end

  pthread_join(sRadioThread, NULL);

  close(sRadioFD);

  hal::FMRadioOperationInformation info;
  info.operation() = hal::FM_RADIO_OPERATION_DISABLE;
  info.status() = hal::FM_RADIO_OPERATION_STATUS_SUCCESS;
  hal::NotifyFMRadioStatus(info);
}
Example #18
0
void
SetScreenBrightness(double brightness)
{
  // Don't use De Morgan's law to push the ! into this expression; we want to
  // catch NaN too.
  if (!(0 <= brightness && brightness <= 1)) {
    HAL_LOG(("SetScreenBrightness: Dropping illegal brightness %f.",
             brightness));
    return;
  }

  // Convert the value in [0, 1] to an int between 0 and 255 and convert to a color
  // note that the high byte is FF, corresponding to the alpha channel.
  int val = static_cast<int>(round(brightness * 255));
  uint32_t color = (0xff<<24) + (val<<16) + (val<<8) + val;

  hal::LightConfiguration aConfig;
  aConfig.mode() = hal::eHalLightMode_User;
  aConfig.flash() = hal::eHalLightFlash_None;
  aConfig.flashOnMS() = aConfig.flashOffMS() = 0;
  aConfig.color() = color;
  hal::SetLight(hal::eHalLightID_Backlight, aConfig);
  hal::SetLight(hal::eHalLightID_Buttons, aConfig);
}
Example #19
0
/* This runs on the main thread but most of the
 * initialization is pushed to the radio thread. */
void
EnableFMRadio(const hal::FMRadioSettings& aInfo)
{
  if (sRadioEnabled) {
    HAL_LOG(("Radio already enabled!"));
    return;
  }

  mozilla::ScopedClose fd(open("/dev/radio0", O_RDWR));
  if (fd < 0) {
    HAL_LOG(("Unable to open radio device"));
    return;
  }

  struct v4l2_capability cap;
  int rc = ioctl(fd, VIDIOC_QUERYCAP, &cap);
  if (rc < 0) {
    HAL_LOG(("Unable to query radio device"));
    return;
  }

  HAL_LOG(("Radio: %s (%s)\n", cap.driver, cap.card));

  if (!(cap.capabilities & V4L2_CAP_RADIO)) {
    HAL_LOG(("/dev/radio0 isn't a radio"));
    return;
  }

  if (!(cap.capabilities & V4L2_CAP_TUNER)) {
    HAL_LOG(("/dev/radio0 doesn't support the tuner interface"));
    return;
  }
  sRadioFD = fd.forget();
  sRadioSettings = aInfo;

  // Tavarua specific start
  sTavaruaVersion = cap.version;
  pthread_create(&sRadioThread, NULL, runTavaruaRadio, NULL);
  // Tavarua specific end
}
Example #20
0
void
SetProcessPriority(int aPid, ProcessPriority aPriority)
{
  HAL_LOG(("SetProcessPriority(pid=%d, priority=%d)", aPid, aPriority));

  const char* priorityStr = NULL;
  switch (aPriority) {
  case PROCESS_PRIORITY_BACKGROUND:
    priorityStr = "background";
    break;
  case PROCESS_PRIORITY_FOREGROUND:
    priorityStr = "foreground";
    break;
  case PROCESS_PRIORITY_MASTER:
    priorityStr = "master";
    break;
  default:
    MOZ_NOT_REACHED();
  }

  // Notice that you can disable oom_adj and renice by deleting the prefs
  // hal.processPriorityManager{foreground,background,master}{OomAdjust,Nice}.

  int32_t oomScoreAdj = 0;
  nsresult rv = Preferences::GetInt(nsPrintfCString(
    "hal.processPriorityManager.gonk.%sOomScoreAdjust",
    priorityStr).get(), &oomScoreAdj);

  if (NS_SUCCEEDED(rv)) {

    int clampedOomScoreAdj = clamped<int>(oomScoreAdj, OOM_SCORE_ADJ_MIN,
                                                       OOM_SCORE_ADJ_MAX);
    if(clampedOomScoreAdj != oomScoreAdj) {
      HAL_LOG(("Clamping OOM adjustment for pid %d to %d",
               aPid, clampedOomScoreAdj));
    } else {
      HAL_LOG(("Setting OOM adjustment for pid %d to %d",
               aPid, clampedOomScoreAdj));
    }

    // We try the newer interface first, and fall back to the older interface
    // on failure.

    if (!WriteToFile(nsPrintfCString("/proc/%d/oom_score_adj", aPid).get(),
                     nsPrintfCString("%d", clampedOomScoreAdj).get()))
    {
      int oomAdj = oomAdjOfOomScoreAdj(clampedOomScoreAdj);

      WriteToFile(nsPrintfCString("/proc/%d/oom_adj", aPid).get(),
                  nsPrintfCString("%d", oomAdj).get());
    }
  }

  int32_t nice = 0;
  rv = Preferences::GetInt(nsPrintfCString(
    "hal.processPriorityManager.gonk.%sNice", priorityStr).get(), &nice);
  if (NS_SUCCEEDED(rv)) {
    HAL_LOG(("Setting nice for pid %d to %d", aPid, nice));

    int success = setpriority(PRIO_PROCESS, aPid, nice);
    if (success != 0) {
      HAL_LOG(("Failed to set nice for pid %d to %d", aPid, nice));
    }
  }
}
void
SetProcessPriority(int aPid, ProcessPriority aPriority)
{
  HAL_LOG(("FallbackProcessPriority - SetProcessPriority(%d, %d)\n", aPid, aPriority));
}
Example #22
0
File: osal.c Project: PheeL79/diOS
Status OSAL_Init(void)
{
extern Status OS_MemoryInit(void);
extern Status OS_SettingsInit(void);
extern Status OS_EnvInit(void);
extern Status OS_EventInit(void);
extern Status OS_TimeInit(void);
#if (OS_TIMERS_ENABLED)
extern Status OS_TimerInit(void);
#endif //(OS_TIMERS_ENABLED)
extern Status OS_DriverInit_(void);
extern Status OS_QueueInit(void);
extern Status OS_TaskInit_(void);
#if (OS_AUDIO_ENABLED)
extern Status OS_AudioInit(void);
#endif // (OS_AUDIO_ENABLED)
#if (OS_NETWORK_ENABLED)
extern Status OS_NetworkInit(void);
#endif // (OS_NETWORK_ENABLED)
Status s;
    //Init OSAL.
    HAL_CRITICAL_SECTION_ENTER();
    is_idle = OS_FALSE;
    // uxCriticalNesting = 0; !!! Variables are created before OS Engine scheduler is started! Affects on drivers interrupts!
    IF_STATUS(s = OS_MemoryInit())      { return s; }
#if (OS_TIMERS_ENABLED)
    IF_STATUS(s = OS_TimerInit())       { return s; }
#endif //(OS_TIMERS_ENABLED)
    IF_STATUS(s = OS_TimeInit())        { return s; }
    IF_STATUS(s = OS_DriverInit_())     { return s; }
    IF_STATUS(s = OS_DebugInit())       { return s; }
    IF_STATUS(s = OS_QueueInit())       { return s; }
    IF_STATUS(s = OS_TaskInit_())       { return s; }
    IF_STATUS(s = OS_ShellInit())       { return s; }
    IF_STATUS(s = OS_EnvInit())         { return s; }
#if (OS_EVENTS_ENABLED)
    IF_STATUS(s = OS_EventInit())       { return s; }
#endif //(OS_EVENTS_ENABLED)
    IF_STATUS(s = OS_SettingsInit())    { return s; }
    IF_STATUS(s = OS_PowerInit())       { return s; }
    IF_STATUS(s = OSAL_DriversCreate()) { return s; }
    HAL_CRITICAL_SECTION_EXIT();
    HAL_LOG(D_INFO, "OSAL init...");
    HAL_LOG(D_INFO, "-------------------------------");
#if (OS_FILE_SYSTEM_ENABLED)
    IF_STATUS(s = OS_FileSystemInit())  { return s; }
#endif // OS_FILE_SYSTEM_ENABLED
#if (OS_AUDIO_ENABLED)
    IF_STATUS(s = OS_AudioInit())       { return s; }
#endif //(OS_AUDIO_ENABLED)
#if (OS_NETWORK_ENABLED)
    IF_STATUS(s = OS_NetworkInit())     { return s; }
#endif //(OS_NETWORK_ENABLED)
    //Create environment variables.
    IF_STATUS(s = OS_EnvVariableSet("locale", HAL_LOCALE_DEFAULT, OS_LocaleSet))            { return s; }
//    IF_STATUS(s = OS_EnvVariableSet("stdio", "USART6", OS_StdIoSet))                    { return s; }
    IF_STATUS(s = OS_EnvVariableSet("log_level", OS_LOG_LEVEL_DEFAULT, OS_LogLevelSet)) { return s; }
    IF_STATUS(s = OS_EnvVariableSet("log_file", OS_LOG_FILE_PATH, OS_NULL))             { return s; }
    IF_STATUS(s = OS_EnvVariableSet("config_file", OS_SETTINGS_FILE_PATH, OS_NULL))     { return s; }
#if (OS_FILE_SYSTEM_ENABLED)
    IF_STATUS(s = OS_EnvVariableSet("media_automount", "on", OS_NULL))                  { return s; }
#endif // OS_FILE_SYSTEM_ENABLED
#if (OS_AUDIO_ENABLED)
    Str volume_str[4];
    if (0 > OS_SNPrintF(volume_str, sizeof(volume_str), "%u", OS_AUDIO_OUT_VOLUME_DEFAULT)) {
        return S_INVALID_VALUE;
    }
    IF_STATUS(s = OS_EnvVariableSet("volume", volume_str, OS_VolumeSet)) {
        if (S_INVALID_PTR != s) { return s; } //Ignore first attempt. No audio devices are created so far.
    }
#endif //(OS_AUDIO_ENABLED)
    //Init environment variables.
    const OS_PowerState power = PWR_STARTUP;
    os_env.hal_env_p->power = power;
    //Create and start system tasks.
    IF_STATUS(s = OS_StartupInit())     { return s; }
    IF_STATUS(s = OS_StartupSystem())   { return s; }
    HAL_LOG(D_INFO, "-------------------------------");
    return s;
}
void
SetCurrentThreadPriority(ThreadPriority aPriority)
{
  HAL_LOG("FallbackThreadPriority - SetCurrentThreadPriority(%d)\n",
          ThreadPriorityToString(aPriority));
}
Example #24
0
/* This runs on the main thread but most of the
 * initialization is pushed to the radio thread. */
void
EnableFMRadio(const hal::FMRadioSettings& aInfo)
{
  if (sRadioEnabled) {
    HAL_LOG("Radio already enabled!");
    return;
  }

  hal::FMRadioOperationInformation info;
  info.operation() = hal::FM_RADIO_OPERATION_ENABLE;
  info.status() = hal::FM_RADIO_OPERATION_STATUS_FAIL;

  mozilla::ScopedClose fd(open("/dev/radio0", O_RDWR));
  if (fd < 0) {
    HAL_LOG("Unable to open radio device");
    hal::NotifyFMRadioStatus(info);
    return;
  }

  struct v4l2_capability cap;
  int rc = ioctl(fd, VIDIOC_QUERYCAP, &cap);
  if (rc < 0) {
    HAL_LOG("Unable to query radio device");
    hal::NotifyFMRadioStatus(info);
    return;
  }

  sMsmFMMode = !strcmp((char *)cap.driver, "radio-tavarua") ||
      !strcmp((char *)cap.driver, "radio-iris");
  HAL_LOG("Radio: %s (%s)\n", cap.driver, cap.card);

  if (!(cap.capabilities & V4L2_CAP_RADIO)) {
    HAL_LOG("/dev/radio0 isn't a radio");
    hal::NotifyFMRadioStatus(info);
    return;
  }

  if (!(cap.capabilities & V4L2_CAP_TUNER)) {
    HAL_LOG("/dev/radio0 doesn't support the tuner interface");
    hal::NotifyFMRadioStatus(info);
    return;
  }

  sRDSSupported = cap.capabilities & V4L2_CAP_RDS_CAPTURE;
  sRadioSettings = aInfo;

  if (sMsmFMMode) {
    sRadioFD = fd.forget();
    sMsmFMVersion = cap.version;
    if (pthread_create(&sRadioThread, nullptr, runMsmFMRadio, nullptr)) {
      HAL_LOG("Couldn't create radio thread");
      hal::NotifyFMRadioStatus(info);
    }
    return;
  }

  struct v4l2_tuner tuner = {0};
  tuner.type = V4L2_TUNER_RADIO;
  tuner.rangelow = (aInfo.lowerLimit() * 10000) / 625;
  tuner.rangehigh = (aInfo.upperLimit() * 10000) / 625;
  tuner.audmode = V4L2_TUNER_MODE_STEREO;
  rc = ioctl(fd, VIDIOC_S_TUNER, &tuner);
  if (rc < 0) {
    HAL_LOG("Unable to adjust band limits");
  }

  int emphasis;
  switch (aInfo.preEmphasis()) {
  case 0:
    emphasis = V4L2_DEEMPHASIS_DISABLED;
    break;
  case 50:
    emphasis = V4L2_DEEMPHASIS_50_uS;
    break;
  case 75:
    emphasis = V4L2_DEEMPHASIS_75_uS;
    break;
  default:
    MOZ_CRASH("Invalid preemphasis setting");
    break;
  }
  rc = setControl(V4L2_CID_TUNE_DEEMPHASIS, emphasis);
  if (rc < 0) {
    HAL_LOG("Unable to configure deemphasis");
  }

  sRadioFD = fd.forget();
  sRadioEnabled = true;

  info.status() = hal::FM_RADIO_OPERATION_STATUS_SUCCESS;
  hal::NotifyFMRadioStatus(info);
}
Example #25
0
/* Runs on the rds thread */
static void*
readRDSDataThread(void* data)
{
  v4l2_rds_data rdsblocks[16];
  uint16_t blocks[4];

  ScopedClose pipefd((int)data);

  ScopedClose epollfd(epoll_create(2));
  if (epollfd < 0) {
    HAL_LOG("Could not create epoll FD for RDS thread (%d)", errno);
    return nullptr;
  }

  epoll_event event = {
    EPOLLIN,
    { 0 }
  };

  event.data.fd = pipefd;
  if (epoll_ctl(epollfd, EPOLL_CTL_ADD, pipefd, &event) < 0) {
    HAL_LOG("Could not set up epoll FD for RDS thread (%d)", errno);
    return nullptr;
  }

  event.data.fd = sRadioFD;
  if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sRadioFD, &event) < 0) {
    HAL_LOG("Could not set up epoll FD for RDS thread (%d)", errno);
    return nullptr;
  }

  epoll_event events[2] = {{ 0 }};
  int event_count;
  uint32_t block_bitmap = 0;
  while ((event_count = epoll_wait(epollfd, events, 2, -1)) > 0 ||
         errno == EINTR) {
    bool RDSDataAvailable = false;
    for (int i = 0; i < event_count; i++) {
      if (events[i].data.fd == pipefd) {
        if (!sRDSEnabled)
          return nullptr;
        char tmp[32];
        TEMP_FAILURE_RETRY(read(pipefd, tmp, sizeof(tmp)));
      } else if (events[i].data.fd == sRadioFD) {
        RDSDataAvailable = true;
      }
    }

    if (!RDSDataAvailable)
      continue;

    ssize_t len =
      TEMP_FAILURE_RETRY(read(sRadioFD, rdsblocks, sizeof(rdsblocks)));
    if (len < 0) {
      HAL_LOG("Unexpected error while reading RDS data %d", errno);
      return nullptr;
    }

    int blockcount = len / sizeof(rdsblocks[0]);
    int lastblock = -1;
    for (int i = 0; i < blockcount; i++) {
      if ((rdsblocks[i].block & V4L2_RDS_BLOCK_MSK) == V4L2_RDS_BLOCK_INVALID ||
           rdsblocks[i].block & V4L2_RDS_BLOCK_ERROR) {
        block_bitmap |= 1 << V4L2_RDS_BLOCK_INVALID;
        continue;
      }

      int blocknum = rdsblocks[i].block & V4L2_RDS_BLOCK_MSK;
      // In some cases, the full set of bits in an RDS group isn't
      // needed, in which case version B RDS groups can be sent.
      // Version B groups replace block C with block C' (V4L2_RDS_BLOCK_C_ALT).
      // Block C' always stores the PI code, so receivers can find the PI
      // code more quickly/reliably.
      // However, we only process whole RDS groups, so it doesn't matter here.
      if (blocknum == V4L2_RDS_BLOCK_C_ALT)
        blocknum = V4L2_RDS_BLOCK_C;
      if (blocknum > V4L2_RDS_BLOCK_D) {
        HAL_LOG("Unexpected RDS block number %d. This is a driver bug.",
                blocknum);
        continue;
      }

      if (blocknum == V4L2_RDS_BLOCK_A)
        block_bitmap = 0;

      // Skip the group if we skipped a block.
      // This stops us from processing blocks sent out of order.
      if (block_bitmap != ((1 << blocknum) - 1)) {
        block_bitmap |= 1 << V4L2_RDS_BLOCK_INVALID;
        continue;
      }

      block_bitmap |= 1 << blocknum;

      lastblock = blocknum;
      blocks[blocknum] = (rdsblocks[i].msb << 8) | rdsblocks[i].lsb;

      // Make sure we have all 4 blocks and that they're valid
      if (block_bitmap != 0x0F)
        continue;

      hal::FMRadioRDSGroup group;
      group.blockA() = blocks[V4L2_RDS_BLOCK_A];
      group.blockB() = blocks[V4L2_RDS_BLOCK_B];
      group.blockC() = blocks[V4L2_RDS_BLOCK_C];
      group.blockD() = blocks[V4L2_RDS_BLOCK_D];
      NotifyFMRadioRDSGroup(group);
    }
  }

  return nullptr;
}
Example #26
0
/* Runs on the radio thread */
static void
initTavaruaRadio(hal::FMRadioSettings &aInfo)
{
  mozilla::ScopedClose fd(sRadioFD);
  char version[64];
  int rc;
  snprintf(version, sizeof(version), "%d", sTavaruaVersion);
  property_set("hw.fm.version", version);

  /* Set the mode for soc downloader */
  property_set("hw.fm.mode", "normal");
  /* start fm_dl service */
  property_set("ctl.start", "fm_dl");

  /*
   * Fix bug 800263. Wait until the FM radio chips initialization is done
   * then set other properties, or the system will hang and reboot. This
   * work around is from codeaurora
   * (git://codeaurora.org/platform/frameworks/base.git).
   */
  for (int i = 0; i < 4; ++i) {
    sleep(1);
    char value[PROPERTY_VALUE_MAX];
    property_get("hw.fm.init", value, "0");
    if (!strcmp(value, "1")) {
      break;
    }
  }

  rc = setControl(V4L2_CID_PRIVATE_TAVARUA_STATE, FM_RECV);
  if (rc < 0) {
    HAL_LOG(("Unable to turn on radio |%s|", strerror(errno)));
    return;
  }

  int preEmphasis = aInfo.preEmphasis() <= 50;
  rc = setControl(V4L2_CID_PRIVATE_TAVARUA_EMPHASIS, preEmphasis);
  if (rc) {
    HAL_LOG(("Unable to configure preemphasis"));
    return;
  }

  rc = setControl(V4L2_CID_PRIVATE_TAVARUA_RDS_STD, 0);
  if (rc) {
    HAL_LOG(("Unable to configure RDS"));
    return;
  }

  int spacing;
  switch (aInfo.spaceType()) {
  case 50:
    spacing = FM_CH_SPACE_50KHZ;
    break;
  case 100:
    spacing = FM_CH_SPACE_100KHZ;
    break;
  case 200:
    spacing = FM_CH_SPACE_200KHZ;
    break;
  default:
    HAL_LOG(("Unsupported space value - %d", aInfo.spaceType()));
    return;
  }

  rc = setControl(V4L2_CID_PRIVATE_TAVARUA_SPACING, spacing);
  if (rc) {
    HAL_LOG(("Unable to configure spacing"));
    return;
  }

  /*
   * Frequency conversions
   *
   * HAL uses units of 1k for frequencies
   * V4L2 uses units of 62.5kHz
   * Multiplying by (10000 / 625) converts from HAL units to V4L2.
   */

  struct v4l2_tuner tuner = {0};
  tuner.rangelow = (aInfo.lowerLimit() * 10000) / 625;
  tuner.rangehigh = (aInfo.upperLimit() * 10000) / 625;
  rc = ioctl(fd, VIDIOC_S_TUNER, &tuner);
  if (rc < 0) {
    HAL_LOG(("Unable to adjust band limits"));
    return;
  }

  rc = setControl(V4L2_CID_PRIVATE_TAVARUA_REGION, TAVARUA_REGION_OTHER);
  if (rc < 0) {
    HAL_LOG(("Unable to configure region"));
    return;
  }

  // Some devices do not support analog audio routing. This should be
  // indicated by the 'ro.moz.fm.noAnalog' property at build time.
  char propval[PROPERTY_VALUE_MAX];
  property_get("ro.moz.fm.noAnalog", propval, "");
  bool noAnalog = !strcmp(propval, "true");

  rc = setControl(V4L2_CID_PRIVATE_TAVARUA_SET_AUDIO_PATH,
                  noAnalog ? FM_DIGITAL_PATH : FM_ANALOG_PATH);
  if (rc < 0) {
    HAL_LOG(("Unable to set audio path"));
    return;
  }

  if (!noAnalog) {
    /* Set the mode for soc downloader */
    property_set("hw.fm.mode", "config_dac");
    /* Use analog mode FM */
    property_set("hw.fm.isAnalog", "true");
    /* start fm_dl service */
    property_set("ctl.start", "fm_dl");

    for (int i = 0; i < 4; ++i) {
      sleep(1);
      char value[PROPERTY_VALUE_MAX];
      property_get("hw.fm.init", value, "0");
      if (!strcmp(value, "1")) {
        break;
      }
    }
  }

  fd.forget();
  sRadioEnabled = true;
}
Example #27
0
bool
NetlinkPoller::OpenSocket()
{
  mSocket.rwget() = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
  if (mSocket.get() < 0)
    return false;

  int sz = kBuffsize;

  if (setsockopt(mSocket.get(), SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0)
    return false;

  // add FD_CLOEXEC flag
  int flags = fcntl(mSocket.get(), F_GETFD);
  if (flags == -1) {
      return false;
  }
  flags |= FD_CLOEXEC;
  if (fcntl(mSocket.get(), F_SETFD, flags) == -1)
    return false;

  // set non-blocking
  if (fcntl(mSocket.get(), F_SETFL, O_NONBLOCK) == -1)
    return false;

  struct sockaddr_nl saddr;
  bzero(&saddr, sizeof(saddr));
  saddr.nl_family = AF_NETLINK;
  saddr.nl_groups = 1;
  saddr.nl_pid = gettid();

  do {
    if (bind(mSocket.get(), (struct sockaddr *)&saddr, sizeof(saddr)) == 0) {
      break;
    }

    if (errno != EADDRINUSE) {
      return false;
    }

    if (saddr.nl_pid == 0) {
      return false;
    }

    // Once there was any other place in the same process assigning saddr.nl_pid by
    // gettid(), we can detect it and print warning message.
    HAL_LOG("The netlink socket address saddr.nl_pid=%u is in use. "
            "Let the kernel re-assign.\n", saddr.nl_pid);
    saddr.nl_pid = 0;
  } while (true);

  if (!mIOLoop->WatchFileDescriptor(mSocket.get(),
                                    true,
                                    MessageLoopForIO::WATCH_READ,
                                    &mReadWatcher,
                                    this)) {
      return false;
  }

  return true;
}