打印

我遇到的问题

[复制链接]
1994|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
happlylife|  楼主 | 2008-1-28 22:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我坐了一个USB键盘,现在枚举有点问题,已经能被Windows认识了,提示发现HID备,并已经可以使用.可是实际上不可以使用,我用BusHound观察发现有问题.
在获得Report描述符后,主机参数了一个DO 01.然后我的设备就完全不能使用了.我不知道是什么原因啊.

相关帖子

沙发
happlylife|  楼主 | 2008-1-28 22:11 | 只看该作者

继续

我把我的截图和我的描述符发给大家.
// 设备描述符号
const USB_DEVICE_DESCRIPTOR DeviceDescr =
{
    sizeof(USB_DEVICE_DESCRIPTOR),
    USB_DEVICE_DESCRIPTOR_TYPE,
    0x00010000,
    0,    //USB分配的类代码    (已更改用于HID设备)
    0,    //USB分配的子类代码
    0,    //USB分配的协议代码
    EP0_PACKET_SIZE,
    0x00040071,    //idVendor
    0x00060066,    //idProduct
    0x00010000,    //bcdDevce
    0,//1,            //iManufactor
    0,//2,            //iProduct
    0,//3,            //iSerialNumber
    1            //bNumConfigurations
};

// 配置描述符
const USB_CONFIGURATION_DESCRIPTOR ConfigDescr =
{
    sizeof(USB_CONFIGURATION_DESCRIPTOR),    //09
    USB_CONFIGURATION_DESCRIPTOR_TYPE,        //02
    CONFIG_DESCRIPTOR_LENGTH,                //29
    1,                                        //0x0001
    1,                                        //1
    0,                                        //0
    0xa0,    //总线供电,支持远程唤醒            //0xa0
    0xc8    //400mA                            //0xc8
};

// 接口描述符
const USB_INTERFACE_DESCRIPTOR InterfaceDescr =
{
    sizeof(USB_INTERFACE_DESCRIPTOR),        //09
    USB_INTERFACE_DESCRIPTOR_TYPE,            //04
    0,                                        //00
    0,                                        //00
    NUM_ENDPOINTS,                            //02
    0x03,//原来是USB_CLASS_CODE_TEST_CLASS_DEVICE,
    0x01,//原来是USB_SUBCLASS_CODE_TEST_CLASS_D12,
    0x01,//原来是USB_PROTOCOL_CODE_TEST_CLASS_D12,
    0
};
//HID描述符
const USB_HID_DESCRIPTOR HidDescr=
{
    sizeof(USB_HID_DESCRIPTOR),                //09
    0x21,        //HID描述符
    0x00010010,    //HID版本号
    0x21,        //国家代码
    0x01,        //随后的描述符数,这里只有一个报告描述符
    0x22,        //随后的描述符类型,这里为报表描述符
    (unsigned long int)sizeof(ReportDescr)        //报表描述符的长度
};
// 端点1输入描述符
const USB_ENDPOINT_DESCRIPTOR EP1_TXDescr =
{
    sizeof(USB_ENDPOINT_DESCRIPTOR),        //07
    USB_ENDPOINT_DESCRIPTOR_TYPE,            //05
    0x81,                    //输入端点
    USB_ENDPOINT_TYPE_INTERRUPT,            
    EP1_PACKET_SIZE,        //16字节
    0x0a        //中断扫描时间:10ms
};

// 端点1输出描述符
const USB_ENDPOINT_DESCRIPTOR EP1_RXDescr =
{
    sizeof(USB_ENDPOINT_DESCRIPTOR),
    USB_ENDPOINT_DESCRIPTOR_TYPE,
    0x01,                    //输出端点
    USB_ENDPOINT_TYPE_INTERRUPT,
    EP1_PACKET_SIZE,
    0x0a        //中断扫描时间:10ms
};
我用的是凌阳的16位单片机,是小端格式的.所以和51有点不一样.

使用特权

评论回复
板凳
平常人| | 2008-1-28 22:42 | 只看该作者

你的输出端点是做什么的?

你键盘上的CAP Lock、Num Lock这几个灯是如何控制的?

使用特权

