void TopCanvas::Flip() { #ifdef USE_FB #ifdef GREYSCALE CopyFromGreyscale( #ifdef DITHER dither, #endif #ifdef KOBO enable_dither, #endif map, map_pitch, map_bpp, buffer); #else CopyFromBGRA(map, map_pitch, map_bpp, buffer); #endif #ifdef KOBO if (frame_sync) Wait(); epd_update_marker++; struct mxcfb_update_data epd_update_data = { { 0, 0, buffer.width, buffer.height }, uint32_t(enable_dither && (/* use A2 mode only on some Kobo models */ DetectKoboModel() == KoboModel::TOUCH2 || DetectKoboModel() == KoboModel::GLO_HD) ? WAVEFORM_MODE_A2 : WAVEFORM_MODE_AUTO), UPDATE_MODE_FULL, // PARTIAL epd_update_marker, TEMP_USE_AMBIENT, enable_dither ? EPDC_FLAG_FORCE_MONOCHROME : 0, }; ioctl(fd, MXCFB_SEND_UPDATE, &epd_update_data); #endif #endif /* USE_FB */ }
bool KoboExportUSBStorage() { #ifdef KOBO bool result = false; RmMod("g_ether"); RmMod("g_file_storage"); switch (DetectKoboModel()) { case KoboModel::UNKNOWN: // Let unknown try the old device case KoboModel::MINI: case KoboModel::TOUCH: case KoboModel::AURA: InsMod("/drivers/ntx508/usb/gadget/arcotg_udc.ko"); result = InsMod("/drivers/ntx508/usb/gadget/g_file_storage.ko", "file=/dev/mmcblk0p3", "stall=0"); break; case KoboModel::GLO_HD: InsMod("/drivers/mx6sl-ntx/usb/gadget/arcotg_udc.ko"); result = InsMod("/drivers/mx6sl-ntx/usb/gadget/g_file_storage.ko", "file=/dev/mmcblk0p3", "stall=0"); break; } return result; #else return true; #endif }
KoboModel DetectKoboModel() { char buffer[16]; if (!ReadFromFile("/dev/mmcblk0", 0x200, buffer, sizeof(buffer))) return KoboModel::UNKNOWN; return DetectKoboModel(buffer); }
KoboModel DetectKoboModel() { char buffer[16]; if (!ReadFromFile("/dev/mmcblk0", 0x200, buffer, sizeof(buffer))) return KoboModel::UNKNOWN; #if TESTBENCH StartupStore(_T(".. Detected Kobo Model <%s>%s"),buffer,,NEWLINE); #endif return DetectKoboModel(buffer); }
static unsigned TranslateDimension(unsigned value) { #ifdef KOBO if (value == 1024 && DetectKoboModel() == KoboModel::AURA) /* the Kobo Aura announces 1024 pixel rows, but the physical display only shows 1014 */ value -= 10; #endif return value; }
int main(int argc, char **argv) { /* enable FreeType anti-aliasing, because we don't use dithering in this program */ FreeType::mono = false; ScreenGlobalInit screen_init; Layout::Initialize({600, 800}); Font::Initialise(); Display::Rotate(DisplayOrientation::PORTRAIT); InitialiseFonts(); { TopCanvas screen; screen.Create(PixelSize(100, 100), true, false); Canvas canvas = screen.Lock(); if (canvas.IsDefined()) { /* all black first, to eliminate E-ink ghost images */ canvas.Clear(COLOR_BLACK); screen.Flip(); screen.Wait(); /* disable dithering, render with 16 shades of gray, to make the (static) display more pretty */ screen.SetEnableDither(false); /* draw the pictuer */ canvas.ClearWhite(); Draw(canvas); /* finish */ screen.Unlock(); screen.Flip(); screen.Wait(); } } /* now we can power off the Kobo; the picture remains on the screen */ if (DetectKoboModel() == KoboModel::GLO_HD) //The GloHD needs -f to not clear screen execl("/sbin/poweroff", "poweroff", "-f", nullptr); else execl("/sbin/poweroff", "poweroff", nullptr); return 0; }
bool KoboWifiOn() { #ifdef KOBO switch (DetectKoboModel()) { case KoboModel::UNKNOWN: // Let unknown try the old device case KoboModel::MINI: case KoboModel::TOUCH: case KoboModel::AURA: case KoboModel::GLO: // TODO: is this correct? InsMod("/drivers/ntx508/wifi/sdio_wifi_pwr.ko"); InsMod("/drivers/ntx508/wifi/dhd.ko"); break; case KoboModel::TOUCH2: case KoboModel::GLO_HD: InsMod("/drivers/mx6sl-ntx/wifi/sdio_wifi_pwr.ko"); InsMod("/drivers/mx6sl-ntx/wifi/dhd.ko"); break; case KoboModel::AURA2: InsMod("/drivers/mx6sl-ntx/wifi/sdio_wifi_pwr.ko"); InsMod("/drivers/mx6sl-ntx/wifi/8189fs.ko"); break; } Sleep(2000); Run("/sbin/ifconfig", "eth0", "up"); Run("/sbin/iwconfig", "eth0", "power", "off"); Run("/bin/wlarm_le", "-i", "eth0", "up"); Run("/bin/wpa_supplicant", "-i", "eth0", "-c", "/etc/wpa_supplicant/wpa_supplicant.conf", "-C", "/var/run/wpa_supplicant", "-B", "-D", "wext"); Sleep(2000); Start("/sbin/udhcpc", "-S", "-i", "eth0", "-s", "/etc/udhcpc.d/default.script", "-t15", "-T10", "-A3", "-f", "-q"); return true; #else return false; #endif }
inline void SystemWidget::SwitchKernel() { #ifdef KOBO KoboModel model = DetectKoboModel(); if (model != KoboModel::MINI && model != KoboModel::GLO && model != KoboModel::TOUCH2 && model != KoboModel::GLO_HD && model != KoboModel::AURA2 && ShowMessageBox(_T("This feature was designed for the Kobo Mini, Touch 2.0, Glo HD and Aura 2, but this is not one. Use at your own risk. Continue?"), _T("USB-OTG"), MB_YESNO) != IDYES) return; const char *otg_kernel_image, *kobo_kernel_image; switch (model) { case KoboModel::GLO_HD: case KoboModel::TOUCH2: otg_kernel_image = "/opt/xcsoar/lib/kernel/uImage.glohd.otg"; kobo_kernel_image = "/opt/xcsoar/lib/kernel/uImage.glohd"; break; case KoboModel::AURA2: otg_kernel_image = "/opt/xcsoar/lib/kernel/uImage.aura2.otg"; kobo_kernel_image = "/opt/xcsoar/lib/kernel/uImage.aura2"; break; default: otg_kernel_image = "/opt/xcsoar/lib/kernel/uImage.otg"; kobo_kernel_image = "/opt/xcsoar/lib/kernel/uImage.kobo"; } const char *kernel_image = IsKoboOTGKernel() ? kobo_kernel_image : otg_kernel_image; if (!KoboInstallKernel(kernel_image)) { ShowMessageBox(_T("Failed to activate kernel."), _("Error"), MB_OK); return; } KoboReboot(); #endif }
inline void SystemWidget::SwitchKernel() { #ifdef KOBO if (DetectKoboModel() != KoboModel::MINI && ShowMessageBox(_T("This feature was designed for the Kobo Mini, but this is not one. Use at your own risk. Continue?"), _T("USB-OTG"), MB_YESNO) != IDYES) return; const char *otg_kernel_image = "/opt/xcsoar/lib/kernel/uImage.otg"; const char *kobo_kernel_image = "/opt/xcsoar/lib/kernel/uImage.kobo"; const char *kernel_image = IsKoboOTGKernel() ? kobo_kernel_image : otg_kernel_image; if (!KoboInstallKernel(kernel_image)) { ShowMessageBox(_T("Failed to activate kernel."), _("Error"), MB_OK); return; } KoboReboot(); #endif }
void TopCanvas::Create(PixelSize new_size, bool full_screen, bool resizable) { #ifdef USE_FB assert(fd < 0); #ifdef USE_TTY InitialiseTTY(); #endif const char *path = "/dev/fb0"; fd = open(path, O_RDWR | O_NOCTTY | O_CLOEXEC); if (fd < 0) { fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno)); return; } struct fb_fix_screeninfo finfo; if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) < 0) { fprintf(stderr, "FBIOGET_FSCREENINFO failed: %s\n", strerror(errno)); Destroy(); return; } if (finfo.type != FB_TYPE_PACKED_PIXELS) { fprintf(stderr, "Unsupported console hardware\n"); Destroy(); return; } switch (finfo.visual) { case FB_VISUAL_TRUECOLOR: case FB_VISUAL_PSEUDOCOLOR: case FB_VISUAL_STATIC_PSEUDOCOLOR: case FB_VISUAL_DIRECTCOLOR: break; default: fprintf(stderr, "Unsupported console hardware\n"); Destroy(); return; } /* Memory map the device, compensating for buggy PPC mmap() */ const off_t page_size = getpagesize(); off_t offset = off_t(finfo.smem_start) - (off_t(finfo.smem_start) &~ (page_size - 1)); off_t map_size = finfo.smem_len + offset; map = mmap(nullptr, map_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (map == (void *)-1) { fprintf(stderr, "Unable to memory map the video hardware: %s\n", strerror(errno)); map = nullptr; Destroy(); return; } /* Determine the current screen depth */ struct fb_var_screeninfo vinfo; if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) { fprintf(stderr, "Couldn't get console pixel format: %s\n", strerror(errno)); Destroy(); return; } #ifdef GREYSCALE /* switch the frame buffer to 8 bits per pixel greyscale */ vinfo.bits_per_pixel = 8; vinfo.grayscale = true; if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo) < 0) { fprintf(stderr, "Couldn't set greyscale pixel format: %s\n", strerror(errno)); Destroy(); return; } /* read new finfo */ ioctl(fd, FBIOGET_FSCREENINFO, &finfo); map_bpp = 1; #else map_bpp = vinfo.bits_per_pixel / 8; if (map_bpp != 2 && map_bpp != 4) { fprintf(stderr, "Unsupported console hardware\n"); Destroy(); return; } #endif map_pitch = finfo.line_length; epd_update_marker = 0; #ifdef KOBO int updateSheme = UPDATE_SCHEME_QUEUE_AND_MERGE; if(ioctl(fd, MXCFB_SET_UPDATE_SCHEME, &updateSheme) < 0) { fprintf(stderr, "Couldn't set update_scheme: %s\n", strerror(errno)); } KoboModel model = DetectKoboModel(); switch(model) { case KoboModel::UNKNOWN: frame_sync = true; break; case KoboModel::MINI: case KoboModel::TOUCH: case KoboModel::GLO: frame_sync = false; break; case KoboModel::GLOHD: frame_sync = true; break; default: frame_sync = true; break; }; #endif const unsigned width = vinfo.xres, height = vinfo.yres; #elif defined(USE_VFB) const unsigned width = new_size.cx, height = new_size.cy; #else #error No implementation #endif buffer.Allocate(width, height); }
void UpdateBatteryInfo() { // assume failure at entry Power::Battery::RemainingPercentValid = false; Power::Battery::Status = Power::Battery::UNKNOWN; Power::External::Status = Power::External::UNKNOWN; char line[256]; if (DetectKoboModel() == KoboModel::GLO_HD) { if (File::ReadString(Path("/sys/class/power_supply/mc13892_bat/status"), line, sizeof(line))) { if (StringIsEqual(line,"Not charging\n") || StringIsEqual(line,"Charging\n")) Power::External::Status = Power::External::ON; else if (StringIsEqual(line,"Discharging\n")) Power::External::Status = Power::External::OFF; } if (File::ReadString(Path("/sys/class/power_supply/mc13892_bat/capacity"), line, sizeof(line))) { int rem = atoi(line); Power::Battery::RemainingPercentValid = true; Power::Battery::RemainingPercent = rem; } } else { // code shamelessly copied from OS/SystemLoad.cpp if (!File::ReadString(Path("/sys/class/power_supply/mc13892_bat/uevent"), line, sizeof(line))) return; char field[80], value[80]; int n; char* ptr = line; while (sscanf(ptr, "%[^=]=%[^\n]\n%n", field, value, &n)==2) { ptr += n; if (StringIsEqual(field,"POWER_SUPPLY_STATUS")) { if (StringIsEqual(value,"Not charging") || StringIsEqual(value,"Charging")) { Power::External::Status = Power::External::ON; } else if (StringIsEqual(value,"Discharging")) { Power::External::Status = Power::External::OFF; } } else if (StringIsEqual(field,"POWER_SUPPLY_CAPACITY")) { int rem = atoi(value); Power::Battery::RemainingPercentValid = true; Power::Battery::RemainingPercent = rem; } } } if (Power::External::Status == Power::External::OFF) { if (Power::Battery::RemainingPercentValid) { if (Power::Battery::RemainingPercent>30) Power::Battery::Status = Power::Battery::HIGH; else if (Power::Battery::RemainingPercent>10) Power::Battery::Status = Power::Battery::LOW; else if (Power::Battery::RemainingPercent<10) Power::Battery::Status = Power::Battery::CRITICAL; } } else if (Power::External::Status == Power::External::ON) Power::Battery::Status = Power::Battery::CHARGING; }