ChangeBlog  •  Archiwum  •  Kategorie  •  Artykuły  •  Galeria  •  Czytelnicy  •  Rupieciarnia
RSS wpisów  |  RSS komentarzy
Podłączanie C-4000 pod Linuksem (USB mass storage)

Ha, przechodziłem parę dni temu mroźnym porankiem przez miasto i co widzę? Ano coś takiego:
Kolejka przed PKO
Nie, nie jest to młodzież szkolna przed wejściem do kina. Bo to nie kino. To bank PKO. I to chyba wystarczy za komentarz ;)

Dzisiaj miałem opowiedzieć o podłączaniu aparatu pod Linuksem i, o dziwo, dotrzymam słowa ;)
Punkt pierwszy - mój aparat (C-4000) jest zgodny z ogólnym schematem USB mass storage (Hurrej!). To jednak oznacza, że praktycznie nie ma aplikacji które by jakoś miały z tym współgrać (Hurrej!, acz mniej entuzjastycznie). OK, możesz zapytać "Czy to naprawdę problem? W końcu urządzenia usb mass storage są w linuksie montowane jak normalne dyski i z punktu widzenia systemu traktuje się je tak, jak dodatkowy dysk podłączony do komputera..." - i będziesz mieć, mój czytelniku/czytelniczko absolutną, rację. Ja jednak lubię sobie automatyzować pracę, tzn. chciałbym aby to komputer zajął się wszystkim - tak jak to się dzieje przy tych mniej wygodnych aparatach wspieranych przez gphoto2, gdzie produkuje się dedykowane aplikacje zgrywające fotki na dysk itp. Nie no, oczywiście że cieszę się z tego, że sterowniki "do aparatu" są standardowo w kernelu i nie muszę się gimnastykować by sobie fotki zgrywać, ale mimo wszystko brakowało mi jakiegoś zautomatyzowanego front-endu. Tutaj możesz powiedzieć "No to sobie napisz jakiś skrypt czy coś" i znowu będziesz mieć rację, ale o tym za chwilę.

Repo dostaje sporo odwiedzin z googla, więc opiszę cały proces podłączania po kolei, może ktoś tutaj trafi kiedyś w poszukiwaniu haseł "aparat cyfrowy", "linux", "usb", "jak podłączyć", "konfiguracja", "mass storage", "Olympus C-4000".
Pierwsze co potrzebne to obsługa USB. Istnieją dwa wykluczające się modele - UHCI i OHCI. Jak rozpoznać posiadany? Najprościej przez "lspci -v|grep USB". Płyta będzie posiadała raczej tylko jeden model kontrolera, więc drugiego nie warto włączać. Istnieje jeszcze EHCI, aka "USB 2.0". Szczęśliwcy posiadający płyty z USB 2.0 mogą włączyć EHCI i, oprócz niego, UHCI lub OHCI (wg. informacji z lspci). Samo EHCI nie obsługuje niczego poza USB2.0, dlatego też chipsety z EHCI zawierają też odpowiednie podzespoły UHCI/OHCI dla komunikacji ze starszymi urządzeniami USB.

Oprócz tego warto też włączyć "USB device filesystem" i dodać do /etc/fstab np. taki wpis: usbfs /proc/bus/usb usbfs defaults Nie jest to konieczne, ale przydaje się przy diagnostyce (odpukać).

Potem można się wziąć za aparat. Potrzebne będzie "USB mass storage support" (pozostałe opcje w tej grupie konfiguratora kernela mogą pozostać odznaczone). Linux będzie przedstawiał aparat (i ogólnie wszystkie urządzenia usb mass storage) jako dyski SCSI, dlatego by się do nich dostać trzeba też włączyć obsługę dysków SCSI :) Czyli to, co kernel nazywa modułem sd_mod (oczywiście można go wkompilować w monolit kernela). Oprócz tego włącz "support for hot-pluggable devices" w sekcji "General setup" jądra.

Na moim systemie po powłączaniu wszystkich potrzebnych i powyłączaniu niepotrzebnych opcji uzyskuję takie coś:

# egrep '^[^#].*(USB|SCSI|HOT)' /usr/src/linux/.config
CONFIG_HOTPLUG=y
CONFIG_SCSI=y
CONFIG_SCSI_QLA2XXX=y
CONFIG_USB=y
CONFIG_USB_DEVICEFS=y
CONFIG_USB_UHCI_HCD=y
CONFIG_USB_STORAGE=y

(nie mam pojęcia czym jest to "CONFIG_SCSI_QLA2XXX", teoretycznie to jakiś low-level scsi driver, widać jakiś obligatoryjny kawałek kodu włączany "po cichu" przez kernel)

W każdym razie tak to wygląda. Kernel z takimi opcjami wykrywa u mnie samodzielnie podłączanie/odłączanie aparatu (warunek: pokrętło trybów aparatu jest ustawione na coś innego niż "off") i chwilkę po podłączeniu aparatu w /proc/partitions pojawiają się wpisy dla nowego dysku /dev/sda oraz partycji /dev/sda1.
Wtedy pozostaje tylko ją gdzieś podmontować, z sytemem plików vfat (to tradycyjny system plików w takich urządzeniach - jak widać wreszcie systemy plików z rodziny FAT znalazły sobie właściwe pole zastosowań ;)
Ja w /etc/fstab zdefiniowałem sobie dla aparatu taki wiersz:
/dev/sda1 /mnt/camera vfat user,noauto,rw,fmask=0111

Po zamontowaniu zawartość aparatu widać w /mnt/camera, można usuwać i dodawać pliki itp. Uwaga: trzeba odmontować /mnt/camera przed wyciągnięciem wtyczki, bo inaczej część danych do zapisania na karcie może pozostać tylko w buforach dyskowych linuksa. Albo, alternatywnie, uruchomić /bin/sync... Ale umount jest elegantszy... Poza tym, w ogóle o czym ja mówię! Przecież każdy dysk należy odmontować przed odłączeniem :)

W tym momencie można już uznać, że aparat jest obsługiwany. Ale mi brakowało jakiegoś front-endu. Więc sobie zrobiłem własny. Najpierw opiszę jak jego działanie wygląda z punktu widzenia usera:
Po podłączeniu aparatu do portu USB na ekranie wyskakuje stylizowany na OSD tekst "Camera detected", po czym rozpoczyna się zgrywanie danych z aparatu. Na ekranie wyświetlana jest liczba zdjęć w aparacie, ich sumaryczna wielkość, numer zdjęcia właśnie kopiowanego, ilość danych już przekopiowana oraz średni transfer przez USB. Oraz pasek postępu całej operacji. Oto przykładowy screenshot.
Zdjęcia lądują w katalogu /home/grzegorz/cam, każde zdjęcie po przekopiowaniu jest kasowane z aparatu. Po przekopiowaniu OSD się nieco zmienia - następny screenshot, a nowy tytuł "Disconnect the camera" ostrzegawczo mruga, czego jednak nie widać na zrzucie. Po wyłączeniu aparatu lub odłączeniu od kabla USB przez parę sekund na ekranie wisi potwierdzenie, że linux wszystko wykrył i poprawnie obsłużył - o, tak.

No i to wszystko. Karta w aparacie jest znowu czysta, wszystkie zdjęcia czekają na mnie w ~/cam/. Proste i dokładnie to o co mi chodziło. Ktoś może zapytać dlaczego bawię się w ten cały "graficzny feedback", kiedy jeden skrypt by wystarczył... I owszem, ale dzięki takiemu podejściu nie nudzę się czekając na ściągnięcie fotek, bo widzę że coś się dzieje i widzę postęp (zwykła psychologia GUI), no i wiem dokładnie kiedy mogę odłączyć aparat. Poza tym mogę sygnalizować userowi (czyli sobie) ew. błędy (znowu, odpukać).

A jak to wszystko wygląda "za kulisami"? Używam spreparowanego, minimalnego polecenia /sbin/hotplug (w sumie to miniaturowy skrypt shellowy) który wykrywa pojawienie się w systemie urządzenia /dev/sda1. Wtedy na X-owym wyświetlaczu o adresie ":0.0" uruchamia (ale na uprawnieniach usera "grzegorz", bo sam hotplug działał na prawach roota) polecenie /usr/bin/camport. CamPort to właśnie ta zabawka wyświetlająca informacje na ekranie itp. CamPort podmontowuje katalog /mnt/camera (musi być zdefiniowany w fstab) i robi skan katalogu, wyszukując i zliczając zdjęcia. Następnie po kolei kopiuje je gdzie trzeba i usuwa z aparatu. Po wszystkim odmontowuje /mnt/camera i wyświetla w nieskończonej pętli prośbę o odłączenie aparatu - to ważne, bo mój C-4000 przy włączonym kablu USB nie przełącza się nigdy w stan spoczynku i żre sporo prądu - po paru godzinach akumulatorki są zeżarte do zera. Już dwa razy je sobie tak przypadkiem rozładowałem - bo podłączyłem, zgrałem zdjęcia, zacząłem od razu oglądać i zapomniałem na śmierć o aparacie.

Wtedy użytkownik odłącza aparat, kernel to wykrywa, znowu uruchamia mój skrypt /sbin/hotplug który wykrywa tym razem zniknięcie urządzenia /dev/sda1 i informuje działający od poprzedniego razu proces CamPort o tym zdarzeniu. CamPort zmienia wtedy wyświetlany tekst i po paru sekundach się wyłącza. Bardzo proste i eleganckie. Wyświetlanie tekstów "nakładanych" na ekran CamPort realizuje poprzez libxosd, a "wskazówkę" o zniknięciu /dev/sda1 otrzymuje nie poprzez rurkę czy inne klasyczne IPC, ale przez sygnał. Po prostu reaguje na sygnał SIGUSR1 wysyłany mu w stosownym kontekście przez /sbin/hotplug.

Czego mu brakuje? No, na pewno sortowania fotek do katalogów wg. daty zrobienia zdjęcia. Dorobię to gdy tylko zaprzyjaźnię się z libexif. Poza tym nie sądzę by funkcjonalnie czegoś jeszcze potrzebował... no, może przydałaby się prawdziwa obsługa błędów, uwolnienie części opcji zakodowanych na sztywno w źródłach itp., ale to już drobiazgi. No, na pewno poprawię kod zgrywający fotki i sprawię by pasek postępu nie łaził tak skokowo (obecnie odświeża się po skopiowaniu 1 zdjęcia, a powinien w sumie odświeżać np. po każdych skopiowanych 256KB).

Dla zainteresowanych: Kod źródłowy CamPort-0.1 można pobrać. Użytkownicy Hiero mogą ściągnąć gotowy pakiet HBS. Obok źródeł znajduje się tam też minimalny /sbin/hotplug, trzeba w nim na pewno zmienić nazwę usera na prawach którego ma być uruchamiany camport. W źródłach samego camport trzeba pewnie zmienić punkt montowania/katalog docelowy itp. rzeczy - te najbardziej oczywiste wywlokłem jako #define na szczyt kodu. Jakby co, to wiadomo - walić na maila.

Pozostaw dopisek: