touch panel驅動程式實做

38
觸觸觸觸觸觸觸觸觸觸觸 觸觸觸觸觸觸觸觸觸觸觸 指指指指 指指指指指 指指指指 指指指指指 指指指指指 指指指指指 指指指指指 指指指指指 指指 指指指 指指 指指指 指指 指指指 指指指 指指指 指指指 指指 指指指 指指指 指指指 指指指

Upload: bryant6831

Post on 16-Nov-2014

3.914 views

Category:

Documents


5 download

TRANSCRIPT

Page 1: touch panel驅動程式實做

觸控面板驅動實作觸控面板驅動實作與應用與應用

指導老師: 李志賢組長指導老師: 李志賢組長 孫文駿老師孫文駿老師

黃馨臻老師黃馨臻老師

組長:黃熠样組長:黃熠样組員:王奕晨 林承毅 黃秀蕙 魏韶羿組員:王奕晨 林承毅 黃秀蕙 魏韶羿

Page 2: touch panel驅動程式實做

研究動機本組藉由這次專題實作的機會,練習寫觸控面板的 usb 驅動程式並移植在 ARM 板上控制QT/embedded 滑鼠游標,增進驅動程式撰寫經驗,以利未來職場上的應用。

Page 3: touch panel驅動程式實做

電阻式的驅動原理是用電壓降的方式來找座標軸,由下圖可以看出, X軸和 Y 軸各由一對 0∼5V 的電壓來驅動,當電阻式觸控螢幕被 Touch

到的時候,由於迴路被導通,而會產生電壓降,而控制器則會算出電壓降所佔的比例然後 更進一步算出座標軸。

電阻式觸控面板原理

Page 4: touch panel驅動程式實做

運作原理

ADC Interface IC

電壓值

根據電壓值轉換座標

控制器

電阻式觸控面板 電腦

USB OR RS232

Page 5: touch panel驅動程式實做

Usb Core

Usb core

Touch panel

Usb 隨身碟

Usb 等等裝置

USB CORE 是所有 USB 裝置的介面 ,USB 裝置透過 USB CORE 跟 USB DRIVER 溝通

URB 是 USB DRIVER 和 USB CORE 間 , 傳輸資料的方式 ,URB 有下面這 4 種

控制傳輸( control urb ) 中斷傳輸( interrupt urb ) 巨量傳輸( bulk urb ) 等時傳輸( isochronous urb )

(vendor ID 1391 prod ID 1000 )

Touch panel driver

If vid=1391 and pid=1000 ?(Load driver)

urb

(vendor 1391 prod ID 1000 )

Page 6: touch panel驅動程式實做

Usb 驅動介紹 第一步 :

Fill in vendor 1391 and prod ID 1000 into the structure

static struct usb_device_id skel_table [] = {{ USB_DEVICE(1391,1000) },{ }

};MODULE_DEVICE_TABLE(usb, skel_table);

#cat /proc/bus/usb/devices

Page 7: touch panel驅動程式實做

Usb 驅動介紹第二步 :

Set up the function name in this structure :

將 driver 所需功能填入此 file_operations 結構中 , 上層 ap 呼叫 open 時則 driver 會執行 skel_open , read 時會執行 skel_read write時會執行 skel_write , ioctl 時會執行 skel_ioctl

static struct file_operations skel_fops = {.owner = THIS_MODULE,.read = skel_read,.write = skel_write,.open = skel_open,.release = skel_release,.ioctl = skel_ioctl,

};

Page 8: touch panel驅動程式實做

Usb 驅動介紹第三步 :

Set up device file into structure :

設定裝置檔案名稱 , 填入 file_operations 結構名稱 , 設定 minor number

static struct usb_class_driver skel_class = {.name = "skel%d",.fops = &skel_fops,.minor_base =196,

};

Page 9: touch panel驅動程式實做

Usb 驅動介紹第四步 :

Set up structure usb_driver for this driver static struct usb_driver skel_driver = {

.name = “skeleton”, //driver 名稱 .id_table = skel_table, //usb id table 表 .probe = skel_probe, // 裝置插入會執行 .disconnect = skel_disconnect, // 裝置拔出會執行

};

第五步 :

Register the usb_driver into usb core static int __init usb_skel_init(void) {

usb_register(&skel_driver); // 註冊 driver 到 usb core

}

Page 10: touch panel驅動程式實做

第六步

Write program in this functions skel_probe() skel_release()

skel_disconnect() skel_ioctl()

skel_read()

skel_write()

skel_open()

Usb 驅動介紹

Page 11: touch panel驅動程式實做

skel_probe()裝置插入會執行static int skel_probe(struct usb_interface *interface, const struct usb_device_id

*id)

{

………………………..

struct usb_skel *dev = NULL; // 此 driver 的資源結構 usb_register_dev(interface, &skel_class); // 註冊 /dev 底下的裝置檔案 dev->interface = interface; // 取得 interface 儲存進資源結構裡 dev->urb = usb_alloc_urb(0, GFP_KERNEL); // 設定 urb

usb_fill_int_urb(…………..) // 初始化 read 中斷 urb

usb_submit_urb(dev->urb, GFP_KERNEL); // 提交 urb

usb_set_intfdata(interface, dev); // 把資源結構儲存進 interface 裡 , 供往後使 用 ………………………….

}

Page 12: touch panel驅動程式實做

skel_open()

上層 ap open 時會執行static int skel_open(struct inode *inode, struct file *file)

{

……………………………..

struct usb_skel *dev; // 資源結構 dev = usb_get_intfdata(interface); // 從 interface 取得之前儲存的資源結構 file->private_data = dev; // 把資源結構儲存進 file 指標裡 , 供往後 read write 使用 kref_get(&dev->kref); // 驅動使用權 +1 動作

………………………………….

}

Page 13: touch panel驅動程式實做

skel_irq()

中斷 urb 完工函式static void skel_irq(struct urb *urb, struct pt_regs *regs)

{

struct usb_skel *dev = urb->context; // 從 urb 裡取得資源結構 ……………………………….

解析 5byte 座標資訊 , 完成後儲存進 kernel space buf 裡 ……………………………….

usb_submit_urb (urb, GFP_ATOMIC);

// 重新提交 read 中斷 urb 到 usb core 裡 , 排定下次傳輸

}

Page 14: touch panel驅動程式實做

skel_read()上層 ap read 時會執行static ssize_t skel_read(struct file *file, char __user *user_buf, size_t count, loff_t

*ppos)

{

………………………….

struct usb_skel *dev; // 資源結構 dev = (struct usb_skel *)file->private_data; // 取得 file 指標指的資源結構

………………………….

copy_to_user(user_buf,_kernel_buffer,byteread); // 把座標資訊丟到 user space

…………………………..

}

Page 15: touch panel驅動程式實做

skel_write()上層 ap write 時會執行static ssize_t skel_write(struct file *file, const char __user *user_buffer, size_t count,

loff_t *ppos)

{

struct usb_skel *dev; // 資源結構 dev = (struct usb_skel *)file->private_data; // 取得 file 指標指的資源結構 ……………………………

copy_from_user(kernel_buf,user_buffer,count) // 取得 user sapce 送進來的資訊 usb_control_msg(…………….) // 把 user space 送進來的資訊使用 urb 寫進 user

space 裡 …………………………...

}

Page 16: touch panel驅動程式實做

skel_ioctl()供上層 ap 呼叫的 ioctl

static int skel_ioctl(struct inode *inode, struct file * file,unsigned int cmd, unsigned long arg)

{

struct usb_skel *dev; // 資源結構 dev=(struct usb_skel *)file->private_data; // 取的資源結構 switch (cmd)

{

case SCR_IOCTL_CLEAR_BUFF:

memset(kernel_buf,0x00,sizeof(kernel_buf));// 清空 kernel space buf

return 1;

}

}

Page 17: touch panel驅動程式實做

skel_release()

上層 ap close 呼叫會執行

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

{

struct usb_skel *dev; // 資源結構 dev = (struct usb_skel *)file->private_data;// 取得資源結構 kref_put(&dev->kref, skel_delete);// 驅動使用權 -1 動作

}

Page 18: touch panel驅動程式實做

skel_disconnect()

裝置拔出會執行

static void skel_disconnect(struct usb_interface *interface)

{

………………………………….

usb_set_intfdata(interface, NULL); // 取消資源結構的儲存 usb_deregister_dev(interface, &skel_class); // 解除 /dev 裝置檔案 usb_unlink_urb(dev->urb); // 取消 urb

usb_free_urb(dev->urb);// 取消 urb

……………………………………

}

Page 19: touch panel驅動程式實做

usb_skel_exit(void)

rmmod usb.ko 會執行

static void __exit usb_skel_exit(void)

