1. 程式人生 > >USB驅動程式之滑鼠用做鍵盤

USB驅動程式之滑鼠用做鍵盤

我們還是接著來看看我們的例子程式 usbmouse.c

這裡它接著判斷了他是不是滑鼠,

得到它的usb_host_interface,interface=intf->cur_alsetting就是當前介面的設定


這裡有個介面描述符,我們來看看介面描述符


介面描述符裡面有個__u8  bNumEndpoints端點的個數

這個端點的個數是除了端點0之外還有多少個端點


這裡首先判斷如果除了端點0之外,端點個數不是1的話就返回錯誤,不是我能夠支援的裝置

如果只有一個端點,那就把這個端點放到endpoint這個數組裡面,這個並不是端點0,而是除了端點0之外第一個端點

得到一個端點描述符

if(!usb_endpoint_is_int_in(endpoint))這個是指如果他不是中斷類似的端點,不是輸入端點,注意了我們這裡輸入輸出是站在主機的角度說的,站在主機角度,我們的滑鼠是輸入裝置,資料是輸入給主機的。如果不是輸入型別端點,中斷型別端點,就返回一個錯誤。這個怎麼回事呢,怎麼知道你是不是中斷輸入端點呢,端點描述符裡面不是有個屬性嗎,屬性裡面就是表示它是什麼型別的,方向。

我們在我們自己的程式裡就不做判斷了,我們回到我們的主題,我們就認為就是一個滑鼠,

我們硬體相關的操作要用到USB匯流排驅動程式裡面的讀寫函式

我們只需要記住資料傳輸3要素,把這個三要素找出就可以實現這一點

1.源   在我們這裡是USB裝置的某個端點


這個就是源

我們來看看usb_rcvintpipe這個巨集


這個源是個整數,pipe_interrupt是指中斷型別端點,USB_DIR_IN是端點的方向。我們進入__create_pipe(dev,endpoint)這個巨集


devnum是裝置的地址,endpoint是端點的地址也是端點編號

2.目的

我們從USB裝置裡面讀資料,讀到哪裡去,肯定讀到緩衝區,但這個緩衝區肯定不能用kmallioc函式,

用這函式

返回一個void* 是個虛擬地址

最後一個引數是指的實體地址

3.長度就是我們的端點描述符最大包大小

使用我們三要素

怎麼用呢,看一下我們的例子


分配一個urb urb是什麼意思呢,就是USB請求快的意思 usb request block

然後使用這個3要素設定我們的urb  來看我們的例子程式


看看這個函式原型


第一個引數是urb,第二個引數是裝置,第三個引數是源,第四個引數是目的,第五個引數是長度 ,第6個引數是完成函式,第7個引數是給那個完成函式用的,我們不需要,第8個引數是查詢的頻率。

我們前面說過usb裝置不能打斷主機控制器,只能讓主機控制器查詢,不斷的去查詢,等有資料之後才能中斷CPU。當它得到資料之後,匯流排驅動程式就會呼叫這個complete_fn這個函式,查詢多頻繁呢就是int interval 。

端點描述符裡面有個binterval就是的


我們USB主機控制器,得到資料之後是往某個地方寫,但是我們主機控制器沒那麼聰明,所以我們要告訴它,例子裡面


第一句就是告訴實體地址,下面一句是設定某些標記

我們構造了URB 就要使用urb

怎麼使用urb


使用usb_submit_urb提交urb

usb滑鼠資料含義

我們前面說框架的時候說過,USB裝置驅動程式知道資料的含義,USB匯流排驅動程式提供識別裝置,給裝置找到驅動,提供讀寫函式,但是不知道資料的含義。這些資料需要由裝置驅動程式來解析,

data[0] bit 0表示左鍵,1表示按下,0表示鬆開

     bit 1表示右鍵,1表示按下,0表示鬆開

     bit  2表示中鍵    1表示按下,0表示鬆開

程式碼如下

#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb/input.h>
#include <linux/hid.h>


static struct input_dev *usb_key;
static char * usb_buf;
static dma_addr_t usb_buf_phys;
static int len;
static struct urb *uk_urb;
static struct usb_device_id usbmouse_as_key_id_table[] = {
{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,USB_INTERFACE_PROTOCOL_MOUSE) },
{ }/* Terminating entry */
};


static void usbmouse_as_key_irq(struct urb *urb)
{
static unsigned char pre_val;
/* USB滑鼠資料含義
* data[0]: bit0-左鍵, 1-按下, 0-鬆開
*          bit1-右鍵, 1-按下, 0-鬆開
*          bit2-中鍵, 1-按下, 0-鬆開 
*/
if((pre_val & (1<<0)) != (usb_buf[0] & (1<<0)))
{
//左鍵發生了變化
input_event(usb_key, EV_KEY, KEY_L, (usb_buf[0] & (1<<0)) ? 1 : 0);
input_sync(usb_key);
}
if ((pre_val & (1<<1)) != (usb_buf[0] & (1<<1)))
{
/* 右鍵發生了變化 */
input_event(usb_key, EV_KEY, KEY_S, (usb_buf[0] & (1<<1)) ? 1 : 0);
input_sync(usb_key);
}
if ((pre_val & (1<<2)) != (usb_buf[0] & (1<<2)))
{
/* 中鍵發生了變化 */
input_event(usb_key, EV_KEY, KEY_ENTER, (usb_buf[0]  & (1<<2)) ? 1 : 0);
input_sync(usb_key);
}

pre_val = usb_buf[0];


/* 重新提交urb */
usb_submit_urb(uk_urb, GFP_KERNEL);
}


static int usbmouse_as_key_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
int pipe;//源


interface = intf->cur_altsetting;


endpoint = &interface->endpoint[0].desc;
/*a.分配一個input_device結構體*/
usb_key=input_allocate_device();
/*b.設定*/
/*b.1能產生哪類事件*/
//能夠產生按鍵類事件
set_bit(EV_KEY,usb_key->evbit);
set_bit(EV_REP,usb_key->evbit);//能夠產生重複類事件,就是隻我們按下一個字母不動就會不斷的打印出來


/*b.2能產生這類事件的哪些事件*/
set_bit(KEY_L,usb_key->keybit);
set_bit(KEY_S,usb_key->keybit);
set_bit(KEY_ENTER,usb_key->keybit);


/*c.註冊*/
input_register_device(usb_key);
/*d.硬體相關的操作*/
/*資料傳輸3要素 源,目的,長度*/
/*1.源 :USB裝置的某個端點*/
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);


//長度 等於端點描述符的最大包大小
len=endpoint->wMaxPacketSize;


/*2.目的 */
usb_buf = usb_alloc_coherent(dev,len, GFP_ATOMIC, &usb_buf_phys);


//使用三要素
/*分配一個urb usb request block*/
uk_urb= usb_alloc_urb(0, GFP_KERNEL);
//使用3要素設定這個urb
usb_fill_int_urb(uk_urb, dev, pipe, usb_buf,len,usbmouse_as_key_irq,NULL, endpoint->bInterval);
uk_urb->transfer_dma = usb_buf_phys;
uk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
//使用URB
usb_submit_urb(uk_urb, GFP_KERNEL);


return 0;
}


static void usbmouse_as_key_disconnect(struct usb_interface *intf)
{
struct usb_device *dev = interface_to_usbdev(intf);
usb_kill_urb(uk_urb);
usb_free_urb(uk_urb);
usb_free_coherent(dev, len, usb_buf, usb_buf_phys);
input_unregister_device(usb_key);
input_free_device(usb_key);




}
/*1.分配/設定usb_driver*/
static struct usb_driver usbmouse_as_key_driver = {
.name= "usbmouse_as_key",
.probe = usbmouse_as_key_probe,
.disconnect = usbmouse_as_key_disconnect,
.id_table = usbmouse_as_key_id_table,
};
static int usbmouse_as_key_init(void)
{
/*2.註冊usb_driver結構體*/
usb_register(&usbmouse_as_key_driver);
return 0;
}

static void usbmouse_as_key_exit(void)
{
usb_deregister(&usbmouse_as_key_driver);
}


