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")); }
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())); }
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); }
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; }
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; }
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; }
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; }
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; }
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; }
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); }
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)); }
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); }
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); }
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); }
/* 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 }
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)); }
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)); }
/* 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); }
/* 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; }
/* 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; }
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; }