diff --git a/lcdproc-0.5.2-imonlcd.patch b/lcdproc-0.5.2-imonlcd.patch new file mode 100644 index 0000000..2628aac --- /dev/null +++ b/lcdproc-0.5.2-imonlcd.patch @@ -0,0 +1,2859 @@ +diff -Naurp lcdproc-0.5.2/acinclude.m4 lcdproc-0.5.2.imonlcd/acinclude.m4 +--- lcdproc-0.5.2/acinclude.m4 2007-04-14 10:39:28.000000000 -0400 ++++ lcdproc-0.5.2.imonlcd/acinclude.m4 2008-11-07 10:31:38.374066457 -0500 +@@ -6,7 +6,7 @@ AC_ARG_ENABLE(drivers, + [ which is a comma-separated list of drivers.] + [ Possible drivers are:] + [ bayrad,CFontz,CFontz633,CFontzPacket,curses,CwLnx,ea65,] +- [ EyeboxOne,g15,glcdlib,glk,hd44780,icp_a106,imon,IOWarrior,] ++ [ EyeboxOne,g15,glcdlib,glk,hd44780,icp_a106,imon,imonlcd,imonlcd2,IOWarrior,] + [ irman,joy,lb216,lcdm001,lcterm,lirc,MD8800,ms6931,] + [ mtc_s16209x,MtxOrb,NoritakeVFD,picolcd,pyramid,sed1330] + [ sed1520,serialPOS,serialVFD,sli,stv5730,svga,t6963,text,] +@@ -16,7 +16,7 @@ AC_ARG_ENABLE(drivers, + drivers="$enableval", + drivers=[bayrad,CFontz,CFontz633,curses,CwLnx,glk,lb216,lcdm001,MtxOrb,pyramid,text]) + +-allDrivers=[bayrad,CFontz,CFontz633,CFontzPacket,curses,CwLnx,ea65,EyeboxOne,g15,glcdlib,glk,hd44780,icp_a106,imon,IOWarrior,irman,joy,lb216,lcdm001,lcterm,lirc,MD8800,ms6931,mtc_s16209x,MtxOrb,NoritakeVFD,picolcd,pyramid,sed1330,sed1520,serialPOS,serialVFD,sli,stv5730,svga,t6963,text,tyan,ula200,xosd] ++allDrivers=[bayrad,CFontz,CFontz633,CFontzPacket,curses,CwLnx,ea65,EyeboxOne,g15,glcdlib,glk,hd44780,icp_a106,imon,imonlcd,imonlcd2,IOWarrior,irman,joy,lb216,lcdm001,lcterm,lirc,MD8800,ms6931,mtc_s16209x,MtxOrb,NoritakeVFD,picolcd,pyramid,sed1330,sed1520,serialPOS,serialVFD,sli,stv5730,svga,t6963,text,tyan,ula200,xosd] + + drivers=`echo $drivers | sed -e 's/,/ /g'` + +@@ -207,6 +207,14 @@ dnl else + DRIVERS="$DRIVERS imon${SO}" + actdrivers=["$actdrivers imon"] + ;; ++ imonlcd) ++ DRIVERS="$DRIVERS imonlcd${SO}" ++ actdrivers=["$actdrivers imonlcd"] ++ ;; ++ imonlcd2) ++ DRIVERS="$DRIVERS imonlcd2${SO}" ++ actdrivers=["$actdrivers imonlcd2"] ++ ;; + IOWarrior) + if test "$enable_libusb" = yes ; then + DRIVERS="$DRIVERS IOWarrior${SO}" +diff -Naurp lcdproc-0.5.2/server/drivers/imonlcd2.c lcdproc-0.5.2.imonlcd/server/drivers/imonlcd2.c +--- lcdproc-0.5.2/server/drivers/imonlcd2.c 1969-12-31 19:00:00.000000000 -0500 ++++ lcdproc-0.5.2.imonlcd/server/drivers/imonlcd2.c 2008-11-07 10:39:57.741816312 -0500 +@@ -0,0 +1,1347 @@ ++/** ++ * Driver for SoundGraph iMON OEM (and others) LCD Module, newer version ++ * ++ * In order to be able to use it, you have to install the lirc_imon ++ * kernel module for LIRC (http://www.lirc.org) ++ * ++ * Copyright (c) 2007, Dean Harding , but (heavily :p) ++ * on the work of Venky Raju. ++ * Vastly (hopefully) improved by Christian Leuschen . ++ * ++ * This source code is being released under the GPL. ++ * Please see the file COPYING in this package for details. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef HAVE_CONFIG_H ++# include "config.h" ++#endif ++ ++#include "lcd.h" ++#include "lcd_lib.h" ++#include "shared/debug.h" ++//#define DEBUG ++#include "report.h" ++ ++ ++#include "imonlcd.h" ++ ++#define DEFAULT_DEVICE "/dev/lcd0" ++#define DEFAULT_SIZE "96x16" // This is the size in "pixels"... ++#define DEFAULT_CONTRAST "625" ++#define DEFAULT_BACKLIGHT "1" // default: turn backlight on ++#define DEFAULT_DISCMODE "0" // default: spin the "slim" disc ++ ++#define LCD_DEFAULT_CELL_WIDTH 6 ++#define LCD_DEFAULT_CELL_HEIGHT 8 ++ ++#define ON_EXIT_SHOWMSG 0 // Do nothing -- just leave the "shutdown" message there ++#define ON_EXIT_SHOWCLOCK 1 // Show the big clock ++#define ON_EXIT_BLANKSCREEN 2 // Blank the device completely ++ ++#define DEFAULT_ON_EXIT "1" ++ ++// Vars for the server core ++MODULE_EXPORT char *api_version = API_VERSION; ++MODULE_EXPORT int stay_in_foreground = 0; ++MODULE_EXPORT int supports_multiple = 0; ++MODULE_EXPORT char *symbol_prefix = "imonlcd_"; ++ ++// Our private data ++typedef struct { ++ char info[255]; ++ int imon_fd; ++ unsigned char *framebuf; ++ int height; ++ int width; ++ int cellwidth; ++ int cellheight; ++ int on_exit; ++ int contrast; // 0 = lowest contrast, 1000 = highest ++ int backlightOn; // stores the backlight state ++ int discMode; // 0 = two disc-segments spinning as default, ++ // 1 = their complement spinning ++ ++ /* ++ * Here we record the last "state" of the CD icon so that we can "animate" it. ++ */ ++ int last_cd_state; ++ time_t last_cd_state_change; ++ uint64_t last_icon_state; ++ int lastPrivateIconState; // remind the last state for setting the icons ++} PrivateData; ++ ++/** ++ * Just for convenience and to have the commands at one place. ++ */ ++#define COMMANDS_SET_ICONS (uint64_t) 0x0100000000000000 ++#define COMMANDS_SET_CONTRAST (uint64_t) 0x0300000000000000 ++#define COMMANDS_DISPLAY (uint64_t) 0x8800000000000000 ++#define COMMANDS_SHUTDOWN (uint64_t) 0x8800000000000008 ++#define COMMANDS_DISPLAY_ON (uint64_t) 0x8800000000000040 ++#define COMMANDS_CLEAR_ALARM (uint64_t) 0x8a00000000000000 ++#define COMMANDS_SET_LINES0 (uint64_t) 0x1000000000000000 ++#define COMMANDS_SET_LINES1 (uint64_t) 0x1100000000000000 ++#define COMMANDS_SET_LINES2 (uint64_t) 0x1200000000000000 ++ ++/* ++ * These are used with the imon_output function to determine which icons to turn on/off. Because we ++ * only get a 32-bit integer to play, some of the icons are grouped into "sets" from which you can ++ * only select to turn one on at a time. ++ */ ++#define IMON_OUTPUT_CD_MASK 0x00000001 ++#define IMON_OUTPUT_TOPROW_MASK 0x0000000E ++#define IMON_OUTPUT_SPEAKER_MASK 0x00000030 ++#define IMON_OUTPUT_SPDIF_MASK 0x00000040 ++#define IMON_OUTPUT_SRC_MASK 0x00000080 ++#define IMON_OUTPUT_FIT_MASK 0x00000100 ++#define IMON_OUTPUT_TV_MASK 0x00000200 ++#define IMON_OUTPUT_HDTV_MASK 0x00000400 ++#define IMON_OUTPUT_SCR1_MASK 0x00000800 ++#define IMON_OUTPUT_SCR2_MASK 0x00001000 ++#define IMON_OUTPUT_BRICONS_MASK 0x0000E000 ++#define IMON_OUTPUT_BMICONS_MASK 0x00070000 ++#define IMON_OUTPUT_BLICONS_MASK 0x00380000 ++#define IMON_OUTPUT_VOL_MASK 0x00400000 ++#define IMON_OUTPUT_TIME_MASK 0x00800000 ++#define IMON_OUTPUT_ALARM_MASK 0x01000000 ++#define IMON_OUTPUT_REC_MASK 0x02000000 ++#define IMON_OUTPUT_REP_MASK 0x04000000 ++#define IMON_OUTPUT_SFL_MASK 0x08000000 ++ ++#define IMON_OUTPUT_PBARS_MASK 0x10000000 ++#define IMON_OUTPUT_DISK_IN_MASK 0x20000000 ++ ++ ++#define IMON_ICON_ALL (uint64_t) 0x00FFFFFFFFFFFFFF ++//Byte 6 ++#define IMON_ICON_DISK_OFF (uint64_t) 0x7F7000FFFFFFFFFF ++#define IMON_ICON_DISK_ON (uint64_t) 0x0080FF0000000000 ++ ++#define IMON_ICON_DISK_IN (uint64_t) 0x0080000000000000 ++#define IMON_ICON_CD_IN (uint64_t) 0x00806B0000000000 ++#define IMON_ICON_DVD_IN (uint64_t) 0x0080550000000000 ++ ++// Byte 5 ++#define IMON_ICON_WMA2 ((uint64_t) 0x1 << 39) ++#define IMON_ICON_WAV ((uint64_t) 0x1 << 38) ++#define IMON_ICON_REP ((uint64_t) 0x1 << 37) ++#define IMON_ICON_SFL ((uint64_t) 0x1 << 36) ++#define IMON_ICON_ALARM ((uint64_t) 0x1 << 35) ++#define IMON_ICON_REC ((uint64_t) 0x1 << 34) ++#define IMON_ICON_VOL ((uint64_t) 0x1 << 33) ++#define IMON_ICON_TIME ((uint64_t) 0x1 << 32) ++// Byte 4 ++#define IMON_ICON_XVID ((uint64_t) 0x1 << 31) ++#define IMON_ICON_WMV ((uint64_t) 0x1 << 30) ++#define IMON_ICON_MPG2 ((uint64_t) 0x1 << 29) ++#define IMON_ICON_AC3 ((uint64_t) 0x1 << 28) ++#define IMON_ICON_DTS ((uint64_t) 0x1 << 27) ++#define IMON_ICON_WMA ((uint64_t) 0x1 << 26) ++#define IMON_ICON_MP3 ((uint64_t) 0x1 << 25) ++#define IMON_ICON_OGG ((uint64_t) 0x1 << 24) ++ ++//Byte 3 ++#define IMON_ICON_SRC ((uint64_t) 0x1 << 23) ++#define IMON_ICON_FIT ((uint64_t) 0x1 << 22) ++#define IMON_ICON_TV_2 ((uint64_t) 0x1 << 21) ++#define IMON_ICON_HDTV ((uint64_t) 0x1 << 20) ++#define IMON_ICON_SCR1 ((uint64_t) 0x1 << 19) ++#define IMON_ICON_SCR2 ((uint64_t) 0x1 << 18) ++#define IMON_ICON_MPG ((uint64_t) 0x1 << 17) ++#define IMON_ICON_DIVX ((uint64_t) 0x1 << 16) ++// Byte 2 ++#define IMON_SPKR_FC ((uint64_t) 0x1 << 15) ++#define IMON_SPKR_FR ((uint64_t) 0x1 << 14) ++#define IMON_SPKR_SL ((uint64_t) 0x1 << 13) ++#define IMON_SPKR_LFE ((uint64_t) 0x1 << 12) ++#define IMON_SPKR_SR ((uint64_t) 0x1 << 11) ++#define IMON_SPKR_RL ((uint64_t) 0x1 << 10) ++#define IMON_SPKR_SPDIF ((uint64_t) 0x1 << 9) ++#define IMON_SPKR_RR ((uint64_t) 0x1 << 8) ++// Byte 1 ++#define IMON_ICON_MUSIC ((uint64_t) 0x1 << 7) ++#define IMON_ICON_MOVIE ((uint64_t) 0x1 << 6) ++#define IMON_ICON_PHOTO ((uint64_t) 0x1 << 5) ++#define IMON_ICON_CD_DVD ((uint64_t) 0x1 << 4) ++#define IMON_ICON_TV ((uint64_t) 0x1 << 3) ++#define IMON_ICON_WEBCAST ((uint64_t) 0x1 << 2) ++#define IMON_ICON_NEWS ((uint64_t) 0x1 << 1) ++#define IMON_SPKR_FL ((uint64_t) 0x1) ++ ++/* ++ * The iMON LCD doesn't have a "text mode" -- everthing is pixel-based. So we need to define ++ * our own font, basically. This structure holds the definition of that font. The characters ++ * we define here are 6x8 pixels in size, each byte in the 'pixels' array represents one column ++ * of pixels. The most significant bit is the top row, the least significant bit is the bottom ++ * row. ++ */ ++typedef struct { ++ int ch; ++ char pixels[6]; ++} imon_font; ++ ++static imon_font font[] = { ++ { ' ', { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }, ++ { '!', { 0x0, 0x0, 0x0, 0xF6, 0x0, 0x0 } }, ++ { '"', { 0x0, 0x0, 0xE0, 0x0, 0xE0, 0x0 } }, ++ { '#', { 0x0, 0x28, 0xFE, 0x28, 0xFE, 0x28 } }, ++ { '$', { 0x0, 0x0, 0xE0, 0x20, 0x78, 0x0 } }, ++ { '%', { 0x0, 0xC4, 0xC8, 0x10, 0x26, 0x46 } }, ++ { '&', { 0x0, 0x6C, 0x92, 0x6A, 0x4, 0xA } }, ++ { '\'', { 0x0, 0x0, 0x0, 0xE0, 0x0, 0x0 } }, ++ { '(', { 0x0, 0x0, 0x38, 0x44, 0x82, 0x0 } }, ++ { ')', { 0x0, 0x0, 0x82, 0x44, 0x38, 0x0 } }, ++ { '*', { 0x0, 0x28, 0x10, 0x7C, 0x10, 0x28 } }, ++ { '+', { 0x0, 0x10, 0x10, 0x7C, 0x10, 0x10 } }, ++ { ',', { 0x0, 0x0, 0xA, 0xC, 0x0, 0x0 } }, ++ { '-', { 0x0, 0x10, 0x10, 0x10, 0x10, 0x10 } }, ++ { '.', { 0x0, 0x0, 0x6, 0x6, 0x0, 0x0 } }, ++ { '/', { 0x0, 0x4, 0x8, 0x10, 0x20, 0x40 } }, ++ { '0', { 0x0, 0x7C, 0x8A, 0x92, 0xA2, 0x7C } }, ++ { '1', { 0x0, 0x0, 0x42, 0xFE, 0x2, 0x0 } }, ++ { '2', { 0x0, 0x42, 0x86, 0x8A, 0x92, 0x62 } }, ++ { '3', { 0x0, 0x84, 0x82, 0xA2, 0xD2, 0x8C } }, ++ { '4', { 0x0, 0x18, 0x28, 0x48, 0xFE, 0x8 } }, ++ { '5', { 0x0, 0xE4, 0xA2, 0xA2, 0xA2, 0x9C } }, ++ { '6', { 0x0, 0x3C, 0x52, 0x92, 0x92, 0xC } }, ++ { '7', { 0x0, 0x80, 0x8E, 0x90, 0xA0, 0xC0 } }, ++ { '8', { 0x0, 0x6C, 0x92, 0x92, 0x92, 0x6C } }, ++ { '9', { 0x0, 0x60, 0x92, 0x92, 0x94, 0x78 } }, ++ { ':', { 0x0, 0x0, 0x6C, 0x6C, 0x0, 0x0 } }, ++ { ';', { 0x0, 0x0, 0x6A, 0x6C, 0x0, 0x0 } }, ++ { '<', { 0x0, 0x10, 0x28, 0x44, 0x82, 0x0 } }, ++ { '=', { 0x0, 0x28, 0x28, 0x28, 0x28, 0x28 } }, ++ { '>', { 0x0, 0x0, 0x82, 0x44, 0x28, 0x10 } }, ++ { '?', { 0x0, 0x40, 0x80, 0x8A, 0x90, 0x60 } }, ++ { '@', { 0x0, 0x7C, 0x82, 0xBA, 0x92, 0x72 } }, ++ { 'A', { 0x0, 0x7E, 0x90, 0x90, 0x90, 0x7E } }, ++ { 'B', { 0x0, 0xFE, 0x92, 0x92, 0x92, 0x6C } }, ++ { 'C', { 0x0, 0x7C, 0x82, 0x82, 0x82, 0x44 } }, ++ { 'D', { 0x0, 0xFE, 0x82, 0x82, 0x82, 0x7C } }, ++ { 'E', { 0x0, 0xFE, 0x92, 0x92, 0x92, 0x82 } }, ++ { 'F', { 0x0, 0xFE, 0x90, 0x90, 0x90, 0x80 } }, ++ { 'G', { 0x0, 0x7C, 0x82, 0x92, 0x92, 0x5E } }, ++ { 'H', { 0x0, 0xFE, 0x10, 0x10, 0x10, 0xFE } }, ++ { 'I', { 0x0, 0x0, 0x82, 0xFE, 0x82, 0x0 } }, ++ { 'J', { 0x0, 0x4, 0x2, 0x82, 0xFC, 0x80 } }, ++ { 'K', { 0x0, 0xFE, 0x10, 0x28, 0x44, 0x82 } }, ++ { 'L', { 0x0, 0xFE, 0x2, 0x2, 0x2, 0x2 } }, ++ { 'M', { 0x0, 0xFE, 0x40, 0x30, 0x40, 0xFE } }, ++ { 'N', { 0x0, 0xFE, 0x20, 0x10, 0x8, 0xFE } }, ++ { 'O', { 0x0, 0x7C, 0x82, 0x82, 0x82, 0x7C } }, ++ { 'P', { 0x0, 0xFE, 0x90, 0x90, 0x90, 0x60 } }, ++ { 'Q', { 0x0, 0x7C, 0x82, 0x8A, 0x84, 0x7A } }, ++ { 'R', { 0x0, 0xFE, 0x90, 0x98, 0x94, 0x62 } }, ++ { 'S', { 0x0, 0x62, 0x92, 0x92, 0x92, 0x8C } }, ++ { 'T', { 0x0, 0x80, 0x80, 0xFE, 0x80, 0x80 } }, ++ { 'U', { 0x0, 0xFC, 0x2, 0x2, 0x2, 0xFC } }, ++ { 'V', { 0x0, 0xF0, 0xC, 0x2, 0xC, 0xF0 } }, ++ { 'W', { 0x0, 0xFC, 0x2, 0xC, 0x2, 0xFC } }, ++ { 'X', { 0x0, 0xC6, 0x28, 0x10, 0x28, 0xC6 } }, ++ { 'Y', { 0x0, 0xE0, 0x10, 0xE, 0x10, 0xE0 } }, ++ { 'Z', { 0x0, 0x86, 0x8A, 0x92, 0xA2, 0xC2 } }, ++ { '[', { 0x0, 0x0, 0xFE, 0x82, 0x0, 0x0 } }, ++ { '\\', { 0x0, 0x40, 0x20, 0x10, 0x8, 0x4 } }, ++ { ']', { 0x0, 0x0, 0x82, 0xFE, 0x0, 0x0 } }, ++ { '^', { 0x0, 0x20, 0x40, 0x80, 0x40, 0x20 } }, ++ { '_', { 0x0, 0x2, 0x2, 0x2, 0x2, 0x2 } }, ++ { '`', { 0x0, 0x0, 0x0, 0xC0, 0x20, 0x0 } }, ++ { 'a', { 0x0, 0x4, 0x2A, 0x2A, 0x2A, 0x1E } }, ++ { 'b', { 0x0, 0xFE, 0x12, 0x22, 0x22, 0x1C } }, ++ { 'c', { 0x0, 0x1C, 0x22, 0x22, 0x22, 0x4 } }, ++ { 'd', { 0x0, 0x1C, 0x22, 0x22, 0x12, 0xFE } }, ++ { 'e', { 0x0, 0x1C, 0x2A, 0x2A, 0x2A, 0x18 } }, ++ { 'f', { 0x0, 0x10, 0x7E, 0x90, 0x80, 0x40 } }, ++ { 'g', { 0x0, 0x30, 0x4A, 0x4A, 0x4A, 0x7C } }, ++ { 'h', { 0x0, 0xFE, 0x10, 0x20, 0x20, 0x1E } }, ++ { 'i', { 0x0, 0x0, 0x22, 0xBE, 0x2, 0x0 } }, ++ { 'j', { 0x0, 0x4, 0x2, 0x22, 0xBC, 0x0 } }, ++ { 'k', { 0x0, 0x0, 0xFE, 0x8, 0x14, 0x22 } }, ++ { 'l', { 0x0, 0x0, 0x82, 0xFE, 0x2, 0x0 } }, ++ { 'm', { 0x0, 0x3E, 0x20, 0x18, 0x20, 0x1E } }, ++ { 'n', { 0x0, 0x3E, 0x10, 0x20, 0x20, 0x1E } }, ++ { 'o', { 0x0, 0x1C, 0x22, 0x22, 0x22, 0x1C } }, ++ { 'p', { 0x0, 0x3E, 0x28, 0x28, 0x28, 0x10 } }, ++ { 'q', { 0x0, 0x10, 0x28, 0x28, 0x18, 0x3E } }, ++ { 'r', { 0x0, 0x3E, 0x10, 0x20, 0x20, 0x10 } }, ++ { 's', { 0x0, 0x12, 0x2A, 0x2A, 0x2A, 0x4 } }, ++ { 't', { 0x0, 0x20, 0xFC, 0x22, 0x2, 0x4 } }, ++ { 'u', { 0x0, 0x3C, 0x2, 0x2, 0x4, 0x3E } }, ++ { 'v', { 0x0, 0x38, 0x4, 0x2, 0x4, 0x38 } }, ++ { 'w', { 0x0, 0x3C, 0x2, 0xC, 0x2, 0x3C } }, ++ { 'x', { 0x0, 0x22, 0x14, 0x8, 0x14, 0x22 } }, ++ { 'y', { 0x0, 0x30, 0xA, 0xA, 0xA, 0x3C } }, ++ { 'z', { 0x0, 0x22, 0x26, 0x2A, 0x32, 0x22 } }, ++ { '{', { 0x0, 0x0, 0x10, 0x6C, 0x82, 0x82 } }, ++ { '|', { 0x0, 0x0, 0x0, 0xFE, 0x0, 0x0 } }, ++ { '}', { 0x0, 0x82, 0x82, 0x6C, 0x10, 0x0 } }, ++ { '~', { 0x0, 0x20, 0x40, 0x20, 0x10, 0x20 } }, ++/* ++ { 'Ö', { 0x0, 0x1C, 0xA2, 0x22, 0xA2, 0x1C } }, ++ { 'Ä', { 0x0, 0x04, 0xAA, 0x2A, 0xAA, 0x1E } }, ++ { 'Ü', { 0x0, 0x3C, 0x82, 0x02, 0x84, 0x3E } }, ++ { 'ö', { 0x0, 0x1C, 0xA2, 0x22, 0xA2, 0x1C } }, ++ { 'ä', { 0x0, 0x04, 0xAA, 0x2A, 0xAA, 0x1E } }, ++ { 'ü', { 0x0, 0x3C, 0x82, 0x02, 0x84, 0x3E } }, ++ { 'ß', { 0x0, 0x7E, 0x80, 0xA8, 0xA8, 0x50 } }, ++*/ ++ /* TODO ++ * Add more characters here. The 'ch' member is an int so theoretically, you could ++ * specify UTF-32 code points as the ch. But then you'd have to translate the UTF-8 ++ * (or whatever) input to imonlcd_string to UTF-32, which doesn't sound like much fun... ++ */ ++ ++ /* Marks the end of the array, but also serves as the character that ++ * unknown inputs are mapped to (essentially, a "space") ++ */ ++ { '\0' } ++}; ++ ++/** ++ * This is the definition for a "big" font, which is a font that simply takes up twice as many pixels ++ * as the normal font. We only use it for drawing numbers. ++ */ ++typedef struct { ++ int ch; ++ unsigned short pixels[12]; ++} imon_bigfont; ++ ++/* TODO ++ * Some of these characters need a bit of tweaking... ++ */ ++static imon_bigfont bigfont[] = { ++ { '0', { 0x0000, 0x07E0, 0x1FF8, 0x3FFC, 0x7FFE, 0x4002, 0x4002, 0x4002, 0x3FFC, 0x3FFC, 0x1FF8, 0x07E0 } }, ++ { '1', { 0x0000, 0x0000, 0x0000, 0x4002, 0x7FFE, 0x7FFE, 0x7FFE, 0x7FFE, 0x0002, 0x0000, 0x0000, 0x0000 } }, ++ { '2', { 0x0000, 0x1806, 0x3C2C, 0x7C7C, 0x5C5C, 0x40DE, 0x7F9E, 0x7F8E, 0x3F0E, 0x1E0C, 0x0018, 0x0000 } }, ++ { '3', { 0x0000, 0x001C, 0x3C3C, 0x7C3E, 0x7C1A, 0x0080, 0x4182, 0x7FFE, 0x7FFE, 0x3E7C, 0x1C38, 0x0000 } }, ++ { '4', { 0x0000, 0x0030, 0x0050, 0x0190, 0x0610, 0x0002, 0x1FFE, 0x3FFE, 0x7FFE, 0x7FFE, 0x0012, 0x0002 } }, ++ { '5', { 0x0000, 0x0018, 0x7FBC, 0x793E, 0x3B1A, 0x3800, 0x3B02, 0x3BFE, 0x31FE, 0x61FC, 0x00F8, 0x0000 } }, ++ { '6', { 0x0000, 0x07E0, 0x1FF8, 0x3FFC, 0x7FFE, 0x4002, 0x0180, 0x5982, 0x7DFE, 0x3DFC, 0x18FC, 0x0078 } }, ++ { '7', { 0x0000, 0x0800, 0x7000, 0x3000, 0x703C, 0x787E, 0x79FE, 0x7BFC, 0x3E00, 0x3000, 0x6000, 0x0000 } }, ++ { '8', { 0x0000, 0x1C3C, 0x3E7E, 0x7FFE, 0x7FFE, 0x4182, 0x4182, 0x7FFE, 0x7FFE, 0x3E7E, 0x1C3C, 0x0000 } }, ++ { '9', { 0x0000, 0x1E18, 0x3F3C, 0x7FBE, 0x7F9A, 0x0180, 0x4002, 0x7FFE, 0x3FFC, 0x1FF8, 0x07E0, 0x0000 } }, ++ { ':', { 0x0000, 0x030C, 0x079E, 0x079E, 0x030C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 } }, ++ ++ /* Marks the end of the array, but also serves as the character that ++ * unknown inputs are mapped to (essentially, a "space") ++ */ ++ { '\0' } ++}; ++ ++static void send_data(uint64_t value, int fd); ++static void send_byte_data(unsigned char data[], int fd); ++static void set_screen(unsigned char *columns, int fd); ++static void draw_char(imon_font *font, char ch, int x, int y, unsigned char *columns); ++static void draw_bigchar(imon_bigfont *font, int ch, int x, int y, unsigned char *columns); ++static void draw_string(imon_font *font, char *string, int fd); ++static void setLineLength( int topLine, int botLine, int topProgress, int botProgress, int fd ); ++static void setBuiltinProgressBars( int topLine, int botLine, ++ int topProgress, int botProgress, int fd ); ++static int lengthToPixels( int length ); ++static void send_command_data( uint64_t commandData, int fd ); ++ ++/** ++ * Initialize the driver. ++ * \param drvthis Pointer to driver structure. ++ * \return Information of success (1) or failure (< 0). ++ */ ++MODULE_EXPORT int imonlcd_init (Driver *drvthis) ++{ ++ PrivateData *p = NULL; ++ ++ // Allocate, initialize and store private p ++ p = (PrivateData *) calloc(1, sizeof(PrivateData)); ++ if (p == NULL) { ++ debug(RPT_ERR, "%s: failed to allocate private data", drvthis->name); ++ return -1; ++ } ++ ++ if (drvthis->store_private_ptr(drvthis, p)) { ++ debug(RPT_ERR, "%s: failed to store private data pointer", drvthis->name); ++ return -1; ++ } ++ ++ char buf[256]; ++ p->imon_fd = -1; ++ p->width = 0; ++ p->height = 0; ++ p->cellwidth = LCD_DEFAULT_CELL_WIDTH; ++ p->cellheight = LCD_DEFAULT_CELL_HEIGHT; ++ p->last_cd_state = 0; ++ p->last_icon_state = 0x0; // no icons turned on at startup ++ p->lastPrivateIconState = 0x0; // no icons turned on at startup ++ p->discMode = 0; ++ ++ ++ /* Get settings from config file*/ ++ ++ /* Get device */ ++ strncpy(buf, drvthis->config_get_string(drvthis->name, "Device", 0, DEFAULT_DEVICE), sizeof(buf)); ++ buf[sizeof(buf)-1] = '\0'; ++ report(RPT_INFO, "%s: using Device %s", drvthis->name, buf); ++ ++ /* Open device for writing */ ++ if ((p->imon_fd = open(buf, O_WRONLY)) < 0) { ++ report(RPT_ERR, "%s: ERROR opening %s (%s).", drvthis->name, buf, strerror(errno)); ++ report(RPT_ERR, "%s: Did you load the iMON VFD kernel module?", drvthis->name); ++ report(RPT_ERR, "%s: More info in lcdproc/docs/README.imon", drvthis->name); ++ return -1; ++ } ++ ++ /* Get size settings*/ ++ strncpy(buf, drvthis->config_get_string(drvthis->name, "Size", 0, DEFAULT_SIZE), sizeof(buf)); ++ buf[sizeof(buf)-1] = '\0'; ++ if ((sscanf(buf , "%dx%d", &p->width, &p->height) != 2) ++ || (p->width <= 0) || (p->width > LCD_MAX_WIDTH) ++ || (p->height <= 0) || (p->height > LCD_MAX_HEIGHT)) { ++ report(RPT_WARNING, "%s: cannot read Size: %s; using default %s", ++ drvthis->name, buf, DEFAULT_SIZE); ++ sscanf(DEFAULT_SIZE , "%dx%d", &p->width, &p->height); ++ } ++ ++ /* Get the "on exit" setting so we know what to do when we shut the device down */ ++ strncpy(buf, drvthis->config_get_string(drvthis->name, "OnExit", 0, DEFAULT_ON_EXIT), sizeof(buf)); ++ buf[sizeof(buf)-1] = '\0'; ++ if ((sscanf(buf, "%d", &p->on_exit) != 1)) { ++ report(RPT_WARNING, "%s: cannot read OnExit: %s, using default %d", ++ drvthis->name, buf, DEFAULT_ON_EXIT); ++ sscanf(DEFAULT_ON_EXIT, "%d", &p->on_exit); ++ } ++ ++ /* Get the "contrast" setting */ ++ strncpy(buf, drvthis->config_get_string(drvthis->name, "Contrast", 0, DEFAULT_CONTRAST), sizeof(buf)); ++ buf[sizeof(buf)-1] = '\0'; ++ if ((sscanf(buf, "%d", &p->contrast) != 1)) { ++ report(RPT_WARNING, "%s: cannot read Contrast: %s, using default %d", ++ drvthis->name, buf, DEFAULT_CONTRAST); ++ sscanf(DEFAULT_CONTRAST, "%d", &p->contrast); ++ } ++ /* Get the "backlight" setting */ ++ strncpy(buf, drvthis->config_get_string(drvthis->name, "Backlight", 0, DEFAULT_BACKLIGHT), sizeof(buf)); ++ buf[sizeof(buf)-1] = '\0'; ++ if ((sscanf(buf, "%d", &p->backlightOn) != 1)) { ++ report(RPT_WARNING, "%s: cannot read Backlight: %s, using default %d", ++ drvthis->name, buf, DEFAULT_BACKLIGHT); ++ sscanf(DEFAULT_BACKLIGHT, "%d", &p->backlightOn); ++ } ++ /* Get the "disc-mode" setting */ ++ strncpy(buf, drvthis->config_get_string(drvthis->name, "DiscMode", 0, DEFAULT_DISCMODE), sizeof(buf)); ++ buf[sizeof(buf)-1] = '\0'; ++ if ((sscanf(buf, "%d", &p->discMode) != 1)) { ++ report(RPT_WARNING, "%s: cannot read DiscMode: %s, using default %d", ++ drvthis->name, buf, DEFAULT_DISCMODE); ++ sscanf(DEFAULT_DISCMODE, "%d", &p->discMode); ++ } ++ /* Make sure the frame buffer is there... */ ++ report(RPT_INFO, "%s: allocating %d bytes for framebuffer.", drvthis->name, p->width * (p->height / p->cellheight)); ++ p->framebuf = (unsigned char *) malloc(p->width * (p->height / p->cellheight)); ++ if (p->framebuf == NULL) { ++ report(RPT_ERR, "%s: unable to allocate framebuffer", drvthis->name); ++ return -1; ++ } ++ memset(p->framebuf, 0x00, p->width * (p->height / p->cellheight)); ++ ++ /* Send the "initialize" commands to the screen */ ++ /* TODO ++ * I still need to figure out what most of these do, and what should be "configurable"... ++ */ ++ if ( p->backlightOn ) ++ send_command_data( COMMANDS_DISPLAY_ON, p->imon_fd ); ++ else ++ send_command_data( COMMANDS_SHUTDOWN, p->imon_fd ); ++ send_command_data( COMMANDS_CLEAR_ALARM, p->imon_fd ); ++ imonlcd_set_contrast( drvthis, p->contrast ); ++ send_command_data( 0x0200000000000000, p->imon_fd ); // unknown ++ send_command_data( COMMANDS_SET_ICONS, p->imon_fd ); ++ send_command_data( COMMANDS_SET_LINES0, p->imon_fd ); // clear the progress-bars ++ send_command_data( COMMANDS_SET_LINES1, p->imon_fd ); // on top and bottom of the ++ send_command_data( COMMANDS_SET_LINES2, p->imon_fd ); // display ++ ++ report(RPT_DEBUG, "%s: init() done", drvthis->name); ++ ++ return 1; ++} ++ ++/** ++ * Close the driver (do necessary clean-up). ++ * \param drvthis Pointer to driver structure. ++ */ ++MODULE_EXPORT void imonlcd_close (Driver *drvthis) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ if (p != NULL) { ++ if (p->imon_fd >= 0) { ++ if (p->on_exit == ON_EXIT_SHOWMSG) { ++ // "show message" means "do nothing" -- the message is there already ++ report(RPT_INFO, "%s: closing, leaving \"goodbye\" message.", drvthis->name); ++ } else if (p->on_exit == ON_EXIT_BLANKSCREEN) { ++ // turning backlight off (confirmed for my Silverstone LCD) ++ // (as "cybrmage" at mediaportal pointed out, his LCD is an Antec built-in one ++ // and turns completely off with this command) ++ // TODO: Why does the backlight turn on again at reboot and/or shutdown ++ // just when the computer turns it's power off / reboots. ++ // Is it just my bios sending a reset to all USB-devices, is it ++ // the USB-kernel-code that's sending the reset?! ++ // Maybe gets solved with setting the alarm!? ++ report(RPT_INFO, "%s: closing, turning backlight off.", drvthis->name); ++ send_command_data( COMMANDS_SHUTDOWN, p->imon_fd ); ++ send_command_data( COMMANDS_CLEAR_ALARM, p->imon_fd ); ++ } else { ++ // by default, show the big clock. We need to set it to the current ++ // time, then it just keeps counting automatically. ++ report(RPT_INFO, "%s: closing, showing clock.", drvthis->name); ++ ++ time_t tt = time(NULL); ++ struct tm *t = localtime(&tt); ++ uint64_t data; ++ ++ data = ((uint64_t)0x50 << 56); ++ data += ((uint64_t)t->tm_sec << 48); ++ data += ((uint64_t)t->tm_min << 40); ++ data += ((uint64_t)t->tm_hour << 32); ++ data += ((uint64_t)t->tm_mday << 24); ++ data += ((uint64_t)t->tm_mon << 16); ++ data += (((uint64_t)t->tm_year) << 8); ++ data += 0x80; ++ send_command_data(data, p->imon_fd); ++ send_command_data( COMMANDS_CLEAR_ALARM, p->imon_fd ); ++ } ++ ++ close(p->imon_fd); ++ } ++ ++ if (p->framebuf != NULL) ++ free(p->framebuf); ++ p->framebuf = NULL; ++ ++ free(p); ++ } ++ drvthis->store_private_ptr(drvthis, NULL); ++} ++ ++ ++/** ++ * Provide some information about this driver. ++ * \param drvthis Pointer to driver structure. ++ * \return Constant string with information. ++ */ ++MODULE_EXPORT const char * imonlcd_get_info (Driver *drvthis) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ strcpy(p->info, "SoundGraph iMON OEM (and others) LCD driver"); ++ return p->info; ++} ++ ++ ++/** ++ * Clear the screen. ++ * \param drvthis Pointer to driver structure. ++ */ ++MODULE_EXPORT void imonlcd_clear (Driver *drvthis) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ memset(p->framebuf, 0, p->width * (p->height / 8)); ++} ++ ++ ++/** ++ * Flush data on screen to the LCD. ++ * \param drvthis Pointer to driver structure. ++ */ ++MODULE_EXPORT void imonlcd_flush (Driver *drvthis) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ set_screen(p->framebuf, p->imon_fd); ++} ++ ++ ++/** ++ * Print a string on the screen at position (x,y). ++ * The upper-left corner is (1,1), the lower-right corner is (p->width, p->height). ++ * \param drvthis Pointer to driver structure. ++ * \param x Horizontal character position (column). ++ * \param y Vertical character position (row). ++ * \param string String that gets written. ++ */ ++MODULE_EXPORT void imonlcd_string (Driver *drvthis, int x, int y, const char string[]) ++{ ++ int i; ++ ++ for (i = 0; string[i] != '\0'; i++) ++ imonlcd_chr(drvthis, x+i, y, string[i]); ++} ++ ++ ++/** ++ * Print a character on the screen at position (x,y). ++ * The upper-left corner is (1,1), the lower-right corner is (p->width/p->cellwidth, p->height/p->cellheight). ++ * \param drvthis Pointer to driver structure. ++ * \param x Horizontal character position (column). ++ * \param y Vertical character position (row). ++ * \param c Character that gets written. ++ */ ++MODULE_EXPORT void imonlcd_chr (Driver *drvthis, int x, int y, char ch) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ y--; x--; ++ ++ if ((x < 0) || (y < 0) || (x >= (p->width / p->cellwidth)) || (y >= (p->height / p->cellheight))) ++ return; ++ ++ draw_char(font, ch, x * p->cellwidth, y * p->cellheight, p->framebuf); ++} ++ ++/** ++ * Draw a vertical bar bottom-up. ++ * \param drvthis Pointer to driver structure. ++ * \param x Horizontal character position (column) of the starting point. ++ * \param y Vertical character position (row) of the starting point. ++ * \param len Number of characters that the bar is high at 100% ++ * \param promille Current height level of the bar in promille. ++ * \param options Options (currently unused). ++ */ ++MODULE_EXPORT void imonlcd_vbar (Driver *drvthis, int x, int y, int len, int promille, int options) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ if ((x < 0) || (y < 0) || (y > (p->width / p->cellwidth))) ++ return; ++ ++ // Pixels is the number of pixels we need to draw, vertically, based on the passed-in promille. ++ int pixels = (int) ( (double)( ( 2 * len * p->cellheight ) * ( (double)promille / 2000 ) ) ); ++ ++ x--; y--; ++ x *= p->cellwidth; ++ ++ int j, k; ++ unsigned char barChar; ++ ++ for ( j=0; j0 && k < 8; pixels-- ) ++ { ++ barChar = barChar | (1 << k); ++ k++; ++ } ++ p->framebuf[x+1 + ((y-j) * 96)] = barChar; ++ p->framebuf[x+2 + ((y-j) * 96)] = barChar; ++ p->framebuf[x+3 + ((y-j) * 96)] = barChar; ++ p->framebuf[x+4 + ((y-j) * 96)] = barChar; ++ p->framebuf[x+5 + ((y-j) * 96)] = barChar; ++ ++ } ++} ++ ++ ++/** ++ * Draw a horizontal bar to the right. ++ * \param drvthis Pointer to driver structure. ++ * \param x Horizontal character position (column) of the starting point. ++ * \param y Vertical character position (row) of the starting point. ++ * \param len Number of characters that the bar is long at 100% ++ * \param promille Current length level of the bar in promille (i.e. from 0 to 1000). ++ * \param options Options (currently unused). ++ */ ++MODULE_EXPORT void imonlcd_hbar (Driver *drvthis, int x, int y, int len, int promille, int options) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ if ((x < 0) || (y < 0) || (y > (p->height / p->cellheight))) ++ return; ++ ++ // Pixels is the number of pixels we need to draw, horizontally, based on the passed-in promille. ++ int pixels = (int) ( (double)( ( 2 * len * p->cellwidth ) * ( (double)promille / 2000 ) ) ); ++ ++ x--; y--; ++ x *= p->cellwidth; ++ ++ for (; pixels >= 0; pixels--) { ++ ++ if (x > (p->width * p->cellwidth)) ++ return; ++ ++ p->framebuf[x + (y * 96)] = 0x3C; ++ x++; ++ } ++} ++ ++/** ++ * Draws a "big" number at the specified x-coordinate. ++ * ++ * Normally, the number that is displayed is "meant" to be 3x4 characters, but because we have a bit ++ * more flexibility, I've drawn the numbers as just being 12x16 pixels. That means that while the ++ * client will pass x-values between 0 and 16, we need to scale it and make sure the numbers remain ++ * centered. ++ * ++ * \param drvthis A point of the the Driver structure. ++ * \param the x-coordinate to display the character at. ++ * \num The number to display ("10" is the colon) ++ */ ++MODULE_EXPORT void imonlcd_num (Driver *drvthis, int x, int num) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ // This isn't that great, and really it only works when your screen is 96 pixels wide and ++ // even then, it makes assumptions about the coordinates the client passes to us. However, ++ // it works for MythTV... and looks pretty cool, too :-) ++ // TODO: Check the number flashing with the colon with "lcdproc K". Done! Please anyone recheck with mythtv ++ if(num < 10) ++ x = 12 + (int)(((x - 1) * p->cellwidth) * 0.75); ++ else ++ x = 12 + (int)(((x - 1) * p->cellwidth) * 0.72); ++ ++ draw_bigchar(bigfont, (num >= 10 ? ':' : (num + '0')), x, 0, p->framebuf); ++} ++ ++/** ++ * Sets the "output state" for the device. We use this to control the icons around the outside the ++ * display. The bits in \c state correspond to the icons as follows: ++ * ++ * bit 0 : disc icon (0=off, 1='spin') , if Toprow==4, use CD-animation, else use "HDD-recording-animation" ++ * bit 1,2,3 : top row (0=none, 1=music, 2=movie, 3=photo, 4=CD/DVD, 5=TV, 6=Web, 7=News/Weather) ++ * bit 4,5 : 'speaker' icons (0=off, 1=L+R, 2=5.1ch, 3=7.1ch) ++ * bit 6 : S/PDIF icon ++ * bit 7 : 'SRC' ++ * bit 8 : 'FIT' ++ * bit 9 : 'TV' ++ * bit 10 : 'HDTV' ++ * bit 11 : 'SRC1' ++ * bit 12 : 'SRC2' ++ * bit 13,14,15: bottom-right icons (0=off, 1=MP3, 2=OGG, 3=WMA, 4=WAV) ++ * bit 16,17,18: bottom-middle icons (0=off, 1=MPG, 2=AC3, 3=DTS, 4=WMA) ++ * bit 19,20,21: bottom-left icons (0=off, 1=MPG, 2=DIVX, 3=XVID, 4=WMV) ++ * bit 22 : 'VOL' (volume) ++ * bit 23 : 'TIME' ++ * bit 24 : 'ALARM' ++ * bit 25 : 'REC' (recording) ++ * bit 26 : 'REP' (repeat) ++ * bit 27 : 'SFL' (shuffle) ++ * bit 28 : Abuse this for progress bars (if set to 1), lower bits represent ++ * the length (6 bits each: P|6xTP|6xTL|6xBL|6xBP with P = bit 28, ++ * TP=Top Progress, TL = Top Line, BL = Bottom Line, BP = Bottom Progress). ++ * If bit 28 is set to 1, lower bits are interpreted as ++ * lengths; otherwise setting the symbols as usual. ++ * 0 <= length <= 32, bars extend from left to right. ++ * length > 32, bars extend from right to left, length is counted ++ * from 32 up (i.e. 35 means a length of 3). ++ * ++ * Remember: There are two kinds of calls! ++ * With bit 28 set to 1: Set all bars (leaving the symbols as is), ++ * with bit 28 set to 0: Set the symbols (leaving the bars as is). ++ * Beware: TODO: May become a race condition, if both calls are executed ++ * before the display gets updated. Keep this in mind in your ++ * client-code. ++ * bit 29 : 'disc-in icon' - half ellipsoid under the disc symbols (0=off, 1=on) ++ */ ++ ++MODULE_EXPORT void imonlcd_output (Driver *drvthis, int state) ++{ ++ ++ PrivateData *p = drvthis->private_data; ++ uint64_t icon = 0x0; ++ ++ if ( state == -1 ) // the value for "on" in the lcdproc-protocol ++ { ++ icon = (uint64_t)IMON_ICON_ALL; ++ send_command_data( COMMANDS_SET_ICONS | icon, p->imon_fd); ++ p->lastPrivateIconState = state; ++ setLineLength( 32, 32, 32, 32, p->imon_fd ); ++ ++ return; ++ } ++ else if ( state == 0x0 ) // the value for "off" in the lcdproc-protocol ++ { ++ icon = (uint64_t)0x0;; ++ send_command_data( COMMANDS_SET_ICONS | icon, p->imon_fd); ++ p->lastPrivateIconState = state; ++ setLineLength( 0, 0, 0, 0, p->imon_fd ); ++ return; ++ } ++ // bit 28 : Abuse this for progress bars. See above for usage. ++ else if ( ( state & IMON_OUTPUT_PBARS_MASK ) != 0 && state > 0 ) ++ { ++ int topProgress = ( state & 63 ); // extract the bar-values ++ int topLine = ( state & (63<<6) ) >> 6; // for each bar separately ++ int botProgress = ( state & (63<<12) ) >> 12; ++ int botLine = ( state & (63<<18) ) >> 18; ++ ++ botProgress = botProgress > 32 ? -( botProgress - 32 ) : botProgress; ++ topProgress = topProgress > 32 ? -( topProgress - 32 ) : topProgress; ++ botLine = botLine > 32 ? -( botLine - 32 ) : botLine; ++ topLine = topLine > 32 ? -( topLine - 32 ) : topLine; ++ ++ setLineLength( topLine, botLine, topProgress, botProgress, p->imon_fd ); ++ ++ state = p->lastPrivateIconState; // continue and set all other icons as before ++ } ++ ++ // bit 0 : disc icon (0=off, 1='spin') ++ if ( ( state & IMON_OUTPUT_CD_MASK ) != 0 ) ++ { ++ switch( p->last_cd_state ) { ++ case 0: ++ p->last_cd_state = 1; ++ if ( p->discMode == 1 ) ++ icon |= ( (uint64_t)(255 - 128 - 8) << 40); // all on except top & bottom ++ else ++ icon |= ( (uint64_t)(128 | 8) << 40); // top & bottom on ++ break; ++ case 1: ++ p->last_cd_state = 2; ++ if ( p->discMode == 1 ) ++ icon |= ( (uint64_t)(255 - 16 - 1) << 40); //all on except top-right & bottom-left ++ else ++ icon |= ( (uint64_t)(1 | 16) << 40); // top-right & bottom-left on ++ break; ++ case 2: ++ p->last_cd_state = 3; ++ if ( p->discMode == 1 ) ++ icon |= ( (uint64_t)(255 - 32 - 2) << 40); // all on except right & left ++ else ++ icon |= ( (uint64_t)(32 | 2) << 40); // right & left on ++ break; ++ default: ++ p->last_cd_state = 0; ++ if ( p->discMode == 1 ) ++ icon |= ( (uint64_t)(255 - 64 - 4) << 40); // all on except top-left & bottom-right ++ else ++ icon |= ( (uint64_t)(4 | 64) << 40); // top-left & bottom-right on ++ break; ++ } ++ } ++ ++ // bit 1,2,3 : top row (0=none, 1=music, 2=movie, 3=photo, 4=CD/DVD, 5=TV, 6=Web, 7=News/Weather) ++ if ( ( ( state & IMON_OUTPUT_TOPROW_MASK ) != 0) ) ++ { ++ switch( ( ( state & IMON_OUTPUT_TOPROW_MASK ) >> 1 ) ) ++ { ++ case 1: ++ icon |= IMON_ICON_MUSIC; ++ break; ++ case 2: ++ icon |= IMON_ICON_MOVIE; ++ break; ++ case 3: ++ icon |= IMON_ICON_PHOTO; ++ break; ++ case 4: ++ icon |= IMON_ICON_CD_DVD; ++ break; ++ case 5: ++ icon |= IMON_ICON_TV; ++ break; ++ case 6: ++ icon |= IMON_ICON_WEBCAST; ++ break; ++ case 7: ++ icon |= IMON_ICON_NEWS; ++ break; ++ default: ++ break; ++ } ++ } ++ // bit 4,5 : 'speaker' icons (0=off, 1=L+R, 2=5.1ch, 3=7.1ch) ++ if ( ( ( state & IMON_OUTPUT_SPEAKER_MASK ) != 0) ) ++ { ++ switch( ( ( state & IMON_OUTPUT_SPEAKER_MASK ) >> 4 ) ) ++ { ++ case 1: ++ icon |= IMON_SPKR_FL | IMON_SPKR_FR; ++ break; ++ case 2: ++ icon |= IMON_SPKR_FL | IMON_SPKR_FC | IMON_SPKR_FR | IMON_SPKR_RL | IMON_SPKR_RR | IMON_SPKR_LFE; ++ break; ++ case 3: ++ icon |= IMON_SPKR_FL | IMON_SPKR_FC | IMON_SPKR_FR | IMON_SPKR_RL | IMON_SPKR_RR | IMON_SPKR_SL | IMON_SPKR_SR | IMON_SPKR_LFE; ++ break; ++ default: ++ break; ++ } ++ } ++ // bit 6 : S/PDIF icon ++ icon = ( ( state & IMON_OUTPUT_SPDIF_MASK ) != 0 ) ? (icon | IMON_SPKR_SPDIF) : (icon & ~IMON_SPKR_SPDIF); ++ // bit 7 : 'SRC' ++ icon = ( ( state & IMON_OUTPUT_SRC_MASK ) != 0 ) ? (icon | IMON_ICON_SRC) : (icon & ~IMON_ICON_SRC); ++ // bit 8 : 'FIT' ++ icon = ( ( state & IMON_OUTPUT_FIT_MASK ) != 0 ) ? (icon | IMON_ICON_FIT) : (icon & ~IMON_ICON_FIT); ++ // bit 9 : 'TV' ++ icon = ( ( state & IMON_OUTPUT_TV_MASK ) != 0 ) ? (icon | IMON_ICON_TV_2) : (icon & ~IMON_ICON_TV_2); ++ // bit 10 : 'HDTV' ++ icon = ( ( state & IMON_OUTPUT_HDTV_MASK ) != 0 ) ? (icon | IMON_ICON_HDTV) : (icon & ~IMON_ICON_HDTV); ++ // bit 11 : 'SRC1' ++ icon = ( ( state & IMON_OUTPUT_SCR1_MASK ) != 0 ) ? (icon | IMON_ICON_SCR1) : (icon & ~IMON_ICON_SCR1); ++ // bit 12 : 'SRC2' ++ icon = ( ( state & IMON_OUTPUT_SCR2_MASK ) != 0 ) ? (icon | IMON_ICON_SCR2) : (icon & ~IMON_ICON_SCR2); ++ // bit 13,14,15: bottom-right icons (0=off, 1=MP3, 2=OGG, 3=WMA, 4=WAV) ++ if ( ( ( state & IMON_OUTPUT_BRICONS_MASK ) != 0) ) ++ { ++ switch( ( ( state & IMON_OUTPUT_BRICONS_MASK ) >> 13 ) ) ++ { ++ case 1: ++ icon |= IMON_ICON_MP3; ++ break; ++ case 2: ++ icon |= IMON_ICON_OGG; ++ break; ++ case 3: ++ icon |= IMON_ICON_WMA2; ++ break; ++ case 4: ++ icon |= IMON_ICON_WAV; ++ break; ++ default: ++ break; ++ } ++ } ++ // bit 16,17,18: bottom-middle icons (0=off, 1=MPG, 2=AC3, 3=DTS, 4=WMA) ++ if ( ( ( state & IMON_OUTPUT_BMICONS_MASK ) != 0) ) ++ { ++ switch( ( ( state & IMON_OUTPUT_BMICONS_MASK ) >> 16 ) ) ++ { ++ case 1: ++ icon |= IMON_ICON_MPG2; ++ break; ++ case 2: ++ icon |= IMON_ICON_AC3; ++ break; ++ case 3: ++ icon |= IMON_ICON_DTS; ++ break; ++ case 4: ++ icon |= IMON_ICON_WMA; ++ break; ++ default: ++ break; ++ } ++ } ++ // bit 19,20,21: bottom-left icons (0=off, 1=MPG, 2=DIVX, 3=XVID, 4=WMV) ++ if ( ( ( state & IMON_OUTPUT_BLICONS_MASK ) != 0) ) ++ { ++ switch( ( ( state & IMON_OUTPUT_BLICONS_MASK ) >> 19 ) ) ++ { ++ case 1: ++ icon |= IMON_ICON_MPG; ++ break; ++ case 2: ++ icon |= IMON_ICON_DIVX; ++ break; ++ case 3: ++ icon |= IMON_ICON_XVID; ++ break; ++ case 4: ++ icon |= IMON_ICON_WMV; ++ break; ++ default: ++ break; ++ } ++ } ++ // bit 22 : 'VOL' (volume) ++ icon = ( ( state & IMON_OUTPUT_VOL_MASK ) != 0 ) ? (icon | IMON_ICON_VOL) : (icon & ~IMON_ICON_VOL); ++ // bit 23 : 'TIME' ++ icon = ( ( state & IMON_OUTPUT_TIME_MASK ) != 0 ) ? (icon | IMON_ICON_TIME) : (icon & ~IMON_ICON_TIME); ++ // bit 24 : 'ALARM' ++ icon = ( ( state & IMON_OUTPUT_ALARM_MASK ) != 0 ) ? (icon | IMON_ICON_ALARM) : (icon & ~IMON_ICON_ALARM); ++ // bit 25 : 'REC' (recording) ++ icon = ( ( state & IMON_OUTPUT_REC_MASK ) != 0 ) ? (icon | IMON_ICON_REC) : (icon & ~IMON_ICON_REC); ++ // bit 26 : 'REP' (repeat) ++ icon = ( ( state & IMON_OUTPUT_REP_MASK ) != 0 ) ? (icon | IMON_ICON_REP) : (icon & ~IMON_ICON_REP); ++ // bit 27 : 'SFL' (shuffle) ++ icon = ( ( state & IMON_OUTPUT_SFL_MASK ) != 0 ) ? (icon | IMON_ICON_SFL) : (icon & ~IMON_ICON_SFL); ++ // bit 29 : 'disc-in' ++ icon = ( ( state & IMON_OUTPUT_DISK_IN_MASK ) != 0 ) ? (icon | IMON_ICON_DISK_IN) : (icon & ~IMON_ICON_DISK_IN); ++ ++ p->last_icon_state = (uint64_t)icon; ++ p->lastPrivateIconState = state; ++ send_command_data( COMMANDS_SET_ICONS | p->last_icon_state, p->imon_fd); ++} ++ ++/** ++ * Return the display width in characters. ++ * \param drvthis Pointer to driver structure. ++ * \return Number of characters the display is wide. ++ */ ++MODULE_EXPORT int imonlcd_width (Driver *drvthis) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ return p->width/p->cellwidth; ++} ++ ++ ++/** ++ * Return the display height in characters. ++ * \param drvthis Pointer to driver structure. ++ * \return Number of characters the display is high. ++ */ ++MODULE_EXPORT int imonlcd_height (Driver *drvthis) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ return p->height/p->cellheight; ++} ++ ++ ++/** ++ * Return the width of a character in pixels. ++ * \param drvthis Pointer to driver structure. ++ * \return Number of pixel columns a character cell is wide. ++ */ ++MODULE_EXPORT int imonlcd_cellwidth (Driver *drvthis) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ return p->cellwidth; ++} ++ ++ ++/** ++ * Return the height of a character in pixels. ++ * \param drvthis Pointer to driver structure. ++ * \return Number of pixel lines a character cell is high. ++ */ ++MODULE_EXPORT int imonlcd_cellheight (Driver *drvthis) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ return p->cellheight; ++} ++ ++/** ++ * Sends data to the screen. The kernel module expects data to be ++ * sent in 8 byte chunks, so for simplicity, we allow you to define ++ * the data as a 64-bit integer. ++ * ++ * \param value The data to send. Must be in a format that is recognized ++ * by the device. The kernel module doesn't actually do ++ * validation. ++ * \param fd A file descriptor pointing to the /dev/lcd* file that we write to. ++ */ ++static void send_data(uint64_t value, int fd) ++{ ++ /* TODO ++ * In order to make big- and little-endian issues more clear, we should probably ++ * drop this method in favour of the send_byte_data method... ++ */ ++ ++ // Note: We do it like this so that we can be sure we work on big- and little- ++ // endian machines the same way. ++ unsigned char data[8]; ++ data[0] = (value & 0xFF00000000000000) >> (7 * 8); ++ data[1] = (value & 0x00FF000000000000) >> (6 * 8); ++ data[2] = (value & 0x0000FF0000000000) >> (5 * 8); ++ data[3] = (value & 0x000000FF00000000) >> (4 * 8); ++ data[4] = (value & 0x00000000FF000000) >> (3 * 8); ++ data[5] = (value & 0x0000000000FF0000) >> (2 * 8); ++ data[6] = (value & 0x000000000000FF00) >> (1 * 8); ++ data[7] = (value & 0x00000000000000FF); ++ ++ send_byte_data(data, fd); ++} ++ ++/** ++ * TODO: Check why exactly this has to be done ;-) and if this also works for ++ * 64-bit OSs. ++ * Sends data to the screen. The kernel module expects data to be ++ * sent in 8 byte chunks, so for simplicity, we allow you to define ++ * the data as a 64-bit integer. ++ * The bytes are reversed because all commands seem to need this to work! ++ * ++ * \param value The data to send. Must be in a format that is recognized ++ * by the device. The kernel module doesn't actually do ++ * validation. ++ * \param fd A file descriptor pointing to the /dev/lcd* file that we write to. ++ */ ++static void send_command_data( uint64_t commandData, int fd ) ++{ ++ if ((commandData & 0xFF00000000000000L) == 0x8800000000000000L) { ++ printf("%s: sending command: %lX\n", "imonlcd2", commandData); ++ } ++ ++ unsigned char data[8]; ++ data[7] = (unsigned char)((commandData >> 56) & 0xFF); ++ data[6] = (unsigned char)((commandData >> 48) & 0xFF); ++ data[5] = (unsigned char)((commandData >> 40) & 0xFF); ++ data[4] = (unsigned char)((commandData >> 32) & 0xFF); ++ data[3] = (unsigned char)((commandData >> 24) & 0xFF); ++ data[2] = (unsigned char)((commandData >> 16) & 0xFF); ++ data[1] = (unsigned char)((commandData >> 8) & 0xFF); ++ data[0] = (unsigned char)(commandData & 0xFF); ++ ++ send_byte_data(data, fd); ++ ++} ++ ++/** ++ * Sends data to the screen. ++ * ++ * \param data The 8 byte packet to send to the screen. ++ * \param fd A file descriptor pointing to the /dev/lcd* file that we write to. ++ */ ++static void send_byte_data(unsigned char data[], int fd) ++{ ++ write(fd, data, 8); ++} ++ ++/** ++ * Sets the contrast of the display. ++ * ++ * \param drvthis Pointer to driver structure. ++ * \param promille The value the contrast is set to in promille ++ * (0 = lowest contrast; 1000 = highest contrast). ++ * \return 0 on failure, >0 on success. ++ */ ++MODULE_EXPORT int imonlcd_set_contrast( Driver *drvthis, int promille ) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ if ( promille < 0) { ++ promille = 0; ++ } else if ( promille > 1000 ) { ++ promille = 1000; ++ } ++ ++ p->contrast = promille; ++ ++ // send contrast normalized to the hardware-understandable-value (0 to 40) ++ // 0 is the lowest (and usually the best, in my opinion) and 40 is the highest. TODO: @Dean: really 0=best?! ++ send_command_data(0x03FFFFFF00580A00L + (uint64_t)( p->contrast/25 ), p->imon_fd); ++ return 1; ++} ++ ++/** ++ * Gets the current contrast of the display. ++ * ++ * \param drvthis Pointer to driver structure. ++ * \return The current contrast in promille (0 = lowest contrast; ++ * 1000 = highest contrast). ++ */ ++MODULE_EXPORT int imonlcd_get_contrast( Driver *drvthis ) ++{ ++ PrivateData *p = drvthis->private_data; ++ return p->contrast; ++} ++ ++/** ++ * Sets the backlight state of the display. ++ * ++ * \param drvthis Pointer to driver structure. ++ * \param on The backlight state boolean-like: 0 = off; >0 = on. ++ */ ++MODULE_EXPORT void imonlcd_backlight(Driver *drvthis, int on) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ /* ++ * TODO: For some reason, lcdproc keeps calling this and flipping the ++ * 'on' so you end up flashing the backlight for no particular reason ++ * (and on my Antec, turning the backlight off, turns the whole thing ++ * off, so it's really bad...) ++ */ ++ return; ++ ++ // To prevent superfluous (and erroneous) communication ++ if ( p->backlightOn == on ) ++ return; ++ else ++ p->backlightOn = on; ++ ++ if ( on ) ++ { ++ send_command_data( COMMANDS_DISPLAY_ON, p->imon_fd ); ++ } ++ else ++ { ++ send_command_data( COMMANDS_SHUTDOWN, p->imon_fd ); ++ } ++} ++ ++/** ++ * Sets the pixels on the screen, using the specified "columns". ++ * Each column is eight pixels high (and represented by one byte) ++ * and the columns are filled from left to right. When the end ++ * of the screen is hit, the columns wrap to the next line. Each ++ * line is 96 pixels wide, so you need to pass an array of 192 ++ * bytes. ++ * ++ * \param columns The data for each column. ++ * \param fd A file descriptor pointing to the /dev/lcd* file that we write to. ++ */ ++static void set_screen(unsigned char *columns, int fd) ++{ ++ /* TODO ++ * This could be implemented as a single call to write() with all the data, ++ * but that would require corresponding changes to the lirc kernel module. ++ */ ++ int i; ++ uint64_t msb; ++ uint64_t data; ++ int byteno; ++ ++ i = 0; ++ for (msb = 0x20; msb <= 0x3b; msb++) { ++ data = 0; ++ for (byteno = 1; byteno < 8; byteno ++) { ++ data |= columns[i]; ++ data <<= 8; ++ i++; ++ } ++ data |= msb; ++ send_data(data, fd); ++ } ++} ++ ++/** ++ * Draws a "big" character -- that is, one that's twice as big as a normal character -- at ++ * the specified position on the screen. ++ */ ++static void draw_bigchar(imon_bigfont *font, int ch, int x, int y, unsigned char *columns) ++{ ++ imon_bigfont *defn = font; ++ int i; ++ ++ while (defn->ch != ch && defn->ch != '\0') { ++ defn++; ++ } ++ ++ int colBorder = 12; // correction for the number flashing with the colon running "lcdproc K" ++ if ( ch == ':' ) // TODO: Please check anybody with mythtv ++ colBorder = 6; ++ for(i = 0; i < colBorder; i++) { ++ columns[x + i + (y * colBorder)] = (defn->pixels[i] & 0xFF00) >> 8; ++ } ++ for(i = 0; i < colBorder; i++) { ++ columns[x + i + (y * colBorder) + 96] = (defn->pixels[i] & 0x00FF); ++ } ++} ++ ++/** ++ * Draws a single character at the specified (x,y) coordinates of the given screen data. ++ */ ++static void draw_char(imon_font *font, char ch, int x, int y, unsigned char *columns) ++{ ++ imon_font *defn = font; ++ int i; ++ ++ while (defn->ch != ch && defn->ch != '\0') { ++ defn++; ++ } ++ ++ for(i = 0; i < 6; i++) { ++ columns[x + i + (y * 12)] = defn->pixels[i]; ++ } ++} ++ ++/** ++ * Sets the length of the built-in progress-bars and lines. ++ * Values from -32 to 32 are allowed. Positive values indicate that bars extend ++ * from left to right, negative values indicate that the run from right to left. ++ * Conventient method to simplify setting the bars with "human understandable ++ * values". ++ * ++ * \see setBuiltinProgressBars, lengthToPixels ++ * ++ * \param topLine ++ * \param botLine ++ * \param topProgress ++ * \param botProgress ++ * \param fd A file descriptor pointing to the /dev/lcd* file that we write to. ++ */ ++static void setLineLength( int topLine, int botLine, int topProgress, int botProgress, int fd ) ++{ ++ setBuiltinProgressBars( lengthToPixels( topLine ), ++ lengthToPixels( botLine ), ++ lengthToPixels( topProgress ), ++ lengthToPixels( botProgress ), ++ fd ++ ); ++} ++ ++/** ++ * Sets the length of the built-in progress-bars and lines. ++ * Values from -32 to 32 are allowed. Positive values indicate that bars extend ++ * from left to right, negative values indicate that the run from right to left. ++ * ++ * \param topLine ++ * \param botLine ++ * \param topProgress ++ * \param botProgress ++ * \param fd A file descriptor pointing to the /dev/lcd* file that we write to. ++ */ ++static void setBuiltinProgressBars( int topLine, int botLine, ++ int topProgress, int botProgress, int fd ) ++{ ++ // Least sig. bit is on the right ++ uint64_t data; ++ ++ data = ( (uint64_t) topProgress ) << 8 * 4; ++ data |= (uint64_t) topLine & 0x00000000FFFFFFFF; ++ data &= 0x00FFFFFFFFFFFFFF; ++ send_command_data( COMMANDS_SET_LINES0 | data, fd ); ++ ++ data = ( ( (uint64_t) topProgress ) >> 8 * 3 ) & 0x00000000000000FF; ++ data |= ( ( (uint64_t) botProgress ) << 8 ) & 0x000000FFFFFFFF00; ++ data |= ( ( (uint64_t) botLine ) << 8 * 5 ) & 0x00FFFF0000000000; ++ send_command_data( COMMANDS_SET_LINES1 | data, fd ); ++ ++ data = ( (uint64_t) botLine ) >> 8 * 2; ++ send_command_data( COMMANDS_SET_LINES2 | data, fd ); ++} ++ ++/** ++ * Maps values to corresponding pixmaps for the built-in progress bars. ++ * Values from -32 to 32 are allowed. Positive values indicate that bars extend ++ * from left to right, negative values indicate that they run from right to left. ++ * ++ * \param length The length of the bar. ++ * \return The pixmap that represents the given length. ++ * ++ */ ++static int lengthToPixels( int length ) ++{ ++ int pixLen[] = ++ { ++ 0x00, 0x00000080, 0x000000c0, 0x000000e0, 0x000000f0, ++ 0x000000f8, 0x000000fc, 0x000000fe, 0x000000ff, ++ 0x000080ff, 0x0000c0ff, 0x0000e0ff, 0x0000f0ff, ++ 0x0000f8ff, 0x0000fcff, 0x0000feff, 0x0000ffff, ++ 0x0080ffff, 0x00c0ffff, 0x00e0ffff, 0x00f0ffff, ++ 0x00f8ffff, 0x00fcffff, 0x00feffff, 0x00ffffff, ++ 0x80ffffff, 0xc0ffffff, 0xe0ffffff, 0xf0ffffff, ++ 0xf8ffffff, 0xfcffffff, 0xfeffffff, 0xffffffff ++ }; ++ ++ if ( abs( length ) > 32 ) ++ { ++ return (0); ++ } ++ if ( length >= 0 ) ++ { ++ return pixLen[ length ]; ++ } ++ else ++ { ++ return ( pixLen[ 32 + length ] ^ 0xffffffff ); ++ } ++} ++ ++// EOF ++ +diff -Naurp lcdproc-0.5.2/server/drivers/imonlcd.c lcdproc-0.5.2.imonlcd/server/drivers/imonlcd.c +--- lcdproc-0.5.2/server/drivers/imonlcd.c 1969-12-31 19:00:00.000000000 -0500 ++++ lcdproc-0.5.2.imonlcd/server/drivers/imonlcd.c 2008-11-07 10:30:16.285849399 -0500 +@@ -0,0 +1,1349 @@ ++/** ++ * Driver for SoundGraph iMON OEM (and others) LCD Module ++ * ++ * In order to be able to use it, you have to install the lirc_imonlcd ++ * kernel module for LIRC (http://www.lirc.org) -- until that module is ++ * available in the main LIRC branch, you can get a patch for it from ++ * the same place you got this patch. ++ * ++ * Copyright (c) 2007, Dean Harding , but (heavily :p) ++ * on the work of Venky Raju. ++ * Vastly (hopefully) improved by Christian Leuschen . ++ * ++ * This source code is being released under the GPL. ++ * Please see the file COPYING in this package for details. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef HAVE_CONFIG_H ++# include "config.h" ++#endif ++ ++#include "lcd.h" ++#include "lcd_lib.h" ++#include "shared/debug.h" ++//#define DEBUG ++#include "report.h" ++ ++ ++#include "imonlcd.h" ++ ++#define DEFAULT_DEVICE "/dev/lcd0" ++#define DEFAULT_SIZE "96x16" // This is the size in "pixels"... ++#define DEFAULT_CONTRAST "625" ++#define DEFAULT_BACKLIGHT "1" // default: turn backlight on ++#define DEFAULT_DISCMODE "0" // default: spin the "slim" disc ++ ++#define LCD_DEFAULT_CELL_WIDTH 6 ++#define LCD_DEFAULT_CELL_HEIGHT 8 ++ ++#define ON_EXIT_SHOWMSG 0 // Do nothing -- just leave the "shutdown" message there ++#define ON_EXIT_SHOWCLOCK 1 // Show the big clock ++#define ON_EXIT_BLANKSCREEN 2 // Blank the device completely ++ ++#define DEFAULT_ON_EXIT "1" ++ ++// Vars for the server core ++MODULE_EXPORT char *api_version = API_VERSION; ++MODULE_EXPORT int stay_in_foreground = 0; ++MODULE_EXPORT int supports_multiple = 0; ++MODULE_EXPORT char *symbol_prefix = "imonlcd_"; ++ ++// Our private data ++typedef struct { ++ char info[255]; ++ int imon_fd; ++ unsigned char *framebuf; ++ int height; ++ int width; ++ int cellwidth; ++ int cellheight; ++ int on_exit; ++ int contrast; // 0 = lowest contrast, 1000 = highest ++ int backlightOn; // stores the backlight state ++ int discMode; // 0 = two disc-segments spinning as default, ++ // 1 = their complement spinning ++ ++ /* ++ * Here we record the last "state" of the CD icon so that we can "animate" it. ++ */ ++ int last_cd_state; ++ time_t last_cd_state_change; ++ uint64_t last_icon_state; ++ int lastPrivateIconState; // remind the last state for setting the icons ++} PrivateData; ++ ++/** ++ * Just for convenience and to have the commands at one place. ++ */ ++#define COMMANDS_SET_ICONS (uint64_t) 0x0100000000000000 ++#define COMMANDS_SET_CONTRAST (uint64_t) 0x0300000000000000 ++#define COMMANDS_DISPLAY (uint64_t) 0x5000000000000000 ++#define COMMANDS_SHUTDOWN (uint64_t) 0x5000000000000008 ++#define COMMANDS_DISPLAY_ON (uint64_t) 0x5000000000000040 ++#define COMMANDS_CLEAR_ALARM (uint64_t) 0x5100000000000000 ++#define COMMANDS_SET_LINES0 (uint64_t) 0x1000000000000000 ++#define COMMANDS_SET_LINES1 (uint64_t) 0x1100000000000000 ++#define COMMANDS_SET_LINES2 (uint64_t) 0x1200000000000000 ++ ++/* ++ * These are used with the imon_output function to determine which icons to turn on/off. Because we ++ * only get a 32-bit integer to play, some of the icons are grouped into "sets" from which you can ++ * only select to turn one on at a time. ++ */ ++#define IMON_OUTPUT_CD_MASK 0x00000001 ++#define IMON_OUTPUT_TOPROW_MASK 0x0000000E ++#define IMON_OUTPUT_SPEAKER_MASK 0x00000030 ++#define IMON_OUTPUT_SPDIF_MASK 0x00000040 ++#define IMON_OUTPUT_SRC_MASK 0x00000080 ++#define IMON_OUTPUT_FIT_MASK 0x00000100 ++#define IMON_OUTPUT_TV_MASK 0x00000200 ++#define IMON_OUTPUT_HDTV_MASK 0x00000400 ++#define IMON_OUTPUT_SCR1_MASK 0x00000800 ++#define IMON_OUTPUT_SCR2_MASK 0x00001000 ++#define IMON_OUTPUT_BRICONS_MASK 0x0000E000 ++#define IMON_OUTPUT_BMICONS_MASK 0x00070000 ++#define IMON_OUTPUT_BLICONS_MASK 0x00380000 ++#define IMON_OUTPUT_VOL_MASK 0x00400000 ++#define IMON_OUTPUT_TIME_MASK 0x00800000 ++#define IMON_OUTPUT_ALARM_MASK 0x01000000 ++#define IMON_OUTPUT_REC_MASK 0x02000000 ++#define IMON_OUTPUT_REP_MASK 0x04000000 ++#define IMON_OUTPUT_SFL_MASK 0x08000000 ++ ++#define IMON_OUTPUT_PBARS_MASK 0x10000000 ++#define IMON_OUTPUT_DISK_IN_MASK 0x20000000 ++ ++ ++#define IMON_ICON_ALL (uint64_t) 0x00FFFFFFFFFFFFFF ++//Byte 6 ++#define IMON_ICON_DISK_OFF (uint64_t) 0x7F7000FFFFFFFFFF ++#define IMON_ICON_DISK_ON (uint64_t) 0x0080FF0000000000 ++ ++#define IMON_ICON_DISK_IN (uint64_t) 0x0080000000000000 ++#define IMON_ICON_CD_IN (uint64_t) 0x00806B0000000000 ++#define IMON_ICON_DVD_IN (uint64_t) 0x0080550000000000 ++ ++// Byte 5 ++#define IMON_ICON_WMA2 ((uint64_t) 0x1 << 39) ++#define IMON_ICON_WAV ((uint64_t) 0x1 << 38) ++#define IMON_ICON_REP ((uint64_t) 0x1 << 37) ++#define IMON_ICON_SFL ((uint64_t) 0x1 << 36) ++#define IMON_ICON_ALARM ((uint64_t) 0x1 << 35) ++#define IMON_ICON_REC ((uint64_t) 0x1 << 34) ++#define IMON_ICON_VOL ((uint64_t) 0x1 << 33) ++#define IMON_ICON_TIME ((uint64_t) 0x1 << 32) ++// Byte 4 ++#define IMON_ICON_XVID ((uint64_t) 0x1 << 31) ++#define IMON_ICON_WMV ((uint64_t) 0x1 << 30) ++#define IMON_ICON_MPG2 ((uint64_t) 0x1 << 29) ++#define IMON_ICON_AC3 ((uint64_t) 0x1 << 28) ++#define IMON_ICON_DTS ((uint64_t) 0x1 << 27) ++#define IMON_ICON_WMA ((uint64_t) 0x1 << 26) ++#define IMON_ICON_MP3 ((uint64_t) 0x1 << 25) ++#define IMON_ICON_OGG ((uint64_t) 0x1 << 24) ++ ++//Byte 3 ++#define IMON_ICON_SRC ((uint64_t) 0x1 << 23) ++#define IMON_ICON_FIT ((uint64_t) 0x1 << 22) ++#define IMON_ICON_TV_2 ((uint64_t) 0x1 << 21) ++#define IMON_ICON_HDTV ((uint64_t) 0x1 << 20) ++#define IMON_ICON_SCR1 ((uint64_t) 0x1 << 19) ++#define IMON_ICON_SCR2 ((uint64_t) 0x1 << 18) ++#define IMON_ICON_MPG ((uint64_t) 0x1 << 17) ++#define IMON_ICON_DIVX ((uint64_t) 0x1 << 16) ++// Byte 2 ++#define IMON_SPKR_FC ((uint64_t) 0x1 << 15) ++#define IMON_SPKR_FR ((uint64_t) 0x1 << 14) ++#define IMON_SPKR_SL ((uint64_t) 0x1 << 13) ++#define IMON_SPKR_LFE ((uint64_t) 0x1 << 12) ++#define IMON_SPKR_SR ((uint64_t) 0x1 << 11) ++#define IMON_SPKR_RL ((uint64_t) 0x1 << 10) ++#define IMON_SPKR_SPDIF ((uint64_t) 0x1 << 9) ++#define IMON_SPKR_RR ((uint64_t) 0x1 << 8) ++// Byte 1 ++#define IMON_ICON_MUSIC ((uint64_t) 0x1 << 7) ++#define IMON_ICON_MOVIE ((uint64_t) 0x1 << 6) ++#define IMON_ICON_PHOTO ((uint64_t) 0x1 << 5) ++#define IMON_ICON_CD_DVD ((uint64_t) 0x1 << 4) ++#define IMON_ICON_TV ((uint64_t) 0x1 << 3) ++#define IMON_ICON_WEBCAST ((uint64_t) 0x1 << 2) ++#define IMON_ICON_NEWS ((uint64_t) 0x1 << 1) ++#define IMON_SPKR_FL ((uint64_t) 0x1) ++ ++/* ++ * The iMON LCD doesn't have a "text mode" -- everthing is pixel-based. So we need to define ++ * our own font, basically. This structure holds the definition of that font. The characters ++ * we define here are 6x8 pixels in size, each byte in the 'pixels' array represents one column ++ * of pixels. The most significant bit is the top row, the least significant bit is the bottom ++ * row. ++ */ ++typedef struct { ++ int ch; ++ char pixels[6]; ++} imon_font; ++ ++static imon_font font[] = { ++ { ' ', { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }, ++ { '!', { 0x0, 0x0, 0x0, 0xF6, 0x0, 0x0 } }, ++ { '"', { 0x0, 0x0, 0xE0, 0x0, 0xE0, 0x0 } }, ++ { '#', { 0x0, 0x28, 0xFE, 0x28, 0xFE, 0x28 } }, ++ { '$', { 0x0, 0x0, 0xE0, 0x20, 0x78, 0x0 } }, ++ { '%', { 0x0, 0xC4, 0xC8, 0x10, 0x26, 0x46 } }, ++ { '&', { 0x0, 0x6C, 0x92, 0x6A, 0x4, 0xA } }, ++ { '\'', { 0x0, 0x0, 0x0, 0xE0, 0x0, 0x0 } }, ++ { '(', { 0x0, 0x0, 0x38, 0x44, 0x82, 0x0 } }, ++ { ')', { 0x0, 0x0, 0x82, 0x44, 0x38, 0x0 } }, ++ { '*', { 0x0, 0x28, 0x10, 0x7C, 0x10, 0x28 } }, ++ { '+', { 0x0, 0x10, 0x10, 0x7C, 0x10, 0x10 } }, ++ { ',', { 0x0, 0x0, 0xA, 0xC, 0x0, 0x0 } }, ++ { '-', { 0x0, 0x10, 0x10, 0x10, 0x10, 0x10 } }, ++ { '.', { 0x0, 0x0, 0x6, 0x6, 0x0, 0x0 } }, ++ { '/', { 0x0, 0x4, 0x8, 0x10, 0x20, 0x40 } }, ++ { '0', { 0x0, 0x7C, 0x8A, 0x92, 0xA2, 0x7C } }, ++ { '1', { 0x0, 0x0, 0x42, 0xFE, 0x2, 0x0 } }, ++ { '2', { 0x0, 0x42, 0x86, 0x8A, 0x92, 0x62 } }, ++ { '3', { 0x0, 0x84, 0x82, 0xA2, 0xD2, 0x8C } }, ++ { '4', { 0x0, 0x18, 0x28, 0x48, 0xFE, 0x8 } }, ++ { '5', { 0x0, 0xE4, 0xA2, 0xA2, 0xA2, 0x9C } }, ++ { '6', { 0x0, 0x3C, 0x52, 0x92, 0x92, 0xC } }, ++ { '7', { 0x0, 0x80, 0x8E, 0x90, 0xA0, 0xC0 } }, ++ { '8', { 0x0, 0x6C, 0x92, 0x92, 0x92, 0x6C } }, ++ { '9', { 0x0, 0x60, 0x92, 0x92, 0x94, 0x78 } }, ++ { ':', { 0x0, 0x0, 0x6C, 0x6C, 0x0, 0x0 } }, ++ { ';', { 0x0, 0x0, 0x6A, 0x6C, 0x0, 0x0 } }, ++ { '<', { 0x0, 0x10, 0x28, 0x44, 0x82, 0x0 } }, ++ { '=', { 0x0, 0x28, 0x28, 0x28, 0x28, 0x28 } }, ++ { '>', { 0x0, 0x0, 0x82, 0x44, 0x28, 0x10 } }, ++ { '?', { 0x0, 0x40, 0x80, 0x8A, 0x90, 0x60 } }, ++ { '@', { 0x0, 0x7C, 0x82, 0xBA, 0x92, 0x72 } }, ++ { 'A', { 0x0, 0x7E, 0x90, 0x90, 0x90, 0x7E } }, ++ { 'B', { 0x0, 0xFE, 0x92, 0x92, 0x92, 0x6C } }, ++ { 'C', { 0x0, 0x7C, 0x82, 0x82, 0x82, 0x44 } }, ++ { 'D', { 0x0, 0xFE, 0x82, 0x82, 0x82, 0x7C } }, ++ { 'E', { 0x0, 0xFE, 0x92, 0x92, 0x92, 0x82 } }, ++ { 'F', { 0x0, 0xFE, 0x90, 0x90, 0x90, 0x80 } }, ++ { 'G', { 0x0, 0x7C, 0x82, 0x92, 0x92, 0x5E } }, ++ { 'H', { 0x0, 0xFE, 0x10, 0x10, 0x10, 0xFE } }, ++ { 'I', { 0x0, 0x0, 0x82, 0xFE, 0x82, 0x0 } }, ++ { 'J', { 0x0, 0x4, 0x2, 0x82, 0xFC, 0x80 } }, ++ { 'K', { 0x0, 0xFE, 0x10, 0x28, 0x44, 0x82 } }, ++ { 'L', { 0x0, 0xFE, 0x2, 0x2, 0x2, 0x2 } }, ++ { 'M', { 0x0, 0xFE, 0x40, 0x30, 0x40, 0xFE } }, ++ { 'N', { 0x0, 0xFE, 0x20, 0x10, 0x8, 0xFE } }, ++ { 'O', { 0x0, 0x7C, 0x82, 0x82, 0x82, 0x7C } }, ++ { 'P', { 0x0, 0xFE, 0x90, 0x90, 0x90, 0x60 } }, ++ { 'Q', { 0x0, 0x7C, 0x82, 0x8A, 0x84, 0x7A } }, ++ { 'R', { 0x0, 0xFE, 0x90, 0x98, 0x94, 0x62 } }, ++ { 'S', { 0x0, 0x62, 0x92, 0x92, 0x92, 0x8C } }, ++ { 'T', { 0x0, 0x80, 0x80, 0xFE, 0x80, 0x80 } }, ++ { 'U', { 0x0, 0xFC, 0x2, 0x2, 0x2, 0xFC } }, ++ { 'V', { 0x0, 0xF0, 0xC, 0x2, 0xC, 0xF0 } }, ++ { 'W', { 0x0, 0xFC, 0x2, 0xC, 0x2, 0xFC } }, ++ { 'X', { 0x0, 0xC6, 0x28, 0x10, 0x28, 0xC6 } }, ++ { 'Y', { 0x0, 0xE0, 0x10, 0xE, 0x10, 0xE0 } }, ++ { 'Z', { 0x0, 0x86, 0x8A, 0x92, 0xA2, 0xC2 } }, ++ { '[', { 0x0, 0x0, 0xFE, 0x82, 0x0, 0x0 } }, ++ { '\\', { 0x0, 0x40, 0x20, 0x10, 0x8, 0x4 } }, ++ { ']', { 0x0, 0x0, 0x82, 0xFE, 0x0, 0x0 } }, ++ { '^', { 0x0, 0x20, 0x40, 0x80, 0x40, 0x20 } }, ++ { '_', { 0x0, 0x2, 0x2, 0x2, 0x2, 0x2 } }, ++ { '`', { 0x0, 0x0, 0x0, 0xC0, 0x20, 0x0 } }, ++ { 'a', { 0x0, 0x4, 0x2A, 0x2A, 0x2A, 0x1E } }, ++ { 'b', { 0x0, 0xFE, 0x12, 0x22, 0x22, 0x1C } }, ++ { 'c', { 0x0, 0x1C, 0x22, 0x22, 0x22, 0x4 } }, ++ { 'd', { 0x0, 0x1C, 0x22, 0x22, 0x12, 0xFE } }, ++ { 'e', { 0x0, 0x1C, 0x2A, 0x2A, 0x2A, 0x18 } }, ++ { 'f', { 0x0, 0x10, 0x7E, 0x90, 0x80, 0x40 } }, ++ { 'g', { 0x0, 0x30, 0x4A, 0x4A, 0x4A, 0x7C } }, ++ { 'h', { 0x0, 0xFE, 0x10, 0x20, 0x20, 0x1E } }, ++ { 'i', { 0x0, 0x0, 0x22, 0xBE, 0x2, 0x0 } }, ++ { 'j', { 0x0, 0x4, 0x2, 0x22, 0xBC, 0x0 } }, ++ { 'k', { 0x0, 0x0, 0xFE, 0x8, 0x14, 0x22 } }, ++ { 'l', { 0x0, 0x0, 0x82, 0xFE, 0x2, 0x0 } }, ++ { 'm', { 0x0, 0x3E, 0x20, 0x18, 0x20, 0x1E } }, ++ { 'n', { 0x0, 0x3E, 0x10, 0x20, 0x20, 0x1E } }, ++ { 'o', { 0x0, 0x1C, 0x22, 0x22, 0x22, 0x1C } }, ++ { 'p', { 0x0, 0x3E, 0x28, 0x28, 0x28, 0x10 } }, ++ { 'q', { 0x0, 0x10, 0x28, 0x28, 0x18, 0x3E } }, ++ { 'r', { 0x0, 0x3E, 0x10, 0x20, 0x20, 0x10 } }, ++ { 's', { 0x0, 0x12, 0x2A, 0x2A, 0x2A, 0x4 } }, ++ { 't', { 0x0, 0x20, 0xFC, 0x22, 0x2, 0x4 } }, ++ { 'u', { 0x0, 0x3C, 0x2, 0x2, 0x4, 0x3E } }, ++ { 'v', { 0x0, 0x38, 0x4, 0x2, 0x4, 0x38 } }, ++ { 'w', { 0x0, 0x3C, 0x2, 0xC, 0x2, 0x3C } }, ++ { 'x', { 0x0, 0x22, 0x14, 0x8, 0x14, 0x22 } }, ++ { 'y', { 0x0, 0x30, 0xA, 0xA, 0xA, 0x3C } }, ++ { 'z', { 0x0, 0x22, 0x26, 0x2A, 0x32, 0x22 } }, ++ { '{', { 0x0, 0x0, 0x10, 0x6C, 0x82, 0x82 } }, ++ { '|', { 0x0, 0x0, 0x0, 0xFE, 0x0, 0x0 } }, ++ { '}', { 0x0, 0x82, 0x82, 0x6C, 0x10, 0x0 } }, ++ { '~', { 0x0, 0x20, 0x40, 0x20, 0x10, 0x20 } }, ++/* ++ { 'Ö', { 0x0, 0x1C, 0xA2, 0x22, 0xA2, 0x1C } }, ++ { 'Ä', { 0x0, 0x04, 0xAA, 0x2A, 0xAA, 0x1E } }, ++ { 'Ü', { 0x0, 0x3C, 0x82, 0x02, 0x84, 0x3E } }, ++ { 'ö', { 0x0, 0x1C, 0xA2, 0x22, 0xA2, 0x1C } }, ++ { 'ä', { 0x0, 0x04, 0xAA, 0x2A, 0xAA, 0x1E } }, ++ { 'ü', { 0x0, 0x3C, 0x82, 0x02, 0x84, 0x3E } }, ++ { 'ß', { 0x0, 0x7E, 0x80, 0xA8, 0xA8, 0x50 } }, ++*/ ++ /* TODO ++ * Add more characters here. The 'ch' member is an int so theoretically, you could ++ * specify UTF-32 code points as the ch. But then you'd have to translate the UTF-8 ++ * (or whatever) input to imonlcd_string to UTF-32, which doesn't sound like much fun... ++ */ ++ ++ /* Marks the end of the array, but also serves as the character that ++ * unknown inputs are mapped to (essentially, a "space") ++ */ ++ { '\0' } ++}; ++ ++/** ++ * This is the definition for a "big" font, which is a font that simply takes up twice as many pixels ++ * as the normal font. We only use it for drawing numbers. ++ */ ++typedef struct { ++ int ch; ++ unsigned short pixels[12]; ++} imon_bigfont; ++ ++/* TODO ++ * Some of these characters need a bit of tweaking... ++ */ ++static imon_bigfont bigfont[] = { ++ { '0', { 0x0000, 0x07E0, 0x1FF8, 0x3FFC, 0x7FFE, 0x4002, 0x4002, 0x4002, 0x3FFC, 0x3FFC, 0x1FF8, 0x07E0 } }, ++ { '1', { 0x0000, 0x0000, 0x0000, 0x4002, 0x7FFE, 0x7FFE, 0x7FFE, 0x7FFE, 0x0002, 0x0000, 0x0000, 0x0000 } }, ++ { '2', { 0x0000, 0x1806, 0x3C2C, 0x7C7C, 0x5C5C, 0x40DE, 0x7F9E, 0x7F8E, 0x3F0E, 0x1E0C, 0x0018, 0x0000 } }, ++ { '3', { 0x0000, 0x001C, 0x3C3C, 0x7C3E, 0x7C1A, 0x0080, 0x4182, 0x7FFE, 0x7FFE, 0x3E7C, 0x1C38, 0x0000 } }, ++ { '4', { 0x0000, 0x0030, 0x0050, 0x0190, 0x0610, 0x0002, 0x1FFE, 0x3FFE, 0x7FFE, 0x7FFE, 0x0012, 0x0002 } }, ++ { '5', { 0x0000, 0x0018, 0x7FBC, 0x793E, 0x3B1A, 0x3800, 0x3B02, 0x3BFE, 0x31FE, 0x61FC, 0x00F8, 0x0000 } }, ++ { '6', { 0x0000, 0x07E0, 0x1FF8, 0x3FFC, 0x7FFE, 0x4002, 0x0180, 0x5982, 0x7DFE, 0x3DFC, 0x18FC, 0x0078 } }, ++ { '7', { 0x0000, 0x0800, 0x7000, 0x3000, 0x703C, 0x787E, 0x79FE, 0x7BFC, 0x3E00, 0x3000, 0x6000, 0x0000 } }, ++ { '8', { 0x0000, 0x1C3C, 0x3E7E, 0x7FFE, 0x7FFE, 0x4182, 0x4182, 0x7FFE, 0x7FFE, 0x3E7E, 0x1C3C, 0x0000 } }, ++ { '9', { 0x0000, 0x1E18, 0x3F3C, 0x7FBE, 0x7F9A, 0x0180, 0x4002, 0x7FFE, 0x3FFC, 0x1FF8, 0x07E0, 0x0000 } }, ++ { ':', { 0x0000, 0x030C, 0x079E, 0x079E, 0x030C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 } }, ++ ++ /* Marks the end of the array, but also serves as the character that ++ * unknown inputs are mapped to (essentially, a "space") ++ */ ++ { '\0' } ++}; ++ ++static void send_data(uint64_t value, int fd); ++static void send_byte_data(unsigned char data[], int fd); ++static void set_screen(unsigned char *columns, int fd); ++static void draw_char(imon_font *font, char ch, int x, int y, unsigned char *columns); ++static void draw_bigchar(imon_bigfont *font, int ch, int x, int y, unsigned char *columns); ++static void draw_string(imon_font *font, char *string, int fd); ++static void setLineLength( int topLine, int botLine, int topProgress, int botProgress, int fd ); ++static void setBuiltinProgressBars( int topLine, int botLine, ++ int topProgress, int botProgress, int fd ); ++static int lengthToPixels( int length ); ++static void send_command_data( uint64_t commandData, int fd ); ++ ++/** ++ * Initialize the driver. ++ * \param drvthis Pointer to driver structure. ++ * \return Information of success (1) or failure (< 0). ++ */ ++MODULE_EXPORT int imonlcd_init (Driver *drvthis) ++{ ++ PrivateData *p = NULL; ++ ++ // Allocate, initialize and store private p ++ p = (PrivateData *) calloc(1, sizeof(PrivateData)); ++ if (p == NULL) { ++ debug(RPT_ERR, "%s: failed to allocate private data", drvthis->name); ++ return -1; ++ } ++ ++ if (drvthis->store_private_ptr(drvthis, p)) { ++ debug(RPT_ERR, "%s: failed to store private data pointer", drvthis->name); ++ return -1; ++ } ++ ++ char buf[256]; ++ p->imon_fd = -1; ++ p->width = 0; ++ p->height = 0; ++ p->cellwidth = LCD_DEFAULT_CELL_WIDTH; ++ p->cellheight = LCD_DEFAULT_CELL_HEIGHT; ++ p->last_cd_state = 0; ++ p->last_icon_state = 0x0; // no icons turned on at startup ++ p->lastPrivateIconState = 0x0; // no icons turned on at startup ++ p->discMode = 0; ++ ++ ++ /* Get settings from config file*/ ++ ++ /* Get device */ ++ strncpy(buf, drvthis->config_get_string(drvthis->name, "Device", 0, DEFAULT_DEVICE), sizeof(buf)); ++ buf[sizeof(buf)-1] = '\0'; ++ report(RPT_INFO, "%s: using Device %s", drvthis->name, buf); ++ ++ /* Open device for writing */ ++ if ((p->imon_fd = open(buf, O_WRONLY)) < 0) { ++ report(RPT_ERR, "%s: ERROR opening %s (%s).", drvthis->name, buf, strerror(errno)); ++ report(RPT_ERR, "%s: Did you load the iMON VFD kernel module?", drvthis->name); ++ report(RPT_ERR, "%s: More info in lcdproc/docs/README.imon", drvthis->name); ++ return -1; ++ } ++ ++ /* Get size settings*/ ++ strncpy(buf, drvthis->config_get_string(drvthis->name, "Size", 0, DEFAULT_SIZE), sizeof(buf)); ++ buf[sizeof(buf)-1] = '\0'; ++ if ((sscanf(buf , "%dx%d", &p->width, &p->height) != 2) ++ || (p->width <= 0) || (p->width > LCD_MAX_WIDTH) ++ || (p->height <= 0) || (p->height > LCD_MAX_HEIGHT)) { ++ report(RPT_WARNING, "%s: cannot read Size: %s; using default %s", ++ drvthis->name, buf, DEFAULT_SIZE); ++ sscanf(DEFAULT_SIZE , "%dx%d", &p->width, &p->height); ++ } ++ ++ /* Get the "on exit" setting so we know what to do when we shut the device down */ ++ strncpy(buf, drvthis->config_get_string(drvthis->name, "OnExit", 0, DEFAULT_ON_EXIT), sizeof(buf)); ++ buf[sizeof(buf)-1] = '\0'; ++ if ((sscanf(buf, "%d", &p->on_exit) != 1)) { ++ report(RPT_WARNING, "%s: cannot read OnExit: %s, using default %d", ++ drvthis->name, buf, DEFAULT_ON_EXIT); ++ sscanf(DEFAULT_ON_EXIT, "%d", &p->on_exit); ++ } ++ ++ /* Get the "contrast" setting */ ++ strncpy(buf, drvthis->config_get_string(drvthis->name, "Contrast", 0, DEFAULT_CONTRAST), sizeof(buf)); ++ buf[sizeof(buf)-1] = '\0'; ++ if ((sscanf(buf, "%d", &p->contrast) != 1)) { ++ report(RPT_WARNING, "%s: cannot read Contrast: %s, using default %d", ++ drvthis->name, buf, DEFAULT_CONTRAST); ++ sscanf(DEFAULT_CONTRAST, "%d", &p->contrast); ++ } ++ /* Get the "backlight" setting */ ++ strncpy(buf, drvthis->config_get_string(drvthis->name, "Backlight", 0, DEFAULT_BACKLIGHT), sizeof(buf)); ++ buf[sizeof(buf)-1] = '\0'; ++ if ((sscanf(buf, "%d", &p->backlightOn) != 1)) { ++ report(RPT_WARNING, "%s: cannot read Backlight: %s, using default %d", ++ drvthis->name, buf, DEFAULT_BACKLIGHT); ++ sscanf(DEFAULT_BACKLIGHT, "%d", &p->backlightOn); ++ } ++ /* Get the "disc-mode" setting */ ++ strncpy(buf, drvthis->config_get_string(drvthis->name, "DiscMode", 0, DEFAULT_DISCMODE), sizeof(buf)); ++ buf[sizeof(buf)-1] = '\0'; ++ if ((sscanf(buf, "%d", &p->discMode) != 1)) { ++ report(RPT_WARNING, "%s: cannot read DiscMode: %s, using default %d", ++ drvthis->name, buf, DEFAULT_DISCMODE); ++ sscanf(DEFAULT_DISCMODE, "%d", &p->discMode); ++ } ++ /* Make sure the frame buffer is there... */ ++ report(RPT_INFO, "%s: allocating %d bytes for framebuffer.", drvthis->name, p->width * (p->height / p->cellheight)); ++ p->framebuf = (unsigned char *) malloc(p->width * (p->height / p->cellheight)); ++ if (p->framebuf == NULL) { ++ report(RPT_ERR, "%s: unable to allocate framebuffer", drvthis->name); ++ return -1; ++ } ++ memset(p->framebuf, 0x00, p->width * (p->height / p->cellheight)); ++ ++ /* Send the "initialize" commands to the screen */ ++ /* TODO ++ * I still need to figure out what most of these do, and what should be "configurable"... ++ */ ++ if ( p->backlightOn ) ++ send_command_data( COMMANDS_DISPLAY_ON, p->imon_fd ); ++ else ++ send_command_data( COMMANDS_SHUTDOWN, p->imon_fd ); ++ send_command_data( COMMANDS_CLEAR_ALARM, p->imon_fd ); ++ imonlcd_set_contrast( drvthis, p->contrast ); ++ send_command_data( 0x0200000000000000, p->imon_fd ); // unknown ++ send_command_data( COMMANDS_SET_ICONS, p->imon_fd ); ++ send_command_data( COMMANDS_SET_LINES0, p->imon_fd ); // clear the progress-bars ++ send_command_data( COMMANDS_SET_LINES1, p->imon_fd ); // on top and bottom of the ++ send_command_data( COMMANDS_SET_LINES2, p->imon_fd ); // display ++ ++ report(RPT_DEBUG, "%s: init() done", drvthis->name); ++ ++ return 1; ++} ++ ++/** ++ * Close the driver (do necessary clean-up). ++ * \param drvthis Pointer to driver structure. ++ */ ++MODULE_EXPORT void imonlcd_close (Driver *drvthis) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ if (p != NULL) { ++ if (p->imon_fd >= 0) { ++ if (p->on_exit == ON_EXIT_SHOWMSG) { ++ // "show message" means "do nothing" -- the message is there already ++ report(RPT_INFO, "%s: closing, leaving \"goodbye\" message.", drvthis->name); ++ } else if (p->on_exit == ON_EXIT_BLANKSCREEN) { ++ // turning backlight off (confirmed for my Silverstone LCD) ++ // (as "cybrmage" at mediaportal pointed out, his LCD is an Antec built-in one ++ // and turns completely off with this command) ++ // TODO: Why does the backlight turn on again at reboot and/or shutdown ++ // just when the computer turns it's power off / reboots. ++ // Is it just my bios sending a reset to all USB-devices, is it ++ // the USB-kernel-code that's sending the reset?! ++ // Maybe gets solved with setting the alarm!? ++ report(RPT_INFO, "%s: closing, turning backlight off.", drvthis->name); ++ send_command_data( COMMANDS_SHUTDOWN, p->imon_fd ); ++ send_command_data( COMMANDS_CLEAR_ALARM, p->imon_fd ); ++ } else { ++ // by default, show the big clock. We need to set it to the current ++ // time, then it just keeps counting automatically. ++ report(RPT_INFO, "%s: closing, showing clock.", drvthis->name); ++ ++ time_t tt = time(NULL); ++ struct tm *t = localtime(&tt); ++ uint64_t data; ++ ++ data = ((uint64_t)0x50 << 56); ++ data += ((uint64_t)t->tm_sec << 48); ++ data += ((uint64_t)t->tm_min << 40); ++ data += ((uint64_t)t->tm_hour << 32); ++ data += ((uint64_t)t->tm_mday << 24); ++ data += ((uint64_t)t->tm_mon << 16); ++ data += (((uint64_t)t->tm_year) << 8); ++ data += 0x80; ++ send_command_data(data, p->imon_fd); ++ send_command_data( COMMANDS_CLEAR_ALARM, p->imon_fd ); ++ } ++ ++ close(p->imon_fd); ++ } ++ ++ if (p->framebuf != NULL) ++ free(p->framebuf); ++ p->framebuf = NULL; ++ ++ free(p); ++ } ++ drvthis->store_private_ptr(drvthis, NULL); ++} ++ ++ ++/** ++ * Provide some information about this driver. ++ * \param drvthis Pointer to driver structure. ++ * \return Constant string with information. ++ */ ++MODULE_EXPORT const char * imonlcd_get_info (Driver *drvthis) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ strcpy(p->info, "SoundGraph iMON OEM (and others) LCD driver"); ++ return p->info; ++} ++ ++ ++/** ++ * Clear the screen. ++ * \param drvthis Pointer to driver structure. ++ */ ++MODULE_EXPORT void imonlcd_clear (Driver *drvthis) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ memset(p->framebuf, 0, p->width * (p->height / 8)); ++} ++ ++ ++/** ++ * Flush data on screen to the LCD. ++ * \param drvthis Pointer to driver structure. ++ */ ++MODULE_EXPORT void imonlcd_flush (Driver *drvthis) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ set_screen(p->framebuf, p->imon_fd); ++} ++ ++ ++/** ++ * Print a string on the screen at position (x,y). ++ * The upper-left corner is (1,1), the lower-right corner is (p->width, p->height). ++ * \param drvthis Pointer to driver structure. ++ * \param x Horizontal character position (column). ++ * \param y Vertical character position (row). ++ * \param string String that gets written. ++ */ ++MODULE_EXPORT void imonlcd_string (Driver *drvthis, int x, int y, const char string[]) ++{ ++ int i; ++ ++ for (i = 0; string[i] != '\0'; i++) ++ imonlcd_chr(drvthis, x+i, y, string[i]); ++} ++ ++ ++/** ++ * Print a character on the screen at position (x,y). ++ * The upper-left corner is (1,1), the lower-right corner is (p->width/p->cellwidth, p->height/p->cellheight). ++ * \param drvthis Pointer to driver structure. ++ * \param x Horizontal character position (column). ++ * \param y Vertical character position (row). ++ * \param c Character that gets written. ++ */ ++MODULE_EXPORT void imonlcd_chr (Driver *drvthis, int x, int y, char ch) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ y--; x--; ++ ++ if ((x < 0) || (y < 0) || (x >= (p->width / p->cellwidth)) || (y >= (p->height / p->cellheight))) ++ return; ++ ++ draw_char(font, ch, x * p->cellwidth, y * p->cellheight, p->framebuf); ++} ++ ++/** ++ * Draw a vertical bar bottom-up. ++ * \param drvthis Pointer to driver structure. ++ * \param x Horizontal character position (column) of the starting point. ++ * \param y Vertical character position (row) of the starting point. ++ * \param len Number of characters that the bar is high at 100% ++ * \param promille Current height level of the bar in promille. ++ * \param options Options (currently unused). ++ */ ++MODULE_EXPORT void imonlcd_vbar (Driver *drvthis, int x, int y, int len, int promille, int options) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ if ((x < 0) || (y < 0) || (y > (p->width / p->cellwidth))) ++ return; ++ ++ // Pixels is the number of pixels we need to draw, vertically, based on the passed-in promille. ++ int pixels = (int) ( (double)( ( 2 * len * p->cellheight ) * ( (double)promille / 2000 ) ) ); ++ ++ x--; y--; ++ x *= p->cellwidth; ++ ++ int j, k; ++ unsigned char barChar; ++ ++ for ( j=0; j0 && k < 8; pixels-- ) ++ { ++ barChar = barChar | (1 << k); ++ k++; ++ } ++ p->framebuf[x+1 + ((y-j) * 96)] = barChar; ++ p->framebuf[x+2 + ((y-j) * 96)] = barChar; ++ p->framebuf[x+3 + ((y-j) * 96)] = barChar; ++ p->framebuf[x+4 + ((y-j) * 96)] = barChar; ++ p->framebuf[x+5 + ((y-j) * 96)] = barChar; ++ ++ } ++} ++ ++ ++/** ++ * Draw a horizontal bar to the right. ++ * \param drvthis Pointer to driver structure. ++ * \param x Horizontal character position (column) of the starting point. ++ * \param y Vertical character position (row) of the starting point. ++ * \param len Number of characters that the bar is long at 100% ++ * \param promille Current length level of the bar in promille (i.e. from 0 to 1000). ++ * \param options Options (currently unused). ++ */ ++MODULE_EXPORT void imonlcd_hbar (Driver *drvthis, int x, int y, int len, int promille, int options) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ if ((x < 0) || (y < 0) || (y > (p->height / p->cellheight))) ++ return; ++ ++ // Pixels is the number of pixels we need to draw, horizontally, based on the passed-in promille. ++ int pixels = (int) ( (double)( ( 2 * len * p->cellwidth ) * ( (double)promille / 2000 ) ) ); ++ ++ x--; y--; ++ x *= p->cellwidth; ++ ++ for (; pixels >= 0; pixels--) { ++ ++ if (x > (p->width * p->cellwidth)) ++ return; ++ ++ p->framebuf[x + (y * 96)] = 0x3C; ++ x++; ++ } ++} ++ ++/** ++ * Draws a "big" number at the specified x-coordinate. ++ * ++ * Normally, the number that is displayed is "meant" to be 3x4 characters, but because we have a bit ++ * more flexibility, I've drawn the numbers as just being 12x16 pixels. That means that while the ++ * client will pass x-values between 0 and 16, we need to scale it and make sure the numbers remain ++ * centered. ++ * ++ * \param drvthis A point of the the Driver structure. ++ * \param the x-coordinate to display the character at. ++ * \num The number to display ("10" is the colon) ++ */ ++MODULE_EXPORT void imonlcd_num (Driver *drvthis, int x, int num) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ // This isn't that great, and really it only works when your screen is 96 pixels wide and ++ // even then, it makes assumptions about the coordinates the client passes to us. However, ++ // it works for MythTV... and looks pretty cool, too :-) ++ // TODO: Check the number flashing with the colon with "lcdproc K". Done! Please anyone recheck with mythtv ++ if(num < 10) ++ x = 12 + (int)(((x - 1) * p->cellwidth) * 0.75); ++ else ++ x = 12 + (int)(((x - 1) * p->cellwidth) * 0.72); ++ ++ draw_bigchar(bigfont, (num >= 10 ? ':' : (num + '0')), x, 0, p->framebuf); ++} ++ ++/** ++ * Sets the "output state" for the device. We use this to control the icons around the outside the ++ * display. The bits in \c state correspond to the icons as follows: ++ * ++ * bit 0 : disc icon (0=off, 1='spin') , if Toprow==4, use CD-animation, else use "HDD-recording-animation" ++ * bit 1,2,3 : top row (0=none, 1=music, 2=movie, 3=photo, 4=CD/DVD, 5=TV, 6=Web, 7=News/Weather) ++ * bit 4,5 : 'speaker' icons (0=off, 1=L+R, 2=5.1ch, 3=7.1ch) ++ * bit 6 : S/PDIF icon ++ * bit 7 : 'SRC' ++ * bit 8 : 'FIT' ++ * bit 9 : 'TV' ++ * bit 10 : 'HDTV' ++ * bit 11 : 'SRC1' ++ * bit 12 : 'SRC2' ++ * bit 13,14,15: bottom-right icons (0=off, 1=MP3, 2=OGG, 3=WMA, 4=WAV) ++ * bit 16,17,18: bottom-middle icons (0=off, 1=MPG, 2=AC3, 3=DTS, 4=WMA) ++ * bit 19,20,21: bottom-left icons (0=off, 1=MPG, 2=DIVX, 3=XVID, 4=WMV) ++ * bit 22 : 'VOL' (volume) ++ * bit 23 : 'TIME' ++ * bit 24 : 'ALARM' ++ * bit 25 : 'REC' (recording) ++ * bit 26 : 'REP' (repeat) ++ * bit 27 : 'SFL' (shuffle) ++ * bit 28 : Abuse this for progress bars (if set to 1), lower bits represent ++ * the length (6 bits each: P|6xTP|6xTL|6xBL|6xBP with P = bit 28, ++ * TP=Top Progress, TL = Top Line, BL = Bottom Line, BP = Bottom Progress). ++ * If bit 28 is set to 1, lower bits are interpreted as ++ * lengths; otherwise setting the symbols as usual. ++ * 0 <= length <= 32, bars extend from left to right. ++ * length > 32, bars extend from right to left, length is counted ++ * from 32 up (i.e. 35 means a length of 3). ++ * ++ * Remember: There are two kinds of calls! ++ * With bit 28 set to 1: Set all bars (leaving the symbols as is), ++ * with bit 28 set to 0: Set the symbols (leaving the bars as is). ++ * Beware: TODO: May become a race condition, if both calls are executed ++ * before the display gets updated. Keep this in mind in your ++ * client-code. ++ * bit 29 : 'disc-in icon' - half ellipsoid under the disc symbols (0=off, 1=on) ++ */ ++ ++MODULE_EXPORT void imonlcd_output (Driver *drvthis, int state) ++{ ++ ++ PrivateData *p = drvthis->private_data; ++ uint64_t icon = 0x0; ++ ++ if ( state == -1 ) // the value for "on" in the lcdproc-protocol ++ { ++ icon = (uint64_t)IMON_ICON_ALL; ++ send_command_data( COMMANDS_SET_ICONS | icon, p->imon_fd); ++ p->lastPrivateIconState = state; ++ setLineLength( 32, 32, 32, 32, p->imon_fd ); ++ ++ return; ++ } ++ else if ( state == 0x0 ) // the value for "off" in the lcdproc-protocol ++ { ++ icon = (uint64_t)0x0;; ++ send_command_data( COMMANDS_SET_ICONS | icon, p->imon_fd); ++ p->lastPrivateIconState = state; ++ setLineLength( 0, 0, 0, 0, p->imon_fd ); ++ return; ++ } ++ // bit 28 : Abuse this for progress bars. See above for usage. ++ else if ( ( state & IMON_OUTPUT_PBARS_MASK ) != 0 && state > 0 ) ++ { ++ int topProgress = ( state & 63 ); // extract the bar-values ++ int topLine = ( state & (63<<6) ) >> 6; // for each bar separately ++ int botProgress = ( state & (63<<12) ) >> 12; ++ int botLine = ( state & (63<<18) ) >> 18; ++ ++ botProgress = botProgress > 32 ? -( botProgress - 32 ) : botProgress; ++ topProgress = topProgress > 32 ? -( topProgress - 32 ) : topProgress; ++ botLine = botLine > 32 ? -( botLine - 32 ) : botLine; ++ topLine = topLine > 32 ? -( topLine - 32 ) : topLine; ++ ++ setLineLength( topLine, botLine, topProgress, botProgress, p->imon_fd ); ++ ++ state = p->lastPrivateIconState; // continue and set all other icons as before ++ } ++ ++ // bit 0 : disc icon (0=off, 1='spin') ++ if ( ( state & IMON_OUTPUT_CD_MASK ) != 0 ) ++ { ++ switch( p->last_cd_state ) { ++ case 0: ++ p->last_cd_state = 1; ++ if ( p->discMode == 1 ) ++ icon |= ( (uint64_t)(255 - 128 - 8) << 40); // all on except top & bottom ++ else ++ icon |= ( (uint64_t)(128 | 8) << 40); // top & bottom on ++ break; ++ case 1: ++ p->last_cd_state = 2; ++ if ( p->discMode == 1 ) ++ icon |= ( (uint64_t)(255 - 16 - 1) << 40); //all on except top-right & bottom-left ++ else ++ icon |= ( (uint64_t)(1 | 16) << 40); // top-right & bottom-left on ++ break; ++ case 2: ++ p->last_cd_state = 3; ++ if ( p->discMode == 1 ) ++ icon |= ( (uint64_t)(255 - 32 - 2) << 40); // all on except right & left ++ else ++ icon |= ( (uint64_t)(32 | 2) << 40); // right & left on ++ break; ++ default: ++ p->last_cd_state = 0; ++ if ( p->discMode == 1 ) ++ icon |= ( (uint64_t)(255 - 64 - 4) << 40); // all on except top-left & bottom-right ++ else ++ icon |= ( (uint64_t)(4 | 64) << 40); // top-left & bottom-right on ++ break; ++ } ++ } ++ ++ // bit 1,2,3 : top row (0=none, 1=music, 2=movie, 3=photo, 4=CD/DVD, 5=TV, 6=Web, 7=News/Weather) ++ if ( ( ( state & IMON_OUTPUT_TOPROW_MASK ) != 0) ) ++ { ++ switch( ( ( state & IMON_OUTPUT_TOPROW_MASK ) >> 1 ) ) ++ { ++ case 1: ++ icon |= IMON_ICON_MUSIC; ++ break; ++ case 2: ++ icon |= IMON_ICON_MOVIE; ++ break; ++ case 3: ++ icon |= IMON_ICON_PHOTO; ++ break; ++ case 4: ++ icon |= IMON_ICON_CD_DVD; ++ break; ++ case 5: ++ icon |= IMON_ICON_TV; ++ break; ++ case 6: ++ icon |= IMON_ICON_WEBCAST; ++ break; ++ case 7: ++ icon |= IMON_ICON_NEWS; ++ break; ++ default: ++ break; ++ } ++ } ++ // bit 4,5 : 'speaker' icons (0=off, 1=L+R, 2=5.1ch, 3=7.1ch) ++ if ( ( ( state & IMON_OUTPUT_SPEAKER_MASK ) != 0) ) ++ { ++ switch( ( ( state & IMON_OUTPUT_SPEAKER_MASK ) >> 4 ) ) ++ { ++ case 1: ++ icon |= IMON_SPKR_FL | IMON_SPKR_FR; ++ break; ++ case 2: ++ icon |= IMON_SPKR_FL | IMON_SPKR_FC | IMON_SPKR_FR | IMON_SPKR_RL | IMON_SPKR_RR | IMON_SPKR_LFE; ++ break; ++ case 3: ++ icon |= IMON_SPKR_FL | IMON_SPKR_FC | IMON_SPKR_FR | IMON_SPKR_RL | IMON_SPKR_RR | IMON_SPKR_SL | IMON_SPKR_SR | IMON_SPKR_LFE; ++ break; ++ default: ++ break; ++ } ++ } ++ // bit 6 : S/PDIF icon ++ icon = ( ( state & IMON_OUTPUT_SPDIF_MASK ) != 0 ) ? (icon | IMON_SPKR_SPDIF) : (icon & ~IMON_SPKR_SPDIF); ++ // bit 7 : 'SRC' ++ icon = ( ( state & IMON_OUTPUT_SRC_MASK ) != 0 ) ? (icon | IMON_ICON_SRC) : (icon & ~IMON_ICON_SRC); ++ // bit 8 : 'FIT' ++ icon = ( ( state & IMON_OUTPUT_FIT_MASK ) != 0 ) ? (icon | IMON_ICON_FIT) : (icon & ~IMON_ICON_FIT); ++ // bit 9 : 'TV' ++ icon = ( ( state & IMON_OUTPUT_TV_MASK ) != 0 ) ? (icon | IMON_ICON_TV_2) : (icon & ~IMON_ICON_TV_2); ++ // bit 10 : 'HDTV' ++ icon = ( ( state & IMON_OUTPUT_HDTV_MASK ) != 0 ) ? (icon | IMON_ICON_HDTV) : (icon & ~IMON_ICON_HDTV); ++ // bit 11 : 'SRC1' ++ icon = ( ( state & IMON_OUTPUT_SCR1_MASK ) != 0 ) ? (icon | IMON_ICON_SCR1) : (icon & ~IMON_ICON_SCR1); ++ // bit 12 : 'SRC2' ++ icon = ( ( state & IMON_OUTPUT_SCR2_MASK ) != 0 ) ? (icon | IMON_ICON_SCR2) : (icon & ~IMON_ICON_SCR2); ++ // bit 13,14,15: bottom-right icons (0=off, 1=MP3, 2=OGG, 3=WMA, 4=WAV) ++ if ( ( ( state & IMON_OUTPUT_BRICONS_MASK ) != 0) ) ++ { ++ switch( ( ( state & IMON_OUTPUT_BRICONS_MASK ) >> 13 ) ) ++ { ++ case 1: ++ icon |= IMON_ICON_MP3; ++ break; ++ case 2: ++ icon |= IMON_ICON_OGG; ++ break; ++ case 3: ++ icon |= IMON_ICON_WMA2; ++ break; ++ case 4: ++ icon |= IMON_ICON_WAV; ++ break; ++ default: ++ break; ++ } ++ } ++ // bit 16,17,18: bottom-middle icons (0=off, 1=MPG, 2=AC3, 3=DTS, 4=WMA) ++ if ( ( ( state & IMON_OUTPUT_BMICONS_MASK ) != 0) ) ++ { ++ switch( ( ( state & IMON_OUTPUT_BMICONS_MASK ) >> 16 ) ) ++ { ++ case 1: ++ icon |= IMON_ICON_MPG2; ++ break; ++ case 2: ++ icon |= IMON_ICON_AC3; ++ break; ++ case 3: ++ icon |= IMON_ICON_DTS; ++ break; ++ case 4: ++ icon |= IMON_ICON_WMA; ++ break; ++ default: ++ break; ++ } ++ } ++ // bit 19,20,21: bottom-left icons (0=off, 1=MPG, 2=DIVX, 3=XVID, 4=WMV) ++ if ( ( ( state & IMON_OUTPUT_BLICONS_MASK ) != 0) ) ++ { ++ switch( ( ( state & IMON_OUTPUT_BLICONS_MASK ) >> 19 ) ) ++ { ++ case 1: ++ icon |= IMON_ICON_MPG; ++ break; ++ case 2: ++ icon |= IMON_ICON_DIVX; ++ break; ++ case 3: ++ icon |= IMON_ICON_XVID; ++ break; ++ case 4: ++ icon |= IMON_ICON_WMV; ++ break; ++ default: ++ break; ++ } ++ } ++ // bit 22 : 'VOL' (volume) ++ icon = ( ( state & IMON_OUTPUT_VOL_MASK ) != 0 ) ? (icon | IMON_ICON_VOL) : (icon & ~IMON_ICON_VOL); ++ // bit 23 : 'TIME' ++ icon = ( ( state & IMON_OUTPUT_TIME_MASK ) != 0 ) ? (icon | IMON_ICON_TIME) : (icon & ~IMON_ICON_TIME); ++ // bit 24 : 'ALARM' ++ icon = ( ( state & IMON_OUTPUT_ALARM_MASK ) != 0 ) ? (icon | IMON_ICON_ALARM) : (icon & ~IMON_ICON_ALARM); ++ // bit 25 : 'REC' (recording) ++ icon = ( ( state & IMON_OUTPUT_REC_MASK ) != 0 ) ? (icon | IMON_ICON_REC) : (icon & ~IMON_ICON_REC); ++ // bit 26 : 'REP' (repeat) ++ icon = ( ( state & IMON_OUTPUT_REP_MASK ) != 0 ) ? (icon | IMON_ICON_REP) : (icon & ~IMON_ICON_REP); ++ // bit 27 : 'SFL' (shuffle) ++ icon = ( ( state & IMON_OUTPUT_SFL_MASK ) != 0 ) ? (icon | IMON_ICON_SFL) : (icon & ~IMON_ICON_SFL); ++ // bit 29 : 'disc-in' ++ icon = ( ( state & IMON_OUTPUT_DISK_IN_MASK ) != 0 ) ? (icon | IMON_ICON_DISK_IN) : (icon & ~IMON_ICON_DISK_IN); ++ ++ p->last_icon_state = (uint64_t)icon; ++ p->lastPrivateIconState = state; ++ send_command_data( COMMANDS_SET_ICONS | p->last_icon_state, p->imon_fd); ++} ++ ++/** ++ * Return the display width in characters. ++ * \param drvthis Pointer to driver structure. ++ * \return Number of characters the display is wide. ++ */ ++MODULE_EXPORT int imonlcd_width (Driver *drvthis) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ return p->width/p->cellwidth; ++} ++ ++ ++/** ++ * Return the display height in characters. ++ * \param drvthis Pointer to driver structure. ++ * \return Number of characters the display is high. ++ */ ++MODULE_EXPORT int imonlcd_height (Driver *drvthis) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ return p->height/p->cellheight; ++} ++ ++ ++/** ++ * Return the width of a character in pixels. ++ * \param drvthis Pointer to driver structure. ++ * \return Number of pixel columns a character cell is wide. ++ */ ++MODULE_EXPORT int imonlcd_cellwidth (Driver *drvthis) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ return p->cellwidth; ++} ++ ++ ++/** ++ * Return the height of a character in pixels. ++ * \param drvthis Pointer to driver structure. ++ * \return Number of pixel lines a character cell is high. ++ */ ++MODULE_EXPORT int imonlcd_cellheight (Driver *drvthis) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ return p->cellheight; ++} ++ ++/** ++ * Sends data to the screen. The kernel module expects data to be ++ * sent in 8 byte chunks, so for simplicity, we allow you to define ++ * the data as a 64-bit integer. ++ * ++ * \param value The data to send. Must be in a format that is recognized ++ * by the device. The kernel module doesn't actually do ++ * validation. ++ * \param fd A file descriptor pointing to the /dev/lcd* file that we write to. ++ */ ++static void send_data(uint64_t value, int fd) ++{ ++ /* TODO ++ * In order to make big- and little-endian issues more clear, we should probably ++ * drop this method in favour of the send_byte_data method... ++ */ ++ ++ // Note: We do it like this so that we can be sure we work on big- and little- ++ // endian machines the same way. ++ unsigned char data[8]; ++ data[0] = (value & 0xFF00000000000000) >> (7 * 8); ++ data[1] = (value & 0x00FF000000000000) >> (6 * 8); ++ data[2] = (value & 0x0000FF0000000000) >> (5 * 8); ++ data[3] = (value & 0x000000FF00000000) >> (4 * 8); ++ data[4] = (value & 0x00000000FF000000) >> (3 * 8); ++ data[5] = (value & 0x0000000000FF0000) >> (2 * 8); ++ data[6] = (value & 0x000000000000FF00) >> (1 * 8); ++ data[7] = (value & 0x00000000000000FF); ++ ++ send_byte_data(data, fd); ++} ++ ++/** ++ * TODO: Check why exactly this has to be done ;-) and if this also works for ++ * 64-bit OSs. ++ * Sends data to the screen. The kernel module expects data to be ++ * sent in 8 byte chunks, so for simplicity, we allow you to define ++ * the data as a 64-bit integer. ++ * The bytes are reversed because all commands seem to need this to work! ++ * ++ * \param value The data to send. Must be in a format that is recognized ++ * by the device. The kernel module doesn't actually do ++ * validation. ++ * \param fd A file descriptor pointing to the /dev/lcd* file that we write to. ++ */ ++static void send_command_data( uint64_t commandData, int fd ) ++{ ++ if ((commandData & 0xFF00000000000000L) == 0x5000000000000000L) { ++ printf("%s: sending command: %lX\n", "imonlcd", commandData); ++ } ++ ++ unsigned char data[8]; ++ data[7] = (unsigned char)((commandData >> 56) & 0xFF); ++ data[6] = (unsigned char)((commandData >> 48) & 0xFF); ++ data[5] = (unsigned char)((commandData >> 40) & 0xFF); ++ data[4] = (unsigned char)((commandData >> 32) & 0xFF); ++ data[3] = (unsigned char)((commandData >> 24) & 0xFF); ++ data[2] = (unsigned char)((commandData >> 16) & 0xFF); ++ data[1] = (unsigned char)((commandData >> 8) & 0xFF); ++ data[0] = (unsigned char)(commandData & 0xFF); ++ ++ send_byte_data(data, fd); ++ ++} ++ ++/** ++ * Sends data to the screen. ++ * ++ * \param data The 8 byte packet to send to the screen. ++ * \param fd A file descriptor pointing to the /dev/lcd* file that we write to. ++ */ ++static void send_byte_data(unsigned char data[], int fd) ++{ ++ write(fd, data, 8); ++} ++ ++/** ++ * Sets the contrast of the display. ++ * ++ * \param drvthis Pointer to driver structure. ++ * \param promille The value the contrast is set to in promille ++ * (0 = lowest contrast; 1000 = highest contrast). ++ * \return 0 on failure, >0 on success. ++ */ ++MODULE_EXPORT int imonlcd_set_contrast( Driver *drvthis, int promille ) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ if ( promille < 0) { ++ promille = 0; ++ } else if ( promille > 1000 ) { ++ promille = 1000; ++ } ++ ++ p->contrast = promille; ++ ++ // send contrast normalized to the hardware-understandable-value (0 to 40) ++ // 0 is the lowest (and usually the best, in my opinion) and 40 is the highest. TODO: @Dean: really 0=best?! ++ send_command_data(0x03FFFFFF00580A00L + (uint64_t)( p->contrast/25 ), p->imon_fd); ++ return 1; ++} ++ ++/** ++ * Gets the current contrast of the display. ++ * ++ * \param drvthis Pointer to driver structure. ++ * \return The current contrast in promille (0 = lowest contrast; ++ * 1000 = highest contrast). ++ */ ++MODULE_EXPORT int imonlcd_get_contrast( Driver *drvthis ) ++{ ++ PrivateData *p = drvthis->private_data; ++ return p->contrast; ++} ++ ++/** ++ * Sets the backlight state of the display. ++ * ++ * \param drvthis Pointer to driver structure. ++ * \param on The backlight state boolean-like: 0 = off; >0 = on. ++ */ ++MODULE_EXPORT void imonlcd_backlight(Driver *drvthis, int on) ++{ ++ PrivateData *p = drvthis->private_data; ++ ++ /* ++ * TODO: For some reason, lcdproc keeps calling this and flipping the ++ * 'on' so you end up flashing the backlight for no particular reason ++ * (and on my Antec, turning the backlight off, turns the whole thing ++ * off, so it's really bad...) ++ */ ++ return; ++ ++ // To prevent superfluous (and erroneous) communication ++ if ( p->backlightOn == on ) ++ return; ++ else ++ p->backlightOn = on; ++ ++ if ( on ) ++ { ++ send_command_data( COMMANDS_DISPLAY_ON, p->imon_fd ); ++ } ++ else ++ { ++ send_command_data( COMMANDS_SHUTDOWN, p->imon_fd ); ++ } ++} ++ ++/** ++ * Sets the pixels on the screen, using the specified "columns". ++ * Each column is eight pixels high (and represented by one byte) ++ * and the columns are filled from left to right. When the end ++ * of the screen is hit, the columns wrap to the next line. Each ++ * line is 96 pixels wide, so you need to pass an array of 192 ++ * bytes. ++ * ++ * \param columns The data for each column. ++ * \param fd A file descriptor pointing to the /dev/lcd* file that we write to. ++ */ ++static void set_screen(unsigned char *columns, int fd) ++{ ++ /* TODO ++ * This could be implemented as a single call to write() with all the data, ++ * but that would require corresponding changes to the lirc kernel module. ++ */ ++ int i; ++ uint64_t msb; ++ uint64_t data; ++ int byteno; ++ ++ i = 0; ++ for (msb = 0x20; msb <= 0x3b; msb++) { ++ data = 0; ++ for (byteno = 1; byteno < 8; byteno ++) { ++ data |= columns[i]; ++ data <<= 8; ++ i++; ++ } ++ data |= msb; ++ send_data(data, fd); ++ } ++} ++ ++/** ++ * Draws a "big" character -- that is, one that's twice as big as a normal character -- at ++ * the specified position on the screen. ++ */ ++static void draw_bigchar(imon_bigfont *font, int ch, int x, int y, unsigned char *columns) ++{ ++ imon_bigfont *defn = font; ++ int i; ++ ++ while (defn->ch != ch && defn->ch != '\0') { ++ defn++; ++ } ++ ++ int colBorder = 12; // correction for the number flashing with the colon running "lcdproc K" ++ if ( ch == ':' ) // TODO: Please check anybody with mythtv ++ colBorder = 6; ++ for(i = 0; i < colBorder; i++) { ++ columns[x + i + (y * colBorder)] = (defn->pixels[i] & 0xFF00) >> 8; ++ } ++ for(i = 0; i < colBorder; i++) { ++ columns[x + i + (y * colBorder) + 96] = (defn->pixels[i] & 0x00FF); ++ } ++} ++ ++/** ++ * Draws a single character at the specified (x,y) coordinates of the given screen data. ++ */ ++static void draw_char(imon_font *font, char ch, int x, int y, unsigned char *columns) ++{ ++ imon_font *defn = font; ++ int i; ++ ++ while (defn->ch != ch && defn->ch != '\0') { ++ defn++; ++ } ++ ++ for(i = 0; i < 6; i++) { ++ columns[x + i + (y * 12)] = defn->pixels[i]; ++ } ++} ++ ++/** ++ * Sets the length of the built-in progress-bars and lines. ++ * Values from -32 to 32 are allowed. Positive values indicate that bars extend ++ * from left to right, negative values indicate that the run from right to left. ++ * Conventient method to simplify setting the bars with "human understandable ++ * values". ++ * ++ * \see setBuiltinProgressBars, lengthToPixels ++ * ++ * \param topLine ++ * \param botLine ++ * \param topProgress ++ * \param botProgress ++ * \param fd A file descriptor pointing to the /dev/lcd* file that we write to. ++ */ ++static void setLineLength( int topLine, int botLine, int topProgress, int botProgress, int fd ) ++{ ++ setBuiltinProgressBars( lengthToPixels( topLine ), ++ lengthToPixels( botLine ), ++ lengthToPixels( topProgress ), ++ lengthToPixels( botProgress ), ++ fd ++ ); ++} ++ ++/** ++ * Sets the length of the built-in progress-bars and lines. ++ * Values from -32 to 32 are allowed. Positive values indicate that bars extend ++ * from left to right, negative values indicate that the run from right to left. ++ * ++ * \param topLine ++ * \param botLine ++ * \param topProgress ++ * \param botProgress ++ * \param fd A file descriptor pointing to the /dev/lcd* file that we write to. ++ */ ++static void setBuiltinProgressBars( int topLine, int botLine, ++ int topProgress, int botProgress, int fd ) ++{ ++ // Least sig. bit is on the right ++ uint64_t data; ++ ++ data = ( (uint64_t) topProgress ) << 8 * 4; ++ data |= (uint64_t) topLine & 0x00000000FFFFFFFF; ++ data &= 0x00FFFFFFFFFFFFFF; ++ send_command_data( COMMANDS_SET_LINES0 | data, fd ); ++ ++ data = ( ( (uint64_t) topProgress ) >> 8 * 3 ) & 0x00000000000000FF; ++ data |= ( ( (uint64_t) botProgress ) << 8 ) & 0x000000FFFFFFFF00; ++ data |= ( ( (uint64_t) botLine ) << 8 * 5 ) & 0x00FFFF0000000000; ++ send_command_data( COMMANDS_SET_LINES1 | data, fd ); ++ ++ data = ( (uint64_t) botLine ) >> 8 * 2; ++ send_command_data( COMMANDS_SET_LINES2 | data, fd ); ++} ++ ++/** ++ * Maps values to corresponding pixmaps for the built-in progress bars. ++ * Values from -32 to 32 are allowed. Positive values indicate that bars extend ++ * from left to right, negative values indicate that they run from right to left. ++ * ++ * \param length The length of the bar. ++ * \return The pixmap that represents the given length. ++ * ++ */ ++static int lengthToPixels( int length ) ++{ ++ int pixLen[] = ++ { ++ 0x00, 0x00000080, 0x000000c0, 0x000000e0, 0x000000f0, ++ 0x000000f8, 0x000000fc, 0x000000fe, 0x000000ff, ++ 0x000080ff, 0x0000c0ff, 0x0000e0ff, 0x0000f0ff, ++ 0x0000f8ff, 0x0000fcff, 0x0000feff, 0x0000ffff, ++ 0x0080ffff, 0x00c0ffff, 0x00e0ffff, 0x00f0ffff, ++ 0x00f8ffff, 0x00fcffff, 0x00feffff, 0x00ffffff, ++ 0x80ffffff, 0xc0ffffff, 0xe0ffffff, 0xf0ffffff, ++ 0xf8ffffff, 0xfcffffff, 0xfeffffff, 0xffffffff ++ }; ++ ++ if ( abs( length ) > 32 ) ++ { ++ return (0); ++ } ++ if ( length >= 0 ) ++ { ++ return pixLen[ length ]; ++ } ++ else ++ { ++ return ( pixLen[ 32 + length ] ^ 0xffffffff ); ++ } ++} ++ ++// EOF ++ +diff -Naurp lcdproc-0.5.2/server/drivers/imonlcd.h lcdproc-0.5.2.imonlcd/server/drivers/imonlcd.h +--- lcdproc-0.5.2/server/drivers/imonlcd.h 1969-12-31 19:00:00.000000000 -0500 ++++ lcdproc-0.5.2.imonlcd/server/drivers/imonlcd.h 2008-11-07 10:30:16.286851426 -0500 +@@ -0,0 +1,49 @@ ++/** ++ * Driver for SoundGraph iMON OEM (and others) LCD Module ++ * ++ * In order to be able to use it, you have to install the lirc_imonlcd ++ * kernel module for LIRC (http://www.lirc.org) -- until that module is ++ * available in the main LIRC branch, you can get a patch for it from ++ * the same place you got this patch. ++ * ++ * Copyright (c) 2007, Dean Harding , but (heavily :p) ++ * on the work of Venky Raju. ++ * ++ * This source code is being released under the GPL. ++ * Please see the file COPYING in this package for details. ++ * ++ */ ++ ++#ifndef IMONLCD_H ++#define IMONLCD_H ++ ++#include "lcd.h" ++ ++MODULE_EXPORT int imonlcd_init (Driver *drvthis); ++MODULE_EXPORT void imonlcd_close (Driver *drvthis); ++MODULE_EXPORT int imonlcd_width (Driver *drvthis); ++MODULE_EXPORT int imonlcd_height (Driver *drvthis); ++MODULE_EXPORT int imonlcd_cellwidth (Driver *drvthis); ++MODULE_EXPORT int imonlcd_cellheight (Driver *drvthis); ++MODULE_EXPORT void imonlcd_clear (Driver *drvthis); ++MODULE_EXPORT void imonlcd_flush (Driver *drvthis); ++MODULE_EXPORT void imonlcd_string (Driver *drvthis, int x, int y, const char string[]); ++MODULE_EXPORT void imonlcd_chr (Driver *drvthis, int x, int y, char c); ++MODULE_EXPORT const char *imonlcd_get_info (Driver *drvthis); ++MODULE_EXPORT void imonlcd_vbar (Driver *drvthis, int x, int y, int len, int promille, int options); ++MODULE_EXPORT void imonlcd_hbar (Driver *drvthis, int x, int y, int len, int promille, int options); ++MODULE_EXPORT void imonlcd_num (Driver *drvthis, int x, int num); ++MODULE_EXPORT void imonlcd_output (Driver *drvthis, int state); ++MODULE_EXPORT int imonlcd_set_contrast (Driver *drvthis, int promille); ++MODULE_EXPORT int imonlcd_get_contrast (Driver *drvthis); ++MODULE_EXPORT void imonlcd_backlight(Driver *drvthis, int on); ++ ++/** ++ * These are not supported by the iMON LCD module ++ */ ++//MODULE_EXPORT int imonlcd_get_free_chars (Driver *drvthis); ++//MODULE_EXPORT void imonlcd_set_char (Driver *drvthis, int n, char *dat); ++//MODULE_EXPORT int imonlcd_icon (Driver *drvthis, int x, int y, int icon); ++ ++#endif ++ +diff -Naurp lcdproc-0.5.2/server/drivers/Makefile.am lcdproc-0.5.2.imonlcd/server/drivers/Makefile.am +--- lcdproc-0.5.2/server/drivers/Makefile.am 2007-04-14 10:39:53.000000000 -0400 ++++ lcdproc-0.5.2.imonlcd/server/drivers/Makefile.am 2008-11-07 10:32:58.927066724 -0500 +@@ -19,7 +19,7 @@ AM_LDFLAGS = @LDSHARED@ + #LIBS = + + pkglib_PROGRAMS = @DRIVERS@ +-EXTRA_PROGRAMS = bayrad CFontz CFontz633 CFontzPacket curses CwLnx ea65 EyeboxOne g15 glcdlib glk hd44780 icp_a106 imon IOWarrior irman joy lb216 lcdm001 lcterm lirc MD8800 ms6931 mtc_s16209x MtxOrb NoritakeVFD picolcd pyramid sed1330 sed1520 serialPOS serialVFD stv5730 svga t6963 text tyan sli ula200 xosd ++EXTRA_PROGRAMS = bayrad CFontz CFontz633 CFontzPacket curses CwLnx ea65 EyeboxOne g15 glcdlib glk hd44780 icp_a106 imon imonlcd imonlcd2 IOWarrior irman joy lb216 lcdm001 lcterm lirc MD8800 ms6931 mtc_s16209x MtxOrb NoritakeVFD picolcd pyramid sed1330 sed1520 serialPOS serialVFD stv5730 svga t6963 text tyan sli ula200 xosd + noinst_LIBRARIES = libLCD.a libbignum.a + + IOWarrior_CFLAGS = @libusb_cflags@ $(AM_CFLAGS) +@@ -37,6 +37,8 @@ hd44780_LDADD = libLCD.a @HD44780_D + hd44780_DEPENDENCIES = @HD44780_DRIVERS@ + icp_a106_LDADD = libLCD.a + imon_LDADD = libLCD.a ++imonlcd_LDADD = libLCD.a ++imonlcd2_LDADD = libLCD.a + IOWarrior_LDADD = @libusb_libs@ libLCD.a libbignum.a + irman_LDADD = @LIBIRMAN@ + lcterm_LDADD = libLCD.a +@@ -75,6 +77,8 @@ EXTRA_hd44780_SOURCES = hd44780-4bit.c h + + icp_a106_SOURCES = lcd.h lcd_lib.h icp_a106.c icp_a106.h report.h + imon_SOURCES = lcd.h lcd_lib.h imon.h imon.c report.h ++imonlcd_SOURCES = lcd.h lcd_lib.h imonlcd.h imonlcd.c report.h ++imonlcd2_SOURCES = lcd.h lcd_lib.h imonlcd.h imonlcd2.c report.h + IOWarrior_SOURCES = lcd.h lcd_lib.h hd44780-charmap.h IOWarrior.c IOWarrior.h report.h adv_bignum.h + irman_SOURCES = lcd.h irmanin.c irmanin.h report.h + joy_SOURCES = lcd.h joy.c joy.h port.h report.h +--- lcdproc-0.5.2/LCDd.conf 2007-04-14 10:41:51.000000000 -0400 ++++ lcdproc-0.5.2.imonlcd/LCDd.conf 2008-11-07 12:01:18.193816869 -0500 +@@ -37,7 +37,7 @@ + # + # The following drivers are supported: + # bayrad, CFontz, CFontz633, CFontzPacket, curses, CwLnx, ea65, +-# EyeboxOne, g15, glcdlib, glk, hd44780, icp_a106, imon, IOWarrior, ++# EyeboxOne, g15, glcdlib, glk, hd44780, icp_a106, imon, imonlcd, imonlcd2, IOWarrior, + # irman, joy, lb216, lcdm001, lcterm, lirc, MD8800, ms6931, mtc_s16209x, + # MtxOrb, NoritakeVFD, picolcd, pyramid, sed1330, sed1520, serialPOS, + # serialVFD, sli, stv5730, svga, t6963, text, tyan, ula200, xosd +@@ -508,7 +508,7 @@ Size=20x4 + + + +-## Soundgraph/Ahanix/Silverstone/Uneed/Accent iMON driver ## ++## Soundgraph/Ahanix/Silverstone/Uneed/Accent iMON VFD driver ## + [imon] + + # select the device to use +@@ -517,6 +517,15 @@ Device=/dev/lcd0 + # display dimensions + Size=16x2 + ++## Soundgraph first-gen lcd device ## ++[imonlcd] ++Device=/dev/lcd0 ++Contrast=200 ++ ++## Soundgraph second-gen lcd device ## ++[imonlcd2] ++Device=/dev/lcd0 ++Contrast=200 + + + ## IrMan driver ## diff --git a/lcdproc-0.5.2-initscripts.patch b/lcdproc-0.5.2-initscripts.patch index 8baa9d0..79e60b9 100644 --- a/lcdproc-0.5.2-initscripts.patch +++ b/lcdproc-0.5.2-initscripts.patch @@ -1,26 +1,27 @@ -diff -up lcdproc-0.5.2/scripts/init-lcdproc.LSB.in.initscripts lcdproc-0.5.2/scripts/init-lcdproc.LSB.in ---- lcdproc-0.5.2/scripts/init-lcdproc.LSB.in.initscripts 2007-04-14 16:41:20.000000000 +0200 -+++ lcdproc-0.5.2/scripts/init-lcdproc.LSB.in 2008-07-08 16:32:30.000000000 +0200 +diff -Naurp lcdproc-0.5.2.orig/scripts/init-LCDd.LSB.in lcdproc-0.5.2/scripts/init-LCDd.LSB.in +--- lcdproc-0.5.2.orig/scripts/init-LCDd.LSB.in 2007-04-14 10:41:20.000000000 -0400 ++++ lcdproc-0.5.2/scripts/init-LCDd.LSB.in 2008-11-07 12:07:34.597854268 -0500 @@ -4,6 +4,7 @@ - # Provides: lcdproc + # Provides: LCDd # Required-Start: $syslog $local_fs $network $remote_fs # Required-Stop: $syslog $local_fs $network $remote_fs -+# Should-Start: LCDd ++# Should-Start: udev # Default-Start: 2 3 4 5 # Default-Stop: S 0 1 6 - # Short-Description: LCDproc system status information viewer -@@ -23,8 +24,9 @@ PATH=/sbin:/bin:/usr/sbin:/usr/bin - NAME=lcdproc - DAEMON=${bindir}/$NAME - DESC="LCDproc system status monitor" + # Short-Description: LCDproc Server Daemon +@@ -23,8 +24,10 @@ PATH=/sbin:/bin:/usr/sbin:/usr/bin + NAME=LCDd + DAEMON=${sbindir}/$NAME + DESC="LCDproc display server daemon" -DEFAULTS=/etc/default/$NAME +DEFAULTS=@sysconfdir@/${NAME} START=yes +RETVAL=0 ++ # Source defaults file; edit that file to configure this script. if [ -e "${DEFAULTS}" ]; then -@@ -40,29 +42,39 @@ fi +@@ -40,29 +43,39 @@ fi test -x $DAEMON || exit 5 # load LSB 3.x init functions @@ -38,9 +39,10 @@ diff -up lcdproc-0.5.2/scripts/init-lcdproc.LSB.in.initscripts lcdproc-0.5.2/scr case "$1" in start) - log_daemon_msg "Starting $DESC" "$NAME" -+ echo -n $"Starting $DESC $NAME :" - start_daemon $DAEMON $OPTIONS +- start_daemon $DAEMON $OPTIONS - log_end_msg $? ++ echo -n $"Starting $DESC $NAME :" ++ daemon $DAEMON $OPTIONS + RETVAL=$? + echo ;; @@ -67,30 +69,29 @@ diff -up lcdproc-0.5.2/scripts/init-lcdproc.LSB.in.initscripts lcdproc-0.5.2/scr -exit 0 +exit $RETVAL -diff -up lcdproc-0.5.2/scripts/init-LCDd.LSB.in.initscripts lcdproc-0.5.2/scripts/init-LCDd.LSB.in ---- lcdproc-0.5.2/scripts/init-LCDd.LSB.in.initscripts 2007-04-14 16:41:20.000000000 +0200 -+++ lcdproc-0.5.2/scripts/init-LCDd.LSB.in 2008-07-08 16:32:22.000000000 +0200 +diff -Naurp lcdproc-0.5.2.orig/scripts/init-lcdproc.LSB.in lcdproc-0.5.2/scripts/init-lcdproc.LSB.in +--- lcdproc-0.5.2.orig/scripts/init-lcdproc.LSB.in 2007-04-14 10:41:20.000000000 -0400 ++++ lcdproc-0.5.2/scripts/init-lcdproc.LSB.in 2008-11-07 12:06:30.333851207 -0500 @@ -4,6 +4,7 @@ - # Provides: LCDd + # Provides: lcdproc # Required-Start: $syslog $local_fs $network $remote_fs # Required-Stop: $syslog $local_fs $network $remote_fs -+# Should-Start: udev ++# Should-Start: LCDd # Default-Start: 2 3 4 5 # Default-Stop: S 0 1 6 - # Short-Description: LCDproc Server Daemon -@@ -23,8 +24,10 @@ PATH=/sbin:/bin:/usr/sbin:/usr/bin - NAME=LCDd - DAEMON=${sbindir}/$NAME - DESC="LCDproc display server daemon" + # Short-Description: LCDproc system status information viewer +@@ -23,8 +24,9 @@ PATH=/sbin:/bin:/usr/sbin:/usr/bin + NAME=lcdproc + DAEMON=${bindir}/$NAME + DESC="LCDproc system status monitor" -DEFAULTS=/etc/default/$NAME +DEFAULTS=@sysconfdir@/${NAME} START=yes +RETVAL=0 -+ # Source defaults file; edit that file to configure this script. if [ -e "${DEFAULTS}" ]; then -@@ -40,29 +43,39 @@ fi +@@ -40,29 +42,39 @@ fi test -x $DAEMON || exit 5 # load LSB 3.x init functions @@ -108,9 +109,10 @@ diff -up lcdproc-0.5.2/scripts/init-LCDd.LSB.in.initscripts lcdproc-0.5.2/script case "$1" in start) - log_daemon_msg "Starting $DESC" "$NAME" -+ echo -n $"Starting $DESC $NAME :" - start_daemon $DAEMON $OPTIONS +- start_daemon $DAEMON $OPTIONS - log_end_msg $? ++ echo -n $"Starting $DESC $NAME :" ++ daemon $DAEMON $OPTIONS + RETVAL=$? + echo ;; diff --git a/lcdproc.spec b/lcdproc.spec index 8e742c1..4183234 100644 --- a/lcdproc.spec +++ b/lcdproc.spec @@ -1,13 +1,14 @@ Summary: LCDproc displays real-time system information on a 20x4 backlit LCD -Name: lcdproc +Name: lcdproc Version: 0.5.2 -Release: 6%{?dist} +Release: 7%{?dist} License: GPLv2 URL: http://lcdproc.omnipotent.net -Group: System Environment/Libraries +Group: System Environment/Libraries Source0: http://downloads.sourceforge.net/%{name}/%{name}-%{version}.tar.gz Patch0: lcdproc-0.5.2-initscripts.patch Patch1: lcdproc-0.5.2-memset_swp.patch +Patch2: lcdproc-0.5.2-imonlcd.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: doxygen @@ -40,24 +41,28 @@ Requires(postun): /sbin/chkconfig %description LCDproc is a client/server suite inclduding drivers for all kinds of nifty LCD displays. The server supports several -serial devices: Matrix Orbital, Crystal Fontz, Bayrad, LB216, -LCDM001 (kernelconcepts.de), Wirz-SLI and PIC-an-LCD; and some -devices connected to the LPT port: HD44780, STV5730, T6963, -SED1520 and SED1330. Various clients are available that display -things like CPU load, system load, memory usage, uptime, and a lot more. -See also http://lcdproc.omnipotent.net. +serial devices: Matrix Orbital, Crystal Fontz, Bayrad, LB216, +LCDM001 (kernelconcepts.de), Wirz-SLI and PIC-an-LCD; and some +devices connected to the LPT port: HD44780, STV5730, T6963, +SED1520 and SED1330. Various clients are available that display +things like CPU load, system load, memory usage, uptime, and a lot more. +See also http://lcdproc.omnipotent.net. %prep %setup -q -%patch0 -p1 -b .initscripts +#patch0 -p1 -b .initscripts %patch1 -p1 -b .memset_swp +%patch2 -p1 -b .imonlcd chmod 644 server/drivers/timing.h sed -i -e 's|server/drivers|%{_libdir}/lcdproc|' LCDd.conf touch -r TODO LCDd.conf %build +# run aclocal and automake to pick up the imon lcd additions +aclocal +automake %configure \ --sysconfdir=%{_sysconfdir}/sysconfig/%{name} \ --enable-libusb \ @@ -70,7 +75,7 @@ touch -r TODO LCDd.conf --with-lcdport=13666 sed -i -e 's|-L/usr/lib|-L%{_libdir}|g' Makefile - + make CFLAGS="$RPM_OPT_FLAGS" %{?_smp_mflags} @@ -96,7 +101,7 @@ install -pm 0755 scripts/init-lcdproc.LSB $RPM_BUILD_ROOT%{_initrddir}/lcdproc %post if [ $1 -eq 1 ]; then # Add init script but don't start it - /sbin/chkconfig --add LCDd + /sbin/chkconfig --add LCDd /sbin/chkconfig --add lcdproc ||: fi @@ -130,6 +135,10 @@ rm -rf $RPM_BUILD_ROOT __doc %changelog +* Fri Nov 07 2008 Jarod Wilson - 0.5.2-7 +- Add SoundGraph iMon and Antec Veris LCD device support +- Replace start_daemon w/daemon in initscripts (#468611) + * Tue Jul 8 2008 kwizart < kwizart at gmail.com > - 0.5.2-6 - Add BR on Fedora > 9 : docbook-dtds @@ -146,7 +155,7 @@ rm -rf $RPM_BUILD_ROOT __doc * Sun Aug 12 2007 kwizart < kwizart at gmail.com > 0.5.2-2 - Fix memset swap from djones advice - License is GPLv2 -- Fix #246971 +- Fix #246971 * Sat May 19 2007 kwizart < kwizart at gmail.com > 0.5.2-1 - Update to 0.5.2