?? linux設備驅動之usb主機控制器驅動分析-(4)_linux技術文章_linux_操作系統4.htm
字號:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0072)http://www.diybl.com/course/6_system/linux/Linuxjs/2008923/144940_4.html -->
<HTML><HEAD><TITLE>linux設備驅動之USB主機控制器驅動分析-(4)_Linux技術文章_Linux_操作系統</TITLE>
<META http-equiv=Content-Type content=text/html;charset=gb2312>
<META content=www.diybl.com,DIY部落版權所有 name=Copyright>
<META content=linux設備驅動之USB主機控制器驅動分析_Linux技術文章_Linux_操作系統 name=keywords>
<META
content="linux設備驅動之USB主機控制器驅動分析_Linux技術文章_ port1); dev->dev..."
name=description>
<META content=index,follow name=robots>
<META content=INDEX,FOLLOW name=GOOGLEBOT><LINK href="article2.css"
type=text/css rel=stylesheet><LINK
href="linux設備驅動之USB主機控制器驅動分析-(4)_Linux技術文章_Linux_操作系統4.files/article2.css"
type=text/css rel=stylesheet>
<SCRIPT src="linux設備驅動之USB主機控制器驅動分析-(4)_Linux技術文章_Linux_操作系統4.files/article.js"
type=text/javascript></SCRIPT>
<SCRIPT src="linux設備驅動之USB主機控制器驅動分析-(4)_Linux技術文章_Linux_操作系統4.files/1060103.js"
type=text/javascript></SCRIPT>
<META content="MSHTML 6.00.2900.3395" name=GENERATOR></HEAD>
<BODY><INPUT type=hidden value=144940 name=passage_id><INPUT type=hidden
value=1060103 name=catalog_id>
<DIV id=wrap>
<DIV class=top_bar align=center>
<TABLE cellSpacing=0 width=935>
<TBODY>
<TR>
<TD><A href="http://www.diybl.com/">網站首頁</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://news.diybl.com/" target=_blank>新聞首頁</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/1_web/">網頁設計</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/2_picdesign/">圖形動畫</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/3_program/">軟件編程</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/4_webprogram/">網站開發</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/5_office/">辦公軟件</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/6_system/">操作系統</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/7_databases/">數據庫</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/webjsh/">網絡技術</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/comshiti/">認證考試</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/fwzl/">范文資料</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/hack/">黑客攻防</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/chm/" target=_blank><FONT
color=red>書籍教程</FONT></A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://bbs.diybl.com/"
target=_blank>進入論壇</A></TD></TR></TBODY></TABLE></DIV>
<TABLE class=adNone id=PublicRelation cellSpacing=0 cellPadding=0 width=950
border=0>
<TBODY>
<TR>
<TD vAlign=top width=864>
<DIV class=logo><A href="http://www.diybl.com/" target=_blank><IMG
height=60
src="linux設備驅動之USB主機控制器驅動分析-(4)_Linux技術文章_Linux_操作系統4.files/logo.gif"
width=200></A></DIV>
<DIV class=ad_f1 id=ad_f1>
<SCRIPT
src="linux設備驅動之USB主機控制器驅動分析-(4)_Linux技術文章_Linux_操作系統4.files/ad_f1.js"></SCRIPT>
</DIV><!--<div class="top_bar2">-->
<UL class=menu>
<LI><A href="http://www.diybl.com/course/6_system/linux/"
target=_blank><SPAN>Linux</SPAN></A>
<LI><A href="http://www.diybl.com/course/6_system/linux/Linuxxl/"
target=_blank><SPAN>Linux系列教程</SPAN></A>
<LI><A href="http://www.diybl.com/course/6_system/linux/linuxjq/"
target=_blank><SPAN>Linux應用技巧</SPAN></A>
<LI><A
href="http://www.diybl.com/course/6_system/linux/Linuxjs/70b7fsdwvtk.html"
target=_blank><SPAN>Linux技術文章</SPAN></A></LI></UL><!--</div>--></TD>
<TD width=6></TD>
<TD vAlign=top align=middle width=100>
<DIV class=hotNCout>
<DIV class=hotNC>
<UL>
<LI><A
href="javascript:window.external.addFavorite('http://www.diybl.com/','DIY部落');">加入收藏</A>
<LI><A href="http://www.diybl.com/map.html" target=_blank>網站地圖</A>
<LI><A href="http://www.diybl.com/chm/" target=_blank>書籍教程</A>
<LI><A href="http://www.diybl.com/user/register.asp"
target=_blank>會員注冊</A> </LI></UL></DIV></DIV></TD></TR></TBODY></TABLE>
<DIV class=split style="HEIGHT: 3px"></DIV>
<DIV class=ad_ftop id=ad_ftop>
<SCRIPT
src="linux設備驅動之USB主機控制器驅動分析-(4)_Linux技術文章_Linux_操作系統4.files/ad_ftop.js"></SCRIPT>
</DIV>
<DIV class=subNav>
<DIV style="FLOAT: right"><INPUT name=wd1> <INPUT onclick=tosearch(document.all.wd1); type=button value=" 千尋搜索 "></DIV><SPAN><A
href="http://www.diybl.com/">DIY部落</A> >> <A
href="http://www.diybl.com/course/6_system/">操作系統</A> >> <A
href="http://www.diybl.com/course/6_system/linux/">Linux</A> >> <A
href="http://www.diybl.com/course/6_system/linux/Linuxjs/70b7fsdwvtk.html">Linux技術文章</A>
>> 正文</SPAN></DIV>
<DIV class=split></DIV>
<DIV class=main>
<DIV class=lc_blue>
<DIV class=lcBlk>
<H1>linux設備驅動之USB主機控制器驅動分析</H1>
<DIV class=from_info>http://www.diybl.com/ 2008-9-23 網絡 點擊:<SPAN
style="FONT-WEIGHT: bold; COLOR: #ff0000">
<SCRIPT src="linux設備驅動之USB主機控制器驅動分析-(4)_Linux技術文章_Linux_操作系統4.files/p_count.htm"
lanuage="javascript"></SCRIPT>
</SPAN> <A
href="http://www.diybl.com/course/6_system/linux/Linuxjs/2008923/144940_4.html#comment">[
評論 ]</A></DIV>
<DIV class=artibody>
<DIV class=ad_f2 id=ad_f2>
<SCRIPT
src="linux設備驅動之USB主機控制器驅動分析-(4)_Linux技術文章_Linux_操作系統4.files/ad_f2.js"></SCRIPT>
</DIV>
<DIV class=ad_f3 id=ad_f3>
<SCRIPT
src="linux設備驅動之USB主機控制器驅動分析-(4)_Linux技術文章_Linux_操作系統4.files/ad_f3.js"></SCRIPT>
</DIV>文章搜索: <INPUT maxLength=255 size=30 name=wd2> <INPUT onclick=tosearch(document.all.wd2); type=button value=千尋搜索><A
class=redlink
href="javascript:self.location='/user/chm/rar.asp?c_id=48375'">【點擊打包該文章】</A>
<SCRIPT
src="linux設備驅動之USB主機控制器驅動分析-(4)_Linux技術文章_Linux_操作系統4.files/art_top.js"></SCRIPT>
<P>port1);<BR> <BR>
dev->dev.parent =
&parent->dev;<BR>
sprintf(&dev->dev.bus_id[0],
"%d-%s",<BR>
bus->busnum,
dev->devpath);<BR> <BR>
/* hub driver sets up TT records */<BR>
}<BR>//上面的節點名稱賦值很有意思: 如果是根集線器,它的名稱為"usb"+總線號<BR>//如果是第1條總線上的root
hub,對應就是usb0<BR>//如果是根集線其下面的設備.它的名稱為:總線號+ "-" + portnum 或者:總線號+ "-" +
上層總線//的devpath<BR> <BR> dev->portnum =
port1;<BR> dev->bus =
bus;<BR> dev->parent =
parent;<BR>
INIT_LIST_HEAD(&dev->filelist);<BR> <BR>#ifdef
CONFIG_PM<BR>
mutex_init(&dev->pm_mutex);<BR>
INIT_DELAYED_WORK(&dev->autosuspend,
usb_autosuspend_work);<BR> dev->autosuspend_delay =
usb_autosuspend_delay * HZ;<BR> dev->connect_time =
jiffies;<BR> dev->active_duration =
-jiffies;<BR>#endif<BR> if (root_hub) /* Root hub always
ok [and always wired] */<BR>
dev->authorized = 1;<BR> else
{<BR> dev->authorized =
usb_hcd->authorized_default;<BR>
dev->wusb = usb_bus_is_wusb(bus)? 1 : 0;<BR>
}<BR> return
dev;<BR>}<BR>該函數的參數如下:<BR>Parent:該設備的上層hub.對于root
hub來說,該參數為NULL.表示它的上層無設備<BR>Bus :該設備所屬的bus<BR>port1:該設備所連hub的端口號.對于root
hub來說,該項為0.<BR>參考添加的注釋,這段代碼應該很容易理解.注意在代碼為usb_driver內嵌的struct
device的賦值過程.它的bus被設置成了usb_bus_type.它的type被設置成了usb_device_type.這些賦值是我們以后分析usb設備驅動的基礎.這里不再啰嗦.為以后的分析打一個伏筆.:-)
.在這里,注重分析一下對端點0的操作以及設備的命名規則.<BR>1:對于端點0:<BR>USB協議規定每個設備都必須要有一個端點0.USB控制器和這個端點0通信都可以獲得整個設備的信息.USB設備可以有多個端口.但是除了端點0外,其它端口的通信都是單向的.如:一些端點只能接收數據.另外的端點只能發送數據.每個端點都對應一個端點號,一個端點號+通信方向就確定了一個端點.也就是說,一個端點號對應二個端點,進來方向的一個,出去方向的一個.<BR>對于端點0.就分析這么多.具體的流程.以后結合代碼再來分析.<BR>結合上面的代碼:<BR>dev->ep0.desc.表示ep0(端點0)的端點描述符.desc的定義為struct
usb_endpoint_descriptor.在usb2.0的規范中,總共有8種描述符.端點描述符的類型定義為5.整個端點描述符的長度為7.<BR>跟進去看一下usb_enable_endpoint():<BR>void
usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint
*ep)<BR>{<BR> int epnum =
usb_endpoint_num(&ep->desc);<BR> int is_out =
usb_endpoint_dir_out(&ep->desc);<BR> int
is_control =
usb_endpoint_xfer_control(&ep->desc);<BR> <BR>
if (is_out || is_control) {<BR>
usb_settoggle(dev, epnum, 1,
0);<BR> dev->ep_out[epnum] =
ep;<BR> }<BR> if (!is_out ||
is_control) {<BR>
usb_settoggle(dev, epnum, 0,
0);<BR> dev->ep_in[epnum] =
ep;<BR> }<BR> ep->enabled =
1;<BR>}<BR>Usb_endpoint_num()定義如下:<BR>static inline int usb_endpoint_num(const
struct usb_endpoint_descriptor *epd)<BR>{<BR> return
epd->bEndpointAddress &
USB_ENDPOINT_NUMBER_MASK;<BR>}<BR>即在描述符的bEndpointAddress字段中,取得端點號.<BR>usb_endpoint_dir_out()定義如下:<BR>static
inline int
usb_endpoint_dir_out(<BR>
const struct usb_endpoint_descriptor *epd)<BR>{<BR>
return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
USB_DIR_OUT);<BR>}<BR>即判斷該端點是否是OUT方向的.OUT方向.就是指從主機發往設備方向.<BR>usb_endpoint_xfer_control()定義如下:<BR>static
inline int
usb_endpoint_xfer_control(<BR>
const struct usb_endpoint_descriptor *epd)<BR>{<BR>
return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
==<BR>
USB_ENDPOINT_XFER_CONTROL);<BR>}<BR>即檢查該端點是否是控制傳輸端點.<BR> <BR>從上面的流程看,我們并沒有對ep0的相關字段賦值,這些函數會全部都返回0.<BR>所以,流程就轉到這里:<BR> <BR>if
(!is_out || is_control) {<BR>
usb_settoggle(dev, epnum, 0,
0);<BR> dev->ep_in[epnum] =
ep;<BR>}<BR> ep->enabled =
1;<BR> <BR>這段代碼執行的效果就是:dev->ep_in[0]=ep. Dev->
toggle[0]的0位被置1.<BR>最后將ep->enabled置為1.表示啟用該設備.<BR>其實該段代碼主要是改變dev->ep_in[]和dev->toggle[].將struct
usb_device的相關成員列出:<BR>struct usb_device {<BR>
……<BR> unsigned int toggle[2];
/* one bit for each endpoint*/<BR>
……<BR> struct usb_host_endpoint
*ep_in[16];<BR> struct usb_host_endpoint
*ep_out[16];<BR>
……<BR>}<BR>Usb2.0的spec規定.每個設備最多有15個端點號.即最多表示30個端點.另外再加一個端點0.共計31個.<BR>數組ep_in[]表示in方向的端點集合.ep_out[]表示ONT方向的集合.它們在數組中的位置是以端點號做為索引的.<BR><BR>而對于toggle[]數組.他實際上就是一個位圖.IN方向的是toggle[0].OUT方向的是toggle[1].其實,這個數組中的每一位表示ep的toggle值.關于toggle,在分析USB的數據傳輸再來說明,另外,從usb_enable_endpoint()中的代碼可以看到,端點的toggle是初始化為0的.<BR>2:對于usb設備的命名規則<BR>注釋中解釋了一部份,在這里整理一下.相應的代碼如下:<BR>if
(unlikely(!parent)) {<BR>
dev->devpath[0] =
'0';<BR> <BR>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -