diff --git a/.gitignore b/.gitignore index ff1d16f..e206406 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,7 @@ lcdproc-0.5.2.tar.gz +lcdproc-0.5.3.tar.gz +/lcdproc-0.5.4.tar.gz +/lcdproc-0.5.6.tar.gz +/lcdproc-0.5.7.tar.gz +/lcdproc-781b311.tar.gz +/lcdproc-5c21e8c.tar.gz diff --git a/0001-server-drivers-g15-Add-support-for-the-LCD-on-Logite.patch b/0001-server-drivers-g15-Add-support-for-the-LCD-on-Logite.patch new file mode 100644 index 0000000..870fc04 --- /dev/null +++ b/0001-server-drivers-g15-Add-support-for-the-LCD-on-Logite.patch @@ -0,0 +1,33 @@ +From 1c6be22c5eeea9a7f83192153b282b6002b89923 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 12 Apr 2021 22:44:06 +0200 +Subject: [PATCH] server/drivers/g15: Add support for the LCD on Logitech Z-10 + speakers + +The LCD on Logitech Z-10 speakers uses the exact same protocol as on +the g15 keyboards, add the USB-id + HID-descriptor header of the +USB-intf. for the LCD. + +Signed-off-by: Hans de Goede +--- + server/drivers/g15.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/server/drivers/g15.c b/server/drivers/g15.c +index 154e253..48f5fe5 100644 +--- a/server/drivers/g15.c ++++ b/server/drivers/g15.c +@@ -90,6 +90,10 @@ static const struct lib_hidraw_id hidraw_ids[] = { + { { BUS_USB, 0x046d, 0xc22e }, + { 0x05, 0x0c, 0x09, 0x01, 0xa1, 0x01, 0x85, 0x02, + 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x07 } }, ++ /* Z-10 */ ++ { { BUS_USB, 0x046d, 0x0a07 }, ++ { 0x06, 0x00, 0xff, 0x09, 0x00, 0xa1, 0x01, 0x15, ++ 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x08 } }, + /* Terminator */ + {} + }; +-- +2.31.1 + diff --git a/90-lcdproc.rules b/90-lcdproc.rules new file mode 100644 index 0000000..e69e4a8 --- /dev/null +++ b/90-lcdproc.rules @@ -0,0 +1,57 @@ +# lcdproc udev rules + +ACTION!="add", GOTO="lcdproc_end" + +### 1. Check for USB LCD panels which we access directly through libusb ### + +# Till Harbaum's LCD2USB device +SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c630", GOTO="lcdproc_lcd_found" + +### 2. Check for HID LCD panels accessed through their hidraw device ### + +# Logitech MX5000 keyboard Bluetooth and USB (BT receiver as HID-proxy) modes +DEVPATH=="*/0003:046D:B305.*/hidraw/hidraw*", GOTO="lcdproc_lcd_found" +DEVPATH=="*/0005:046D:B305.*/hidraw/hidraw*", GOTO="lcdproc_lcd_found" + +# Logitech MX5500 keyboard Bluetooth and USB (BT receiver as HID-proxy) modes +DEVPATH=="*/0003:046D:B30B.*/hidraw/hidraw*", GOTO="lcdproc_lcd_found" +DEVPATH=="*/0005:046D:B30B.*/hidraw/hidraw*", GOTO="lcdproc_lcd_found" + +# Logitech G15 gaming keyboard +DEVPATH=="*/0003:046D:C222.*/hidraw/hidraw*", GOTO="lcdproc_lcd_found" + +# Logitech G15 v2 gaming keyboard +DEVPATH=="*/0003:046D:C227.*/hidraw/hidraw*", GOTO="lcdproc_lcd_found" + +# Logitech G510 gaming keyboard, note we only want interface 1 +DEVPATH=="*/0003:046D:C22D.*/hidraw/hidraw*", ATTRS{bInterfaceNumber}=="01", GOTO="lcdproc_lcd_found" +DEVPATH=="*/0003:046D:C22E.*/hidraw/hidraw*", ATTRS{bInterfaceNumber}=="01", GOTO="lcdproc_lcd_found" + +# Logitech Z-10 speakers with G15 style LCD screen, note we only want interface 2 +DEVPATH=="*/0003:046D:0A07.*/hidraw/hidraw*", ATTRS{bInterfaceNumber}=="02", GOTO="lcdproc_lcd_found" + +### 3. Check for input devices for LCD menu buttons ### + +# Logitech G15, G15 v2 and G510 Gaming and LCD menu keys +SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="Logitech Gaming Keyboard Gaming Keys", GOTO="lcdproc_input_found" +# Logitech MX5000 keyboard connected over Bluetooth +SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="Logitech MX5000 Keyboard", GOTO="lcdproc_input_found" +# Logitech MX5000 keyboard connected through its receiver in USB HID proxy mode +SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="Logitech Wireless Keyboard PID:b305", GOTO="lcdproc_input_found" +# Logitech Z-10 speakers LCD menu keys +SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="Logitech Z-10 LCD Menu Keys", GOTO="lcdproc_input_found" + + +### Nothing found, leave ### +GOTO="lcdproc_end" + + +LABEL="lcdproc_lcd_found" +TAG+="systemd" +ENV{SYSTEMD_WANTS}+="lcdproc.target" + +LABEL="lcdproc_input_found" +# Grant rw permission to the lcdd group using acl(5), for both LCD and input devs +RUN+="/usr/bin/sh -c '/usr/bin/setfacl -m g:lcdd:rw %E{DEVNAME} 2>/dev/null || :'" + +LABEL="lcdproc_end" diff --git a/LCDd-hwdetect.service b/LCDd-hwdetect.service new file mode 100644 index 0000000..cfc0779 --- /dev/null +++ b/LCDd-hwdetect.service @@ -0,0 +1,9 @@ +[Unit] +Description=LCDd hardware detection Service +After=syslog.target +Before=LCDd.service +ConditionPathExists=!/etc/lcdproc/LCDd.conf + +[Service] +Type=oneshot +ExecStart=/usr/sbin/LCDd-hwdetect diff --git a/LCDd-hwdetect.sh b/LCDd-hwdetect.sh new file mode 100644 index 0000000..7869a9f --- /dev/null +++ b/LCDd-hwdetect.sh @@ -0,0 +1,179 @@ +#!/bin/bash + +lcd_device="" +extra_lcd_devices="" +lcd_driver="" +input_name="" + +add_device () { + if [ -z "$lcd_device" ]; then + lcd_device="$1" + lcd_driver="$2" + input_name="$3" + elif [ "$1" != "$lcd_device" ]; then + extra_lcd_devices="$extra_lcd_devices $1" + fi +} + +if [ -f /etc/lcdproc/LCDd.conf ]; then + echo "/etc/lcdproc/LCDd.conf already exists" + echo "If you want LCDd-hwdetect to create a new config move it out of the way" + exit 1 +fi + +# USB devices where we use raw USB access (through libusb) +if [ -d /sys/bus/hid/devices ]; then + for i in $(cat /sys/bus/usb/devices/*/modalias); do + case "$i" in + usb:v0403pC630d*) + add_device "lcd2usb" "hd44780" + ;; + esac + done +fi + +# HID devices +if [ -d /sys/bus/hid/devices ]; then + pushd /sys/bus/hid/devices > /dev/null + for i in $(ls); do + case "$i" in + # Logitech MX5000 connected through its receiver in USB HID proxy mode + 0003:046D:B305.*) + add_device "mx5000" "mx5000" "Logitech Wireless Keyboard PID:b305" + ;; + # Logitech MX5000 connected over bluetooth + 0005:046D:B305.*) + add_device "mx5000" "mx5000" "Logitech MX5000 Keyboard" + ;; + # Logitech MX5500 connected through its receiver in USB HID proxy mode + # Note the MX5500's LCD menu buttons are not accessible by the host + 0003:046D:B30B.*) + add_device "mx5500" "mx5000" + ;; + # Logitech MX5500 connected over bluetooth, no usable LCD menu btns + 0005:046D:B30B.*) + add_device "mx5500" "mx5000" + ;; + # Logitech G15 + 0003:046D:C222.*) + add_device "g15" "g15" "Logitech Gaming Keyboard Gaming Keys" + ;; + # Logitech G15 v2 + 0003:046D:C227.*) + add_device "g15-v2" "g15" "Logitech Gaming Keyboard Gaming Keys" + ;; + # Logitech G510 without a headset plugged in, without USB audio intf. + 0003:046D:C22D.*) + add_device "g510" "g15" "Logitech Gaming Keyboard Gaming Keys" + ;; + # Logitech G510 with a headset plugged, with extra USB audio intf. + 0003:046D:C22E.*) + add_device "g510" "g15" "Logitech Gaming Keyboard Gaming Keys" + ;; + # Logitech Z10 speakers + 0003:046D:0A07.*) + add_device "z-10" "g15" "Logitech Z-10 LCD Menu Keys" + ;; + esac + done + popd > /dev/null +fi + +if [ -z "$lcd_device" ]; then + echo "No known LCD devices detected" + exit 1 +fi + +echo "Detected $lcd_device LCD device" +if [ -n "$extra_lcd_devices" ]; then + echo "Detected extra LCD devices:$extra_lcd_devices" + echo "Multiple devices are not supported, these extra LCD devices will be ignored" +fi + +# Write LCDd.conf for the found device, also: +# Disable the server screen in the rotation of screens +# Disable the annoying blinking heartbeat by default +# Disable title scrolling (set the speed to 0) most keyboard LCDs have +# a low refresh rate making the scrolling look terrible +cat /etc/lcdproc/LCDd.conf.example | \ + sed -e "s/^Driver=curses/Driver=$lcd_driver/" \ + -e "s/#ServerScreen=no/ServerScreen=no/" \ + -e "s/#Heartbeat=open/Heartbeat=off/" \ + -e "s/#TitleSpeed=10/TitleSpeed=0/" > \ + /etc/lcdproc/LCDd.conf + +# Add input-device config if specified +# Also set prev / next screen to up/down since non of the supported devices +# has enough buttons to create mappings for both left and right +# And uncomment the LeftKey and RightKey assignments so that they work +# when they are available +if [ "$input_name" ]; then + sed -i -e "s|Driver=$lcd_driver|Driver=$lcd_driver\nDriver=linux_input|" \ + -e "s|PrevScreenKey=Left|PrevScreenKey=Up|" \ + -e "s|NextScreenKey=Right|NextScreenKey=Down|" \ + -e "s|# Device=/dev/input/event0|Device=\"$input_name\"|" \ + -e "s|#LeftKey=Left|LeftKey=Left|" \ + -e "s|#RightKey=Right|RightKey=Right|" \ + /etc/lcdproc/LCDd.conf +fi + +# Device specific config bits +case "$lcd_device" in + "lcd2usb") + # This assume a 16x2 display as the lcd2usb board is typically sold with + # this display on aliexpress / banggood. There are only 2 buttons making + # menu navigation impossible. We map button 1 to toggling auto-rotate on/off + # and button 2 to manually switching to the next screen + sed -i -e 's/ConnectionType=4bit/ConnectionType=lcd2usb/' \ + -e 's/Keypad=no/Keypad=yes/' \ + -e 's/#Contrast=0/Contrast=600/' \ + -e 's/Size=20x4/Size=16x2/g' \ + -e 's/KeyMatrix_4_1=Enter/# Button config for lcd2usb, not enough buttons for menu navigation/' \ + -e 's/KeyMatrix_4_2=Up/# so we only do screen rotation control/' \ + -e 's/KeyMatrix_4_3=Down/KeyDirect_1=Enter/' \ + -e 's/KeyMatrix_4_4=Escape/KeyDirect_2=Right/' \ + /etc/lcdproc/LCDd.conf + ;; + "g15"|"g15-2"|"g510"|"z-10") + sed -i -e "s/# specify a non-default key map/# Keymap for the G15's 5 LCD-menu buttons/" \ + -e 's/#key=1,Escape/key=0x2b8,Escape/' \ + -e 's/#key=28,Enter/key=0x2b9,Left/' \ + -e 's/#key=96,Enter/key=0x2ba,Up/' \ + -e 's/#key=105,Left/key=0x2bb,Down/' \ + -e 's/#key=106,Right/key=0x2bc,Enter/' \ + -e 's/#key=103,Up//' \ + -e 's/#key=108,Down//' \ + /etc/lcdproc/LCDd.conf + ;; + "mx5000") + sed -i -e "s/# specify a non-default key map/# Keymap for the MX5000's 4 LCD-menu buttons/" \ + -e 's/#key=1,Escape/key=0x2b8,Escape/' \ + -e 's/#key=28,Enter/key=0x2b9,Up/' \ + -e 's/#key=96,Enter/key=0x2ba,Down/' \ + -e 's/#key=105,Left/key=0x2bb,Enter/' \ + -e 's/#key=106,Right//' \ + -e 's/#key=103,Up//' \ + -e 's/#key=108,Down//' \ + /etc/lcdproc/LCDd.conf + ;; +esac + +echo "Wrote /etc/lcdproc/LCDd.conf for $lcd_device using $lcd_driver driver" + +# If there is no lcdproc.conf, generate one from the example file +if [ -f /etc/lcdproc/lcdproc.conf ]; then + exit 0 +fi + +install -p -m 644 /etc/lcdproc/lcdproc.conf.example /etc/lcdproc/lcdproc.conf + +# Device specific config bits +case "$lcd_device" in + "mx5000"|"mx5500") + # The mx5000 and mx5500 do not do vertical-bars, disable load screen + sed -i -e '73s/Active=True/Active=false/' \ + /etc/lcdproc/lcdproc.conf + ;; +esac + +echo "Wrote /etc/lcdproc/lcdproc.conf" diff --git a/LCDd.service b/LCDd.service new file mode 100644 index 0000000..b77d2e2 --- /dev/null +++ b/LCDd.service @@ -0,0 +1,12 @@ +[Unit] +Description=LCDd Service +After=syslog.target + +[Service] +Type=forking +ExecStart=/usr/sbin/LCDd -c /etc/lcdproc/LCDd.conf +User=root +Group=lcdd + +[Install] +WantedBy=multi-user.target diff --git a/lcdproc-0.5.2-imonlcd.patch b/lcdproc-0.5.2-imonlcd.patch deleted file mode 100644 index 2628aac..0000000 --- a/lcdproc-0.5.2-imonlcd.patch +++ /dev/null @@ -1,2859 +0,0 @@ -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 deleted file mode 100644 index fe83c45..0000000 --- a/lcdproc-0.5.2-initscripts.patch +++ /dev/null @@ -1,310 +0,0 @@ -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 2009-05-13 17:14:25.000000000 +0200 -@@ -1,10 +1,18 @@ - #! /bin/sh -+# -+# chkconfig: - 70 21 -+# description: LCDd(8) is the LCDproc server used for displaying text and other data to LCDs. \ -+# Apart from the main client lcdproc(1) there are various clients. \ -+# See http://lcdproc.omnipotent.net for details. -+# processname: LCDd -+# -+# config: /etc/sysconfig/lcdproc/LCDd.conf - --#### BEGIN INIT INFO -+### BEGIN INIT INFO - # Provides: LCDd - # Required-Start: $syslog $local_fs $network $remote_fs - # Required-Stop: $syslog $local_fs $network $remote_fs --# Default-Start: 2 3 4 5 -+# Default-Start: - # Default-Stop: S 0 1 6 - # Short-Description: LCDproc Server Daemon - # Description: LSB init script for LCDd, the display -@@ -12,57 +20,92 @@ - ### END INIT INFO - - --# local variables --prefix=@prefix@ --exec_prefix=@exec_prefix@ --bindir=@bindir@ --sbindir=@sbindir@ --etc=@sysconfdir@ -- --PATH=/sbin:/bin:/usr/sbin:/usr/bin --NAME=LCDd --DAEMON=${sbindir}/$NAME --DESC="LCDproc display server daemon" --DEFAULTS=/etc/default/$NAME --START=yes -- --# Source defaults file; edit that file to configure this script. --if [ -e "${DEFAULTS}" ]; then -- . "${DEFAULTS}" -+prog=LCDd -+lockfile=/var/lock/subsys/$prog -+configfile=@sysconfdir@/$prog.conf -+RETVAL=0 -+ -+ -+# load LSB 3.x init functions -+if [ -e /lib/lsb/init-functions ]; then -+ . /lib/lsb/init-functions - fi - --# If we're not to start the daemon, simply exit --if [ "${START}" != "yes" ]; then -- exit 0 -+# Source function library. -+if [ -e /etc/rc.d/init.d/functions ]; then -+ . /etc/rc.d/init.d/functions - fi - --# installation check --test -x $DAEMON || exit 5 -+# check that non-default config file exists. -+ [ -f $configfile ] || exit 6 - --# load LSB 3.x init functions --. /lib/lsb/init-functions -+ -+start() { -+ echo -n $"Starting $prog services: " -+ daemon $prog -c $configfile -+ RETVAL=$? -+ echo -+ [ $RETVAL -eq 0 ] && touch $lockfile || \ -+ RETVAL=1 -+ return $RETVAL -+} -+ -+stop() { -+ echo -n $"Shutting down $prog services: " -+ killproc $prog -+ RETVAL=$? -+ echo -+ [ $RETVAL -eq 0 ] && rm -f $lockfile -+ return $RETVAL -+} -+ -+reload() { -+ echo -n $"Reloading $prog file: " -+ killproc $prog -HUP -+ RETVAL=$? -+ echo -+ return $RETVAL -+} -+ -+rhstatus() { -+ status $prog -+ return $? -+} -+ -+ -+# Allow status as non-root. -+if [ "$1" = status ]; then -+ rhstatus -+ exit $? -+fi - - - case "$1" in - start) -- log_daemon_msg "Starting $DESC" "$NAME" -- start_daemon $DAEMON $OPTIONS -- log_end_msg $? -+ start - ;; - stop) -- log_daemon_msg "Stopping $DESC" "$NAME" -- killproc $DAEMON -- log_end_msg $? -- ;; -- restart|reload|force-reload) -- $0 stop -- sleep 1 -- $0 start -+ stop -+ ;; -+ status) -+ status $prog -+ ;; -+ restart|force-reload) -+ stop -+ start -+ ;; -+ try-restart|condrestart) -+ if [ -f $lockfile ]; then -+ stop -+ start -+ fi -+ ;; -+ reload) -+ reload - ;; - *) -- echo "Usage: $0 {start|stop|restart|reload|force-reload}" >&2 -+ echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}" - exit 2 -- ;; - esac - --exit 0 -+exit $RETVAL -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 2009-05-13 10:37:32.000000000 +0200 -@@ -1,10 +1,19 @@ - #! /bin/sh -+# -+# chkconfig: - 71 20 -+# description: LCDd(8) is the LCDproc server used for displaying text and other data to LCDs. \ -+# Apart from the main client lcdproc(1) there are various clients. \ -+# See http://lcdproc.omnipotent.net for details. -+# processname: lcdproc -+# -+# config: /etc/sysconfig/lcdproc/lcdproc.conf - --#### BEGIN INIT INFO -+### BEGIN INIT INFO - # Provides: lcdproc - # Required-Start: $syslog $local_fs $network $remote_fs - # Required-Stop: $syslog $local_fs $network $remote_fs --# Default-Start: 2 3 4 5 -+# Should-Start: LCDd -+# Default-Start: - # Default-Stop: S 0 1 6 - # Short-Description: LCDproc system status information viewer - # Description: LSB init script for lcdproc, the system -@@ -12,57 +21,91 @@ - ### END INIT INFO - - --# local variables --prefix=@prefix@ --exec_prefix=@exec_prefix@ --bindir=@bindir@ --sbindir=@sbindir@ --etc=@sysconfdir@ -- --PATH=/sbin:/bin:/usr/sbin:/usr/bin --NAME=lcdproc --DAEMON=${bindir}/$NAME --DESC="LCDproc system status monitor" --DEFAULTS=/etc/default/$NAME --START=yes -- --# Source defaults file; edit that file to configure this script. --if [ -e "${DEFAULTS}" ]; then -- . "${DEFAULTS}" -+prog=lcdproc -+lockfile=/var/lock/subsys/$prog -+configfile=@sysconfdir@/$prog.conf -+RETVAL=0 -+ -+# load LSB 3.x init functions -+if [ -e /lib/lsb/init-functions ]; then -+ . /lib/lsb/init-functions - fi - --# If we're not to start the daemon, simply exit --if [ "${START}" != "yes" ]; then -- exit 0 -+# Source function library. -+if [ -e /etc/rc.d/init.d/functions ]; then -+ . /etc/rc.d/init.d/functions - fi - --# installation check --test -x $DAEMON || exit 5 -+# check that non-default config file exists. -+ [ -f $configfile ] || exit 6 - --# load LSB 3.x init functions --. /lib/lsb/init-functions -+ -+start() { -+ echo -n $"Starting $prog services: " -+ daemon $prog -c $configfile -+ RETVAL=$? -+ echo -+ [ $RETVAL -eq 0 ] && touch $lockfile || \ -+ RETVAL=1 -+ return $RETVAL -+} -+ -+stop() { -+ echo -n $"Shutting down $prog services: " -+ killproc $prog -+ RETVAL=$? -+ echo -+ [ $RETVAL -eq 0 ] && rm -f $lockfile -+ return $RETVAL -+} -+ -+reload() { -+ echo -n $"Reloading $prog file: " -+ killproc $prog -HUP -+ RETVAL=$? -+ echo -+ return $RETVAL -+} -+ -+rhstatus() { -+ status $prog -+ return $? -+} -+ -+ -+# Allow status as non-root. -+if [ "$1" = status ]; then -+ rhstatus -+ exit $? -+fi - - - case "$1" in - start) -- log_daemon_msg "Starting $DESC" "$NAME" -- start_daemon $DAEMON $OPTIONS -- log_end_msg $? -+ start - ;; - stop) -- log_daemon_msg "Stopping $DESC" "$NAME" -- killproc $DAEMON -- log_end_msg $? -- ;; -- restart|reload|force-reload) -- $0 stop -- sleep 1 -- $0 start -+ stop -+ ;; -+ status) -+ status $prog -+ ;; -+ restart|force-reload) -+ stop -+ start -+ ;; -+ try-restart|condrestart) -+ if [ -f $lockfile ]; then -+ stop -+ start -+ fi -+ ;; -+ reload) -+ reload - ;; - *) -- echo "Usage: $0 {start|stop|restart|reload|force-reload}" >&2 -+ echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}" - exit 2 -- ;; - esac - --exit 0 -+exit $RETVAL diff --git a/lcdproc-0.5.2-memset_swp.patch b/lcdproc-0.5.2-memset_swp.patch deleted file mode 100644 index 3b36a7a..0000000 --- a/lcdproc-0.5.2-memset_swp.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- lcdproc-0.5.2/server/drivers/pylcd.c.memset_swp 2007-08-12 19:27:34.000000000 +0200 -+++ lcdproc-0.5.2/server/drivers/pylcd.c 2007-08-12 19:42:05.000000000 +0200 -@@ -118,7 +118,7 @@ - - if (zeichen!=0x02) - { -- memset(buffer, MAXCOUNT, 0); -+ memset(buffer, 0, MAXCOUNT); - return False; - } - -@@ -146,7 +146,7 @@ - } - else - { -- memset(buffer, MAXCOUNT, 0); -+ memset(buffer, 0, MAXCOUNT); - return False; - } - } diff --git a/lcdproc-0.5.2-novalidate.patch b/lcdproc-0.5.2-novalidate.patch deleted file mode 100644 index 4223683..0000000 --- a/lcdproc-0.5.2-novalidate.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff -up lcdproc-0.5.2/docs/lcdproc-dev/Makefile.am.novalidate lcdproc-0.5.2/docs/lcdproc-dev/Makefile.am ---- lcdproc-0.5.2/docs/lcdproc-dev/Makefile.am.novalidate 2007-04-14 16:39:53.000000000 +0200 -+++ lcdproc-0.5.2/docs/lcdproc-dev/Makefile.am 2009-04-14 15:28:01.000000000 +0200 -@@ -18,6 +18,6 @@ developerguidedir = $(DESTDIR)$(htmldir) - - install-html-developerguide: $(xmlto) lcdproc-dev.docbook - $(mkinstalldirs) $(developerguidedir) -- $(xmlto) html -o $(developerguidedir) lcdproc-dev.docbook -+ $(xmlto) html -o $(developerguidedir) --skip-validation lcdproc-dev.docbook - - ## EOF -diff -up lcdproc-0.5.2/docs/lcdproc-user/Makefile.am.novalidate lcdproc-0.5.2/docs/lcdproc-user/Makefile.am ---- lcdproc-0.5.2/docs/lcdproc-user/Makefile.am.novalidate 2009-04-14 15:32:24.000000000 +0200 -+++ lcdproc-0.5.2/docs/lcdproc-user/Makefile.am 2009-04-14 15:32:44.000000000 +0200 -@@ -21,6 +21,6 @@ userguidedir = $(DESTDIR)$(htmldir)/user - - install-html-userguide: $(xmlto) lcdproc-user.docbook - $(mkinstalldirs) $(userguidedir) -- $(xmlto) html -o $(userguidedir) lcdproc-user.docbook -+ $(xmlto) html -o $(userguidedir) --skip-validation lcdproc-user.docbook - - ## EOF diff --git a/lcdproc-conf.patch b/lcdproc-conf.patch new file mode 100644 index 0000000..520560a --- /dev/null +++ b/lcdproc-conf.patch @@ -0,0 +1,30 @@ +diff -up lcdproc-0.5.7/clients/lcdproc/lcdproc.conf~ lcdproc-0.5.7/clients/lcdproc/lcdproc.conf +--- lcdproc-0.5.7/clients/lcdproc/lcdproc.conf~ 2014-03-23 11:22:07.000000000 +0100 ++++ lcdproc-0.5.7/clients/lcdproc/lcdproc.conf 2019-06-02 12:44:40.366733461 +0200 +@@ -39,7 +39,7 @@ ShowInvisible=false + + [Iface] + # Show screen +-Active=True ++Active=false + + # Show stats for Interface0 + Interface0=eth0 +@@ -79,7 +79,7 @@ HighLoad=1.3 + + [TimeDate] + # Show screen +-Active=True ++Active=false + # time format [default: %H:%M:%S; legal: see strftime(3)] + TimeFormat="%H:%M:%S" + # date format [default: %x; legal: see strftime(3)] +@@ -130,7 +130,7 @@ Active=false + + [ProcSize] + # Show screen +-Active=false ++Active=True + + + [Disk] diff --git a/lcdproc.rpmlintrc b/lcdproc.rpmlintrc new file mode 100644 index 0000000..f76d24f --- /dev/null +++ b/lcdproc.rpmlintrc @@ -0,0 +1,3 @@ +addFilter("conffile-without-noreplace-flag") +addFilter("no-manual-page-for-binary") +addFilter("incorrect-fsf-address") diff --git a/lcdproc.service b/lcdproc.service new file mode 100644 index 0000000..1b59679 --- /dev/null +++ b/lcdproc.service @@ -0,0 +1,11 @@ +[Unit] +Description=lcdproc Service +After=syslog.target LCDd.service + +[Service] +Type=forking +PIDFile=/run/lcdproc.pid +ExecStart=/usr/bin/lcdproc -c /etc/lcdproc/lcdproc.conf + +[Install] +WantedBy=multi-user.target diff --git a/lcdproc.spec b/lcdproc.spec index a55c70f..9318cb5 100644 --- a/lcdproc.spec +++ b/lcdproc.spec @@ -1,153 +1,368 @@ -Summary: LCDproc displays real-time system information on a 20x4 backlit LCD -Name: lcdproc -Version: 0.5.2 -Release: 12%{?dist} -License: GPLv2 -URL: http://lcdproc.omnipotent.net -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 -Patch3: lcdproc-0.5.2-novalidate.patch -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) +%global commit 5c21e8c75fbab53574275c8007f5af746e333144 +%global commitdate 20210209 +%global shortcommit %(c=%{commit}; echo ${c:0:7}) +Summary: Display real-time system information on a 20x4 back-lit LCD +Name: lcdproc +Version: 0.5.9 +Release: 26.%{commitdate}git%{shortcommit}%{?dist} +# Automatically converted from old format: GPLv2 - review is highly recommended. +License: GPL-2.0-only +URL: http://lcdproc.org +Source0: https://github.com/%{name}/%{name}/archive/%{commit}/%{name}-%{shortcommit}.tar.gz +Source1: lcdproc.service +Source2: lcdproc.target +Source3: LCDd.service +Source4: LCDd-hwdetect.service +Source5: LCDd-hwdetect.sh +Source6: 90-lcdproc.rules +Source7: lcdproc.sysusers +Patch1: 0001-server-drivers-g15-Add-support-for-the-LCD-on-Logite.patch +# lcdconf.conf tweaks: +# 1. Enable ProcSize, this is quite useful to have +# 2. Disable TimeDate, its info is duplicate with the MiniClock and it is ugly +# 3. Disable network interface screen by default, since Fedora uses predictable +# network interface names, having a simple default like Interface0=eth0 does +# not work +Patch99: lcdproc-conf.patch + +BuildRequires: perl-generators +BuildRequires: systemd-rpm-macros BuildRequires: doxygen BuildRequires: graphviz -# necessary for imonlcd patch -BuildRequires: libtool - -BuildRequires: libusb-devel +BuildRequires: freetype-devel +%ifnarch s390 s390x +BuildRequires: libhid-devel +%endif +BuildRequires: libusb1-devel BuildRequires: lirc-devel BuildRequires: ncurses-devel -BuildRequires: nfs-utils-lib-devel BuildRequires: openldap-devel -BuildRequires: pth-devel BuildRequires: xmlto -%if 0%{?fedora} > 9 BuildRequires: docbook-dtds -%endif -BuildRequires: xosd-devel BuildRequires: libX11-devel BuildRequires: libXext-devel +BuildRequires: libftdi-devel +BuildRequires: libg15render-devel +BuildRequires: mx5000tools-devel +BuildRequires: libtool autoconf automake +BuildRequires: gcc make -%ifarch %{ix86} x86_64 -BuildRequires: svgalib-devel -%endif - -Requires(post): /sbin/chkconfig -Requires(postun): /sbin/chkconfig +%{?systemd_requires} %description -LCDproc is a client/server suite inclduding drivers for all +LCDproc is a client/server suite including 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 +LCDM001 (http://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. +things like CPU load, system load, memory usage, up-time, and a lot more. See also http://lcdproc.omnipotent.net. %prep -%setup -q -%patch0 -p1 -b .initscripts -%patch1 -p1 -b .memset_swp -%patch2 -p1 -b .imonlcd -%patch3 -p1 -b .novalidate -chmod 644 server/drivers/timing.h - +%autosetup -p1 -n %{name}-%{commit} +# Fixup DriverPath sed -i -e 's|server/drivers|%{_libdir}/lcdproc|' LCDd.conf touch -r TODO LCDd.conf + %build -# run autoreconf to pick up the imon lcd additions -# liboolize to refresh libtool -autoreconf -f -i -libtoolize --force +# This package has a configure test which uses ASMs, but does not link the +# resultant .o files. As such the ASM test is always successful in a LTO +# build. We can force code generation with the -ffat-lto-objects to make +# the test work as expected. +# +# -ffat-lto-objects is the default for F33, but will not be for F34, so we +# make it explicit here. +%define _lto_cflags -flto=auto -ffat-lto-objects + +autoreconf -vif %configure \ - --sysconfdir=%{_sysconfdir}/sysconfig/%{name} \ + --sysconfdir=%{_sysconfdir}/%{name} \ --enable-libusb \ - --enable-ldap \ --enable-drivers=all \ - --enable-permissive-menu-goto \ --enable-lcdproc-menus \ --enable-stat-nfs \ --enable-stat-smbfs \ - --with-lcdport=13666 - -make %{?_smp_mflags} + --with-lcdport=13666 \ + --with-pidfile-dir=/run +%make_build %install -rm -rf $RPM_BUILD_ROOT __doc -make install DESTDIR=$RPM_BUILD_ROOT INSTALL="install -p" -make install-html-guides DESTDIR=$RPM_BUILD_ROOT INSTALL="install -p" +%make_install INSTALL="install -p" +# remove non useful (and not "lcd" prefixed) perl example scripts +rm $RPM_BUILD_ROOT%{_bindir}/fortune.pl +rm $RPM_BUILD_ROOT%{_bindir}/iosock.pl +rm $RPM_BUILD_ROOT%{_bindir}/tail.pl +rm $RPM_BUILD_ROOT%{_bindir}/x11amp.pl -# Fix docs -mkdir -p __doc/developer-guide -mkdir -p __doc/user-guide -install -pm 0644 $RPM_BUILD_ROOT%{_datadir}/doc/lcdproc/user-guide/* __doc/user-guide -install -pm 0644 $RPM_BUILD_ROOT%{_datadir}/doc/lcdproc/developer-guide/* __doc/developer-guide -rm -rf $RPM_BUILD_ROOT%{_datadir}/doc +# docs +make install-html-guides DESTDIR=$RPM_BUILD_ROOT INSTALL="install -p" +rm $RPM_BUILD_ROOT%{_docdir}/%{name}/*-guide/*.proc +install -pm 0644 CREDITS.md ChangeLog.md README.md \ + $RPM_BUILD_ROOT%{_docdir}/%{name} # init -install -d $RPM_BUILD_ROOT%{_initrddir} -install -pm 0755 scripts/init-LCDd.LSB $RPM_BUILD_ROOT%{_initrddir}/LCDd -install -pm 0755 scripts/init-lcdproc.LSB $RPM_BUILD_ROOT%{_initrddir}/lcdproc +install -d $RPM_BUILD_ROOT%{_unitdir} +install -d $RPM_BUILD_ROOT%{_unitdir}/lcdproc.target.wants +install -d $RPM_BUILD_ROOT%{_udevrulesdir} +install -d $RPM_BUILD_ROOT%{_sysusersdir} +install -pm 0644 %{SOURCE1} $RPM_BUILD_ROOT%{_unitdir} +install -pm 0644 %{SOURCE2} $RPM_BUILD_ROOT%{_unitdir} +install -pm 0644 %{SOURCE3} $RPM_BUILD_ROOT%{_unitdir} +install -pm 0644 %{SOURCE4} $RPM_BUILD_ROOT%{_unitdir} +install -pm 0755 %{SOURCE5} $RPM_BUILD_ROOT%{_sbindir}/LCDd-hwdetect +install -pm 0644 %{SOURCE6} $RPM_BUILD_ROOT%{_udevrulesdir} +install -pm 0644 %{SOURCE7} $RPM_BUILD_ROOT%{_sysusersdir}/lcdproc.conf +for i in lcdproc.service LCDd.service LCDd-hwdetect.service; do + ln -s ../$i $RPM_BUILD_ROOT%{_unitdir}/lcdproc.target.wants +done #Disable default configuration #Thoses are only provided as an example since ncurses isn't a suitable default configuration. for f in LCDd.conf lcdproc.conf ; do -mv $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/%{name}/${f} \ - $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/%{name}/${f}.example -touch $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/%{name}/${f} + mv $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/${f} \ + $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/${f}.example done %post -if [ $1 -eq 1 ]; then -# Add init script but don't start it - /sbin/chkconfig --add LCDd - /sbin/chkconfig --add lcdproc ||: -fi +%systemd_post LCDd.service lcdproc.service %preun -if [ $1 -eq 0 ]; then -# Disable driver on final removal - %{_initrddir}/lcdproc stop &>/dev/null - %{_initrddir}/LCDd stop &>/dev/null - /sbin/chkconfig --del lcdproc - /sbin/chkconfig --del LCDd ||: -fi +%systemd_preun LCDd.service lcdproc.service -%clean -rm -rf $RPM_BUILD_ROOT __doc +%postun +%systemd_postun_with_restart LCDd.service lcdproc.service + %files -%defattr(-,root,root,-) -%doc README* INSTALL COPYING CREDITS TODO ChangeLog -%doc docs/*.txt docs/README.* __doc/* +%doc %{_docdir}/%{name} +%license COPYING %{_bindir}/* -%dir %{_libdir}/lcdproc -%{_libdir}/lcdproc/* %{_sbindir}/* +%{_libdir}/lcdproc/ %{_mandir}/man?/* -%dir %{_sysconfdir}/sysconfig/%{name} -%ghost %{_sysconfdir}/sysconfig/%{name}/*.conf -%config %{_sysconfdir}/sysconfig/%{name}/*.conf.example -%{_initrddir}/LCDd -%{_initrddir}/lcdproc +%dir %{_sysconfdir}/%{name} +%config %{_sysconfdir}/%{name}/*.conf +%config %{_sysconfdir}/%{name}/*.conf.example +%{_unitdir}/* +%{_udevrulesdir}/90-%{name}.rules +%{_sysusersdir}/lcdproc.conf %changelog +* Thu Jul 24 2025 Fedora Release Engineering - 0.5.9-26.20210209git5c21e8c +- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild + +* Tue Feb 11 2025 Zbigniew Jędrzejewski-Szmek - 0.5.9-25.20210209git5c21e8c +- Drop call to %sysusers_create_compat + +* Fri Jan 17 2025 Fedora Release Engineering - 0.5.9-24.20210209git5c21e8c +- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild + +* Mon Jul 29 2024 Miroslav Suchý - 0.5.9-23.20210209git5c21e8c +- convert license to SPDX + +* Thu Jul 18 2024 Fedora Release Engineering - 0.5.9-22.20210209git5c21e8c +- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild + +* Thu Jan 25 2024 Fedora Release Engineering - 0.5.9-21.20210209git5c21e8c +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Sun Jan 21 2024 Fedora Release Engineering - 0.5.9-20.20210209git5c21e8c +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Thu Jul 20 2023 Fedora Release Engineering - 0.5.9-19.20210209git5c21e8c +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + +* Thu Jan 19 2023 Fedora Release Engineering - 0.5.9-18.20210209git5c21e8c +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Thu Jul 21 2022 Fedora Release Engineering - 0.5.9-17.20210209git5c21e8c +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Thu Jan 20 2022 Fedora Release Engineering - 0.5.9-16.20210209git5c21e8c +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Thu Jul 22 2021 Fedora Release Engineering - 0.5.9-15.20210209git5c21e8c +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Thu Apr 15 2021 Hans de Goede - 0.5.9-14.20210209git5c21e8c +- Sync with latest upstream git +- Add support for LCD found on Logitech Z-10 speakers, + inc. autodetect by udev + automatic LCDd.conf generation by LCDd-hwdetect +- Fix Logitech G15 family devices requiring a manual restart of LCDd + after a unplug + replug +- Drop ghosting of /etc/lcdproc/*.conf files, these may contain user + modifications, so they should not be removed on package removal +- This also fixes lcdexec.conf and lcdvc.conf not being packaged + +* Tue Mar 02 2021 Zbigniew Jędrzejewski-Szmek - 0.5.9-13.20190625git781b311 +- Rebuilt for updated systemd-rpm-macros + See https://pagure.io/fesco/issue/2583. + +* Tue Jan 26 2021 Fedora Release Engineering - 0.5.9-12.20190625git781b311 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Tue Nov 24 21:06:08 GMT 2020 Peter Robinson - 0.5.9-11.20190625git781b311 +- Build with libusb1 + +* Thu Aug 20 2020 Jeff Law - 0.5.9-10.20190625git781b311 +- Re-enable LTO + +* Tue Jul 28 2020 Fedora Release Engineering - 0.5.9-9.20190625git781b311 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Tue Jul 14 2020 Jeff Law - 0.5.9-8.20190625git781b311 +- Disable LTO + +* Fri Mar 20 2020 Hans de Goede - 0.5.9-7.20190625git781b311 +- Drop svgalib support, svgalib is being dropped from the distro (rhbz#1814816) + +* Mon Feb 24 2020 Than Ngo - 0.5.9-6.git +- Fixed FTBFS against gcc10 + +* Wed Jan 29 2020 Fedora Release Engineering - 0.5.9-5.20190625git781b311 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Fri Oct 4 2019 Hans de Goede - 0.5.9-4.20190625git781b311 +- Replace Group=lcdd statement in LCDd.service with Group=nobody, LCDd does not + need a special group and it breaks starting LCDd (rhbz#1742994) + +* Thu Oct 3 2019 Hans de Goede - 0.5.9-3.20190625git781b311 +- The patch adding the keycodes for LCD menu buttons on Logitech keyboards was + still pending upstream. The final version of the patch has changed the codes, + update LCDd-hwdetect.sh to use the new codes when writing out LCDd.conf + +* Thu Jul 25 2019 Fedora Release Engineering - 0.5.9-2.20190625git781b311 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Thu Jul 04 2019 Hans de Goede - 0.5.9-1.20190625git781b311 +- Update to upstream 0.5.9 release + latest improvements from git +- Add support for Logitech MX5000, MX5500, G15, G15 V2 and G510 keyboards +- Add LCDd-hwdetect script automatically generating LCDd.conf for + USB gaming keyboards with LCD panels and LCD2USB devices +- Add udev-rules to call LCDd-hwdetect when there is no existing LCDd.conf + and to make LCDd and lcdproc hw-activated when using supported USB devices + +* Fri Feb 01 2019 Fedora Release Engineering - 0.5.7-14 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Fri Jul 13 2018 Fedora Release Engineering - 0.5.7-13 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Wed Feb 07 2018 Fedora Release Engineering - 0.5.7-12 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Mon Aug 07 2017 Igor Gnatenko - 0.5.7-11 +- Remove unneeded BuildRequires: pth-devel + +* Thu Aug 03 2017 Fedora Release Engineering - 0.5.7-10 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Wed Jul 26 2017 Fedora Release Engineering - 0.5.7-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Fri Feb 10 2017 Fedora Release Engineering - 0.5.7-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Thu Sep 29 2016 Nicolas Chauvet - 0.5.7-7 +- Remove ControlGroup from services - rhbz#1324015 + +* Thu Feb 04 2016 Fedora Release Engineering - 0.5.7-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Wed Jun 17 2015 Fedora Release Engineering - 0.5.7-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Sat Oct 04 2014 Dan Horák - 0.5.7-4 +- update BR, libusbx-devel is brought in by libftdi-devel + +* Sun Aug 17 2014 Fedora Release Engineering - 0.5.7-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Sat Jun 07 2014 Fedora Release Engineering - 0.5.7-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Fri May 30 2014 Peter Robinson 0.5.7-1 +- Update to 0.5.7 +- Build against libusbx and libftdi 1 +- Cleanup spec + +* Sat Aug 03 2013 Fedora Release Engineering - 0.5.6-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Wed Jul 17 2013 Petr Pisar - 0.5.6-5 +- Perl 5.18 rebuild + +* Sat Apr 27 2013 Nicolas Chauvet - 0.5.6-4 +- Enable hardened build rhbz#955453 + +* Thu Feb 14 2013 Fedora Release Engineering - 0.5.6-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Mon Jan 07 2013 Dan Horák - 0.5.6-2 +- update BR for s390(x) + +* Wed Jan 02 2013 Nicolas Chauvet - 0.5.6-1 +- Update to 0.5.6 + +* Wed Aug 29 2012 Nicolas Chauvet - 0.5.5-6 +- Add systemd macro - rbz#850181 + +* Sun Jul 22 2012 Nicolas Chauvet - 0.5.5-5 +- Fix for rhbz#821270 + +* Thu Jul 19 2012 Fedora Release Engineering - 0.5.5-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Mon Feb 13 2012 Nicolas Chauvet - 0.5.5-3 +- Convert to native systemd units + +* Fri Jan 13 2012 Fedora Release Engineering - 0.5.5-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Tue Nov 29 2011 Nicolas Chauvet - 0.5.5-1 +- Update to 5.5 +- Fix path of functions +- Disable xosd and svga + +* Wed Mar 30 2011 Nicolas Chauvet - 0.5.4-1 +- Update to 0.5.4 + +* Mon Feb 07 2011 Fedora Release Engineering - 0.5.3-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Sun Apr 18 2010 Nicolas Chauvet - 0.5.3-5 +- Remove Uneeded BR - rhbz#572621 +- Rebuild for libftdi update - rhbz#581601 + +* Thu Sep 10 2009 Jarod Wilson - 0.5.3-4 +- Add BR: libftdi-devel to build lis driver (#522270) + +* Fri Jul 24 2009 Fedora Release Engineering - 0.5.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Thu Jun 25 2009 Jarod Wilson - 0.5.3-2 +- Fix broken LCDd initscript patch that prevented it from starting + +* Mon Jun 22 2009 Jarod Wilson - 0.5.3-1 +- Update to lcdproc v0.5.3 release +- Drop upstreamed imonlcd and memset_swp patches +- Switch to upstream's rpm initscripts (albeit still patched, need + to get that bit upstream for the next release) + * Wed May 13 2009 kwizart < kwizart at gmail.com > - 0.5.2-12 - Improve the initscripts patch - Fix #498384 diff --git a/lcdproc.sysusers b/lcdproc.sysusers new file mode 100644 index 0000000..7213bda --- /dev/null +++ b/lcdproc.sysusers @@ -0,0 +1 @@ +g lcdd - diff --git a/lcdproc.target b/lcdproc.target new file mode 100644 index 0000000..4001109 --- /dev/null +++ b/lcdproc.target @@ -0,0 +1,3 @@ +[Unit] +Description=lcdproc Target +StopWhenUnneeded=yes diff --git a/sources b/sources index cbf2751..7d495a3 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -860f192d061d87dda6512b11b79daac2 lcdproc-0.5.2.tar.gz +SHA512 (lcdproc-5c21e8c.tar.gz) = cc0f6622bfc76382306d1419b76e9d9d16740722bc29568559f4b022e0747a2edb3fece8d3f3d5871972b778290bc6178bd2de3919b6eae019505551e91f93cb