當(dāng)前位置:首頁 > 芯聞號(hào) > 充電吧
[導(dǎo)讀]作者: Sam(甄峰)?sam_code@hotmail.com ? 1. 解讀hiddevice probe程序: static int hid_probe(struct usb_interface

作者: Sam(甄峰)?sam_code@hotmail.com

?

1. 解讀hiddevice probe程序:

static int hid_probe(struct usb_interface*intf, const struct usb_device_id *id)
{
?struct hid_device *hid;
?char path[64];
?int i;
?char *c;

?dbg_hid("HID probecalled for ifnum %dn",
???intf->altsetting->desc.bInterfaceNumber);

?if (!(hid =usb_hid_configure(intf)))
??return -ENODEV;

?usbhid_init_reports(hid);
?hid_dump_device(hid);
?if (hid->quirks &HID_QUIRK_RESET_LEDS)
??usbhid_set_leds(hid);

?if(!hidinput_connect(hid))
??hid->claimed |=HID_CLAIMED_INPUT;
?if (!hiddev_connect(hid))
??hid->claimed |=HID_CLAIMED_HIDDEV;

?usb_set_intfdata(intf,hid);

?if(!hid->claimed) {
??printk ("HID device not claimedby input or hiddevn");
??hid_disconnect(intf);
??return -ENODEV;
?}

?if((hid->claimed &HID_CLAIMED_INPUT))
??hid_ff_init(hid);

?if(hid->quirks &HID_QUIRK_SONY_PS3_CONTROLLER)
??hid_fixup_sony_ps3_controller(interface_to_usbdev(intf),
???intf->cur_altsetting->desc.bInterfaceNumber);

?printk(KERN_INFO);

?if(hid->claimed &HID_CLAIMED_INPUT)
??printk("input");
?if (hid->claimed ==(HID_CLAIMED_INPUT | HID_CLAIMED_HIDDEV))
??printk(",");
?if (hid->claimed &HID_CLAIMED_HIDDEV)
??printk("hiddev%d",hid->minor);

?c = "Device";
?for (i = 0; i maxcollection; i++) {
??if(hid->collection[i].type ==HID_COLLECTION_APPLICATION &&
?????(hid->collection[i].usage &HID_USAGE_PAGE) == HID_UP_GENDESK&&
?????(hid->collection[i].usage & 0xffff)< ARRAY_SIZE(hid_types)) {
???c =hid_types[hid->collection[i].usage &0xffff];
???break;
??}
?}

?usb_make_path(interface_to_usbdev(intf),path, 63);

?printk(": USB HIDv%x.%02x %s [%s] on %sn",
??hid->version>> 8, hid->version& 0xff, c, hid->name,path);

?return 0;
}

1.1:usb_hid_configure(intf)解讀:

從字面來看,它是指配置hid。

static struct hid_device*usb_hid_configure(struct usb_interface *intf)
{
?struct usb_host_interface *interface =intf->cur_altsetting;
?struct usb_device *dev = interface_to_usbdev(intf);
?struct hid_descriptor *hdesc;
?struct hid_device *hid;
?u32 quirks = 0;
?unsigned rsize = 0;
?char *rdesc;
?int n, len, insize = 0;
?struct usbhid_device *usbhid;

?

//得到對(duì)應(yīng)vid,pid的quriks.如果沒有,則返回0
?quirks =usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
???le16_to_cpu(dev->descriptor.idProduct));

?

//如果為boot設(shè)備且為keyboard或mouse.則quirks=HID_QUIRK_NOGET

?
?if(interface->desc.bInterfaceSubClass ==USB_INTERFACE_SUBCLASS_BOOT) {
??if(interface->desc.bInterfaceProtocol ==USB_INTERFACE_PROTOCOL_KEYBOARD ||
???interface->desc.bInterfaceProtocol== USB_INTERFACE_PROTOCOL_MOUSE)
????quirks|= HID_QUIRK_NOGET;
?}

?

//如果quirks顯示要忽略,則退出probe

?if (quirks& HID_QUIRK_IGNORE)
??return NULL;

?

//HID_QUIRK_IGNORE_MOUSE表示如果為mouse,則忽略。

?if ((quirks& HID_QUIRK_IGNORE_MOUSE)&&
??(interface->desc.bInterfaceProtocol== USB_INTERFACE_PROTOCOL_MOUSE))
???returnNULL;

?

//如果interface擴(kuò)展描述符中沒有類型為HID_DT_HID條目,或者interface包含的endpoint數(shù)目為0,又或者interfaceendpoint中擴(kuò)展描述符中沒有類型為HID_DT_HID的條目。則退出。
?if(usb_get_extra_descriptor(interface, HID_DT_HID,&hdesc) &&
????(!interface->desc.bNumEndpoints ||
?????usb_get_extra_descriptor(&interface->endpoint[0],HID_DT_HID, &hdesc))) {
??dbg_hid("class descriptor notpresentn");
??return NULL;
?}

?

//得到描述符長度:

?for (n = 0; n< hdesc->bNumDescriptors; n++)
??if(hdesc->desc[n].bDescriptorType ==HID_DT_REPORT)
???rsize =le16_to_cpu(hdesc->desc[n].wDescriptorLength);

?

//如果描述符長度不對(duì),則退出

?if (!rsize || rsize> HID_MAX_DESCRIPTOR_SIZE) {
??dbg_hid("weird size of reportdescriptor (%u)n", rsize);
??return NULL;
?}

?

//創(chuàng)建此長度內(nèi)存空間

?if (!(rdesc =kmalloc(rsize, GFP_KERNEL))) {
??dbg_hid("couldn't allocaterdesc memoryn");
??return NULL;
?}

?

//向dev的endpoint發(fā)送HID_REQ_SET_IDLErequest.

?hid_set_idle(dev,interface->desc.bInterfaceNumber, 0, 0);

?

//取得reportdescription的詳細(xì)信息,放到rdesc中。

?if ((n =hid_get_class_descriptor(dev,interface->desc.bInterfaceNumber, HID_DT_REPORT,rdesc, rsize)) < 0) {
??dbg_hid("reading reportdescriptor failedn");
??kfree(rdesc);
??return NULL;
?}

?usbhid_fixup_report_descriptor(le16_to_cpu(dev->descriptor.idVendor),
???le16_to_cpu(dev->descriptor.idProduct),rdesc,
???rsize,rdesc_quirks_param);

?dbg_hid("reportdescriptor (size %u, read %d) = ", rsize, n);
?for (n = 0; n < rsize; n++)
??dbg_hid_line(" %02x", (unsignedchar) rdesc[n]);
?dbg_hid_line("n");

?

//解析report。并建立hid_device.返回給hid.

?if (!(hid =hid_parse_report(rdesc, n))) {
??dbg_hid("parsing reportdescriptor failedn");
??kfree(rdesc);
??return NULL;
?}

?kfree(rdesc);
?hid->quirks = quirks;

?

?

?if (!(usbhid =kzalloc(sizeof(struct usbhid_device), GFP_KERNEL)))
??goto fail_no_usbhid;

?hid->driver_data =usbhid;
?usbhid->hid = hid;

?usbhid->bufsize =HID_MIN_BUFFER_SIZE;
?hid_find_max_report(hid, HID_INPUT_REPORT,&usbhid->bufsize);
?hid_find_max_report(hid, HID_OUTPUT_REPORT,&usbhid->bufsize);
?hid_find_max_report(hid, HID_FEATURE_REPORT,&usbhid->bufsize);

?if(usbhid->bufsize >HID_MAX_BUFFER_SIZE)
??usbhid->bufsize= HID_MAX_BUFFER_SIZE;

?hid_find_max_report(hid,HID_INPUT_REPORT, &insize);

?if (insize> HID_MAX_BUFFER_SIZE)
??insize =HID_MAX_BUFFER_SIZE;

?if(hid_alloc_buffers(dev, hid)) {
??hid_free_buffers(dev,hid);
??goto fail;
?}

?for (n = 0; n< interface->desc.bNumEndpoints; n++){

??structusb_endpoint_descriptor *endpoint;
??int pipe;
??int interval;

??endpoint =&interface->endpoint[n].desc;
??if((endpoint->bmAttributes & 3) !=3)??
???continue;

??interval =endpoint->bInterval;

??
??if(hid->collection->usage ==HID_GD_MOUSE &&hid_mousepoll_interval > 0)
???interval =hid_mousepoll_interval;

??if(usb_endpoint_dir_in(endpoint)) {
???if(usbhid->urbin)
????continue;
???if(!(usbhid->urbin = usb_alloc_urb(0,GFP_KERNEL)))
????gotofail;
???pipe =usb_rcvintpipe(dev,endpoint->bEndpointAddress);
???usb_fill_int_urb(usbhid->urbin,dev, pipe, usbhid->inbuf, insize,
?????hid_irq_in, hid, interval);
???usbhid->urbin->transfer_dma= usbhid->inbuf_dma;
???usbhid->urbin->transfer_flags|= URB_NO_TRANSFER_DMA_MAP;
??} else {
???if(usbhid->urbout)
????continue;
???if(!(usbhid->urbout = usb_alloc_urb(0,GFP_KERNEL)))
????gotofail;
???pipe =usb_sndintpipe(dev,endpoint->bEndpointAddress);
???usb_fill_int_urb(usbhid->urbout,dev, pipe, usbhid->outbuf, 0,
?????hid_irq_out, hid, interval);
???usbhid->urbout->transfer_dma= usbhid->outbuf_dma;
???usbhid->urbout->transfer_flags|= URB_NO_TRANSFER_DMA_MAP;
??}
?}

?if(!usbhid->urbin) {
??err_hid("couldn't find an inputinterrupt endpoint");
??goto fail;
?}

?init_waitqueue_head(&hid->wait);

?INIT_WORK(&usbhid->reset_work,hid_reset);
?setup_timer(&usbhid->io_retry,hid_retry_timeout, (unsigned long) hid);

?spin_lock_init(&usbhid->inlock);
?spin_lock_init(&usbhid->outlock);
?spin_lock_init(&usbhid->ctrllock);

?hid->version =le16_to_cpu(hdesc->bcdHID);
?hid->country =hdesc->bCountryCode;
?hid->dev =&intf->dev;
?usbhid->intf = intf;
?usbhid->ifnum =interface->desc.bInterfaceNumber;

?hid->name[0] =0;

?if(dev->manufacturer)
??strlcpy(hid->name,dev->manufacturer,sizeof(hid->name));

?if(dev->product) {
??if(dev->manufacturer)
???strlcat(hid->name," ", sizeof(hid->name));
??strlcat(hid->name,dev->product,sizeof(hid->name));
?}

?if(!strlen(hid->name))
??snprintf(hid->name,sizeof(hid->name), "HID %04x:%04x",
???le16_to_cpu(dev->descriptor.idVendor),
???le16_to_cpu(dev->descriptor.idProduct));

?hid->bus= BUS_USB;
?hid->vendor =le16_to_cpu(dev->descriptor.idVendor);
?hid->product =le16_to_cpu(dev->descriptor.idProduct);

?usb_make_path(dev,hid->phys, sizeof(hid->phys));
?strlcat(hid->phys, "/input",sizeof(hid->phys));
?len = strlen(hid->phys);
?if (len phys) - 1)
??snprintf(hid->phys+ len, sizeof(hid->phys) - len,
??? "%d",intf->altsetting[0].desc.bInterfaceNumber);

?if (usb_string(dev,dev->descriptor.iSerialNumber,hid->uniq, 64) <= 0)
??hid->uniq[0] =0;

?usbhid->urbctrl =usb_alloc_urb(0, GFP_KERNEL);
?if (!usbhid->urbctrl)
??goto fail;

?usb_fill_control_urb(usbhid->urbctrl,dev, 0, (void *) usbhid->cr,
???????usbhid->ctrlbuf, 1, hid_ctrl, hid);
?usbhid->urbctrl->setup_dma= usbhid->cr_dma;
?usbhid->urbctrl->transfer_dma= usbhid->ctrlbuf_dma;
?usbhid->urbctrl->transfer_flags|= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
?hid->hidinput_input_event =usb_hidinput_input_event;
?hid->hid_open = usbhid_open;
?hid->hid_close =usbhid_close;
#ifdef CONFIG_USB_HIDDEV
?hid->hiddev_hid_event =hiddev_hid_event;
?hid->hiddev_report_event =hiddev_report_event;
#endif
?return hid;

fail:
?usb_free_urb(usbhid->urbin);
?usb_free_urb(usbhid->urbout);
?usb_free_urb(usbhid->urbctrl);
?hid_free_buffers(dev, hid);
?kfree(usbhid);
fail_no_usbhid:
?hid_free_device(hid);

