CÁC KHÓ KHĂN KHI PHÁT TRIỂN DRIVER 40-

Một phần của tài liệu đồ án công nghệ thông tin USB driver trên hệ điều hành Linux Red Hat (Trang 40)

Phát triển driver là một công việc kho khăn, khi viết một driver mới cần các kiến thức:

+ OS internals (khác nhau cho mỗi hệ điều hành mà HW chạy trên đó) + OS APIs (DDK, DDI, ..)

+ Bus protocols and APIs (PCI, USB, PCMCIA, ...) + Drivers không tương thích giữa các OS

+ Kernel Level Debugging (WinDBG, SoftIce, ..) - “The blue screen of death”, phần cứng chưa được kiểm tra cẩn thận

3.3. QUÁ TRÌNH PHÁT TRIỂN MỘT DRIVER

Driver cũng như các phần mềm khác, cũng có vòng đời phát triển của nó. Vòng đời phần mềm của driver được mô tả theo lược đồ sau:

Gồm 5 giai đoạn:

1. HW Testing là giai đoạn kiểm tra phần cứng

2. Code Development là giai đoạn viết mã chưuơng trình cho phần cứng 3. Debug Driver là giai đoạn kiêm tra mã chưưong trình và gỡ rối

4. Tuning Performance là giai đoạn hiệu chỉnh các tham số để có được driver tốt nhất cho thiết bị

5. Driver Distributution & Deployment triển khai driver lên hệ điều hành tương ứng

Quá trình này lặp lại đối với mỗi hệ điều hành mới và thiết bị mới

3.4. GIỚI THIỆU VỀ LINUX DRIVER

Linux Driver là một thành phần của kernel, dùng để giao tiếp với các thiết bị phần cứng. Điều này co nghĩa là, nếu trong kernel co hỗ trợ các hàm giao tiếp với phần cứng loại nào thì người phát triển hệ thống có thể sử dụng để giao tiếp với các thiết bi phần cứng đó.

Mặt khác, do tinh mở từ trong kernel của Linux, nên trong cộng dồng nguồn mở Linux có những thành viên chuyên phát triển kernel cho các thiết bị, họ là nhung người hỗ trợ phần driver cho kernel. Bên cạnh đó còn có rất nhiều các người chuyên làm nhiệm vụ gỡ lỗi, phát hiện lỗi hệ thống. Vì vậy có thể nói rằng, Linux driver được phát triển mở và hỗ trợ phong phú các thiết bị phần cứng khác nhau. Bất cứ một loại thiết bị mới nào ra đời mà trong cộng đồng nguồn mở Linux có nhu cầu sử dụng thì sẽ những thành viên chuyên phát triển cho thiết bị sẽ phát triển các giao diện, các hàm hỗ trợ cho thiết bị này và tích hợp vào trong kernel phiên bản mới hơn.

USB là một bus phổ dụng, vì vậy, ngay từ phiên bản 2.0, kernel đã hỗ trợ các giao diện và hàm cho USB.

CHƯƠNG 4 USB DRIVER

4.1. THIẾT BỊ KÝ TỰ VÀ THIẾT BỊ KHỐI

Linux hỗ trợ nhiều các thiết bị phần cứng khác nhau, điều này có nghĩa là cũng có rất nhiều các phần mềm tương ứng (các driver) để hỗ trợ cho các thiết bị phần cứng đó.

Trên Linux , các thiết bị phần cứng được coi như ẩn với người dung nhưng cung cấp đầy đủ chức năng của các thiết bị đó. Điều này được thực hiện nhờ việc coi các device như các file đặc biệt, nó cho phép phát triển các chương trình ứng dụng có thể truy cập nhiều thiết bị khac nhau với cùng một lời gọi hệ thống, ví dụ như write (ghi) và read (đọc). Để xử lý vấn đề này các driver được tích hợp như một phần của nhân Linux (Linux kernel), điều này cung cấp một điều khiển thốn nhất từ trong nhân hệ thống.

Để thực hiện việc coi device driver như là một phần nhân của Linux, chúng ta sử dụng mọt trong các hàm sau:

int register_chrdev(unsigned int major, cosnt char * name,

struct file_operations * fops); int register_blkdev(unsigned int major,

cosnt char * name,

struct file_operations * fops);

file_operations được đưa vào trong tham số mảng chrdevr[] (đối với character driver) và blkdevr[] (đối với block driver)

Các phần cứng được hỗ trợ trên Linux rất phong phú rất Trên Linux các thiết bị chia lam 2 loại chính

+ Thiết bị khối

Là loại thiết bị có thể truy cập ngẫu nhiên, điều này có nghĩa là các khối bất ky có thể đọc ghi tại mọi thời điểm

+Thiết bị ký tự là loại thiết bị ma việc đọc va ghi theo tuần tự vì vậy có thể truy cập không cần bộ đệm

4.2. POLLING & INTERUPTS

Khi đồng bộ giữa bộ vi xử lý (CPU) và các thiết bị phần cứng, có một số yêu cầu cần thực hiện. Vì bản chất sự truy cập phần cứng thì chậm hơn nhiểu so với tốc độ xử lý của CPU. Vì vậy đã có một số kỹ thuật được áp dụng để kết nối các thiết bị phần cứng tới CPU.

+ Polling mode + Interrupt mode + Interrupt sharing + Bottom halvels + Task queues + DMA mode 4.2.1. Polling mode

Polling mode là cách CPU sẽ truy vấn lần lượt các thiết bi phần cứng đang kết nối với máy tính xem nó co sẵn sàng làm việc không? Nếu thiết bị sẵn sàng thì quá trình trao đổi dữ liệu diễn ra. Cách nay chậm nhưng thích hợp với các thiết bị có vào ra chậm.

4.2.2. Interrupt mode

Khi CPU đang thực hiện tác vụ, ngẫu nhiên, ngoại vi thứ i xin phục vụ bằng cách phát ra tín hiệu IRQ(i) (Interrupt Request) đến CPU.

Nói chung, CPU sẽ ngừng xử lý tác vụ đang thục hiện và cất ngữ cảnh vào Stack Mem, rồi tìm địa chỉ của phục vụ ngắt tng ứng (Interrupt Service Routine - ISR) để thực hiện.

Sau khi thực hiện xong ISR, gặp lệnh iret (reti...), CPU khôi phục lại ngữ cảnh của tác vụ đang thuc hiện dở và tiếp tục thực hiện.

4.2.3. Interrupt sharing

Do số lượng IRQ của một máy tính la có hạn, vì vậy có thể thiết kế chương trình để nhiều thiết bị có thể sử dụng chung một IRQ

4.2.4. Bottom halvels

Nếu thường xuyên xảy ra tình trạng không cần thực hiện ngay hàm sau khi ngắt trong khi chức năng đang thực hiên dở cần thuẹc hiện hơn, trong trường hợp này một bottom halvels được tạo ra.

4.2.5. Task queues

Trong trường hợp bottom halvels được tạo ra thì khó để kiếm soát tác vụ nao quan trọng hơn, vì vậy mỗi tác vụ được gán cho 1 số nguyên trong khoảng 32, task queues được tạo ra và coi như một mở rộng của bottom halvels

Là cách trao đổi dữ liệu trực tiếp giữa device và bộ nhớ không thông qua bộ vi xử lý.

4.3. USB TOPOGY

Mỗi hệ thống bus USB bao gồm một host controller và một root hup, trong đó, root hup được hiểu như là điểm mắc gốc của các device và các hup khác, host controller la thành phần điều khiển, phát hiện các kết nối và xử lý các urb từ các device.

4.4. CÁC KIỂU LUỒNG ĐIỀU KHIỂN

Trên USB có 4 kiểu luồng điều khiển

+ Control Transfers: Được sử dụng để cấu hình thiết bị lúc gắn kết và có thể sử dụng cho các mục đích khác bao gồm cả diều khiển các pipes của thiết bị. Truyền theo phương pháp này thì an toàn, dữ liệu không bị mất. Điều khiển được thực hiện thông qua các lệnh

GET STATUS

CLEAR FEATURE

SET ADDRESS

GET DESCRIPTOR

SET DESCRIPTOR

GET CONFIGURATION

