case TYPE_CONFIGURATION_DESCRIPTOR: printf("\n\rConfiguration Descriptor: Bytes Asked For %d, Size of Descriptor %d\n\r", \ SetupPacket->wLength, sizeof(ConfigurationDescriptor)); pSendBuffer = (const unsigned char *)&ConfigurationDescriptor; BytesToSend = sizeof(ConfigurationDescriptor); if (BytesToSend > SetupPacket->wLength) BytesToSend = SetupPacket->wLength; WriteBufferToEndPoint(); break; } void WriteBufferToEndPoint(void) { if (BytesToSend == 0) { D11WriteEndpoint(D11_ENDPOINT_EP0_IN, NULL, 0); } else if (BytesToSend >= 8) { D11WriteEndpoint(D11_ENDPOINT_EP0_IN, pSendBuffer, 8); pSendBuffer += 8; BytesToSend -= 8; } else { D11WriteEndpoint(D11_ENDPOINT_EP0_IN, pSendBuffer, BytesToSend); BytesToSend = 0; } void loadfromcircularbuffer(void) { unsigned char Buffer[10]; unsigned char count; D11CmdDataRead(D11_ENDPOINT_EP1_IN, Buffer, 1); if (Buffer[0] == 0){ if (inpointer != outpointer){ count = 0; do { Buffer[count++] = circularbuffer[outpointer++]; if (outpointer >= MAX_BUFFER_SIZE) outpointer = 0; if (outpointer == inpointer) break; // No more data } while (count < 8); // Maximum Buffer Size D11WriteEndpoint(D11_ENDPOINT_EP1_IN, Buffer, count); } const USB_DEVICE_DESCRIPTOR DeviceDescriptor = { sizeof(USB_DEVICE_DESCRIPTOR), /* bLength */ TYPE_DEVICE_DESCRIPTOR, /* bDescriptorType */ 0x0110, /* bcdUSB USB Version 1.1 */ 0, /* bDeviceClass */ 0, /* bDeviceSubclass */ 0, /* bDeviceProtocol */ 8, /* bMaxPacketSize 8 Bytes */ 0x04B4, /* idVendor (Cypress Semi) */ 0x0002, /* idProduct (USB Thermometer Example) */ 0x0000, /* bcdDevice */ 1, /* iManufacturer String Index */ 0, /* iProduct String Index */ 0, /* iSerialNumber String Index */ 1 /* bNumberConfigurations */ }; if(Irq & D11_INT_EP2_OUT) { printf("EP2_OUT\n\r"); D11CmdDataRead(D11_READ_LAST_TRANSACTION + D11_ENDPOINT_EP2_OUT, Buffer, 1); Buffer[0] = 0x01; /* Stall Endpoint */ D11CmdDataWrite(D11_SET_ENDPOINT_STATUS + D11_ENDPOINT_EP2_OUT, Buffer, 1); } if(Irq & D11_INT_EP2_IN) { printf("EP2_IN\n\r"); D11CmdDataRead(D11_READ_LAST_TRANSACTION + D11_ENDPOINT_EP2_IN, Buffer, 1); Buffer[0] = 0x01; /* Stall Endpoint */ D11CmdDataWrite(D11_SET_ENDPOINT_STATUS + D11_ENDPOINT_EP2_IN, Buffer, 1); } if(Irq & D11_INT_EP3_OUT) { printf("EP3_OUT\n\r"); D11CmdDataRead(D11_READ_LAST_TRANSACTION + D11_ENDPOINT_EP3_OUT, Buffer, 1); Buffer[0] = 0x01; /* Stall Endpoint */ D11CmdDataWrite(D11_SET_ENDPOINT_STATUS + D11_ENDPOINT_EP3_OUT, Buffer, 1); } if(Irq & D11_INT_EP3_IN) { printf("EP3_IN\n\r"); D11CmdDataRead(D11_READ_LAST_TRANSACTION + D11_ENDPOINT_EP3_IN, Buffer, 1); Buffer[0] = 0x01; /* Stall Endpoint */ D11CmdDataWrite(D11_SET_ENDPOINT_STATUS + D11_ENDPOINT_EP3_IN, Buffer, 1); } }if(Irq & D11_INT_EP1_OUT) { printf("EP1_OUT\n\r"); D11CmdDataRead(D11_READ_LAST_TRANSACTION + D11_ENDPOINT_EP1_OUT, Buffer, 1); bytes = D11ReadEndpoint(D11_ENDPOINT_EP1_OUT, Buffer); for (count = 0; count < bytes; count++) { circularbuffer[inpointer++] = Buffer[count]; if (inpointer >= MAX_BUFFER_SIZE) inpointer = 0; } loadfromcircularbuffer(); //Kick Start }if(Irq & D11_INT_EP1_IN) { printf("EP1_IN\n\r"); D11CmdDataRead(D11_READ_LAST_TRANSACTION + D11_ENDPOINT_EP1_IN, Buffer, 1); loadfromcircularbuffer(); } const USB_CONFIG_DATA ConfigurationDescriptor = { { /* configuration descriptor */ sizeof(USB_CONFIGURATION_DESCRIPTOR), /* bLength */ TYPE_CONFIGURATION_DESCRIPTOR, /* bDescriptorType */ sizeof(USB_CONFIG_DATA), /* wTotalLength */ 1, /* bNumInterfaces */ 1, /* bConfigurationValue */ 0, /* iConfiguration String Index */ 0x80, /* bmAttributes Bus Powered, No Remote Wakeup */ 0x32 /* bMaxPower, 100mA */ }, { /* interface descriptor */ sizeof(USB_INTERFACE_DESCRIPTOR), /* bLength */ TYPE_INTERFACE_DESCRIPTOR, /* bDescriptorType */ 0, /* bInterface Number */ 0, /* bAlternateSetting */ 2, /* bNumEndpoints */ 0xFF, /* bInterfaceClass (Vendor specific) */ 0xFF, /* bInterfaceSubClass */ 0xFF, /* bInterfaceProtocol */ 0 /* iInterface String Index */ }, { /* endpoint descriptor */ sizeof(USB_ENDPOINT_DESCRIPTOR), /* bLength */ TYPE_ENDPOINT_DESCRIPTOR, /* bDescriptorType */ 0x01, /* bEndpoint Address EP1 OUT */ 0x02, /* bmAttributes - Interrupt */ 0x0008, /* wMaxPacketSize */ 0x00 /* bInterval */ }, { /* endpoint descriptor */ sizeof(USB_ENDPOINT_DESCRIPTOR), /* bLength */ TYPE_ENDPOINT_DESCRIPTOR, /* bDescriptorType */ 0x81, /* bEndpoint Address EP1 IN */ 0x02, /* bmAttributes - Interrupt */ 0x0008, /* wMaxPacketSize */ 0x00 /* bInterval */ } }; pPacke upPacket->wLeng ufferToEndPoint(); ase TYPE_DEVICE_DES escri ength) iteBuffe nt(); case TYPE_C ATION fig. pSendBuffer=(const unsigned char *)&DeviceDescriptor;BytesToSe if (BytesToSend>SetupPacket->wLength) BytesToSend= SetupPacket-> SetupPacket->wLength, sizeof(ConfigurationDescriptor));BytesTo Buffer[count rbuff 0x07 (outpoin _SIZE =0xC1|( cket.wInd INT_EP0_IN,Buffer,2 RTB=(PORTB&0x0F)| rolEndPoi __ _______ ____ / / / / ___// __ ) / / / /\__ \/ __ | / /_/ /___/ / /_/ / \____//____/_____/ Guilherme Krause Valter Toffolo PUCRS 2007/2 Programação de Periféricos - T590 professor Eduardo Bezerra _____ ____ _____________ _____ ____ ______ / ___// __ \/ ____/_ __/ | / / | / __ \/ ____/ \__ \/ / / / /_ / / | | /| / / /| | / /_/ / __/ ___/ / /_/ / __/ / / | |/ |/ / ___ |/ _, _/ /___ /____/\____/_/ /_/ |__/|__/_/ |_/_/ |_/_____/ ____ / \ / \____/
FUNCTIONS, ENDPOINTS e PIPES HUBS e FUNCTIONS dispositivos usb podem ser hub ou function, ou várias functions ligadas a um hub. ex: uma webcam com microfone cada function corresponde a uma classe usb (mass storage device, HID keyboard, etc) ENDPOINTS parte do dispositivo usb onde termina uma conexão lógica cada function pode ter vários endpoints em hardware, corresponde a um buffer de I/O PIPES conexão lógica entre o host e um endpoint são unidirecionais, exceto para endpoints de controle
FUNCTIONS, ENDPOINTS e PIPES
COMUNICAÇÃO - pacotes TOKEN PID: pode ser IN, OUT, SETUP, SOF ADDR: endereço do dispositivo ENDP: endpoint do dispositivo endereçado DATA PID: pode ser DATA0, DATA1, e também DATA2, MDATA para high speed DATA: tamanho variável tamanho menor que o máximo indica que é o ultimo pacote de dados HANDSHAKE PID: pode ser ACK, NAK, STALL, NYET quando a tranferencia termina com sucesso, é enviado ack nak geralmente informa que não foi possivel transmitir, mas não é erro quando ocorre um erro, é enviado um stall SYNC[8/8/32]PID [4+^4]ADDR[7]ENDP[4]CRC[5]EOP[3]DATA[8/1023/1024CRC[16]EOP[3]SYNC[8/8/32]PID [4+^4]SYNC[8/8/32]PID [4+^4]EOP[3]
COMUNICAÇÃO - fluxo Iniciada pelo host, através de um token packet. O token define a direção da comunicação. host <- device: no lugar do data packet, o device pode responder com um handshake do tipo nak caso não tenha dados a enviar, um stall em caso de erro interno. host <- device: caso o device não esteja pronto para receber o pacote (buffer cheio), o handshake será do tipo no caso de receber dados inválidos, não é enviado handshake, e o envio é feito novamente para isochronous transfers não há handshake packet from hostpacket from device handshake : nak handshake : stall token : outdataHandshake : ack handshake : nak handshake : stall token : inHandshake : ackdata handshake : nak handshake : stall
ENDPOINTS - modos de transferencia CONTROL permitido somente através de control pipes geralmente usado para comandos e status, por ter entrega garantida é o modo usado no endpoint0, para configurar o device e ler os descritores BULK usado para grandes quantidades de dados entrega garantida e integridade verificada por crc não garante latencia baixa nem transferência rápida INTERRUPT baixa latencia, entrega e integridade garantidas host faz polling em intervalo definido. ISOCHRONOUS velocidade garantida, baixa latencia, transferencia contínua entrega não garantida (não tem pacote de handshake)
DESCRIPTORS DEFINIÇÃO estruturas de dados com informações sobre o dispositivo são requisitadas pelo host na ocasião da enumeração CARACTERÍSTICAS permite que o host identifique o dispositivo possibilita múltiplas configurações
DESCRIPTORS - exemplo CELULAR mass storage device webcam modos camera/foto carga pela usb DEVICE USB: 2.0 Class/SubClass: 0 pktsz: 8 VID/PID/rev: NumConfigs: 2 EP ID: 1 inout: in type: bulk pktsz: 64 intfreq: 0 ID: 2 inout: out type: bulk pktsz: 64 intfreq: 0 EP ID: 1 inout: in type: iso pktsz: 64 intfreq: 1 EP ID: 1 inout: in type: bulk pktsz: 64 intfreq: 0 EP ID: 1 inout: in type: bulk pktsz: 64 intfreq: 0 EP ID: 2 inout: out type: bulk pktsz: 64 intfreq: 0 EP ID: 1 inout: - type: ctrl pktsz: 8 intfreq: - EP ID: 2 inout: in type: int pktsz: 8 intfreq: 50 EPINTERFACE class: MSD ID: 0 alt_setting: 0 num_endpoints: 3 INTERFACE class: 0 ID: 2 alt_setting: 0 num_endpoints: 3 INTERFACE class: photo ID: 1 alt_setting: 1 num_endpoints: 2 class: cam ID: 1 alt_setting: 0 num_endpoints: 2 INTERFACE class: MSD ID: 0 alt_setting: 0 num_endpoints: 3 INTERFACECONFIG ID: 1 power: self maxpower: 0 num_ifaces: 1 ID: 0 power: bus maxpower: 255 num_ifaces: 4 CONFIG
DESCRIPTORS - exemplo DEVICE: apenas um descritor desse tipo identifica o dispositivo fisico, fabricante e modelo permite informar classe, para buscar driver paket size referente aos endpoint0 exemplo: usb 2.0, classe será informada nas interfaces, ep0 tem buffer de 8 bytes DEVICE USB: 2.0 Class/SubClass: 0 pktsz: 8 VID/PID/rev: NumConfigs: 2 EP ID: 1 inout: in type: bulk pktsz: 64 intfreq: 0 ID: 2 inout: out type: bulk pktsz: 64 intfreq: 0 EP ID: 1 inout: in type: iso pktsz: 64 intfreq: 1 EP ID: 1 inout: in type: bulk pktsz: 64 intfreq: 0 EP ID: 1 inout: in type: bulk pktsz: 64 intfreq: 0 EP ID: 2 inout: out type: bulk pktsz: 64 intfreq: 0 EP ID: 1 inout: - type: ctrl pktsz: 8 intfreq: - EP ID: 2 inout: in type: int pktsz: 8 intfreq: 50 EPINTERFACE class: MSD ID: 0 alt_setting: 0 num_endpoints: 3 INTERFACE class: 0 ID: 2 alt_setting: 0 num_endpoints: 3 INTERFACE class: photo ID: 1 alt_setting: 1 num_endpoints: 2 class: cam ID: 1 alt_setting: 0 num_endpoints: 2 INTERFACE class: MSD ID: 0 alt_setting: 0 num_endpoints: 3 INTERFACECONFIG ID: 1 power: self maxpower: 0 num_ifaces: 1 ID: 0 power: bus maxpower: 255 num_ifaces: 4 CONFIG
DESCRIPTORS - exemplo CONFIGS: raramente tem mais de um config descriptor define os requisitos de alimentacao tem um conjunto especifico de interfaces exemplo: configuracao alternativa sem alimentacao pela usb, caso seja um laptop. apenas MSD disponivel nesse modo DEVICE USB: 2.0 Class/SubClass: 0 pktsz: 8 VID/PID/rev: NumConfigs: 2 EP ID: 1 inout: in type: bulk pktsz: 64 intfreq: 0 ID: 2 inout: out type: bulk pktsz: 64 intfreq: 0 EP ID: 1 inout: in type: iso pktsz: 64 intfreq: 1 EP ID: 1 inout: in type: bulk pktsz: 64 intfreq: 0 EP ID: 1 inout: in type: bulk pktsz: 64 intfreq: 0 EP ID: 2 inout: out type: bulk pktsz: 64 intfreq: 0 EP ID: 1 inout: - type: ctrl pktsz: 8 intfreq: - EP ID: 2 inout: in type: int pktsz: 8 intfreq: 50 EPINTERFACE class: MSD ID: 0 alt_setting: 0 num_endpoints: 3 INTERFACE class: 0 ID: 2 alt_setting: 0 num_endpoints: 3 INTERFACE class: photo ID: 1 alt_setting: 1 num_endpoints: 2 class: cam ID: 1 alt_setting: 0 num_endpoints: 2 INTERFACE class: MSD ID: 0 alt_setting: 0 num_endpoints: 3 INTERFACECONFIG ID: 1 power: self maxpower: 0 num_ifaces: 1 ID: 0 power: bus maxpower: 255 num_ifaces: 4 CONFIG
DESCRIPTORS - exemplo INTERFACE: define a classe da function pode ter uma configuracao alternativa exemplo: interface1 tem duas configurações, com endpoints diferentes, permitindo alterar endpoint1 sem interferir no endpoint0 DEVICE USB: 2.0 Class/SubClass: 0 pktsz: 8 VID/PID/rev: NumConfigs: 2 EP ID: 1 inout: in type: bulk pktsz: 64 intfreq: 0 ID: 2 inout: out type: bulk pktsz: 64 intfreq: 0 EP ID: 1 inout: in type: iso pktsz: 64 intfreq: 1 EP ID: 1 inout: in type: bulk pktsz: 64 intfreq: 0 EP ID: 1 inout: in type: bulk pktsz: 64 intfreq: 0 EP ID: 2 inout: out type: bulk pktsz: 64 intfreq: 0 EP ID: 1 inout: - type: ctrl pktsz: 8 intfreq: - EP ID: 2 inout: in type: int pktsz: 8 intfreq: 50 EPINTERFACE class: MSD ID: 0 alt_setting: 0 num_endpoints: 3 INTERFACE class: 0 ID: 2 alt_setting: 0 num_endpoints: 3 INTERFACE class: photo ID: 1 alt_setting: 1 num_endpoints: 2 class: cam ID: 1 alt_setting: 0 num_endpoints: 2 INTERFACE class: MSD ID: 0 alt_setting: 0 num_endpoints: 3 INTERFACECONFIG ID: 1 power: self maxpower: 0 num_ifaces: 1 ID: 0 power: bus maxpower: 255 num_ifaces: 4 CONFIG
DESCRIPTORS - exemplo ENDPOINTS: sempre existe UM endpoint0 por interface define a direção do pipe e tipo de transação pktsz corresponde ao buffer em hw exemplo: interface msd tem um endpoint de entrada e um de saída. DEVICE USB: 2.0 Class/SubClass: 0 pktsz: 8 VID/PID/rev: NumConfigs: 2 EP ID: 1 inout: in type: bulk pktsz: 64 intfreq: 0 ID: 2 inout: out type: bulk pktsz: 64 intfreq: 0 EP ID: 1 inout: in type: iso pktsz: 64 intfreq: 1 EP ID: 1 inout: in type: bulk pktsz: 64 intfreq: 0 EP ID: 1 inout: in type: bulk pktsz: 64 intfreq: 0 EP ID: 2 inout: out type: bulk pktsz: 64 intfreq: 0 EP ID: 1 inout: - type: ctrl pktsz: 8 intfreq: - EP ID: 2 inout: in type: int pktsz: 8 intfreq: 50 EPINTERFACE class: MSD ID: 0 alt_setting: 0 num_endpoints: 3 INTERFACE class: 0 ID: 2 alt_setting: 0 num_endpoints: 3 INTERFACE class: photo ID: 1 alt_setting: 1 num_endpoints: 2 class: cam ID: 1 alt_setting: 0 num_endpoints: 2 INTERFACE class: MSD ID: 0 alt_setting: 0 num_endpoints: 3 INTERFACECONFIG ID: 1 power: self maxpower: 0 num_ifaces: 1 ID: 0 power: bus maxpower: 255 num_ifaces: 4 CONFIG
IMPLEMENTAÇÕES – linux KERNEL LEVEL URBS são USB Request Blocks API fornecida pelo kernel para comunicar com a usb em um nível mais alto a comunicação é assíncrona, com handlers para tratar o fim da transferência TRANSFERS é o nível mais baixo, que é abstraído pelos URBs são transferências síncronas USER LEVEL LIBUSB permite a comunicação com dispositivos usb em nível de usuário ainda não é muito usada não chegou na versão 1.0 ainda
case TYPE_CONFIGURATION_DESCRIPTOR: printf("\n\rConfiguration Descriptor: Bytes Asked For %d, Size of Descriptor %d\n\r", \ SetupPacket->wLength, sizeof(ConfigurationDescriptor)); pSendBuffer = (const unsigned char *)&ConfigurationDescriptor; BytesToSend = sizeof(ConfigurationDescriptor); if (BytesToSend > SetupPacket->wLength) BytesToSend = SetupPacket->wLength; WriteBufferToEndPoint(); break; } void WriteBufferToEndPoint(void) { if (BytesToSend == 0) { D11WriteEndpoint(D11_ENDPOINT_EP0_IN, NULL, 0); } else if (BytesToSend >= 8) { D11WriteEndpoint(D11_ENDPOINT_EP0_IN, pSendBuffer, 8); pSendBuffer += 8; BytesToSend -= 8; } else { D11WriteEndpoint(D11_ENDPOINT_EP0_IN, pSendBuffer, BytesToSend); BytesToSend = 0; } void loadfromcircularbuffer(void) { unsigned char Buffer[10]; unsigned char count; D11CmdDataRead(D11_ENDPOINT_EP1_IN, Buffer, 1); if (Buffer[0] == 0){ if (inpointer != outpointer){ count = 0; do { Buffer[count++] = circularbuffer[outpointer++]; if (outpointer >= MAX_BUFFER_SIZE) outpointer = 0; if (outpointer == inpointer) break; // No more data } while (count < 8); // Maximum Buffer Size D11WriteEndpoint(D11_ENDPOINT_EP1_IN, Buffer, count); } const USB_DEVICE_DESCRIPTOR DeviceDescriptor = { sizeof(USB_DEVICE_DESCRIPTOR), /* bLength */ TYPE_DEVICE_DESCRIPTOR, /* bDescriptorType */ 0x0110, /* bcdUSB USB Version 1.1 */ 0, /* bDeviceClass */ 0, /* bDeviceSubclass */ 0, /* bDeviceProtocol */ 8, /* bMaxPacketSize 8 Bytes */ 0x04B4, /* idVendor (Cypress Semi) */ 0x0002, /* idProduct (USB Thermometer Example) */ 0x0000, /* bcdDevice */ 1, /* iManufacturer String Index */ 0, /* iProduct String Index */ 0, /* iSerialNumber String Index */ 1 /* bNumberConfigurations */ }; if(Irq & D11_INT_EP2_OUT) { printf("EP2_OUT\n\r"); D11CmdDataRead(D11_READ_LAST_TRANSACTION + D11_ENDPOINT_EP2_OUT, Buffer, 1); Buffer[0] = 0x01; /* Stall Endpoint */ D11CmdDataWrite(D11_SET_ENDPOINT_STATUS + D11_ENDPOINT_EP2_OUT, Buffer, 1); } if(Irq & D11_INT_EP2_IN) { printf("EP2_IN\n\r"); D11CmdDataRead(D11_READ_LAST_TRANSACTION + D11_ENDPOINT_EP2_IN, Buffer, 1); Buffer[0] = 0x01; /* Stall Endpoint */ D11CmdDataWrite(D11_SET_ENDPOINT_STATUS + D11_ENDPOINT_EP2_IN, Buffer, 1); } if(Irq & D11_INT_EP3_OUT) { printf("EP3_OUT\n\r"); D11CmdDataRead(D11_READ_LAST_TRANSACTION + D11_ENDPOINT_EP3_OUT, Buffer, 1); Buffer[0] = 0x01; /* Stall Endpoint */ D11CmdDataWrite(D11_SET_ENDPOINT_STATUS + D11_ENDPOINT_EP3_OUT, Buffer, 1); } if(Irq & D11_INT_EP3_IN) { printf("EP3_IN\n\r"); D11CmdDataRead(D11_READ_LAST_TRANSACTION + D11_ENDPOINT_EP3_IN, Buffer, 1); Buffer[0] = 0x01; /* Stall Endpoint */ D11CmdDataWrite(D11_SET_ENDPOINT_STATUS + D11_ENDPOINT_EP3_IN, Buffer, 1); } }if(Irq & D11_INT_EP1_OUT) { printf("EP1_OUT\n\r"); D11CmdDataRead(D11_READ_LAST_TRANSACTION + D11_ENDPOINT_EP1_OUT, Buffer, 1); bytes = D11ReadEndpoint(D11_ENDPOINT_EP1_OUT, Buffer); for (count = 0; count < bytes; count++) { circularbuffer[inpointer++] = Buffer[count]; if (inpointer >= MAX_BUFFER_SIZE) inpointer = 0; } loadfromcircularbuffer(); //Kick Start }if(Irq & D11_INT_EP1_IN) { printf("EP1_IN\n\r"); D11CmdDataRead(D11_READ_LAST_TRANSACTION + D11_ENDPOINT_EP1_IN, Buffer, 1); loadfromcircularbuffer(); } const USB_CONFIG_DATA ConfigurationDescriptor = { { /* configuration descriptor */ sizeof(USB_CONFIGURATION_DESCRIPTOR), /* bLength */ TYPE_CONFIGURATION_DESCRIPTOR, /* bDescriptorType */ sizeof(USB_CONFIG_DATA), /* wTotalLength */ 1, /* bNumInterfaces */ 1, /* bConfigurationValue */ 0, /* iConfiguration String Index */ 0x80, /* bmAttributes Bus Powered, No Remote Wakeup */ 0x32 /* bMaxPower, 100mA */ }, { /* interface descriptor */ sizeof(USB_INTERFACE_DESCRIPTOR), /* bLength */ TYPE_INTERFACE_DESCRIPTOR, /* bDescriptorType */ 0, /* bInterface Number */ 0, /* bAlternateSetting */ 2, /* bNumEndpoints */ 0xFF, /* bInterfaceClass (Vendor specific) */ 0xFF, /* bInterfaceSubClass */ 0xFF, /* bInterfaceProtocol */ 0 /* iInterface String Index */ }, { /* endpoint descriptor */ sizeof(USB_ENDPOINT_DESCRIPTOR), /* bLength */ TYPE_ENDPOINT_DESCRIPTOR, /* bDescriptorType */ 0x01, /* bEndpoint Address EP1 OUT */ 0x02, /* bmAttributes - Interrupt */ 0x0008, /* wMaxPacketSize */ 0x00 /* bInterval */ }, { /* endpoint descriptor */ sizeof(USB_ENDPOINT_DESCRIPTOR), /* bLength */ TYPE_ENDPOINT_DESCRIPTOR, /* bDescriptorType */ 0x81, /* bEndpoint Address EP1 IN */ 0x02, /* bmAttributes - Interrupt */ 0x0008, /* wMaxPacketSize */ 0x00 /* bInterval */ } }; pPacke upPacket->wLeng ufferToEndPoint(); ase TYPE_DEVICE_DES escri ength) iteBuffe nt(); case TYPE_C ATION fig. pSendBuffer=(const unsigned char *)&DeviceDescriptor;BytesToSe if (BytesToSend>SetupPacket->wLength) BytesToSend= SetupPacket-> SetupPacket->wLength, sizeof(ConfigurationDescriptor));BytesTo Buffer[count rbuff 0x07 (outpoin _SIZE =0xC1|( cket.wInd INT_EP0_IN,Buffer,2 RTB=(PORTB&0x0F)| rolEndPoi beyond logic – usb in a nutshell universal serial bus 2.0 specification wikipedia ____ ____ ______________________ /_/|_|_ _______________ _____ / __ \/ ____/ ____/ ____/ __ \/ ____/ | / / ____/ _/ | / ___/ / /_/ / __/ / /_ / __/ / /_/ / __/ / |/ / / / // /| | \__ \ / _, _/ /___/ __/ / /___/ _, _/ /___/ /| / /____/ // ___ |___/ / /_/ |_/_____/_/ /_____/_/ |_/_____/_/ |_/\____/___/_/ |_/____/