?return NULL;
}

?

1.1.1:usbhid_lookup_quirk(pid,vid)解析:

分別使用usbhid_exists_dquirk(pid,vid),usbhid_exists_squirk(pid,vid)來查看動(dòng)態(tài)和靜態(tài)的quirks-list.如果有,則返回此quirks.沒有,則返回0。

?

1.1.2:usb_get_extra_descriptor(descriptor, type,&hdesc)解析:

它調(diào)用__usb_get_extra_descriptor()來解析參數(shù)一(interface或endpoint描述符)中的擴(kuò)展描述符區(qū)--extra??词欠裼蓄愋蜑閰?shù)二(type)的條目,然后把地址交給參數(shù)三。

Sam未經(jīng)證明的猜測:HID設(shè)備中,interface描述符中包含的這個(gè)擴(kuò)展描述符。其中存放的都是HID信息,以hid_descriptor結(jié)構(gòu)存放。

對(duì)于HID設(shè)備來說,在interface description之后會(huì)附加一個(gè)hid description, hiddescription中的最后部份包含有Report description或者PhysicalDescriptors的長度.

hid_descriptor->usb_descriptor_header->bDescriptorType為HID_DT_HID

后面描述符(包括它自己)hid_descriptor->hid_class_descriptor->bDescriptorType為HID_DT_REPORT

