音樂播放器之 CD 轉成 mp3《四》跨年…

路加福音 15 章 4~7 節

1 眾稅吏和罪人都挨近耶穌,要聽他講道。
2 法利賽人和文士私下議論說:這個人接待罪人,又同他們吃飯。
3 耶穌就用比喻說:
4 你們中間誰有一百隻羊失去一隻,不把這九十九隻撇在曠野、去找那失去的羊,直到找著呢?
5 找著了,就歡歡喜喜的扛在肩上,回到家裡,
6 就請朋友鄰舍來,對他們說:我失去的羊已經找著了,你們和我一同歡喜吧!
7 我告訴你們,一個罪人悔改,在天上也要這樣為他歡喜,較比為九十九個不用悔改的義人歡喜更大。

現行的『公曆』 Calendarium Gregorianum,又叫做『格里曆』,是由義大利醫生與哲學家阿洛伊修斯‧里利烏斯 Aloysius Lilius 改革儒略曆制定的曆法,由教宗格列高利十三世在一五八二年頒行。當格里曆開始實行時,將儒略曆一五八二年十月四日星期四之『明日』,改為格里曆一五八二年十月十五日星期五『那一天』。也就是說有『十天被刪去』了,但是原有星期的週期卻保持不變。這格里曆的紀年沿用儒略曆,自西方傳統耶穌誕生年開始,稱之為『公元』,亦叫作『西元』。據聞,這個結果使得一個小男孩弟八豆發現《我的生日不見了》!!

Frame buffer 命令列常用程式安裝以及 ssh 使用範例︰

sudo apt-get install -y mplayer
wget http://fredrik.hubbe.net/plugger/test.mpg

mplayer -nolirc -vo fbdev2:/dev/fb1 -vf scale=WIDTH:-3 test.mpg

此處 WIDTH 是螢幕寬度,就 Adafruit PiTFT 3.5″觸控螢幕來講,是 420。由於一般影片的解析度比較高,因此需要縮放, scale 參數 -3  的目的是在保持影片之顯示比例

sudo apt-get -y install fbi
wget http://art110.wikispaces.com/file/view/Mystery-100x100.jpg/30649064/Mystery-100x100.jpg

sudo fbi -d /dev/fb1 -T 1 -noverbose -a Mystery-100x100.jpg

當我們安裝了 fbi 之後,還有一個指令可用 fbgs ,它可以用於顯示『 .ps 』或者『 .pdf 』的檔案。

# Map console 1 to framebuffer 1, login screen will show up on the display
con2fbmap 1 1

con2fbmap 1
console 1 is mapped to framebuffer 1

# Revert
con2fbmap 1 0

對於『 headless 』的應用,比方說某種特定『伺服器』也許需要;假使當這個『系統開機』時已經有了『鍵盤』,大概必須要『 reboot 』才能使用的吧。

sudo apt-get install cmake
git clone https://github.com/tasanakorn/rpi-fbcp
cd rpi-fbcp/
mkdir build
cd build/
cmake ..
make
sudo install fbcp /usr/local/bin/fbcp

由於目前『樹莓派』上使用『硬體加速器』的『命令列』程式 ── 比方說 omxplayer ── 通常只是針對『 /dev/fb0 』第一個  Framebuffer 而『設計』的,因而想要使用『硬體加速』功能的人,可能需要這個程式。它的目的是將『 /dev/fb0 』的輸出,拷貝到『 /dev/fb1 』上。使用時請『注意』用命令列『背景模式』  background mode 來執 行︰ fbcp & ,假使想結束此『拷貝模式』,可用 killall fbcp 清除。舉例說︰

# Start fb copying process in the background
fbcp &

#Play video on /dev/fb0, which will also show up on /dev/fb1
omxplayer test.mpg

#Stop framebuffer copy
killall fbcp

#syslog output

$ tail /var/log/messages
Dec 15 17:38:07 raspberrypi fbcp[4836]: Primary display is 720 x 480
Dec 15 17:38:07 raspberrypi fbcp[4836]: Second display is 480 x 320 16bps

這裡用的『 test.mpg 』就是之前使用 mplayer 時,所下載的那一個檔案,如果你沒買 mpg2 codec,那你將會得到『 have a nice day 😉 』的訊息。這時你可以用 wget 指令下載『 wget http://adafruit-download.s3.amazonaws.com/bigbuckbunny320p.mp4 』,再試一次。

sudo apt-get install youtube-dl
# Do this twice
sudo youtube-dl -U
sudo youtube-dl -U

sudo apt-get install python-setuptools
sudo easy_install whitey

據聞過去播放可用『 yt –player omxplayer 』,現今作者不知如何的啦,彷彿是有錯誤的勒!想不想試試『 Raspberry PI Community Projects  』的呢?

wget http://fbgrab.monells.se/fbgrab-1.2.tar.gz (http://adafru.it/diW)
tar -zxvf fbgrab*gz
cd fbgrab/
make
./fbgrab screenshot.png

要是你想抓螢幕上的圖的話。

 

 

── 新年快樂! Happy New Year! ──

 

 

音樂播放器之 CD 轉成 mp3《三》下‧下

250px-Theseus_Minotaur_Mosaic

彌諾陶洛斯和忒修斯的迷宮

220px-Minotaurus

Knossos_silver_coin_400bc

637px-Triple-Spiral-labyrinth-variant.svg
Maze Generator

迷宮 λαβύρινθος,labyrinthos 在希臘神話中是一座精心製作的建築物,由名匠代達羅斯克里特島的國王米諾斯所設計,建造於克諾索斯。這座迷宮用來囚禁米諾斯的兒子,半人半牛怪物的彌諾陶洛斯代達羅斯巧妙地建造這座迷宮,使得在完成後他本人幾乎無法從中逃脫。雅典英雄忒修斯得到阿里阿德涅的襄相,在殺害彌諾陶洛斯後,順著阿里阿德涅的線帶領之下成功逃出迷宮

當一個系統存在多年,經歷眾多的發展者,各種新舊功能交織,很容易形成盤根錯節的複雜現象,甚至某些基本想法的衝突。這對於開源的 Linux 系統來說,更是如此。即使就大的骨幹 grub boot、 kernel 、gnu gcc 、gnome gtk 、kde qt 、等等已經改代多次,繼至系統的管理辦法,友善的桌面環境種種,在出名的發行版逐鹿競爭之下,真是洋洋灑灑,儼然是個迷宮。果然,一個裝置或某種功能,此家可以彼家不行,這版沒問題,那版沒得救。於是各家論壇鼎沸,議論是非真假,誰對誰錯!既然『樹莓派』已有『官方版』,也有『官方論壇』,也許碰到問題時,最好從此出發,或許會有類似遭遇者的吧!當然要是有忒修斯的本事,何不勇闖迷宮,縱橫五湖四海的呢??不過忒修斯還是需要『線頭』的吧!!對於想學 python 的讀者,在此推薦 Albert Sweigart 之『用騛罿創造』免費讀書網。

事實上『軟體工程』的歷史很短,假使從一九六八年『克努斯』的《電腦程式設計藝術》 The Art of Computer Programming 算起, 也還不到半個世紀,尚不要說『藝術』一詞所指的『意義』是什麼呢?因而□□『軟體標準化』 Software standard 大概還是某些○○『系統平台』 Computing platform 圈內的事。這樣難道不好嗎?如果用『螺絲釘』與『螺絲帽』來比喻,有人說軟體『工程化』的好處就是彼此間說『同一國的語言』,因此『協作容易』。作者認為自然中豐富之『多樣性』,正是『生態平衡』的大道;地球上不同的『方言』,產生『社會文化』的消長,所以無須強求一致的吧!然而這或許就得面對『甲軟體』和『乙軟體No Talking 的問題的了?!

那麼我們將要怎麽了解《 Remotely running Python-based graphics on a connected screen 》所講的 ssh 需要 『 sodu ☆☆ 』的問題呢?假使你已經『嘗試』過了各種『作法』,最後也正如那文本所說,發現只要冠上了『 sudo 』果真就可以,這樣我們是否就能作成『結論』呢?在眼前的這一個『問題』就是『使用者』之『權限』所引發的『麻煩』!有一天『偶然的』我們讀到一篇《 Segfault when I use SDL via ssh as pi user 》議論,然後開始『懷疑』真的是這樣的嗎?之後又讀到《 Displaying content/info on TFT display over SSH 》說法,於是產生『煩惱』果真的是這樣的嗎??也許講,本來事物的『複雜性』並不會引起『疑慮』,硬要將它『簡單化』可就『困擾』多多的嘍!!

250px-0726_La_Canée_musée_linéaire_A
線形文字A

250px-NAMA_Linear_B_tablet_of_Pylos
線形文字B

線形文字 A 是種在古代克里特島上使用,尚未破解文字。它的解譯會是考古學上的『聖杯』。其一種關聯文字,線形文字 B 於一九五零年被 Michael Ventris 破譯,證明它為希臘語的一種古代形式。

如果把不能『簡單化』的『疑難』強迫簡化,也許只是『過度化』的吧!奥卡姆的『剃刀原理』去除『多餘的假設』,就像『歸謬證法』排除『邏輯之矛盾』一樣,難到『科學』果能有『神奇』之『其他辦法』的嗎??假使『科學精神』是建立在人人可得之『事實』,大家可以『實驗』驗證的基礎上,所謂的『科學假設』或許是喜歡被打敗的事吧!於是愛因斯坦設想『光速不變』,真的是宛如『燃素說』一般的嗎?當然不是,邏輯上講,要是 A + New \ Theory \Longrightarrow \approx \ Old \ Theory,那麼要『 A 』又有何用?因是之故,『科學假設SA 通常是說, SA + New \ Theory \Longrightarrow \neq Old \ Theory ,因此才可以判定『是非對錯』的吧!!

300px-Longleat_maze

220px-Minotauros_Myron_NAMA_1664_n1

Maze01-02

怎麽『』迷宮,『』出路的呢?大數學家『尤拉』是第一位使用平面連通之『分析方法』來解決『迷途』 Maze 的人,後來此種研究『方式』被稱之為『拓撲學』。依據『右 手定律』,或者對等的說就是『左手定則』,這就是著名的『迷宮演算法』︰

如果那個迷宮是由簡單的路徑連接起來,也就是說,要是所有牆壁都是連接著的,這樣只要用右手指延著入口之某一堵 牆,如斯的前進,那將肯定不會迷路,並且可能尋着出口,也許最壞的打算祇是回到原點

假使按造『尤拉』的解法,即使是『迷宮般的軟體』,也都有『方法可循』,只要堅持到底,總有找到答案的一天。或許有人認為那作法『太慢』了『不好』,但是『』也得要能『解決』問題吧!否則『』又有什麼用呢?

那麼這個回覆
However, if you’re running graphical SDL apps on the framebuffer as a normal user via ssh, take into account how SDL framebuffer choses the active console and keyboard: take a look at src/video/fbcon/SDL_fbevents.c, around line 263 where it tests it you’re root or a normal user. Only the root path works via ssh… tell me if you manage to fix it.  

,是這個問題

Traceback (most recent call last):
  File "pygametest.py", line 14, in <module>
    DISPLAYSURF = pygame.display.set_mode((480, 320), 0, 32)
pygame.error: Unable to open a console terminal

的答案嗎??

點擊閱讀一個可以同時用於『命令列』與『視窗』環境的︰

#!/usr/bin/env python

import os
import pygame
import time
import random

class pyscope :
    screen = None;

    def __init__(self):
        "Ininitializes a new pygame screen using the framebuffer"
        # Based on "Python GUI in Linux frame buffer"
        # http://www.karoltomala.com/blog/?p=679
        disp_no = os.getenv("DISPLAY")
        if disp_no:
            print "I'm running under X display = {0}".format(disp_no)

