LINUX-USB 啟動 移除 流程




USB 啟動 移除 流程

0.先告訴usb core 驅動程式有支援有哪些裝置


如下 id table

/* table of devices that work with this driver */
static struct usb_device_id skel_table [] = {
{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
{ }
/* Terminating entry */
};

你必須使用下列巨集讓 user-space能判別驅動程式所支援的裝置
對於usb裝置而言,巨集的第一個參數需為'usb' 字串

MODULE_DEVICE_TABLE (usb, skel_table);


usb core 利用這個結構去得知驅動程式所支援的裝置id
此結構定義在
include/linux/mod_devicetable.h


1.掛載 modprobe

ex:
modprobe skel size=vga fps=30 power_save=0 compression=0 trace=0xff dev_hint=0
後面接的是要傳給 初始函式的參數

上面範例 將會呼叫 usb_skel_init 函式去註冊usb裝置


所有 USB 驅動程式必須建立的主要架構是 struct usb_driver. 這個結構必須被 USB 驅動程式填充並且包含多個函數作業方法和變數, 來向 USB core程式碼描述 USB 驅動程式:

為建立一個值 struct usb_driver 架構, 只有 5 個成員需要被初始化:


static struct usb_driver skel_driver = {
.owner = THIS_MODULE,
.name = "skeleton",
.id_table = skel_table,
.probe = skel_probe,
.disconnect = skel_disconnect,
};


為註冊 struct usb_driver 到 USB core, 一個呼叫 usb_register_driver 帶一個指向 struct usb_driver 的指標. 傳統上在 USB 驅動程式的模組初始化程式碼:

static int __init usb_skel_init(void)
{
int result; /* register this driver with the USB subsystem */
result = usb_register( skel_driver);
if (result)
err("usb_register failed. Error number %d", result);
return result;
}


2. 插入USB 偵測裝置

當使用者安插新的usb裝置時呼叫 .probe 作業方法
如下

static int usb_skel_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
1.檢查新裝置是否支援
2.初始化任何管理USB裝置所需的任何私有結構
3.將裝置相關訊息存入私有結構 usb_set_intfdata(interface, dev);
4.向usb core 註冊一個裝置 usb_register_dev(interface, &skel_class);
}


/* save our data pointer in this interface device */  

usb_set_intfdata(interface, dev);

這個函數接受一個指向任何數據類型的指標, 並且儲存它到 struct usb_interface 架構為後面的存取

usb_register_dev 函數要求一個指向 struct usb_interface 的指標和指向 struct usb_class_driver 的指標.

struct usb_class_driver 用來定義許多不同的參數, 當註冊一個次編號USB 驅動程式要 USB core知道這些參數.
這個結構包括下列變數:.

struct usb_class_driver {
char *name;
const struct file_operations *fops;
int minor_base;
};


若為特殊裝置 如video 則用 video_register_device


static struct file_operations skel_fops = {
.owner = THIS_MODULE,
.open = skel_video_open,
.release = skel_video_close,
.read = skel_video_read,
.poll = skel_video_poll,
.mmap = skel_video_mmap,
.ioctl = skel_video_ioctl,
.llseek = no_llseek,
};

static struct video_device skel_template = {
.owner = THIS_MODULE,
.name = " Webcam", /* Filled in later */
.type = VID_TYPE_CAPTURE,
.hardware = VID_HARDWARE_skel,
.release = video_device_release,
.fops = &skel_fops,
.minor = -1,
};

i = video_register_device(skel_template, VFL_TYPE_GRABBER, video_nr);


 


3.開啟AP


EX:
xawtv -geometry 320x240


open
static int skel_video_open(struct inode *inode, struct file *file)
{

1.初始目標裝置 暫存器

2.配置記憶體與參數

3.配置urb
struct urb *usb_alloc_urb(int iso_packets, int mem_flags);

唯一可產生 urb 的函式
輸入參數 第一個 iso_packets 為 iso封包數 ,若你建立的不是iso 的傳輸 則設為0
......................二個 mem_flags 與用來配置核心記憶體 kmalloc() 函式的旗標是相同的

4.初始urb 剛建好的urb 必須先初始好才能給 usb core 使用
usb_fill_int_urb ()
usb_fill_bulk_urb
usb_fill_control_urb

iso urb 需自行初始

5.提交urb - 當提交給 usb core 後就不應該存取 urb 的任何欄位 直到完工函式被呼叫為止
usb_submit_urb

}








iso urb 初始範例

urb->dev = dev;  

urb->context = uvd;

urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp-1);

urb->interval = 1;

urb->transfer_flags = URB_ISO_ASAP;

urb->transfer_buffer = cam->sts_buf[i];

urb->complete = konicawc_isoc_irq;

urb->number_of_packets = FRAMES_PER_DESC;

urb->transfer_buffer_length = FRAMES_PER_DESC;

for (j=0; j < FRAMES_PER_DESC; j++)

{

urb->iso_frame_desc[j].offset = j;

urb->iso_frame_desc[j].length = 1;

}




完工函式 complete
如果對 usb_submit_urb 的呼叫成功, 傳遞對 urb 的控制給 USB core, 這個函數返回 0; 否則, 一個負錯誤值被返回. 如果函數成功, urb 的完成處理者(如同被完成函數指標指定的)被確切地呼叫一次, 當 urb 被完成. 立即呼叫urb 內的 complete 指標所指向完工函式並獲得urb 的控制權


 


4.關閉AP


.release = close

static int skel_video_close(struct inode *inode, struct file *file)

當驅動程式需要撤銷以提交給 usb core 的 urb 時 可用 下列兩個之一


int usb_kill_urb(struct urb *urb);
int usb_unlink_urb(struct urb *urb);


 


5.斷開USB

當usb core認為驅動程式以不再需要控制目標裝置時 會呼叫 disconnect 去執行一些收尾的動作
如下

static void usb_skel_disconnect(struct usb_interface *intf)
{
1.取回之前呼叫 usb_set_intfdata 所設定的數據
2.設定數據指標在 struct us_interface 架構為 NULL 來阻止在不正確存取
3.遞減使用次數


}


 


6.卸載模組

ex:
modprobe -r skel

如上指令
卸載usb驅動程式必須使用 usb_deregister() 向核心註銷 struct usb_driver

呼叫
static void __exit usb_skel_exit(void)
{
/* deregister this driver with the USB subsystem */
usb_deregister( skel_driver);
}


立你斯 發表在 痞客邦 留言(0) 人氣()