+ Bulk Data Transfers: sử dụng khi truyền dữ liệu không chặt chẽ về rang buộc như máy in, sanner… tuỳ thuọc vào tình trang bus mà việc truyền có hiệu qua không

+ Interrupt Data Transfers:được sử dụng cho các mục đích của người sử dụng hoặc có thông tin phản hồi

+ Isochronous Data Transfers: gọi là truyền luồng theo thời gian ( streaming real time transfers) như âm thanh, hình ảnh

4.5. CẤU HÌNH THIÊT BỊ

Mỗi khi thiết bị (device) được gắn vào hệ thống thì nó được đánh số và các thông tin description được đọc. Description là các thông tin mô tả về thiết bị và các thuộc tính của nó

+ Device Descriptor chứa thông tin về device. Một device thì có một Descriptor

+ Configuration Descriptor xác định các thông tin cấu hình, môt device thì có một hay nhiều configuration descriptors.

+ Interface Descriptor mô tả giao diện đối với một configuration descriptor + Endpoint Descriptor chứa các thông tin được yêu cầu bởi host để lấy được băng thông của mỗi điểm truy cập cuối.

+ String Descriptors cung cấp thêm các thồn tin có thê đọc được dưới ở Unicode format.

Một USB device được đăng ký và gỡ bỏ khỏi host như một hệ thống con. Mỗi USB device driver cần đăng ký một file, một số chính (đối với USB luôn luôn la 180) và một số phụ từ 0 đến 15.

+ Cấu trúc dữ liệu lưu các thông tin về USB driver

struct usb_driver { const char *name;

void * (*probe)(struct usb_device *, unsigned int, const struct usb_device_id *id_table);

void (*disconnect)(struct usb_device *, void *); struct list_head driver_list;

struct file_operations *fops; int minor;

struct semaphore serialize;

int (*ioctl) (struct usb_device *dev, unsigned int code, void *buf);

const struct usb_device_id *id_table; };

Trong đó

- name: thường là tên module

- probe: điểm truy cập của probe function.

- disconnect: điểm truy cập của disconnect function.

- driver list: cho sử dụng bên trong driver - khởi tạo là NULL,NULL - fops: các thao tác đối với a driver

- minor: so phụ được gán cho device này device - serialize:

- ioctl: - id table:

+ 2 điểm truy cập các hàm chức năng

probe được gọi khi một device được kết gắn vào hệ thống disconnect được gọi khi một device được tháo ra khỏi hệ thống

void *probe(struct usb_device *dev, unsigned int interface, const struct usb_device_id *id_table)

{

struct driver_context *context;

if (dev->descriptor.idVendor == 0x0547 && dev->descriptor.idProduct == 0x2131 && interface == 1 ) { context=allocate_driver_resources(); return context; } return NULL;

}

static void dabusb_disconnect (struct usb_device *usbdev, void *drv_context)

{

struct driver_context *s = drv_context; s->remove_pending = 1; wake_up (&s->wait); sleep_on (&s->remove_ok); free_driver_resources(s); } + Các hàm hỗ trợ từ host

- int usb register(struct usb driver *drv);

dùng để dăng ký một USB device driver mới như một hệ thống con của host

- void usb deregister(struct usb driver *drv);

dùng để gỡ bỏ một USB device driver ra khỏi host host

- void usb driver claim interface(struct usb driver *driver, struct usb interface *iface, void *drv context);

dùng để đăng ky USB sử dụng nhiều giao diện khác nhau - int usb interface claimed(struct usb interface *iface);

dung để kiểm tra xem device driver khác đã sử dụng giao dien này chưa

- void usb driver release interface(struct usb driver *driver, struct usb interface *iface);

giải phóng tất cả các giao diện đã được đăng ký trong hàm probe

- const struct usb device id *usb match id( struct usb device *dev, struct usb interface *interface, const struct usb device id *id);

+ Cấu hình Descriptor cho device:

Mỗi device có một cấu trúc phân cấp các thông tin về device và thuộc tính của nó

struct usb_device{ ...

struct usb_config_descriptor *actconfig;/* the active configuration */

...

struct usb_device_descriptor descriptor;/* Descriptor */ struct usb_config_descriptor *config; /* All of the configs */ }

