新聞中心
作為Linux開發(fā)人員,我們經(jīng)常會遇到需要處理二進(jìn)制數(shù)據(jù)的情況。在這些過程中,至關(guān)重要。本文將介紹這些東西,以及它們?nèi)绾卧贚inux中使用。

創(chuàng)新互聯(lián)一直在為企業(yè)提供服務(wù),多年的磨煉,使我們在創(chuàng)意設(shè)計,全網(wǎng)整合營銷推廣到技術(shù)研發(fā)擁有了開發(fā)經(jīng)驗。我們擅長傾聽企業(yè)需求,挖掘用戶對產(chǎn)品需求服務(wù)價值,為企業(yè)制作有用的創(chuàng)意設(shè)計體驗。核心團隊擁有超過十余年以上行業(yè)經(jīng)驗,涵蓋創(chuàng)意,策化,開發(fā)等專業(yè)領(lǐng)域,公司涉及領(lǐng)域有基礎(chǔ)互聯(lián)網(wǎng)服務(wù)服務(wù)器托管德陽、成都app開發(fā)、手機移動建站、網(wǎng)頁設(shè)計、網(wǎng)絡(luò)整合營銷。
u8和u32的定義
u8和u32是兩種不同的數(shù)據(jù)類型,在Linux內(nèi)核中使用。它們的名稱可能會有一點迷惑,因為它們實際上是無符號整數(shù)類型,而不是8位或32位整數(shù)類型。但是,在大多數(shù)系統(tǒng)中,u8的大小確實為8位,而u32的大小確實為32位。
u8和u32都是在stdint.h頭文件中定義的類型。u8的定義如下:
typedef __u8 uint8_t;
typedef unsigned char __u8;
u32的定義如下:
typedef __u32 uint32_t;
typedef unsigned int __u32;
值得注意的是,u8和u32的定義中,typedef關(guān)鍵字被使用。typedef的作用是為現(xiàn)有的數(shù)據(jù)類型創(chuàng)建一個別名。在這種情況下,它們分別為uint8_t和uint32_t。
u8和u32的用途
在Linux內(nèi)核開發(fā)中,u8和u32用于處理各種數(shù)據(jù)類型,包括網(wǎng)絡(luò)協(xié)議、文件系統(tǒng)和設(shè)備驅(qū)動程序等。
例如,在網(wǎng)絡(luò)協(xié)議中,ip.h頭文件中有這樣一個定義:
typedef u32 __be32;
這里的__be32表示網(wǎng)絡(luò)字節(jié)序中的32位整數(shù)。它實際上是一個u32類型,可以用于處理網(wǎng)絡(luò)字節(jié)序中的數(shù)據(jù)。
文件系統(tǒng)和設(shè)備驅(qū)動程序也使用u8和u32類型。在這些情況下,u8和u32通常用于表示不同的二進(jìn)制數(shù)據(jù)結(jié)構(gòu)。例如,在block.h頭文件中,有以下定義:
typedef unsigned short sector_t;
typedef struct {
sector_t start_sect;
unsigned int count;
} sector_t;
這里的sector_t是一個16位無符號整數(shù)類型。sectors_t結(jié)構(gòu)體中包含一個start_sect成員,它是一個sector_t類型,用于表示數(shù)據(jù)塊的起始部分。同時,count成員是一個unsigned int類型,用于表示數(shù)據(jù)塊的長度。
在Linux內(nèi)核中使用u8和u32
在Linux內(nèi)核中,對于u8和u32數(shù)據(jù)類型的操作,通常會使用一些宏和函數(shù)來實現(xiàn)。例如,對于u8類型,以下宏被定義:
#define __u8_to_user(ptr, x) (*(__u8 __user *)(ptr) = (x))
#define __u8_from_user(ptr) (*(__u8 __user *)(ptr))
這些宏用于將u8類型從用戶空間復(fù)制到內(nèi)核空間,或從內(nèi)核空間復(fù)制到用戶空間。將數(shù)據(jù)存儲到用戶區(qū)域時,使用“__u8_to_user”宏。反過來,將數(shù)據(jù)從用戶區(qū)域讀取到內(nèi)核區(qū)域時,使用“__u8_from_user”宏。
對于u32類型,也有類似的宏和函數(shù)。例如:
#define __le32_to_cpu(x) ((__u32)(__le32)(x))
#define __cpu_to_le32(x) ((__le32)(__u32)(x))
#define le32_to_cpu(x) ((__force __u32)(__le32)(x))
#define cpu_to_le32(x) ((__force __le32)(__u32)(x))
#define put_unaligned_le32(x,p) ((__u32 *)(p))[0] = __cpu_to_le32(x)
#define get_unaligned_le32(p) __le32_to_cpu(((const __le32 *)(p))[0])
這些宏和函數(shù)用于將u32類型從不同字節(jié)順序的數(shù)據(jù)格式復(fù)制到本機字節(jié)順序。例如,在網(wǎng)絡(luò)通信中,經(jīng)常需要將數(shù)據(jù)內(nèi)容從大端字節(jié)順序轉(zhuǎn)換為小端字節(jié)順序,或從小端字節(jié)順序轉(zhuǎn)換為大端字節(jié)順序。函數(shù)“__le32_to_cpu”和“__cpu_to_le32”可以用于完成這個處理。而“put_unaligned_le32”和“get_unaligned_le32”可以用于將u32類型原子性地存儲到內(nèi)存中,或者從內(nèi)存中讀取。
在Linux內(nèi)核開發(fā)中,處理二進(jìn)制數(shù)據(jù)是一項非常重要的任務(wù)。u8和u32是兩種用于處理二進(jìn)制數(shù)據(jù)的無符號整數(shù)類型。這些類型通常用于表示不同的二進(jìn)制數(shù)據(jù)結(jié)構(gòu),并且在網(wǎng)絡(luò)協(xié)議、文件系統(tǒng)和設(shè)備驅(qū)動程序中發(fā)揮重要作用。在Linux內(nèi)核中,為了操作這些數(shù)據(jù)類型,需要使用一些宏和函數(shù),從而使開發(fā)人員可以輕松地在內(nèi)核空間中處理二進(jìn)制數(shù)據(jù)。
成都網(wǎng)站建設(shè)公司-創(chuàng)新互聯(lián)為您提供網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)頁設(shè)計及定制高端網(wǎng)站建設(shè)服務(wù)!
怎樣寫linux下的USB設(shè)備驅(qū)動程序
Linux內(nèi)核提供了一個稱為USB core的子系統(tǒng)來處理了大部分USB設(shè)備的復(fù)雜工作,所以這里所描述的是驅(qū)動程序和USB core之間的接口。
在USB設(shè)備組織結(jié)構(gòu)中,從上到下分為設(shè)備(device)、知尺配置(config)、接口(interface)和端點(endpoint)四個層次。
對于裂猛返這四個層次的簡單描述如下:
1、設(shè)備通常具有一個或多個的配置
2、配置經(jīng)常具有一個或多個的接口
3、接口通常具有一個或多個的設(shè)置
4、接口沒有或具有一個以上的端點
設(shè)備
代表了一個插入的USB設(shè)備,在內(nèi)核使用數(shù)據(jù)結(jié)構(gòu) struct u_device來描述整個USB設(shè)備。(include/linux/u.h)
struct u_device {
肆饑 int devnum; //設(shè)備號,是在USB總線的地址
char devpath ; //用于消息的設(shè)備ID字符串
enum u_device_state state; //設(shè)備狀態(tài):已配置、未連接等等
enum u_device_speed speed; //設(shè)備速度:高速、全速、低速或錯誤
struct u_tt *tt; //處理傳輸者信息;用于低速、全速設(shè)備和高速HUB
int ttport; //位于tt HUB的設(shè)備口
unsigned int toggle; //每個端點的占一位,表明端點的方向( = IN, = OUT)
struct u_device *parent; //上一級HUB指針
struct u_bus *bus; //總線指針
struct u_host_endpoint ep0; //端點0數(shù)據(jù)
struct device dev; //一般的設(shè)備接口數(shù)據(jù)結(jié)構(gòu)
struct u_device_descriptor descriptor; //USB設(shè)備描述符
struct u_host_config *config; //設(shè)備的所有配置
struct u_host_config *actconfig; //被激活的設(shè)備配置
struct u_host_endpoint *ep_in; //輸入端點數(shù)組
struct u_host_endpoint *ep_out; //輸出端點數(shù)組
char **rawdescriptors; //每個配置的raw描述符
unsigned short bus_mA; //可使用的總線電流
u8 portnum;//父端口號
u8 level; //USB HUB的層數(shù)
unsigned can_submit:1; //URB可被提交標(biāo)志
unsigned discon_suspended:1; //暫停時斷開標(biāo)志
unsigned persist_enabled:1; //USB_PERSIST使能標(biāo)志
unsigned have_langid:1; //string_langid存在標(biāo)志
unsigned authorized:1;
unsigned authenticated:1;
unsigned wu:1; //無線USB標(biāo)志
int string_langid; //字符串語言ID
/* static strings from the device */ //設(shè)備的靜態(tài)字符串
char *product; //產(chǎn)品名
char *manufacturer; //廠商名
char *serial; //產(chǎn)品串號
struct list_head filelist; //此設(shè)備打開的ufs文件
#ifdef CONFIG_USB_DEVICE_CLASS
struct device *u_classdev; //用戶空間訪問的為ufs設(shè)備創(chuàng)建的USB類設(shè)備
#endif
#ifdef CONFIG_USB_DEVICEFS
struct dentry *ufs_dentry; //設(shè)備的ufs入口
#endif
int maxchild; //(若為HUB)接口數(shù)
struct u_device *children;//連接在這個HUB上的子設(shè)備
int pm_usage_cnt; //自動掛起的使用計數(shù)
u32 quirks;
atomic_t urbnum; //這個設(shè)備所提交的URB計數(shù)
unsigned long active_duration; //激活后使用計時
#ifdef CONFIG_PM //電源管理相關(guān)
struct delayed_work autosuspend; //自動掛起的延時
struct work_struct autoresume; //(中斷的)自動喚醒需求
struct mutex pm_mutex; //PM的互斥鎖
unsigned long last_busy; //最后使用的時間
int autosuspend_delay;
unsigned long connect_time; //之一次連接的時間
unsigned auto_pm:1; //自動掛起/喚醒
unsigned do_remote_wakeup:1; //遠(yuǎn)程喚醒
unsigned reset_resume:1; //使用復(fù)位替代喚醒
unsigned autosuspend_disabled:1; //掛起關(guān)閉
unsigned autoresume_disabled:1; //喚醒關(guān)閉
unsigned skip_sys_resume:1; //跳過下個系統(tǒng)喚醒
#endif
struct wu_dev *wu_dev; //(如果為無線USB)連接到WUSB特定的數(shù)據(jù)結(jié)構(gòu)
};
配置
一個USB設(shè)備可以有多個配置,并可在它們之間轉(zhuǎn)換以改變設(shè)備的狀態(tài)。比如一個設(shè)備可以通過下載固件(firmware)的方式改變設(shè)備的使用狀態(tài)(我感覺類似FPGA或CPLD),那么USB設(shè)備就要切換配置,來完成這個工作。一個時刻只能有一個配置可以被激活。Linux使用結(jié)構(gòu) struct u_host_config 來描述USB配置。我們編寫的USB設(shè)備驅(qū)動通常不需要讀寫這些結(jié)構(gòu)的任何值??稍趦?nèi)核源碼的文件include/linux/u.h中找到對它們的描述。
struct u_host_config {
struct u_config_descriptor desc; //配置描述符
char *string; /* 配置的字符串指針(如果存在) */
struct u_interface_assoc_descriptor *intf_assoc; //配置的接口聯(lián)合描述符鏈表
struct u_interface *interface; //接口描述符鏈表
struct u_interface_cache *intf_cache;
unsigned char *extra; /* 額外的描述符 */
int extralen;
};
接口
USB端點被綁為接口,USB接口只處理一種USB邏輯連接。一個USB接口代表一個基本功能,每個USB驅(qū)動控制一個接口。所以一個物理上的硬件設(shè)備可能需要一個以上的驅(qū)動程序。這可以在“暈到死 差屁”系統(tǒng)中看出,有時插入一個USB設(shè)備后,系統(tǒng)會識別出多個設(shè)備,并安裝相應(yīng)多個的驅(qū)動。
USB 接口可以有其他的設(shè)置,它是對接口參數(shù)的不同選擇. 接口的初始化的狀態(tài)是之一個設(shè)置,編號為0。 其他的設(shè)置可以以不同方式控制獨立的端點。
USB接口在內(nèi)核中使用 struct u_interface 來描述。USB 核心將其傳遞給USB驅(qū)動,并由USB驅(qū)動負(fù)責(zé)后續(xù)的控制。
struct u_interface {
struct u_host_interface *altsetting; /* 包含所有可用于該接口的可選設(shè)置的接口結(jié)構(gòu)數(shù)組。每個 struct u_host_interface 包含一套端點配置(即struct u_host_endpoint結(jié)構(gòu)所定義的端點配置。這些接口結(jié)構(gòu)沒有特別的順序。*/
struct u_host_interface *cur_altsetting; /* 指向altsetting內(nèi)部的指針,表示當(dāng)前激活的接口配置*/
unsigned num_altsetting; /* 可選設(shè)置的數(shù)量*/
/* If there is an interface association descriptor then it will list the associated interfaces */
struct u_interface_assoc_descriptor *intf_assoc;
int minor; /* 如果綁定到這個接口的 USB 驅(qū)動使用 USB 主設(shè)備號, 這個變量包含由 USB 核心分配給接口的次設(shè)備號. 這只在一個成功的調(diào)用 u_register_dev后才有效。*/
/*以下的數(shù)據(jù)在我們寫的驅(qū)動中基本不用考慮,系統(tǒng)會自動設(shè)置*/
enum u_interface_condition condition; /* state of binding */
unsigned is_active:1; /* the interface is not suspended */
unsigned sysfs_files_created:1; /* the sysfs attributes exist */
unsigned ep_devs_created:1; /* endpoint “devices” exist */
unsigned unregistering:1; /* unregistration is in progress */
unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */
unsigned needs_altsetting0:1; /* switch to altsetting 0 is pending */
unsigned needs_binding:1; /* needs delayed unbind/rebind */
unsigned reset_running:1;
struct device dev; /* 接口特定的設(shè)備信息 */
struct device *u_dev;
int pm_usage_cnt; /* usage counter for autosuspend */
struct work_struct reset_ws; /* for resets in atomic context */
};
struct u_host_interface {
struct u_interface_descriptor desc; //接口描述符
struct u_host_endpoint *endpoint; /* 這個接口的所有端點結(jié)構(gòu)體的聯(lián)合數(shù)組*/
char *string; /* 接口描述字符串 */
unsigned char *extra; /* 額外的描述符 */
int extralen;
};
端點
USB 通訊的最基本形式是通過一個稱為端點的東西。一個USB端點只能向一個方向傳輸數(shù)據(jù)(從主機到設(shè)備(稱為輸出端點)或者從設(shè)備到主機(稱為輸入端點))
端點在內(nèi)核中使用結(jié)構(gòu) struct u_host_endpoint 來描述,它所包含的真實端點信息在另一個結(jié)構(gòu)中:struct u_endpoint_descriptor(端點描述符,包含所有的USB特定數(shù)據(jù))。
struct u_host_endpoint {
struct u_endpoint_descriptor desc; //端點描述符
struct list_head urb_list; //此端點的URB對列,由USB核心維護
void *hcpriv;
struct ep_device *ep_dev; /* For sysfs info */
unsigned char *extra; /* Extra descriptors */
int extralen;
int enabled;
};
/*—*/
/* USB_DT_ENDPOINT: Endpoint descriptor */
struct u_endpoint_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bEndpointAddress; /*這個特定端點的 USB 地址,這個8位數(shù)據(jù)包含端點的方向,結(jié)合位掩碼 USB_DIR_OUT 和 USB_DIR_IN 使用, 確定這個端點的數(shù)據(jù)方向。*/
__u8 bmAttributes; //這是端點的類型,位掩碼如下
__le16 wMaxPacketSize; /*端點可以一次處理的更大字節(jié)數(shù)。驅(qū)動可以發(fā)送比這個值大的數(shù)據(jù)量到端點, 但是當(dāng)真正傳送到設(shè)備時,數(shù)據(jù)會被分為 wMaxPakcetSize 大小的塊。對于高速設(shè)備, 通過使用高位部分幾個額外位,可用來支持端點的高帶寬模式。*/
__u8 bInterval; //如果端點是中斷類型,該值是端點的間隔設(shè)置,即端點的中斷請求間的間隔時間,以毫秒為單位
/* NOTE: these two are _only_ in audio endpoints. */
/* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
__u8 bRefresh;
__u8 bSynchAddress;
} __attribute__ ((packed));
#define USB_DT_ENDPOINT_SIZE 7
#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
/*
* Endpoints
*/
#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress 端點的 USB 地址掩碼 */
#define USB_ENDPOINT_DIR_MASK 0x80 /* in bEndpointAddress 數(shù)據(jù)方向掩碼 */
#define USB_DIR_OUT 0 /* to device */
#define USB_DIR_IN 0x80 /* to host */
#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* bmAttributes 的位掩碼*/
#define USB_ENDPOINT_XFER_CONTROL 0
#define USB_ENDPOINT_XFER_ISOC 1
#define USB_ENDPOINT_XFER_BULK 2
#define USB_ENDPOINT_XFER_INT 3
#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80
/*—*/
寫一個USB的驅(qū)動程序最 基本的要做四件事:驅(qū)動程序要支持的設(shè)備、注冊USB驅(qū)動程序、探測和斷開、提交和控制urb(USB請求塊)
驅(qū)動程序支持的設(shè)備:有一個結(jié)構(gòu)體struct u_device_id,這個結(jié)構(gòu)體提供了一列不同類型的該驅(qū)動程序支持的USB設(shè)備,對于一個只控制一個特定的USB設(shè)備的驅(qū)動程序來說,struct u_device_id表被定義為:
/* 驅(qū)動程序支持的設(shè)備列表 */
static struct u_device_id skel_table = {
{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
{ } /* 終止入口 */
};
MODULE_DEVICE_TABLE (u, skel_table);
對 于PC驅(qū)動程序,MODULE_DEVICE_TABLE是必需的,而且u必需為該宏的之一個值,而USB_SKEL_VENDOR_ID和 USB_SKEL_PRODUCT_ID就是這渣碧個特殊設(shè)備的制造商和產(chǎn)品的ID了,我們在程序中把定義的值改為我們這款USB的,如:
/* 定義制造商和產(chǎn)品的ID號 */
#define USB_SKEL_VENDOR_ID 0x1234
#define USB_SKEL_PRODUCT_ID 0x2345
這兩個值可以通過命令lsu,當(dāng)然你得先把USB設(shè)備先插到主機上了?;蛘卟榭磸S商的USB設(shè)備的手冊也能得到,在我機器上運行l(wèi)su是這樣的結(jié)果:
Bus 004 Device 001: ID 0000:0000
Bus 003 Device 002: ID 1234:2345 Abc Corp.
Bus 002 Device 001: ID 0000:0000
Bus 001 Device 001: ID 0000:0000
得到這兩個值后把它定義到程序里就可以了。
注冊USB驅(qū)動程序:所 有的USB驅(qū)動程序都必須創(chuàng)建的結(jié)構(gòu)體是struct u_driver。這個結(jié)構(gòu)體必須由USB驅(qū)動程序來填寫,包括許多回調(diào)函數(shù)和變量,它們向USB核心代碼描述USB驅(qū)動程序。創(chuàng)建一個有效的 struct u_driver結(jié)構(gòu)體,只須要初始化五個字段就可以了,在框架程序中是這樣的:
static struct u_driver skel_driver = {
.owner = THIS_MODULE,
.name =”skeleton”,
.probe = skel_probe,
.disconnect = skel_disconnect,
.id_table = skel_table,
};
探測和斷開:當(dāng) 一個設(shè)備被安裝而USB核心認(rèn)為該驅(qū)動程序應(yīng)該處理時,探測函數(shù)被調(diào)用,探測函數(shù)檢查傳遞給它的設(shè)備信息,確定驅(qū)動程序是否真的適合該設(shè)備。當(dāng)驅(qū)動程序因 為某種原因不應(yīng)該控制設(shè)備時,斷開函數(shù)被調(diào)用,它可以做一些清理工作。探測回調(diào)函數(shù)中,USB驅(qū)動程序初始化任何可能用于控制USB設(shè)備的局部結(jié)構(gòu)體,它 還把所需的啟梁仿任何設(shè)備相關(guān)信息保存到一個局部結(jié)構(gòu)體中悄纖,
提交和控制urb:當(dāng)驅(qū)動程序有數(shù)據(jù)要發(fā)送到USB設(shè)備時(大多數(shù)情況是在驅(qū)動程序的寫函數(shù)中),要分配一個urb來把數(shù)據(jù)傳輸給設(shè)備:
/* 創(chuàng)建一個urb,并且給它分配一個緩存*/
urb = u_alloc_urb(0, GFP_KERNEL);
if (!urb) {
retval = -ENOMEM;
goto error;
}
當(dāng)urb被成功分配后,還要創(chuàng)建一個DMA緩沖區(qū)來以高效的方式發(fā)送數(shù)據(jù)到設(shè)備,傳遞給驅(qū)動程序的數(shù)據(jù)要復(fù)制到這塊緩沖中去:
buf = u_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);
if (!buf) {
retval = -ENOMEM;
goto error;
}
if (copy_from_user(buf, user_buffer, count)) {
retval = -EFAULT;
goto error;
}
當(dāng)數(shù)據(jù)從用戶空間正確復(fù)制到局部緩沖區(qū)后,urb必須在可以被提交給USB核心之前被正確初始化:
/* 初始化urb */
u_fill_bulk_urb(urb, dev->udev,
u_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
buf, count, skel_write_bulk_callback, dev);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
然后urb就可以被提交給USB核心以傳輸?shù)皆O(shè)備了:
/* 把數(shù)據(jù)從批量OUT端口發(fā)出 */
retval = u_submit_urb(urb, GFP_KERNEL);
if (retval) {
err(“%s – failed submitting write urb, error %d”, __FUNCTION__, retval);
goto error;
}
當(dāng)urb被成功傳輸?shù)経SB設(shè)備之后,urb回調(diào)函數(shù)將被USB核心調(diào)用,在我們的例子中,我們初始化urb,使它指向skel_write_bulk_callback函數(shù),以下就是該函數(shù):
static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
{
struct u_skel *dev;
dev = (struct u_skel *)urb->context;
if (urb->status &&
!(urb->status == -ENOENT ||
urb->status == -ECONNRESET ||
urb->status == -ESHUTDOWN)) {
dbg(“%s – nonzero write bulk status received: %d”,
__FUNCTION__, urb->status);
}
/* 釋放已分配的緩沖區(qū) */
u_buffer_free(urb->dev, urb->transfer_buffer_length,
urb->transfer_buffer, urb->transfer_dma);
}
有時候USB驅(qū)動程序只是要發(fā)送或者接收一些簡單的數(shù)據(jù),驅(qū)動程序也可以不用urb來進(jìn)行數(shù)據(jù)的傳輸,這是里涉及到兩個簡單的接口函數(shù):u_bulk_msg和u_control_msg ,在這個USB框架程序里讀操作就是這樣的一個應(yīng)用:
/* 進(jìn)行阻塞的批量讀以從設(shè)備獲取數(shù)據(jù) */
retval = u_bulk_msg(dev->udev,
u_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
dev->bulk_in_buffer,
min(dev->bulk_in_size, count),
&count, HZ*10);
/*如果讀成功,復(fù)制到用戶空間 */
if (!retval) {
if (copy_to_user(buffer, dev->bulk_in_buffer, count))
retval = -EFAULT;
else
retval = count;
}
u_bulk_msg接口函數(shù)的定義如下:
int u_bulk_msg(struct u_device *u_dev,unsigned int pipe,
void *data,int len,int *actual_length,int timeout);
其參數(shù)為:
struct u_device *u_dev:指向批量消息所發(fā)送的目標(biāo)USB設(shè)備指針。
unsigned int pipe:批量消息所發(fā)送目標(biāo)USB設(shè)備的特定端點,此值是調(diào)用u_sndbulkpipe或者u_rcvbulkpipe來創(chuàng)建的。
void *data:如果是一個OUT端點,它是指向即將發(fā)送到設(shè)備的數(shù)據(jù)的指針。如果是IN端點,它是指向從設(shè)備讀取的數(shù)據(jù)應(yīng)該存放的位置的指針。
int len:data參數(shù)所指緩沖區(qū)的大小。
int *actual_length:指向保存實際傳輸字節(jié)數(shù)的位置的指針,至于是傳輸?shù)皆O(shè)備還是從設(shè)備接收取決于端點的方向。
int timeout:以Jiffies為單位的等待的超時時間,如果該值為0,該函數(shù)一直等待消息的結(jié)束。
如果該接口函數(shù)調(diào)用成功,返回值為0,否則返回一個負(fù)的錯誤值。
u_control_msg接口函數(shù)定義如下:
int u_control_msg(struct u_device *dev,unsigned int pipe,__u8 request,__u8requesttype,__u16 value,__u16 index,void *data,__u16 size,int timeout)
除了允許驅(qū)動程序發(fā)送和接收USB控制消息之外,u_control_msg函數(shù)的運作和u_bulk_msg函數(shù)類似,其參數(shù)和u_bulk_msg的參數(shù)有幾個重要區(qū)別:
struct u_device *dev:指向控制消息所發(fā)送的目標(biāo)USB設(shè)備的指針。
unsigned int pipe:控制消息所發(fā)送的目標(biāo)USB設(shè)備的特定端點,該值是調(diào)用u_sndctrlpipe或u_rcvctrlpipe來創(chuàng)建的。
__u8 request:控制消息的USB請求值。
__u8 requesttype:控制消息的USB請求類型值。
__u16 value:控制消息的USB消息值。
__u16 index:控制消息的USB消息索引值。
void *data:如果是一個OUT端點,它是指身即將發(fā)送到設(shè)備的數(shù)據(jù)的指針。如果是一個IN端點,它是指向從設(shè)備讀取的數(shù)據(jù)應(yīng)該存放的位置的指針。
__u16 size:data參數(shù)所指緩沖區(qū)的大小。
int timeout:以Jiffies為單位的應(yīng)該等待的超時時間,如果為0,該函數(shù)將一直等待消息結(jié)束。
如果該接口函數(shù)調(diào)用成功,返回傳輸?shù)皆O(shè)備或者從設(shè)備讀取的字節(jié)數(shù);如果不成功它返回一個負(fù)的錯誤值。
這兩個接口函數(shù)都不能在一個中斷上下文中或者持有自旋鎖的情況下調(diào)用,同樣,該函數(shù)也不能被任何其它函數(shù)取消,使用時要謹(jǐn)慎。
我們要給未知的USB設(shè)備寫驅(qū)動程序,只需要把這個框架程序稍做修改就可以用了,前面我們已經(jīng)說過要修改制造商和產(chǎn)品的ID號,把0xfff0這兩個值改為未知USB的ID號。
#define USB_SKEL_VENDOR_IDxfff0
#define USB_SKEL_PRODUCT_ID 0xfff0
還 有就是在探測函數(shù)中把需要探測的接口端點類型寫好,在這個框架程序中只探測了批量(USB_ENDPOINT_XFER_BULK)IN和OUT端點,可 以在此處使用掩碼(USB_ENDPOINT_XFERTYPE_MASK)讓其探測其它的端點類型,驅(qū)動程序會對USB設(shè)備的每一個接口進(jìn)行一次探測, 當(dāng)探測成功后,驅(qū)動程序就被綁定到這個接口上。再有就是urb的初始化問題,如果你只寫簡單的USB驅(qū)動,這塊不用多加考慮,框架程序里的東西已經(jīng)夠用 了,這里我們簡單介紹三個初始化urb的輔助函數(shù):
u_fill_int_urb :它的函數(shù)原型是這樣的:
void u_fill_int_urb(struct urb *urb,struct u_device *dev,
unsigned int pipe,void *transfer_buff,
int buffer_length,u_complete_t complete,
void *context,int interval);
這個函數(shù)用來正確的初始化即將被發(fā)送到USB設(shè)備的中斷端點的urb。
u_fill_bulk_urb :它的函數(shù)原型是這樣的:
void u_fill_bulk_urb(struct urb *urb,struct u_device *dev,
unsigned int pipe,void *transfer_buffer,
int buffer_length,u_complete_t complete)
這個函數(shù)是用來正確的初始化批量urb端點的。
u_fill_control_urb :它的函數(shù)原型是這樣的:
void u_fill_control_urb(struct urb *urb,struct u_device *dev,unsigned int pipe,unsigned char *setup_packet,void *transfer_buffer,int buffer_length,u_complete_t complete,void *context);
這個函數(shù)是用來正確初始化控制urb端點的。
C語言“u8 *“什么類型?
u8 是 unsigned char
u16 是 unsigned short
u32 是 unsigned int
u8 * 就缺叢敬表示指向unsigned char(無符號字符類型)的伏慎指針,鄭陪屬于指針類型。
“u8*”是使用typedef或者define重好物新定義過的,
一般代表unsigned char* ,指向無符號字符灶羨數(shù)據(jù)類型隱襪拍的指針
u8 * :指向unsigned char(無符號字符類型)的指針
unsigned char,字符型,占1個字節(jié)
linux u8 u32 定義的介紹就聊到這里吧,感謝你花時間閱讀本站內(nèi)容,更多關(guān)于linux u8 u32 定義,了解Linux中u8和u32的定義和用途,怎樣寫linux下的USB設(shè)備驅(qū)動程序,C語言“u8 *“什么類型?的信息別忘了在本站進(jìn)行查找喔。
香港云服務(wù)器機房,創(chuàng)新互聯(lián)(www.cdcxhl.com)專業(yè)云服務(wù)器廠商,回大陸優(yōu)化帶寬,安全/穩(wěn)定/低延遲.創(chuàng)新互聯(lián)助力企業(yè)出海業(yè)務(wù),提供一站式解決方案。香港服務(wù)器-免備案低延遲-雙向CN2+BGP極速互訪!
網(wǎng)站欄目:了解Linux中u8和u32的定義和用途(linuxu8u32定義)
網(wǎng)站鏈接:http://m.fisionsoft.com.cn/article/cdcjgpe.html


咨詢
建站咨詢