?

1.1.3:hid_set_idle(structusb_device *dev, int ifnum, int report, intidle):

它簡單的調(diào)用usb_control_msg() 發(fā)送或接收一個(gè)usb控制消息。

具體到這個(gè)例子中:

usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
??HID_REQ_SET_IDLE,USB_TYPE_CLASS | USB_RECIP_INTERFACE, (idle<< 8) | report,
??ifnum, NULL, 0,USB_CTRL_SET_TIMEOUT);

usb_sndctrlpipe(dev,0):指出將dev中endpoint 0 設(shè)為發(fā)送control管道。

HID_REQ_SET_IDLE:此控制消息的Request。

USB_TYPE_CLASS |USB_RECIP_INTERFACE:請(qǐng)求類型.

調(diào)用成功才會(huì)返回。

?

1.1.4:hid_get_class_descriptor(dev,interface->desc.bInterfaceNumber, HID_DT_REPORT,rdesc, rsize)

也是通過調(diào)用usb_control_msg() 發(fā)送或接收一個(gè)usb控制消息。

發(fā)送USB_REQ_GET_DESCRIPTOR,將得到的report descriptor放到rdesc中。

?

1.1.5: hid_parse_report(__u8*start, unsigned size)

參數(shù)一:通過usb_control_msg發(fā)送request(USB_REQ_GET_DESCRIPTOR)從設(shè)備得到的report descriptor.

參數(shù)二:是此report Descriptor的長度。

1).首先創(chuàng)建hid_device類型設(shè)備。

2).將參數(shù)一中數(shù)據(jù)保存在hid_device->rdesc中。長度保存在hid_device->rsize中。

3). 使用fetch_item(__u8 *start, __u8 *end, struct hid_item*item)得到report description的下一項(xiàng)數(shù)據(jù)。放到item中。

4). 根據(jù)不同的item.type.分別調(diào)用

hid_parser_main,
??hid_parser_global,
??hid_parser_local,
??hid_parser_reserved

來處理。

?


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動(dòng)力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