打印

如果**不能在usb_core.c中不能修改的原则的话,

[复制链接]
4562|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
armmcu|  楼主 | 2008-8-23 05:21 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
用 USB Firmware 2.2 , HID 协议 ,PC发过来的 SET REPORT(0x21,09...) 命令 不支持,几个USB例程也没有 ,请问版主,这个库有支持这个功能吗,是否要自己来写啊? 谢谢
沙发
香水城| | 2008-8-23 08:39 | 只看该作者

STM32的USB库支持所有的USB协议命令

当然也包括HID类中的SET REPORT。

使用特权

评论回复
板凳
computer00| | 2008-8-23 10:24 | 只看该作者

自己看看里面有没有对SET REPORT处理就知道了。没有的话就自

使用特权

评论回复
地板
armmcu|  楼主 | 2008-8-23 14:43 | 只看该作者

Re:

香版主,你确认有 HID类中的SET REPORT 的支持吗? 我怎么找遍了也没见啊? 

使用特权

评论回复
5
香水城| | 2008-8-23 15:34 | 只看该作者

STM32的USB库支持所有的USB协议命令

包括HID类中的SET REPORT,但没有专门的函数解码这个请求,需要利用库中提供的功能自己解码,

使用特权

评论回复
6
armmcu|  楼主 | 2008-8-24 03:11 | 只看该作者

Re:

香版主啊, SET REPORT 可是 很基本的功能啊,比较之前做过的USB驱动,ST的这个USB库 可说是最复杂的,没几天工夫,想加上这个功能没那么容易,但对ST写这个驱动的人来说就很容易了。 
我们现在把其他的ARM都放弃了,老产品也正在转到STM32F103上来,能否支持一吧呢,第一次订单 100PCS 小批量试,第二个单 计划是 10K的采购,版主有兴趣的话,请Email:armmcu_6@hotmail.com,谢谢!

使用特权

评论回复
7
香水城| | 2008-8-24 19:26 | 只看该作者

请楼主就近与ST的FAE联系,他们可以给你提供帮助

使用特权

评论回复
8
computer00| | 2008-8-24 21:57 | 只看该作者

晕……应该是在usb_core.c里面修改

有个void DataStageOut(void)函数,在函数末尾,增加对数据的处理:

#define SET_REPORT 0x09

if(pInformation->ControlState == WAIT_STATUS_IN) //如果数据已经接收完毕
{
//则对数据处理
if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
           && RequestNo == SET_REPORT)  //如果是SET REPORT请求
{
  //则处理SET REPORT请求
  
}
}


前面的接收数据可能你还要自己改下,不知道他这个缓冲区是从哪里获取来的。
最简单的办法就是自己开辟一个缓冲区来代替那里的Buffer来接收数据。

使用特权

评论回复
9
armmcu|  楼主 | 2008-8-25 04:43 | 只看该作者

Re:

我从来不相信FAE能解决什么实际性的问题,不论是哪家的FAE,现在这个问题是一个很通用性的问题,尽管我们从确定采用ST的这个IC和拿到开发板也不过一周的时间,但我搜索这个坛子的问题,版主是有问必答,不好意思,我不知道版主和ST是什么关系,这个问题一定要透过FAE来解决吗?我们是冲着$1.8/片 10K的起订量 来的啊

感谢computer00,在我写第一个USB程序的时候就拜读过你的**,但这个问题,你没有仔细研究,从 这个void DataStageOut(void)修改,我不能认同,ST的这个驱动弄得真的复杂,我觉得应该是在Usb_prop.c 改, 但还是没有改出来。  

使用特权

评论回复
10
香水城| | 2008-8-25 09:27 | 只看该作者

不知道9楼这位兄弟是否联系过ST的FAE

其它公司的FAE是否能解决问题我不知道,但只要你是我们登记的客户,你的问题我们一定能解决。

如果与你联络的FAE解决不了,他会反馈到我们在上海的中国区支持中心,上海的工程师解决不了会反馈到总部的支持工程师,总部的工程师再解决不了,还会反馈到设计工程师,只要这个东西是经ST工程师设计的,问题一定能解决!


关于USB的库,不知道各位是否看过它的用户手册,手册里清楚地写明如何使用库所提供的手段实现各种功能。请参考第1.4节:Implementing a USB application using the STM32F10xxx USB library

请不要修改目录 STM32F10xUSBLibUSBLiblibrary 下的任何文件,如果我们需要更新这个库时,ST将仅仅更新上述目录下的文件,而不会触动任何用户程序,如果你修改了这些文件,则可能给以后的库升级造成麻烦。


9楼的朋友说曾经使用过这个库添加功能,但没有成功,如果你能说明你是如何操作的,我们在这里讨论,我一定能帮你解决。

使用特权

评论回复
11
cpufan| | 2008-8-25 11:51 | 只看该作者

可以不改core.c

以Custom_HID例子为例,楼主有没有尝试实现这个函数:
void CustomHID_Status_In(void)
对应的结构体DEVICE_PROP的第三个成员void (*Process_Status_IN)(void);

使用特权

评论回复
12
computer00| | 2008-8-25 12:58 | 只看该作者

如果**不能在usb_core.c中不能修改的原则的话,

那么可以考虑在usb_prop.c中的void Joystick_Status_In(void)函数中添加代码(我用的是摇杆实例,
具体的不同程序可能有不同的Status_In处理函数,具体在DEVICE_PROP结构体中的第三个成员函数指定),
从该函数的名字来看,是处理状态输入过程的,这也正好是控制输出传输的最后一个过程,只要在这里
增加对刚刚输出的数据处理即可。

从usb_core.c中也可以推测出来,其中的u8 In0_Process(void)函数(处理端点0输入的函数)中有如下代码:
  else if (ControlState == WAIT_STATUS_IN) //如果是等待状态输入(也就是我前面所说的数据接收完毕)
  {
   //如果是标准的设置地址请求,那么库函数将处理它
    if ((pInformation->USBbRequest == SET_ADDRESS) &&
        (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)))
    {
      SetDeviceAddress(pInformation->USBwValue0);
      pUser_Standard_Requests->User_SetDeviceAddress();
    }
    //然后再转交给用户的Process_Status_IN函数(也就是前面的void Joystick_Status_In(void)函数)
    (*pProperty->Process_Status_IN)();
    ControlState = STALLED;
  }

从这里可以看出,处理端点0输出(因为设置地址也是控制输出请求)可以在用户指定的pProperty->Process_Status_IN函数中处理。

对比我前面给出的方案可以看出,其实处理过程是一样的。我是在最后一个数据输出包后就处理输出数据,
而这里则是等待当主机发送最后一个输出包后再请求状态输入时才去处理数据。

那么只要在指定的Process_Status_IN函数中增加处理的代码:

#define SET_REPORT 0x09

if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
           && (pInformation->USBbRequest) == SET_REPORT)  //如果是SET REPORT请求
{
  //则处理SET REPORT请求
}

那么接收的数据保存在了哪呢?这就要看前面所提到过的那个void DataStageOut(void)函数了,
在这里有如下代码:

    Buffer = (*pEPinfo->CopyData)(Length);
    pEPinfo->Usb_rLength -= Length;
    pEPinfo->Usb_rOffset += Length; //这里调整了Usb_rOffset

它调用了pEPinfo->CopyData这个函数来获取缓冲取的地址,所以我们需要自己写一个提供缓冲区
地址的函数。在该函数中由pInformation->Ctrl_Info.Usb_wOffset来指定当前缓冲区的地址,
增加函数代码如下:

#define OUT_REPORT_LENGTH 100

u8 SetReportBuffer[OUT_REPORT_LENGTH]; //定义保存输出报告的缓冲区

//返回输出报告的缓冲区地址函数
u8 *Joystick_GetBufferForSetReport(u16 Length); //声明

u8 *Joystick_GetBufferForSetReport(u16 Length)
{
 //根据当前偏移量返回保存报告的地址
 return SetReportBuffer+(pInformation->Ctrl_Info.Usb_wOffset);
}

那么这个函数该在哪里赋给上面的pEPinfo->CopyData呢?(pEPinfo其实就是&pInformation->Ctrl_Info)
这就要看usb_core.c中的void Data_Setup0(void)函数了,里面有如下代码:

  if (CopyRoutine) //由于在上面并没有处理SET REPORT,所以这里为假
  {
    pInformation->Ctrl_Info.Usb_wOffset = wOffset;
    pInformation->Ctrl_Info.CopyData = CopyRoutine;
    /* sb in the original the cast to word was directly */
    /* now the cast is made step by step */
    (*CopyRoutine)(0);
    Result = USB_SUCCESS;
  }
  else  //那么就会调用下面的pProperty->Class_Data_Setup函数了,
  {
    Result = (*pProperty->Class_Data_Setup)(pInformation->USBbRequest);
    if (Result == USB_NOT_READY)
    {
      pInformation->ControlState = PAUSE;
      return;
    }
  }

通过查看usb_prop.c中的DEVICE_PROP Device_Property结构体,发现它就是用户函数Joystick_Data_Setup,
我们只要在该函数中初始化CopyData即可。
在Joystick_Data_Setup函数中可以找到如下代码:

  if (CopyRoutine == NULL)
  {
    return USB_UNSUPPORT;
  }

只要在这段代码之前添加初始化即可:

#define SET_REPORT 0x09

if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
           && (pInformation->USBbRequest) == SET_REPORT)  //如果是SET REPORT请求
{
  //设置复制数据的函数
  CopyRoutine=Joystick_GetBufferForSetReport;
  //设置要复制数据的长度
  pInformation->Ctrl_Info.Usb_rLength=pInformation->USBwLength;
}


接着下面就可以看到代码

  pInformation->Ctrl_Info.CopyData = CopyRoutine;
  pInformation->Ctrl_Info.Usb_wOffset = 0;
  (*CopyRoutine)(0);

它将复制数据的处理函数赋给了pInformation->Ctrl_Info.CopyData,并设置了pInformation->Ctrl_Info.Usb_wOffset为0,
然后调用了复制数据的函数,也就是说,Joystick_GetBufferForSetReport函数将返回缓冲区的首地址。以后每次接收到
数据后,pInformation->Ctrl_Info.Usb_wOffset将自动增加接收数据的长度,调用Joystick_GetBufferForSetReport函数
后将获取到缓冲区的后续地址。

其中接收数据的长度由pInformation->Ctrl_Info.Usb_rLength决定,我们只需要将SETUP包中的wLength
值赋给它即可,即pInformation->Ctrl_Info.Usb_rLength=pInformation->USBwLength。当数据接收完毕后,
数据保存在SetReportBuffer中,总个数为pInformation->Ctrl_Info.Usb_wOffset。这时pInformation->Ctrl_Info.Usb_rLength
值应该为0。


以上是我对这个USB程序的分析,由于手头只有一条USB数据线,所以无法调试,楼主
可以按照这个思路去分析下,应该能解决问题。

其实如果直接在usb_core.c的void DataStageOut(void)函数中处理将不会绕这么多弯子了,
不过既然香主说了最好不要修改库文件,那还是不修改吧。祝楼主好运……晕,写了这么长,
都忘记吃饭了,先去吃个饭……

使用特权

评论回复
13
computer00| | 2008-8-25 12:59 | 只看该作者

晕……写完才发现cpufan已经发了,撞车了……

使用特权

评论回复
14
香水城| | 2008-8-25 15:06 | 只看该作者

哈哈,圈圈的钻研精神可嘉

其实如何使用这个USB库,在它的说明手册中都写明了,看手册比研究程序要容易一些。

请看我根据手册做的一个中文的介绍:以HID的SET REPORT为例说明如何使用STM32的USB库支持控制端点0

使用特权

评论回复
15
computer00| | 2008-8-25 17:04 | 只看该作者

呵呵,俺还是直接看代码直观,有针对性,

看了手册最终还是要看代码的……

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

145

主题

181

帖子

0

粉丝