打印

USB枚举问题

[复制链接]
4530|21
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
沙发
ranxiaokang|  楼主 | 2013-4-10 14:27 | 只看该作者
比如最后剩下12个字节数据,我发送到了端点0的缓冲区,主机并没有发起IN传输将这几个字节数据读走,就没有谁帮帮我吗。

使用特权

评论回复
板凳
john_lee| | 2013-4-10 17:05 | 只看该作者
HID descriptor 中的 wDescriptorLength 是不是写小了?

使用特权

评论回复
地板
jornny520| | 2013-4-10 23:28 | 只看该作者
我也是刚学,,说一下,也不清楚是不是你想要的答案。主机在一开始的时候 并不是读取description里面的全部数据,而是先读部分,第一次的数据里面告诉了主机description的长度,后面他会再发一次指令要求输入全部的数据。

使用特权

评论回复
5
ranxiaokang|  楼主 | 2013-4-11 10:01 | 只看该作者
john_lee 发表于 2013-4-10 17:05
HID descriptor 中的 wDescriptorLength 是不是写小了?

HID描述符的length没有写少

使用特权

评论回复
6
ranxiaokang|  楼主 | 2013-4-11 10:02 | 只看该作者
jornny520 发表于 2013-4-10 23:28
我也是刚学,,说一下,也不清楚是不是你想要的答案。主机在一开始的时候 并不是读取description里 ...

报告描述符的长度从配置描述符中已知了,只需要获取完全就是了。

使用特权

评论回复
7
john_lee| | 2013-4-11 11:57 | 只看该作者
ranxiaokang 发表于 2013-4-11 10:01
HID描述符的length没有写少

不是hid descriptor的length,而是hid descriptor中的每个report 的 length:

使用特权

评论回复
8
ranxiaokang|  楼主 | 2013-4-11 14:59 | 只看该作者
john_lee 发表于 2013-4-11 11:57
不是hid descriptor的length,而是hid descriptor中的每个report 的 length:

谢谢版主的回答,这个是没有写少的。

使用特权

评论回复
9
ranxiaokang|  楼主 | 2013-4-12 10:06 | 只看该作者
描述符如下
unsigned char code device_descriptor[] = {
        0x12,                /* bLength */
        0x01,                /* bDescriptor */
        0x10, 0x01,        /* bcdUSB */
        0x00,                /* bDeviceClass */
        0x00,                /* bDeviceSubClass */
        0x00,                /* bDevcieProtocol */
        //0x40,                /* bMaxPacketSize */
        0x10,                /* bMaxPacketSize */
        0x00, 0x80,        /* idVendor */
        0x01, 0x00,        /* idProduct */
        0x00, 0x01,        /* bcdDevice */
        0x00,//0x01,                /* iManufacturer */
        0x00,//0x02,                /* iProduct */
        0x00,                /* iSerialNumber */
        0x01                /* bNumConfigurations */
};

unsigned char code config_descriptor[] = {
        /* usb configuration descriptor */
        0x09,                /* bLength */
        0x02,                /* bDescriptorType */
        0x22, 0x00,        /* wTotalLength */
        0x01,                /* bNumInterfaces */
        0x01,                /* bConfigurationValue */
        0x00,                /* iConfiguration */
        0x80,                /* bmAttributes */
        0x32,                /* bMaxPower */

        /* usb interface descriptor */
        0x09,                /* bLength */
        0x04,                /* bDescriptorType */
        0x00,                /* bInterfaceNumber */
        0x00,                /* bAlternateSetting */
        0x01,                /* bNumEndpoints */
        0x03,                /* bInterfaceClass */
        0x01,                /* bInterfaceSubClass */
        0x01,                /* bInterfaceProtocol */
        0x00,                /* iInterface */

        /* usb hid descriptor */
        0x09,                /* bLength */
        0x21,                /* bDescriptorType */
        0x01, 0x01,        /* bcdHID */
        0x00,                /* bCountryCode */
        0x01,                /* bNumDescriptor */
        0x22,                /* wDescriptorType */
        0x2d, 0x00,        /* wDescriptorLength */

        /* usb endpoint descriptor */
        0x07,                /* bLength */
        0x05,                /* bDescriptorType */
        0x81,                /* bEndpointAddress */
        0x03,                /* bmAttributes */
        0x08, 0x00,        /* wMaxPacketSize */
        0x0a                /* bInterval */
};

//#define USB_KEYBOARD_USE_LED                1
#define REPORT_DESCRIPTOR_SIZE                0x3f
#define REPORT_DESCRIPTOR_NOLED_SIZE        0x2d

/*
* 键盘有输入报告和输出报告,其中输入报告8个字节,输出报告1个字节
* 输入报告格式如下:
* [Key6][Key5][Key4][Key3][Key2][Key1][Reserved][Function Key]
* 输出报告格式如下:
* 7~5                4        3        2                1                0
* Reserved        Kana        Compose        Scroll Lock        Caps Lock        Num Lock
*/
unsigned char code report_descriptor[] = {
        0x05, 0x01,        /* Usage Page(Generic Desktop) */
        0x09, 0x06,        /* Usage(Keyboard) */
        0xa1, 0x01,        /* Collection(Application) */

        /* function key, such as Ctrl, Shift... */
        0x05, 0x07,        /* Usage Page(Keyboard) */
        0x19, 0xe0,        /* Usage Minimum(Keyboard LeftControl) */
        0x29, 0xe7,        /* Usage Maximum(Keyboard Right GUI) */
        0x15, 0x00,        /* Logical Minimum(0) */
        0x25, 0x01,        /* Logical Maximum(1) */
        0x75, 0x01,        /* Report Size(1) */
        0x95, 0x08,        /* Report Count(8) */
        0x81, 0x02,        /* Input(Data, Variable, Absolute) */

        /* byte for reserved */
        0x95, 0x01,        /* Report Count(1) */
        0x75, 0x08,        /* Report Size(8) */
        0x81, 0x01,        /* Input(Constant) */

#ifdef USB_KEYBOARD_USE_LED
        /* for LED */
        0x95, 0x05,        /* Report Count(5) */
        0x75, 0x01,        /* Report Size(1) */
        0x05, 0x08,        /* Usage Page(for LEDs) */
        0x19, 0x01,        /* Usage Minimum(Num Lock) */
        0x29, 0x05,        /* Usage Maximum(Kana) */
        0x91, 0x02,        /* Output(Data, Variable, Absolute) */
        0x95, 0x01,        /* Report Count(1) */
        0x75, 0x03,        /* Report Size(3) */
        0x91, 0x01,        /* Output(Constant) */
#endif
        /* generic key */
        0x95, 0x06,        /* Report Count(6) */
        0x75, 0x08,        /* Report Size(8) */
        0x15, 0x00,        /* Logical Minimum(0) */
        0x25, 0x65,        /* Logical Maximum(101) */
        0x05, 0x07,        /* Usage Page(Key Codes) */
        0x19, 0x00,        /* Usage Minimum(0) */
        0x29, 0x65,        /* Usage Maximum(101) */
        0x81, 0x00,        /* Input(Data, Array) */

        0xc0                /* End Collection */
};

使用特权

评论回复
10
ranxiaokang|  楼主 | 2013-4-12 10:08 | 只看该作者
报告描述符长度为0x2d时,有0x0d字节未获取,如果是0x3f,则有0x0f字节未获取,感觉是丢掉了少于端点0最大数据包长度的数据。

使用特权

评论回复
11
ranxiaokang|  楼主 | 2013-4-12 10:11 | 只看该作者
以下是枚举过程的代码:
#include "types.h"
#include "printf.h"
#include "time.h"
#include "d12.h"
#include "ch9.h"
#include "usb.h"
#include "hid.h"


struct usb_device idata                device;

void usb_interrupt_handler(void) interrupt 0
//void usb_interrupt_handler(void)
{
        struct usb_device *idata dev = &device;
        u16 idata status;

        status = d12_read_interrupt_status();
        //printf("status %x\r\n", (int)status);
        switch (status) {
        case D12_INT_BUS_RESET:
                //printf("usb bus reset.\r\n");
                break;
        case D12_INT_SUSPEND_CHANGE:
                //printf("usb bus suspend.\r\n");
                break;
        case D12_INT_EPT0_OUT:
                ept0out_event_handler(dev);
                break;
        case D12_INT_EPT0_IN:
                ept0in_event_handler(dev);
                break;
        case D12_INT_EPT1_OUT:
                break;
        case D12_INT_EPT1_IN:
                d12_read_trans_status(D12_EPT1_IN);
                break;
        default:
                break;
        }
}

