Блог о Gentoo и около-линуксовым штукам

Показаны сообщения с ярлыком Железо. Показать все сообщения
Показаны сообщения с ярлыком Железо. Показать все сообщения

10 апреля 2018 г.

NoWOL: питание ПК через интернет. Часть 2.

05:55 Опубликовал Дмитрий Исаенко , , Нет комментариев
Продолжаем! Для проекта NoWOL есть Android-приложение с виджетом.

Вообще, там всё весьма просто. Как будет возможность (не лень), загружу исходники в GitHub. Пока же там лежит вполне готовая к использованию APK'шка.
Из ключевых моментов: внутри используется библиотека Volley; работает приложение под Android 4.0 и выше (minSdkVersion 14, target 26).

UPD: Исходники https://github.com/developersu/NoWOL-APK
Архитектура проста донельзя. Приложение отправляет HTTP-запросы по указанному адресу и парсит ответы.

А теперь скриншоты!

После установки станет доступно основное приложение, а в разделе виджетов появится новый виджет с одноимённым названием «NoWOL».

Что касается приложения, то в нём доступно несколько состояний: неизвестно, онлайн, офлайн, нет ответа (от хоста). Обновить состояние можно нажав на кнопочку в верхней панели.


Если нажать на шестерёнку на верхней панели, всплывёт окно для указания IP хоста в сети. Следует обратить внимание на формат записи. Защиты от дурака там, к сожалению, не так много как хотелось бы. Вот хороший пример:

  

При добавлении виджета появится окно конфигуратора. Как видно, в нём нет указателя на адрес хоста. Он настраивается внутри приложения, поэтому сперва стоит запустить его.
Зато в конфигураторе можно выбрать задний фон (белый или чёрный) с альфа-каналом и уровень его прозрачности.
UI немного неочевиден и меняется в зависимости от выбора "галочки". Я знаю, так делать нехорошо.


В итоге, после добавления, виджет будет выглядеть как-то так (см. ниже). В его верхней строке может отображаться один из трёх возможных статусов. В отличии от приложения, там нет варианта "неизвестно". Зато вдалеке от домашней сети будет красоваться "нет ответа".

Забавный момент: если ПК в режиме ожидания, то статус будет или "онлайн" или "офлайн" в зависимости от того, мигнула ли лампочка в момент запроса состояния :)

Принудительно обновить статус можно ловко попав по верхнему правому углу, или через приложение — оно передаст полученные данные в виджет. 
Вообще, статус обновляется сам каждые пол часа (если мне не изменяет память, но уж точно не чаще). Сделано это только для того, чтобы не сажать батарею телефона почём зря.


В общем-то на этом всё. Надеюсь, вам понравилось =)

NoWOL: питание ПК через интернет. Часть 1.

04:28 Опубликовал Дмитрий Исаенко , , , Нет комментариев
Ох, давно хотел уже задокументировать это здесь, да всё времени не было. И вот, спустя полтора года…

Какую проблему решаем?

Стоит задача включать и выключать ПК нажимая на кнопки включения\выключения и сброса не руками, а через интернет (ну или через тоннель в интранет). В идеале спросонья через виджет в телефоне а-ля узнал погоду за бортом, включил ПК и можно идти ставить кофе.

Для этого было решено пилить какой-то контроллер Atmega с каким-то ethernet-свистком, чтобы он через оптопары замыкал кнопки включения. А заодно сообщал об успехе или неуспехе затеи.

Немного покопавшись я решил закупить основанную на enc28j60 приблуду для ардуины, а заодно и саму ардуину. Изучив особенности программирования enc28j60 руками (без высокоуровневых IDE и готовых библиотек) и бегло осмотрев errata, который, надо отметить, чуть ли не больше даташита, стало ясно, что на низком уровне рулить “этим” сущий ад и боль. Поэтому, будем собирать всё на базе добротного китайского клона Arduino nano или функционального аналога (лучше просто взять arduino, правда).

В итоге система будет состоять из основного модуля в виде связки Arduino+enc28j60 и выносного блока с оптопарами и резисторами.

В целом выглядеть и подключаться всё будет так:

Но перед тем, как начать…

Поставим себе пару пакетов:
1. dev-embedded/arduino
2. sci-electronics/eagle (ветка 7.x.x и лучше из нестабильной ветки) 
Все необходимые файлы лежат в проекте на GitHub:
https://github.com/developersu/NoWOL

Про выносной модуль

Файлы для Eagle CAD находятся в директории eagle_files/m2Board/ .
Необходимые библиотеки в eagle_files/lib/ .

Для выносного модуля понадобится:

Part Value Device Package Library Sheet
IC2 КР293КП4А DIL08 ic-package 1
IC3 КР293КП4А DIL08 ic-package 1
IN PINHD-1X6 1X06 pinhead 1
OUT PINHD-1X6 1X06 pinhead 1
R1 450Ω или 470Ω R-EU_0204/5 0204/5 resistor 1
R2 450Ω или 470Ω R-EU_0204/5 0204/5 resistor 1
R3 330Ω R-EU_0204/5 0204/5 resistor 1
TO_MCU PINHD-1X5 1X05 pinhead 1

По-поводу R1 и R2 резисторов, я собрал две пары, чтобы получилось 450 Ом в каждой. Думаю, что если взять просто пару штук на 470 Ом всё тоже будет работать. Но всё же обещать не буду.

Его принципиальная схема выглядит весьма просто:

Разводка выполняется на односторонней плате:


* 'cuz soviet works better
Если присмотреться, разводка слегка отличается от той, что приведена на первом рисунке. Тут я убрал перемычку.

Как вы уже поняли, в качестве оптопар используется отечественная схема КР293КП4А в корпусе DIP8. Внутри каждой микросхемы находится 2 оптопары. Одна из схем замыкает и размыкает кнопки (питание и сброс), а вторая говорит микроконтроллеру включена ли система, определяя это по светодиоду-индикатору питания. Если первую микросхему замыкает МК, то вторую — ПК. Через отдельный пин микроконтроллер зажигает индикатор питания сам, когда понимает, что и система (ПК) тоже его зажгла. Уж не знаю.. может это несколько избыточно и можно было сделать проще. Впрочем, получилось как получилось.

Примечание: наверное надо было навесить на вторую оптопару какие-то резисторы.. но блин, datasheet по ним такой немногословный. В общем как-то работает уже больше года, так что, пока всё не сгорело, имеет право на жизнь.

Если всё спаять и приправить должным количеством пыли, получится примерно следующее:


Про программирование Arduino

Теперь перейдём к программированию Arduino. Как говорилось ранее, предполагается использование Arduino Nano.
Я уже не помню что куда нажимать и подключать, чтобы это дело прошить но у меня есть скетч!
Для этого скетча понадобится библиотека ehtercard. И скетч и библиотека находятся в директории arduino_sketchbook/.

А вот и сам код:
#include <EtherCard.h>

#define PWR_PIN 6
#define RST_PIN 7
#define PWR_LED_IN 8
#define PWR_LED_OUT 5


int i;
// Зададим MAC адрес устройства
static byte mymac[] = { 0xDE,0xAD,0xBE,0xEE,0xEE,0xEF };
 
// Чем больше данных отображается на странице, тем больше требуется буфер для них
byte Ethernet::buffer[900];
BufferFiller bfill;
 
//Массив задействованных контактов для управления оптопарами
int LedPins[] = {PWR_PIN,RST_PIN};
 
//Массив для фиксации изменений
boolean PinUpdate = 0;      //100-reset 200-power 5050-powerOFF
 
const char http_OK[] PROGMEM =
"HTTP/1.0 200 OK\r\n"
"Content-Type: text/html\r\n"
"Pragma: no-cache\r\n\r\n"
"\r\n"
"<html>"
  "<head><title>"
    "noWOL"
  "</title><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"><style>"
  "body { font-family: monospace;\n"
   "background-color: #000000;\n"
   "font-size: 30px;\n"
   "font-weight: bold;\n"
   "color: #b2b2b2;}\n"
   "a:link, a:visited {  display: inline-block;\n"
  "color: #b2b2b2;\n"
  "font-weight: 700;\n"
  "text-decoration: none;\n"
  "padding: .3em 2em;\n"
  "outline: none;\n"
  "border: 2px solid;\n"
  "border-radius: 15px;\n"
  "transition: 0.2s;}\n"
  "a:hover {color: #fefefe;}\n"
  "</style></head>"
  "<body><center>"
;
const char http_Found[] PROGMEM =
"HTTP/1.0 302 Found\r\n"
"Location: /\r\n\r\n";

const char http_Unauthorized[] PROGMEM =
"HTTP/1.0 401 Unauthorized\r\n"
"Content-Type: text/html\r\n\r\n"
"401 Unauthorized";
 
void homePage()
{
bfill.emit_p(PSTR("$F"
  " "
  "$F<p>"
  "<a href='?RESET=on'>  RESET   </a><p>"  //D6
  "<a href='?POWER0=on'>  POWER   </a><p>" //D7 short
  "<a href='?POWER1=on'>POWER 5sec</a><br />"),  //D7 long
  //"PWR LED out D5 : $F <br /></body></html>"),
  
  http_OK,
  (digitalRead(PWR_LED_IN) == HIGH)?PSTR("<span style=\"color: #AA0000\">          ▄▄▄▄▄▄</span>"):PSTR("<span style=\"color: #00c600\">          ▄▄▄▄▄▄</span>")),//⬤
//  (bitRead(PORTD,PWR_LED_OUT) == HIGH)?PSTR("HIGH"):PSTR("LOW")),

"</center></body>"
"</html>"
  ;
}

void pick_pin(int pin, int del) {
      digitalWrite(pin,HIGH);
        delay(del);
        digitalWrite(pin,LOW);
        PinUpdate = 0;
}
 
void setup()
{
// SET UART
//  Serial.begin(9600);
//Change default ethercard CS - pin 8 to 10
  //if (ether.begin(sizeof Ethernet::buffer, mymac, 10) == 0)

//  Serial.println( "Access to Ethernet controller failed");
    ether.begin(sizeof Ethernet::buffer, mymac, 10);
    ether.dhcpSetup();
//  if (!ether.dhcpSetup())
//       Serial.println("DHCP routine failed");
    //Print over UART configuration recieved:
//  ether.printIp("IP:  ", ether.myip);          
//  ether.printIp("GW:  ", ether.gwip);  
//  ether.printIp("DNS: ", ether.dnsip);  

  for(i = 0; i < 2; i++) {
    pinMode(LedPins[i],OUTPUT);
  }
  
    pinMode(PWR_LED_OUT,OUTPUT);
    pinMode(PWR_LED_IN,INPUT_PULLUP); // LED-питания как вход
}
 
void loop()
{
    delay(1);

        if (digitalRead(PWR_LED_IN) == HIGH) {        // если мать выключена
            if (bitRead(PORTD,PWR_LED_OUT) == HIGH) digitalWrite(PWR_LED_OUT,LOW);
        }
        else if (bitRead(PORTD,PWR_LED_OUT) == LOW) {
          digitalWrite(PWR_LED_OUT,HIGH);
        }

        switch (PinUpdate) {
          case 0:
            break;
          case 1:
            pick_pin(RST_PIN, 200);
            break;
          case 2:
            pick_pin(PWR_PIN, 200);
            break;
          case 3:
            pick_pin(PWR_PIN, 5050);
            break;
        }

    word len = ether.packetReceive(); //Проверить ethernet пакеты
    word pos = ether.packetLoop(len); //Проверить TCP пакеты
    if (pos) {
        bfill = ether.tcpOffset();
        char *data = (char *) Ethernet::buffer + pos;
        if (strncmp("GET /", data, 5) != 0) {
            bfill.emit_p(http_Unauthorized);
        }
        else {
            data += 5;
            if (data[0] == ' ') {
                    homePage(); //Если обнаружено изменения на станице, то запускаем функцию
            }
            //"10" = количество символов "?RESET=on ".
            else if (strncmp("?RESET=on ", data, 10) == 0) {
                bfill.emit_p(http_Found);
                                PinUpdate = 1;
            }
 
            else if (strncmp("?POWER0=on ", data, 11) == 0) {
                  bfill.emit_p(http_Found);
                                PinUpdate = 2;
            }
 
            else if (strncmp("?POWER1=on ", data, 11) == 0) {
                    bfill.emit_p(http_Found);
                                PinUpdate = 3;
            }

            else {
                //Страница не найдена
                bfill.emit_p(http_Unauthorized);
            }
        }
        ether.httpServerReply(bfill.position());
    }
}
Теперь, когда всё что надо прошито, соединяем как указано на рисунке в начале публикации и подключаем это дело к сети. На машрутизаторе должен быть настроен DHCP сервер.
Мак-адрес нового устройства, как ясно из исходного кода, будет de:ad:be:ee:ee:ef. Лучше сразу назначить постоянную аренду. В OpenWRT с LuCI идём в:
«Сеть» → «DHCP и DNS» → вкладка «Основные настройки» → «Постоянные аренды» → «Добавить».
Пишем там как показано на рисунке:


Когда всё настроено и подключено, заходим на адрес http://192.168.1.100 и видим следующее:


Только вот квадратик будет красным, а не зеленым. Это и есть индикатор питания.
Назначение кнопок пояснять нет смысла. Последняя симулирует долгое нажатие, что приводит к принудительному отключению.

То, что всё это находится в интрасети и не отсвечивает в мир меня вполне устраивает, ведь при подключении по VPN доступ появляется и в Android-приложении и через WEB-интерфейс. Ах да! Для всего этого дела есть ещё и Android-приложение :) Но о нём во второй части.

Вредные советы

Как бы не использовать Arduino?

Лучше таки его использовать.
Но можно и спаять свою ардуину, с блекджеком и профусетками, чтобы она была поменьше и конкретно под этот проект.
Сразу оговорюсь, я наделал кучу ошибок и паял отдельные костыли чтобы всё сошлось.. потом переделал схему, потом ещё пару раз, и уже не помню на сколько там правильная разводка. Так что лучше внимательно изучить и прислать мне фидбек в виде линки на исправленную версию. Или апробировать, если всё правильно =)

Используется двусторонний текстолит. Перемычки тут не помогут.

Находится всё в директории eagle_files/atmegaBoard/ .

Список компонентов:

Part Value Device Package Library Sheet
C1 22pF C-EUC0603 C0603 resistor 1
C2 22pF C-EUC0603 C0603 resistor 1
C3 10uF CC0603 C0603 eagle-ltspice 1
C4 22uF CC0603 C0603 eagle-ltspice 1
IC1 atmega328p atmega328p TQFP32-08 avr-6 1
IC3 LM1117IMPX-3.3 LM1117IMPX-3.3 SOT223 lm1117 1
JP1
PINHD-2X5 2X05 pinhead 1
JP3 PINHD-1X2 1X02 pinhead 1
Q1 16MHz XTAL/S QS special 1
SV1 MA05-1 MA05-1 con-lstb 1
U1 USB"" USB-MICRO-SMD MicroUSB 1

Схема принципиальная:


Сама разводка:


Что тут добавить.. земля на гребёнке справа. JP3 нужен для прошивки схемы. Прошивается она через Arduino IDE.. Кажется с помощью самой ардуины. Ну или через USBasp программатор. В общем, главное ничего не перепутать. А настройки должны быть вроде таких:

1)
 

2)


В следующей части будет обзор Android-приложения. APK файл находится в папке Android_APK.

Итого

У меня вся эта разработка шла не очень гладко, но получилось вполне сносно. Вот конечный результат в корпусе из спичек. Для антуража покрашено йодом.



Что касается дальнейшего развития этой инициативы, то я планирую добавить сюда ещё один выносной модуль для ещё одного ПК.

--
Особая благодарность Unyuu за неоценимый вклад. Во многом благодаря его советам этот проект стал возможен.


Лицензия Creative Commons
Текстовый материал распространяется по лицензии Creative Commons С указанием авторства-Некоммерческая-С сохранением условий 4.0 Всемирная.
Обратите внимание: это ограничение не касается графических изображений и исходного кода. Если на самом изображении не указано иного, они доступны по лицензии Creative Commons С указанием авторства 4.0 Всемирная.

29 августа 2016 г.

Vostro 5470: про Optimus и кнопки настройки яркости

05:32 Опубликовал Дмитрий Исаенко , , 1 коммент.
Сегодня будем разбираться, как избавиться от чёрного экрана при запуске SDDM (замена KDM) в Dell Vostro 5470. Тут я не ставлю целью добиться максимального энергосбережения, т.к. KDE всё равно использует для отрисовки графики OpenGL, ведь суть optimus - использовать для отрисовки 3D как раз nvidia чип, а не встроенный intel. Также мы рассмотрим тему оживления кнопок настроек яркости, а в конце ещё и заставим кнопку suspend уводить ноутбук в ждущий режим.

Итак, чтобы настроить работу Nvidia Optimus нужно, кроме того, что описано в wiki, добавить в настройки sddm строку modesetting. Эта фича не работает в случае, если прописать её в ~/.xinitrc как некоторые советуют. И это ключевой момент.
# vim /usr/share/sddm/scripts/Xsetup
xrandr --setprovideroutputsource modesetting NVIDIA-0
xrandr --auto
Касательно xorg.conf. В моём случае выглядит как-то так:
# cat /etc/X11/xorg.conf
Section "ServerLayout"
        Identifier "layout"
        Screen 0 "nvidia"
        Inactive "intel"
EndSection

Section "Device"
        Identifier "nvidia"
        Driver "nvidia"
        BusID "PCI:09:00:0"
EndSection

Section "Screen"
        Identifier "nvidia"
        Device "nvidia"
EndSection

Section "Device"
        Identifier "intel"
        Driver "modesetting"
        BusID "PCI:00:02:00"
        Option "AccelMethod"  "none"
EndSection
 
Section "Screen"
        Identifier "intel"
        Device "intel"
EndSection 
Теперь по драйверам. Используется проприетарные nvidia-drivers и интеловские драйвера. В make.conf имеется следующее:
VIDEO_CARDS="nvidia intel i965 modesetting"
Что касается настроек в ядре:
> Device Drivers > Graphics support >
<*> /dev/agpgart (AGP Support)  --->         ##есть подозрение, что это совершенно не нужно
      {*}   Intel 440LX/BX/GX, I8xx and E7x05 chipset support
-*- VGA Arbitration
(16)  Maximum number of GPUs
[*] Laptop Hybrid Graphics - GPU switching support
<*> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)  --->
      [*]   Enable legacy fbdev support for your modesetting driver
<M> Intel 8xx/9xx/G3x/G4x/HD Graphics
    Frame buffer Devices  --->
      [*] Enable Video Mode Handling Helpers
      [*] VESA VGA graphics support
-*- Backlight & LCD device support  --->
      <*>   Lowlevel LCD controls
      <*>     Platform LCD controls
      {*}   Lowlevel Backlight controls
      <*>     Generic (aka Sharp Corgi) Backlight Driver
    Console display driver support  --->
      -*- VGA text console   
      [*]   Enable Scrollback Buffer in System RAM
      (64)    Scrollback Buffer Size (in KB)      
      (80) Initial number of console screen columns      
      (25) Initial number of console screen rows  
      -*- Framebuffer Console support      
      -*-   Map the console to the primary display device
      [ ]   Framebuffer Console Rotation   
      [*]   Support for the Framebuffer Console Decorations
[*] Bootup logo  --->

Ну-с, вроде всё. Теперь перейдём к теме яркости. Почему-то у меня из коробки не работают кнопки увеличения и уменьшения яркости. Т.е. они, конечно, работают как кнопки, но яркость не меняют. Проверим для начала, определяет ли система нажатие на эти кнопки. Для этого запустим acpi_listen и пожмакаем. Должно появиться примерно следующее:
# acpi_listen 
video/brightnessdown BRTDN 00000087 00000000 K
video/brightnessdown BRTDN 00000087 00000000
video/brightnessup BRTUP 00000086 00000000
video/brightnessup BRTUP 00000086 00000000 K
^C
Если этого не произошло, идём смотреть ядро:
Device Drivers > X86 Platform Specific Device Drivers
    <*>   Dell Laptop Extras
    <*>   Dell Latitude freefall driver (ACPI SMO88XX)
    <M>   Intel PMC IPC Driver

Power management and ACPI options >
    [*] Suspend to RAM and standby         
    [*] Hibernation (aka 'suspend to disk')
    ()  Default resume partition           
    [ ] Opportunistic sleep                
    [ ] User space wakeup sources interface
    -*- Device power management core functionality
    [ ]   Power Management Debug Support   
    [ ] Enable workqueue power-efficient mode by default
    [*] ACPI (Advanced Configuration and Power Interface) Support  --->
      --- ACPI (Advanced Configuration and Power Interface) Support 
      [ ]   AML debugger interface (EXPERIMENTAL)
      [ ]   Deprecated power /proc/acpi directories
      [*]   Allow supported ACPI revision to be overriden
      < >   EC read/write access through /sys/kernel/debug/ec
      <*>   AC Adapter
      <*>   Battery
      {*}   Button
      {*}   Video
      {*}   Fan
      [*]   Dock
      <*>   Processor
      < >   Processor Aggregator
      <*>   Thermal Zone
      -*-   NUMA support
      [ ]   ACPI tables override via initrd
      [ ]   Debug Statements
      [ ]   PCI slot detection driver
      -*-   Container and Module Devices
      <*>   Smart Battery System
      < >   Hardware Error Device
      < >   Allow ACPI methods to be inserted/replaced at run time
      <M>   ACPI NVDIMM Firmware Interface Table (NFIT)
      [ ]   ACPI Platform Error Interface (APEI)
      [ ]   PMIC (Power Management Integrated Circuit) operation region support  ----
    [*] SFI (Simple Firmware Interface) Support  ----
        CPU Frequency scaling  --->        
        CPU Idle  --->                     
    [*] Cpuidle Driver for Intel Processors
        Memory power savings  --->
          <*> Intel chipset idle memory power saving driver
Это должно помочь.

Также, у вас должен быть в системе следующий путь:
/sys/class/backlight/intel_backlight/
В директории /sys/class/backlight вы также можете обнаружить под-директорию dell_backlight . Скорее всего вы что-то перемудрили с настройками. В целом - то, что эта папка есть, нет ничего страшного, ведь что там не меняй - подсведка меняться не будет.

Если кнопки определились, то пропишем правило скрипту ACPI. Тут привожу скрипт(ы) в полном варианте. Изменённые секции выделены красным.
# vim /etc/acpi/default.sh 
#!/bin/sh
# /etc/acpi/default.sh
# Default acpi script that takes an entry for all actions

set $*

group=${1%%/*}
action=${1#*/}
device=$2
id=$3
value=$4

log_unhandled() {
        logger "ACPI event unhandled: $*"
}

case "$group" in
        button)
                case "$action" in
                        power)
                                /etc/acpi/actions/powerbtn.sh
                                ;;

                        *)      log_unhandled $* ;;
                esac
                ;;

        ac_adapter)
                case "$value" in

                        *)      log_unhandled $* ;;
                esac
                ;;

        video)
                case "$action" in
                        brightnessdown)

                                /etc/acpi/actions/brightness.sh -

                                ;;

                        brightnessup)

                                /etc/acpi/actions/brightness.sh +

                                ;;

                        *)      log_unhandled $* ;;
                esac
                ;;

        *)      log_unhandled $* ;;
esac
Ну и сделаем для этого ещё один скрипт:
# vim /etc/acpi/actions/brightness.sh 

#!/bin/bash
bl_dev=/sys/class/backlight/intel_backlight/
step=10   #set 

case $1 in
        -) echo $(($(< $bl_dev/brightness) - $step)) >$bl_dev/brightness ;;
        +) echo $(($(< $bl_dev/brightness) + $step)) >$bl_dev/brightness ;;
esac
И тут вы можете заметить, что т.к. в acpi_listen одно нажатие кнопки определялось двумя ивентами ACPI, то и изменение яркости будет происходить с двойной силой. Итого, устанавливая step=10 он фактически будет отрабатывать 20-ку. Ну и ладно. Я вот ставил step=1 и сначала думал, что изменение яркости вообще не происходит. 10 - это норма ;)
# chmod +x /etc/acpi/actions/brightness.sh 

А чтобы два раза не вставать, настроим заодно и поведение кнопки sleep. Я постоянно пользуюсь утилитой pm-suspend и хотел бы отправлять в сон ноут по одному клику. Для начала установим пакет, содержащий pm-suspend.
# emerge sys-power/pm-utils
Посмотрим, как эта кнопка определяется системой:
# acpi_listen 
button/sleep SBTN 00000080 00000000 K
^C
Всё вроде хорошо. Осталось модифицировать наш скрипт.
# cat /etc/acpi/default.sh    
#!/bin/sh
# /etc/acpi/default.sh
# Default acpi script that takes an entry for all actions

set $*

group=${1%%/*}
action=${1#*/}
device=$2
id=$3
value=$4

log_unhandled() {
        logger "ACPI event unhandled: $*"
}

case "$group" in
        button)
                case "$action" in
                        power)
                                /etc/acpi/actions/powerbtn.sh
                                ;;

                        # if your laptop doesnt turn on/off the display via hardware
                        # switch and instead just generates an acpi event, you can force
                        # X to turn off the display via dpms.  note you will have to run
                        # 'xhost +local:0' so root can access the X DISPLAY.
                        #lid)
                        #       xset dpms force off
                        #       ;;

                        sleep)
                                /usr/sbin/pm-suspend
                                ;;

                        *)      log_unhandled $* ;;
                esac
                ;;

        ac_adapter)
                case "$value" in
                        # Add code here to handle when the system is unplugged
                        # (maybe change cpu scaling to powersave mode).  For
                        # multicore systems, make sure you set powersave mode
                        # for each core!
                        #*0)
                        #       cpufreq-set -g powersave
                        #       ;;

                        # Add code here to handle when the system is plugged in
                        # (maybe change cpu scaling to performance mode).  For
                        # multicore systems, make sure you set performance mode
                        # for each core!
                        #*1)
                        #       cpufreq-set -g performance
                        #       ;;

                        *)      log_unhandled $* ;;
                esac
                ;;

        video)
                case "$action" in
                        brightnessdown)

                                /etc/acpi/actions/brightness.sh -
                                ##echo $group -  $action - $device - $id - $id>> /tmp/1.sh

                                ;;

                        brightnessup)

                                /etc/acpi/actions/brightness.sh +
                                ##echo $group -  $action - $device - $id - $id>> /tmp/1.sh

                                ;;

                        *)      log_unhandled $* ;;
                esac
                ;;

        *)      log_unhandled $* ;;
esac

На этом всё.

Ссылки:
https://wiki.archlinux.org/index.php/acpid
https://wiki.gentoo.org/wiki/ACPI

20 марта 2016 г.

Делаем IR приёмник для LIRC (igorplugusb)

16:51 Опубликовал Дмитрий Исаенко , , Нет комментариев
Сегодня будем делать инфракрасный приёмник. В таком качестве мною был выбран распространённый igorplugusb — старая, не лишенная недостатков, но очень простая в создании схема. Прекрасный пример реализации я нашел на сайте JumpTruck, который в свою очередь почти без изменений списан с проекта Дика Стрифланда (Dick Streefland). Но не смотря на это, готовые схемы мне не понравились. Мне хотелось micro-usb штекер и миниатюрную плату, поэтому я решил переделать реализацию под себя. 
Для новой разводки был использован бесплатный (условно) Eagle cad, который прекрасно подходит для разработки небольших схем и обладает огромным набором библиотек компонентов. В конечном итоге у меня получилось следующее (кликабельно):



Скачать их, вместе с прошивкой и самую-малость-кривым-PDF для лазерного утюга можно отсюда: https://cloud.mail.ru/public/CH4D/Sw3D5nLh5

Честно говоря, я не помню уже какие сторонние библиотеки были использованы, так что в архиве лежат, на всякий случай, все.

Если вы в первый раз используете Eagle (у меня это версия 7.4.0), то после установки и первого запуска он предложит вам создать папку по-умолчанию для проектов и всего-такого-прочего. В неё-то и надо скопировать директории IR3 и lib.

Теперь о том, что касается компонентов (нагло содрано):
Комп. Значение Корпус Описание
C1 27pf 0603 Керамический конденсатор
C2 27pf 0603 Керамический конденсатор
C3 0.1uf 0603 Керамический конденсатор
C4 4,7uf 0603 Конденсатор (тут у автора была ошибка - нужен именно 4,7uf)
C5 100uf E2,5-6 Электролит. конденсатор
D1 3,6V SOD80C Стабилитрон 3.6V
D2 3,6V SOD80C Стабилитрон 3.6V
IC1 ATtiny2313 DIL20 ATTINY2313-20PU
LED1 LED3MM 3mm LED (синенький)
Q1 12MHz HC49U70 Кварц
R1 68 0805 (или 0603) 68Ом резистор
R2 1k5 0603 1,5КОм резистор
R3 68 0805 (или 0603) 68Ом резистор
R4 330 0603 330Ом резистор
R5 22k 0603 22КОм резистор
R6 100 0603 100Ом резистор
R7 4,7КОм 0603 4,7КОм резистор
U$1 TSOP4838 782-TSOP4838 IR приёмник 38kHz
X1 Micro-usb USB-MICRO-SMD micro-usb разъём

Теперь несколько слов о прошивке. Я использовал, как и Jumptruck, прошивку main.hex из папки IR из пакета 1,4. Сейчас на сайте доступен для скачивания архив 1.7 — что там внутри и как оно работает я не знаю. Если есть желание проверить, то пожалуйста.

Прошивал я своим программатором usbasp через avrdude. Тут проблем у вас возникнуть не должно. Как настроить окружение я писал в одной из предыдущих публикаций. Тут же традиционно показываю выкладку:
 # avrdude -c usbasp -pt2313 -U flash:w:main.hex                     

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e910a
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "main.hex"
avrdude: input file main.hex auto detected as Intel Hex
avrdude: writing flash (2006 bytes):

Writing | ################################################## | 100% 18.64s


avrdude: 2006 bytes of flash written
avrdude: verifying flash memory against main.hex:
avrdude: load data flash data from input file main.hex:
avrdude: input file main.hex auto detected as Intel Hex
avrdude: input file main.hex contains 2006 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 8.66s


avrdude: verifying ...
avrdude: 2006 bytes of flash verified
avrdude: safemode: Fuses OK