{

usb_deregister(&skel_driver); // 解除驅動的註冊}

Page 20: touch panel驅動程式實做

驅動程式流程

Skel_open()

Skel_read()

Skel_write()

Skel_release()

Skel_probe()

skel_disconnect()

Usb coreinterrupt urb

control urb

Open()

read()

write()

close()

Copy_to_user()

Copy_from_user()

Kernel space user space

AP

/dev/skel

Skel_irq()1

2

4

5

Skel_ioctl()3

user_buf[130]Kernel_buf[130]6

78

9

11

10

Page 21: touch panel驅動程式實做

Usb Device Driver 最後結果 :

Insmod usb.ko 和插入裝置後

查看 /dev 是否有裝置檔案

查看裝置是否有載入驅動

Cat /proc/bus/usb/devices

Page 22: touch panel驅動程式實做

座標資訊

(C8 or 88) 6a 60 7a 70

X 座標 14bit y 座標 14bit

Up or down

公式轉換

high low high low

同一點 3 筆資料

1200 1133 1202 1120 1212 1111

/ 3 = 1204 1121

3 筆取平均數

Page 23: touch panel驅動程式實做

Driver porting to ARM

Page 24: touch panel驅動程式實做

ARM 軟硬體架構

• ARM9 + 3.5 吋 LCD • 10 吋電阻式 USB 觸控式面板 ( 接在 ARM9 的 USB 接

口 )• Linux kernel 2.6• QT/embedded 3.3.8• Touch panel Usb driver• QT 程式

Page 25: touch panel驅動程式實做

QT/embedded 介紹

Trolltech 針對嵌入式環境推出 Qt/Embedded 產品。與桌上出版本不同, Qt/Embedded 已經直接取代了 X Server 及 X Library 等角色,將所有的功能全部整合在一起。

Qt/Embedded 的底層圖形引擎採用 FrameBuffer

的方式顯示 gui 介面

Page 26: touch panel驅動程式實做

PC & ARM GUI

PC 與 ARM 在視窗介面的差異性比較

GNOME or KDE

X Server(x window driver)

Touch panel Usb driver

PC

QT 任意程式

QT/Embedded(QT touch driver)

Touch panel Usb driver

ARM

Page 27: touch panel驅動程式實做

QT/embedded 移植1. 為了讓 QT 支援 touch panel usb

driver 修改 qte/src/embedded/qmouselinuxtp_qws.cpp (QT touch driver)

2. 修改 qte/mkspecs/qws/linux-arm-g++/qmake.conf

把原本的 gcc and g++ 改成 arm-linux-gcc arm-linux-g++

3. 開始編譯 :

./configure -thread -embedded ipaq -shared -depths 16 -no-cups -no-ipv6 -thread -no-gfx-qvfb -no-freetype -disable-opengl -disable-xml -disable-canvas -qt-libjpeg -qt-mouse-linuxtp -xplatform qws/linux-arm-g++

4.Configure 成功後開始 make sub-src

成功後會產生 4 個 .so 檔 libqte-mt.so, libqte-mt.so.3, libqte-mt.so.3.3, libqte-mt.so.3.3.8

最後在使用 NFS server 跟板子連線的方式把這 4 個檔放進 ARM 裡就成功完成移植

Page 28: touch panel驅動程式實做

qmouselinuxtp_qws.cpp

• 要修改的有裝置檔案名稱 , 還有 read 方式( 改成 touch panel usb driver 的 device file /dev/skel0)

void QWSLinuxTPMouseHandlerPrivate::readMouseData(){

改成可以讀取 touch panel usb driver 的座標 加入兩點校正公式 , 讀取校正檔案 samples[currSample] = QPoint( x, y);

…………………………………

handler->mouseChanged(mousePos,0); // 實際控制 QT 鼠標的函式

}

Page 29: touch panel驅動程式實做

USB driver 移植1. 要先在 PC 上用 cross compile 成 arm 可以用的 driver

2. 利用 NFS server 跟板子做連線 , 放進 ARM 板後試試看有沒有作用 利用一隻簡單的 ap跑看看

3. 最後試者跟 QT/embedded 做結合

寫個簡單的 QT 程式試試看

在終端機打入 ./myqt –qws (FrameBuffer 來執行 ) ( 執行後會找尋這 4 個檔案 libqte-mt.so, libqte-mt.so.3, libqte-mt.so.3.3, libqte-

mt.so.3.3.8, load 這些檔案後 , 成功就會跑出 gui 介面 )

Page 30: touch panel驅動程式實做

ARM QT

samples[currSample] = QPoint( x, y);100,100

900,900

測試出來 (100,100) 鼠標在左下 (900,900) 鼠標在右上

Page 31: touch panel驅動程式實做

座標轉換

X=((byte2<<1) | ((byte1)<<7))Y=((byte4<<1) | ((byte3)<<7))

(16376,16376)

(0,0)

( 原始面板座標 )

X=(X/20)+100Y=(Y/20)+100

( 轉換 QT 對應座標 )

(900,900)

(0,0)

(4 byte 座標合併公式 )

Page 32: touch panel驅動程式實做

兩點校正公式(X1,Y1) 為 touch panel左下座標 (X2,Y2) 為 touch panel右上座標 , 900,900 為 QT 鼠標最大座標

X=900-(900 * ( X-X2) / (X1 – X2) )Y=900-(900 * ( Y- Y2) / (Y1 – Y2) )

(0,0)

(900,900)(touch panel 校正前 )

(0,0)

(900,900)

(touch panel 校正完後 )

(X1,Y1)

(X2,Y2)

(X1,Y1)

(X2,Y2) (900,900)

(0,0)

Page 33: touch panel驅動程式實做

校正程式

白色紙表示校正的區域

Page 34: touch panel驅動程式實做

校正程式終端機打入 ./2Pcail_QT -qws 執行 QT 校正程式

點擊畫面上 1 左下座標 2 右上座標

Page 35: touch panel驅動程式實做

校正程式校正完成後 ,畫面會顯示校正完成

程式會把兩點的座標存到檔案裡面 , 供 QT touch driver 使用

Page 36: touch panel驅動程式實做

運作結果• 已經可以利用選定的 3.5區域來控制鼠標了 ,現在可以點擊和移動鼠

標 但移動還是會有點誤差

Page 37: touch panel驅動程式實做

參考資料Linux device driver 3/e 第 13章

Page 38: touch panel驅動程式實做

謝謝您耐心聆聽謝謝您耐心聆聽