void ept0out_event_handler(struct usb_device *dev)
{
        struct usb_setup_packet *idata pkt;
        u8 idata buf[8];
        u8 idata status;

        status = d12_read_trans_status(D12_EPT0_OUT);
        pkt = (struct usb_setup_packet *)buf;

        //buf[0] = 0x80;
        //puts("ept0out_event_handler\r\n");
        if (status & D12_TRANS_STATUS_SETUP_PACKET) {
                d12_read_buffer(D12_EPT0_OUT, buf, 8);
                //printf("bmRequestType 0x%x bRequest 0x%x wValue 0x%x wIndex 0x%x wLength 0x%x\r\n",
                //        (int)pkt->bmRequestType, (int)pkt->bRequest, (int)pkt->wValue, (int)pkt->wIndex, (int)pkt->wLength);
                //printf("bRequest 0x%x\r\n", (int)pkt->bRequest);
                //printf("bmRequestType %x\r\n", (int)buf[0]);
                //printf("bRequest %x\r\n", buf[1]);
                //puts("usb setup request\r\n");
                //printf("读端点0缓冲区8个字节\r\n");
                //printf("0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\r\n",
                //        (int)buf[0], (int)buf[1], (int)buf[2], (int)buf[3], (int)buf[4], (int)buf[5], (int)buf[6], (int)buf[7], (int)buf[8]);
                d12_ack_setup();
                d12_clear_buffer();
                usb_setup_request(dev, pkt);
        } else {
                d12_read_buffer(D12_EPT0_OUT, buf, 8);
                //d12_ack_setup();
                d12_clear_buffer();
        }
}

void usb_setup_request(struct usb_device *dev, struct usb_setup_packet *pkt)
{
        switch (pkt->bmRequestType & USB_TYPE_MASK) {
        case USB_TYPE_STANDARD:
                //puts("usb standard request\r\n");
                usb_standard_request(dev, pkt);
                break;
        case USB_TYPE_CLASS:
                usb_class_request(dev, pkt);
                break;
        default:
                break;
        }

        if (pkt->bmRequestType & 0x80) {
                dev->dir = USB_DIR_IN;
                usb_control_transfer(dev);
        } else {
                dev->dir = USB_DIR_OUT;
                //d12_write_buffer(D12_EPT0_IN, (u8 *)0, 0);
                usb_control_transfer(dev);
        }
       
}

void usb_standard_request(struct usb_device *dev, struct usb_setup_packet *pkt)
{
        //struct usb_request
        u16 idata value = le16_to_cpu(pkt->wValue);
        u16 idata index = le16_to_cpu(pkt->wIndex);
        u16 idata length = le16_to_cpu(pkt->wLength);

        //printf("length = %x\r\n", (int)length);
        switch (pkt->bRequest) {
        case USB_REQ_GET_STATUS:
                //puts("get status\r\n");
                break;
        case USB_REQ_CLEAR_FEATURE:
                //puts("clear feature\r\n");
                break;
        //case USB_REQ_SET_FEATURE:
        //        break;
        case USB_REQ_SET_FEATURE:
                //puts("set feature\r\n");
                break;
        case USB_REQ_SET_ADDRESS:
                d12_set_address((u8)value);
                //d12_write_buffer(D12_EPT0_IN, (u8 *)0, 0); /* return zero-length data packet */
                usb_set_device_state(dev, USB_STATE_ADDRESS);
                //puts("set address\r\n");
                break;
        case USB_REQ_GET_DESCRIPTOR:
                //printf("length = %x\r\n", length);
                switch (value >> 8) {
                case USB_DT_DEVICE:
                        dev->buf = device_descriptor;
                        dev->size = MIN(0x12, length);
                        //puts("get device descriptor\r\n");
                        break;
                case USB_DT_CONFIG:
                        dev->buf = config_descriptor;
                        //dev->size = MIN(0x43, length);
                        dev->size = MIN(0x22, length);
                        //puts("get config descriptor\r\n");
                        break;
                case USB_DT_STRING:
                        break;
                case USB_DT_REPORT:
                        dev->buf = report_descriptor;
                        dev->size = MIN(0x2d, length);
                        //printf("get report descriptor\r\n");
                        //dev->size = 0x2d;
                        break;
                }
                //puts("get device descriptor\r\n");
                //usb_control_transfer(dev);
                break;
        case USB_REQ_SET_DESCRIPTOR:
                //puts("set descriptor\r\n");
                break;
        case USB_REQ_GET_CONFIGURATION:
                dev->buf = &dev->config;
                dev->size = 1;
                //puts("get config\r\n");
                //usb_control_transfer(dev);
                break;
        case USB_REQ_SET_CONFIGURATION:
                dev->config = (u8)value;
                //d12_endpoint_enable(ENABLE);
                d12_endpoint_enable(1);
                //d12_write_buffer(D12_EPT0_IN, (u8 *)0, 0);
                usb_set_device_state(dev, USB_STATE_CONFIGURED);
                //puts("set config\r\n");
                break;
        case USB_REQ_GET_INTERFACE:
                //d12_write_buffer(D12_EPT0_IN, (u8 *)0, 0);
                //puts("get interface\r\n");
                break;
        case USB_REQ_SET_INTERFACE:
                //puts("set interface\r\n");
                break;
        default:
                break;
        }
}

void usb_class_request(struct usb_device *dev, struct usb_setup_packet *pkt)
{
        hid_class_request(dev, pkt);
}

void ept0in_event_handler(struct usb_device *dev)
{
        //puts("ept0in_event_handler\r\n");
        d12_read_trans_status(D12_EPT0_IN);
       
        usb_control_transfer(dev);
}

void usb_control_transfer(struct usb_device *dev)
{
        u8 code buf_size = 16;
        u8 idata len;

        //printf("size %x\r\n", (int)dev->size);
        //puts("control transfer\r\n");
        if (dev->dir == USB_DIR_IN) {
                //puts("control transfer\r\n");
                //printf("size %x\r\n", (int)dev->size);
                if (dev->size != 0) {
                        if (dev->size >= buf_size) {
                                len = buf_size;
                                dev->size -= len;
                        } else {
                                len = dev->size;
                                dev->size = 0;
                        }
                        //dev->size -= len;

                        d12_write_buffer(D12_EPT0_IN, dev->buf, len);
                        dev->buf += len;
                }
        } else {
                d12_write_buffer(D12_EPT0_IN, (u8 *)0, 0);
        }
}

void usb_set_device_state(struct usb_device *dev, enum usb_device_state new_state)
{
        dev->state = new_state;
}

enum usb_device_state usb_get_device_state(void)
{
        struct usb_device *dev = &device;

        return &dev->state;
}

u8 usb_init(void)
{
        u16 chip_id;

        chip_id = d12_read_id();
        if (chip_id != D12_CHIP_ID) {
                printf("d12 is not working.\r\n");
                return -1;
        }

        d12_disconnect();
        delayms(100);
        d12_init();

        return 0;
}

使用特权

评论回复
12
ranxiaokang|  楼主 | 2013-4-12 10:13 | 只看该作者
获取设备描述符、配置描述符都是对的,希望大虾们帮我看看是哪里出了问题。

使用特权

评论回复
13
ranxiaokang|  楼主 | 2013-4-16 16:47 | 只看该作者
:(

使用特权

评论回复
14
liyihong028| | 2013-4-16 23:40 | 只看该作者
device_descriptor[]中的bMaxPacketSize应该为0x40,而不是0x10.

使用特权

评论回复
15
ranxiaokang|  楼主 | 2013-4-20 10:52 | 只看该作者
本帖最后由 ranxiaokang 于 2013-4-20 11:02 编辑
liyihong028 发表于 2013-4-16 23:40
device_descriptor[]中的bMaxPacketSize应该为0x40,而不是0x10.

device_descriptor[]中的bMaxPacketSize表示端点0的最大传输能力,d12就是16个字节,而不是64个字节。

使用特权

评论回复
16
jiege0129| | 2013-4-22 11:35 | 只看该作者
报告描述符的长度为63,而你在hid描述符中写0x2d,改为63应该就可以了,还有,你报告描述符中有输出功能,但是你没有定义输出端点,应该增加一个端点作为输出。

使用特权

评论回复
17
ranxiaokang|  楼主 | 2013-4-22 14:11 | 只看该作者
jiege0129 发表于 2013-4-22 11:35
报告描述符的长度为63,而你在hid描述符中写0x2d,改为63应该就可以了,还有,你报告描述符中有输出功能, ...

不是这个问题啊,报告描述符中如果使用LED,那么描述符长度为63,如果不使用LED的话,长度就是0x2d,也就不需要输出端点了。

使用特权

评论回复
18
jiege0129| | 2013-4-22 16:44 | 只看该作者
ranxiaokang 发表于 2013-4-22 14:11
不是这个问题啊,报告描述符中如果使用LED,那么描述符长度为63,如果不使用LED的话,长度就是0x2d,也就 ...

对啊,那你描述符里有写啊,这样后面的数据就忽略了,oxc0不就也会被忽略吗

使用特权

评论回复
19
ranxiaokang|  楼主 | 2013-4-22 16:55 | 只看该作者
jiege0129 发表于 2013-4-22 16:44
对啊,那你描述符里有写啊,这样后面的数据就忽略了,oxc0不就也会被忽略吗 ...

我有宏定义会忽略这部分的定义。

使用特权

评论回复
20
jiege0129| | 2013-4-22 19:10 | 只看该作者
ranxiaokang 发表于 2013-4-22 16:55
我有宏定义会忽略这部分的定义。

哦,看到了,那描述符应该是没问题,那你枚举成功了吗,用bus hound抓的数据确实是不完全的,至少报告描述符不能全部抓到。

使用特权

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

本版积分规则

1

主题

14

帖子

1

粉丝