avrdude done.  Thank you.

 # avrdude -pt2313 -U hfuse:w:0xdb:m -U lfuse:w:0xef:m -c usbasp

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e910a
avrdude: reading input file "0xdb"
avrdude: writing hfuse (1 bytes):

Writing | ################################################## | 100% 0.02s

avrdude: 1 bytes of hfuse written
avrdude: verifying hfuse memory against 0xdb:
avrdude: load data hfuse data from input file 0xdb:
avrdude: input file 0xdb contains 1 bytes
avrdude: reading on-chip hfuse data:

Reading | ################################################## | 100% 0.00s

avrdude: verifying ...
avrdude: 1 bytes of hfuse verified
avrdude: reading input file "0xef"
avrdude: writing lfuse (1 bytes):

Writing | ################################################## | 100% 0.02s

avrdude: 1 bytes of lfuse written
avrdude: verifying lfuse memory against 0xef:
avrdude: load data lfuse data from input file 0xef:
avrdude: input file 0xef contains 1 bytes
avrdude: reading on-chip lfuse data:

Reading | ################################################## | 100% 0.00s

avrdude: verifying ...
avrdude: 1 bytes of lfuse verified

avrdude: safemode: Fuses OK

avrdude done.  Thank you.

Перейдём к настройке LIRC. 

Для начала, необходимо правильно сконфигурировать ядро. Для этого включим следующие необходимые фичи через menuconfig.
Device Drivers -> Multimedia Support
  [*]   Remote Controller support
  [*]   Remote controller decoders  ---> 
      <M>   LIRC interface driver
      <M>     Enable IR to LIRC bridge
      <M>   Enable IR raw decoder for the NEC protocol
      <M>   Enable IR raw decoder for the RC-5 protocol
      <M>   Enable IR raw decoder for the RC6 protocol
      <M>   Enable IR raw decoder for the JVC protocol
      <M>   Enable IR raw decoder for the Sony protocol
      <M>   Enable IR raw decoder for the Sanyo protocol
      <M>   Enable IR raw decoder for the Sharp protocol
      <M>   Enable IR raw decoder for the MCE keyboard/mouse protocol
      <M>   Enable IR raw decoder for the XMP protocol
  [*]   Remote Controller devices  --->
         IgorPlug-USB IR Receiver
  Input device support  --->
      <*>   Event interface  (не знаю на сколько это актуально)

После того, как мы настроили ядро и перезагрузились, при подключении устройства в dmesg должно появиться следующее:
[57672.609962] usb 1-5.2: new low-speed USB device number 9 using xhci_hcd
[57672.699435] usb 1-5.2: New USB device found, idVendor=03eb, idProduct=0002
[57672.699438] usb 1-5.2: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[57672.699439] usb 1-5.2: Product: USBtiny IR/LCD
[57672.700146] Registered IR keymap rc-hauppauge
[57672.700217] input: IgorPlug-USB IR Receiver as /devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.2/1-5.2:1.0/rc/rc0/input20
[57672.700250] rc0: IgorPlug-USB IR Receiver as /devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5.2/1-5.2:1.0/rc/rc0
[57672.700309] input: MCE IR Keyboard/Mouse (igorplugusb) as /devices/virtual/input/input21
[57672.700452] rc rc0: lirc_dev: driver ir-lirc-codec (igorplugusb) registered at minor = 0
Соответсвенно в /dev теперь есть устройство /dev/lirc0.

Теперь самое интересное - заставить всё это дело работать. Версия lirc-0.9.0-r5, которая есть сейчас в portage безумно устарела и, строго говоря, не работает. Поэтому я решил написать ebuild для более свежей, но не последней версии 0.9.3a.

Вот выкладка:
$ cat lirc-0.9.3a.ebuild    
# Copyright 1999-2016 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$

EAPI=4

inherit eutils systemd flag-o-matic autotools

DESCRIPTION="decode and send infra-red signals of many commonly used remote controls"
HOMEPAGE="http://www.lirc.org/"

MY_P=${PN}-${PV/_/}

if [[ "${PV/_pre/}" = "${PV}" ]]; then
        SRC_URI="mirror://sourceforge/lirc/${MY_P}.tar.bz2"
else
        SRC_URI="http://www.lirc.org/software/snapshots/${MY_P}.tar.bz2"
fi

LICENSE="GPL-2"
SLOT="0"
KEYWORDS="amd64 ppc ppc64 x86"
IUSE="doc static-libs X audio irman ftdi inputlirc iguanair"

S="${WORKDIR}/${MY_P}"


REQUIRED_USE="
        iguanair? ( irman )
"
DEPEND="
        doc? ( app-doc/doxygen )
"

RDEPEND="
        X? (
                x11-libs/libX11
                x11-libs/libSM
                x11-libs/libICE
        )
        audio? ( 
                >media-libs/portaudio-18 
                media-libs/alsa-lib
        )
        irman? ( media-libs/libirman )

        iguanair? ( app-misc/iguanaIR )

        ftdi? ( dev-embedded/libftdi:0 )

        inputlirc? ( app-misc/inputlircd )
"

pkg_setup() {

        # set default configure options
        LIRC_DRIVER_DEVICE="/dev/lirc0"

        filter-flags -Wl,-O1
}

src_prepare() {
        # Rip out dos CRLF
        edos2unix contrib/lirc.rules
}

src_configure() {
        econf \
                $(use_enable static-libs static) \
                $(use_with X x)
}


