日韩一区二区三区精品,欧美疯狂xxxxbbbb牲交,热99re久久免费视精品频,人妻互换 综合,欧美激情肉欲高潮视频

基于ok6410的韋東山驅(qū)動視頻簡要分析--USB驅(qū)動

發(fā)布者:溫柔的愛情最新更新時(shí)間:2024-11-06 來源: cnblogs關(guān)鍵字:ok6410  USB驅(qū)動 手機(jī)看文章 掃描二維碼
隨時(shí)隨地手機(jī)看文章

注意:本篇講的鼠標(biāo)驅(qū)動僅能實(shí)現(xiàn)鼠標(biāo)左右鍵跟滑輪這三個(gè)按鍵類似button的功能,按下左鍵則打出'l',右鍵打出“s”,滑輪打出“enter”。如果要實(shí)現(xiàn)正常的鼠標(biāo)驅(qū)動,參考內(nèi)核的鼠標(biāo)驅(qū)動,修改input的一些參數(shù)即可。


 


一、寫驅(qū)動的步驟(新手稍微看下即可,內(nèi)容有點(diǎn)搞)


1、復(fù)制頭文件;


2、寫入口函數(shù),出口函數(shù),再加上協(xié)議;


3、分配注冊usb_driver結(jié)構(gòu)體(拷別人的),


static struct usb_driver usb_mk_driver = {};


在init中注冊該結(jié)構(gòu)體:usb_register(&usb_mk_driver);


在exit中注銷該結(jié)構(gòu)體:usb_deregister(&usb_mk_driver);


4、寫id_table函數(shù),static struct usb_device_id usb_mk_id_table [] = {},只有滿足id_table中的各種類別,子類號,協(xié)議,才能調(diào)用;


5、寫probe函數(shù):static int usb_mk_probe(struct usb_interface *intf, const struct usb_device_id *id);


6、寫disconnect函數(shù):static void usb_mk_disconnect(struct usb_interface *intf)


7、如果想在開發(fā)板插入usb設(shè)備的時(shí)候打印設(shè)備信息(可以不用),可以在probe中加入:


printk('VID = 0x%x, PID = 0x%xn', dev->descriptor.idVendor, dev->descriptor.idProduct);


printk('USB VERS = 0x%x, PID = 0x%xn', dev->descriptor.bcdUSB);


8、probe之后要進(jìn)一步判斷你這個(gè)是不是鼠標(biāo):


1、分配一個(gè)input_dev結(jié)構(gòu)體:在頭文件下定義;static struct input_dev       *mk_dev;  在probe內(nèi):mk_dev = input_allocate_device();


2、設(shè)置:


1、能產(chǎn)生哪類事件


set_bit(EV_KEY, mk_dev->evbit);


set_bit(EV_REP, mk_dev->evbit);


2、能產(chǎn)生哪些事件


set_bit(KEY_L, mk_dev->keybit);


set_bit(KEY_S, mk_dev->keybit);


set_bit(KEY_ENTER, mk_dev->keybit);


3、注冊:input_register_device(mk_dev);


4、設(shè)置:數(shù)據(jù)傳輸3要素: 源, 目的, 長度


先從usbmouse.c中拷入幾行代碼


struct usb_device *dev = interface_to_usbdev(intf);


struct usb_host_interface *interface;


struct usb_endpoint_descriptor *endpoint;


int pipe;


endpoint = &interface->endpoint[0].desc;


源:usb設(shè)備的某個(gè)端點(diǎn)


pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);


目的:需要設(shè)置緩沖區(qū)buffer:


buf = usb_alloc_coherent(dev, len, GFP_ATOMIC, &buf_phys);


在頭文件下定義一個(gè)緩沖區(qū):


static char *buf; 


static dma_addr_t buf_phys;


長度:static  int len(作為全局變量,等會有用)


len = endpoint->wMaxPacketSize;


5、怎么用那三要素呢?


在probe中;


1、分配一個(gè)urb,mk_urb = usb_alloc_urb(0, GFP_KERNEL);


在頭文件下定義urb:static struct urb *mk_urb;


2、使用三要素填充urb:


usb_fill_int_urb(mk_urb, dev, pipe, buf,


 len,


 uk_callback, NULL, endpoint->bInterval);


mk_urb->transfer_dma = buf_phys;


mk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;


 


3、使用URB:usb_submit_urb(mk_urb, GFP_KERNEL);


6、要寫一個(gè)中斷函數(shù),原因是usb控制器收到從usb傳來的數(shù)據(jù)后,需要一個(gè)中斷來通知cpu有信號啦!static void uk_callback(struct urb *urb)


在中斷函數(shù)中定義一些唧唧歪歪的東西后看,重新提交urb:


usb_submit_urb(mk_urb, GFP_KERNEL);


7,提交urb后當(dāng)然還要做殺掉urb,在disconnect中殺掉它!usb_kill_urb(mk_urb);


順便再disconnect中注銷或卸載其他的函數(shù);


8、在中斷函數(shù)里上報(bào)事件。


 


**************************************************************************************************************


 


二、驅(qū)動程序


#include <linux/kernel.h>

#include

#include

#include

#include

#include

#include


/* 參考drivershidusbhidusbmouse.c

 */


static struct input_dev *mk_dev;

static int len;

static char *buf;  //定義一個(gè)緩沖區(qū)

static dma_addr_t buf_phys; //dma_addr實(shí)際上是一個(gè)物理地址

static struct urb *mk_urb;


static struct usb_device_id usb_mk_id_table [] = {

{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,

USB_INTERFACE_PROTOCOL_MOUSE) },

/*只要它的類是class_hid,子類是boot,協(xié)議是mouse,那么就可以匹配*/

 *{USB_DEVICE(0x46d, 0xc52f)或者直接指定自己的usb設(shè)備只支持這種廠家的設(shè)備。*/

{ } /* Terminating entry */

};


/* 當(dāng)USB主機(jī)控制器獲得鼠標(biāo)數(shù)據(jù)后,

 * 會調(diào)用這個(gè)函數(shù)

 */

static void uk_callback(struct urb *urb)//這是一個(gè)中斷函數(shù)!

{

int i;

static char pre_val;

#if 0 //這一段都用不到了,因?yàn)閕f = 0 ;這一段的作用就是用來看鼠標(biāo)按下之后都顯示什么數(shù)值,最后通過這些數(shù)值來設(shè)置上報(bào)事件。

printk('Get datas:n');

for (i = 0; i < len; i++)

{

printk('%02x ', buf[i]);

}

printk('n');

#endif

/* 鼠標(biāo)數(shù)據(jù)含義:

* buf[0]: bit0-左鍵, 0-松開, 1-按下

*         bit1-右鍵, 0-松開, 1-按下

*         bit2-中鍵, 0-松開, 1-按下

* buf[1],buf[2]構(gòu)成一個(gè)整數(shù), 表示X方向的相對位移

*         >0 : 右移

*         <0 : 左移

* buf[3],buf[4]構(gòu)成一個(gè)整數(shù), 表示Y方向的相對位移

*         >0 : 下移

*         <0 : 上移

* buf[6]: 滾輪

*/

 

/* 確定按鍵值 */

/* 上報(bào)數(shù)據(jù) */

if ((pre_val & (1<<0)) != (buf[0] & (1<<0))) //如果上次數(shù)據(jù)的bit0不等于這次數(shù)據(jù)的bit0,那么就是左鍵發(fā)生變化

{

/* 左鍵按下或松開 */

input_event(mk_dev, EV_KEY, KEY_L, (buf[0] & (1<<0)) ? 1 : 0);//如果buf0=1的話那就是按下,既是1,否則為0;

input_sync(mk_dev);

}


if ((pre_val & (1<<1)) != (buf[0] & (1<<1)))

{

/* 右鍵按下或松開 */

input_event(mk_dev, EV_KEY, KEY_S, (buf[0] & (1<<1)) ? 1 : 0);

input_sync(mk_dev);

}


if ((pre_val & (1<<2)) != (buf[0] & (1<<2)))

{

/* 中鍵按下或松開 */

input_event(mk_dev, EV_KEY, KEY_ENTER, (buf[0] & (1<<2)) ? 1 : 0);

input_sync(mk_dev);

}


pre_val = buf[0];


/* 重新提交URB */

usb_submit_urb(mk_urb, GFP_KERNEL);

}


