Viết driver chuột USB cho hệ điều hành Linux

14 918 3
Viết driver chuột USB cho hệ điều hành Linux

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Phân tích mã nguồn USB mouse chuẩn giao tiếp USB (Universal Series Bus) đã và đang trở thành một trong những chuẩn giao tiếp phổ biến nhất. Hiện tại, USB đã trở thành chuẩn kết nối cũng như phương thức truyền dữ liệu thân thuộc với người dùng công nghệ nhờ vào sự thuận tiện, độ bền và giá thành hợp lý của nó. Do đó chúng em quyết định chọn đề tài “Viết driver chuột USB cho hệ điều hành Linux” làm bài tập lớn cho môn học Hệ điều hành. Vì đây là một đề tài tương đối phức tạp và thời gian thực hiện có hạn, nên nhóm chúng em chỉ dừng lại ở mức độ đi sâu phân tích mã nguồn của hệ điều hành nhằm tìm hiểu cơ chế quản lý giao tiếp USB của Linux. Phần code được sử dụng nằm trong file drivershidusbhidusbmouse.c của Linux kernel v3.13.6

TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI VIỆN ĐIỆN TỬ - VIỄN THÔNG BÁO CÁO BÀI TẬP LỚN Môn: Hệ điều hành Đề tài: Viết driver chuột usb cho Linux Giáo viên hướng dẫn: Phạm Doãn Tĩnh Sinh viên: MSSV Trần Sơn Tùng 20102506 Trần Tiến Thành 20102170 5/2014 Lời mở đầu Hiện nay, với sự phát triển ngày càng nhanh của hệ thống nhúng để đáp ứng lại nhu cầu thị trường, dễ dàng có thể thấy hệ điều hành Linux xuất hiện ở hầu hết các thiết bị có độ phức tạp cũng như khả năng đáp ứng cao. Việc tích hợp hệ điều hành lên hệ thống nhúng giúp đơn giản hóa quá trình thiết kế sản phẩm, rút ngắn thời gian cũng như chi phí xây dựng hệ thống vì các ứng dụng này được kế thừa sự ưu việt của một hệ điều hành nói chung và Linux nói riêng. Đó là sự nhỏ gọn, ổn định, thực thi nhanh, đơn giản hóa và khả năng can thiệp sâu vào phần cứng. Hơn thế nữa, cùng với cộng đồng sử dụng Linux rộng lớn trên khắp thế giới và các phần mềm mã nguồn mở đa dạng làm cho việc phát triển hệ thống Linux nhúng trở thành một chiến lược được các công ty lựa chọn hàng đầu. Mặt khác, chuẩn giao tiếp USB (Universal Series Bus) đã và đang trở thành một trong những chuẩn giao tiếp phổ biến nhất. Hiện tại, USB đã trở thành chuẩn kết nối cũng như phương thức truyền dữ liệu thân thuộc với người dùng công nghệ nhờ vào sự thuận tiện, độ bền và giá thành hợp lý của nó. Do đó chúng em quyết định chọn đề tài “Viết driver chuột USB cho hệ điều hành Linux” làm bài tập lớn cho môn học Hệ điều hành. Vì đây là một đề tài tương đối phức tạp và thời gian thực hiện có hạn, nên nhóm chúng em chỉ dừng lại ở mức độ đi sâu phân tích mã nguồn của hệ điều hành nhằm tìm hiểu cơ chế quản lý giao tiếp USB của Linux. Phần code được sử dụng nằm trong file /drivers/hid/usbhid/usbmouse.c của Linux kernel v3.13.6 I. Khái quát về giao thức USB Một thiết bị giao tiếp bằng chuẩn USB thực ra rất phức tạp. Nhưng may mắn là hệ điều hành Linux cung cấp cho ta những thư viện hỗ trợ khá đầy đủ, và điều đó đã giúp tiết kiệm được rất nhiều thời gian, công sức cũng như chi phí xây dựng một thiết bị như thế. Đa phần sự phức tạp của USB được hỗ trợ bởi USB Core của Linux. 1. Các thành phần cơ bản của giao thức USB a. Endpoint: Thành phần cơ bản nhất trong chuẩn giao tiếp USB. USB Endpoint truyền dữ liệu theo một hướng duy nhất, từ host đến device (gọi là OUT Endpoint) hoặc ngược lại (In Endpoint). Có 4 loại endpoint: - Controll: Controll endpoint dùng để truy cập các phần khác nhau trong thiết bị USB. Chúng thường được dùng để cài đặt thiết bị, lấy thông tin thiết bị, gửi lệnh đến thiết bị, hoặc lấy báo cáo trạng thái của thiết bị. - Interupt: Interupt endpoint dùng để truyền dữ liệu dung lượng nhỏ mỗi khi máy chủ truy vấn dữ liệu từ thiết bị. Loại endpoint này hay được sử dụng với những thiết bị như chuột hay bàn phím. Chúng cũng hay được dùng để gửi dữ liệu giữa các thiết bị với nhau, nhưng lượng dữ liệu truyền đi thường không lớn. Giao thức USB luôn đảm bảo có băng thông dự phòng cho loại endpoint này. - Bulk: Bulk endpoint dùng để truyền dữ liệu có dung lượng lớn. Loại endpoint này có kích thước lớn hơn nhiều so với interupt. Chúng được dùng cho loại thiết bị yêu cầu truyền dẫn dữ liệu kích thước lớn mà không được xảy ra mất mát dữ liệu. Chúng cũng không có băng thông dự trữ giống như interupt endpoint. Nếu không có đủ băng thông để truyền cả gói tin đi, dữ liệu sẽ được chia nhỏ. Loại endpoint này được sử dụng cho các thiết bị như máy in, ổ nhớ flash… - Isochorous: Isochorous endpoint dùng để truyền dữ liệu kích thước lớn, nhưng không yêu cầu sự đảm bảo dữ liệu toàn vẹn. Chúng được dùng cho các thiết bị chấp nhận sự mất mát trong truyền dữ liệu, đổi lại sự đảm bảo quá trình được liên tục, như các thiết bị truyền dẫn thời gian thực như video và audio… Cấu trúc dữ liệu của endpoint được định nghĩa trong struct usb_host_endpoint của Linux kernel. Trong đó thông tin thực sự của endpoint được chứa trong struct usb_endpoint_descriptor. struct usb_host_endpoint { struct usb_endpoint_descriptor desc; struct usb_ss_ep_comp_descriptor ss_ep_comp; struct list_head urb_list; void * hcpriv; struct ep_device * ep_dev; unsigned char * extra; int extralen; int enabled; int streams; }; Các thông số cần quan tâm: - bEndpointAddress: địa chỉ của endpoint, trong đó có 8 bit dùng mã hóa hướng của endpoint là IN hay OUT. - bmAttributes: Dùng định nghĩa loại endpoint là kiểu nào trong 4 kiểu controll, bulk, interupt hay isochorous. - wMaxPacketSize: Kích thước tối đa gói tin mà endpoint có thể chuyển đi. Nếu gói tin cần chuyển lớn hơn giá trị này thì nó sẽ bị chia thành các gói có kích thước tương đương. - bInterval: Nếu endpoint là loại interupt thì biến này sẽ xác định khoảng thời gian giữa các lần gửi request từ host đến device (đo bằng mili giây). b. Interface: Tập hợp các endpoint gọi là interface. Mỗi interface thể hiện một chức năng cơ bản duy nhất của thiết bị, ví dụ như ổ flash, hay bàn phím. Một thiết bị có thể có nhiều interface. Một interface có nhiều thiết lập, với thiết lập ban đầu được đánh số 0. Thiết lập khác nhau có thể dùng điều khuyển endpoint theo các cách khác nhau… Interface được định nghĩa trong Linux kernel bằng struct usb_interface. Các thông số cần quan tâm: - struct usb_host_interface *altsetting: Một mảng chứa các phần tử kiểu interface tương ứng với mỗi thiết lập khác nhau. Mỗi struct usb_host_interface chứa một tập hợp các endpoint đã được định nghĩa trong usb_host_endpoint. - unsigned num_altsetting: số thiết lập khác nhau của interface, được trỏ đến bởi con trỏ *altsetting. - struct usb_host_interface *cur_altsetting: con trỏ trỏ đến thiết lập hiện tại của struct usb_interface { struct usb_host_interface * altsetting; struct usb_host_interface * cur_altsetting; unsigned num_altsetting; struct usb_interface_assoc_descriptor * intf_assoc; int minor; enum usb_interface_condition condition; unsigned sysfs_files_created:1; unsigned ep_devs_created:1; unsigned unregistering:1; unsigned needs_remote_wakeup:1; unsigned needs_altsetting0:1; unsigned needs_binding:1; unsigned reset_running:1; unsigned resetting_device:1; struct device dev; struct device * usb_dev; atomic_t pm_usage_cnt; struct work_struct reset_ws; }; interface. - int minor: Thiết bị trong hệ thống được truy cập bằng tên. Tên thiết bị bao gồm 2 phần là major và minor. major dùng xác định driver cho thiết bị, còn minor dùng để xác định chính xác thiết bị đang xét. c. Configuration: là tập hợp các interface. Một thiết bị có thể có nhiều configuration và chuyển đổi qua lại giữa chúng. Chỉ có một configuration được phép sử dụng tại mỗi thời điểm. Linux không thể hỗ trợ các thiết bị sử dụng đồng thời nhiều configuration (tuy nhiên các thiết bị đó rất hiếm). Tóm lại: - Một thiết bị có thể có nhiều configuration. - Một configuration có thể có nhiều interface. - Một interface có thể có nhiều setting. - Interface không có hoặc có thể có nhiều endpoint. d. Sysfs: do tính phức tạp trong cấu trúc vật lý của thiết bị USB, việc mô tả thiết bị trong lập trình cũng không đơn giản. Sysfs được sử dụng như một trình quản lý dữ liệu của Linux giúp việc quản lý những thiết bị như thế này được đơn giản hơn. Mô tả vật lý thiết bị USB cũng như interface của nó được mô tả như những thiết bị độc lập trong sysfs. 2. Mô hình giao thức USB a. Chuẩn tín hiệu Chuẩn USB sử dụng 4 đường tín hiệu trong đó có 2 đường cấp nguồn DC (VBUS-5V và GND). 2 đường còn lại là một cặp tín hiệu vi sai (D+ và D-) cho phép truyền dữ liệu. Cặp dây tín hiệu này được nối xoắn ở bên trong nên có khả năng chống nhiễu tốt. b. Mô hình mạng Các thiết bị hoạt động theo chuẩn USB được kết nối với nhau theo đồ hình mạng hình sao phân cấp. Trung tâm của mỗi hình sao này là các Hub. Trong đồ hình như vậy, các thiết bị USB được chia làm 3 loại chính: - USB Host: thiết bị đóng vai trò điều khiển toàn bộ mạng USB (có thể lên tới tối đa 126 thiết bị). Ví dụ như trên máy tính, USB Host được gắn trên mainboard. Để giao tiếp và điều khiển các USB device, USB Host controller cần được thiết kế tích hợp với USB RootHub (Hub mức cao nhất). Vai trò của thiết bị USB Host: • Trao đổi dữ liệu với các USB Device • Điều khiển USB Bus:  Quản lý các thiết bị cắm vào hay rút ra khỏi Bus USB qua quá trình điểm danh (Enumeration)  Phân xử, quản lý luồng dữ liệu trên Bus, đảm bảo các thiết bị đều có cơ hội trao đổi dữ liệu tùy thuộc vào cấu hình của mỗi thiết bị. - USB Device: là các thiết bị đóng vai trò như các slave giao tiếp với USB Host. Xin lưu ý một điều hết sức quan trọng đó là các thiết bị này hoàn toàn đóng vai trò bị động, không bao giờ được tự ý gửi gói tin lên USB Host hay gửi gói tin giữa các USB Device với nhau, tất cả đều phải thông qua quá trình điều phối của USB Host. Các bạn sẽ hiểu cơ chế này rõ hơn trong phần truyền thông của chuẩn USB. Chức năng của thiết bị USB Device: • Trao đổi dữ liệu với USB Host • Phát hiện gói tin hay yêu cầu từ USB Host theo giao thức USB. - USB Hub: đóng vai trò như các Hub trong mạng Ethernet của chúng ta. Cấp nguồn cho các thiết bị USB c. Host view: d. Device view: e. Kịch bản hoạt động Quá trình hoạt động của chuẩn USB có thể được chia làm hai giai đoạn chính: - Quá trình điểm danh: là quá trình USB Host phát hiện các thiết bị cắm vào và rút ra khỏi đường USB Bus. Mỗi khi một thiết bị tham gia vào Bus USB, USB Host sẽ tiến hành đọc các thông tin mô tả (Description) của USB Device, từ đó thiết lập địa chỉ (NodeID) và chế độ hoạt động tương ứng cho thiết bị USB Device. Các địa chỉ sẽ được đánh từ 1->126 nên về lý thuyết, chuẩn USB cho phép kết nối 126 thiết bị vào đường Bus. Khi thiết bị rút ra khỏi đường Bus, địa chỉ này sẽ được thu hồi. - Quá trình truyền dữ liệu: Đứng ở góc độ mức hệ thống, các Interface chính là các dịch vụ khác nhau mà thiết bị đó cung cấp còn các Endpoint chính là các cổng cần thiết cho mỗi dịch vụ. Tương ứng với khái niệm trong kiến trúc TCP/IP, ví dụ giao thức FTP là giao thức sử dụng để truyền file sẽ sử dụng hai cổng 20,21. Trong khi đó giao thức HTTP lại sử dụng port 80, giao thức Telnet sử dụng port 23. Thực tế các Endpoint cũng như các Port trong chuẩn TCP/IP đóng vai trò như các bộ đệm truyền/nhận dữ liệu. Nhờ việc sử dụng nhiều bộ đệm mà các quá trình truyền thông được tiến hành song song và cho tốc độ cao hơn, bên cạnh đó giúp cho việc phân tách các dịch vụ khác nhau. Với chuẩn USB, các thiết bị được thiết kế với tối đa là 16 Endpoint. II. USB driver 1. Khung chương trình của một USB driver bất kì 2. Xây dựng driver cho chuột USB a. Thư viện b. Khởi tạo Cấu trúc sau đây dùng mô tả thiết bị chuột USB – là 1 input device giao tiếp bằng urb. - Name: tên thiết bị - Phys: chuỗi định danh thiết bị - *usbdev: con trỏ dùng để trỏ tới thiết bị đã gửi urb đi. - *dev: con trỏ dùng mô tả 1 thiết bị đầu vào. - *irq: con trỏ kiểu urb – USB request block. USB code dùng urb để giao tiếp với các struct usb_<tên thiết bị> { }; /* Chứa thông tin thiết bị */ static struct usb_device_id <tên thiết bị>_table [] = { { USB_DEVICE(ML_VENDOR_ID, ML_PRODUCT_ID) }, { } }; /* Chứa id thiết bị*/ static int <tên thiết bị>_open(struct inode *inode, struct file *file) { /* open syscall */ } static int <tên thiết bị>_release(struct inode *inode, struct file *file) { /* close syscall */ } static ssize_t <tên thiết bị>_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos); { /* write syscall */ } static struct file_operations <tên thiết bị>_fops = { .owner = THIS_MODULE, .write = ml_write, .open = ml_open, .release = ml_release, }; static int <tên thiết bị>_probe(struct usb_interface *interface, const struct usb_device_id *id) { /* hàm này được gọi khi thiết bị được kết nối với máy tính */ } static void <tên thiết bị>_disconnect(struct usb_interface *interface) { /* hàm này được gọi khi thiết bị được rút khỏi máy tính */ } static struct usb_driver ml_driver = { .name = "missile_launcher", .id_table = ml_table, .probe = ml_probe, .disconnect = ml_disconnect, }; static int __init usb_<tên thiết bị>_init(void) { /* Khởi tạo */ } static void __exit usb_<tên thiết bị>_exit(void) { /* Giải phóng tài nguyên */ } module_init(usb_<tên thiết bị>_init); module_exit(usb_<tên thiết bị>_exit); #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> struct usb_mouse { char name[128]; char phys[64]; struct usb_device *usbdev; struct input_dev *dev; struct urb *irq; signed char *data; dma_addr_t data_dma; }; thiết bị USB. Urb được dùng để gửi đi cũng như nhận dữ liệu từ endpoint của thiết bị theo phương thức không đồng bộ. Chu kì của 1 urb như sau: • Được tạo bởi usb device driver • Được gán vào một endpoint của driver • Được gửi tới USB core bởi driver • Được gửi tới host controller driver bởi core • Được xử lý bởi host controller driver rồi thực hiện truyền dữ liệu về device • Khi hoàn tất thủ tục request, host controller driver sẽ gửi thông báo đến device. - *data: biến dữ liệu. - *data_dma: biến dữ liệu theo cơ chế DMA (Direct Memory Access) c. Interupt Hàm sau đây được gọi để xử lý ngắt. - *mouse: con trỏ mô tả thiết bị kiểu mouse như đã được định nghĩa ở khởi tạo. - *data: con trỏ dữ liệu. - *dev: con trỏ kiểu input device. - status là 1 biến kiểu nguyên thuộc struct urb. Khi urb được xử lý hoặc hoàn tất, status sẽ được cập nhật giá trị tương ứng với trạng thái hiện tại của urb. Giá trị biến status sau đó sẽ được truyền vào hàm xử lý ngắt. 1 cấu trúc điều kiện sẽ kiểm tra giá trị biến này. • TH1: Nếu status = 0, tức là quá trình truyền urb thành công. • TH2: Nếu status = ESHUTDOWN, tức là đã xảy ra lỗi với USB host controller driver khiến cho nó bị vô hiệu hóa, hoặc là do urb được gửi sau khi thiết bị đã ngắt kết nối. Lỗi này cũng xảy ra nếu configuration bị thay đổi khi urb đang được gửi. • TH3: Nếu status = ECONNRESET, thì urb bị ngắt kết nối bởi hàm usb_unlink_urb, biến transfer_flags trong urb được set giá trị bằng URB_ASYNC_UNLINK. • TH4: Nếu status = ENOENT, thì urb bị dừng lại bởi hàm usb_kill_urb. - Nếu status rơi vào 3 trường hợp lỗi thì chương trình sẽ thoát khỏi hàm ngắt. - Nếu status rơi vào trường hợp đầu tiên, chương trình sẽ thoát khỏi cấu trúc switch và nhảy đến khối lệnh tiếp theo: Các lệnh trên gửi các tín hiệu ngắt khi các nút tương ứng được bấm, hoặc lấy tọa độ tương đối của chuột. static void usb_mouse_irq(struct urb *urb) { struct usb_mouse *mouse = urb->context; signed char *data = mouse->data; struct input_dev *dev = mouse->dev; int status; switch (urb->status) { case 0: /* success */ break; case -ECONNRESET: /* unlink */ case -ENOENT: case -ESHUTDOWN: return; /* -EPIPE: should clear the halt */ default: /* error */ goto resubmit; } input_report_key(dev, BTN_LEFT, data[0] & 0x01); //chuột trái input_report_key(dev, BTN_RIGHT, data[0] & 0x02); //chuột phải input_report_key(dev, BTN_MIDDLE, data[0] & 0x04); //chuột giữa input_report_key(dev, BTN_SIDE, data[0] & 0x08); //chuột bên input_report_key(dev, BTN_EXTRA, data[0] & 0x10); //chuột phụ input_report_rel(dev, REL_X, data[1]); //hoành độ input_report_rel(dev, REL_Y, data[2]); //tung độ input_report_rel(dev, REL_WHEEL, data[3]); //tọa độ núm xoay input_sync(dev); //đồng bộ dữ liệu với input device [...]... static struct usb _driver usb_ mouse _driver = { name = "usbmouse", probe = usb_ mouse_probe, disconnect = usb_ mouse_disconnect, id_table = usb_ mouse_id_table, }; module _usb _driver( usb_ mouse _driver) ; Tài liệu tham khảo (1) Jonathan Corbet, Alessandro Rubini, Greg Kroah-Hartman Linux Device Drivers” (2) http://matthias.vallentin.net/blog/2007/04/writing-a -linux- kernel -driver- for-an-unknown- usb- device/ (3)... trỏ kiểu thiết bị USB Một USB driver thường phải chuyển định dạng dữ static int dữ liệu được truyền từ struct usb_ interface *intf, const struct usb_ device_id liệu khi usb_ mouse_probe(struct usb_ interface sang struct usb_ device để thuận *id) { tiện cho USB core khi gọi hàm Để làm việc đó ta sử dụng hàm interface_to_usbdev struct usb_ device *dev = interface_to_usbdev(intf); struct usb_ host_interface... cơ bản phục vụ cho chương trình của driver Ngoài ra 1 số hàm cũng như cấu trúc phụ cũng được dùng nhằm khai báo thông tin driver để phục vụ cho việc quản lý trong sysfs static struct usb_ device_id usb_ mouse_id_table [] = { { USB_ INTERFACE_INFO (USB_ INTERFACE_CLASS_HID, USB_ INTERFACE_SUBCLASS_BOOT, USB_ INTERFACE_PROTOCOL_MOUSE) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, usb_ mouse_id_table);... urb sẽ usb_ submit_urb (urb, GFP_ATOMIC); status = được chuyển thành trạng thái đã gửi, bằng cách gọi đến hàm if (status) int usb_ submit_urb(struct urb *urb, int mem_flags); tại đây cờ mem_flags được sử dev_err(&mouse->usbdev->dev, "can't resubmit dụng để thiết lập phương thức phân bố bộ intr, %s-%s/input0, status %d\n", nhớ đệm cho USB core Khi urb được mouse->usbdev->bus->bus_name, mouse->usbdev->devpath,... phát bộ nhớ hoặc bộ đệm - mouse->data = usb_ alloc_coherent(dev, 8, GFP_ATOMIC, &mouse->data_dma); cho chuột (!mouse->data) vào if hoặc thiết bị đầu //(2) fail1: giải phóngfail1; dành cho thiết bị đầu vào cũng như chuột, và trả về lỗi goto bộ nhớ fail1: –ENOMEM input_free_device(input_dev); Bắt đầu tạo một urb mới cho chuột sử dụng kfree(mouse); mouse->irq = usb_ alloc_urb(0, chưa được cấp phát Nếu urb... truyền urb static void usb_ mouse_close(struct input_dev *dev) return 0; { } struct usb_ mouse *mouse = input_get_drvdata(dev); g Disconnect usb_ kill_urb(mouse->irq); Hàm này được gọi khi chuột được ngắt kết nối với máy tính - } Khi thiết bị được ngắt kết nối thì việc lấy lại dữ liệu từ interface là rất cần thiết static void usb_ mouse_disconnect(struct usb_ interface *intf) {Hàm usb_ get_intfdata có chức... được cấp được làm rỗng - input_dev thực usb_ rcvintpipe(dev, endpoint->bEndpointAddress); Lệnh (1) = input_allocate_device(); thiết bị đầu vào //(1) pipe = hiện phân bố bộ nhớ cho if (!mouse || !input_dev) - Lệnh (2) thực usb_ maxpacket(dev, đệm theo cơ chế DMA cho chuột maxp = hiện phân bố bộ nhớ pipe, usb_ pipeout(pipe)); mousegoto nhảy = kzalloc(sizeof(struct usb_ mouse), GFP_KERNEL); - Chương trình... input_set_drvdata(input_dev, mouse); Là 1 lời gọi hệ thống để USB core gọi khi cần Chức năng lời gọi này là lấy dữ liệu của thiết bị và gửi đi cùng với urb static int usb_ mouse_open(struct input_dev *dev) { struct usb_ mouse *mouse = input_get_drvdata(dev); f Close syscall mouse->irq->dev = mouse->usbdev; GFP_KERNEL)) return -EIO; Là 1 lời gọi hệ thống tương tự Open syscall if (usb_ submit_urb(mouse->irq, Chức năng... có chức năng như thế, nó sẽ lấy lại những dữ liệu struct usb_ mouse *mouse = usb_ get_intfdata (intf); - đã được cấp phát trước đó bởi hàm usb_ set_intfdata Sau khi usb_ set_intfdata(intf, NULL); đã lấy lại dữ liệu, hàm usb_ set_intfdata sẽ thiết lập dữ liệu về mức NULL if (mouse) { nhằm tránh những sai sót phát sinh trong quá trình truy nhập dữ liệu usb_ kill_urb(mouse->irq); input_unregister_device(mouse->dev);... input_unregister_device(mouse->dev); - Khối lệnh tiếp theo sẽ giải phóng tài nguyên cho thiết bị Bao gồm: usb_ free_urb(mouse->irq); • Hủy urb usb_ free_coherent(interface_to_usbdev(intf), 8, mouse->data, • Hủy đăng kí thiết mouse->data_dma); bị kfree(mouse); • Giải phóng tài nguyên urb Khi lệnh usb_ free_urb được gọi ra, struct urb đó sẽ bị } } xóa và driver sẽ không thể truy nhập urb đó được nữa • Giải phóng bộ nhớ và . *intf) { struct usb_ mouse *mouse = usb_ get_intfdata (intf); usb_ set_intfdata(intf, NULL); if (mouse) { usb_ kill_urb (mouse- >irq); input_unregister_device (mouse- >dev); usb_ free_urb (mouse- >irq); usb_ free_coherent(interface_to_usbdev(intf),. BIT_MASK(REL_WHEEL); input_set_drvdata(input_dev, mouse) ; input_dev->open = usb_ mouse_ open; input_dev->close = usb_ mouse_ close; usb_ fill_int_urb (mouse- >irq, dev, pipe, mouse- >data, (maxp > 8 ? 8 : maxp), usb_ mouse_ irq, mouse, . 0; } static void usb_ mouse_ close(struct input_dev *dev) { struct usb_ mouse *mouse = input_get_drvdata(dev); usb_ kill_urb (mouse- >irq); } static void usb_ mouse_ disconnect(struct usb_ interface *intf) { struct

Ngày đăng: 08/07/2014, 21:07

Tài liệu cùng người dùng

Tài liệu liên quan