评论回复
地板
happlylife|  楼主 | 2008-1-28 23:11 | 只看该作者

谢谢

我没有用输出端点做任何东西,但是我有对set report的处理.收到set report后我发送了一个0字节数据包.我也没有去设定字符串描述符.

使用特权

评论回复
5
happlylife|  楼主 | 2008-1-29 00:26 | 只看该作者

继续

    在调试的过程中我还发现,我的设备根本就没有收到端点1的IN中断,所以在IN中断处理程序中的发送按键值的函数根本得不到执行.我可以把我的程序发上来让大家看看.我现在该位1个端点,设定位IN端点,中断传输.我在程序中加入了字符串描述符的发送.让程序更加完整.但是好像还是不可以使用哦.

下面是附件,大家可以下载下去看看,里面有我的截图.
相关链接:https://bbs.21ic.com/upfiles/img/20081/200812902634820.rar

使用特权

评论回复
6
CheneyPeng| | 2008-1-29 08:43 | 只看该作者

11

是不是OUT端点的中断没有清除,导致一直进入OUT中断? 我之前好像也碰到过这个问题,

使用特权

评论回复
7
happlylife|  楼主 | 2008-1-29 09:54 | 只看该作者

谢谢楼上的

是吗?那我读一次OUT端点最后状态是不是就可以了,可是我没有设置OUT端点啊,我的端点描述符就只有对IN端点的描述符啊.怎么会这样呢?

使用特权

评论回复
8
nj手术刀| | 2008-1-29 12:23 | 只看该作者

可能DO命令01你没正确处理,程序死了

使用特权

评论回复
9
happlylife|  楼主 | 2008-1-29 12:43 | 只看该作者

谢谢楼上

DO命令 01是什么?应该怎么处理啊??我看OO的程序里没有发现有对这个进行处理的内容啊.

使用特权

评论回复
10
xwj| | 2008-1-29 12:51 | 只看该作者

“我坐了一个USB键盘”...

只听说过跪键盘的,没听说过坐键盘的;-)

使用特权

评论回复
11
happlylife|  楼主 | 2008-1-29 12:53 | 只看该作者

佩服

呵呵,楼上的好眼力啊..

使用特权

评论回复
12
平常人| | 2008-1-29 13:46 | 只看该作者

既然没有用输出端点,为什么有输出端点描述符?

在USB键盘中,输出端点就是用来控制键盘上的CAP Lock、Num Lock这几个灯,我在3楼已经暗示过,但你没反应,说明你还没搞懂USB键盘;请打开HID报告描述符好好看一下吧,那里面一定有这部分内容。

看样子这个键盘被你“坐”坏了,哈哈哈。。。。。。。

使用特权

评论回复
13
happlylife|  楼主 | 2008-1-29 16:58 | 只看该作者

谢谢楼上的指点

谢谢楼上的指点.我前面的那个描述符里是同时定义了输入输出端点,因为我看OO的程序里是这样的,只不过他用的是端点2(主端点),而我用的是端点1.另外我的报告描述符也是从OO哪里直接粘贴过来的.

我后来只定义了一个输入端点,这个时候是在对SetReport处理后,产生了DO 01,DO 00 01 这两数据.然而当我同时定义了输入和输出端点时,没有产生SetReport命令,就直接产生了DO 01 DO 00 01这两个数据包.我又看了下书,书上说是:"SetReport是主机向HID设备发送数据,如设置输入报告,输出报告和特征报告的状态等,如果HID设备没有中断OUT结点或者其只遵循HID规范1.0版,则她是主机向设备发送数据的唯一方法.对于HID设备来说,该请求不是必须的."
所以从我上面的情况看来在这一块是没有问题的,当定义了输入端点时就不需要用SetReport命令来向设备发送数据,而是直接用输出端点就可以了.