/*interface是指接口,一個(gè)usb設(shè)備可能有多個(gè)邏輯接口,這個(gè)邏輯接口就是用下面的usb_interface來表示的*/

static int usb_mk_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;

static int first = 1;


if (!first)

return -EIO;

first = 0;


/* 每一個(gè)設(shè)備都有端點(diǎn)0

* interface->endpoint[]數(shù)組里放'除了端點(diǎn)0外的其他端點(diǎn)'

* interface->endpoint[0]表示'除端點(diǎn)0外的第1個(gè)端點(diǎn)'

* interface->endpoint[1]表示'除端點(diǎn)0外的第2個(gè)端點(diǎn)'

*/

interface = intf->cur_altsetting;

endpoint = &interface->endpoint[0].desc;


/* 1. 分配inputd_dev */

mk_dev = input_allocate_device();

/* 2. 設(shè)置 */

/* 2.1 能產(chǎn)生哪類事件 */

set_bit(EV_KEY, mk_dev->evbit);  //按鍵類事件

set_bit(EV_REP, mk_dev->evbit);  //重復(fù)類事件,例如一直按著L,則會顯示LLLLLLL。。。

/* 2.2 能產(chǎn)生這類事件里的哪些事件 */

set_bit(KEY_L, mk_dev->keybit);

set_bit(KEY_S, mk_dev->keybit);

set_bit(KEY_ENTER, mk_dev->keybit);

/* 3. 注冊 */

input_register_device(mk_dev);


/* 4. 硬件相關(guān)的操作: 

*    對于GPIO按鍵, 是request_irq, 在中斷處理函數(shù)里上報(bào)按鍵

*    對于USB設(shè)備, 是使用'USB主機(jī)驅(qū)動程序提供的函數(shù)'發(fā)起USB傳輸獲得數(shù)據(jù)

*/

/* 數(shù)據(jù)傳輸3要素: 源, 目的, 長度 */

/* A. 源: USB設(shè)備的某個(gè)端點(diǎn) */

/* ((PIPE_INTERRUPT << 30) | (dev->devnum << 8) | (endpoint << 15) | USB_DIR_IN) */

pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);//pipe是源,源是一個(gè)整數(shù),這個(gè)整數(shù)里有端點(diǎn)的類型,端點(diǎn)的方向

/* C. 長度: 這個(gè)端點(diǎn)描述符的wMaxPacketSize */

len = endpoint->wMaxPacketSize;


/* B. 目的: 分配buffer */

buf = usb_alloc_coherent(dev, len, GFP_ATOMIC, &buf_phys);//從usb_buffer_alloc換成usb_alloc_coherent


/* D. 怎么使用這3要素 ? */

/* 分配URB: USB Reqeust Block ,usb請求塊*/

mk_urb = usb_alloc_urb(0, GFP_KERNEL);

/* 用3要素填充URB 

*實(shí)際上usb設(shè)備沒有中斷cpu的能力,但是電腦的usb主機(jī)有中斷cpu的能力,所以usb主機(jī)不斷查詢,有信號便中斷cpu。

*/

usb_fill_int_urb(mk_urb, dev, pipe, buf,

len,

uk_callback, NULL, endpoint->bInterval);//bInterval:查詢頻率,uk_callback是一個(gè)中斷函數(shù);

mk_urb->transfer_dma = buf_phys; //得到數(shù)據(jù)后要往某個(gè)內(nèi)存里寫,它沒那么聰明,需要一個(gè)物理地址

