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

touch panel驅動程式實做

Embed Size (px)

Citation preview

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驅動程式實做

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