# Check which frame buffer drivers are available
        # Start with fbcon since directfb hangs with composite output
        drivers = ['fbcon', 'directfb', 'svgalib']
        found = False
        for driver in drivers:
            # Make sure that SDL_VIDEODRIVER is set
            if not os.getenv('SDL_VIDEODRIVER'):
                os.putenv('SDL_VIDEODRIVER', driver)
                os.putenv('SDL_FBDEV', '/dev/fb1')
            try:
                pygame.display.init()
            except pygame.error:
                print 'Driver: {0} failed.'.format(driver)
                continue
            found = True
            break

        if not found:
            raise Exception('No suitable video driver found!')

        size = (pygame.display.Info().current_w, pygame.display.Info().current_h)
        print "Framebuffer size: %d x %d" % (size[0], size[1])
        self.screen = pygame.display.set_mode(size, pygame.FULLSCREEN)
        # Clear the screen to start
        self.screen.fill((0, 0, 0))
        # Initialise font support
        pygame.font.init()
        # Render the screen
        pygame.display.update()

    def __del__(self):
        "Destructor to make sure pygame shuts down, etc."

    def drawGraticule(self):
        "Renders an empty graticule"
        # The graticule is divided into 10 columns x 8 rows
        # Each cell is 50x40 pixels large, with 5 subdivisions per
        # cell, meaning 10x8 pixels each. Subdivision lines are
        # displayed on the central X and Y axis
        # Active area = 10,30 to 510,350 (500x320 pixels)
        borderColor = (255, 255, 255)
        lineColor = (64, 64, 64)
        subDividerColor = (128, 128, 128)
        # Outer border: 2 pixels wide
        pygame.draw.rect(self.screen, borderColor, (8,28,504,324), 2)
        # Horizontal lines (40 pixels apart)
        for i in range(0, 7):
            y = 70+i*40
            pygame.draw.line(self.screen, lineColor, (10, y), (510, y))
        # Vertical lines (50 pixels apart)
        for i in range(0, 9):
            x = 60+i*50
            pygame.draw.line(self.screen, lineColor, (x, 30), (x, 350))
        # Vertical sub-divisions (8 pixels apart)
        for i in range(1, 40):
            y = 30+i*8
            pygame.draw.line(self.screen, subDividerColor, (258, y), (262, y))
        # Horizontal sub-divisions (10 pixels apart)
        for i in range(1, 50):
            x = 10+i*10
            pygame.draw.line(self.screen, subDividerColor, (x, 188), (x, 192))

    def test(self):
        "Test method to make sure the display is configured correctly"
        adcColor = (255, 255, 0) # Yellow
        self.drawGraticule()
        # Render the Adafruit logo at 10,360
        #logo = pygame.image.load('images/adafruit_logo.gif').convert()
        #self.screen.blit(logo, (10, 335))
        # Get a font and use it render some text on a Surface.
        font = pygame.font.Font(None, 30)
        text_surface = font.render('pyScope (%s)' % "0.1",
        True, (255, 255, 255)) # White text
        # Blit the text at 10, 0
        self.screen.blit(text_surface, (10, 0))
        # Render some text with a background color
        text_surface = font.render('Channel 0',
        True, (0, 0, 0), (255, 255, 0)) # Black text with yellow BG
        # Blit the text
        self.screen.blit(text_surface, (540, 30))
        # Update the display
        pygame.display.update()
        # Random adc data
        yLast = 260
        for x in range(10, 509):
            y = random.randrange(30, 350, 2) # Even number from 30 to 350
            pygame.draw.line(self.screen, adcColor, (x, yLast), (x+1, y))
            yLast = y
            pygame.display.update()
# Create an instance of the PyScope class
scope = pyscope()
scope.test()
# Wait 10 seconds
time.sleep(10)

 

 

音樂播放器之 CD 轉成 mp3《三》下‧中

雖說作者揣測︰

或許因為 Adafruit 的『 PiTFT 3.5″觸控螢幕』已經使用了兩個 SPI 裝置,為了避免可能的『衝突』,所以當『驅動程式』 fbtft_device 載入時,它就將系統原始的『 spidev0.0 』以及『 spidev0.1 』裝置給刪除了。

然而考之於『 fbtft_device 』的開發網頁『驅動程式』載入說明,證明作者的揣想『錯誤sudo modprobe fbtft_device name=adafruit22

dmesg

fbtft_device: SPI devices registered:
fbtft_device: spidev spi0.0 500kHz 8 bits mode=0x00
fbtft_device: spidev spi0.1 500kHz 8 bits mode=0x00
fbtft_device: ‘fb’ Platform devices registered:
fbtft_device: bcm2708_fb id=-1 pdata? no
fbtft_device: Deleting spi0.0
fbtft_device: GPIOS used by ‘adafruit22’:
fbtft_device: ‘reset’ = GPIO25
fbtft_device: ‘led’ = GPIO23
fbtft_device: SPI devices registered:
fbtft_device: spidev spi0.1 500kHz 8 bits mode=0x00
fbtft_device: fb_hx8340bn spi0.0 32000kHz 8 bits mode=0x00
graphics fb1: fb_hx8340bn frame buffer, 176×220, 75 KiB video memory, 16 KiB buffer memory, fps=20, spi0.0 at 32 MHz

1.  First it lists all SPI devices and platform devices with a name containing ‘fb’ (framebuffer) that was registered before the module was loaded.

2. Then it deletes the device connected to spi0.0 (spidev) so we can register a new one.

3. Then it tells which GPIOs that is associated with this display.

4. Then it lists which SPI devices that are currently registered (spi0.0 means SPI busnum.chipselect).

5. And lastly the driver is loaded.

再從『 fbtft Performance 』上考察,現今的『驅動程式』預設的是高速的『直接記憶體存取DMA Direct Memory Access。假使就 Adafruit 文件的 FAQ 【 page 43 】來看,這個 『驅動程式』可以『超頻』 overclock。Adafruit 版的『觸控輸入』與『螢幕輸出』之『原始碼』 Source Code 是放在『 adafruit-raspberrypi-linux forked from raspberrypi/linux 』這裡,有興趣的讀者可以研究看看。

如果仔細讀過 Adafruit 的文件,我們當然可以知道如何『測試』與『校正』觸控螢幕︰

page 25裝置檢查
ls -l /dev/input/touchscreen

page 26裝置測試
sudo evtest /dev/input/touchscreen

page 28裝置校正
sudo TSLIB_FBDEVICE=/dev/fb1 TSLIB_TSDEVICE=/dev/input/touchscreen ts_calibrate

page 29裝置操作實測
sudo TSLIB_FBDEVICE=/dev/fb1 TSLIB_TSDEVICE=/dev/input/touchscreen ts_test

ResistiveTouchscreen
電阻式觸控輸入

TouchScreen_projective_capacitive.svg
電容式觸控輸入

tscalibration
顯示器區域 (x, y) 與觸控輸入區域 (x^{\prime}, y^{\prime}) 不同,所以才需要校正。

假使我們略為了解觸控螢幕的『設計』與『工作原理』,就可以知道『理想』的點對點『平面觸控』裝置,回報『觸控點』的幾何『座標(x^{\prime}, y^{\prime}) ,它在『觸控區域』內應該是『線性的』。因此從幾何『平移』與『旋轉』的角度來看,這樣的『校正』只需要『三個點』。然而『實際裝置』通常只能足夠『線性』,而且『 X 軸』與『 Y 軸』的『解析度』未必相同,因而一般常會用『多點校正』來減少使用上之『座標誤差』。