usb_device là gốc truy cập của tất cả các descriptor

+ Truy cập tất cả các descriptor

for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { struct usb_config_descriptor *cfg = &dev->config[i]; ...

}

+ Truy cập tất cả các interface của một Configuration

for (j = 0; j < cfg->bNumInterfaces; j++) {

struct usb_interface *ifp = &cfg->interface[j]; ...

}

+ Truy cập tất cả các interface thay thế của một Configuration

for (k = 0; k < ifp->num_altsetting; k++) {

struct usb_interface_descriptor *as = &ifp->altsetting[k]; ...

}

+ Truy cập tất cả các endpoint descriptors của một interface

for(l = 0; l < as->bNumEndpoints; l++) {

struct usb_endpoint_descriptor *ep=&as->endpoint[k]; ...

}

+ Các hàm thiết lập, gỡ bỏ Desctiptor, Interface, Configuration

- int usb set_configuration(struct usb device *dev, int configuration); thiết lập một configuration

- int usb set_interface(struct usb device *dev, int interface, int alternate);

thiết lập một interface thay thế

- int usb_ get_ device descriptor(struct usb device *dev); lấy các thông tin về usb device

- int usb get descriptor(struct usb device *dev, unsigned char desctype, unsigned char descindex, void *buf, int size);

lấy các thông tin về descriptors

- int usb get string(struct usb device *dev, unsigned short langid, unsigned char index,

void *buf, int size);

lấy các string đã được đánh chỉ mục cho một device, configuration hay interface

- int usb string(struct usb device *dev, int index, char *buf, size t size);

lấy các string đã được đánh chỉ mục cho một device,

configuration hay interface nhưng chuyển đổi từ Unicode sang ASCII

- int usb get status(struct usb device *dev, int type, int target, void *data)

lấy trạng thái của device

+Một số hàm khác