module_init(usbmouse_as_key_init);
module_exit(usbmouse_as_key_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("EIGHT");

測試結構如下圖


相關推薦

USB驅動程式滑鼠鍵盤

我們還是接著來看看我們的例子程式 usbmouse.c 這裡它接著判斷了他是不是滑鼠, 得到它的usb_host_interface,interface=intf->cur_alsetting就是當前介面的設定 這裡有個介面描述符,我們來看看介面描述符 介面

嵌入式Linux USB驅動開發教你一步步編寫USB驅動程式

編寫與一個USB裝置驅動程式的方法和其他匯流排驅動方式類似,驅動程式把驅動程式物件註冊到USB子系統中,稍後再使用製造商和裝置標識來判斷是否安裝了硬體。當然,這些製造商和裝置標識需要我們編寫進USB 驅動程式中。 USB 驅動程式依然遵循裝置模型 —— 匯流排、裝置、驅動

USB驅動程式(三)——滑鼠驅動程式(中斷傳輸)

 本文以 usbmouse.c 為例,簡單分析usb滑鼠驅動程式。 [cpp] view plain copy  print? staticint __init usb_mouse_init(void)   {       int retval = usb

linux驅動USB驅動程式框架

USB驅動程式框架: app: -----------------------------------------------------------------------                              USB裝置驅動程式         

字元裝置驅動程式非同步通知

非同步通知:      驅動程式的所謂非同步通知,指的是應用程式不是主動對驅動程式進行操作,而是驅動程式查詢到有事件發生或者有資料發生變化的時候通知應用程式。角色發生了變化,應用程式由主動改為被動執行。 比如按鍵驅動: 1、要不斷進行查詢引腳狀

(二)USB驅動程式_USB裝置驅動(Host)

USB裝置驅動(Host) 深入,並且廣泛 -沉默犀牛 有了第一篇文章的基礎,我們這篇文章來看一下USB裝置驅動的原始碼。與其他的Driver一樣,USB的driver也表現為一個結構體:struct usb_driver 驅動整體結構 在編寫新的USB

usb驅動程式小結(六)

title: usb驅動程式小結 tags: linux date: 2018/12/20/ 17:59:51 toc: true --- usb驅動程式小結 linux中為usb驅動也提供了一套匯流排驅動,類似platform裝置平臺,這個匯流排為我們提供了usb匯流排的時序相關的東西,能夠讀

【2018.05.09】python3.6 + selenium 定位 滑鼠事件操作+鍵盤事件操作

一、簡單操作     1.點選(滑鼠左鍵)頁面按鈕:click()     2.請空輸入框:clear()     3.輸入字串:send_keys()     4.submit()一

C#窗體應用程式滑鼠事件

                                   和重繪一樣,窗體本身有paint,還有mousemove等事件 private void Form1_MouseMove(o

Linux USB 驅動開發(五)—— USB驅動程式開發過程簡單總結

       裝置驅動程式是作業系統核心和機器硬體之間的介面,由一組函式和一些私有資料組成,是應用程式和硬體裝置之間的橋樑。在應用程式看來,硬體裝置只是一個裝置檔案,應用程式可以像操作普通檔案一樣對硬體裝置進行操作。       裝置驅動程式是核心的一部分,主要完成以下功能

(一)USB驅動程式_USB基礎知識

深入,並且廣泛 -沉默犀牛 USB裝置驅動分類 USB驅動程式可以粗分為兩類: 一、主機(Host)系統上的驅動程式 ,這個驅動程式控制插入其中的USB裝置 二、裝置(Device)上的驅動程式,這個驅動程式控制USB裝置如何與主機通訊 為了舉一個形象的例子,我得先展示

USB驅動開發FPGA下環路程式碼設計

目錄 1. 下環路程式碼設計要求 2. FPGA狀態機設計 3. 下環路程式碼測試 3.1 資料傳輸測試 3.2 資料傳輸速度測試 4. 遇到的問題與收穫 5. 參考 6. 附錄 1. 下環路程式碼設計要求      

USB驅動開發FPGA環路程式碼設計

目錄 1. 環路程式碼設計要求 2. FPGA狀態機設計 3. 程式碼測試 3.1 使用上位機測試FPGA程式碼 3.2 signalTap II時序模擬 4. 遇到的問題與收穫 5. 參考 6. 附錄 1. 環路程式碼設計要求   &

韋東山嵌入式Linux學習筆記——第12課第8節 字元裝置驅動程式定時器防抖動

注:本文部分內容摘自《魚樹學員筆記》。 當按鍵按得比較快的時候,這裡出現了兩次中斷值,也即產生了抖動。 這裡產生了“抖動”,按鍵是機械開關,按下鬆開時裡面的金屬彈片可能抖動了好幾次。這種抖動產生了多次“脈衝”導致多次中斷。 方法: 使用定時器來防抖動。

nandflash驅動程式完善識別過程

我們發出了那些訊號, 如上圖,發出一些訊號我們應該會維持一段時間啊,太短了 nandflash可能反應不過來,所以我們還要設定一些事件引數 根據nandflash的手冊 設定時間引數 我們看一看那開發板的晶片手冊 它的時間引數就在TACLS TWRPH0 TWRPH1

S3C JZ2440 USB 驅動程式完整

/*參考例子:drivers\hid\usbhid\usbmouse.c  *功能:完整的USB驅動程式  *  *2016年6月23日21:37:10  */ #include <linux/kernel.h> #include <linux/slab.

什麼是驅動程式?為什麼要驅動程式?

驅動程式,英文名為“Device Driver”,全稱為“裝置驅動程式”,它是一種特殊的程式。首先其作用是將硬體本身的功能告訴作業系統,接下來的主要功能就是完成硬體裝置電子訊號與作業系統及軟體的高階程式語言之間的互相翻譯。當作業系統需要使用某個硬體時,比如:讓音效卡播放音樂,

編寫USB滑鼠驅動程式,並測試

學習目標:編寫USB滑鼠驅動程式,並測試(將USB滑鼠的左鍵當作L按鍵,將USB滑鼠的右鍵當作S按鍵,中鍵當作回車按鍵). 一、怎麼寫USB裝置驅動程式?步驟如下: 1. 首先先定義全域性變數usb_driver結構體,並在入口函式中通過usb_register()函式進行註冊; 2. 分別寫usb

[Win10]滑鼠沒用,插入USB口電腦提示USB Optical Mouse找不到驅動程式的解決方案

系統: Win 10(x64) 把手機通過資料線插在電腦USB口上讀取資料正常(說明USB口沒有壞) 問題 昨天電腦還好好的,今天起來滑鼠就沒用了,不管是有線還是無線滑鼠都用不了。 滑鼠插電腦上,不停的有USB連線和斷開的聲音重複。 檢查

STM32 標準外設版USB驅動庫詳解(架構+檔案+函式+使用說明+示例程式

寫在前面 目前,ST的USB驅動有兩套,一套是早期的獨立版USB驅動,官方培訓文件中稱為Legacy library,最新版為2.2.0;一套為針對其Cube系列的驅動,根據晶片不同可能有區別,具體見對應晶片的Cube驅動包,官方培訓文件中稱為Cube li