Merge pull request #1709 from lrusak/slice-cleanup

Slice cleanup
This commit is contained in:
Christian Hewitt 2017-07-02 05:26:31 +04:00 committed by GitHub
commit 5cc37cc3ae
43 changed files with 388 additions and 2573 deletions

View File

@ -0,0 +1,2 @@
100
- Initial release

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -0,0 +1,46 @@
################################################################################
# This file is part of LibreELEC - https://libreelec.tv
# Copyright (C) 2016-present Team LibreELEC
#
# LibreELEC is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# LibreELEC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LibreELEC. If not, see <http://www.gnu.org/licenses/>.
################################################################################
PKG_NAME="slice"
PKG_VERSION="0"
PKG_REV="100"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE=""
PKG_URL=""
PKG_DEPENDS_TARGET="toolchain"
PKG_SECTION="service"
PKG_SHORTDESC="Provides the ability to change the led lights on the Slice box via Kodi actions"
PKG_LONGDESC="Provides the ability to change the led lights on the Slice box via Kodi actions"
PKG_AUTORECONF="no"
PKG_IS_ADDON="yes"
PKG_ADDON_NAME="Slice"
PKG_ADDON_TYPE="xbmc.service"
make_target() {
:
}
makeinstall_target() {
:
}
addon() {
:
}

View File

@ -0,0 +1,237 @@
################################################################################
# This file is part of LibreELEC - https://libreelec.tv
# Copyright (C) 2016-present Team LibreELEC
#
# LibreELEC is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# LibreELEC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LibreELEC. If not, see <http://www.gnu.org/licenses/>.
################################################################################
from PIL import Image
import os
import threading
import time
import Queue
import xbmc
import xbmcaddon
'''
ffwd.png
pause.png
play.png
quit.png
rew.png
shutdown.png
skipf.png
skipr.png
sleep.png
startup.png
stop.png
wake.png
'''
__addon__ = xbmcaddon.Addon()
__path__ = __addon__.getAddonInfo('path')
class PNGPatternPlayer(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.path = __path__ + "/resources/media/ledpatterns"
self.patterns = Queue.Queue()
self.responses = Queue.Queue()
self.stopped = False
self.memo = {}
self.start()
def setPath(self, path):
if self.path != path:
self.path = path
self.memo = {}
def clearPattern(self):
with open('/dev/ws2812', 'wb') as f:
f.write(bytearray(25))
def playPattern(self, file, delay):
xbmc.log('playing pattern: %s' % file, xbmc.LOGNOTICE)
'get pixel data from a cache if available, otherwise load and calculate'
if file not in self.memo:
image = Image.open(file)
pixels = image.load()
width, height = image.size
data = []
for y in range(height):
x_pixels = []
for x in range(width):
pixel = []
r, g, b, a = pixels[x, y]
pixel.append(hex(r)[2:].zfill(2))
pixel.append(hex(g)[2:].zfill(2))
pixel.append(hex(b)[2:].zfill(2))
pixel.append(hex(a)[2:].zfill(2))
x_pixels.append(''.join(str(e) for e in pixel))
data.append(' '.join(str(e) for e in x_pixels))
self.memo[file] = data
for hexline in self.memo[file]:
if not self.stopped:
with open('/dev/ws2812', 'wb') as f:
f.write(bytearray.fromhex(hexline))
time.sleep(delay)
else:
break
def play(self, file, repeat=False, delay=0.030, wait=None):
self.stopped = True
if wait is not None:
# wait up to specified time if this pattern is to be processed synchronously
self.patterns.put((file, repeat, delay, True))
try:
result = self.responses.get(block=True, timeout=wait)
except Queue.Empty:
pass
else:
self.patterns.put((file, repeat, delay, False))
def stop(wait=None):
self.play(None, wait=wait)
def run(self):
repeat = False
while True:
try:
(file, repeat, delay, wait) = self.patterns.get(block=True, timeout=0 if repeat and not self.stopped else None)
self.stopped = False
if file is not None:
self.playPattern("%s/%s.png" % (self.path, file), delay)
else:
self.clearPattern()
if wait:
self.responses.put(True)
# Queue will be empty if we're repeating the last pattern and there is no new work
except Queue.Empty:
self.playPattern("%s/%s.png" % (self.path, file), delay)
class SlicePlayer(xbmc.Player):
def __init__(self, *args, **kwargs):
xbmc.Player.__init__(self)
'maps kodi player speed to delay in seconds'
self.speed_map = { 1: 0.060,
2: 0.040,
4: 0.035,
8: 0.030,
16: 0.025,
32: 0.015,
}
self.speed = 1
patterns.play('startup', False, 0.02)
def onPlayBackEnded(self):
'Will be called when Kodi stops playing a file'
patterns.play('stop')
def onPlayBackPaused(self):
'Will be called when user pauses a playing file'
patterns.play('pause')
def onPlayBackResumed(self):
'Will be called when user resumes a paused file'
patterns.play('play')
def onPlayBackSeek(self, iTime, seekOffset):
'Will be called when user seeks to a time'
# todo: not working
xbmc.log('time offset: %d' % iTime, xbmc.LOGNOTICE)
xbmc.log('seek offset: %d' % seekOffset, xbmc.LOGNOTICE)
if seekOffset > 0:
patterns.play('skipf')
else:
patterns.play('skipr')
def onPlayBackSeekChapter(self, chapter):
'Will be called when user performs a chapter seek'
pass
def onPlayBackSpeedChanged(self, speed):
'Will be called when players speed changes. (eg. user FF/RW)'
xbmc.log('seek speed: %d' % speed, xbmc.LOGNOTICE)
self.speed = speed
if self.speed != 1:
patterns.play('ffwd' if self.speed > 0 else 'rew', True, self.speed_map[self.speed])
else:
patterns.stop()
#OR: patterns.play('play') ???
def onPlayBackStarted(self):
'Will be called when Kodi starts playing a file'
patterns.play('play')
def onPlayBackStopped(self):
'Will be called when user stops Kodi playing a file'
patterns.play('stop')
class SliceMonitor(xbmc.Monitor):
def __init__(self, *args, **kwargs):
xbmc.Monitor.__init__(self)
def onScreensaverActivated(self):
'Will be called when screensaver kicks in'
patterns.play('sleep')
def onScreensaverDeactivated(self):
'Will be called when screensaver goes off'
patterns.play('wake')
def onSettingsChanged(self):
'Will be called when addon settings are changed'
# meh
if (__name__ == "__main__"):
patterns = PNGPatternPlayer()
player = SlicePlayer()
monitor = SliceMonitor()
monitor.waitForAbort()
patterns.play('shutdown', wait=5.0)
del SliceMonitor
del SlicePlayer
del PNGPatternPlayer

View File

Before

Width:  |  Height:  |  Size: 235 B

After

Width:  |  Height:  |  Size: 235 B

View File

Before

Width:  |  Height:  |  Size: 247 B

After

Width:  |  Height:  |  Size: 247 B

View File

Before

Width:  |  Height:  |  Size: 250 B

After

Width:  |  Height:  |  Size: 250 B

View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Before

Width:  |  Height:  |  Size: 242 B

After

Width:  |  Height:  |  Size: 242 B

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

Before

Width:  |  Height:  |  Size: 229 B

After

Width:  |  Height:  |  Size: 229 B

View File

Before

Width:  |  Height:  |  Size: 228 B

After

Width:  |  Height:  |  Size: 228 B

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,45 @@
################################################################################
# This file is part of LibreELEC - https://libreelec.tv
# Copyright (C) 2016-present Team LibreELEC
#
# LibreELEC is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# LibreELEC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LibreELEC. If not, see <http://www.gnu.org/licenses/>.
################################################################################
PKG_NAME="slice-drivers"
PKG_VERSION="d02f3e7"
PKG_ARCH="arm"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/LibreELEC/slice-drivers"
PKG_URL="https://github.com/LibreELEC/slice-drivers/archive/$PKG_VERSION.tar.gz"
PKG_DEPENDS_TARGET="toolchain linux"
PKG_NEED_UNPACK="$LINUX_DEPENDS"
PKG_SECTION="driver"
PKG_SHORTDESC="linux kernel modules for the Slice box"
PKG_LONGDESC="linux kernel modules for the Slice box"
PKG_IS_ADDON="no"
PKG_AUTORECONF="no"
pre_make_target() {
unset LDFLAGS
}
make_target() {
make KDIR=$(kernel_path)
}
makeinstall_target() {
mkdir -p $INSTALL/usr/lib/modules/$(get_module_dir)/$PKG_NAME
cp *.ko $INSTALL/usr/lib/modules/$(get_module_dir)/$PKG_NAME
}

View File

@ -0,0 +1,44 @@
################################################################################
# This file is part of LibreELEC - https://libreelec.tv
# Copyright (C) 2016-present Team LibreELEC
#
# LibreELEC is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# LibreELEC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LibreELEC. If not, see <http://www.gnu.org/licenses/>.
################################################################################
PKG_NAME="slice-firmware"
PKG_VERSION="0f463cc"
PKG_ARCH="arm"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/FiveNinjas/slice-firmware"
PKG_URL="https://github.com/libreelec/slice-firmware/archive/$PKG_VERSION.tar.gz"
PKG_DEPENDS_TARGET="toolchain dtc:host"
PKG_SECTION="linux-firmware"
PKG_SHORTDESC="BCM270x firmware related stuff for Slice"
PKG_LONGDESC="BCM270x firmware related stuff for Slice"
PKG_IS_ADDON="no"
PKG_AUTORECONF="no"
make_target() {
if [ "$DEVICE" = "Slice3" ]; then
dtc -O dtb -I dts -o dt-blob.bin slice3-dt-blob.dts
elif [ "$DEVICE" = "Slice" ]; then
dtc -O dtb -I dts -o dt-blob.bin slice-dt-blob.dts
fi
}
makeinstall_target() {
mkdir -p $INSTALL/usr/share/bootloader/
cp -a dt-blob.bin $INSTALL/usr/share/bootloader/
}

View File

@ -135,16 +135,10 @@ post_patch() {
for f in $PROJECT_DIR/$PROJECT/config/*-overlay.dts; do
[ -f "$f" ] && cp -v $f $PKG_BUILD/arch/$TARGET_KERNEL_ARCH/boot/dts/overlays
done
if [ -f $PROJECT_DIR/$PROJECT/config/dt-blob.dts ]; then
cp -v $PROJECT_DIR/$PROJECT/config/dt-blob.dts $PKG_BUILD/arch/$TARGET_KERNEL_ARCH/boot/dts
fi
if [ -n "$DEVICE" ]; then
for f in $PROJECT_DIR/$PROJECT/devices/$DEVICE/config/*-overlay.dts; do
[ -f "$f" ] && cp -v $f $PKG_BUILD/arch/$TARGET_KERNEL_ARCH/boot/dts/overlays
done
if [ -f $PROJECT_DIR/$PROJECT/devices/$DEVICE/config/dt-blob.dts ]; then
cp -v $PROJECT_DIR/$PROJECT/devices/$DEVICE/config/dt-blob.dts $PKG_BUILD/arch/$TARGET_KERNEL_ARCH/boot/dts
fi
fi
}

View File

@ -25,8 +25,8 @@ mkdir -p $RELEASE_DIR/3rdparty/bootloader
cp -PR $BUILD/bcm2835-bootloader-*/bootcode.bin $RELEASE_DIR/3rdparty/bootloader/
cp -PR $BUILD/bcm2835-bootloader-*/fixup_x.dat $RELEASE_DIR/3rdparty/bootloader/fixup.dat
cp -PR $BUILD/bcm2835-bootloader-*/start_x.elf $RELEASE_DIR/3rdparty/bootloader/start.elf
if [ -f $PROJECT_DIR/$PROJECT/devices/$DEVICE/config/dt-blob.bin ]; then
cp -PR $PROJECT_DIR/$PROJECT/devices/$DEVICE/config/dt-blob.bin $RELEASE_DIR/3rdparty/bootloader/
if [ -f $(get_build_dir slice-firmware)/dt-blob.bin ]; then
cp -PR $(get_build_dir slice-firmware)/dt-blob.bin $RELEASE_DIR/3rdparty/bootloader/
fi
cp -PR $INSTALL/usr/share/bootloader/*.dtb $RELEASE_DIR/3rdparty/bootloader/
cp -PR $INSTALL/usr/share/bootloader/overlays $RELEASE_DIR/3rdparty/bootloader/

View File

@ -37,6 +37,6 @@ makeinstall_target() {
}
makeinstall_host() {
mkdir -p $INSTALL/usr/bin
cp -P $PKG_BUILD/dtc $INSTALL/usr/bin
mkdir -p $TOOLCHAIN/bin
cp -P $PKG_BUILD/dtc $TOOLCHAIN/bin
}

View File

@ -40,7 +40,4 @@ make_target() {
makeinstall_target() {
mkdir -p $INSTALL/usr/bin
cp led_png $INSTALL/usr/bin
mkdir -p $INSTALL/usr/share/kodi/
cp -r $PKG_DIR/media $INSTALL/usr/share/kodi/
}

View File

@ -1,92 +0,0 @@
/dts-v1/;
/ {
videocore {
pins_cm {
pin_config {
pin@default {
polarity = "active_high";
termination = "pull_down";
startup_state = "inactive";
function = "input";
}; // pin
// BANK 0 //
pin@p0 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
pin@p1 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
pin@p2 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
pin@p3 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
pin@p4 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
pin@p5 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
pin@p6 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
pin@p7 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
pin@p8 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
pin@p9 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p10 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p11 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p12 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p13 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p14 { function = "uart0"; termination = "no_pulling"; }; // UART0_TX
pin@p15 { function = "uart0"; termination = "pull_up"; }; // UART0_RX
pin@p16 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p17 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p18 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p19 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p20 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p21 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p22 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p23 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p24 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p25 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p26 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p27 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
// BANK 1 //
pin@p28 { function = "pcm"; termination = "no_pulling"; }; // PCM_CLK
pin@p29 { function = "pcm"; termination = "no_pulling"; }; // PCM_FS
pin@p30 { function = "pcm"; termination = "no_pulling"; }; // PCM_DIN
pin@p31 { function = "pcm"; termination = "no_pulling"; }; // PCM_DOUT
pin@p32 { function = "gp_clk"; termination = "no_pulling"; }; // PCM_MCLK (GPCLK0)
pin@p33 { function = "output"; termination = "no_pulling"; polarity = "active_low"; startup_state = "inactive"; }; // AUD_RST_N
pin@p34 { function = "input"; termination = "pull_up"; }; // NOT USED
pin@p35 { function = "output"; termination = "no_pulling"; polarity = "active_high"; startup_state = "active"; }; // USB_ON
pin@p36 { function = "input"; termination = "no_pulling"; }; // RTC_IRQ
pin@p37 { function = "input"; termination = "no_pulling"; }; // IR_RX
pin@p38 { function = "output"; termination = "no_pulling"; polarity = "active_high"; startup_state = "inactive"; }; // STBY_LED
pin@p39 { function = "output"; termination = "no_pulling"; polarity = "active_high"; startup_state = "inactive"; }; // DISK_OFF
pin@p40 { function = "pwm"; termination = "no_pulling"; }; // LED_PWM
pin@p41 { function = "output"; termination = "no_pulling"; }; // LAN_RUN
pin@p42 { function = "gp_clk"; termination = "no_pulling"; }; // ETH_CLK (GPCLK1)
pin@p43 { function = "output"; termination = "pull_down"; polarity = "active_high"; startup_state = "inactive"; }; // LEDS_ON
pin@p44 { function = "i2c1"; termination = "no_pulling"; }; // SDA1
pin@p45 { function = "i2c1"; termination = "no_pulling"; }; // SCL1
// BANK 2 //
pin@p46 { function = "input"; termination = "no_pulling"; drive_strength_mA = <8>; polarity = "active_high"; }; // HPD_N
pin@p47 { function = "output"; termination = "no_pulling"; drive_strength_mA = <8>; polarity = "active_low"; startup_state = "active"; }; // EMMC_DISABLE_N CONTROL
pin@p48 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD CLK
pin@p49 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD CMD
pin@p50 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD D0
pin@p51 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD D1
pin@p52 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD D2
pin@p53 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD D3
}; // pin_config
pin_defines {
pin_define@HDMI_CONTROL_ATTACHED { type = "internal"; number = <46>; }; // HPD_N on GPIO46
pin_define@LAN_RUN { type = "internal"; number = <41>; }; // LAN_RUN
}; // pin_defines
}; // pins_cm
clock_setup {
clock@PWM { freq = < 2400000>; }; // LEDS PWM CLOCK
clock@GPCLK1 { freq = <25000000>; }; // ETH_CLK
}; // clock_setup
}; // videocore
};

View File

@ -1,2 +1,2 @@
# Additional kernel make parameters
KERNEL_MAKE_EXTRACMD+=" dt-blob.dtb overlays/slice.dtbo overlays/ws2812.dtbo"
KERNEL_MAKE_EXTRACMD+=" overlays/slice.dtbo overlays/ws2812.dtbo"

View File

@ -1,677 +0,0 @@
--- a/xbmc/windows/GUIWindowHome.cpp 2016-09-17 16:35:22.000000000 +0100
+++ b/xbmc/windows/GUIWindowHome.cpp 2016-10-01 19:22:20.908566550 +0100
@@ -30,9 +30,245 @@
#include "guilib/GUIWindowManager.h"
#include "Application.h"
#include "utils/StringUtils.h"
+extern "C"
+{
+ #include "readpng.h"
+}
using namespace ANNOUNCEMENT;
+int g_pattern = 0;
+int g_halt = 0;
+int g_pattern_playing = 0;
+int g_speed = 30000;
+int g_repeat = 0;
+
+enum pattern_e {
+ PAT_PLAY, PAT_PAUSE, PAT_STOP, PAT_SLEEP, PAT_WAKE, PAT_FFWD, PAT_REW, PAT_SKIPF, PAT_SKIPR, PAT_STARTUP, PAT_QUIT, PAT_NONE
+};
+#define NUM_PATTERNS 11
+const char *patterns[NUM_PATTERNS] = {
+ "play" , "pause", "stop", "sleep", "wake", "ffwd", "rew", "skipf", "skipr", "startup", "quit"
+};
+
+void on_speed_changed(const char *message, const CVariant &data)
+{
+ int speed = data["player"]["speed"].asInteger();
+
+ CLog::Log(LOGDEBUG, "speed changed %d", speed);
+
+ switch(abs(speed))
+ {
+ case 1: g_speed = 60000; break;
+ case 2: g_speed = 40000; break;
+ case 4: g_speed = 35000; break;
+ case 8: g_speed = 30000; break;
+ case 16: g_speed = 25000; break;
+ case 32: g_speed = 15000; break;
+ }
+
+ if(speed > 0)
+ g_pattern = PAT_FFWD;
+ else
+ g_pattern = PAT_REW;
+
+ if(speed != 1)
+ g_repeat = 1;
+ else
+ {
+ g_repeat = 0;
+ g_pattern = PAT_NONE;
+ }
+}
+
+void on_seek(const char *message, const CVariant &data)
+{
+ int seek_time = data["player"]["seekoffset"]["seconds"].asInteger() +
+ data["player"]["seekoffset"]["minutes"].asInteger() * 60;
+
+ CLog::Log(LOGDEBUG, "Seek offset = %d", seek_time);
+ if(seek_time > 0)
+ {
+ g_pattern = PAT_SKIPF;
+ }
+ else
+ {
+ g_pattern = PAT_SKIPR;
+ }
+
+ g_repeat = 0;
+}
+
+enum action_e {
+ ACTION_DO, ACTION_REPEAT, ACTION_FN
+ };
+
+enum led_state_e {
+ LED_STATE_INVALID = 0,
+ LED_STATE_IDLE,
+ LED_STATE_PLAYING,
+ LED_STATE_PAUSED,
+ LED_STATE_SLEEP
+};
+
+struct led_action_s {
+ const char * event_name;
+ enum action_e action;
+ enum pattern_e action_data;
+ void (*action_fn)(const char *, const CVariant &);
+ led_state_e action_state;
+} led_actions[] = {
+ { "OnPlay", ACTION_DO, PAT_PLAY, NULL, LED_STATE_PLAYING },
+ { "OnPause", ACTION_DO, PAT_PAUSE, NULL, LED_STATE_PAUSED },
+ { "OnStop", ACTION_DO, PAT_STOP, NULL, LED_STATE_IDLE },
+ { "OnSpeedChanged", ACTION_FN, PAT_NONE, on_speed_changed, LED_STATE_INVALID },
+ { "OnSeek", ACTION_FN, PAT_NONE, on_seek, LED_STATE_INVALID },
+ { "OnScreensaverActivated", ACTION_DO, PAT_SLEEP, NULL, LED_STATE_SLEEP },
+ { "OnScreensaverDeactivated", ACTION_DO, PAT_WAKE, NULL, LED_STATE_IDLE },
+ { "OnQuit", ACTION_REPEAT, PAT_QUIT, NULL, LED_STATE_IDLE },
+};
+
+int zeroes[25] = { 0,};
+
+class CLedPattern : public IRunnable
+{
+ int m_going;
+ CEvent *m_ev;
+ struct pattern {
+ unsigned long w;
+ unsigned long h;
+ unsigned long rowbytes;
+ unsigned char * img;
+ } m_pattern[NUM_PATTERNS];
+
+ void open_patterns()
+ {
+ unsigned int i;
+ for(i = 0; i < sizeof(patterns)/sizeof(patterns[0]); i++)
+ {
+ FILE * fp;
+ char filename[256];
+ int channels;
+
+ m_pattern[i].img = NULL;
+ sprintf(filename, "/storage/.kodi/media/ledpatterns/%s.png", patterns[i]);
+ fp = fopen(filename , "rb");
+ if(fp == NULL)
+ {
+ sprintf(filename, "/usr/share/kodi/media/ledpatterns/%s.png", patterns[i]);
+ fp = fopen(filename, "rb");
+ if(fp == NULL)
+ {
+ CLog::Log(LOGDEBUG, "Unable to open file %s", filename);
+ goto drop_out;
+ }
+ }
+
+ if(readpng_init(fp, &m_pattern[i].w, &m_pattern[i].h) != 0)
+ {
+ CLog::Log(LOGERROR, "Unable to parse png files %s", filename);
+ goto drop_out;
+ }
+
+ m_pattern[i].img = readpng_get_image(1.0, &channels, &m_pattern[i].rowbytes);
+ if(m_pattern[i].img == NULL || channels != 4)
+ {
+ CLog::Log(LOGERROR, "Invalid png %s, width = %lu, height = %lu, channels = %d, rowbytes = %lu",
+ filename, m_pattern[i].w, m_pattern[i].h, channels, m_pattern[i].rowbytes);
+ goto drop_out;
+ }
+
+ CLog::Log(LOGDEBUG, "Opened %s: (%lu x %lu)", filename, m_pattern[i].w, m_pattern[i].h);
+
+drop_out:
+ if(fp)
+ fclose(fp);
+
+ }
+ }
+
+ void play_pattern(int pat)
+ {
+ int fd = open("/dev/ws2812", O_WRONLY, 0);
+ if(fd < 0)
+ {
+ CLog::Log(LOGERROR, "Unable to open /dev/ws2812");
+ }
+ else
+ {
+ if(pat < PAT_NONE && m_pattern[pat].img != NULL)
+ {
+ CLog::Log(LOGDEBUG, "playing pattern");
+ g_pattern_playing = 1;
+ do
+ {
+ unsigned char * p_line = m_pattern[pat].img;
+ unsigned int i;
+
+ for(i = 0; i < m_pattern[pat].h; i++)
+ {
+ write(fd, p_line, m_pattern[pat].w * 4);
+ if(m_pattern[pat].w == 26)
+ {
+ int *p = (int *) (p_line + (25 * 4));
+ usleep(*p);
+ }
+ else
+ {
+ usleep(g_speed);
+ }
+ p_line += m_pattern[pat].rowbytes;
+ // If we get the g_halt signal then stop repeating
+ // the pattern
+ if(g_halt)
+ {
+ g_halt = 0;
+ g_repeat = 0;
+ break;
+ }
+ }
+ p_line += m_pattern[pat].rowbytes;
+ }
+ while(g_repeat);
+ g_pattern_playing = 0;
+
+ if(pat != PAT_QUIT)
+ write(fd, zeroes, sizeof(zeroes));
+ }
+ else
+ {
+ CLog::Log(LOGDEBUG, "No img for LED pattern %d", pat);
+ }
+ close(fd);
+ }
+ }
+
+public:
+ CLedPattern(CEvent *ev)
+ {
+ CLog::Log(LOGDEBUG, "Initialising CLedPattern");
+ open_patterns();
+ m_ev = ev;
+ }
+
+ void Run()
+ {
+ m_going = 1;
+ while(m_going)
+ {
+ m_ev->Wait();
+ CLog::Log(LOGDEBUG, "Led Pattern %d triggered", g_pattern);
+ play_pattern(g_pattern);
+ }
+ }
+
+ void Stop()
+ {
+ m_going = 0;
+ m_ev->Set();
+ }
+};
+
CGUIWindowHome::CGUIWindowHome(void) : CGUIWindow(WINDOW_HOME, "Home.xml"),
m_recentlyAddedRunning(false),
m_cumulativeUpdateFlag(0)
@@ -40,6 +276,14 @@ CGUIWindowHome::CGUIWindowHome(void) : C
m_updateRA = (Audio | Video | Totals);
m_loadType = KEEP_IN_MEMORY;
+ m_ledevent = new CEvent();
+ m_ledthread = new CThread(new CLedPattern(m_ledevent), "LedThread");
+ m_ledthread->Create();
+ g_pattern = PAT_STARTUP;
+ g_speed = 30000;
+ g_repeat = 0;
+ m_ledevent->Set();
+
CAnnouncementManager::GetInstance().AddAnnouncer(this);
}
@@ -75,10 +319,49 @@ void CGUIWindowHome::OnInitWindow()
void CGUIWindowHome::Announce(AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data)
{
+ unsigned int i;
int ra_flag = 0;
CLog::Log(LOGDEBUG, "GOT ANNOUNCEMENT, type: %i, from %s, message %s",(int)flag, sender, message);
+ for(i = 0; i < sizeof(led_actions)/sizeof(led_actions[0]); i++)
+ {
+ if(strcmp(message, led_actions[i].event_name) == 0)
+ {
+ switch(led_actions[i].action) {
+ case ACTION_DO:
+ case ACTION_REPEAT:
+ {
+ g_halt = 1;
+ while(g_pattern_playing)
+ usleep(10);
+ g_halt = 0;
+ g_repeat = (led_actions[i].action == ACTION_DO) ? 0 : 1;
+ g_speed = 30000;
+ g_pattern = (int) led_actions[i].action_data;
+ m_ledevent->Set();
+ break;
+ }
+ case ACTION_FN:
+ {
+ g_halt = 1;
+ while(g_pattern_playing)
+ usleep(10);
+ g_halt = 0;
+ g_repeat = 0;
+ g_speed = 30000;
+ led_actions[i].action_fn(message, data);
+ m_ledevent->Set();
+ break;
+ }
+ default:
+ {
+ CLog::Log(LOGERROR, "Failed to execute LED action %d for event %s\n", i, led_actions[i].event_name);
+ }
+ }
+ }
+ }
+
// we are only interested in library changes
if ((flag & (VideoLibrary | AudioLibrary)) == 0)
return;
--- a/xbmc/windows/GUIWindowHome.h 2016-09-17 16:35:22.000000000 +0100
+++ b/xbmc/windows/GUIWindowHome.h 2016-10-01 19:34:18.585113811 +0100
@@ -23,6 +23,8 @@
#include "guilib/GUIWindow.h"
#include "interfaces/IAnnouncer.h"
#include "utils/Job.h"
+#include "threads/Thread.h"
+#include "threads/Event.h"
class CVariant;
@@ -47,4 +49,7 @@
bool m_recentlyAddedRunning;
int m_cumulativeUpdateFlag;
+
+ CThread *m_ledthread;
+ CEvent *m_ledevent;
};
--- a/xbmc/windows/readpng.c 1970-01-01 00:00:00.000000000 +0000
+++ b/xbmc/windows/readpng.c 2016-01-08 06:49:51.049652775 +0000
@@ -0,0 +1,274 @@
+/*---------------------------------------------------------------------------
+
+ rpng - simple PNG display program readpng.c
+
+ ---------------------------------------------------------------------------
+
+ Copyright (c) 1998-2000 Greg Roelofs. All rights reserved.
+
+ This software is provided "as is," without warranty of any kind,
+ express or implied. In no event shall the author or contributors
+ be held liable for any damages arising in any way from the use of
+ this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute
+ it freely, subject to the following restrictions:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, disclaimer, and this list of conditions.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, disclaimer, and this list of conditions in the documenta-
+ tion and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this
+ software must display the following acknowledgment:
+
+ This product includes software developed by Greg Roelofs
+ and contributors for the book, "PNG: The Definitive Guide,"
+ published by O'Reilly and Associates.
+
+ ---------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "png.h" /* libpng header; includes zlib.h */
+#include "readpng.h" /* typedefs, common macros, public prototypes */
+
+
+static png_structp png_ptr = NULL;
+static png_infop info_ptr = NULL;
+
+png_uint_32 width, height;
+int bit_depth, color_type;
+uch *image_data = NULL;
+
+
+void readpng_version_info(void)
+{
+ fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n",
+ PNG_LIBPNG_VER_STRING, png_libpng_ver);
+}
+
+
+/* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */
+
+int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight)
+{
+ uch sig[8];
+
+
+ /* first do a quick check that the file really is a PNG image; could
+ * have used slightly more general png_sig_cmp() function instead */
+
+ fread(sig, 1, 8, infile);
+ if(png_sig_cmp(sig, 0, 8))
+ return 1; /* bad signature */
+
+
+ /* could pass pointers to user-defined error handlers instead of NULLs: */
+
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png_ptr)
+ return 4; /* out of memory */
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr) {
+ png_destroy_read_struct(&png_ptr, NULL, NULL);
+ return 4; /* out of memory */
+ }
+
+
+ /* we could create a second info struct here (end_info), but it's only
+ * useful if we want to keep pre- and post-IDAT chunk info separated
+ * (mainly for PNG-aware image editors and converters) */
+
+
+ /* setjmp() must be called in every function that calls a PNG-reading
+ * libpng function */
+
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ return 2;
+ }
+
+
+ png_init_io(png_ptr, infile);
+ png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */
+
+ png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */
+
+
+ /* alternatively, could make separate calls to png_get_image_width(),
+ * etc., but want bit_depth and color_type for later [don't care about
+ * compression_type and filter_type => NULLs] */
+
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
+ NULL, NULL, NULL);
+ *pWidth = width;
+ *pHeight = height;
+
+
+ /* OK, that's all we need for now; return happy */
+
+ return 0;
+}
+
+
+
+
+/* returns 0 if succeeds, 1 if fails due to no bKGD chunk, 2 if libpng error;
+ * scales values to 8-bit if necessary */
+
+int readpng_get_bgcolor(uch *red, uch *green, uch *blue)
+{
+ png_color_16p pBackground;
+
+
+ /* setjmp() must be called in every function that calls a PNG-reading
+ * libpng function */
+
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ return 2;
+ }
+
+
+ if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD))
+ return 1;
+
+ /* it is not obvious from the libpng documentation, but this function
+ * takes a pointer to a pointer, and it always returns valid red, green
+ * and blue values, regardless of color_type: */
+
+ png_get_bKGD(png_ptr, info_ptr, &pBackground);
+
+
+ /* however, it always returns the raw bKGD data, regardless of any
+ * bit-depth transformations, so check depth and adjust if necessary */
+
+ if (bit_depth == 16) {
+ *red = pBackground->red >> 8;
+ *green = pBackground->green >> 8;
+ *blue = pBackground->blue >> 8;
+ } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
+ if (bit_depth == 1)
+ *red = *green = *blue = pBackground->gray? 255 : 0;
+ else if (bit_depth == 2)
+ *red = *green = *blue = (255/3) * pBackground->gray;
+ else /* bit_depth == 4 */
+ *red = *green = *blue = (255/15) * pBackground->gray;
+ } else {
+ *red = (uch)pBackground->red;
+ *green = (uch)pBackground->green;
+ *blue = (uch)pBackground->blue;
+ }
+
+ return 0;
+}
+
+
+
+
+/* display_exponent == LUT_exponent * CRT_exponent */
+
+uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes)
+{
+ double gamma;
+ png_uint_32 i, rowbytes;
+ png_bytepp row_pointers = NULL;
+
+
+ /* setjmp() must be called in every function that calls a PNG-reading
+ * libpng function */
+
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ return NULL;
+ }
+
+
+ /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits,
+ * transparency chunks to full alpha channel; strip 16-bit-per-sample
+ * images to 8 bits per sample; and convert grayscale to RGB[A] */
+
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_expand(png_ptr);
+ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
+ png_set_expand(png_ptr);
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+ png_set_expand(png_ptr);
+ if (bit_depth == 16)
+ png_set_strip_16(png_ptr);
+ if (color_type == PNG_COLOR_TYPE_GRAY ||
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_gray_to_rgb(png_ptr);
+
+
+ /* unlike the example in the libpng documentation, we have *no* idea where
+ * this file may have come from--so if it doesn't have a file gamma, don't
+ * do any correction ("do no harm") */
+
+ if (png_get_gAMA(png_ptr, info_ptr, &gamma))
+ png_set_gamma(png_ptr, display_exponent, gamma);
+
+
+ /* all transformations have been registered; now update info_ptr data,
+ * get rowbytes and channels, and allocate image memory */
+
+ png_read_update_info(png_ptr, info_ptr);
+
+ *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr);
+ *pChannels = (int)png_get_channels(png_ptr, info_ptr);
+
+ if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ return NULL;
+ }
+ if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ free(image_data);
+ image_data = NULL;
+ return NULL;
+ }
+
+ Trace((stderr, "readpng_get_image: rowbytes = %ld, height = %ld\n", rowbytes, height));
+
+
+ /* set the individual row_pointers to point at the correct offsets */
+
+ for (i = 0; i < height; ++i)
+ row_pointers[i] = image_data + i*rowbytes;
+
+
+ /* now we can go ahead and just read the whole image */
+
+ png_read_image(png_ptr, row_pointers);
+
+
+ /* and we're done! (png_read_end() can be omitted if no processing of
+ * post-IDAT text/time/etc. is desired) */
+
+ free(row_pointers);
+ row_pointers = NULL;
+
+ png_read_end(png_ptr, NULL);
+
+ return image_data;
+}
+
+
+void readpng_cleanup(int free_image_data)
+{
+ if (free_image_data && image_data) {
+ free(image_data);
+ image_data = NULL;
+ }
+
+ if (png_ptr && info_ptr) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ png_ptr = NULL;
+ info_ptr = NULL;
+ }
+}
+
--- a/xbmc/windows/readpng.h 1970-01-01 00:00:00.000000000 +0000
+++ b/xbmc/windows/readpng.h 2016-01-08 06:49:51.049652775 +0000
@@ -0,0 +1,65 @@
+/*---------------------------------------------------------------------------
+
+ rpng - simple PNG display program readpng.h
+
+ ---------------------------------------------------------------------------
+
+ Copyright (c) 1998-2000 Greg Roelofs. All rights reserved.
+
+ This software is provided "as is," without warranty of any kind,
+ express or implied. In no event shall the author or contributors
+ be held liable for any damages arising in any way from the use of
+ this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute
+ it freely, subject to the following restrictions:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, disclaimer, and this list of conditions.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, disclaimer, and this list of conditions in the documenta-
+ tion and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this
+ software must display the following acknowledgment:
+
+ This product includes software developed by Greg Roelofs
+ and contributors for the book, "PNG: The Definitive Guide,"
+ published by O'Reilly and Associates.
+
+ ---------------------------------------------------------------------------*/
+
+#ifndef TRUE
+# define TRUE 1
+# define FALSE 0
+#endif
+
+#ifndef MAX
+# define MAX(a,b) ((a) > (b)? (a) : (b))
+# define MIN(a,b) ((a) < (b)? (a) : (b))
+#endif
+
+#ifdef DEBUG
+# define Trace(x) {fprintf x ; fflush(stderr); fflush(stdout);}
+#else
+# define Trace(x) ;
+#endif
+
+typedef unsigned char uch;
+typedef unsigned short ush;
+typedef unsigned long ulg;
+
+
+/* prototypes for public functions in readpng.c */
+
+void readpng_version_info(void);
+
+int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight);
+
+int readpng_get_bgcolor(uch *bg_red, uch *bg_green, uch *bg_blue);
+
+uch *readpng_get_image(double display_exponent, int *pChannels,
+ ulg *pRowbytes);
+
+void readpng_cleanup(int free_image_data);
+

View File

@ -1,18 +0,0 @@
--- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp 2016-09-17 16:35:20.000000000 +0100
+++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp 2016-10-01 19:26:40.470553260 +0100
@@ -527,6 +527,7 @@
m_info.m_wantsIECPassthrough = true;
list.push_back(m_info);
+#if 0
m_info.m_channels.Reset();
m_info.m_dataFormats.clear();
m_info.m_streamTypes.clear();
@@ -548,6 +549,7 @@
m_info.m_wantsIECPassthrough = true;
list.push_back(m_info);
+#endif
m_info.m_channels.Reset();
m_info.m_dataFormats.clear();

View File

@ -1,22 +0,0 @@
--- a/system/keymaps/keyboard.xml 2016-09-17 16:35:20.000000000 +0100
+++ b/system/keymaps/keyboard.xml 2016-10-01 19:31:07.928719606 +0100
@@ -56,7 +56,7 @@
<menu mod="longpress">Menu</menu>
<c>ContextMenu</c>
<c mod="longpress">Menu</c>
- <space>Pause</space>
+ <space>PlayPause</space>
<x>Stop</x>
<period>SkipNext</period>
<comma>SkipPrevious</comma>
@@ -321,8 +321,8 @@
<l>NextSubtitle</l>
<left>StepBack</left>
<right>StepForward</right>
- <up>ChapterOrBigStepForward</up>
- <down>ChapterOrBigStepBack</down>
+ <up>VolumeUp</up>
+ <down>VolumeDown</down>
<up mod="longpress">AudioNextLanguage</up>
<down mod="longpress">NextSubtitle</down>
<a>AudioDelay</a>

View File

@ -1,31 +0,0 @@
diff --git a/xbmc/windows/CMakeLists.txt b/xbmc/windows/CMakeLists.txt
index 3700602..c75f78f 100644
--- a/xbmc/windows/CMakeLists.txt
+++ b/xbmc/windows/CMakeLists.txt
@@ -1,3 +1,5 @@
+find_package(PNG REQUIRED)
+
set(SOURCES GUIMediaWindow.cpp
GUIWindowDebugInfo.cpp
GUIWindowFileManager.cpp
@@ -9,7 +11,8 @@ set(SOURCES GUIMediaWindow.cpp
GUIWindowSplash.cpp
GUIWindowStartup.cpp
GUIWindowSystemInfo.cpp
- GUIWindowWeather.cpp)
+ GUIWindowWeather.cpp
+ readpng.c)
set(HEADERS GUIMediaWindow.h
GUIWindowDebugInfo.h
@@ -22,6 +25,9 @@ set(HEADERS GUIMediaWindow.h
GUIWindowSplash.h
GUIWindowStartup.h
GUIWindowSystemInfo.h
- GUIWindowWeather.h)
+ GUIWindowWeather.h
+ readpng.h)
core_add_library(windows)
+
+target_link_libraries(windows PRIVATE ${PNG_LIBRARIES})

View File

@ -1,98 +0,0 @@
/dts-v1/;
/ {
videocore {
pins_cm3 {
pin_config {
pin@default {
polarity = "active_high";
termination = "pull_down";
startup_state = "inactive";
function = "input";
}; // pin
// BANK 0 //
pin@p0 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
pin@p1 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
pin@p2 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
pin@p3 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
pin@p4 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
pin@p5 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
pin@p6 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
pin@p7 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
pin@p8 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
pin@p9 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p10 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p11 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p12 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p13 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p14 { function = "uart0"; termination = "no_pulling"; }; // UART0_TX
pin@p15 { function = "uart0"; termination = "pull_up"; }; // UART0_RX
pin@p16 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p17 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p18 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p19 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p20 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p21 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p22 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p23 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p24 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p25 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p26 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
pin@p27 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
// BANK 1 //
pin@p28 { function = "pcm"; termination = "no_pulling"; }; // PCM_CLK
pin@p29 { function = "pcm"; termination = "no_pulling"; }; // PCM_FS
pin@p30 { function = "pcm"; termination = "no_pulling"; }; // PCM_DIN
pin@p31 { function = "pcm"; termination = "no_pulling"; }; // PCM_DOUT
pin@p32 { function = "gp_clk"; termination = "no_pulling"; }; // PCM_MCLK (GPCLK0)
pin@p33 { function = "output"; termination = "no_pulling"; polarity = "active_low"; startup_state = "inactive"; }; // AUD_RST_N
pin@p34 { function = "input"; termination = "pull_up"; }; // NOT USED
pin@p35 { function = "output"; termination = "no_pulling"; polarity = "active_high"; startup_state = "active"; }; // USB_ON
pin@p36 { function = "input"; termination = "no_pulling"; }; // RTC_IRQ
pin@p37 { function = "input"; termination = "no_pulling"; }; // IR_RX
pin@p38 { function = "output"; termination = "no_pulling"; polarity = "active_high"; startup_state = "inactive"; }; // STBY_LED
pin@p39 { function = "output"; termination = "no_pulling"; polarity = "active_high"; startup_state = "inactive"; }; // DISK_OFF
pin@p40 { function = "pwm"; termination = "no_pulling"; }; // LED_PWM
pin@p41 { function = "output"; termination = "no_pulling"; }; // LAN_RUN
pin@p42 { function = "gp_clk"; termination = "no_pulling"; }; // ETH_CLK (GPCLK1)
pin@p43 { function = "output"; termination = "pull_down"; polarity = "active_high"; startup_state = "inactive"; }; // LEDS_ON
pin@p44 { function = "i2c1"; termination = "no_pulling"; }; // SDA1
pin@p45 { function = "i2c1"; termination = "no_pulling"; }; // SCL1
// BANK 2 //
pin@p46 { function = "input"; termination = "pull_up"; }; // SMPS_SCL
pin@p47 { function = "input"; termination = "pull_up"; }; // SMPS_SDA
pin@p48 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD CLK
pin@p49 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD CMD
pin@p50 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD D0
pin@p51 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD D1
pin@p52 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD D2
pin@p53 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD D3
pin@p128 { function = "input"; termination = "no_pulling"; polarity = "active_low"; }; // Hotplug
pin@p129 { function = "output"; termination = "no_pulling"; polarity = "active_low"; }; // EMMC_ENABLE_N
}; // pin_config
pin_defines {
pin_define@HDMI_CONTROL_ATTACHED { type = "external"; number = <0>; }; // HPD_N on external gpio
pin_define@LAN_RUN { type = "internal"; number = <41>; }; // LAN_RUN
pin_define@EMMC_ENABLE { type = "external"; number = <1>; };
pin_define@SMPS_SDA { type = "internal"; number = <46>; };
pin_define@SMPS_SCL { type = "internal"; number = <47>; };
}; // pin_defines
}; // pins_cm
clock_setup {
clock@PWM { freq = < 2400000>; }; // LEDS PWM CLOCK
clock@GPCLK1 { freq = <25000000>; }; // ETH_CLK
}; // clock_setup
}; // videocore
};

View File

@ -1,2 +1,2 @@
# Additional kernel make parameters
KERNEL_MAKE_EXTRACMD+=" dt-blob.dtb overlays/slice.dtbo overlays/ws2812.dtbo"
KERNEL_MAKE_EXTRACMD+=" overlays/slice.dtbo overlays/ws2812.dtbo"

View File

@ -1,677 +0,0 @@
--- a/xbmc/windows/GUIWindowHome.cpp 2016-09-17 16:35:22.000000000 +0100
+++ b/xbmc/windows/GUIWindowHome.cpp 2016-10-01 19:22:20.908566550 +0100
@@ -30,9 +30,245 @@
#include "guilib/GUIWindowManager.h"
#include "Application.h"
#include "utils/StringUtils.h"
+extern "C"
+{
+ #include "readpng.h"
+}
using namespace ANNOUNCEMENT;
+int g_pattern = 0;
+int g_halt = 0;
+int g_pattern_playing = 0;
+int g_speed = 30000;
+int g_repeat = 0;
+
+enum pattern_e {
+ PAT_PLAY, PAT_PAUSE, PAT_STOP, PAT_SLEEP, PAT_WAKE, PAT_FFWD, PAT_REW, PAT_SKIPF, PAT_SKIPR, PAT_STARTUP, PAT_QUIT, PAT_NONE
+};
+#define NUM_PATTERNS 11
+const char *patterns[NUM_PATTERNS] = {
+ "play" , "pause", "stop", "sleep", "wake", "ffwd", "rew", "skipf", "skipr", "startup", "quit"
+};
+
+void on_speed_changed(const char *message, const CVariant &data)
+{
+ int speed = data["player"]["speed"].asInteger();
+
+ CLog::Log(LOGDEBUG, "speed changed %d", speed);
+
+ switch(abs(speed))
+ {
+ case 1: g_speed = 60000; break;
+ case 2: g_speed = 40000; break;
+ case 4: g_speed = 35000; break;
+ case 8: g_speed = 30000; break;
+ case 16: g_speed = 25000; break;
+ case 32: g_speed = 15000; break;
+ }
+
+ if(speed > 0)
+ g_pattern = PAT_FFWD;
+ else
+ g_pattern = PAT_REW;
+
+ if(speed != 1)
+ g_repeat = 1;
+ else
+ {
+ g_repeat = 0;
+ g_pattern = PAT_NONE;
+ }
+}
+
+void on_seek(const char *message, const CVariant &data)
+{
+ int seek_time = data["player"]["seekoffset"]["seconds"].asInteger() +
+ data["player"]["seekoffset"]["minutes"].asInteger() * 60;
+
+ CLog::Log(LOGDEBUG, "Seek offset = %d", seek_time);
+ if(seek_time > 0)
+ {
+ g_pattern = PAT_SKIPF;
+ }
+ else
+ {
+ g_pattern = PAT_SKIPR;
+ }
+
+ g_repeat = 0;
+}
+
+enum action_e {
+ ACTION_DO, ACTION_REPEAT, ACTION_FN
+ };
+
+enum led_state_e {
+ LED_STATE_INVALID = 0,
+ LED_STATE_IDLE,
+ LED_STATE_PLAYING,
+ LED_STATE_PAUSED,
+ LED_STATE_SLEEP
+};
+
+struct led_action_s {
+ const char * event_name;
+ enum action_e action;
+ enum pattern_e action_data;
+ void (*action_fn)(const char *, const CVariant &);
+ led_state_e action_state;
+} led_actions[] = {
+ { "OnPlay", ACTION_DO, PAT_PLAY, NULL, LED_STATE_PLAYING },
+ { "OnPause", ACTION_DO, PAT_PAUSE, NULL, LED_STATE_PAUSED },
+ { "OnStop", ACTION_DO, PAT_STOP, NULL, LED_STATE_IDLE },
+ { "OnSpeedChanged", ACTION_FN, PAT_NONE, on_speed_changed, LED_STATE_INVALID },
+ { "OnSeek", ACTION_FN, PAT_NONE, on_seek, LED_STATE_INVALID },
+ { "OnScreensaverActivated", ACTION_DO, PAT_SLEEP, NULL, LED_STATE_SLEEP },
+ { "OnScreensaverDeactivated", ACTION_DO, PAT_WAKE, NULL, LED_STATE_IDLE },
+ { "OnQuit", ACTION_REPEAT, PAT_QUIT, NULL, LED_STATE_IDLE },
+};
+
+int zeroes[25] = { 0,};
+
+class CLedPattern : public IRunnable
+{
+ int m_going;
+ CEvent *m_ev;
+ struct pattern {
+ unsigned long w;
+ unsigned long h;
+ unsigned long rowbytes;
+ unsigned char * img;
+ } m_pattern[NUM_PATTERNS];
+
+ void open_patterns()
+ {
+ unsigned int i;
+ for(i = 0; i < sizeof(patterns)/sizeof(patterns[0]); i++)
+ {
+ FILE * fp;
+ char filename[256];
+ int channels;
+
+ m_pattern[i].img = NULL;
+ sprintf(filename, "/storage/.kodi/media/ledpatterns/%s.png", patterns[i]);
+ fp = fopen(filename , "rb");
+ if(fp == NULL)
+ {
+ sprintf(filename, "/usr/share/kodi/media/ledpatterns/%s.png", patterns[i]);
+ fp = fopen(filename, "rb");
+ if(fp == NULL)
+ {
+ CLog::Log(LOGDEBUG, "Unable to open file %s", filename);
+ goto drop_out;
+ }
+ }
+
+ if(readpng_init(fp, &m_pattern[i].w, &m_pattern[i].h) != 0)
+ {
+ CLog::Log(LOGERROR, "Unable to parse png files %s", filename);
+ goto drop_out;
+ }
+
+ m_pattern[i].img = readpng_get_image(1.0, &channels, &m_pattern[i].rowbytes);
+ if(m_pattern[i].img == NULL || channels != 4)
+ {
+ CLog::Log(LOGERROR, "Invalid png %s, width = %lu, height = %lu, channels = %d, rowbytes = %lu",
+ filename, m_pattern[i].w, m_pattern[i].h, channels, m_pattern[i].rowbytes);
+ goto drop_out;
+ }
+
+ CLog::Log(LOGDEBUG, "Opened %s: (%lu x %lu)", filename, m_pattern[i].w, m_pattern[i].h);
+
+drop_out:
+ if(fp)
+ fclose(fp);
+
+ }
+ }
+
+ void play_pattern(int pat)
+ {
+ int fd = open("/dev/ws2812", O_WRONLY, 0);
+ if(fd < 0)
+ {
+ CLog::Log(LOGERROR, "Unable to open /dev/ws2812");
+ }
+ else
+ {
+ if(pat < PAT_NONE && m_pattern[pat].img != NULL)
+ {
+ CLog::Log(LOGDEBUG, "playing pattern");
+ g_pattern_playing = 1;
+ do
+ {
+ unsigned char * p_line = m_pattern[pat].img;
+ unsigned int i;
+
+ for(i = 0; i < m_pattern[pat].h; i++)
+ {
+ write(fd, p_line, m_pattern[pat].w * 4);
+ if(m_pattern[pat].w == 26)
+ {
+ int *p = (int *) (p_line + (25 * 4));
+ usleep(*p);
+ }
+ else
+ {
+ usleep(g_speed);
+ }
+ p_line += m_pattern[pat].rowbytes;
+ // If we get the g_halt signal then stop repeating
+ // the pattern
+ if(g_halt)
+ {
+ g_halt = 0;
+ g_repeat = 0;
+ break;
+ }
+ }
+ p_line += m_pattern[pat].rowbytes;
+ }
+ while(g_repeat);
+ g_pattern_playing = 0;
+
+ if(pat != PAT_QUIT)
+ write(fd, zeroes, sizeof(zeroes));
+ }
+ else
+ {
+ CLog::Log(LOGDEBUG, "No img for LED pattern %d", pat);
+ }
+ close(fd);
+ }
+ }
+
+public:
+ CLedPattern(CEvent *ev)
+ {
+ CLog::Log(LOGDEBUG, "Initialising CLedPattern");
+ open_patterns();
+ m_ev = ev;
+ }
+
+ void Run()
+ {
+ m_going = 1;
+ while(m_going)
+ {
+ m_ev->Wait();
+ CLog::Log(LOGDEBUG, "Led Pattern %d triggered", g_pattern);
+ play_pattern(g_pattern);
+ }
+ }
+
+ void Stop()
+ {
+ m_going = 0;
+ m_ev->Set();
+ }
+};
+
CGUIWindowHome::CGUIWindowHome(void) : CGUIWindow(WINDOW_HOME, "Home.xml"),
m_recentlyAddedRunning(false),
m_cumulativeUpdateFlag(0)
@@ -40,6 +276,14 @@ CGUIWindowHome::CGUIWindowHome(void) : C
m_updateRA = (Audio | Video | Totals);
m_loadType = KEEP_IN_MEMORY;
+ m_ledevent = new CEvent();
+ m_ledthread = new CThread(new CLedPattern(m_ledevent), "LedThread");
+ m_ledthread->Create();
+ g_pattern = PAT_STARTUP;
+ g_speed = 30000;
+ g_repeat = 0;
+ m_ledevent->Set();
+
CAnnouncementManager::GetInstance().AddAnnouncer(this);
}
@@ -75,10 +319,49 @@ void CGUIWindowHome::OnInitWindow()
void CGUIWindowHome::Announce(AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data)
{
+ unsigned int i;
int ra_flag = 0;
CLog::Log(LOGDEBUG, "GOT ANNOUNCEMENT, type: %i, from %s, message %s",(int)flag, sender, message);
+ for(i = 0; i < sizeof(led_actions)/sizeof(led_actions[0]); i++)
+ {
+ if(strcmp(message, led_actions[i].event_name) == 0)
+ {
+ switch(led_actions[i].action) {
+ case ACTION_DO:
+ case ACTION_REPEAT:
+ {
+ g_halt = 1;
+ while(g_pattern_playing)
+ usleep(10);
+ g_halt = 0;
+ g_repeat = (led_actions[i].action == ACTION_DO) ? 0 : 1;
+ g_speed = 30000;
+ g_pattern = (int) led_actions[i].action_data;
+ m_ledevent->Set();
+ break;
+ }
+ case ACTION_FN:
+ {
+ g_halt = 1;
+ while(g_pattern_playing)
+ usleep(10);
+ g_halt = 0;
+ g_repeat = 0;
+ g_speed = 30000;
+ led_actions[i].action_fn(message, data);
+ m_ledevent->Set();
+ break;
+ }
+ default:
+ {
+ CLog::Log(LOGERROR, "Failed to execute LED action %d for event %s\n", i, led_actions[i].event_name);
+ }
+ }
+ }
+ }
+
// we are only interested in library changes
if ((flag & (VideoLibrary | AudioLibrary)) == 0)
return;
--- a/xbmc/windows/GUIWindowHome.h 2016-09-17 16:35:22.000000000 +0100
+++ b/xbmc/windows/GUIWindowHome.h 2016-10-01 19:34:18.585113811 +0100
@@ -23,6 +23,8 @@
#include "guilib/GUIWindow.h"
#include "interfaces/IAnnouncer.h"
#include "utils/Job.h"
+#include "threads/Thread.h"
+#include "threads/Event.h"
class CVariant;
@@ -47,4 +49,7 @@
bool m_recentlyAddedRunning;
int m_cumulativeUpdateFlag;
+
+ CThread *m_ledthread;
+ CEvent *m_ledevent;
};
--- a/xbmc/windows/readpng.c 1970-01-01 00:00:00.000000000 +0000
+++ b/xbmc/windows/readpng.c 2016-01-08 06:49:51.049652775 +0000
@@ -0,0 +1,274 @@
+/*---------------------------------------------------------------------------
+
+ rpng - simple PNG display program readpng.c
+
+ ---------------------------------------------------------------------------
+
+ Copyright (c) 1998-2000 Greg Roelofs. All rights reserved.
+
+ This software is provided "as is," without warranty of any kind,
+ express or implied. In no event shall the author or contributors
+ be held liable for any damages arising in any way from the use of
+ this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute
+ it freely, subject to the following restrictions:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, disclaimer, and this list of conditions.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, disclaimer, and this list of conditions in the documenta-
+ tion and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this
+ software must display the following acknowledgment:
+
+ This product includes software developed by Greg Roelofs
+ and contributors for the book, "PNG: The Definitive Guide,"
+ published by O'Reilly and Associates.
+
+ ---------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "png.h" /* libpng header; includes zlib.h */
+#include "readpng.h" /* typedefs, common macros, public prototypes */
+
+
+static png_structp png_ptr = NULL;
+static png_infop info_ptr = NULL;
+
+png_uint_32 width, height;
+int bit_depth, color_type;
+uch *image_data = NULL;
+
+
+void readpng_version_info(void)
+{
+ fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n",
+ PNG_LIBPNG_VER_STRING, png_libpng_ver);
+}
+
+
+/* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */
+
+int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight)
+{
+ uch sig[8];
+
+
+ /* first do a quick check that the file really is a PNG image; could
+ * have used slightly more general png_sig_cmp() function instead */
+
+ fread(sig, 1, 8, infile);
+ if(png_sig_cmp(sig, 0, 8))
+ return 1; /* bad signature */
+
+
+ /* could pass pointers to user-defined error handlers instead of NULLs: */
+
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png_ptr)
+ return 4; /* out of memory */
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr) {
+ png_destroy_read_struct(&png_ptr, NULL, NULL);
+ return 4; /* out of memory */
+ }
+
+
+ /* we could create a second info struct here (end_info), but it's only
+ * useful if we want to keep pre- and post-IDAT chunk info separated
+ * (mainly for PNG-aware image editors and converters) */
+
+
+ /* setjmp() must be called in every function that calls a PNG-reading
+ * libpng function */
+
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ return 2;
+ }
+
+
+ png_init_io(png_ptr, infile);
+ png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */
+
+ png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */
+
+
+ /* alternatively, could make separate calls to png_get_image_width(),
+ * etc., but want bit_depth and color_type for later [don't care about
+ * compression_type and filter_type => NULLs] */
+
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
+ NULL, NULL, NULL);
+ *pWidth = width;
+ *pHeight = height;
+
+
+ /* OK, that's all we need for now; return happy */
+
+ return 0;
+}
+
+
+
+
+/* returns 0 if succeeds, 1 if fails due to no bKGD chunk, 2 if libpng error;
+ * scales values to 8-bit if necessary */
+
+int readpng_get_bgcolor(uch *red, uch *green, uch *blue)
+{
+ png_color_16p pBackground;
+
+
+ /* setjmp() must be called in every function that calls a PNG-reading
+ * libpng function */
+
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ return 2;
+ }
+
+
+ if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD))
+ return 1;
+
+ /* it is not obvious from the libpng documentation, but this function
+ * takes a pointer to a pointer, and it always returns valid red, green
+ * and blue values, regardless of color_type: */
+
+ png_get_bKGD(png_ptr, info_ptr, &pBackground);
+
+
+ /* however, it always returns the raw bKGD data, regardless of any
+ * bit-depth transformations, so check depth and adjust if necessary */
+
+ if (bit_depth == 16) {
+ *red = pBackground->red >> 8;
+ *green = pBackground->green >> 8;
+ *blue = pBackground->blue >> 8;
+ } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
+ if (bit_depth == 1)
+ *red = *green = *blue = pBackground->gray? 255 : 0;
+ else if (bit_depth == 2)
+ *red = *green = *blue = (255/3) * pBackground->gray;
+ else /* bit_depth == 4 */
+ *red = *green = *blue = (255/15) * pBackground->gray;
+ } else {
+ *red = (uch)pBackground->red;
+ *green = (uch)pBackground->green;
+ *blue = (uch)pBackground->blue;
+ }
+
+ return 0;
+}
+
+
+
+
+/* display_exponent == LUT_exponent * CRT_exponent */
+
+uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes)
+{
+ double gamma;
+ png_uint_32 i, rowbytes;
+ png_bytepp row_pointers = NULL;
+
+
+ /* setjmp() must be called in every function that calls a PNG-reading
+ * libpng function */
+
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ return NULL;
+ }
+
+
+ /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits,
+ * transparency chunks to full alpha channel; strip 16-bit-per-sample
+ * images to 8 bits per sample; and convert grayscale to RGB[A] */
+
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_expand(png_ptr);
+ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
+ png_set_expand(png_ptr);
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+ png_set_expand(png_ptr);
+ if (bit_depth == 16)
+ png_set_strip_16(png_ptr);
+ if (color_type == PNG_COLOR_TYPE_GRAY ||
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_gray_to_rgb(png_ptr);
+
+
+ /* unlike the example in the libpng documentation, we have *no* idea where
+ * this file may have come from--so if it doesn't have a file gamma, don't
+ * do any correction ("do no harm") */
+
+ if (png_get_gAMA(png_ptr, info_ptr, &gamma))
+ png_set_gamma(png_ptr, display_exponent, gamma);
+
+
+ /* all transformations have been registered; now update info_ptr data,
+ * get rowbytes and channels, and allocate image memory */
+
+ png_read_update_info(png_ptr, info_ptr);
+
+ *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr);
+ *pChannels = (int)png_get_channels(png_ptr, info_ptr);
+
+ if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ return NULL;
+ }
+ if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ free(image_data);
+ image_data = NULL;
+ return NULL;
+ }
+
+ Trace((stderr, "readpng_get_image: rowbytes = %ld, height = %ld\n", rowbytes, height));
+
+
+ /* set the individual row_pointers to point at the correct offsets */
+
+ for (i = 0; i < height; ++i)
+ row_pointers[i] = image_data + i*rowbytes;
+
+
+ /* now we can go ahead and just read the whole image */
+
+ png_read_image(png_ptr, row_pointers);
+
+
+ /* and we're done! (png_read_end() can be omitted if no processing of
+ * post-IDAT text/time/etc. is desired) */
+
+ free(row_pointers);
+ row_pointers = NULL;
+
+ png_read_end(png_ptr, NULL);
+
+ return image_data;
+}
+
+
+void readpng_cleanup(int free_image_data)
+{
+ if (free_image_data && image_data) {
+ free(image_data);
+ image_data = NULL;
+ }
+
+ if (png_ptr && info_ptr) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ png_ptr = NULL;
+ info_ptr = NULL;
+ }
+}
+
--- a/xbmc/windows/readpng.h 1970-01-01 00:00:00.000000000 +0000
+++ b/xbmc/windows/readpng.h 2016-01-08 06:49:51.049652775 +0000
@@ -0,0 +1,65 @@
+/*---------------------------------------------------------------------------
+
+ rpng - simple PNG display program readpng.h
+
+ ---------------------------------------------------------------------------
+
+ Copyright (c) 1998-2000 Greg Roelofs. All rights reserved.
+
+ This software is provided "as is," without warranty of any kind,
+ express or implied. In no event shall the author or contributors
+ be held liable for any damages arising in any way from the use of
+ this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute
+ it freely, subject to the following restrictions:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, disclaimer, and this list of conditions.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, disclaimer, and this list of conditions in the documenta-
+ tion and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this
+ software must display the following acknowledgment:
+
+ This product includes software developed by Greg Roelofs
+ and contributors for the book, "PNG: The Definitive Guide,"
+ published by O'Reilly and Associates.
+
+ ---------------------------------------------------------------------------*/
+
+#ifndef TRUE
+# define TRUE 1
+# define FALSE 0
+#endif
+
+#ifndef MAX
+# define MAX(a,b) ((a) > (b)? (a) : (b))
+# define MIN(a,b) ((a) < (b)? (a) : (b))
+#endif
+
+#ifdef DEBUG
+# define Trace(x) {fprintf x ; fflush(stderr); fflush(stdout);}
+#else
+# define Trace(x) ;
+#endif
+
+typedef unsigned char uch;
+typedef unsigned short ush;
+typedef unsigned long ulg;
+
+
+/* prototypes for public functions in readpng.c */
+
+void readpng_version_info(void);
+
+int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight);
+
+int readpng_get_bgcolor(uch *bg_red, uch *bg_green, uch *bg_blue);
+
+uch *readpng_get_image(double display_exponent, int *pChannels,
+ ulg *pRowbytes);
+
+void readpng_cleanup(int free_image_data);
+

