s3c6410 linux gadget hid驅動

來源:互聯網
上載者:User

s3c6410 linux gadget hid驅動調了我一個多星期了今天終於搞定了,來跟大家分享下.

上一個星期糾結了一個星期的寄存器,試了N次,不管把3.1和3.7的hid驅動移植過來也是一樣的情況,所以這星期直接從問題本身著手一個個找,一個個對比,終於解決了。

我用的核心是linux2.6.38的,最開始的時候開發板是可以當隨身碟用的,而使用hid功能的時候出現如下問題:

g_hid gadget: hid_setup crtl_request : bRequestType:0x21 bRequest:0xa Value:0x0
g_hid gadget: Unknown request 0xa
s3c-hsotg s3c-hsotg: writen DxEPCTL=0x04228000 to 00000900 (DxEPCTL=0x00208000)
s3c-hsotg s3c-hsotg: s3c_hsotg_rx_data: FIFO 8 bytes on ep0 but no req (DxEPCTl=0x00028000)
s3c-hsotg s3c-hsotg: s3c_hsotg_rx_data: FIFO 8 bytes on ep0 but no req (DxEPCTl=0x00028000)
s3c-hsotg s3c-hsotg: s3c_hsotg_rx_data: FIFO 8 bytes on ep0 but no req (DxEPCTl=0x00028000)
s3c-hsotg s3c-hsotg: S3C_GINTSTS_USBSusp
這個是我把debug資訊開啟後列印出來的資訊,前面一直以為是device的時鐘沒有設定對,device的時鐘應該設定為48M,但是結果不是這裡的問題,怎麼修改時鐘效果都是一樣,所以上個星期一個寄存器一個寄存器的對,修改完後發現還是一樣的問題。所以開始研究這個:Unknown request 0xa

hid的大致流程是s3c_hsotg.c->composite.c->f_hid.c具體流程網上有很多這裡我就不作說明了。

資料:

http://blog.csdn.net/wuyuwei45/article/details/8930830

http://blog.csdn.net/fanqipin/article/details/8450694

糾結了一個星期後,中間花了幾個小時把2416的hid調好的,最後沒辦法所以決定一步步對.

6410的當host發送請求0xa時就直接出現了上面的錯誤,但是2416當host發送0xa時也會出現-95的錯誤但是host端會繼續發送0x06和0x09請求,請查看usb協議這裡就不多說了。

6410與2416在接收到0xa請求時的操作基本一樣,不同的是2416在接收到0xa後,會忽略這個請求然後向host發送一個空包,這樣host會繼續發送其它的請求,而6410在接收到0xa後忽略了,但是沒有向host端發送任何資料,所以導致後面的操作無法進行.

所以現在的工作就是當device收到0xa後,向host端發送一個空包,讓枚舉繼續下去.
主要修改就在s3c_hsotg.c裡面的s3c_hsotg_process_control函數,整個過程我就不在這分析了,我也不是很懂,哈哈。

/* as a fallback, try delivering it to the driver to deal with */if (ret == 0 && hsotg->driver) {ret = hsotg->driver->setup(&hsotg->gadget, ctrl);if (ret < 0)dev_dbg(hsotg->dev, "driver->setup() ret %d\n", ret);}


這裡是接收到請求後由composite.c裡面的composite_setup進行處理,當接收到0xa後這裡會返回-95的錯誤,我們接著往下看:

/* the request is either unhandlable, or is not formatted correctly * so respond with a STALL for the status stage to indicate failure. */if (ret < 0) {u32 reg;u32 ctrl;dev_dbg(hsotg->dev, "ep0 stall (dir=%d)\n", ep0->dir_in);reg = (ep0->dir_in) ? S3C_DIEPCTL0 : S3C_DOEPCTL0;/* S3C_DxEPCTL_Stall will be cleared by EP once it has * taken effect, so no need to clear later. */ctrl = readl(hsotg->regs + reg);ctrl |= S3C_DxEPCTL_Stall;ctrl |= S3C_DxEPCTL_CNAK;writel(ctrl, hsotg->regs + reg);dev_dbg(hsotg->dev,"writen DxEPCTL=0x%08x to %08x (DxEPCTL=0x%08x)\n",ctrl, reg, readl(hsotg->regs + reg));/* don't belive we need to anything more to get the EP * to reply with a STALL packet */}

當返回-95後只對DIEPCTL0進行了相關操作,具體設定請查看6410 datasheet

所以我們要在這加上發一個空包的過程

方法一:

看s3c_hsotg.c你會發現,裡面有這樣一個函數:s3c_hsotg_send_zlp

這個函數的功能就是向host發送一個空包的過程,當然不能全部copy過來,全部copy過來是會有問題的,所以我的修改如下:

/* the request is either unhandlable, or is not formatted correctly * so respond with a STALL for the status stage to indicate failure. */if (ret < 0) {u32 reg;u32 ctrl;dev_dbg(hsotg->dev, "ep0 stall (dir=%d)\n", ep0->dir_in);reg = (ep0->dir_in) ? S3C_DIEPCTL0 : S3C_DOEPCTL0;/* S3C_DxEPCTL_Stall will be cleared by EP once it has * taken effect, so no need to clear later. */if(ret != -95) {ctrl = readl(hsotg->regs + reg);ctrl |= S3C_DxEPCTL_Stall;ctrl |= S3C_DxEPCTL_CNAK;writel(ctrl, hsotg->regs + reg);}else {/* issue a zero-sized packet to terminate this */writel(S3C_DxEPTSIZ_MC(1) | S3C_DxEPTSIZ_PktCnt(1) |       S3C_DxEPTSIZ_XferSize(0), hsotg->regs + S3C_DIEPTSIZ(0));ctrl = readl(hsotg->regs + reg);ctrl |= S3C_DxEPCTL_CNAK;  /* clear NAK set by core */ctrl |= S3C_DxEPCTL_EPEna; /* ensure ep enabled */ctrl |= S3C_DxEPCTL_USBActEp;writel(ctrl, hsotg->regs + reg);}dev_dbg(hsotg->dev,"writen DxEPCTL=0x%08x to %08x (DxEPCTL=0x%08x)\n",ctrl, reg, readl(hsotg->regs + reg));/* don't belive we need to anything more to get the EP * to reply with a STALL packet */}

當if(ret < 0)裡改為如下,同時保留原來的設定,以勉後面出現問題,這樣修改後當host發送0xa給device device會回一個空包給host 這樣host會繼續後面的操作,這樣你就可以在你的電腦硬體管理裡面看到你的hid裝置了。

方法二:

         在f_hid.c中的hidg_setup函數中加入如下代碼:

case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8  | HID_REQ_GET_PROTOCOL):VDBG(cdev, "get_protocol\n");goto stall;break;#if 1case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8  | USB_REQ_GET_INTERFACE):VDBG(cdev, "get_interface | wLenght=%d\n", ctrl->wLength);/* send an empty report */length = min_t(unsigned, length, hidg->report_length);memset(req->buf, 0x0, length);goto respond;break;#endif

其中從#if 1開始到#endif為我們加入的代碼 host發送0xa為get_interface命令 這裡我們也是發送的一個空包.至此hid裝置可以正確識別。

在進行hid通訊測試的的時候 發現write之後會溢出,目前還沒有解決......

水平有限 ,如有錯誤請指出。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.