- int usb clear halt(struct usb device *dev, int pipe); - int usb get protocol(struct usb device *dev, int ifnum); - int usb set protocol(struct usb device *dev, int protocol, - int usb get report(struct usb device *dev, unsigned char type, unsigned char id,

int ifnum, void *buf, int size);

- int usb set idle(struct usb device *dev, int ifnum, int duration, int report id);

USB device sử dụng một cấu trúc URB để chuyển tải các yêu cầu tới host: cấu trúc URB

struct urb {

spinlock_t lock; void *hcpriv;

struct list_head urb_list; struct urb *next;

struct usb_device *dev; unsigned int pipe; int status;

unsigned int transfer_flags; void *transfer_buffer; dma_addr_t transfer_dma; int transfer_buffer_length; int actual_length; int bandwidth;

unsigned char *setup_packet; dma_addr_t setup_dma; int start_frame; int number_of_packets; int interval; int error_count; int timeout;

void *context;

usb_complete_t complete;

struct iso_packet_descriptor iso_frame_desc[0]; };

Các hàm hỗ trợ chuyển URB tới host là - urb t usb_alloc_urb(int iso packets); - void usb free urb (purb t purb); - int usb submit urb(purb t purb); - int usb unlink urb(purb t purb);

USB DRIVER CHO FLASH MEMMORY

5.1. GIỚI THIỆU VỀ FLASH MEMMORY

Flash Memmory là loại thiết bị lưu trữ dùng công nghệ EEPROM, được thiết kế theo chuẩn bus vào ra USB. Do tính tiện dụng và khả năng cơ động của nó, Flash Memmory ngày càng được sủ dụng và ứng dụng rộng rãi. Trong phần đồ án tốt nghiệp này, em xin được trình bày về cách thức xây dựng một driver cho flash memmory từ 64 Mb đến 256 Mb.

Việc xây dựng USB driver cho flash memmory cũng như các USB driver khác, vì vậy em chỉ nêu ra các khác biệt

5.2. CÁC SƠ ĐỒ THỰC HIỆN CHOTRÊN USB DRIVER CHO FLASH MEMMORY

Sơ đồ khối quan trọng nhất là sơ đồ thực hiện trong hàm probe

Khoá con trỏ tới device

Xác định lại các tham số

Khởi toạ lại thiết bị

Mỏ khoá tới device

Xác định bộ nhớ và khởi tạo

Xác định URB

Xác định các tham số

Tạo số thứ tự cho device

Xác định các hàm xử lý prôtl

Đăng ký

Xác định các hàm xử lý prôtl

Kiêm tra xem device đã tồn tại chưa

Lấy các Interface

Kiểm tra xem hệ thống có hỗ trọ không Lấy các tham số về device

5.3. CÁC CẤU TRÚC DỮ LIỆU DÙNG TRÊN USB DRIVER CHO FLASH MEMMORY

Để xây dựng driver, cấu trúc quan trọng nhất luu toàn bộ thông tin về driver trong quá trình làm việc la cấu trúc us_data bao gồm các thành phần sau

Struct us_data * next;

Struct semaphore dev_semaphore; Struct usb_device * pusb_dev;

unsigned int flags;

char vendor[32]; char product[32]; char serial[32]; char * transport_name; char * protocol_name; u8 subclass; u8 protocol; u8 max_lun; u8 ifnum; u8 ep_in; u8 ep_out; Struct usb_endpoint_descriptor * ep_int;

Trans_cmnd transport; Trans_reset transport_reset; proto_cmnd proto_handler; GUID(guid);

Struct Scsi_Host * host; Scsi_Host_Template htmplt;

int host_number; int host_no; Scsi_Cmnd * srb;

atomic_t abortcnt; Scsi_Cmnd * queue_srb; int action;

pid_t pid; Struct semaphore ip_waitq; atomic_t ip_wanted[1]; Struct semaphore irq_urb_sem; Struct urb * irq_urb; unsigned char irqbuf[2]; unsigned char irqdata[2]; Struct semaphore current_urb_sem; Struct urb * current_urb; Struct completion current_done; unsigned int tag;

Struct semaphore sema; struct completion notify;

spinlock_t queue_exclusion; Struct us_unusual_dev * unusual_dev; Void * extra;

Cấu trúc lưu giữ toàn bộ các thông tin về device đang làm việc. Trong đó next: là device tiếp theo

dev_semaphore: để bảo vệ pusb_dev pusb_dev: là device hiện tại

flags: cờ khởi động

vendor: là tên nhà cung cấp product:

serial:

transport_name tên của hàm vận chuyển protocol_name: tên của giao thức

subclass: protocol: max_lun:

ifnum: số lượng giao thức ep_in: bulk in endpoint ep_out: bulk out endpoint

struct usb_endpoint_descriptor *ep_int; /* interrupt endpoint */

transport: hàm vận chuyển

transport_reset: hàm reset vận chuyển proto_handler: hàm xử lý giao thức GUID(guid): số được gán cho device Host: bộ đệm của host

Htmplt:mẫu hình của host host_number: để tìm host

host_no: dịa chỉ host xác định bởi scsi srb:

abortcnt: queue_srb:

action: hành động pid: mã tác vụ

ip_waitq: ip_wanted[1]:

irq_urb_sem: để bảo vệ irq_urb irq_urb: USB request

irqbuf[2]: bộ đệm cho irq_urb irqdata[2:; dữ liệu từ irq_urb

current_urb_sem: để bảo vệ current_urb current_urb: current_done: cờ hoàn thành tag: sema: tác vuh nghỉ notify: cờ của tác vụ queue_exclusion:

unusual_dev: nếu là thiết bị không thông thường extra:extra_destructor:

CHƯƠNG 6 TỔNG KẾT

6.1. PHÁT TRIỂN DRIVER TRÊN HỆ ĐIỀU HÀNH MÃ NGUỒN ĐÓNG VÀ HỆ ĐIỀU HÀNH MÃ NGUỒN MỞ

Driver cũng như các sản phẩm phần mềm khác, trong khi trên hệ điều hành mã nguồn đóng như Window, chúng ta hoàn toàn không biết kernel của Windows lmà việc như thê nào với các driver và với các thiết bị phần cứng

Một phần của tài liệu đồ án công nghệ thông tin USB driver trên hệ điều hành Linux Red Hat (Trang 40)

Tải bản đầy đủ (DOC)

(78 trang)
w