一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

USB 3G網(wǎng)卡驅(qū)動(dòng)流程

 wu_wade 2015-01-23
  USB 3G網(wǎng)卡驅(qū)動(dòng)流程
簡介
首先介紹一下linux下的整體驅(qū)動(dòng)模式:
本文基于的linux kernel版本為2.6.36 (并且華為EM770W驅(qū)動(dòng),是由FriendlyARM公司定制的。
所以該部分驅(qū)動(dòng)可以在友善的官方網(wǎng)站上下載。其宏定義為CONFIG_MACH_MINI6410)
總線,設(shè)備,驅(qū)動(dòng):三者是互相關(guān)聯(lián)的,在總線上有設(shè)備列表,和驅(qū)動(dòng)列表。當(dāng)一個(gè)設(shè)備接入時(shí),會(huì)在
總線上遍歷所有的驅(qū)動(dòng),知道找到支持他的驅(qū)動(dòng)。然后就會(huì)將設(shè)備結(jié)構(gòu)體下的driver指針指向該驅(qū)動(dòng)。
同樣,驅(qū)動(dòng)也會(huì)將該設(shè)備加入自己的設(shè)備指針列表。
3G網(wǎng)卡是一個(gè)USB設(shè)備,那么就介紹一下USB驅(qū)動(dòng)。
總線
Usb總線結(jié)構(gòu)體 struct bus_type usb_bus_type ={}; //那我們就來看看總線的結(jié)構(gòu)體

[include/linux/device.h]文件中

struct bus_type {
const char *name;
…...
struct bus_type_private *p;
};
[drivers/base/base.h]文件中
struct bus_type_private {
struct kset subsys;

struct kset *drivers_kset;
struct kset *devices_kset;
struct klist klist_devices;
struct klist klist_drivers;
struct blocking_notifier_head bus_notifier;
unsigned int drivers_autoprobe:1;
struct bus_type *bus;
};
其中的klist_devices, klist_drivers分別為總線上的設(shè)備和驅(qū)動(dòng)列表。當(dāng)有新的設(shè)備接入,或加載新的
驅(qū)動(dòng)時(shí)。就會(huì)在這兩個(gè)列表中遍歷。
設(shè)備
這里就以u(píng)sb_device為例
[include/linux/usb.h]文件中
struct usb_device {
…...
struct usb_bus *bus; //指向該設(shè)備的總線
…...
struce device dev; //linux下通用設(shè)備的屬性
};
[include/linux/device.h]文件中
struct device {
…...
struct device_driver *driver; /* which driver has allocated this device */
…...
};
這里就有設(shè)備指向的總線和驅(qū)動(dòng)指針了。一個(gè)設(shè)備之用一個(gè)驅(qū)動(dòng)。下面的驅(qū)動(dòng),所支持的設(shè)備就是個(gè)列
表了。驅(qū)動(dòng)可以支持一系列的設(shè)備。
驅(qū)動(dòng)
以opton_driver為例[drivers/usb/serial/option.c]
static struct usb_driver option_driver = {
.name = "option",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
#ifdef CONFIG_PM
.suspend = usb_serial_suspend,
.resume = usb_serial_resume,
.supports_autosuspend = 1,
#endif
.id_table = option_ids,
.no_dynamic_id = 1,
};
[include/linux/usb.h]文件中
struct usb_driver {
const char *name;
…...
struct usbdrv_wrap drvwrap;
…...
};
struct usbdrv_wrap {
struct device_driver driver;
int for_devices;
};
[include/linux/device.h]文件中
struct device_driver {
…...
struct bus_type *bus; //驅(qū)動(dòng)所屬的總線
…...
struct driver_private *p;
…...
};
[drivers/base/base.h]文件中
struct driver_private {
struct kobject kobj;
struct klist klist_devices; //正在使用此驅(qū)動(dòng)的設(shè)備列表
struct klist_node knode_bus;
struct module_kobject *mkobj;
struct device_driver *driver;
};
option驅(qū)動(dòng)總線賦值
[drivers/usb/serial/option.c]中option初始化時(shí),注冊(cè)過程會(huì)將驅(qū)動(dòng)所屬總線賦值
static int __init option_init(void)
{
retval = usb_register(&option_driver);
}
[include/linux/usb.h]中
static inline int usb_register(struct usb_driver *driver)
{
return usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME);
}
[drivers/usb/core/driver.c]文件中
int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
const char *mod_name)
{
new_driver->drvwrap.driver.bus = &usb_bus_type;
new_driver->drvwrap.driver.probe = usb_probe_interface;
}
圖例
以華為EM770W為例
以HUAWEI EM770W WCDMA 3G網(wǎng)卡為例。
在內(nèi)核文件linux/drivers/usb/serial/option.c中。
static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) },
}
有此行定義,在設(shè)備EM770W中讀取出的.idProduct與 HUAWEI_PRODUCT_E600定義的值相同。
當(dāng)一個(gè)USB設(shè)備插入時(shí),會(huì)觸發(fā)hub_event時(shí)間調(diào)用函數(shù)
一: 添加usb設(shè)備
hub_events(); -->hub_port_connect_change();
--> udev = usb_alloc_dev(hdev, hdev->bus, port1); //將&usb_bus_type分配給設(shè)備
usb_new_device(udev);
-->device_add(&udev->dev);(drivers/base/core.c)
-->bus_add_device(dev); //將設(shè)備加入總線設(shè)備列表
//klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices);
bus_probe_device(dev);
-->device_attach(dev);[drivers/base/dd.c]
-->bus_for_each_drv(dev->bus, NULL, dev, __device_attach); // 遍歷驅(qū)動(dòng),找到支持此設(shè)備的
驅(qū)動(dòng)
-->__device_attach(drv, dev); // 找的驅(qū)動(dòng)usb 支持此設(shè)備
-->driver_probe_device(drv, dev);
-->really_probe(dev, drv); [drivers/base/dd.c]
-->drv->probe(dev); // 實(shí)際調(diào)用 usb_probe_device(dev);[drivers/usb/core/driver.c]
-->udriver->probe(udev); //實(shí)際上調(diào)用的 generic_probe(udev); [drivers/usb/core/generic.c]
-->usb_set_configuration(udev, c); [drivers/usb/core/message.c]
-->nintf = cp->desc.bNumInterfaces; // 這里首先得到設(shè)備的Interface數(shù)量,下面循環(huán)添加每個(gè)
Interface
for (i = 0; i < nintf; ++i) {
ret = device_add(&intf->dev);
}
二: 添加interface
下面進(jìn)入每個(gè)interface的添加設(shè)備過程,在這里單獨(dú)列出
device_add(&intf->dev);
-->bus_probe_device(dev); -->device_attach(dev); [drivers/base/dd.c]
-->bus_for_each_drv(dev->bus, NULL, dev, __device_attach); // 遍歷驅(qū)動(dòng),找到支持此設(shè)備的
驅(qū)動(dòng)
-->__device_attach(drv, dev); // 遍歷到option驅(qū)動(dòng)時(shí),在option_ids[]結(jié)構(gòu)體中,找到該驅(qū)動(dòng)支
持此設(shè)備
-->driver_probe_device(drv, dev);
-->really_probe(dev, drv); [drivers/base/dd.c]
-->drv->probe(dev); //這里實(shí)際調(diào)用的函數(shù)為 usb_probe_interface(dev);
-->driver->probe(inif, id); //這里實(shí)際調(diào)用的函數(shù)為 usb_serial_probe(interface, id);
[drivers/usb/serial/usb-serial.c]
//這里檢測到使用pl2303 convertor, 并執(zhí)行pl2303的attach函數(shù)
/*****************
*下面這部分做了許多事情。
* 創(chuàng)建一個(gè)usb_serial數(shù)據(jù)結(jié)構(gòu),增加一個(gè)interface接口設(shè)備,找到該接口的驅(qū)動(dòng)(如pl2303),設(shè)置
interface的endpoint等
******************/
-->type = search_serial_device(interface); //這里找到匹配的pl2303驅(qū)動(dòng) 參看下一節(jié)【USB 檢
測pl2303驅(qū)動(dòng)】
serial = create_serial(dev, interface, type); //創(chuàng)建serial, 將type驅(qū)動(dòng)賦值給新創(chuàng)建的serial-
>type,即驅(qū)動(dòng)指向?yàn)閜l2303
port = serial->port[i];
dev_set_name(&port->dev, "ttyUSB%d", port->number);
device_add(&port->dev); //調(diào)用增加設(shè)備 ttyUSB0
-->bus_probe_device(dev);
-->...如上...
-->really_probe(dev, drv); [drivers/base/dd.c]
-->dev->bus->probe(dev); // ***** 這里實(shí)際上調(diào)用的就是usb_serial_device_probe(dev);
-->tty_register_device(usb_serial_tty_driver, minor, dev); //這里會(huì)再次調(diào)用 device_add(dev);
函數(shù)
USB 檢測pl2303驅(qū)動(dòng)
USB的串行設(shè)備也分為很多種類。如pl2303,ViVOpay
usb_serial_probe(interface, id);[drivers/usb/serial/usb-serial.c]
-->type = search_serial_device(interface); //根據(jù)提供的interface接口,
//獲得了 static struct usb_serial_driver pl2303_device ={} [drivers/usb/serial/pl2303.c]
-->list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
id = get_iface_id(drv, iface);
if (id)
return drv;
}
pl2303驅(qū)動(dòng)的注冊(cè)過程
static int __init pl2303_init(void)
{
retval = usb_serial_register(&pl2303_device);
}
[drivers/usb/serial/usb-serial.c] 在注冊(cè)函數(shù)中,將pl2303驅(qū)動(dòng)加入usb serial驅(qū)動(dòng)列表
int usb_serial_register(struct usb_serial_driver *driver)
{
list_add(&driver->driver_list, &usb_serial_driver_list);
}
三: 添加endpoint
// 至此,整個(gè)調(diào)用逐步返回!
最后在usb_set_configuration(udev, c); [drivers/usb/core/message.c] 函數(shù)返回時(shí)調(diào)用
-->create_intf_ep_devs(intf); //增加endpoint設(shè)備
-->for (i = 0; i < alt->desc.bNumEndpoints; ++i)
(void) usb_create_ep_devs(&intf->dev, &alt->endpoint[i], udev);
-->retval = device_register(&ep_dev->dev);
3G網(wǎng)卡如何讀寫呢
在pl2303驅(qū)動(dòng)加載完成后,生成的設(shè)備ttyUSB0, ttyUSB1, ttyUSB2后,即可以對(duì)這些設(shè)備進(jìn)行操
作。如open,close,read,write,ioctl等命令
pl2303.c中有如下函數(shù),即當(dāng)打開網(wǎng)卡設(shè)備時(shí),就會(huì)調(diào)用此函數(shù)。
static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port)
{
}
在板子的可使用3G WCDMA網(wǎng)卡上,因?yàn)殚_發(fā)板為3G網(wǎng)卡建立3個(gè)USB設(shè)備
ttyUSB0,ttyUSB1,ttyUSB2 所以在打開時(shí),會(huì)調(diào)用3次該函數(shù)。
大概流程為
static int serial_open(struct tty_struct *tty, struct file *filp)
-->tty_port_open(&port->port, tty, filp);
-->port->ops->activate(port, tty); //此處調(diào)用的為static int serial_activate(struct tty_port
*tport, struct tty_struct *tty)
-->port->serial->type->open(tty, port); //這里即是調(diào)用static int pl2303_open(struct
tty_struct *tty, struct usb_serial_port *port)
從而對(duì)將設(shè)備打開,可以對(duì)設(shè)備進(jìn)行讀寫,控制等操作。
設(shè)備識(shí)別
在設(shè)備插入后,以HUAWEI ET127 3G網(wǎng)卡為例。插入設(shè)備后會(huì)有如下的log
scsi 0:0:0:0: CD-ROM HUAWEI Mobile CMCC CD 1.25 PQ: 0 ANSI: 0
大唐的AirCard 901插入后,同樣會(huì)有l(wèi)og如下:
csi 1:0:0:0: CD-ROM AirCard SetupDisk 1.00 PQ: 0 ANSI: 2
這時(shí),友善開發(fā)板將此設(shè)備識(shí)別成為一個(gè)光盤,即儲(chǔ)存設(shè)備。這時(shí),如果在ubuntu下,可以使用
usb_modeswitch將usb設(shè)備進(jìn)行模式轉(zhuǎn)換。然后驅(qū)動(dòng)3G網(wǎng)卡。我在網(wǎng)上搜索到一篇文章。說可以驅(qū)
動(dòng)大部分3G網(wǎng)卡,就此我問過胡菲菲。此前驅(qū)動(dòng)大唐的AirCard 901用的就是此種方法。
http://:81/Linux/2011-03/33430.htm
我昨天嘗試按照這些步驟進(jìn)行實(shí)現(xiàn)。但是遇到兩個(gè)問題
1:arm 卡發(fā)板上使用的是busybox, 和一些應(yīng)用程序(如:dhcpcd)在Android系統(tǒng)下編譯。我編譯的
usb_modeswitch無法運(yùn)行
2:插入usb 3G設(shè)備后,arm開發(fā)板識(shí)別為sr0, sr1設(shè)備。不知道該如何將此設(shè)備退出?;蛟S
usb_modeswitch轉(zhuǎn)換完成后,即可以進(jìn)行AT命令通信。還需要進(jìn)行試驗(yàn)才能知道。
usb_modeswitch作用
USB_ModeSwitch 是控制"flip flop"(多重設(shè)備)USB裝置的模式轉(zhuǎn)換工具。作用有如下的幾種:
1. Usb 閃存模式:提取和安裝驅(qū)動(dòng)
2. 轉(zhuǎn)換模式:儲(chǔ)存設(shè)備模式轉(zhuǎn)換為所需(如3G)設(shè)備模式
3. 所需設(shè)備模式:使用設(shè)備新的功能
詳細(xì)的可以參看usb_modeswitch的README文檔。
一些術(shù)語
USB 端點(diǎn)(endpoint)
端點(diǎn)是由廠商在USB設(shè)備內(nèi)部建立的,因此是永久存在的。端點(diǎn)(endpoint)和主控制器(host
controller)基于管道(pipe)連接。
一個(gè)端點(diǎn)只能單向的(in/out)傳輸數(shù)據(jù)。
端點(diǎn)是以interface來分組的。每一個(gè)interface對(duì)應(yīng)著一個(gè)設(shè)備功能。
USB Interface
endpoint(端點(diǎn))是以interface來分組的。比如華為的WCDMA是以每三個(gè)ep為一組,隸屬于一個(gè)
interface。而且每一個(gè)interface對(duì)應(yīng)著一個(gè)單獨(dú)的設(shè)備功能。如華為ET127 TD-CDMA 3G網(wǎng)卡其
中一個(gè)interface設(shè)備命名為ttyUSB_utps_mms,對(duì)應(yīng)的功能應(yīng)該即為短信發(fā)送/接收。
USB設(shè)備號(hào)
//WCDMA 華為EM770W在ubuntu 10.04下查看
crw-rw---- 1 root dialout 188, 1 2011-05-04 16:19 ttyUSB_utps_diag
crw-rw---- 1 root dialout 188, 0 2011-05-04 16:19 ttyUSB_utps_modem
crw-rw---- 1 root dialout 188, 2 2011-05-04 16:21 ttyUSB_utps_pcui
//TD-SCDMA 華為ET127在ubuntu 10.04下查看
crw-rw---- 1 root dialout 166, 1 2011-05-04 16:23 ttyUSB_utps_mms
crw-rw---- 1 root dialout 166, 0 2011-05-04 16:23 ttyUSB_utps_modem
crw-rw---- 1 root dialout 166, 2 2011-05-04 16:23 ttyUSB_utps_pcui
idVendor=12d1, idProduct=1da1
大唐TD-SCDMA設(shè)備參數(shù)
idVendor=1ab7, idProduct=0301
主設(shè)備號(hào)含義
ACM調(diào)制解調(diào)器:主設(shè)備號(hào) 166
USB打印機(jī): 主設(shè)備號(hào) 180(次設(shè)備號(hào)0~15)
USB串口: 主設(shè)備號(hào) 188  

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    久久精视频免费视频观看| 国产传媒中文字幕东京热| 亚洲精品福利视频你懂的| 亚洲人妻av中文字幕| 91麻豆视频国产一区二区| 欧美日本亚欧在线观看| 亚洲中文字幕高清视频在线观看| 久久国产亚洲精品成人| 国产一区二区不卡在线视频| 最新国产欧美精品91| 成人日韩视频中文字幕| 91在线爽的少妇嗷嗷叫| 国产一级一片内射视频在线| 国产亚洲午夜高清国产拍精品| 国产内射一级一片内射高清| 91精品国产品国语在线不卡| 亚洲美女国产精品久久| 中文字幕亚洲人妻在线视频| 精品久久综合日本欧美| 亚洲中文字幕免费人妻| 欧美日韩校园春色激情偷拍| 中文字幕精品人妻一区| 99久久精品国产麻豆| 中文字字幕在线中文乱码二区| 日韩精品视频一二三区| 精品国产品国语在线不卡| 亚洲性日韩精品一区二区| 亚洲精品av少妇在线观看| 国产传媒欧美日韩成人精品| 激情视频在线视频在线视频| 丰满少妇高潮一区二区| 亚洲av熟女国产一区二区三区站| 色哟哟精品一区二区三区| 欧美日韩综合免费视频| 欧美一级内射一色桃子| 亚洲欧美日韩国产自拍| 东京热男人的天堂久久综合| 婷婷色网视频在线播放| 国内午夜精品视频在线观看| 国内九一激情白浆发布| 大屁股肥臀熟女一区二区视频 |