由於在『製造過程』中所可能引起的『區域誤差』,這個『校正程序』常常是避免不了的。雖然 Adafruit 文件說『 PiTFT 3.5″觸控螢幕』已經校正過,也只能假設是使用『設計』時的『校正數據』來做的了。所以是否需要再次校正的問題,應當看『使用者界面』的規格要求而定。假使以『手指』或『手勢』的操作界面來講,就作者所知 Adafruit 的『原始校正』足以作為『基礎』,即使說需要更『精細的控制』,也許在那個『基礎』上,再寫一個應用所需之『校正程序』比較方便的吧!

由於作者考慮使用『 pygame 』來設計簡易的『使用者界面』,於是先做了一些在『 PiTFT 3.5″觸控螢幕』上如何使用『 pygame 』的『驗證』,下面的小程式修改自『 fbtft pygame 』,讀者可以用『 ssh 』指令連上『原型機』後,以

sudo python pygametest.py

跑跑看,當觸碰螢幕時,你的『 ssh 』連線終端機上會顯示︰

Pos: 322×129
Pos: 369×231
Pos: 208×259

# Source: http://inventwithpython.com/drawing.py

import pygame, sys, os
from pygame.locals import *
os.environ[“SDL_FBDEV”] = “/dev/fb1”
# Uncomment if you have a touch panel and find the X value for your device
os.environ[“SDL_MOUSEDRV”] = “TSLIB”
os.environ[“SDL_MOUSEDEV”] = “/dev/input/touchscreen”

pygame.init()

# set up the window
DISPLAYSURF = pygame.display.set_mode((480, 320), 0, 32)
pygame.display.set_caption(‘Drawing’)

# set up the colors
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 0, 0, 255)

# draw on the surface object
DISPLAYSURF.fill(WHITE)
pygame.draw.polygon(DISPLAYSURF, GREEN, ((16, 0), (111, 106), (36, 277), (56, 27), (0, 106)))
pygame.draw.line(DISPLAYSURF, BLUE, (60, 60), (120, 60), 4)
pygame.draw.line(DISPLAYSURF, BLUE, (120, 60), (60, 120))
pygame.draw.line(DISPLAYSURF, BLUE, (60, 120), (120, 120), 4)
pygame.draw.circle(DISPLAYSURF, BLUE, (40, 50), 20, 0)
pygame.draw.ellipse(DISPLAYSURF, RED, (110, 200, 40, 80), 1)
box = pygame.draw.rect(DISPLAYSURF, RED, (100, 150, 100, 50))

pixObj = pygame.PixelArray(DISPLAYSURF)
pixObj[120][144] = BLACK
pixObj[122][146] = BLACK
pixObj[124][148] = BLACK
pixObj[126][158] = BLACK
pixObj[126][158] = BLACK
del pixObj

# run the game loop
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
print(“Pos: %sx%s\n” % pygame.mouse.get_pos())
if box.collidepoint(pygame.mouse.get_pos()):
pygame.quit()
sys.exit()
pygame.display.update()

 

奇怪!!為什麼一定要冠以『 sudo 』的呢??

 

─── 待續

 

 

音樂播放器之 CD 轉成 mp3《三》下‧上

在進入『  PiTFT 3.5″ 觸控螢幕』之前,讓我們先補充一下,如何在樹莓派上,用命令列來播放 CD ︰

mplayer cdda:// 【default /dev/cdrom】
mplayer -cdrom-device /dev/sr0 cdda://

。俗話說︰書到用時方恨少。其實這是實務上常有的狀況,近年來更由於科技飛速變遷倍增壓力。如果真的有『藤子.F.不二雄』所說的《 小叮噹的記憶土司!!》果然幫的上忙嗎?縱使『學海無涯』只是顯現《如何閱讀□○??》的重要性。假使一個人能夠『固守』所學之『』,將它『連接』成『』,『編織』為『』,『貫串』一『』,就算『學網恢恢』也該是『疏而不漏』的吧!!

當我們『閱讀』他人的『文章』,也許會發現『胡適之』先生的『讀書四到』之好處,於此引用他講的『手到』︰

手到的功用。我常說:發表是吸收智識和思想的絕妙方法吸收進來的智識思想,無論是看書來的,或是聽講來的,都只是模糊零碎,都算不得我們自己的東西。自己必須做一番手腳,或做提要,或做說明,或做討論,自己重新組織過,申敘過,用自己的語言記述過,–那種智識思想方才可算是你自己的了。

。如果將此用於『樹莓派』的『學習』上,就是親身『動手做』 Do It Yourself ,如是漸次建立了自己的『思想』與『作法』。當『聽聞』各種『議論』── 比方說udevadm freezes board》── 時,我們可以『驗證』與『判斷』【 udevadm info -a -n /dev/sda 】是否會發生那篇文章所說的事?假使真的會,那麼這個『音樂播放器』上的『程式設計』就必須小心的避開那個可能引發『當機』的 Bug。其實那篇論壇上的癹文 Post 所說之事,曾經發生過 ── 見《Oops in dwc_otg_dump_spram running udevadm #21》── ,就作者當時所『』之記憶︰只要在『 udevadm 』指令上使用『 – -attribute-walk 』選項,就會當機,與使用的 kernel 版本有關。之後『樹莓派基金會』為了能更好的服務『使用者』,於是決定發行『官方版』,此時就與『 raspbian.org 』的發行分開了。或許正因那癹文者不知道過去的一段歷史所導致的吧!底下列出在『原型機』上使用『大拇哥』的命令結果給讀者參考︰

udevadm info -a -n /dev/sda

Udevadm info starts with the device specified by the devpath and then walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format. A rule to match, can be composed by the attributes of the device and the attributes from one single parent device.

looking at device ‘/devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3:1.0/host1/target1:0:0/1:0:0:0/block/sda’:
KERNEL==”sda”
SUBSYSTEM==”block”
DRIVER==””
ATTR{ro}==”0″
ATTR{size}==”15663104″
ATTR{stat}==” 170 2 1376 570 0 0 0 0 0 570 570″
ATTR{range}==”16″
ATTR{discard_alignment}==”0″
ATTR{events}==”media_change”
ATTR{ext_range}==”256″
ATTR{events_poll_msecs}==”-1″
ATTR{alignment_offset}==”0″
ATTR{inflight}==” 0 0″
ATTR{removable}==”1″
ATTR{capability}==”51″
ATTR{events_async}==””

looking at parent device ‘/devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3:1.0/host1/target1:0:0/1:0:0:0’:
KERNELS==”1:0:0:0″
SUBSYSTEMS==”scsi”
DRIVERS==”sd”
ATTRS{rev}==”1.00″
ATTRS{type}==”0″
ATTRS{scsi_level}==”3″
ATTRS{model}==”DataTraveler G2 “
ATTRS{state}==”running”
ATTRS{queue_type}==”none”
ATTRS{iodone_cnt}==”0xd2″
ATTRS{iorequest_cnt}==”0xd2″
ATTRS{evt_capacity_change_reported}==”0″
ATTRS{timeout}==”30″
ATTRS{evt_media_change}==”0″
ATTRS{max_sectors}==”240″
ATTRS{ioerr_cnt}==”0x1″
ATTRS{queue_depth}==”1″
ATTRS{vendor}==”Kingston”
ATTRS{evt_soft_threshold_reached}==”0″
ATTRS{device_blocked}==”0″
ATTRS{evt_mode_parameter_change_reported}==”0″
ATTRS{evt_lun_change_reported}==”0″
ATTRS{evt_inquiry_change_reported}==”0″
ATTRS{iocounterbits}==”32″
ATTRS{eh_timeout}==”10″

looking at parent device ‘/devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3:1.0/host1/target1:0:0’:
KERNELS==”target1:0:0″
SUBSYSTEMS==”scsi”
DRIVERS==””

looking at parent device ‘/devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3:1.0/host1’:
KERNELS==”host1″
SUBSYSTEMS==”scsi”
DRIVERS==””

looking at parent device ‘/devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3:1.0’:
KERNELS==”1-1.2.3:1.0″
SUBSYSTEMS==”usb”
DRIVERS==”usb-storage”
ATTRS{bInterfaceClass}==”08″
ATTRS{bInterfaceSubClass}==”06″
ATTRS{bInterfaceProtocol}==”50″
ATTRS{bNumEndpoints}==”02″
ATTRS{supports_autosuspend}==”1″
ATTRS{bAlternateSetting}==” 0″
ATTRS{bInterfaceNumber}==”00″

looking at parent device ‘/devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.3’:
KERNELS==”1-1.2.3″
SUBSYSTEMS==”usb”
DRIVERS==”usb”
ATTRS{bDeviceSubClass}==”00″
ATTRS{bDeviceProtocol}==”00″
ATTRS{devpath}==”1.2.3″
ATTRS{idVendor}==”0951″
ATTRS{speed}==”480″
ATTRS{bNumInterfaces}==” 1″
ATTRS{bConfigurationValue}==”1″
ATTRS{bMaxPacketSize0}==”64″
ATTRS{busnum}==”1″
ATTRS{devnum}==”8″
ATTRS{configuration}==””
ATTRS{bMaxPower}==”200mA”
ATTRS{authorized}==”1″
ATTRS{bmAttributes}==”80″
ATTRS{bNumConfigurations}==”1″
ATTRS{maxchild}==”0″
ATTRS{bcdDevice}==”13c6″
ATTRS{avoid_reset_quirk}==”0″
ATTRS{quirks}==”0x0″
ATTRS{serial}==”00137299805EA9B0B62404CF”
ATTRS{version}==” 2.00″
ATTRS{urbnum}==”630″
ATTRS{ltm_capable}==”no”
ATTRS{manufacturer}==”Kingston”
ATTRS{removable}==”unknown”
ATTRS{idProduct}==”1624″
ATTRS{bDeviceClass}==”00″
ATTRS{product}==”DataTraveler G2″

looking at parent device ‘/devices/platform/bcm2708_usb/usb1/1-1/1-1.2’:
KERNELS==”1-1.2″
SUBSYSTEMS==”usb”
DRIVERS==”usb”
ATTRS{bDeviceSubClass}==”00″
ATTRS{bDeviceProtocol}==”02″
ATTRS{devpath}==”1.2″
ATTRS{idVendor}==”1a40″
ATTRS{speed}==”480″
ATTRS{bNumInterfaces}==” 1″
ATTRS{bConfigurationValue}==”1″
ATTRS{bMaxPacketSize0}==”64″
ATTRS{busnum}==”1″
ATTRS{devnum}==”4″
ATTRS{configuration}==””
ATTRS{bMaxPower}==”100mA”
ATTRS{authorized}==”1″
ATTRS{bmAttributes}==”e0″
ATTRS{bNumConfigurations}==”1″
ATTRS{maxchild}==”7″
ATTRS{bcdDevice}==”0100″
ATTRS{avoid_reset_quirk}==”0″
ATTRS{quirks}==”0x0″
ATTRS{version}==” 2.00″
ATTRS{urbnum}==”64″
ATTRS{ltm_capable}==”no”
ATTRS{removable}==”removable”
ATTRS{idProduct}==”0201″
ATTRS{bDeviceClass}==”09″
ATTRS{product}==”USB 2.0 Hub [MTT]”

looking at parent device ‘/devices/platform/bcm2708_usb/usb1/1-1’:
KERNELS==”1-1″
SUBSYSTEMS==”usb”
DRIVERS==”usb”
ATTRS{bDeviceSubClass}==”00″
ATTRS{bDeviceProtocol}==”02″
ATTRS{devpath}==”1″
ATTRS{idVendor}==”0424″
ATTRS{speed}==”480″
ATTRS{bNumInterfaces}==” 1″
ATTRS{bConfigurationValue}==”1″
ATTRS{bMaxPacketSize0}==”64″
ATTRS{busnum}==”1″
ATTRS{devnum}==”2″
ATTRS{configuration}==””
ATTRS{bMaxPower}==”2mA”
ATTRS{authorized}==”1″
ATTRS{bmAttributes}==”e0″
ATTRS{bNumConfigurations}==”1″
ATTRS{maxchild}==”5″
ATTRS{bcdDevice}==”0200″
ATTRS{avoid_reset_quirk}==”0″
ATTRS{quirks}==”0x0″
ATTRS{version}==” 2.00″
ATTRS{urbnum}==”51″
ATTRS{ltm_capable}==”no”
ATTRS{removable}==”unknown”
ATTRS{idProduct}==”9514″
ATTRS{bDeviceClass}==”09″

looking at parent device ‘/devices/platform/bcm2708_usb/usb1’:
KERNELS==”usb1″
SUBSYSTEMS==”usb”
DRIVERS==”usb”
ATTRS{bDeviceSubClass}==”00″
ATTRS{bDeviceProtocol}==”01″
ATTRS{devpath}==”0″
ATTRS{idVendor}==”1d6b”
ATTRS{speed}==”480″
ATTRS{bNumInterfaces}==” 1″
ATTRS{bConfigurationValue}==”1″
ATTRS{bMaxPacketSize0}==”64″
ATTRS{authorized_default}==”1″
ATTRS{busnum}==”1″
ATTRS{devnum}==”1″
ATTRS{configuration}==””
ATTRS{bMaxPower}==”0mA”
ATTRS{authorized}==”1″
ATTRS{bmAttributes}==”e0″
ATTRS{bNumConfigurations}==”1″
ATTRS{maxchild}==”1″
ATTRS{bcdDevice}==”0312″
ATTRS{avoid_reset_quirk}==”0″
ATTRS{quirks}==”0x0″
ATTRS{serial}==”bcm2708_usb”
ATTRS{version}==” 2.00″
ATTRS{urbnum}==”26″
ATTRS{ltm_capable}==”no”
ATTRS{manufacturer}==”Linux 3.12.26+ dwc_otg_hcd”
ATTRS{removable}==”unknown”
ATTRS{idProduct}==”0002″
ATTRS{bDeviceClass}==”09″
ATTRS{product}==”DWC OTG Controller”

looking at parent device ‘/devices/platform/bcm2708_usb’:
KERNELS==”bcm2708_usb”
SUBSYSTEMS==”platform”
DRIVERS==”dwc_otg”
ATTRS{hnp}==”HstNegScs = 0x0″
ATTRS{srp}==”SesReqScs = 0x1″
ATTRS{regvalue}==”invalid offset”
ATTRS{hsic_connect}==”HSIC Connect = 0x1″
ATTRS{guid}==”GUID = 0x2708a000″
ATTRS{mode}==”Mode = 0x1″
ATTRS{srpcapable}==”SRPCapable = 0x1″
ATTRS{regdump}==”Register Dump”
ATTRS{gpvndctl}==”GPVNDCTL = 0x00000000″
ATTRS{ggpio}==”GGPIO = 0x00000000″
ATTRS{hprt0}==”HPRT0 = 0x00001005″
ATTRS{wr_reg_test}==”Time to write GNPTXFSIZ reg 10000000 times: 420 msecs (42 jiffies)”
ATTRS{hcd_frrem}==”HCD Dump Frame Remaining”
ATTRS{mode_ch_tim_en}==”Mode Change Ready Timer Enable = 0x0″
ATTRS{gnptxfsiz}==”GNPTXFSIZ = 0x01000306″
ATTRS{remote_wakeup}==”Remote Wakeup Sig = 0 Enabled = 0 LPM Remote Wakeup = 0″
ATTRS{busconnected}==”Bus Connected = 0x1″
ATTRS{hcddump}==”HCD Dump”
ATTRS{gotgctl}==”GOTGCTL = 0x001c0001″
ATTRS{spramdump}==”SPRAM Dump”
ATTRS{grxfsiz}==”GRXFSIZ = 0x00000306″
ATTRS{gsnpsid}==”GSNPSID = 0x4f54280a”
ATTRS{gusbcfg}==”GUSBCFG = 0x00001700″
ATTRS{hptxfsiz}==”HPTXFSIZ = 0x02000406″
ATTRS{devspeed}==”Device Speed = 0x0″
ATTRS{fr_interval}==”Frame Interval = 0x1d4c”
ATTRS{rem_wakeup_pwrdn}==””
ATTRS{bussuspend}==”Bus Suspend = 0x0″
ATTRS{buspower}==”Bus Power = 0x1″
ATTRS{hnpcapable}==”HNPCapable = 0x1″
ATTRS{rd_reg_test}==”Time to read GNPTXFSIZ reg 10000000 times: 1440 msecs (144 jiffies)”
ATTRS{enumspeed}==”Device Enumeration Speed = 0x1″
ATTRS{inv_sel_hsic}==”Invert Select HSIC = 0x0″
ATTRS{regoffset}==”0xffffffff”

looking at parent device ‘/devices/platform’:
KERNELS==”platform”
SUBSYSTEMS==””
DRIVERS==””

 

350px-SPI_single_slave.svg
SPI bus: single master and single slave

400px-SPI_8-bit_circular_transfer.svg
A typical hardware setup

400px-SPI_timing_diagram2.svg
A timing diagram showing clock polarity and phase

bplus-gpio
B+ GPIO

序列週邊介面』 SPI Serial Peripheral Interface 是一種三或四線『同步式』序列資料之『鏈接』 link 電路,據聞,最早由 Motorola 公司所『命名』,功能適用於短距離、全雙工、單一『主控器』 master 的通訊系統。雖然說『樹莓派』上的 BCM2835 晶片有三個 SPI 控制器,然而 GPIO 擴張接腳上只有一個控制器,可以連接兩個 SPI 週邊。Adafruit 的『 PiTFT 3.5″觸控螢幕』就是使用 SPI 『匯流排』 Bus 的裝置,其一用於『螢幕輸出』,另一用於『觸控輸入』。這可以用『 dmesg | grep stmpe 』來確認。而且 Adafruit 的安裝程式創建了一個 udev 的規則『 /etc/udev/rules.d/95-stmpe.rules 』︰

SUBSYSTEM==”input”, ATTRS{name}==”stmpe-ts”, ENV{DEVNAME}==”*event*”, SYMLINK+=”input/touchscreen”

,將『觸控輸入』命名為『 touchscreen 』放在『/dev/input』的目錄下。或許因為 Adafruit 的『 PiTFT 3.5″觸控螢幕』已經使用了兩個 SPI 裝置,為了避免可能的『衝突』,所以當『驅動程式』 fbtft_device 載入時,它就將系統原始的『 spidev0.0 』以及『 spidev0.1 』裝置給刪除了︰

dmesg | grep spi

[ 5.743015] bcm2708_spi bcm2708_spi.0: master is unqueued, this is deprecated
[ 5.876934] bcm2708_spi bcm2708_spi.0: SPI Controller at 0x20204000 (irq 80)
[ 14.052342] fbtft_device: spidev spi0.0 500kHz 8 bits mode=0x00
[ 14.061006] fbtft_device: spidev spi0.1 500kHz 8 bits mode=0x00
[ 14.222481] fbtft_device: Deleting spi0.1 (spi0.1)
[ 14.236388] stmpe-spi spi0.1: stmpe610 detected, chip id: 0x811
[ 14.262495] fbtft_device: Deleting spi0.0 (spi0.0)
[ 14.309301] fbtft_device: stmpe610 spi0.1 500kHz 8 bits mode=0x00
[ 14.341123] fbtft_device: fb_hx8357d spi0.0 32000kHz 8 bits mode=0x00
[ 14.409289] input: stmpe-ts as /devices/platform/bcm2708_spi.0/spi_master/spi0/spi0.1/stmpe-ts.0/input/input2
[ 16.160748] graphics fb1: fb_hx8357d frame buffer, 480×320, 300 KiB video memory, 4 KiB DMA buffer memory, fps=20, spi0.0 at 32 MHz

,所以我們無法如網路上之一些文章所講的,用『 ls -la /dev/spi* 』方法來確定 SPI 裝置是否『存在』。雖然我們可以從『開機過程』和『登錄畫面』來確認『螢幕』工作正常,那麼我們要怎麽確認『觸控輸入』的問題呢?如果用『 cat /dev/input/touchscreen | hexdump 』︰

第一次觸控輸出
0000000 434d 549e d405 0002 0003 0000 0681 0000
0000010 434d 549e d405 0002 0003 0001 0821 0000
0000020 434d 549e d405 0002 0003 0018 0078 0000
0000030 434d 549e d405 0002 0001 014a 0001 0000
0000040 434d 549e d405 0002 0000 0000 0000 0000
0000050 434d 549e f805 0002 0003 0000 06e7 0000
0000060 434d 549e f805 0002 0003 0001 087e 0000
0000070 434d 549e f805 0002 0003 0018 0068 0000
0000080 434d 549e f805 0002 0000 0000 0000 0000
0000090 434d 549e 19d8 0003 0003 0000 06cb 0000
00000a0 434d 549e 19d8 0003 0003 0001 0883 0000
00000b0 434d 549e 19d8 0003 0003 0018 00a4 0000
00000c0 434d 549e 19d8 0003 0000 0000 0000 0000
00000d0 434d 549e 4733 0003 0003 0000 0673 0000
00000e0 434d 549e 4733 0003 0003 0001 085c 0000
00000f0 434d 549e 4733 0003 0003 0018 00c3 0000
0000100 434d 549e 4733 0003 0000 0000 0000 0000
0000110 434d 549e 6804 0003 0003 0000 068c 0000
0000120 434d 549e 6804 0003 0003 0001 0853 0000
0000130 434d 549e 6804 0003 0003 0018 00c5 0000
0000140 434d 549e 6804 0003 0000 0000 0000 0000
0000150 434d 549e 8937 0003 0003 0000 06f2 0000
0000160 434d 549e 8937 0003 0003 0001 0881 0000
0000170 434d 549e 8937 0003 0003 0018 0083 0000
0000180 434d 549e 8937 0003 0000 0000 0000 0000
0000190 434d 549e a9d4 0003 0003 0000 06f6 0000
00001a0 434d 549e a9d4 0003 0003 0001 087d 0000
00001b0 434d 549e a9d4 0003 0003 0018 0073 0000
00001c0 434d 549e a9d4 0003 0000 0000 0000 0000
00001d0 434d 549e 1528 0004 0003 0018 0000 0000
00001e0 434d 549e 1528 0004 0001 014a 0000 0000
00001f0 434d 549e 1528 0004 0000 0000 0000 0000
0000200 434d 549e 9e1a 0004 0003 0000 06a4 0000
0000210 434d 549e 9e1a 0004 0003 0001 0829 0000
0000220 434d 549e 9e1a 0004 0003 0018 004b 0000
0000230 434d 549e 9e1a 0004 0001 014a 0001 0000
0000240 434d 549e 9e1a 0004 0000 0000 0000 0000
0000250 434d 549e c49e 0004 0003 0000 0694 0000
0000260 434d 549e c49e 0004 0003 0018 0088 0000
0000270 434d 549e c49e 0004 0000 0000 0000 0000
0000280 434d 549e 234c 0005 0003 0018 0000 0000
0000290 434d 549e 234c 0005 0001 014a 0000 0000
00002a0 434d 549e 234c 0005 0000 0000 0000 0000

,這樣我們真能歸結『觸控』硬體是沒有問題的嗎??

 

─── 待續

 

 

音樂播放器之 CD 轉成 mp3《三》中

當然確定了『供電』事宜只是個『開始』,如何能減少『使用者』之『操作失敗』的『經驗』,可就是『大哉問』的了。即使祇就

【音樂播放器】需求規格一??

將音樂 CD 轉成 mp3,寫到大拇哥上!!

的考慮也是一樣。這是為什麼的呢?比方說,萬一放錯了 CD 片,一個『使用者』必須要等到做完『製造程序』才可以『換片』的嗎?與其爭議是『誰的過錯』?這難到真是『不可預見』的嗎?再者,大部分的『 USB DVD 讀寫裝置』上面都有『手動的 Eject 按鍵』,假使『作到一半』誤觸了『按鍵』,果然就『沒有辦法』能解決的嗎??『設計者』之『』和『使用人』之『』是否能夠『相通』,這正是古往今來的『器物製造』的『為何如是』之『』的吧!因而作者也就『蕭規曹隨』試圖『避免』那些也許只是『一時之誤』罷了。就裝置的『性能』與『控制』上講,當然要能『鎖定目標』隨心所欲的了!既然意圖想要『控制越多』,因而自己所需要知道的技術『細節也不少』。就像有人問《How can I disable the button of my CD/DVD drive? 》一樣,作者也曾經踏上那種『探索之路』︰

$ eject -i 1 /dev/sr0
eject: CD-Drive may NOT be ejected with device button

$ eject -i 0 /dev/sr0
eject: CD-Drive may be ejected with device button

。一般來說,『過去』 linux 系統上之『裝置驅動程式』假使沒有『提供』某種『功能』,想要自己『寫作』一個『程式』來作這麽一件事,可真的是『不容易』啊!然而在今天那個『不容易』該說是『蠻困難』,絕非是『很困難』的了。這從現今的 linux 『系統架構圖』上來看更是一目了然。

Free_and_open-source-software_display_servers_and_UI_toolkits.svg

那麼為了寫一個『應用程式』,我們需要了解多少『系統細節』的呢?廣泛的說,這是由『應用需要』所決定的事情,一般所講的廣義『應用程式界面』  API 的理念,就是為著能夠減輕不同應用程式『設計者』所需之『知學負擔』而建構的。於是進一步就有了所謂的□□『軟體開發套件』 SDK  Software Development Kit ,因此人們的『程式設計』常常就從學習○○ SDK 開始。由於我們這裡所談的事情並非是某種特定的☆☆『嵌入式系統』 Embedded system,有著很大的『自由度』,實在不好說什麼是『適切的 SDK』?因此有時不得不上窮碧落下黃泉的四下搜尋,如是對 linux 系統『運作』的『整體理解』就顯得必要的了!這好處是什麼呢?也許是在打造自己專屬的 SDK 的樂趣吧!當然像 《V怪客》 V for Vendetta 之輩或許這還是必修課的呢!即使只從『電腦病毒』的發展『歷史』來看,就可以『明白』網際網路上有『四通八達』的渠道,加上某些有心人士的『黑客資訊』。甚至一些『國際大電腦公司』都免不了中了『電腦病毒』以及遭受『駭客攻擊』。多知道一些系統底層所作的事,對於『安全性設計』而言,也是件不可或缺的『實務』的吧!!

據聞 linux kernel 自 2.6.13 提供了新的 uevent interface,而後

In April 2012, udev’s codebase was merged into the systemd source tree. In October 2012, Linus Torvalds criticized Kay Sievers’ approach of udev maintenance and bugs related to firmware loading, stating:

Yes, doing it in the kernel is “more robust”. But don’t play games, and stop the lying. It’s more robust because we have maintainers that care, and because we know that regressions are not something we can play fast and loose with. If something breaks, and we don’t know what the right fix for that breakage is, we revert the thing that broke. So yes, we’re clearly better off doing it in the kernel. Not because firmware loading cannot be done in user space. But simply because udev maintenance since Greg gave it up has gone downhill.

。從此『動態裝置熱插拔管理』 udev 納入了 systemd,由 kernel.org 來做維護管理。

起先 linux 上並沒有所謂的『熱插拔』 hotplug 裝置管理,系統上所用的所有裝置都需要建置『靜態的裝置特殊檔』 static device special file ── mknod – make block or character special files ──。聽說當年最紅火的『Red 9』發行版上有

On Red Hat 9, 18000 entries in /dev!
All entries for all possible devices
had to be created at system installation.

。這對『系統管理者』來說恐怕很難笑的出來的了。

在此我們無法詳細介紹 udev 的用法,有興趣了解的讀者可以參照《這裡》開始。此處僅針對『 USB DVD 讀寫裝置』的『熱插拔』過程有關的事物作點說明。我們可以用『 udevadm monitor 』指令來『觀察』 kernel 『 USB 熱插拔』過程的『 uevent 』,這對理解 udev 的工作方式有很大的幫助。下面列出『 USB DVD 讀寫裝置』的熱插拔過程的輸出訊息︰

$udevadm monitor
monitor will print the received events for:
UDEV – the event which udev sends out after rule processing
KERNEL – the kernel uevent

此時將 USB DVD 讀寫裝置熱插入

輸出訊息

KERNEL[306628.132803] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5 (usb)
KERNEL[306628.139360] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0 (usb)
KERNEL[306628.145393] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3 (scsi)
KERNEL[306628.145647] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/scsi_host/host3 (scsi_host)
UDEV [306628.155527] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5 (usb)
UDEV [306628.175071] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0 (usb)
UDEV [306628.178074] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3 (scsi)
UDEV [306628.182839] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/scsi_host/host3 (scsi_host)
KERNEL[306629.151250] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0 (scsi)
KERNEL[306629.151503] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0 (scsi)
UDEV [306629.153895] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0 (scsi)
UDEV [306629.178328] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0 (scsi)
KERNEL[306629.185589] add /devices/virtual/bdi/11:0 (bdi)
KERNEL[306629.187210] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/block/sr0 (block)
KERNEL[306629.187428] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/scsi_device/3:0:0:0 (scsi_device)
KERNEL[306629.188185] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/scsi_generic/sg0 (scsi_generic)
KERNEL[306629.188970] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/bsg/3:0:0:0 (bsg)
UDEV [306629.197653] add /devices/virtual/bdi/11:0 (bdi)
KERNEL[306629.199077] change /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/block/sr0 (block)
UDEV [306629.231068] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/scsi_device/3:0:0:0 (scsi_device)
UDEV [306629.244105] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/bsg/3:0:0:0 (bsg)
UDEV [306629.262723] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/scsi_generic/sg0 (scsi_generic)
UDEV [306629.903661] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/block/sr0 (block)
UDEV [306630.106289] change /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/block/sr0 (block)
udevadm monitor
monitor will print the received events for:
UDEV – the event which udev sends out after rule processing
KERNEL – the kernel uevent

此時將 USB DVD 讀寫裝置熱拔出

輸出訊息

KERNEL[306678.488526] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/bsg/3:0:0:0 (bsg)
UDEV [306678.493461] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/bsg/3:0:0:0 (bsg)
KERNEL[306678.496300] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/scsi_generic/sg0 (scsi_generic)
KERNEL[306678.497406] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/scsi_device/3:0:0:0 (scsi_device)
KERNEL[306678.499867] remove /devices/virtual/bdi/11:0 (bdi)
KERNEL[306678.500995] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/block/sr0 (block)
KERNEL[306678.501611] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0 (scsi)
KERNEL[306678.503098] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0 (scsi)
KERNEL[306678.508922] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/scsi_host/host3 (scsi_host)
KERNEL[306678.510244] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3 (scsi)
KERNEL[306678.510618] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0 (usb)
KERNEL[306678.512012] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5 (usb)
UDEV [306678.514032] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/scsi_device/3:0:0:0 (scsi_device)
UDEV [306678.525752] remove /devices/virtual/bdi/11:0 (bdi)
UDEV [306678.553766] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/scsi_host/host3 (scsi_host)
UDEV [306678.569584] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/scsi_generic/sg0 (scsi_generic)
UDEV [306678.578413] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/block/sr0 (block)
UDEV [306678.591236] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0 (scsi)
UDEV [306678.593733] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0 (scsi)
UDEV [306678.595992] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3 (scsi)
UDEV [306678.597956] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0 (usb)
UDEV [306678.601293] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5 (usb)


難到我們真的需要知道這些事情的嗎?假使我們不知道在 raspbian 上, udev 系統自動為我們做了些什麼?比方說『一貫性』 CD 裝置名稱的設定︰

more /etc/udev/rules.d/70-persistent-cd.rules

,插拔多種品牌的『 USB DVD 讀寫裝置』後,到底『 /dev/cdrom 』是哪個裝置呢?或者現在的『 /dev/sr0 』又指的是誰丫,那我們就必須得面對這樣的『困擾』;或許根本還不要說那個檔卻是由『 /lib/udev/write_cd_rules 』自動產生的呢!更進一步的講,如果不知道『熱插拔』的『事件』之過程,我們怎麽發現『使用者』已經插上『 USB DVD 讀寫裝置』?而且放入了『音樂 CD』呢?這樣當然『很難』自動『播歌』的吧!萬一這是將來客戶所要『需求規格』之一的呢??

 

─── 待續