Cyfrowa ramka na zdjęcia stała się obiektem pożądania wielu osób które chciały takie urządzenie podłączyć do routera. Są stosunkowo tanie, choć mają ekran niewielkich rozmiarów to umożliwiają wyświetlenie jakiś informacji z routera tym samym wzbogacając jego możliwości. Ramka którą otrzymałem od pepe2k -
Samsung SPF-72H - ani nie jest tania ani nie jest mała - ma
7" ekran umożliwiający wyświetlanie obrazu o rozdzielczości
800x480. Samsung jednak wykonał ją w ciekawy sposób - sama w sobie wyposażona jest w szeroki zestaw złącz dla kart pamięci i USB, umożliwiając wyświetlanie zdjęć z różnych nośników, ma także złącze usb klienckie przez które można podłączyć ramkę do komputera i używać jej jako pamięci masowej. Co więcej - po przez wysłanie odpowiedniego kodu można ramkę przełączyć (technologia wykorzystana podobnie jak w modemach 3G) w inny tryb pracy, dzięki któremu możliwe jest wysyłanie plików jpg bezpośrednio do wyświetlania. Nie trzeba więc jej specjalnie "hackować", wystarczy tylko przełączyć ją w odpowiedni tryb.
Jak większość ramek cyfrowych i wyświetlaczy LCD/LED, i to urządzenie można obsługiwać przy pomocy programu
lcd4linux. Nowsze wersje źródeł zawierają już sterownik o nazwie SamsungSPF, niestety jest on przeznaczony dla ramek SPF-75H, SPF-85H, SPF-107H. Wystarczy więc niewielka poprawka żeby sterownik zechciał ją zobaczyć.
--- drv_SamsungSPF.c.orig 2012-02-23 07:36:53.000000000 +0100
+++ drv_SamsungSPF.c 2014-01-20 09:37:07.648238198 +0100
@@ -69,6 +69,13 @@
static struct SPFdev spfDevices[] = {
{
+ .type = "SPF-72H",
+ .vendorID = 0x04e8,
+ .productID = {0x200a, 0x200b},
+ .xRes = 800,
+ .yRes = 480,
+ },
+ {
.type = "SPF-75H",
.vendorID = 0x04e8,
.productID = {0x200e, 0x200f},
@@ -203,7 +210,7 @@
}
int res = -1;
- char buf[256];
+ char buf[254];
if (myDev->descriptor.idProduct == myFrame->productID.storageMode) {
info("%s: Opening device and switching to monitor mode", Name);
@@ -216,7 +223,7 @@
res = usb_get_string_simple(myDevHandle, myDev->descriptor.iManufacturer, buf, sizeof(buf));
debug("usb_get_string_simple => %d, %s", res, buf);
- memset(buf, 0, 256);
+ memset(buf, 0, 254);
res = usb_control_msg(myDevHandle, USB_TYPE_STANDARD | USB_ENDPOINT_IN,
USB_REQ_GET_DESCRIPTOR, 0xfe, 0xfe, buf, 0xfe, 1000);
@@ -253,31 +260,17 @@
int usb_timeout = 1000;
int usb_endpoint = 0x2;
int ret;
+ #define URBBUF_MAX 0x20000
+ char buf[URBBUF_MAX];
*(int *) (usb_hdr + 4) = len;
- debug("bytes_to_send: %d, offset: %d", len, 12);
+ memset(buf, 0, URBBUF_MAX);
+ memcpy(buf, usb_hdr, 12);
+ if (len < URBBUF_MAX)
+ memcpy(buf + 12, data, len);
- /* Send USB header */
- if ((ret = usb_bulk_write(myDevHandle, usb_endpoint, usb_hdr, 12, usb_timeout)) < 0) {
- error("%s: Error occurred while writing data to device.", Name);
- error("%s: usb_bulk_write returned: %d", Name, ret);
- return -1;
- }
-
- /* Send JPEG image */
- if ((ret = usb_bulk_write(myDevHandle, usb_endpoint, data, len, usb_timeout)) < 0) {
- error("%s: Error occurred while writing data to device.", Name);
- error("%s: usb_bulk_write returned: %d", Name, ret);
- return -1;
- }
-
- /* Finish transmission by sending zero */
- if ((ret = usb_bulk_write(myDevHandle, usb_endpoint, buffer, 1, usb_timeout)) < 0) {
- error("%s: Error occurred while writing data to device.", Name);
- error("%s: usb_bulk_write returned: %d", Name, ret);
- return -1;
- }
+ ret = usb_bulk_write(myDevHandle, usb_endpoint, buf, URBBUF_MAX, usb_timeout);
return 0;
}
Kolejne zmiany to zmiana sposobu wysyłania obrazu do ramki; ten model jest dość wrażliwy i często zgłasza timeouty na magistrali usb, więc warto się tego pozbyć. Sekcje
Display w pliku konfiguracyjnym
lcd4linux deklaruje się wtedy w następujący sposób:
Display SamsungSPF {
Driver 'SamsungSPF'
Model 'spf-72h'
Update 500
}
...
Display 'SamsungSPF'
Layout ...
Po szczegóły odnośnie projektu lcd4linux odsyłam do innego mojego
opisu. Niestety, trzeba się dość dużo natrudzić aby zapełnić taką wielką przestrzeń jaką oferuje ramka, co więcej - lcd4linux z definicji wyświetla wszystko w postaci matrycy znaków, więc efekt końcowy może być daleki od oczekiwań.
Co można więc uzyskać więcej? Jak już wspomniałem ramka umożliwia po prostu wyświetlanie plików jpg, więc można wymaganą treść przygotować w postaci obrazka. Poza samym obrazkiem potrzebujemy dwa programy: jeden do przełączenia ramki w odpowiedni tryb pracy i drugi do wyświetlenia samego zdjęcia, a oba programy dostępne są pod adresem
http://web.media.mit.edu/~gracewoo/stuff/picframe/. Wymagają one delikatnego przerobienia (trzeba zmienić identyfikatory wskazując na tą ramkę, czyli 0x200a i 0x200b].
Przełączenie ramki:
# controlmsg
Urządzenie początkowo ma identyfikator 04e0:200a, po przełączeniu - 04e0:200b. Obecność tego drugiego identyfikatora dopiero umożliwia wyświetlenie zdjęcia, które wykonujemy poleceniem
# echo "obrazek.jpg" | playusb 0
Tylko teraz niezbędny jest odpowiedni plik jpeg do wyświetlenia. Musi on mieć rozdzielczość 800x480 (w innym rozmiarze nie będzie wyświetlał się poprawnie). Albo posługujemy się gotowymi zdjęciami albo można je przygotować "w locie" wykorzystując program
convert z pakietu
imagemagick (uwaga: program convert z OpenWrt nie działa poprawnie, brak mu wszystkich niezbędnych plików do działania). Przygotowanie obrazka jest stosunkowo proste (google dostarczy wielu stron z poradnikami jak uzyskać różne efekty) - na przykład można zrobić zwykły status systemu:
# sysinfo.sh | convert -size 800x480 -font FreeMono-Normalny -pointsize 20 caption:@- /tmp/sysinfo.jpg
A później go wyświetlić:
# echo "/tmp/sysinfo.jpg" | playusb 0
(sorry za jakość ale interferencje wychodzą)
Można to zrobić cyklicznie w cronie lub pisząc prosty skrypt z pętlą.