在我的HID报告描述符里的确是有输出项的,如下:
                 ................前面省略
    0x0095, 0x0005,                    //   REPORT_COUNT (5)
    0x0075, 0x0001,                    //   REPORT_SIZE (1)
    0x0005, 0x0008,                    //   USAGE_PAGE (LEDs)
    0x0019, 0x0001,                    //   USAGE_MINIMUM (Num Lock)
    0x0029, 0x0005,                    //   USAGE_MAXIMUM (Kana)
    0x0091, 0x0002,                    //   OUTPUT (Data,Var,Abs)
    0x0095, 0x0001,                    //   REPORT_COUNT (1)
    0x0075, 0x0003,                    //   REPORT_SIZE (3)
    0x0091, 0x0003,                    //   OUTPUT (Cnst,Var,Abs)
                      .........后面的省略

我又发现一个现象,我用BusHound附带的BusCommder工具,向设备发送命令,通过端点0 Control In/Out 发送获得设备描述符,配置描述符,字符串描述符命令都可以接收到设备返回的内容,我用端点1的OUT 端点发送数据到设备,也可以成功.但是我要是用端点1的IN 端点 想要让设备给主机发送数据,却不能通过,这时BusCommand而就不可以使用了,像死了一样.我想知道为什么会出现IN端点不可以使用呢?
我觉得我的问题不是输出的那两个数据,而是中断IN端点不能正常工作,我也不知道为什么,我的描述符也看不出毛病,并且用BusHound观察发现都被正确的发送到主机了.
看来我还有很多知识不是很清楚啊,我还要好好的学习啊.

使用特权

评论回复
14
CheneyPeng| | 2008-1-30 09:26 | 只看该作者

11

学习东西不能简单的把别人的程序copy过来了事了哦,哈哈,一定要自己搞一遍才能算掌握了,

使用特权

评论回复
15
happlylife|  楼主 | 2008-1-30 13:13 | 只看该作者

大家帮忙啊

还得请大家帮帮忙啊.我就一个人在弄,问人也没得问.只有靠论坛上的朋友帮忙了.先谢谢大家了

使用特权

评论回复
16
happlylife|  楼主 | 2008-1-30 19:55 | 只看该作者

我的问题解决了

我的问题解决了.因为我在枚举的最后会收到主机通过中断OUT端点发送到设备的数据,我在主程序中,对输出中断处理的地方加了一个向IN端点写数据的函数后就好了.后面就可以收到主机每10ms的IN中断,这样我就可以把我的按键值发送过去了.

问题是我收到主机从中断OUT端点发送过来的这个数据后,为什么必须向中断IN端点写数据,这样才可以正常工作呢?如果不去写,就一直不可以工作,难道也是和控制输出一样,要回一个数据包吗?.
还有我的程序里对报告描述符,还有其他的描述符都参考了OO的程序,可是他的程序中对中断OUT的处理没有像我这样,向IN端点里写数据,为什么我会出现这样的情况呢.
我也是初学有很多的不明白,希望有朋友可以帮忙指点以下.
我的程序如下.......
while(1)
    {
        P_Watchdog_Clear = 0x0001;
        if(bEPPflags.bits.bus_reset)                        // 总线复位处理
        {
            bEPPflags.bits.bus_reset = 0;                    // 清标志
        }
        if(bEPPflags.bits.suspend)                            // 总线挂起处理
        {
            bEPPflags.bits.suspend = 0;                        // 清标志
        }
        if(bEPPflags.bits.setup_packet)                        // 协议处理
        {
            bEPPflags.bits.setup_packet = 0;                // 清标志
            D12_Control_Handler();
        }
        if(bEPPflags.bits.Ep1_ReceiveDataFlag==1)
        {
            bEPPflags.bits.Ep1_ReceiveDataFlag = 0;
            D12_ReadEndpointAndClrD12Int(2, 16, aIdFlag);
            D12_WriteEndpointAndClrD12Int(3, 0, 0);        //这个函数是用于应答 DO 的,向结点3(端点1的IN端点)写0字节数据,只有应答后,才算枚举通过,//才可以定时的产生IN中断.否则无法产生IN中断.这样设备不可以使用,无法发送按键值给主机.
        }
        if(bEPPflags.bits.Ep1_SendDataFlag==1)
        {
            bEPPflags.bits.Ep1_SendDataFlag = 0;
            KeyID(); //只有上面对结点3写入数据后,才可以运行到这里,才可以每10ms产生IN中断.发送按键值.
        }
    }

使用特权

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

本版积分规则

2

主题

12

帖子

0

粉丝