View File

@ -1,18 +0,0 @@
--- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp 2016-09-17 16:35:20.000000000 +0100
+++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp 2016-10-01 19:26:40.470553260 +0100
@@ -527,6 +527,7 @@
m_info.m_wantsIECPassthrough = true;
list.push_back(m_info);
+#if 0
m_info.m_channels.Reset();
m_info.m_dataFormats.clear();
m_info.m_streamTypes.clear();
@@ -548,6 +549,7 @@
m_info.m_wantsIECPassthrough = true;
list.push_back(m_info);
+#endif
m_info.m_channels.Reset();
m_info.m_dataFormats.clear();

View File

@ -1,22 +0,0 @@
--- a/system/keymaps/keyboard.xml 2016-09-17 16:35:20.000000000 +0100
+++ b/system/keymaps/keyboard.xml 2016-10-01 19:31:07.928719606 +0100
@@ -56,7 +56,7 @@
<menu mod="longpress">Menu</menu>
<c>ContextMenu</c>
<c mod="longpress">Menu</c>
- <space>Pause</space>
+ <space>PlayPause</space>
<x>Stop</x>
<period>SkipNext</period>
<comma>SkipPrevious</comma>
@@ -321,8 +321,8 @@
<l>NextSubtitle</l>
<left>StepBack</left>
<right>StepForward</right>
- <up>ChapterOrBigStepForward</up>
- <down>ChapterOrBigStepBack</down>
+ <up>VolumeUp</up>
+ <down>VolumeDown</down>
<up mod="longpress">AudioNextLanguage</up>
<down mod="longpress">NextSubtitle</down>
<a>AudioDelay</a>

View File

@ -1,31 +0,0 @@
diff --git a/xbmc/windows/CMakeLists.txt b/xbmc/windows/CMakeLists.txt
index 3700602..c75f78f 100644
--- a/xbmc/windows/CMakeLists.txt
+++ b/xbmc/windows/CMakeLists.txt
@@ -1,3 +1,5 @@
+find_package(PNG REQUIRED)
+
set(SOURCES GUIMediaWindow.cpp
GUIWindowDebugInfo.cpp
GUIWindowFileManager.cpp
@@ -9,7 +11,8 @@ set(SOURCES GUIMediaWindow.cpp
GUIWindowSplash.cpp
GUIWindowStartup.cpp
GUIWindowSystemInfo.cpp
- GUIWindowWeather.cpp)
+ GUIWindowWeather.cpp
+ readpng.c)
set(HEADERS GUIMediaWindow.h
GUIWindowDebugInfo.h
@@ -22,6 +25,9 @@ set(HEADERS GUIMediaWindow.h
GUIWindowSplash.h
GUIWindowStartup.h
GUIWindowSystemInfo.h
- GUIWindowWeather.h)
+ GUIWindowWeather.h
+ readpng.h)
core_add_library(windows)
+
+target_link_libraries(windows PRIVATE ${PNG_LIBRARIES})

View File

@ -137,6 +137,10 @@ fi
# e.g. FIRMWARE="dvb-firmware misc-firmware wlan-firmware"
FIRMWARE="misc-firmware wlan-firmware dvb-firmware brcmfmac_sdio-firmware-rpi"
if [ "$DEVICE" = "Slice" -o "$DEVICE" = "Slice3" ]; then
FIRMWARE="$FIRMWARE slice-firmware"
fi
# build and install ATV IR remote support (yes / no)
ATVCLIENT_SUPPORT="no"
@ -155,3 +159,7 @@ fi
# Space separated list is supported,
# e.g. ADDITIONAL_DRIVERS="DRIVER1 DRIVER2"
ADDITIONAL_DRIVERS="$ADDITIONAL_DRIVERS media_build rpi-cirrus-config"
if [ "$DEVICE" = "Slice" -o "$DEVICE" = "Slice3" ]; then
ADDITIONAL_DRIVERS="$ADDITIONAL_DRIVERS slice-drivers"
fi

View File

@ -1,12 +0,0 @@
--- a/drivers/misc/Kconfig 2016-10-01 08:57:18.219952947 +0100
+++ b/drivers/misc/Kconfig 2016-10-01 09:18:14.792293152 +0100
@@ -4,6 +4,9 @@
menu "Misc devices"
+config BCM2835_WS2812
+ tristate "Support DMA user access to WS2812 LEDs"
+
config SENSORS_LIS3LV02D
tristate
depends on INPUT

View File

@ -1,10 +0,0 @@
--- a/drivers/misc/Makefile 2016-10-01 09:14:16.810942127 +0100
+++ b/drivers/misc/Makefile 2016-10-01 09:14:05.458686888 +0100
@@ -2,6 +2,7 @@
# Makefile for misc devices that really don't fit anywhere else.
#
+obj-$(CONFIG_BCM2835_WS2812) += ws2812.o
obj-$(CONFIG_IBM_ASM) += ibmasm/
obj-$(CONFIG_AD525X_DPOT) += ad525x_dpot.o
obj-$(CONFIG_AD525X_DPOT_I2C) += ad525x_dpot-i2c.o

View File

@ -1,539 +0,0 @@
--- a/drivers/misc/ws2812.c 2016-08-17 21:00:22.264000134 +0100
+++ b/drivers/misc/ws2812.c 2016-10-04 14:12:32.512699063 +0100
@@ -0,0 +1,536 @@
+/*
+ * Raspberry Pi WS2812 PWM driver
+ *
+ * Written by: Gordon Hollingworth <gordon@fiveninjas.com>
+ * Based on DMA PWM driver from Jonathan Bell <jonathan@raspberrypi.org>
+ *
+ * Copyright (C) 2014 Raspberry Pi Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * To use this driver you need to make sure that the PWM clock is set to 2.4MHz
+ * and the correct PWM0 output is connected. The best way to do this is to
+ * create a dt-blob.bin on your RaspberryPi, start by downloading the default
+ * dt-blob.dts from
+ *
+ * Note, this uses the same PWM hardware as the standard audio output on the Pi
+ * so you cannot use both simultaneously.
+ *
+ * http://www.raspberrypi.org/documentation/configuration/pin-configuration.md
+ *
+ * (Copy the bit from /dts-v1/; through to the end... This will contain the pin
+ * configuration for all the Raspberry Pi versions (since they are different.
+ * You can get rid of the ones you don't care about. Next alter the PWM0 output
+ * you want to use.
+ *
+ * http://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2835/BCM2835-ARM-Peripherals.pdf
+ *
+ * The link above will help understand what the GPIOs can do, check out page 102
+ * You can use: GPIO12, GPIO18 or GPIO40, so for the Slice board we use GPIO40 so
+ * we have the following in the dts file
+ *
+ * pin@p40 {
+ * function = "pwm";
+ * termination = "no_pulling";
+ * };
+ *
+ * And at the bottom of the dts file, although still in the 'videocore' block we
+ * have:
+ *
+ * clock_setup {
+ * clock@PWM { freq = <2400000>; };
+ * };
+ *
+ * To check whether the changes are correct you can use 'vcgencmd measure_clock 25'
+ * This should return the value 2400000
+ *
+ * Also if you use wiringPi then you can do 'gpio readall' to check that the pin
+ * alternate setting is set correctly.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fcntl.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/wait.h>
+#include <linux/io.h>
+#include <linux/ioctl.h>
+#include <linux/cdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/gpio/consumer.h>
+#include <asm-generic/ioctl.h>
+
+#define DRIVER_NAME "ws2812"
+
+struct ws2812_state {
+ struct device * dev;
+ struct cdev cdev;
+ struct class * cl;
+ struct dma_chan * dma_chan;
+ dma_addr_t dma_addr;
+
+ void __iomem * ioaddr;
+ phys_addr_t phys_addr;
+
+ uint8_t * buffer;
+ uint32_t * pixbuf;
+
+ struct gpio_desc * led_en;
+
+ unsigned char brightness;
+ u32 invert;
+ u32 num_leds;
+};
+
+#ifndef BCM2708_PERI_BASE
+ #define BCM2708_PERI_BASE 0x20000000
+#endif
+
+#define BCM2835_VCMMU_SHIFT (0x7E000000 - BCM2708_PERI_BASE)
+
+/* Each LED is controlled with a 24 bit RGB value
+ * each bit is created from a nibble of data either
+ * 1000 or 1110 so to create 24 bits you need 12 bytes
+ * of PWM output
+ */
+#define BYTES_PER_LED 12
+
+// Number of 2.4MHz bits in 50us to create a reset condition
+#define RESET_BYTES ((50 * 24) / 80)
+
+#define PWM_CTL 0x0
+#define PWM_STA 0x4
+#define PWM_DMAC 0x8
+#define PWM_RNG1 0x10
+#define PWM_DAT1 0x14
+#define PWM_FIFO1 0x18
+#define PWM_ID 0x50
+
+#define PWM_DMA_DREQ 5
+
+static dev_t devid = MKDEV(1337, 0);
+
+/*
+** Functions to access the pwm peripheral
+*/
+static void pwm_writel(struct ws2812_state * state, uint32_t val, uint32_t reg)
+{
+ writel(val, state->ioaddr + reg);
+}
+
+#if 0
+static uint32_t pwm_readl(struct ws2812_state * state, uint32_t reg)
+{
+ return readl(state->ioaddr + reg);
+}
+#endif
+
+/* Initialise the PWM module to use serial output
+ * mode
+ */
+static int pwm_init(struct ws2812_state * state)
+{
+ uint32_t reg;
+
+ // serial 32 bits per word
+ pwm_writel(state, 32, PWM_RNG1);
+ // Clear
+ pwm_writel(state, 0, PWM_DAT1);
+
+ reg = (1 << 0) | /* CH1EN */
+ (1 << 1) | /* serialiser */
+ (0 << 2) | /* don't repeat last word */
+ (0 << 3) | /* silence is zero */
+ ((state->invert ? 1 : 0) << 4) | /* polarity */
+ (1 << 5) | /* use fifo */
+ (1 << 6) | /* Clear fifo */
+ (1 << 7) | /* MSEN - Mask space enable */
+ ((state->invert ? 1 : 0) << 11); /* Silence bit = 1 */
+ pwm_writel(state, reg, PWM_CTL);
+ reg = (1 << 31) | /* DMA enabled */
+ (4 << 8) | /* Threshold for panic */
+ (8 << 0); /* Threshold for dreq */
+ pwm_writel(state, reg, PWM_DMAC);
+
+ return 0;
+
+}
+
+/*
+ * DMA callback function, release the mapping and the calling function
+ */
+void ws2812_callback(void * param)
+{
+ struct ws2812_state * state = (struct ws2812_state *) param;
+
+ dma_unmap_single(state->dev, state->dma_addr, state->num_leds * BYTES_PER_LED,
+ DMA_TO_DEVICE);
+
+}
+
+/*
+ * Issue a DMA to the PWM peripheral from the assigned buffer
+ * buffer must be unmapped again before being used
+ */
+int issue_dma(struct ws2812_state * state, uint8_t *buffer, int length)
+{
+ struct dma_async_tx_descriptor *desc;
+
+ state->dma_addr = dma_map_single(state->dev,
+ buffer, length,
+ DMA_TO_DEVICE);
+
+ if(state->dma_addr == 0)
+ {
+ pr_err("Failed to map buffer for DMA\n");
+ return -1;
+ }
+
+ desc = dmaengine_prep_slave_single(state->dma_chan, state->dma_addr,
+ length, DMA_TO_DEVICE, DMA_PREP_INTERRUPT);
+ if(desc == NULL)
+ {
+ pr_err("Failed to prep the DMA transfer\n");
+ return -1;
+ }
+
+ desc->callback = ws2812_callback;
+ desc->callback_param = state;
+ dmaengine_submit(desc);
+ dma_async_issue_pending(state->dma_chan);
+
+ return 0;
+}
+
+
+int clear_leds(struct ws2812_state * state)
+{
+ int i;
+
+ for(i = 0; i < state->num_leds * BYTES_PER_LED; i++)
+ state->buffer[i] = 0x88;
+ for(i = 0; i < RESET_BYTES; i++)
+ state->buffer[state->num_leds * BYTES_PER_LED + i] = 0;
+
+ issue_dma(state, state->buffer, state->num_leds * BYTES_PER_LED + RESET_BYTES);
+
+ return 0;
+}
+
+static int ws2812_open(struct inode *inode, struct file *file)
+{
+ struct ws2812_state * state;
+ state = container_of(inode->i_cdev, struct ws2812_state, cdev);
+
+ file->private_data = state;
+
+ return 0;
+}
+
+/* WS2812B gamma correction
+GammaE=255*(res/255).^(1/.45)
+From: http://rgb-123.com/ws2812-color-output/
+*/
+unsigned char gamma_(unsigned char brightness, unsigned char val)
+{
+ int bright = val;
+ unsigned char GammaE[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
+ 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5,
+ 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 11, 11,
+ 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18,
+ 19, 19, 20, 21, 21, 22, 22, 23, 23, 24, 25, 25, 26, 27, 27, 28,
+ 29, 29, 30, 31, 31, 32, 33, 34, 34, 35, 36, 37, 37, 38, 39, 40,
+ 40, 41, 42, 43, 44, 45, 46, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+ 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 83, 84, 85, 86, 88, 89,
+ 90, 91, 93, 94, 95, 96, 98, 99,100,102,103,104,106,107,109,110,
+ 111,113,114,116,117,119,120,121,123,124,126,128,129,131,132,134,
+ 135,137,138,140,142,143,145,146,148,150,151,153,155,157,158,160,
+ 162,163,165,167,169,170,172,174,176,178,179,181,183,185,187,189,
+ 191,193,194,196,198,200,202,204,206,208,210,212,214,216,218,220,
+ 222,224,227,229,231,233,235,237,239,241,244,246,248,250,252,255};
+ bright = (bright * brightness) / 255;
+ return GammaE[bright];
+}
+
+// LED serial output
+// 4 bits make up a single bit of the output
+// 1 1 1 0 -- 1
+// 1 0 0 0 -- 0
+//
+// Plus require a space of 50 microseconds for reset
+// 24 bits per led
+//
+// (24 * 4) / 8 = 12 bytes per led
+//
+// red = 0xff0000 == 0xeeeeeeee 0x88888888 0x88888888
+unsigned char * led_encode(struct ws2812_state * state, int rgb, unsigned char *buf)
+{
+ int i;
+ unsigned char red = gamma_(state->brightness, rgb >> 8);
+ unsigned char blu = gamma_(state->brightness, rgb);
+ unsigned char grn = gamma_(state->brightness, rgb >> 16);
+ int rearrange = red +
+ (blu << 8) +
+ (grn << 16);
+ for(i = 11; i >= 0; i--)
+ {
+ switch(rearrange & 3)
+ {
+ case 0: *buf++ = 0x88; break;
+ case 1: *buf++ = 0x8e; break;
+ case 2: *buf++ = 0xe8; break;
+ case 3: *buf++ = 0xee; break;
+ }
+ rearrange >>= 2;
+ }
+
+ return buf;
+}
+
+
+/* Write to the PWM through DMA
+ * Function to write the RGB buffer to the WS2812 leds, the input buffer
+ * contains a sequence of up to num_leds RGB32 integers, these are then
+ * converted into the nibble per bit sequence required to drive the PWM
+ */
+ssize_t ws2812_write(struct file *filp, const char __user *buf, size_t count, loff_t *pos)
+{
+ int32_t *p_rgb;
+ int8_t * p_buffer;
+ int i, length, num_leds;
+ struct ws2812_state * state = (struct ws2812_state *) filp->private_data;
+
+ num_leds = min(count/4, state->num_leds);
+
+ if(copy_from_user(state->pixbuf, buf, num_leds * 4))
+ return -EFAULT;
+
+ p_rgb = state->pixbuf;
+ p_buffer = state->buffer;
+ for(i = 0; i < num_leds; i++)
+ p_buffer = led_encode(state, *p_rgb++, p_buffer);
+
+ /* Fill rest with '0' */
+ memset(p_buffer, 0x00, RESET_BYTES);
+
+ length = (int) p_buffer - (int) state->buffer + RESET_BYTES;
+
+ /* Setup DMA engine */
+ issue_dma(state, state->buffer, length);
+
+ return count;
+}
+
+
+struct file_operations ws2812_fops = {
+ .owner = THIS_MODULE,
+ .llseek = NULL,
+ .read = NULL,
+ .write = ws2812_write,
+ .open = ws2812_open,
+ .release = NULL,
+};
+
+/*
+ * Probe function
+ */
+static int ws2812_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct device *dev = &pdev->dev;
+ struct device_node *node = dev->of_node;
+ struct ws2812_state * state;
+ const __be32 *addr;
+ struct resource *res;
+ struct dma_slave_config cfg =
+ {
+ .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+ .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+ .slave_id = PWM_DMA_DREQ,
+ .direction = DMA_MEM_TO_DEV,
+ .src_addr = 0,
+ };
+
+ if(node == NULL)
+ {
+ pr_err("Require device tree entry\n");
+ goto fail;
+ }
+
+ state = kmalloc(sizeof(struct ws2812_state), GFP_KERNEL);
+ if (!state) {
+ pr_err("Can't allocate state\n");
+ goto fail;
+ }
+
+ state->dev = dev;
+ state->brightness = 255;
+
+ // Create character device interface /dev/ws2812
+ if(alloc_chrdev_region(&devid, 0, 1, "ws2812") < 0)
+ {
+ pr_err("Unable to create chrdev region");
+ goto fail_malloc;
+ }
+ if((state->cl = class_create(THIS_MODULE, "ws2812")) == NULL)
+ {
+ unregister_chrdev_region(devid, 1);
+ pr_err("Unable to create class ws2812");
+ goto fail_chrdev;
+ }
+ if(device_create(state->cl, NULL, devid, NULL, "ws2812") == NULL)
+ {
+ class_destroy(state->cl);
+ unregister_chrdev_region(devid, 1);
+ pr_err("Unable to create device ws2812");
+ goto fail_class;
+ }
+
+ state->cdev.owner = THIS_MODULE;
+ cdev_init(&state->cdev, &ws2812_fops);
+
+ if(cdev_add(&state->cdev, devid, 1)) {
+ pr_err("CDEV failed\n");
+ goto fail_device;
+ }
+
+ platform_set_drvdata(pdev, state);
+
+ /* get parameters from device tree */
+ of_property_read_u32(node,
+ "rpi,invert",
+ &state->invert);
+ of_property_read_u32(node,
+ "rpi,num_leds",
+ &state->num_leds);
+
+ state->pixbuf = kmalloc(state->num_leds * sizeof(int), GFP_KERNEL);
+ if(state->pixbuf == NULL)
+ {
+ pr_err("Failed to allocate internal buffer\n");
+ goto fail_cdev;
+ }
+
+ /* base address in dma-space */
+ addr = of_get_address(node, 0, NULL, NULL);
+ if (!addr) {
+ dev_err(dev, "could not get DMA-register address - not using dma mode\n");
+ goto fail_pixbuf;
+ }
+ state->phys_addr = be32_to_cpup(addr);
+ pr_err("bus_addr = 0x%x\n", state->phys_addr);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ state->ioaddr = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(state->ioaddr)) {
+ pr_err("Failed to get register resource\n");
+ goto fail_pixbuf;
+ }
+
+ pr_err("ioaddr = 0x%x\n", (int) state->ioaddr);
+
+ state->buffer = kmalloc(state->num_leds * BYTES_PER_LED + RESET_BYTES, GFP_KERNEL);
+ if(state->buffer == NULL)
+ {
+ pr_err("Failed to allocate internal buffer\n");
+ goto fail_pixbuf;
+ }
+
+ state->dma_chan = dma_request_slave_channel(dev, "pwm_dma");
+ if(state->dma_chan == NULL)
+ {
+ pr_err("Failed to request DMA channel");
+ goto fail_buffer;
+ }
+
+ /* request a DMA channel */
+ cfg.dst_addr = state->phys_addr + PWM_FIFO1;
+ ret = dmaengine_slave_config(state->dma_chan, &cfg);
+ if (state->dma_chan < 0) {
+ pr_err("Can't allocate DMA channel\n");
+ goto fail_dma_init;
+ }
+ pwm_init(state);
+
+ // Enable the LED power
+ state->led_en = devm_gpiod_get(dev, "led-en", GPIOD_OUT_HIGH);
+
+ clear_leds(state);
+
+ return 0;
+fail_dma_init:
+ dma_release_channel(state->dma_chan);
+fail_buffer:
+ kfree(state->buffer);
+fail_pixbuf:
+ kfree(state->pixbuf);
+fail_cdev:
+ cdev_del(&state->cdev);
+fail_device:
+ device_destroy(state->cl, devid);
+fail_class:
+ class_destroy(state->cl);
+fail_chrdev:
+ unregister_chrdev_region(devid, 1);
+fail_malloc:
+ kfree(state);
+fail:
+
+ return -1;
+}
+
+
+static int ws2812_remove(struct platform_device *pdev)
+{
+ struct ws2812_state *state = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ dma_release_channel(state->dma_chan);
+ kfree(state->buffer);
+ kfree(state->pixbuf);
+ cdev_del(&state->cdev);
+ device_destroy(state->cl, devid);
+ class_destroy(state->cl);
+ unregister_chrdev_region(devid, 1);
+ kfree(state);
+
+ return 0;
+}
+
+static const struct of_device_id ws2812_match[] = {
+ { .compatible = "rpi,ws2812" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ws2812_match);
+
+static struct platform_driver ws2812_driver = {
+ .probe = ws2812_probe,
+ .remove = ws2812_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = ws2812_match,
+ },
+};
+module_platform_driver(ws2812_driver);
+
+MODULE_ALIAS("platform:ws2812");
+MODULE_DESCRIPTION("WS2812 PWM driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Gordon Hollingworth");

View File

@ -1,279 +0,0 @@
--- a/sound/soc/bcm/slice.c 1969-12-31 16:00:00.000000000 -0800
+++ b/sound/soc/bcm/slice.c 2017-02-15 14:39:20.402591342 -0800
@@ -0,0 +1,276 @@
+ /*
+ * ASoC Driver for Slice on-board sound
+ *
+ * Author: James Adams <james@fiveninjas.com>
+ * Based on the HifiBerry DAC driver by Florian Meier <florian.meier@koalo.de>
+ * Copyright 2014
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+
+ #include <linux/io.h>
+ #include <linux/clk.h>
+
+ #include <sound/core.h>
+ #include <sound/pcm.h>
+ #include <sound/pcm_params.h>
+ #include <sound/soc.h>
+ #include <sound/jack.h>
+
+ #include "../codecs/cs4265.h"
+
+struct clk * gp0_clock;
+
+ static int snd_slice_init(struct snd_soc_pcm_runtime *rtd)
+ {
+ return 0;
+ }
+
+ static int snd_slice_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+ {
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_codec *codec = rtd->codec;
+ int err;
+ int ret;
+ unsigned int rate = params_rate(params);
+ unsigned int sysclk = 12288000;
+
+ switch (rate) {
+ case 32000:
+ sysclk = 12288000;
+ break;
+ case 44100:
+ sysclk = 11289600;
+ break;
+ case 48000:
+ sysclk = 12288000;
+ break;
+ case 64000:
+ sysclk = 12288000;
+ break;
+ case 88200:
+ sysclk = 11289600;
+ break;
+ case 96000:
+ sysclk = 12288000;
+ break;
+ case 128000:
+ dev_err(codec->dev,
+ "Failed to set CS4265 SYSCLK, sample rate not supported in ALSA: 128000\n");
+ break;
+ case 176400:
+ sysclk = 11289600;
+ break;
+ case 192000:
+ sysclk = 12288000;
+ break;
+ default:
+ dev_err(codec->dev,
+ "Failed to set CS4265 SYSCLK, sample rate not supported\n");
+ break;
+ }
+
+ // Need two frequencies: 12.288 or 11.2896MHz
+ // Source is 1,806,336,000
+ // /4 /40 - 1128960
+ // /7 /21 - 1228800
+ clk_disable_unprepare(gp0_clock);
+
+ err = clk_set_rate(gp0_clock, sysclk);
+ if(err < 0)
+ pr_err("Failed to set clock rate for gp0 clock\n");
+
+ if((ret = clk_prepare_enable(gp0_clock)) < 0)
+ pr_err("Failed to enable clock\n");
+
+ dev_err(codec->dev, "Set sampling frequency %d, using sysclk %d\n", rate, sysclk);
+
+ err = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk,
+ SND_SOC_CLOCK_OUT);
+
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+
+ if (ret) {
+ dev_err(cpu_dai->dev,
+ "Failed to set the cpu dai format.\n");
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM);
+ if (ret) {
+ dev_err(cpu_dai->dev,
+ "Failed to set the codec format.\n");
+ return ret;
+ }
+
+ snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
+
+ return 0;
+ }
+
+ static int snd_slice_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+ {
+ printk(KERN_ERR "snd_slice_params_fixup called\n");
+ /* force 32 bit */
+ params_set_format(params, SNDRV_PCM_FORMAT_S32_LE);
+ return 0;
+ }
+
+ /* machine stream operations */
+ static struct snd_soc_ops snd_slice_ops = {
+ .hw_params = snd_slice_hw_params,
+ };
+
+ /* Widgets */
+ static const struct snd_soc_dapm_widget snd_slice_dapm_widgets[] = {
+ SND_SOC_DAPM_SPK("Speaker 1", NULL),
+ SND_SOC_DAPM_SPK("Speaker 2", NULL),
+ SND_SOC_DAPM_MIC("Mic 1", NULL),
+ SND_SOC_DAPM_MIC("Mic 2", NULL),
+ SND_SOC_DAPM_MIC("LineIn 1", NULL),
+ SND_SOC_DAPM_MIC("LineIn 2", NULL),
+ SND_SOC_DAPM_SPK("Spdif", NULL),
+ };
+
+ /* Audio Map */
+ static const struct snd_soc_dapm_route snd_slice_audio_map[] = {
+ {"Speaker 1", NULL, "LINEOUTL"},
+ {"Speaker 2", NULL, "LINEOUTR"},
+ {"MICL", NULL, "Mic 1"},
+ {"MICR", NULL, "Mic 2"},
+ {"LINEINL", NULL, "LineIn 1"},
+ {"LINEINR", NULL, "LineIn 2"},
+ {"Spdif", NULL, "SPDIF"},
+ };
+
+ static const struct snd_soc_pcm_stream snd_slice_params = {
+ .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE,
+ };
+
+ static struct snd_soc_dai_link snd_slice_dai[] = {
+ {
+ .name = "Slice",
+ .stream_name = "Slice HiFi",
+ .cpu_dai_name = "bcm2708-i2s.0",
+ .codec_dai_name = "cs4265-dai1",
+ .platform_name = "bcm2708-i2s.0",
+ .codec_name = "cs4265.1-004e",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
+ .ops = &snd_slice_ops,
+ .init = snd_slice_init,
+ .be_hw_params_fixup = snd_slice_params_fixup,
+ },
+ };
+
+ /* audio machine driver */
+ static struct snd_soc_card snd_slice = {
+ .name = "snd_slice",
+ .dai_link = snd_slice_dai,
+ .num_links = ARRAY_SIZE(snd_slice_dai),
+ .fully_routed = 1,
+ .dapm_widgets = snd_slice_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(snd_slice_dapm_widgets),
+ .dapm_routes = snd_slice_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(snd_slice_audio_map),
+ };
+
+ static int snd_slice_probe(struct platform_device *pdev)
+ {
+ int ret = 0;
+ snd_slice.dev = &pdev->dev;
+
+ if (pdev->dev.of_node) {
+ struct device_node *i2s_node;
+ struct snd_soc_dai_link *dai = &snd_slice_dai[0];
+ i2s_node = of_parse_phandle(pdev->dev.of_node,
+ "i2s-controller", 0);
+
+ if (i2s_node) {
+ dai->cpu_dai_name = NULL;
+ dai->cpu_of_node = i2s_node;
+ dai->platform_name = NULL;
+ dai->platform_of_node = i2s_node;
+ }
+ }
+ else
+ {
+ printk(KERN_ERR "SLICEAUDIO - ERROR no Device Tree!\n");
+ }
+
+ ret = snd_soc_register_card(&snd_slice);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "snd_soc_register_card() failed: %d\n", ret);
+ goto snd_soc_register_card_failed;
+ }
+
+ gp0_clock = devm_clk_get(&pdev->dev, "gp0");
+ if (IS_ERR(gp0_clock)) {
+ pr_err("Failed to get gp0 clock\n");
+ return PTR_ERR(gp0_clock);
+ }
+
+ ret = clk_set_rate(gp0_clock, 12288000);
+ if (ret) {
+ pr_err("Failed to set the GP0 clock rate\n");
+ return ret;
+ }
+
+ ret = clk_prepare_enable(gp0_clock);
+ if (ret) {
+ pr_err("Failed to turn on gp0 clock: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+
+ snd_soc_register_card_failed:
+
+ return ret;
+ }
+
+ static int snd_slice_remove(struct platform_device *pdev)
+ {
+ return snd_soc_unregister_card(&snd_slice);
+ }
+
+ static const struct of_device_id slice_of_match[] = {
+ { .compatible = "fiveninjas,slice", },
+ {},
+ };
+ MODULE_DEVICE_TABLE(of, slice_of_match);
+
+ static struct platform_driver snd_slice_driver = {
+ .driver = {
+ .name = "snd-slice",
+ .owner = THIS_MODULE,
+ .of_match_table = slice_of_match,
+ },
+ .probe = snd_slice_probe,
+ .remove = snd_slice_remove,
+ };
+
+ module_platform_driver(snd_slice_driver);
+
+ MODULE_AUTHOR("James Adams <james@fiveninjas.com>");
+ MODULE_DESCRIPTION("ASoC Driver for Slice on-board audio");
+ MODULE_LICENSE("GPL v2");

View File

@ -1,17 +0,0 @@
--- a/sound/soc/bcm/Kconfig 2016-10-24 08:46:19.034757161 +0100
+++ b/sound/soc/bcm/Kconfig 2016-10-24 08:52:36.735342726 +0100
@@ -131,6 +131,13 @@ config SND_BCM2708_SOC_ALLO_PIANO_DAC
help
Say Y or M if you want to add support for Allo Piano DAC.
+config SND_BCM2708_SOC_SLICE
+ tristate "Support for Slice on-board sound"
+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
+ select SND_SOC_CS4265
+ help
+ Say Y or M if you want to add support for Slice on-board sound.
+
config SND_PISOUND
tristate "Support for Blokas Labs pisound"
depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S

View File

@ -1,15 +0,0 @@
--- a/sound/soc/bcm/Makefile 2016-10-24 08:57:16.805712924 +0100
+++ b/sound/soc/bcm/Makefile 2016-10-24 08:59:51.541235893 +0100
@@ -26,6 +26,7 @@ snd-soc-digidac1-soundcard-objs := digid
snd-soc-allo-piano-dac-objs := allo-piano-dac.o
snd-soc-pisound-objs := pisound.o
snd-soc-fe-pi-audio-objs := fe-pi-audio.o
+snd-soc-slice-objs := slice.o
obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o
obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o
@@ -44,3 +45,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2) +=
obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC) += snd-soc-allo-piano-dac.o
obj-$(CONFIG_SND_PISOUND) += snd-soc-pisound.o
obj-$(CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO) += snd-soc-fe-pi-audio.o
+obj-$(CONFIG_SND_BCM2708_SOC_SLICE) += snd-soc-slice.o