src_install() {
        emake DESTDIR="${D}" install

        newinitd "${FILESDIR}"/lircd lircd
        newinitd "${FILESDIR}"/lircmd lircmd
        newconfd "${FILESDIR}"/lircd.conf.4 lircd

        insinto /etc/modprobe.d/
        newins "${FILESDIR}"/modprobed.lirc lirc.conf

        newinitd "${FILESDIR}"/irexec-initd irexec
        newconfd "${FILESDIR}"/irexec-confd irexec

        systemd_dounit "${FILESDIR}"/irexec.service
        systemd_dounit "${FILESDIR}"/lirc.service
        systemd_dounit "${FILESDIR}"/lircm.service

        if use doc ; then
                dohtml doc/html/*.html
                insinto /usr/share/doc/${PF}/images
                doins doc/images/*
        fi

        keepdir /etc/lirc
        if [[ -e "${D}"/etc/lirc/lircd.conf ]]; then
                newdoc "${D}"/etc/lirc/lircd.conf lircd.conf.example
        fi

        use static-libs || rm "${D}/usr/$(get_libdir)/liblirc_client.la"
}

pkg_preinst() {

        local dir="${EROOT}/etc/modprobe.d"
        if [[ -a "${dir}"/lirc && ! -a "${dir}"/lirc.conf ]]; then
                elog "Renaming ${dir}/lirc to lirc.conf"
                mv -f "${dir}/lirc" "${dir}/lirc.conf"
        fi

        # copy the first file that can be found
        if [[ -f "${EROOT}"/etc/lirc/lircd.conf ]]; then
                cp "${EROOT}"/etc/lirc/lircd.conf "${T}"/lircd.conf
        elif [[ -f "${EROOT}"/etc/lircd.conf ]]; then
                cp "${EROOT}"/etc/lircd.conf "${T}"/lircd.conf
                MOVE_OLD_LIRCD_CONF=1
        elif [[ -f "${D}"/etc/lirc/lircd.conf ]]; then
                cp "${D}"/etc/lirc/lircd.conf "${T}"/lircd.conf
        fi

        # stop portage from touching the config file
        if [[ -e "${D}"/etc/lirc/lircd.conf ]]; then
                rm -f "${D}"/etc/lirc/lircd.conf
        fi

}

pkg_postinst() {

        # copy config file to new location
        # without portage knowing about it
        # so it will not delete it on unmerge or ever touch it again
        if [[ -e "${T}"/lircd.conf ]]; then
                cp "${T}"/lircd.conf "${EROOT}"/etc/lirc/lircd.conf
                if [[ "$MOVE_OLD_LIRCD_CONF" = "1" ]]; then
                        elog "Moved /etc/lircd.conf to /etc/lirc/lircd.conf"
                        rm -f "${EROOT}"/etc/lircd.conf
                fi
        fi

        einfo "The new default location for lircd.conf is inside of"
        einfo "/etc/lirc/ directory"
}

Ну и листинги всего остального, что есть в папке (чего уж мелочиться):
$ ls 
files  lirc-0.9.3a.ebuild  Manifest  metadata.xml

$ cat metadata.xml 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
<pkgmetadata>
  <maintainer type="project">
    <email></email>
  </maintainer>
  <use>
    <flag name="audio">Build alsa-lib and portaudio required for some receivers</flag>
    <flag name="ftdi">Build libftdi required by FTDI driver</flag>
    <flag name="iguanair">Build libiguanair required by iguanaIR</flag>
    <flag name="inputlirc">Build inputlirc</flag>
    <flag name="irman">Build libirman required by Irman</flag>
  </use>
</pkgmetadata>
$ cat files/irexec-confd
# Options to pass to the irexec process
IREXEC_OPTS="/etc/lircrc"

# User to execute irexec as.
# Warning: Running irexec as root can open security holes
#IREXEC_USER="root"

# Use this to disable the warning printed when starting irexec as root
# IREXEC_DISABLE_ROOT_WARNING=yes 
$ cat files/irexec-initd 
#!/sbin/runscript
# Copyright 2003 Martin Hierling <mad@cc.fh-lippe.de>
# Distributed under the terms of the GNU General Public License v2
# $Id$

: ${IREXEC_USER:=root}

depend() {
        need lirc
}

start() {
        if [ "x${IREXEC_USER}" = "xroot" -a "x${IREXEC_DISABLE_ROOT_WARNING}" != "xyes" ]; then
                ewarn "Warning: Running irexec as root can open security holes"
        fi

        ebegin "Starting irexec"
        start-stop-daemon --start --chuid ${IREXEC_USER} --user ${IREXEC_USER} --chdir / \
                --exec /usr/bin/irexec -- --daemon ${IREXEC_OPTS}
        eend $? "Failed to start irexec."
}

stop() {
        ebegin "Stopping irexec"
        start-stop-daemon --stop --exec /usr/bin/irexec --user ${IREXEC_USER}
        eend $? "Failed to stop irexec."
}
 $ cat files/irexec.service 
[Unit]
Description=IR Exec
After=lirc.service
Wants=lirc.service

[Service]
ExecStart=/usr/bin/irexec

[Install]
WantedBy=multi-user.target
$ cat files/lircd
#!/sbin/runscript
# Copyright 1999-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$

PIDFILE=/var/run/lirc/${SVCNAME}.pid
: ${LIRCD_SYMLINKFILE:=/dev/lircd}
: ${LIRCD_SOCKET:=/var/run/lirc/lircd}

depend() {
        need localmount
        use modules
        provide lirc
}

start() {
        local retval

        ebegin "Starting lircd"

        for retval in ${LIRCD_SET_SYSCLASSRCS} ; do
                if [ -e /sys/class/rc/${retval}/protocols ] && \
                grep -qs 'lirc' /sys/class/rc/${retval}/protocols ; then
                        einfo "Setting lirc protocol active for ${retval}"
                        echo lirc >/sys/class/rc/${retval}/protocols
                fi
        done

        checkpath -q -d -m 0755 -o root:root /var/run/lirc
        rm -Rf ${LIRCD_SOCKET} && ln -s ${LIRCD_SOCKET} ${LIRCD_SYMLINKFILE}
        if [ $? -ne 0 ]; then
                eend $? "Unable to create symbolic link ${LIRCD_SYMLINKFILE}"
                return 1
        fi

        start-stop-daemon --start --quiet --pidfile "${PIDFILE}" --exec /usr/sbin/lircd -- \
                -P "${PIDFILE}" ${LIRCD_OPTS}
        retval=$?

        if [ ${retval} -ne 0 ]; then
                rm -Rf ${LIRCD_SOCKET}
        fi

        eend ${retval}
}

stop() {
        ebegin "Stopping lircd"
        rm -f ${LIRCD_SYMLINKFILE}
        start-stop-daemon --stop --quiet --pidfile "${PIDFILE}" --exec /usr/sbin/lircd
        eend $?
}
 $ cat files/lircd.conf.4 
# Options to pass to the lircd process

# for devices with lirc-kernel-module
#LIRCD_OPTS="-d /dev/lirc0"
#LIRCD_OPTS="-d /dev/lirc"

# for devices using the input-layer
#LIRCD_OPTS="-H devinput -d /dev/input/by-path/pci-0000:00:0a.0--event-ir"
# This should work, Bug #235107
#LIRCD_OPTS="-H devinput -d name=*DVB*"

# set default protocol to 'lirc' for in-kernel IR decoding
# for the following entries in /sys/class/rc/
# (space-separated list if there is more than one)
LIRCD_SET_SYSCLASSRCS="rc0"

# If running mulitple instances of lircd, the following
# can be used to override the default socket path and
# socket symlink
#LIRCD_SOCKET="/var/run/lirc/lircd"
#LIRCD_SYMLINKFILE="/dev/lircd"
$ cat files/lircmd 
#!/sbin/runscript
# Copyright 1999-2004 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$

depend() {
        need lircd
}

start() {
        ebegin "Starting lircmd"
        start-stop-daemon --start --quiet --exec /usr/sbin/lircmd
        eend $?
}

stop() {
        ebegin "Stopping lircmd"
        start-stop-daemon --stop --quiet --exec /usr/sbin/lircmd
        eend $?
}
$ cat files/lirc.service 
[Unit]
Description=Linux Infrared Remote Control
After=network.target

[Service]
ExecStart=/usr/sbin/lircd --nodaemon --driver=default --device=/dev/lirc0

[Install]
WantedBy=multi-user.target
$ cat files/modprobed.lirc 
#
# For first serial receivers:
#
#options lirc_serial irq=4 io=0x3f8
#options lirc_sir irq=4 io=0x3f8

#
# Detach first serial port from serial-driver.
# Use this when you have your serial-port-driver statically
# compiled into your kernel, or as a module but loaded before
# the lirc-module.
# 
#install lirc_serial setserial /dev/ttyS0 uart none; modprobe --ignore-install lirc_serial
#
#install lirc_sir    setserial /dev/ttyS0 uart none; modprobe --ignore-install lirc_sir


#
# For parallel receivers:
#
#options lirc_parallel irq=7 io=0x3bc

Таким образом, всё что вам нужно сделать - так это добавить ебилд в локальный репозиторий, выполнить repoman manifest и установить пакет.
# emerge lirc

Скачать zip можно отсюда: https://cloud.mail.ru/public/2Mdy/yGnm7BVgX
Да, я тут подумал, что так жить нельзя, и решил завести себе аккаунт на GitHub. Так что теперь ебилды можно будет качать и отсюда: https://github.com/developersu/loperOverlay

Теперь добавим демон lircd в автозагрузку:
# rc-update add lircd default
И запустим его:
# /etc/init.d/lircd start
 * Starting lircd ...
 * Setting lirc protocol active for rc0        [ ok ]
Проверить, что всё работает как надо можно коммандой mode2. Когда она запущена нужно поклацать пультом и диод замигает, а в консоли вы увидите примерно следующее:
# mode2 
Using device: /dev/lirc0
Using device: /dev/lirc0
Warning: Running as root.
pulse 9045
space 4607
pulse 511
space 1706
pulse 511
space 597
pulse 597
space 511
pulse 597
space 511
pulse 597
space 511
pulse 597
space 597
pulse 597
space 511
pulse 597
space 511
pulse 597
space 511
pulse 597
space 1621
pulse 682
space 1706
pulse 597
space 511
pulse 597
space 597
pulse 597
space 1706
pulse 597
space 1706
pulse 597
space 1621
pulse 682


О том, как настроить конкретный пульт для управление системой в KDE мы поговорим в следующий раз.

На этом у меня всё.

Источники:
https://dicks.home.xs4all.nl/avr/usbtiny/
http://jumptuck.com/2008/10/26/usb-ir-receiver/
http://gentoo-en.vfose.ru/wiki/LIRC

14 февраля 2016 г.

Crossdev окружение для AVR

18:43 Опубликовал Дмитрий Исаенко , , Нет комментариев
Сегодня хочется поговорить о том, как настроить crossdev окружение в Gentoo, которое необходимо для компиляции под микроконтроллеры AVR. По аналогичной схеме собираются тулчейны и для других популярных архитектур, к примеру MIPS или различных веток ARM.

Перед началом работы размаскируем последнюю версию crossdev и установим её:
# echo "sys-devel/crossdev ~amd64" >>  /etc/portage/package.accept_keywords
Теперь создадим и настроим отдельный оверлей, для пакетов crossdev.
# mkdir /usr/local/crossdev-overlay
# cd /usr/local/crossdev-overlay
# mkdir -p /usr/local/crossdev-overlay/{profiles,metadata}
# echo 'crossdevLocalOverlay' > profiles/repo_name
# vim metadata/layout.conf
masters = gentoo
thin-manifests = true
# chown  -R portage:portage /usr/local/crossdev-overlay
Также следует описать оверлей в repos.conf:
# vim /etc/portage/repos.conf/crossdev.conf
[crossdevLocalOverlay]
location = /usr/local/crossdev-overlay
priority = 10
masters = gentoo
auto-sync = no
Тут есть один важный нюанс. Если у нас в системе уже был один локальный оверлей, а для crossdev мы хотим использовать отдельный, то следует существующему оверлею назначить более высокий приоритет. Сделать это можно изменив его настройки там же, в директории repos.conf. В моём случае это выглядело так:
#echo 'priority = 13' >> /etc/portage/repos.conf/local.conf
Соберём окружение для AVR, явно указав версии необходимого нам ПО. У меня всё заработало со следующими параметрами GCC, binutils и libc:
USE="multilib -cxx" crossdev --g 4.6.2 --b 2.21.1-r1 --l 1.7.0 -S -s1 --target avr
USE="multilib cxx" crossdev --g 4.6.2 --b 2.21.1-r1 --l 1.7.0 -S -s4 --target avr 
Если не вышло, можно попробовать проще:
crossdev -s4 --stable --portage --verbose --target avr
Теперь нужно создать ссылку на ldscripts, иначе ничего не соберётся (эта проблема существует уже лет 6, но никто не шевелится её исправлять):
ln -s /usr/x86_64-pc-linux-gnu/avr/lib/ldscripts/ /usr/avr/lib/ldscripts
Осталось установить avrdude:
# emerge avrdude
Попробуем помирать диодиком на PC5:
# vim me.cpp
#define F_CPU 8000000L
#include <avr/io.h>
#include <util/delay.h>

void sleep(uint8_t millisec)
{
        while(millisec)
        {
              _delay_ms(1);
                millisec--;
        }
}

int main(void)
{
while (1) {

DDRC |=1<<PC5;
               PORTC &= ~(1<<PC5);
               sleep(100);

               PORTC |=(1<<PC5);
               sleep(100);
}
}
Теперь скомпилируем и прошьём (я использую программатрор от Thomas Fischl).
# avr-gcc  -O2 -mmcu=atmega8  me.cpp -o me.elf
# avr-objcopy -O ihex me.elf me.hex
# avrdude -c usbasp -p m8 -U hfuse:w:0xd9:m -U lfuse:w:0xe1:m
# avrdude -c usbasp -p m8 -U flash:w:me.hex:i
Вот и всё. Схему приводить тут не вижу смысла, но если кому интересно — смотрите на иконку к этой публикации. Удачи!


Полезные ссылки:
https://wiki.gentoo.org/wiki/Overlay/Local_overlay
http://gentoo-en.vfose.ru/wiki/Crossdev 

21 сентября 2015 г.

"Откирпичиваем" QTECH QBR-1041WU v2

04:45 Опубликовал Дмитрий Исаенко 13 коммент.

Попался мне как-то в руки МТС маршрутизатор. Ну я глянул, что это МТС и решил, что негоже просто взять, и пользоваться им. Срочно надо обновить прошивку на не-МТСовскую. Вот взял я его, посмотрел снизу модель да и качнул прошивку, не придав значения приписке - "v.2". Вот так и получился у меня кирпич. И вот, пол года спустя, дошли и до него руки. Решил я его "раскерпичить" обратно. Сначала читал про JTAG, OpenOCD, ejtag но ничего толкового у меня с ними не получилось. В конце концов я наткнулся на статью, в которой говорилось как легко и просто залить прошивку по tftp. Так я и сделал! 
Для начала я установил на виртуальной машине (c Debian) tftp клиент.
aptitude install tftp
После этого я скачал официальную прошивку. Далее я подключил маршрутизатор к свичу и, зажав снизу кнопку 'Reset', включил вилку питания в сеть. Удерживать 'Reset' нужно 6-7 секунд. Момент когда хватит можно определить по индикаторам - если горит "питание" и порт LAN, к которому подключен кабель - то всё нормально и можно отпускать.
В таком режиме маршрутизатор определятся по адресу 192.168.1.6 и работает как tftp сервер.
Для того, чтобы следить за обстановкой лично, я подключился к маршрутизатору ещё и по UART через распаянный разъём (на картинке справа).

Подключался я к нему через screen (38400 8N1):
screen /dev/ttyUSB0 38400
Пробовал через minicom - не вышло. Там сначала мусор идёт, а потом лог куда-то смещается и вовсе пропадает. В общем я просто не разобрался :(

Теперь, когда все приготовления сделаны и девайс загружен, выполним на машине с tftp клиентом следующие команды:
# tftp 192.168.1.6
tftp> mode binary
tftp> put 1.1.10e.290514.bin
Sent 4442148 bytes in 6.2 seconds
tftp>
tftp>quit 
Здесь "1.1.10e.290514.bin" - прошивка, которую мы передаём, а "mode binary" - переключение режима передачи данных. Если не переключить режим - магии не получится.
Если всё сложилось удачно, то в окне screen мы увидим следующую картину:
Как вы заметили, маршрутизатор сразу после успешной передачи файла-прошивки приступил к его развёртыванию, а после - к перезагрузке.
Это, в общем-то, и всё.

И, в качестве алаверды, вот вам цоколёвка JTAG разъёма (находится на большом фото слева):
Удачных вам экспериментов!

UPD: Линка на прошивку, которую использовал я (надеюсь QTECH на меня не обидится): https://cloud.mail.ru/public/EWMx/bD4FvHb9o

2 августа 2015 г.

Из спичек и жёлудей: заметка о MS3303H UART

03:41 Опубликовал Дмитрий Исаенко 1 коммент.
Коротко расскажу о UART кабелях на микросхеме MS3303H. Пихали её куда только можно, вот я и обнаружил её в дата-кабеле для Samsung C110. 
На это чудо китайской мысли в сети не нашлось никаких даташитов, правда мне удалось отыскать одну статью, которая немало помогла мне. Итак, ниже предлагаю вам распиновку выходов брелка.
Не смотря на такое богатство функционала, я рекомендую вам распаять только RXD, TXD и землю. В подавляющем большинстве случаев этого более чем достаточно.

Для поддержки этого свистка в ядре понадобиться включить поддержку устройств pl2303, под которые он так успешно (?) маскируется.
> Device Drivers 
  > USB support 
    > USB Serial Converter support 
      <M> USB Prolific 2303 Single Port Serial Driver
В итоге в dmesg должно получиться следующее:
[96574.335542] pl2303 ttyUSB0: pl2303 converter now disconnected from ttyUSB0
[96574.335549] pl2303 1-1.1:1.0: device disconnected
[96575.560225] usb 1-1.1: new full-speed USB device number 76 using xhci_hcd
[96575.633670] usb 1-1.1: New USB device found, idVendor=0e55, idProduct=110b
[96575.633672] usb 1-1.1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[96575.634095] pl2303 1-1.1:1.0: pl2303 converter detected
[96575.634191] pl2303 1-1.1:1.0: pl2303_vendor_read - failed to read [8484]: -32
[96575.634346] pl2303 1-1.1:1.0: pl2303_vendor_read - failed to read [8484]: -32
[96575.634447] pl2303 1-1.1:1.0: pl2303_vendor_read - failed to read [8383]: -32
[96575.634551] pl2303 1-1.1:1.0: pl2303_vendor_read - failed to read [8484]: -32
[96575.634735] pl2303 1-1.1:1.0: pl2303_vendor_read - failed to read [8484]: -32
[96575.634837] pl2303 1-1.1:1.0: pl2303_vendor_read - failed to read [8383]: -32
[96575.635093] usb 1-1.1: pl2303 converter now attached to ttyUSB0

На этом у меня всё. Я понятия не имею что делать с этими ошибками. Удачного хакинга ;)

29 мая 2013 г.

Прошивка MLT-1043S подручными средствами(i2c-tiny-usb)

00:36 Опубликовал Дмитрий Исаенко , Нет комментариев
Итак задача - запрограммировать EEPROM 24c04 из чипа CRUM картриджа MLT-1043S. Картридж для принтера Samsung ML-1661/1676/1861/1866/1866W.

Имеется девайс i2c-tiny-usb.
Софт, который потребуется: i2c-tools, hexdump, hexedit и самособранный eeprog. Последний ловко качается исходниками и компилируется в свою же папку, при этом никак не интегрируясь в систему и не представляя призрачной угрозы portage.
Далее всё подключаем\зажимаем и проворачиваем следующее:
Убедимся что поддержка программатора есть в ядре:
Device Drivers > I2C support > I2C device interface <*> (to get access through /dev/i2c-X)
Device Drivers > I2C support > I2C Hardware Bus support > Tiny-USB adapter <*>

Загружаем нужные нам модули
modprobe i2c-tiny-usb i2c-dev i2c-core

Проверяем жив ли интерфейс:
i2cdetect -l
i2c-0   i2c             i2c-tiny-usb at bus 002 device 008      I2C adapter

Проверяем, а не висит ли на этом интерфейсе нечто похожее на EEPROM:
i2cdetect 0
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-0.
I will probe address range 0x03-0x77.
Continue? [Y/n] y
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: 50 51 -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                         

Видим 2 устройства - это нормально. 24с04 отражается в память двумя кусками. Последовательность логична - первые 256 байт на первом сегменте, вторые - на втором.
Считаем содержимое в бинарном виде с обоих сегментов собранным eeprog и пишем вывод в файлики:
# ./eeprog -f /dev/i2c-0 0x50 -r 0:256 > dump1
# ./eeprog -f /dev/i2c-0 0x51 -r 0:256 > dump2

Параметры программы:-f = не спрашивать, /dev/i2c-0 = с какого устройства читать, 0x50 = адрес, который мы узнали выше, -r = чтение, 0:256 = диапазон чтения от 0 до 256 байта.
Просмотреть считанное легко и просто используя hexdump -С.
Далее привожу выхлоп своих данных:
# hexdump -C dump1
00000000  01 33 02 39 01 33 2a df  01 61 ab f4 ff ff ff ff  |.3.9.3*..a......|
00000010  00 00 06 c3 ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00000020  00 00 1c 0d ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00000030  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
*
00000100

# hexdump -C dump2
00000000  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00000010  ff ff ff ff ff ff ff ff  50 54 31 36 36 43 48 4e  |........PT166CHN|
00000020  ff ff ff ff ff ff ff ff  43 52 55 4d 2d 31 31 31  |........CRUM-111|
00000030  30 30 37 38 31 35 31 33  01 32 de 9f 07 ff ff ff  |00781513.2......|
00000040  02 c7 9a e6 ff ff ff ff  00 01 4c 08 ff ff ff ff  |..........L.....|
00000050  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
*
00000070  0a ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00000080  a5 a5 a5 a5 50 54 31 36  36 43 48 4e ff ff ff ff  |....PT166CHN....|
00000090  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
*
00000100

Теперь нам нужно обнулить счётчики и поменять номер картриджа. Делается это в любом HEX-редакторе, например hexedit -s(включает, ИМХО, более учеловеченное отображение).
Рассмотрим на готовом:
Для первого куска:
00000000 00 00 00 02 ff ff ff ff 00 00 00 00 ff ff ff ff |................|
00000010 00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff ff |................|
00000020 00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff ff |................|
00000030 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
00000100

Для второго куска
00000000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
00000010 ff ff ff ff ff ff ff ff 50 54 31 36 36 43 48 4e |........PT166CHN|
00000020 ff ff ff ff ff ff ff ff 43 52 55 4d 2d 31 31 31 |........CRUM-111|
00000030 30 30 37 38 33 35 31 33 01 32 de 9f 07 ff ff ff |00783513.2......|
00000040 02 c7 9a e6 ff ff ff ff 00 01 4c 08 ff ff ff ff |..........L.....|
00000050 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
00000070 0a ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
00000080 ff ff ff ff 50 54 31 36 36 43 48 4e ff ff ff ff |....PT166CHN....|
00000090 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
00000100

Звёздочки, если вы не догадались - повторяющиеся линии файла. В редакторе строк будет несколько большим.
В первом файле мы обнулили счётчики - это первые 3 строки.
Во-втором файле мы изменили версию чипа CRUM, подправив одну цифру. Эта цифра при сбросе чипа будет всегда различаться, и если совпадёт - принтер не примет картридж. В строке |00783513.2......| можно менять всё что угодно, или всё что угодно до точки с двойкой (?).
В строке 00000080 мы убрали все a5 a5 a5 a5. Это, как говорят некоторые особо разбирающиеся люди - прогресс бар.
Всё. Зашиваем обратно:
# cat dump1 |./eeprog -f /dev/i2c-0 0x50 -w 0
# cat dump2 |./eeprog -f /dev/i2c-0 0x51 -w 0

Параметры программы:-f = не спрашивать, /dev/i2c-0 = на какое устройство писать, 0x50 = адрес, по которому писать, -w = запись, 0 = начиная с 0-ого байта.

Вуаля!

22 апреля 2011 г.

Самая короткая заметка о компиляции под МК AVR в Gentoo linux

18:42 Опубликовал Дмитрий Исаенко , Нет комментариев
1. crossdev -t avr
2. emerge codeblocks
3. # cd /usr/x86_64-pc-linux-gnu/avr/binutils-bin/<версия>
4. # ln -s /usr/lib/binutils/avr/<версия>/ldscripts/ .
5. Как отбросить страх и начать программировать для AVR в CodeBlocks
6. Скачать Proteus, запусить его в wine или в настоящей M$ Windows под виртуальной средой и понять что в Proteus Вы ничего не соображаете.