註:在使用者級的USB 驅動編寫,不錯,好像QT 嵌入式移植裡面也是基於此的。
核心級的usb驅動在以下幾個方面會有問題:
1 當使用我們產品的客戶有2.4核心的平台,同時也有2.6核心的平台,我們要設計的驅動是要相容兩個平台的,就連makefile 我們都要寫兩個。
2 當我們要把linux移植到嵌入平台上,你會發現原先linux內建的驅動移過去還挺大的,我的核心當然是越小越好拉,這樣有必要麼。這還不是最鬱悶的地方,如果嵌入平台是客戶的,客戶要購買你的產品,你突然發現客戶裝置裡的系統和你的環境不一樣,它沒有你要的驅動了,你的程式運行不了,你會先想:“沒關係,我寫個核心驅動載入一下不就行了“。卻發現客戶連insmod載入模組的工具都沒移植,那時你就看看老天,說聲我怎麼那麼倒黴啊,客戶可不想你動他花了n時間移植的核心哦
3 花了些功夫寫了個新產品的驅動,挺有成就感啊,代碼品質也是相當的有水準啊。正當你沉醉在你的代碼中時,客服不斷的郵件來了,“客戶需要2.6.5核心的驅動,config檔案我已經發你了” “客戶需要雙核的 2.6.18-smp 的驅動” “客戶的平台是自己定製的是2.6.12-xxx “ 你恨不得把驅動的原始碼給客戶,這樣省得編譯了。你的一部分工作時間編譯核心,定製驅動
有問題產生必然會有想辦法解決問題的人, libusb的出現給我們帶來了某些方便,即節約了我們的時間,也降低了公司的成本。 所以在一些情況下,就可以考慮使用libusb的無驅設計了。
下文轉自:http://blog.sina.com.cn/s/blog_8a84e6d301015uh7.html
在網上買了遊戲搖杆和按鍵,他們通過usb口與電腦串連,於是乎我就想針對此手柄與按鍵開發自己的usb驅動,目的是為了以後玩的happy,哈哈。
libusb是使用者端驅動程式封裝庫,是USB主機對USB裝置進行操作的函數集合,有了它我們針對某型號USB裝置就不用去修改比較繁瑣的linux核心驅動了,方便了對裝置的使用與調試。我電腦的編程環境是ubuntu12.04+geany(一款linux下的整合開發工具,個人感覺挺好用的)。接下來分享一下代碼:
#include<stdio.h>
#include <string.h>
#include <usb.h>
#define IdVendor0x0079 //這是我裝置的廠商號
#define IdProduct0x0006 //這是我裝置的產品號,當你的usb裝置接入電腦時,使用lsusb-v命令來查看裝置資訊,請看下面第三張圖片中的0079:0006
//#define PrintDev
char enp_num[8],buf8[8],is_change=0;
//端點描述符
static void print_endpoint(struct usb_endpoint_descriptor*endpoint)
{
printf(" bEndpointAddress: xh\n",endpoint->bEndpointAddress);
printf(" bmAttributes: xh\n", endpoint->bmAttributes);
printf(" wMaxPacketSize: %d\n",endpoint->wMaxPacketSize);
printf(" bInterval: %d\n", endpoint->bInterval);
printf(" bRefresh: %d\n", endpoint->bRefresh);
printf(" bSynchAddress: %d\n", endpoint->bSynchAddress);
}
static void print_altsetting(struct usb_interface_descriptor*interface)
{
int i;
printf(" bInterfaceNumber: %d\n",interface->bInterfaceNumber);
printf(" bAlternateSetting: %d\n",interface->bAlternateSetting);
printf(" bNumEndpoints: %d\n", interface->bNumEndpoints);
printf(" bInterfaceClass: %d\n", interface->bInterfaceClass);
printf(" bInterfaceSubClass: %d\n",interface->bInterfaceSubClass);
printf(" bInterfaceProtocol: %d\n",interface->bInterfaceProtocol);
printf(" iInterface: %d\n", interface->iInterface);
for (i = 0; i <interface->bNumEndpoints; i++)
print_endpoint(&interface->endpoint[i]);
}
//顯示裝置所擁有的所有介面的描述符
static void print_interface(struct usb_interface *interface)
{
int i;
for (i = 0; i <interface->num_altsetting; i++)
print_altsetting(&interface->altsetting[i]);
}
//配置描述符
static void print_configuration(struct usb_config_descriptor*config)
{
int i;
printf(" wTotalLength: %d\n", config->wTotalLength);
printf(" bNumInterfaces: %d\n", config->bNumInterfaces);
printf(" bConfigurationValue: %d\n",config->bConfigurationValue);
printf(" iConfiguration: %d\n", config->iConfiguration);
printf(" bmAttributes: xh\n", config->bmAttributes);
printf(" MaxPower: %d\n", config->MaxPower);
for (i = 0; i <config->bNumInterfaces; i++)
print_interface(&config->interface[i]);
}
static void print_device(struct usb_device *dev)
{
//讀取描述符
int i;
chardescription[256];
snprintf(description, sizeof(description),"X-X",dev->descriptor.idVendor,dev->descriptor.idProduct);
printf("Dev#%d: %s\n", dev->devnum,description);
for (i = 0;i <dev->descriptor.bNumConfigurations; i++)
print_configuration(&dev->config[i]);
}
//因為我的遊戲裝置屬於HID類型,所以他與電腦通過中斷端點進行資料轉送。當搖杆位置變化或者按鍵按下時,讀取裝置中斷端點值
static int read_interupt(struct usb_device *dev)
{
usb_dev_handle *udev;
charbuf[256];
intret,i;
udev=usb_open(dev);
//#ifdefPrintDev
//print_device(dev);
//#endif