mk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;//還有設(shè)置某些標(biāo)記,這標(biāo)記什么意思偉哥也不懂

/* 使用URB ,看看別人怎么做*/

usb_submit_urb(mk_urb, GFP_KERNEL);//提交urb


return 0;

}


static void usb_mk_disconnect(struct usb_interface *intf)

{

struct usb_device *dev = interface_to_usbdev(intf);

printk('disconnect usb mouse!!!!!n');

usb_kill_urb(mk_urb);

usb_free_urb(mk_urb);

usb_free_coherent(dev,len, buf, buf_phys);//應(yīng)該是usb_free_coherent

input_unregister_device(mk_dev);

input_free_device(mk_dev);

}


/* 1. 分配usb_driver */

/* 2. 設(shè)置 */

static struct usb_driver usb_mk_driver = {

.name = 'usbmk',

.probe = usb_mk_probe,

.disconnect = usb_mk_disconnect,

.id_table = usb_mk_id_table,

};


static int usb_mk_init(void)

{

/* 3. 注冊 */

usb_register(&usb_mk_driver);

return 0;

}


static void usb_mk_exit(void)

{

usb_deregister(&usb_mk_driver);

}


module_init(usb_mk_init);

module_exit(usb_mk_exit);


MODULE_LICENSE('GPL');


關(guān)鍵字:ok6410  USB驅(qū)動 引用地址:基于ok6410的韋東山驅(qū)動視頻簡要分析--USB驅(qū)動

上一篇:u-boot2010.03 移植篇(一) 建立編譯目標(biāo)
下一篇:基于ok6410的韋東山驅(qū)動視頻簡要分析--ts驅(qū)動

推薦閱讀最新更新時(shí)間:2025-07-13 18:40

OK6410裸機(jī)學(xué)習(xí)之時(shí)鐘設(shè)置-匯編
start.S源碼: .globl _start _start: // 硬件相關(guān)的設(shè)置 // Peri port setup ldr r0, =0x70000000 orr r0, r0, #0x13 mcr p15,0,r0,c15,c2,4 @ 256M(0x70000000-0x7fffffff) // 關(guān)看門狗 // 往WTCON(0x7E004000)寫0 ldr r0, =0x7E004000 mov r1, #0 str r1, // 設(shè)置時(shí)鐘 bl clock_init // 設(shè)置棧 ldr sp, =8*1024 bl main
[單片機(jī)]
<font color='red'>OK6410</font>裸機(jī)學(xué)習(xí)之時(shí)鐘設(shè)置-匯編
STM32L0開發(fā)筆記8: USB驅(qū)動的移植
現(xiàn)在使用的STM32L053R8T6單片機(jī)帶有USB接口,原先一直使用UART轉(zhuǎn)USB芯片來完成USB功能的支持,現(xiàn)在這款單片機(jī)帶了就希望使用以下。由于已經(jīng)建立了自己的工程目錄,再重新使用STM32CubeMX生成的工程文件,重新建立是不顯示的,所以本文探索將USB驅(qū)動文件移植到自己項(xiàng)目中的方法,我使用的是USB的CDCD類,步驟如下: 1、使用STM32CubeMX使能USB,如下圖所示: 2、設(shè)置時(shí)鐘,USB需要48M時(shí)鐘,使用內(nèi)部和外部均可,我這里使用外部時(shí)鐘。 3、生成工程文件。 4、在自己的工程目錄中加入如下圖所示的2個(gè)文件,如果此2個(gè)文件不存在,則從新生成的工程目錄中復(fù)制即可(包含
[單片機(jī)]
小廣播
設(shè)計(jì)資源 培訓(xùn) 開發(fā)板 精華推薦

最新單片機(jī)文章

 
EEWorld訂閱號

 
EEWorld服務(wù)號

 
汽車開發(fā)圈

 
機(jī)器人開發(fā)圈

電子工程世界版權(quán)所有 京ICP證060456號 京ICP備10001474號-1 電信業(yè)務(wù)審批[2006]字第258號函 京公網(wǎng)安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved