Merge CDC-ECM, RNG, DFU bootloader, watchdog, settings manager, energy scan routines of Robert Quattlebaum
This commit is contained in:
parent
7b529cac03
commit
110bc0242e
42 changed files with 4739 additions and 2669 deletions
|
@ -94,6 +94,14 @@
|
|||
|
||||
/** USB RNDIS / Virtual com port setup **/
|
||||
|
||||
#ifndef CDC_ECM_USES_INTERRUPT_ENDPOINT
|
||||
#define CDC_ECM_USES_INTERRUPT_ENDPOINT 0
|
||||
#endif
|
||||
|
||||
#ifndef USB_ETH_EMULATE_WIFI
|
||||
#define USB_ETH_EMULATE_WIFI 0
|
||||
#endif
|
||||
|
||||
#define NB_ENDPOINTS 7 //! number of endpoints in the application including control endpoint
|
||||
#define VCP_RX_EP 0x06
|
||||
#define VCP_TX_EP 0x05
|
||||
|
|
327
cpu/avr/dev/usb/rndis/cdc_ecm.c
Normal file
327
cpu/avr/dev/usb/rndis/cdc_ecm.c
Normal file
|
@ -0,0 +1,327 @@
|
|||
#include <stdbool.h>
|
||||
#include "cdc_ecm.h"
|
||||
#include "contiki.h"
|
||||
#include "usb_drv.h"
|
||||
#include "usb_descriptors.h"
|
||||
#include "usb_specific_request.h"
|
||||
#include "rndis/rndis_task.h"
|
||||
#include "rndis/rndis_protocol.h"
|
||||
#include "uip.h"
|
||||
#include "sicslow_ethernet.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
#define BUF ((struct uip_eth_hdr *)&uip_buf[0])
|
||||
#define PRINTF printf
|
||||
#define PRINTF_P printf_P
|
||||
|
||||
extern uint8_t usb_eth_data_buffer[64];
|
||||
static U16 usb_ecm_packet_filter = 0;
|
||||
|
||||
#define PACKET_TYPE_PROMISCUOUS (1<<0)
|
||||
#define PACKET_TYPE_ALL_MULTICAST (1<<1)
|
||||
#define PACKET_TYPE_DIRECTED (1<<2)
|
||||
#define PACKET_TYPE_BROADCAST (1<<3)
|
||||
#define PACKET_TYPE_MULTICAST (1<<4)
|
||||
|
||||
#define Usb_write_word(x) Usb_write_byte((x)&0xFF),Usb_write_byte((x>>8)&0xFF)
|
||||
#define Usb_write_long(x) Usb_write_word((x)&0xFFFF),Usb_write_word((x>>16)&0xFFFF)
|
||||
|
||||
#define Usb_read_word() ((U16)Usb_read_byte()+((U16)Usb_read_byte()<<8))
|
||||
|
||||
void
|
||||
cdc_ecm_set_ethernet_packet_filter(void) {
|
||||
usb_ecm_packet_filter = Usb_read_word();
|
||||
|
||||
Usb_ack_receive_setup();
|
||||
Usb_send_control_in();
|
||||
usb_endpoint_wait_for_read_control_enabled();
|
||||
|
||||
PRINTF_P(PSTR("cdc_ecm: Received SET_ETHERNET_PACKET_FILTER: (0x%04X) "),usb_ecm_packet_filter);
|
||||
if(usb_ecm_packet_filter & PACKET_TYPE_PROMISCUOUS) {
|
||||
PRINTF_P(PSTR("PROMISCUOUS "));
|
||||
USB_ETH_HOOK_SET_PROMISCIOUS_MODE(true);
|
||||
} else {
|
||||
USB_ETH_HOOK_SET_PROMISCIOUS_MODE(false);
|
||||
}
|
||||
|
||||
if(usb_ecm_packet_filter & PACKET_TYPE_ALL_MULTICAST)
|
||||
PRINTF_P(PSTR("ALL_MULTICAST "));
|
||||
if(usb_ecm_packet_filter & PACKET_TYPE_DIRECTED)
|
||||
PRINTF_P(PSTR("DIRECTED "));
|
||||
if(usb_ecm_packet_filter & PACKET_TYPE_BROADCAST)
|
||||
PRINTF_P(PSTR("BROADCAST "));
|
||||
if(usb_ecm_packet_filter & PACKET_TYPE_MULTICAST)
|
||||
PRINTF_P(PSTR("MULTICAST "));
|
||||
|
||||
PRINTF_P(PSTR("\n"));
|
||||
}
|
||||
|
||||
|
||||
#define CDC_NOTIFY_NETWORK_CONNECTION (0x00)
|
||||
#define CDC_NOTIFY_CONNECTION_SPEED_CHANGE (0x2A)
|
||||
|
||||
void
|
||||
cdc_ecm_notify_network_connection(uint8_t value) {
|
||||
#if CDC_ECM_USES_INTERRUPT_ENDPOINT
|
||||
Usb_select_endpoint(INT_EP);
|
||||
|
||||
if(!Is_usb_endpoint_enabled()) {
|
||||
//PRINTF_P(PSTR("cdc_ecm: cdc_ecm_notify_network_connection: endpoint not enabled\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if(usb_endpoint_wait_for_IN_ready()!=0) {
|
||||
//PRINTF_P(PSTR("cdc_ecm: cdc_ecm_notify_network_connection: Timeout waiting for interrupt endpoint to be available\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
Usb_send_control_in();
|
||||
|
||||
Usb_write_byte(0x51); // 10100001b
|
||||
Usb_write_byte(CDC_NOTIFY_NETWORK_CONNECTION);
|
||||
Usb_write_byte(value);
|
||||
Usb_write_byte(0x00);
|
||||
Usb_write_word(ECM_INTERFACE0_NB);
|
||||
Usb_write_word(0x0000);
|
||||
|
||||
Usb_send_in();
|
||||
PRINTF_P(PSTR("cdc_ecm: CDC_NOTIFY_NETWORK_CONNECTION %d\n"),value);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define CDC_ECM_DATA_ENDPOINT_SIZE 64
|
||||
|
||||
void cdc_ecm_configure_endpoints() {
|
||||
#if CDC_ECM_USES_INTERRUPT_ENDPOINT
|
||||
usb_configure_endpoint(INT_EP, \
|
||||
TYPE_INTERRUPT, \
|
||||
DIRECTION_IN, \
|
||||
SIZE_8, \
|
||||
TWO_BANKS, \
|
||||
NYET_ENABLED);
|
||||
#endif
|
||||
|
||||
usb_configure_endpoint(TX_EP, \
|
||||
TYPE_BULK, \
|
||||
DIRECTION_IN, \
|
||||
SIZE_64, \
|
||||
TWO_BANKS, \
|
||||
NYET_ENABLED);
|
||||
|
||||
usb_configure_endpoint(RX_EP, \
|
||||
TYPE_BULK, \
|
||||
DIRECTION_OUT, \
|
||||
SIZE_64, \
|
||||
TWO_BANKS, \
|
||||
NYET_ENABLED);
|
||||
#if CDC_ECM_USES_INTERRUPT_ENDPOINT
|
||||
Usb_reset_endpoint(INT_EP);
|
||||
#endif
|
||||
Usb_reset_endpoint(TX_EP);
|
||||
Usb_reset_endpoint(RX_EP);
|
||||
usb_eth_is_active = 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cdc_ecm_notify_connection_speed_change(uint32_t upstream,uint32_t downstream) {
|
||||
#if CDC_ECM_USES_INTERRUPT_ENDPOINT
|
||||
Usb_select_endpoint(INT_EP);
|
||||
|
||||
if(!Is_usb_endpoint_enabled())
|
||||
return;
|
||||
|
||||
if(usb_endpoint_wait_for_IN_ready()!=0)
|
||||
return;
|
||||
|
||||
Usb_send_control_in();
|
||||
|
||||
Usb_write_byte(0x51); // 10100001b
|
||||
Usb_write_byte(CDC_NOTIFY_CONNECTION_SPEED_CHANGE);
|
||||
Usb_write_word(0x0000);
|
||||
Usb_write_word(ECM_INTERFACE0_NB);
|
||||
Usb_write_word(0x0008);
|
||||
|
||||
Usb_send_in();
|
||||
|
||||
if(usb_endpoint_wait_for_write_enabled()!=0)
|
||||
return;
|
||||
|
||||
Usb_write_long(upstream);
|
||||
Usb_write_long(downstream);
|
||||
Usb_send_in();
|
||||
|
||||
PRINTF_P(PSTR("cdc_ecm: CDC_NOTIFY_CONNECTION_SPEED_CHANGE UP:%d DOWN:%d\n"),upstream,downstream);
|
||||
#endif
|
||||
}
|
||||
|
||||
void cdc_ecm_set_active(uint8_t value) {
|
||||
if(value!=usb_eth_is_active) {
|
||||
Led3_on();
|
||||
|
||||
usb_eth_is_active = value;
|
||||
cdc_ecm_notify_network_connection(value);
|
||||
if(value) {
|
||||
cdc_ecm_notify_connection_speed_change(250000,250000);
|
||||
} else {
|
||||
cdc_ecm_notify_connection_speed_change(0,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
cdc_ecm_process(void) {
|
||||
static uint8_t doInit = 1;
|
||||
|
||||
Usb_select_endpoint(RX_EP);
|
||||
|
||||
if(!Is_usb_endpoint_enabled()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (doInit) {
|
||||
#ifdef USB_ETH_HOOK_INIT
|
||||
USB_ETH_HOOK_INIT();
|
||||
#endif
|
||||
cdc_ecm_notify_network_connection(1);
|
||||
cdc_ecm_notify_connection_speed_change(250000,250000);
|
||||
doInit = 0;
|
||||
if(usb_ecm_packet_filter & PACKET_TYPE_PROMISCUOUS) {
|
||||
#if RF230BB
|
||||
rf230_set_promiscuous_mode(true);
|
||||
#else
|
||||
radio_set_trx_state(RX_ON);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Select again, just to make sure.
|
||||
Usb_select_endpoint(RX_EP);
|
||||
}
|
||||
|
||||
if(!usb_eth_is_active) {
|
||||
// If we aren't active, just eat the packets.
|
||||
if(Is_usb_read_enabled()) {
|
||||
Usb_ack_receive_out();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Connected!
|
||||
Led0_on();
|
||||
|
||||
if(Is_usb_read_enabled()) {
|
||||
uint16_t bytecounter;
|
||||
uint16_t bytes_received = 0;
|
||||
U8 * buffer = uip_buf;
|
||||
|
||||
if(!usb_eth_ready_for_next_packet()) {
|
||||
// Since we aren't ready for a packet yet,
|
||||
// just return.
|
||||
goto bail;
|
||||
}
|
||||
|
||||
#ifdef USB_ETH_HOOK_RX_START
|
||||
USB_ETH_HOOK_RX_START();
|
||||
#endif
|
||||
|
||||
while((bytecounter=Usb_byte_counter_8())==CDC_ECM_DATA_ENDPOINT_SIZE) {
|
||||
while((bytes_received<USB_ETH_MTU) && (bytecounter--)) {
|
||||
*buffer++ = Usb_read_byte();
|
||||
bytes_received++;
|
||||
}
|
||||
bytes_received+=bytecounter+1;
|
||||
|
||||
//ACK previous data
|
||||
Usb_ack_receive_out();
|
||||
|
||||
//Wait for new data
|
||||
if(usb_endpoint_wait_for_read_enabled()!=0) {
|
||||
USB_ETH_HOOK_RX_ERROR("Timeout: read enabled");
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
bytecounter = Usb_byte_counter_8();
|
||||
while((bytes_received<USB_ETH_MTU) && (bytecounter--)) {
|
||||
*buffer++ = Usb_read_byte();
|
||||
bytes_received++;
|
||||
}
|
||||
bytes_received+=bytecounter+1;
|
||||
|
||||
//Ack final data packet
|
||||
Usb_ack_receive_out();
|
||||
|
||||
//PRINTF_P(PSTR("cdc_ecm: Got packet %d bytes long\n"),bytes_received);
|
||||
|
||||
#ifdef USB_ETH_HOOK_RX_END
|
||||
USB_ETH_HOOK_RX_END();
|
||||
#endif
|
||||
|
||||
//Send data over RF or to local stack
|
||||
if(bytes_received<=USB_ETH_MTU) {
|
||||
|
||||
USB_ETH_HOOK_HANDLE_INBOUND_PACKET(uip_buf,bytes_received);
|
||||
} else {
|
||||
USB_ETH_HOOK_RX_ERROR("Oversized packet");
|
||||
}
|
||||
}
|
||||
bail:
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
ecm_send(uint8_t * senddata, uint16_t sendlen, uint8_t led) {
|
||||
U8 byte_in_packet = 0;
|
||||
|
||||
//Send Data
|
||||
Usb_select_endpoint(TX_EP);
|
||||
|
||||
if(usb_endpoint_wait_for_write_enabled()!=0) {
|
||||
USB_ETH_HOOK_TX_ERROR("Timeout: write enabled");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef USB_ETH_HOOK_TX_START
|
||||
USB_ETH_HOOK_TX_START();
|
||||
#endif
|
||||
|
||||
//Send packet
|
||||
while(sendlen) {
|
||||
Usb_write_byte(*senddata);
|
||||
senddata++;
|
||||
sendlen--;
|
||||
byte_in_packet++;
|
||||
|
||||
//If endpoint is full, send data in
|
||||
//And then wait for data to transfer
|
||||
if (!Is_usb_write_enabled()) {
|
||||
Usb_ack_in_ready();
|
||||
|
||||
if(usb_endpoint_wait_for_write_enabled()!=0) {
|
||||
USB_ETH_HOOK_TX_ERROR("Timeout: write enabled");
|
||||
return 0;
|
||||
}
|
||||
byte_in_packet=0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Send last data in - also handles sending a ZLP if needed
|
||||
Usb_ack_in_ready();
|
||||
|
||||
#ifdef USB_ETH_HOOK_TX_END
|
||||
USB_ETH_HOOK_TX_END();
|
||||
#endif
|
||||
|
||||
//Wait for ready
|
||||
if(usb_endpoint_wait_for_IN_ready()!=0) {
|
||||
USB_ETH_HOOK_TX_ERROR("Timeout: IN ready");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
18
cpu/avr/dev/usb/rndis/cdc_ecm.h
Normal file
18
cpu/avr/dev/usb/rndis/cdc_ecm.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
|
||||
#ifndef __CDC_ECM_H__
|
||||
#define __CDC_ECM_H__
|
||||
|
||||
#include "contiki.h"
|
||||
#include <stdint.h>
|
||||
#include "conf_usb.h"
|
||||
|
||||
#define SET_ETHERNET_PACKET_FILTER (0x43)
|
||||
|
||||
|
||||
extern uint8_t cdc_ecm_process(void);
|
||||
extern uint8_t ecm_send(uint8_t * senddata, uint16_t sendlen, uint8_t led);
|
||||
extern void cdc_ecm_set_ethernet_packet_filter(void);
|
||||
extern void cdc_ecm_configure_endpoints();
|
||||
extern void cdc_ecm_set_active(uint8_t value);
|
||||
|
||||
#endif // __CDC_ECM_H__
|
296
cpu/avr/dev/usb/rndis/cdc_eem.c
Normal file
296
cpu/avr/dev/usb/rndis/cdc_eem.c
Normal file
|
@ -0,0 +1,296 @@
|
|||
#include "cdc_eem.h"
|
||||
#include "contiki.h"
|
||||
#include "usb_drv.h"
|
||||
#include "usb_descriptors.h"
|
||||
#include "usb_specific_request.h"
|
||||
#include "rndis/rndis_task.h"
|
||||
#include "rndis/rndis_protocol.h"
|
||||
#include "uip.h"
|
||||
#include "sicslow_ethernet.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
#define BUF ((struct uip_eth_hdr *)&uip_buf[0])
|
||||
#define PRINTF printf
|
||||
#define PRINTF_P printf_P
|
||||
|
||||
extern uint8_t usb_eth_data_buffer[64];
|
||||
|
||||
|
||||
//_____ M A C R O S ________________________________________________________
|
||||
|
||||
|
||||
#define EEMCMD_ECHO 0x00 ///bmEEMCmd Echo
|
||||
#define EEMCMD_ECHO_RESPONSE 0x01 ///bmEEMCmd Echo Response
|
||||
#define EEMCMD_SUSPEND_HINT 0x02 ///bmEEMCmd Suspend Hint
|
||||
#define EEMCMD_RESPONSE_HINT 0x03 ///bmEEMCmd Response Hint
|
||||
#define EEMCMD_RESPONSE_COMPLETE_HINT 0x04 ///bmEEMCmd Response Complete Hint
|
||||
#define EEMCMD_TICKLE 0x05 ///bmEEMCmd Tickle
|
||||
|
||||
|
||||
void cdc_eem_configure_endpoints() {
|
||||
usb_configure_endpoint(TX_EP, \
|
||||
TYPE_BULK, \
|
||||
DIRECTION_IN, \
|
||||
SIZE_64, \
|
||||
TWO_BANKS, \
|
||||
NYET_ENABLED);
|
||||
|
||||
usb_configure_endpoint(RX_EP, \
|
||||
TYPE_BULK, \
|
||||
DIRECTION_OUT, \
|
||||
SIZE_64, \
|
||||
TWO_BANKS, \
|
||||
NYET_ENABLED);
|
||||
Usb_reset_endpoint(TX_EP);
|
||||
Usb_reset_endpoint(RX_EP);
|
||||
}
|
||||
|
||||
void cdc_eem_process(void) {
|
||||
uint16_t datalength;
|
||||
uint8_t bytecounter, headercounter;
|
||||
uint16_t i;
|
||||
|
||||
#ifdef USB_ETH_HOOK_INIT
|
||||
static uint8_t doInit = 1;
|
||||
if (doInit) {
|
||||
USB_ETH_HOOK_INIT();
|
||||
doInit = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
//Connected!
|
||||
Led0_on();
|
||||
|
||||
Usb_select_endpoint(RX_EP);
|
||||
|
||||
//If we have data and a free buffer
|
||||
if(Is_usb_receive_out() && (uip_len == 0)) {
|
||||
|
||||
//Read how much (endpoint only stores up to 64 bytes anyway)
|
||||
bytecounter = Usb_byte_counter_8();
|
||||
|
||||
//EEM uses 2 bytes as a header
|
||||
headercounter = 2;
|
||||
|
||||
uint8_t fail = 0;
|
||||
|
||||
//Hmm.. what's going on here?
|
||||
if (bytecounter < headercounter) {
|
||||
Usb_ack_receive_out();
|
||||
//TODO CO done = 1;
|
||||
}
|
||||
|
||||
//Read EEM Header
|
||||
i = 0;
|
||||
while (headercounter) {
|
||||
usb_eth_data_buffer[i] = Usb_read_byte();
|
||||
bytecounter--;
|
||||
headercounter--;
|
||||
i++;
|
||||
}
|
||||
|
||||
//Order is LSB/MSB, so MSN is in usb_eth_data_buffer[1]
|
||||
//Bit 15 indicates command packet when set
|
||||
if (usb_eth_data_buffer[1] & 0x80) {
|
||||
//not a data payload
|
||||
datalength = 0;
|
||||
} else {
|
||||
//'0' indicates data packet
|
||||
//Length is lower 14 bits
|
||||
datalength = usb_eth_data_buffer[0] | ((usb_eth_data_buffer[1] & 0x3F) << 8);
|
||||
}
|
||||
|
||||
/* EEM Command Packet */
|
||||
if ((datalength == 0) && (fail == 0))
|
||||
{
|
||||
uint8_t command;
|
||||
uint16_t echoLength;
|
||||
|
||||
//Strip command off
|
||||
command = usb_eth_data_buffer[1] & 0x38;
|
||||
command = command >> 3;
|
||||
|
||||
//Decode command type
|
||||
switch (command)
|
||||
{
|
||||
/* Echo Request */
|
||||
case EEMCMD_ECHO:
|
||||
|
||||
//Get echo length
|
||||
echoLength = (usb_eth_data_buffer[1] & 0x07) << 8; //MSB
|
||||
echoLength |= usb_eth_data_buffer[0]; //LSB
|
||||
|
||||
//TODO: everything. oops.
|
||||
|
||||
break;
|
||||
|
||||
/* Everything else: Whatever. */
|
||||
case EEMCMD_ECHO_RESPONSE:
|
||||
case EEMCMD_SUSPEND_HINT:
|
||||
case EEMCMD_RESPONSE_HINT:
|
||||
case EEMCMD_RESPONSE_COMPLETE_HINT:
|
||||
case EEMCMD_TICKLE:
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
/* EEM Data Packet */
|
||||
else if (datalength && (fail == 0))
|
||||
{
|
||||
//Looks like we've got a live one
|
||||
#ifdef USB_ETH_HOOK_RX_START
|
||||
USB_ETH_HOOK_RX_START();
|
||||
#endif
|
||||
|
||||
uint16_t bytes_received = 0;
|
||||
uint16_t dataleft = datalength;
|
||||
U8 * buffer = uip_buf;
|
||||
|
||||
while(dataleft)
|
||||
{
|
||||
*buffer++ = Usb_read_byte();
|
||||
|
||||
dataleft--;
|
||||
bytecounter--;
|
||||
bytes_received++;
|
||||
|
||||
//Check if endpoint is done but we are expecting more data
|
||||
if ((bytecounter == 0) && (dataleft))
|
||||
{
|
||||
//ACK previous data
|
||||
Usb_ack_receive_out();
|
||||
|
||||
//Wait for new data
|
||||
while (!Is_usb_receive_out());
|
||||
|
||||
//Get new data
|
||||
bytecounter = Usb_byte_counter_8();
|
||||
|
||||
//ZLP?
|
||||
if (bytecounter == 0)
|
||||
{
|
||||
//Incomplete!!
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Ack final data packet
|
||||
Usb_ack_receive_out();
|
||||
|
||||
#ifdef USB_ETH_HOOK_RX_END
|
||||
USB_ETH_HOOK_RX_END();
|
||||
#endif
|
||||
|
||||
//Packet has CRC, nobody wants that garbage
|
||||
datalength -= 4;
|
||||
|
||||
//Send data over RF or to local stack
|
||||
if(datalength <= USB_ETH_MTU) {
|
||||
USB_ETH_HOOK_HANDLE_INBOUND_PACKET(uip_buf,datalength);
|
||||
} else {
|
||||
USB_ETH_HOOK_RX_ERROR("Oversized packet");
|
||||
}
|
||||
} //if (datalength)
|
||||
} //if(Is_usb_receive_out() && (uip_len == 0))
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Send a single ethernet frame using EEM
|
||||
*/
|
||||
uint8_t eem_send(uint8_t * senddata, uint16_t sendlen, uint8_t led)
|
||||
{
|
||||
//Make a header
|
||||
uint8_t header[2];
|
||||
|
||||
//Fake CRC! Add 4 to length for CRC
|
||||
sendlen += 4;
|
||||
header[0] = (sendlen >> 8) & 0x3f;
|
||||
header[1] = sendlen & 0xff;
|
||||
|
||||
//We send CRC seperatly..
|
||||
sendlen -= 4;
|
||||
|
||||
//Send Data
|
||||
Usb_select_endpoint(TX_EP);
|
||||
//Usb_send_in();
|
||||
|
||||
//Wait for ready
|
||||
if(usb_endpoint_wait_for_write_enabled()!=0) {
|
||||
USB_ETH_HOOK_TX_ERROR("Timeout: write enabled");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef USB_ETH_HOOK_TX_START
|
||||
USB_ETH_HOOK_TX_START();
|
||||
#endif
|
||||
|
||||
//Send header (LSB then MSB)
|
||||
Usb_write_byte(header[1]);
|
||||
Usb_write_byte(header[0]);
|
||||
|
||||
//Send packet
|
||||
while(sendlen) {
|
||||
Usb_write_byte(*senddata);
|
||||
senddata++;
|
||||
sendlen--;
|
||||
|
||||
//If endpoint is full, send data in
|
||||
//And then wait for data to transfer
|
||||
if (!Is_usb_write_enabled()) {
|
||||
Usb_send_in();
|
||||
|
||||
if(usb_endpoint_wait_for_write_enabled()!=0) {
|
||||
USB_ETH_HOOK_TX_ERROR("Timeout: write enabled");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//CRC = 0xdeadbeef
|
||||
//Linux kernel 2.6.31 needs 0xdeadbeef in wrong order,
|
||||
//like this: uint8_t crc[4] = {0xef, 0xbe, 0xad, 0xde};
|
||||
//This is fixed in 2.6.32 to the correct order (0xde, 0xad, 0xbe, 0xef)
|
||||
uint8_t crc[4] = {0xde, 0xad, 0xbe, 0xef};
|
||||
|
||||
sendlen = 4;
|
||||
uint8_t i = 0;
|
||||
|
||||
//Send fake CRC
|
||||
while(sendlen) {
|
||||
Usb_write_byte(crc[i]);
|
||||
i++;
|
||||
sendlen--;
|
||||
|
||||
//If endpoint is full, send data in
|
||||
//And then wait for data to transfer
|
||||
if (!Is_usb_write_enabled()) {
|
||||
Usb_send_in();
|
||||
if(usb_endpoint_wait_for_write_enabled()!=0) {
|
||||
USB_ETH_HOOK_TX_ERROR("Timeout: write enabled");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Send last data in - also handles sending a ZLP if needed
|
||||
Usb_send_in();
|
||||
|
||||
#ifdef USB_ETH_HOOK_TX_END
|
||||
USB_ETH_HOOK_TX_END();
|
||||
#endif
|
||||
|
||||
//Wait for ready
|
||||
if(usb_endpoint_wait_for_IN_ready()!=0) {
|
||||
USB_ETH_HOOK_TX_ERROR("Timeout: IN ready");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
12
cpu/avr/dev/usb/rndis/cdc_eem.h
Normal file
12
cpu/avr/dev/usb/rndis/cdc_eem.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
|
||||
#ifndef __CDC_EEM_H__
|
||||
#define __CDC_EEM_H__
|
||||
|
||||
#include "contiki.h"
|
||||
#include <stdint.h>
|
||||
|
||||
extern void cdc_eem_process(void);
|
||||
extern uint8_t eem_send(uint8_t * senddata, uint16_t sendlen, uint8_t led);
|
||||
extern void cdc_eem_configure_endpoints();
|
||||
|
||||
#endif // __CDC_EEM_H__
|
|
@ -58,6 +58,7 @@ RNDIS Status Information:
|
|||
|
||||
//_____ I N C L U D E S ____________________________________________________
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "radio.h"
|
||||
#include "contiki.h"
|
||||
#include "config.h"
|
||||
|
@ -65,12 +66,18 @@ RNDIS Status Information:
|
|||
#include "usb_descriptors.h"
|
||||
#include "usb_specific_request.h"
|
||||
#include "rndis/rndis_protocol.h"
|
||||
#include "rndis/rndis_task.h"
|
||||
#include "uip.h"
|
||||
#include "serial/uart_usb_lib.h"
|
||||
#include "sicslow_ethernet.h"
|
||||
#include <avr/pgmspace.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
|
||||
//_____ M A C R O S ________________________________________________________
|
||||
|
||||
//_____ D E F I N I T I O N ________________________________________________
|
||||
|
@ -80,14 +87,10 @@ RNDIS Status Information:
|
|||
extern PGM_VOID_P pbuffer;
|
||||
extern U8 data_to_transfer;
|
||||
|
||||
//NB: If you change the OID list be sure to update this!!!
|
||||
//#define OID_LIST_LENGTH 50
|
||||
#define OID_LIST_LENGTH 35
|
||||
|
||||
/**
|
||||
* \brief List of supported RNDIS OID's
|
||||
*/
|
||||
prog_uint32_t OIDSupportedList[OID_LIST_LENGTH] = {
|
||||
prog_uint32_t OIDSupportedList[] = {
|
||||
/* Required General */
|
||||
OID_GEN_SUPPORTED_LIST ,
|
||||
OID_GEN_HARDWARE_STATUS ,
|
||||
|
@ -128,7 +131,7 @@ prog_uint32_t OIDSupportedList[OID_LIST_LENGTH] = {
|
|||
|
||||
/*802.11 OID's not fully implemented yet. Hence do not say we
|
||||
support them */
|
||||
#ifdef DONOTEVERDEFINETHISORBADSTUFFHAPPENS
|
||||
#if USB_ETH_EMULATE_WIFI
|
||||
/* 802.11 OIDs */
|
||||
OID_802_11_BSSID ,
|
||||
OID_802_11_SSID ,
|
||||
|
@ -156,18 +159,17 @@ prog_uint32_t OIDSupportedList[OID_LIST_LENGTH] = {
|
|||
OID_PNP_ENABLE_WAKE_UP ,
|
||||
OID_PNP_ADD_WAKE_UP_PATTERN ,
|
||||
OID_PNP_REMOVE_WAKE_UP_PATTERN
|
||||
};
|
||||
|
||||
};
|
||||
#define OID_LIST_LENGTH sizeof(OIDSupportedList)/sizeof(*OIDSupportedList)
|
||||
|
||||
|
||||
rndis_state_t rndis_state;
|
||||
|
||||
rndis_stat_t rndis_stat;
|
||||
usb_eth_stat_t usb_eth_stat;
|
||||
|
||||
uint8_t schedule_interrupt = 0;
|
||||
|
||||
uint64_t rndis_ethernet_addr = 0x203478928323ULL;
|
||||
|
||||
//_____ D E C L A R A T I O N ______________________________________________
|
||||
|
||||
|
||||
|
@ -188,7 +190,7 @@ U8 data_to_send = 0x00;
|
|||
*
|
||||
* \return True on success, false on failure.
|
||||
*/
|
||||
uint8_t send_encapsulated_command(uint16_t wLength)
|
||||
uint8_t rndis_send_encapsulated_command(uint16_t wLength)
|
||||
{
|
||||
U8 i = 0;
|
||||
|
||||
|
@ -200,12 +202,6 @@ uint8_t send_encapsulated_command(uint16_t wLength)
|
|||
if (wLength > ENC_BUF_SIZE)
|
||||
wLength = ENC_BUF_SIZE;
|
||||
|
||||
//For debugging: this shouldn't happen, just checked it didn't
|
||||
//if (data_to_send) {
|
||||
// while(1);
|
||||
//}
|
||||
|
||||
|
||||
//Read in all the bytes...
|
||||
|
||||
uint8_t nb_counter;
|
||||
|
@ -256,9 +252,13 @@ uint8_t send_encapsulated_command(uint16_t wLength)
|
|||
m->MinorVersion = RNDIS_MAJOR_VERSION;
|
||||
m->Status = RNDIS_STATUS_SUCCESS;
|
||||
m->DeviceFlags = RNDIS_DF_CONNECTIONLESS;
|
||||
#if USB_ETH_EMULATE_WIFI
|
||||
m->Medium = NDIS_MEDIUM_WIRELESS_LAN;
|
||||
#else
|
||||
m->Medium = RNDIS_MEDIUM_802_3;
|
||||
#endif // USB_ETH_EMULATE_WIFI
|
||||
m->MaxPacketsPerTransfer = 1;
|
||||
m->MaxTransferSize = 1338; /* Space for 1280 IP buffer, Ethernet Header,
|
||||
m->MaxTransferSize = USB_ETH_MTU + 58; /* Space for 1280 IP buffer, Ethernet Header,
|
||||
RNDIS messages */
|
||||
m->PacketAlignmentFactor = 3;
|
||||
m->AfListOffset = 0;
|
||||
|
@ -353,7 +353,9 @@ void rndis_send_interrupt(void)
|
|||
|
||||
uint32_t oid_packet_filter = 0x0000000;
|
||||
|
||||
#if USB_ETH_EMULATE_WIFI
|
||||
uint16_t panid = 0xbaad;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Function to handle a RNDIS "QUERY" command in the encapsulated_buffer
|
||||
|
@ -392,15 +394,20 @@ void rndis_query_process(void)
|
|||
|
||||
case OID_GEN_MEDIA_SUPPORTED:
|
||||
case OID_GEN_MEDIA_IN_USE:
|
||||
*INFBUF = NDIS_MEDIUM_802_3; /* NDIS_MEDIUM_WIRELESS_LAN instead? */
|
||||
case OID_GEN_PHYSICAL_MEDIUM:
|
||||
#if USB_ETH_EMULATE_WIFI
|
||||
*INFBUF = NDIS_MEDIUM_WIRELESS_LAN;
|
||||
#else
|
||||
*INFBUF = NDIS_MEDIUM_802_3;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case OID_GEN_MAXIMUM_FRAME_SIZE:
|
||||
*INFBUF = (uint32_t) 1280; //1280 //102; /* Assume 25 octet header on 15.4 */
|
||||
*INFBUF = (uint32_t) USB_ETH_MTU-14; //1280 //102; /* Assume 25 octet header on 15.4 */
|
||||
break;
|
||||
|
||||
case OID_GEN_LINK_SPEED:
|
||||
*INFBUF = (uint32_t) 100; /* in 100 bytes/sec units.. this is kinda a lie */
|
||||
*INFBUF = (uint32_t) 250000/100; /* in 100 bytes/sec units.. this is kinda a lie */
|
||||
break;
|
||||
|
||||
case OID_GEN_TRANSMIT_BLOCK_SIZE:
|
||||
|
@ -422,57 +429,35 @@ void rndis_query_process(void)
|
|||
break;
|
||||
|
||||
case OID_GEN_MAXIMUM_TOTAL_SIZE:
|
||||
*INFBUF = (uint32_t) 1300; //127;
|
||||
*INFBUF = (uint32_t) USB_ETH_MTU; //127;
|
||||
break;
|
||||
|
||||
case OID_GEN_MEDIA_CONNECT_STATUS:
|
||||
*INFBUF = NDIS_MEDIA_STATE_CONNECTED;
|
||||
*INFBUF = usb_eth_is_active?NDIS_MEDIA_STATE_CONNECTED:NDIS_MEDIA_STATE_DISCONNECTED;
|
||||
break;
|
||||
|
||||
case OID_GEN_VENDOR_DRIVER_VERSION:
|
||||
*INFBUF = 0x00001000;
|
||||
break;
|
||||
|
||||
case OID_GEN_PHYSICAL_MEDIUM:
|
||||
*INFBUF = NDIS_MEDIUM_802_3; /*NDIS_MEDIUM_WIRELESS_LAN;*/
|
||||
break;
|
||||
|
||||
case OID_GEN_CURRENT_LOOKAHEAD:
|
||||
*INFBUF = (uint32_t) 1280; //102;
|
||||
*INFBUF = (uint32_t) USB_ETH_MTU-14; //102;
|
||||
|
||||
// case OID_GEN_RNDIS_CONFIG_PARAMETER:
|
||||
// break;
|
||||
|
||||
/******* 802.3 (Ethernet) *******/
|
||||
|
||||
/*The address of the NIC encoded in the hardware.*/
|
||||
case OID_802_3_PERMANENT_ADDRESS:
|
||||
|
||||
//Clear unused bytes
|
||||
*(INFBUF + 1) = 0;
|
||||
|
||||
//Set address
|
||||
*((uint8_t *)INFBUF + 0) = *(((uint8_t * ) &rndis_ethernet_addr) + 5);
|
||||
*((uint8_t *)INFBUF + 1) = *(((uint8_t * ) &rndis_ethernet_addr) + 4);
|
||||
*((uint8_t *)INFBUF + 2) = *(((uint8_t * ) &rndis_ethernet_addr) + 3);
|
||||
*((uint8_t *)INFBUF + 3) = *(((uint8_t * ) &rndis_ethernet_addr) + 2);
|
||||
*((uint8_t *)INFBUF + 4) = *(((uint8_t * ) &rndis_ethernet_addr) + 1);
|
||||
*((uint8_t *)INFBUF + 5) = *(((uint8_t * ) &rndis_ethernet_addr) + 0);
|
||||
|
||||
|
||||
/*4+2 = 6 Bytes of eth address */
|
||||
c->InformationBufferLength += 2;
|
||||
break;
|
||||
|
||||
/*The address the NIC is currently using.*/
|
||||
case OID_802_3_CURRENT_ADDRESS:
|
||||
|
||||
//Clear unused bytes
|
||||
*(INFBUF + 1) = 0;
|
||||
|
||||
//Set address
|
||||
*((uint8_t *)INFBUF + 0) = *(((uint8_t * ) &rndis_ethernet_addr) + 5);
|
||||
*((uint8_t *)INFBUF + 1) = *(((uint8_t * ) &rndis_ethernet_addr) + 4);
|
||||
*((uint8_t *)INFBUF + 2) = *(((uint8_t * ) &rndis_ethernet_addr) + 3);
|
||||
*((uint8_t *)INFBUF + 3) = *(((uint8_t * ) &rndis_ethernet_addr) + 2);
|
||||
*((uint8_t *)INFBUF + 4) = *(((uint8_t * ) &rndis_ethernet_addr) + 1);
|
||||
*((uint8_t *)INFBUF + 5) = *(((uint8_t * ) &rndis_ethernet_addr) + 0);
|
||||
//get address
|
||||
usb_eth_get_mac_address((uint8_t*)INFBUF);
|
||||
|
||||
/*4+2 = 6 Bytes of eth address */
|
||||
c->InformationBufferLength += 2;
|
||||
|
@ -495,20 +480,14 @@ void rndis_query_process(void)
|
|||
|
||||
/* Frames received with alignment error */
|
||||
case OID_802_3_RCV_ERROR_ALIGNMENT:
|
||||
*INFBUF = 0;
|
||||
break;
|
||||
|
||||
/* Frames transmitted with one collision */
|
||||
case OID_802_3_XMIT_ONE_COLLISION:
|
||||
*INFBUF = 0;
|
||||
break;
|
||||
|
||||
/* Frames transmitted with more than one collision */
|
||||
case OID_802_3_XMIT_MORE_COLLISIONS:
|
||||
*INFBUF = 0;
|
||||
break;
|
||||
|
||||
|
||||
#if USB_ETH_EMULATE_WIFI
|
||||
/*** 802.11 OIDs ***/
|
||||
case OID_802_11_BSSID:
|
||||
*INFBUF = (uint32_t)panid;
|
||||
|
@ -543,27 +522,28 @@ void rndis_query_process(void)
|
|||
case OID_802_11_WEP_STATUS:
|
||||
case OID_802_11_AUTHENTICATION_MODE:
|
||||
break;
|
||||
#endif //USB_ETH_EMULATE_WIFI
|
||||
|
||||
/*** Statistical ***/
|
||||
|
||||
/* Frames transmitted without errors */
|
||||
case OID_GEN_XMIT_OK:
|
||||
*INFBUF = rndis_stat.txok;
|
||||
*INFBUF = usb_eth_stat.txok;
|
||||
break;
|
||||
|
||||
/* Frames received without errors */
|
||||
case OID_GEN_RCV_OK:
|
||||
*INFBUF = rndis_stat.rxok;
|
||||
*INFBUF = usb_eth_stat.rxok;
|
||||
break;
|
||||
|
||||
/* Frames received with errors */
|
||||
case OID_GEN_RCV_ERROR:
|
||||
*INFBUF = rndis_stat.rxbad;
|
||||
*INFBUF = usb_eth_stat.rxbad;
|
||||
break;
|
||||
|
||||
/* Frames transmitted with errors */
|
||||
case OID_GEN_XMIT_ERROR:
|
||||
*INFBUF = rndis_stat.txbad;
|
||||
*INFBUF = usb_eth_stat.txbad;
|
||||
break;
|
||||
|
||||
/* Frames dropped due to lack of buffer space */
|
||||
|
@ -617,9 +597,21 @@ void rndis_query_process(void)
|
|||
#define CFGBUF ((rndis_config_parameter_t *) INFBUF)
|
||||
#define PARMNAME ((uint8_t *)CFGBUF + CFGBUF->ParameterNameOffset)
|
||||
#define PARMVALUE ((uint8_t *)CFGBUF + CFGBUF->ParameterValueOffset)
|
||||
|
||||
#define PARMVALUELENGTH CFGBUF->ParameterValueLength
|
||||
#define PARM_NAME_LENGTH 25 /* Maximum parameter name length */
|
||||
|
||||
bool
|
||||
rndis_handle_config_parm(const char* parmname,const uint8_t* parmvalue,size_t parmlength) {
|
||||
if (strncmp_P(parmname, PSTR("rawmode"), 7) == 0) {
|
||||
if (parmvalue[0] == '0') {
|
||||
usbstick_mode.raw = 0;
|
||||
} else {
|
||||
usbstick_mode.raw = 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Function to deal with a RNDIS "SET" command present in the
|
||||
* encapsulated_buffer
|
||||
|
@ -664,13 +656,7 @@ void rndis_set_process(void)
|
|||
Parameter type: single octet
|
||||
Parameter values: '0' = disabled, '1' = enabled
|
||||
*/
|
||||
if (strncmp_P(parmname, PSTR("rawmode"), 7) == 0) {
|
||||
if (*PARMVALUE == '0') {
|
||||
usbstick_mode.raw = 0;
|
||||
} else {
|
||||
usbstick_mode.raw = 1;
|
||||
}
|
||||
}
|
||||
rndis_handle_config_parm(parmname,PARMVALUE,PARMVALUELENGTH);
|
||||
|
||||
|
||||
break;
|
||||
|
@ -700,6 +686,7 @@ void rndis_set_process(void)
|
|||
case OID_802_3_MULTICAST_LIST:
|
||||
break;
|
||||
|
||||
#if USB_ETH_EMULATE_WIFI
|
||||
/* Mandatory 802.11 OIDs */
|
||||
case OID_802_11_BSSID:
|
||||
panid = *INFBUF;
|
||||
|
@ -708,6 +695,7 @@ void rndis_set_process(void)
|
|||
case OID_802_11_SSID:
|
||||
break;
|
||||
//TODO: rest of 802.11
|
||||
#endif // USB_ETH_EMULATE_WIFI
|
||||
|
||||
/* Power Managment: fails for now */
|
||||
case OID_PNP_ADD_WAKE_UP_PATTERN:
|
||||
|
@ -743,7 +731,7 @@ void rndis_set_process(void)
|
|||
* the "SEND ENCAPSULATED COMMAND" message, which will trigger
|
||||
* and interrupt on the host so it knows data is ready.
|
||||
*/
|
||||
uint8_t get_encapsulated_command(void)
|
||||
uint8_t rndis_get_encapsulated_command(void)
|
||||
{
|
||||
U8 nb_byte, zlp, i;
|
||||
|
||||
|
@ -828,6 +816,261 @@ uint8_t rndis_send_status(rndis_Status_t stat)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void rndis_configure_endpoints() {
|
||||
usb_configure_endpoint(INT_EP, \
|
||||
TYPE_INTERRUPT, \
|
||||
DIRECTION_IN, \
|
||||
SIZE_8, \
|
||||
ONE_BANK, \
|
||||
NYET_ENABLED);
|
||||
usb_configure_endpoint(TX_EP, \
|
||||
TYPE_BULK, \
|
||||
DIRECTION_IN, \
|
||||
SIZE_64, \
|
||||
TWO_BANKS, \
|
||||
NYET_ENABLED);
|
||||
|
||||
usb_configure_endpoint(RX_EP, \
|
||||
TYPE_BULK, \
|
||||
DIRECTION_OUT, \
|
||||
SIZE_64, \
|
||||
TWO_BANKS, \
|
||||
NYET_ENABLED);
|
||||
Usb_reset_endpoint(INT_EP);
|
||||
Usb_reset_endpoint(TX_EP);
|
||||
Usb_reset_endpoint(RX_EP);
|
||||
}
|
||||
|
||||
|
||||
extern char usb_busy;
|
||||
extern uint8_t usb_eth_data_buffer[64];
|
||||
#define PBUF ((rndis_data_packet_t *) usb_eth_data_buffer)
|
||||
|
||||
|
||||
uint8_t rndis_process(void)
|
||||
{
|
||||
uint8_t bytecounter, headercounter;
|
||||
uint16_t i, dataoffset;
|
||||
|
||||
if(rndis_state != rndis_data_initialized) { //Enumeration processs OK ?
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef USB_ETH_HOOK_INIT
|
||||
static uint8_t doInit = 1;
|
||||
if (doInit) {
|
||||
USB_ETH_HOOK_INIT();
|
||||
doInit = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
//Connected!
|
||||
Led0_on();
|
||||
|
||||
Usb_select_endpoint(RX_EP);
|
||||
|
||||
//If we have data and a free buffer
|
||||
if(Is_usb_receive_out() && (uip_len == 0)) {
|
||||
|
||||
//Read how much (endpoint only stores up to 64 bytes anyway)
|
||||
bytecounter = Usb_byte_counter_8();
|
||||
|
||||
//Try and read the header in
|
||||
headercounter = sizeof(rndis_data_packet_t);
|
||||
|
||||
uint8_t fail = 0;
|
||||
|
||||
//Hmm.. what's going on here
|
||||
if (bytecounter < headercounter) {
|
||||
Usb_ack_receive_out();
|
||||
fail = 1;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (headercounter) {
|
||||
usb_eth_data_buffer[i] = Usb_read_byte();
|
||||
bytecounter--;
|
||||
headercounter--;
|
||||
i++;
|
||||
}
|
||||
|
||||
//This is no good. Probably lost syncronization... just drop it for now
|
||||
if(PBUF->MessageType != REMOTE_NDIS_PACKET_MSG) {
|
||||
Usb_ack_receive_out();
|
||||
fail = 1;
|
||||
}
|
||||
|
||||
//802.3 does not have OOB data, and we don't care about per-packet data
|
||||
//so that just leave regular packet data...
|
||||
if (PBUF->DataLength && (fail == 0)) {
|
||||
|
||||
//Looks like we've got a live one
|
||||
#ifdef USB_ETH_HOOK_RX_START
|
||||
USB_ETH_HOOK_RX_START();
|
||||
#endif
|
||||
|
||||
//Get offset
|
||||
dataoffset = PBUF->DataOffset;
|
||||
|
||||
//Make it offset from start of message, not DataOffset field
|
||||
dataoffset += (sizeof(rndis_MessageType_t) + sizeof(rndis_MessageLength_t));
|
||||
|
||||
//Subtract what we already took
|
||||
dataoffset -= sizeof(rndis_data_packet_t);
|
||||
|
||||
//Clear this flag
|
||||
Usb_ack_nak_out();
|
||||
|
||||
//Read to the start of data
|
||||
while(dataoffset) {
|
||||
Usb_read_byte();
|
||||
dataoffset--;
|
||||
bytecounter--;
|
||||
|
||||
//If endpoint is done
|
||||
if (bytecounter == 0) {
|
||||
|
||||
Usb_ack_receive_out();
|
||||
|
||||
|
||||
//Wait for new data
|
||||
while (!Is_usb_receive_out() && (!Is_usb_receive_nak_out()));
|
||||
|
||||
//Check for NAK
|
||||
// TODO: darco: What in the world is this for?
|
||||
if (Is_usb_receive_nak_out()) {
|
||||
Usb_ack_nak_out();
|
||||
break;
|
||||
}
|
||||
|
||||
bytecounter = Usb_byte_counter_8();
|
||||
|
||||
//ZLP?
|
||||
if (bytecounter == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Read the data itself in
|
||||
uint8_t * uipdata = uip_buf;
|
||||
uint16_t datalen = PBUF->DataLength;
|
||||
|
||||
while(datalen) {
|
||||
*uipdata++ = Usb_read_byte();
|
||||
datalen--;
|
||||
bytecounter--;
|
||||
|
||||
//If endpoint is done
|
||||
if (bytecounter == 0) {
|
||||
//Might be everything we need!
|
||||
if (datalen) {
|
||||
Usb_ack_receive_out();
|
||||
//Wait for new data
|
||||
if(usb_endpoint_wait_for_receive_out()!=0) {
|
||||
USB_ETH_HOOK_RX_ERROR("Timeout: receive out");
|
||||
goto bail;
|
||||
}
|
||||
bytecounter = Usb_byte_counter_8();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Ack final data packet
|
||||
Usb_ack_receive_out();
|
||||
|
||||
#ifdef USB_ETH_HOOK_RX_END
|
||||
USB_ETH_HOOK_RX_END();
|
||||
#endif
|
||||
|
||||
//Send data over RF or to local stack
|
||||
if(PBUF->DataLength <= USB_ETH_MTU) {
|
||||
USB_ETH_HOOK_HANDLE_INBOUND_PACKET(uip_buf,PBUF->DataLength);
|
||||
} else {
|
||||
USB_ETH_HOOK_RX_ERROR("Oversized packet");
|
||||
}
|
||||
} //if (PBUF->DataLength)
|
||||
}
|
||||
bail:
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Send data over RNDIS interface, data is in uipbuf and length is uiplen
|
||||
*/
|
||||
uint8_t rndis_send(uint8_t * senddata, uint16_t sendlen, uint8_t led)
|
||||
{
|
||||
|
||||
|
||||
uint16_t i;
|
||||
|
||||
//Setup Header
|
||||
PBUF->MessageType = REMOTE_NDIS_PACKET_MSG;
|
||||
PBUF->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_MessageType_t) - sizeof(rndis_MessageLength_t);
|
||||
PBUF->DataLength = sendlen;
|
||||
PBUF->OOBDataLength = 0;
|
||||
PBUF->OOBDataOffset = 0;
|
||||
PBUF->NumOOBDataElements = 0;
|
||||
PBUF->PerPacketInfoOffset = 0;
|
||||
PBUF->PerPacketInfoLength = 0;
|
||||
PBUF->DeviceVcHandle = 0;
|
||||
PBUF->Reserved = 0;
|
||||
PBUF->MessageLength = sizeof(rndis_data_packet_t) + PBUF->DataLength;
|
||||
|
||||
//Send Data
|
||||
Usb_select_endpoint(TX_EP);
|
||||
Usb_send_in();
|
||||
|
||||
//Wait for ready
|
||||
if(usb_endpoint_wait_for_write_enabled()!=0) {
|
||||
USB_ETH_HOOK_TX_ERROR("Timeout: write enabled");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef USB_ETH_HOOK_TX_START
|
||||
USB_ETH_HOOK_TX_START();
|
||||
#endif
|
||||
|
||||
//Setup first part of transfer...
|
||||
for(i = 0; i < sizeof(rndis_data_packet_t); i++) {
|
||||
Usb_write_byte(usb_eth_data_buffer[i]);
|
||||
}
|
||||
|
||||
//Send packet
|
||||
while(sendlen) {
|
||||
Usb_write_byte(*senddata);
|
||||
senddata++;
|
||||
sendlen--;
|
||||
|
||||
//If endpoint is full, send data in
|
||||
//And then wait for data to transfer
|
||||
if (!Is_usb_write_enabled()) {
|
||||
Usb_send_in();
|
||||
|
||||
if(usb_endpoint_wait_for_write_enabled()!=0) {
|
||||
USB_ETH_HOOK_TX_ERROR("Timeout: write enabled");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Usb_send_in();
|
||||
|
||||
#ifdef USB_ETH_HOOK_TX_END
|
||||
USB_ETH_HOOK_TX_END();
|
||||
#endif
|
||||
|
||||
//Wait for ready
|
||||
if(usb_endpoint_wait_for_IN_ready()!=0) {
|
||||
USB_ETH_HOOK_TX_ERROR("Timeout: IN ready");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/****************** Radio Interface ****************/
|
||||
|
||||
|
@ -837,15 +1080,11 @@ uint8_t rndis_send_status(rndis_Status_t stat)
|
|||
*/
|
||||
void rndis_packetFilter(uint32_t newfilter)
|
||||
{
|
||||
#if !RF230BB
|
||||
if (newfilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
|
||||
rxMode = RX_ON;
|
||||
radio_set_trx_state(RX_ON);
|
||||
USB_ETH_HOOK_SET_PROMISCIOUS_MODE(true);
|
||||
} else {
|
||||
rxMode = RX_AACK_ON;
|
||||
radio_set_trx_state(RX_AACK_ON);
|
||||
USB_ETH_HOOK_SET_PROMISCIOUS_MODE(false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -303,22 +303,23 @@ typedef struct{
|
|||
uint32_t rxok;
|
||||
uint32_t txbad;
|
||||
uint32_t rxbad;
|
||||
} rndis_stat_t;
|
||||
} usb_eth_stat_t;
|
||||
|
||||
extern rndis_stat_t rndis_stat;
|
||||
extern usb_eth_stat_t usb_eth_stat;
|
||||
|
||||
extern rndis_state_t rndis_state;
|
||||
|
||||
extern uint8_t schedule_interrupt;
|
||||
|
||||
extern uint64_t rndis_ethernet_addr;
|
||||
|
||||
uint8_t send_encapsulated_command(uint16_t wLength);
|
||||
uint8_t get_encapsulated_command(void);
|
||||
uint8_t rndis_send_encapsulated_command(uint16_t wLength);
|
||||
uint8_t rndis_get_encapsulated_command(void);
|
||||
void rndis_send_interrupt(void);
|
||||
void rndis_query_process(void);
|
||||
void rndis_set_process(void);
|
||||
uint8_t rndis_send_status(rndis_Status_t stat);
|
||||
uint8_t rndis_process(void);
|
||||
uint8_t rndis_send(uint8_t * senddata, uint16_t sendlen, uint8_t led);
|
||||
extern void rndis_configure_endpoints();
|
||||
|
||||
#endif //_RNDIS_H
|
||||
|
||||
|
|
|
@ -59,6 +59,9 @@
|
|||
#include <avr/pgmspace.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
#include "rndis/cdc_ecm.h"
|
||||
#include "rndis/cdc_eem.h"
|
||||
|
||||
#define BUF ((struct uip_eth_hdr *)&uip_buf[0])
|
||||
#define PRINTF printf
|
||||
#define PRINTF_P printf_P
|
||||
|
@ -66,12 +69,6 @@
|
|||
//_____ M A C R O S ________________________________________________________
|
||||
|
||||
|
||||
#define EEMCMD_ECHO 0x00 ///bmEEMCmd Echo
|
||||
#define EEMCMD_ECHO_RESPONSE 0x01 ///bmEEMCmd Echo Response
|
||||
#define EEMCMD_SUSPEND_HINT 0x02 ///bmEEMCmd Suspend Hint
|
||||
#define EEMCMD_RESPONSE_HINT 0x03 ///bmEEMCmd Response Hint
|
||||
#define EEMCMD_RESPONSE_COMPLETE_HINT 0x04 ///bmEEMCmd Response Complete Hint
|
||||
#define EEMCMD_TICKLE 0x05 ///bmEEMCmd Tickle
|
||||
|
||||
|
||||
|
||||
|
@ -84,436 +81,210 @@
|
|||
#define RNDIS_TIMEOUT_DETACH 900
|
||||
#define RNDIS_TIMEOUT_ATTACH 1000
|
||||
|
||||
#define PBUF ((rndis_data_packet_t *) data_buffer)
|
||||
#define PBUF ((rndis_data_packet_t *) usb_eth_data_buffer)
|
||||
|
||||
//! Temp data buffer when adding RNDIS headers
|
||||
uint8_t usb_eth_data_buffer[64];
|
||||
|
||||
uint64_t usb_ethernet_addr = 0x010000000002ULL;
|
||||
|
||||
//_____ D E C L A R A T I O N S ____________________________________________
|
||||
|
||||
uint8_t eem_send(uint8_t * senddata, uint16_t sendlen, uint8_t led);
|
||||
uint8_t rndis_send(uint8_t * senddata, uint16_t sendlen, uint8_t led);
|
||||
|
||||
//! Timers for LEDs
|
||||
uint8_t led1_timer, led2_timer;
|
||||
|
||||
//! Temp data buffer when adding RNDIS headers
|
||||
uint8_t data_buffer[64];
|
||||
|
||||
//! Usb is busy with RNDIS
|
||||
char usb_busy = 0;
|
||||
uint8_t usb_eth_is_active = 1;
|
||||
|
||||
|
||||
static struct etimer et;
|
||||
static struct timer flood_timer;
|
||||
uint8_t usb_eth_packet_is_available() {
|
||||
Usb_select_endpoint(RX_EP);
|
||||
return Is_usb_read_enabled();
|
||||
}
|
||||
|
||||
static uint8_t doInit = 1;
|
||||
|
||||
extern uint8_t fingerPresent;
|
||||
uint8_t usb_eth_ready_for_next_packet() {
|
||||
#ifdef USB_ETH_HOOK_IS_READY_FOR_INBOUND_PACKET
|
||||
return USB_ETH_HOOK_IS_READY_FOR_INBOUND_PACKET();
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
PROCESS(rndis_process, "RNDIS process");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void rxtx_led_update(void)
|
||||
{
|
||||
// turn off LED's if necessary
|
||||
if (led1_timer) {
|
||||
led1_timer--;
|
||||
if(led1_timer&(1<<2))
|
||||
Led1_on();
|
||||
else
|
||||
Led1_off();
|
||||
}
|
||||
else
|
||||
Led1_off();
|
||||
|
||||
if (led2_timer) {
|
||||
led2_timer--;
|
||||
if(led2_timer&(1<<2))
|
||||
Led2_on();
|
||||
else
|
||||
Led2_off();
|
||||
}
|
||||
else
|
||||
Led2_off();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief This will enable the RX_START LED for a period
|
||||
*/
|
||||
void rx_start_led(void)
|
||||
{
|
||||
led1_timer|=(1<<3);
|
||||
if(((led1_timer-1)&(1<<2)))
|
||||
Led1_on();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief This will enable the TRX_END LED for a period
|
||||
*/
|
||||
void tx_end_led(void)
|
||||
{
|
||||
led2_timer|=(1<<3);
|
||||
if(((led2_timer-1)&(1<<2)))
|
||||
Led1_on();
|
||||
}
|
||||
|
||||
#if USB_ETH_CONF_MASS_STORAGE_FALLBACK
|
||||
static void
|
||||
usb_eth_setup_timeout_fallback_check() {
|
||||
extern uint8_t fingerPresent;
|
||||
/* Device is Enumerated but RNDIS not loading. We might
|
||||
have a system that does not support IAD (winXP). If so
|
||||
count the timeout then switch to just network interface. */
|
||||
static uint16_t iad_fail_timeout, rndis_fail_timeout;
|
||||
if (usb_mode == rndis_debug) {
|
||||
//If we have timed out, detach
|
||||
if (iad_fail_timeout == IAD_TIMEOUT_DETACH) {
|
||||
|
||||
//Failed - BUT we are using "reverse logic", hence we force device
|
||||
//into this mode. This is used to allow Windows Vista have time to
|
||||
//install the drivers
|
||||
if (fingerPresent && (rndis_state != rndis_data_initialized) && Is_device_enumerated() ) {
|
||||
iad_fail_timeout = 0;
|
||||
} else {
|
||||
stdout = NULL;
|
||||
Usb_detach();
|
||||
doInit = 1; //Also mark system as needing intilizing
|
||||
}
|
||||
|
||||
//Then wait a few before re-attaching
|
||||
} else if (iad_fail_timeout == IAD_TIMEOUT_ATTACH) {
|
||||
|
||||
if (fingerPresent) {
|
||||
usb_mode = mass_storage;
|
||||
} else {
|
||||
usb_mode = rndis_only;
|
||||
}
|
||||
Usb_attach();
|
||||
}
|
||||
|
||||
//Increment timeout when device is not initializing, OR we have already detached,
|
||||
//OR the user had their finger on the device, indicating a reverse of logic
|
||||
if ( ( (rndis_state != rndis_data_initialized) && Is_device_enumerated() ) ||
|
||||
(iad_fail_timeout > IAD_TIMEOUT_DETACH) ||
|
||||
(fingerPresent) ) {
|
||||
iad_fail_timeout++;
|
||||
} else {
|
||||
iad_fail_timeout = 0;
|
||||
}
|
||||
} //usb_mode == rndis_debug
|
||||
|
||||
|
||||
/* Device is Enumerated but RNDIS STIL not loading. We just
|
||||
have RNDIS interface, so obviously no drivers on target.
|
||||
Just go ahead and mount ourselves as mass storage... */
|
||||
if (usb_mode == rndis_only) {
|
||||
//If we have timed out, detach
|
||||
if (rndis_fail_timeout == RNDIS_TIMEOUT_DETACH) {
|
||||
Usb_detach();
|
||||
//Then wait a few before re-attaching
|
||||
} else if (rndis_fail_timeout == RNDIS_TIMEOUT_ATTACH) {
|
||||
usb_mode = mass_storage;
|
||||
Usb_attach();
|
||||
}
|
||||
|
||||
//Increment timeout when device is not initializing, OR we are already
|
||||
//counting to detach
|
||||
if ( ( (rndis_state != rndis_data_initialized)) ||
|
||||
(rndis_fail_timeout > RNDIS_TIMEOUT_DETACH) ) {
|
||||
rndis_fail_timeout++;
|
||||
} else {
|
||||
rndis_fail_timeout = 0;
|
||||
}
|
||||
}//usb_mode == rnids_only
|
||||
}
|
||||
#endif
|
||||
|
||||
PROCESS(usb_eth_process, "USB Ethernet process");
|
||||
|
||||
/**
|
||||
* \brief RNDIS Process
|
||||
*
|
||||
* This is the link between USB and the "good stuff". In this routine data
|
||||
* is received and processed by RNDIS
|
||||
* is received and processed by RNDIS, CDC-ECM, or CDC-EEM
|
||||
*/
|
||||
PROCESS_THREAD(rndis_process, ev, data_proc)
|
||||
PROCESS_THREAD(usb_eth_process, ev, data_proc)
|
||||
{
|
||||
static struct etimer et;
|
||||
|
||||
PROCESS_BEGIN();
|
||||
uint8_t bytecounter, headercounter;
|
||||
uint16_t i, dataoffset;
|
||||
clock_time_t timediff;
|
||||
clock_time_t thetime;
|
||||
|
||||
while(1) {
|
||||
rxtx_led_update();
|
||||
|
||||
// turn off LED's if necessary
|
||||
if (led1_timer) led1_timer--;
|
||||
else Led1_off();
|
||||
if (led2_timer) led2_timer--;
|
||||
else Led2_off();
|
||||
|
||||
/* Device is Enumerated but RNDIS not loading. We might
|
||||
have a system that does not support IAD (winXP). If so
|
||||
count the timeout then switch to just network interface. */
|
||||
#if 0
|
||||
static uint16_t iad_fail_timeout, rndis_fail_timeout;
|
||||
if (usb_mode == rndis_debug) {
|
||||
//If we have timed out, detach
|
||||
if (iad_fail_timeout == IAD_TIMEOUT_DETACH) {
|
||||
|
||||
//Failed - BUT we are using "reverse logic", hence we force device
|
||||
//into this mode. This is used to allow Windows Vista have time to
|
||||
//install the drivers
|
||||
if (fingerPresent && (rndis_state != rndis_data_initialized) && Is_device_enumerated() ) {
|
||||
iad_fail_timeout = 0;
|
||||
} else {
|
||||
stdout = NULL;
|
||||
Usb_detach();
|
||||
doInit = 1; //Also mark system as needing intilizing
|
||||
}
|
||||
|
||||
//Then wait a few before re-attaching
|
||||
} else if (iad_fail_timeout == IAD_TIMEOUT_ATTACH) {
|
||||
|
||||
if (fingerPresent) {
|
||||
usb_mode = mass_storage;
|
||||
} else {
|
||||
usb_mode = rndis_only;
|
||||
}
|
||||
Usb_attach();
|
||||
}
|
||||
|
||||
//Increment timeout when device is not initializing, OR we have already detached,
|
||||
//OR the user had their finger on the device, indicating a reverse of logic
|
||||
if ( ( (rndis_state != rndis_data_initialized) && Is_device_enumerated() ) ||
|
||||
(iad_fail_timeout > IAD_TIMEOUT_DETACH) ||
|
||||
(fingerPresent) ) {
|
||||
iad_fail_timeout++;
|
||||
} else {
|
||||
iad_fail_timeout = 0;
|
||||
}
|
||||
} //usb_mode == rndis_debug
|
||||
|
||||
|
||||
/* Device is Enumerated but RNDIS STIL not loading. We just
|
||||
have RNDIS interface, so obviously no drivers on target.
|
||||
Just go ahead and mount ourselves as mass storage... */
|
||||
if (usb_mode == rndis_only) {
|
||||
//If we have timed out, detach
|
||||
if (rndis_fail_timeout == RNDIS_TIMEOUT_DETACH) {
|
||||
Usb_detach();
|
||||
//Then wait a few before re-attaching
|
||||
} else if (rndis_fail_timeout == RNDIS_TIMEOUT_ATTACH) {
|
||||
usb_mode = mass_storage;
|
||||
Usb_attach();
|
||||
}
|
||||
|
||||
//Increment timeout when device is not initializing, OR we are already
|
||||
//counting to detach
|
||||
if ( ( (rndis_state != rndis_data_initialized)) ||
|
||||
(rndis_fail_timeout > RNDIS_TIMEOUT_DETACH) ) {
|
||||
rndis_fail_timeout++;
|
||||
} else {
|
||||
rndis_fail_timeout = 0;
|
||||
}
|
||||
}//usb_mode == rnids_only
|
||||
#if USB_ETH_CONF_MASS_STORAGE_FALLBACK
|
||||
usb_eth_setup_timeout_fallback_check();
|
||||
#endif
|
||||
|
||||
|
||||
if(rndis_state == rndis_data_initialized) //Enumeration processs OK ?
|
||||
{
|
||||
if (doInit) {
|
||||
//start flood timer
|
||||
timer_set(&flood_timer, CLOCK_SECOND / 5);
|
||||
|
||||
mac_ethernetSetup();
|
||||
doInit = 0;
|
||||
}
|
||||
|
||||
//Connected!
|
||||
Led0_on();
|
||||
|
||||
Usb_select_endpoint(RX_EP);
|
||||
|
||||
//If we have data and a free buffer
|
||||
if(Is_usb_receive_out() && (uip_len == 0)) {
|
||||
|
||||
//TODO: Fix this some better way
|
||||
//If you need a delay in RNDIS to slow down super-fast sending, insert it here
|
||||
//Also mark the USB as "in use"
|
||||
|
||||
//This is done as "flood control" by only allowing one IP packet per time limit
|
||||
thetime = clock_time();
|
||||
|
||||
timediff = thetime - flood_timer.start;
|
||||
|
||||
//Oops, timer wrapped! Just ignore it for now
|
||||
if (thetime < flood_timer.start) {
|
||||
timediff = flood_timer.interval;
|
||||
}
|
||||
|
||||
|
||||
//If timer not yet expired
|
||||
//if (timediff < flood_timer.interval) {
|
||||
if (!timer_expired(&flood_timer)) {
|
||||
//Wait until timer expiers
|
||||
usb_busy = 1;
|
||||
etimer_set(&et, flood_timer.interval - timediff);
|
||||
//Try commenting out the next line if Jackdaw stops RF transmission in Windows after a 5 minute idle period - dak
|
||||
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
|
||||
|
||||
//Reselect endpoint in case we lost it
|
||||
Usb_select_endpoint(RX_EP);
|
||||
usb_busy = 0;
|
||||
}
|
||||
|
||||
|
||||
//Restart flood timer
|
||||
timer_restart(&flood_timer);
|
||||
|
||||
//Read how much (endpoint only stores up to 64 bytes anyway)
|
||||
bytecounter = Usb_byte_counter_8();
|
||||
|
||||
//Try and read the header in
|
||||
headercounter = sizeof(rndis_data_packet_t);
|
||||
|
||||
uint8_t fail = 0;
|
||||
|
||||
//Hmm.. what's going on here
|
||||
if (bytecounter < headercounter) {
|
||||
Usb_ack_receive_out();
|
||||
fail = 1;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (headercounter) {
|
||||
data_buffer[i] = Usb_read_byte();
|
||||
bytecounter--;
|
||||
headercounter--;
|
||||
i++;
|
||||
}
|
||||
|
||||
//This is no good. Probably lost syncronization... just drop it for now
|
||||
if(PBUF->MessageType != REMOTE_NDIS_PACKET_MSG) {
|
||||
Usb_ack_receive_out();
|
||||
fail = 1;
|
||||
}
|
||||
|
||||
//802.3 does not have OOB data, and we don't care about per-packet data
|
||||
//so that just leave regular packet data...
|
||||
if (PBUF->DataLength && (fail == 0)) {
|
||||
|
||||
//Looks like we've got a live one
|
||||
rx_start_led();
|
||||
|
||||
|
||||
//Get offset
|
||||
dataoffset = PBUF->DataOffset;
|
||||
|
||||
//Make it offset from start of message, not DataOffset field
|
||||
dataoffset += (sizeof(rndis_MessageType_t) + sizeof(rndis_MessageLength_t));
|
||||
|
||||
//Subtract what we already took
|
||||
dataoffset -= sizeof(rndis_data_packet_t);
|
||||
|
||||
//Clear this flag
|
||||
Usb_ack_nak_out();
|
||||
|
||||
//Read to the start of data
|
||||
while(dataoffset) {
|
||||
Usb_read_byte();
|
||||
dataoffset--;
|
||||
bytecounter--;
|
||||
|
||||
//If endpoint is done
|
||||
if (bytecounter == 0) {
|
||||
|
||||
Usb_ack_receive_out();
|
||||
|
||||
|
||||
//Wait for new data
|
||||
while (!Is_usb_receive_out() && (!Is_usb_receive_nak_out()));
|
||||
|
||||
//Check for NAK
|
||||
if (Is_usb_receive_nak_out()) {
|
||||
Usb_ack_nak_out();
|
||||
break;
|
||||
}
|
||||
|
||||
bytecounter = Usb_byte_counter_8();
|
||||
|
||||
//ZLP?
|
||||
if (bytecounter == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Read the data itself in
|
||||
uint8_t * uipdata = uip_buf;
|
||||
uint16_t datalen = PBUF->DataLength;
|
||||
|
||||
while(datalen) {
|
||||
*uipdata++ = Usb_read_byte();
|
||||
datalen--;
|
||||
bytecounter--;
|
||||
|
||||
//If endpoint is done
|
||||
if (bytecounter == 0) {
|
||||
//Might be everything we need!
|
||||
if (datalen) {
|
||||
Usb_ack_receive_out();
|
||||
//Wait for new data
|
||||
while (!Is_usb_receive_out());
|
||||
bytecounter = Usb_byte_counter_8();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Ack final data packet
|
||||
Usb_ack_receive_out();
|
||||
|
||||
//Send data over RF or to local stack
|
||||
uip_len = PBUF->DataLength; //uip_len includes LLH_LEN
|
||||
mac_ethernetToLowpan(uip_buf);
|
||||
|
||||
|
||||
|
||||
} //if (PBUF->DataLength)
|
||||
|
||||
|
||||
} //if(Is_usb_receive_out() && (uip_len == 0))
|
||||
|
||||
} // if (rndis_data_intialized)
|
||||
else if(Is_device_enumerated() && //Enumeration processs OK &&
|
||||
(usb_mode == eem) ) //USB Stick is using EEM
|
||||
{
|
||||
uint16_t datalength;
|
||||
|
||||
if (doInit) {
|
||||
mac_ethernetSetup();
|
||||
doInit = 0;
|
||||
}
|
||||
|
||||
//Connected!
|
||||
Led0_on();
|
||||
|
||||
Usb_select_endpoint(RX_EP);
|
||||
|
||||
//If we have data and a free buffer
|
||||
if(Is_usb_receive_out() && (uip_len == 0)) {
|
||||
|
||||
//Read how much (endpoint only stores up to 64 bytes anyway)
|
||||
bytecounter = Usb_byte_counter_8();
|
||||
|
||||
//EEM uses 2 bytes as a header
|
||||
headercounter = 2;
|
||||
|
||||
uint8_t fail = 0;
|
||||
|
||||
//Hmm.. what's going on here?
|
||||
if (bytecounter < headercounter) {
|
||||
Usb_ack_receive_out();
|
||||
//TODO CO done = 1;
|
||||
}
|
||||
|
||||
//Read EEM Header
|
||||
i = 0;
|
||||
while (headercounter) {
|
||||
data_buffer[i] = Usb_read_byte();
|
||||
bytecounter--;
|
||||
headercounter--;
|
||||
i++;
|
||||
}
|
||||
|
||||
//Order is LSB/MSB, so MSN is in data_buffer[1]
|
||||
//Bit 15 indicates command packet when set
|
||||
if (data_buffer[1] & 0x80) {
|
||||
//not a data payload
|
||||
datalength = 0;
|
||||
} else {
|
||||
//'0' indicates data packet
|
||||
//Length is lower 14 bits
|
||||
datalength = data_buffer[0] | ((data_buffer[1] & 0x3F) << 8);
|
||||
}
|
||||
|
||||
/* EEM Command Packet */
|
||||
if ((datalength == 0) && (fail == 0))
|
||||
{
|
||||
uint8_t command;
|
||||
uint16_t echoLength;
|
||||
|
||||
//Strip command off
|
||||
command = data_buffer[1] & 0x38;
|
||||
command = command >> 3;
|
||||
|
||||
//Decode command type
|
||||
switch (command)
|
||||
{
|
||||
/* Echo Request */
|
||||
case EEMCMD_ECHO:
|
||||
|
||||
//Get echo length
|
||||
echoLength = (data_buffer[1] & 0x07) << 8; //MSB
|
||||
echoLength |= data_buffer[0]; //LSB
|
||||
|
||||
//TODO: everything. oops.
|
||||
|
||||
break;
|
||||
|
||||
/* Everything else: Whatever. */
|
||||
case EEMCMD_ECHO_RESPONSE:
|
||||
case EEMCMD_SUSPEND_HINT:
|
||||
case EEMCMD_RESPONSE_HINT:
|
||||
case EEMCMD_RESPONSE_COMPLETE_HINT:
|
||||
case EEMCMD_TICKLE:
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
/* EEM Data Packet */
|
||||
else if (datalength && (fail == 0))
|
||||
{
|
||||
//Looks like we've got a live one
|
||||
rx_start_led();
|
||||
|
||||
uint16_t bytes_received = 0;
|
||||
uint16_t dataleft = datalength;
|
||||
U8 * buffer = uip_buf;
|
||||
|
||||
while(dataleft)
|
||||
{
|
||||
*buffer++ = Usb_read_byte();
|
||||
|
||||
dataleft--;
|
||||
bytecounter--;
|
||||
bytes_received++;
|
||||
|
||||
//Check if endpoint is done but we are expecting more data
|
||||
if ((bytecounter == 0) && (dataleft))
|
||||
{
|
||||
//ACK previous data
|
||||
Usb_ack_receive_out();
|
||||
|
||||
//Wait for new data
|
||||
while (!Is_usb_receive_out());
|
||||
|
||||
//Get new data
|
||||
bytecounter = Usb_byte_counter_8();
|
||||
|
||||
//ZLP?
|
||||
if (bytecounter == 0)
|
||||
{
|
||||
//Incomplete!!
|
||||
break;
|
||||
}
|
||||
|
||||
switch(usb_configuration_nb) {
|
||||
case USB_CONFIG_RNDIS_DEBUG:
|
||||
case USB_CONFIG_RNDIS:
|
||||
if(Is_device_enumerated()) {
|
||||
if(rndis_process()) {
|
||||
etimer_set(&et, CLOCK_SECOND/80);
|
||||
} else {
|
||||
Led0_toggle();
|
||||
etimer_set(&et, CLOCK_SECOND/8);
|
||||
}
|
||||
}
|
||||
|
||||
//Ack final data packet
|
||||
Usb_ack_receive_out();
|
||||
|
||||
//Packet has CRC, nobody wants that garbage
|
||||
datalength -= 4;
|
||||
|
||||
//Send data over RF or to local stack
|
||||
uip_len = datalength; //uip_len includes LLH_LEN
|
||||
mac_ethernetToLowpan(uip_buf);
|
||||
|
||||
} //if (datalength)
|
||||
} //if(Is_usb_receive_out() && (uip_len == 0))
|
||||
} // if (Is_device_enumerated())
|
||||
|
||||
if ((usb_mode == rndis_only) || (usb_mode == rndis_debug) || (usb_mode == eem)) {
|
||||
etimer_set(&et, CLOCK_SECOND/80);
|
||||
} else {
|
||||
etimer_set(&et, CLOCK_SECOND);
|
||||
break;
|
||||
case USB_CONFIG_EEM:
|
||||
if(Is_device_enumerated())
|
||||
cdc_eem_process();
|
||||
etimer_set(&et, CLOCK_SECOND/80);
|
||||
break;
|
||||
case USB_CONFIG_ECM:
|
||||
case USB_CONFIG_ECM_DEBUG:
|
||||
if(Is_device_enumerated()) {
|
||||
if(cdc_ecm_process()) {
|
||||
etimer_set(&et, CLOCK_SECOND/80);
|
||||
} else {
|
||||
Led0_toggle();
|
||||
etimer_set(&et, CLOCK_SECOND/8);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Led0_toggle();
|
||||
etimer_set(&et, CLOCK_SECOND/4);
|
||||
break;
|
||||
}
|
||||
|
||||
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
|
||||
|
||||
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)||(usb_eth_packet_is_available()&&usb_eth_ready_for_next_packet()));
|
||||
} // while(1)
|
||||
|
||||
PROCESS_END();
|
||||
|
@ -527,172 +298,70 @@ static uint16_t iad_fail_timeout, rndis_fail_timeout;
|
|||
*/
|
||||
uint8_t usb_eth_send(uint8_t * senddata, uint16_t sendlen, uint8_t led)
|
||||
{
|
||||
if (usb_mode == eem)
|
||||
return eem_send(senddata, sendlen, led);
|
||||
uint8_t ret = 0;
|
||||
|
||||
if(!usb_eth_is_active) {
|
||||
USB_ETH_HOOK_TX_ERROR("Inactive");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if ((usb_mode == rndis_only) || (usb_mode == rndis_debug))
|
||||
return rndis_send(senddata, sendlen, led);
|
||||
//Check device is set up
|
||||
if (Is_device_enumerated() == 0) {
|
||||
USB_ETH_HOOK_TX_ERROR("Device not enumerated");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
switch(usb_configuration_nb) {
|
||||
case USB_CONFIG_RNDIS_DEBUG:
|
||||
case USB_CONFIG_RNDIS:
|
||||
ret = rndis_send(senddata, sendlen, led);
|
||||
break;
|
||||
case USB_CONFIG_EEM:
|
||||
ret = eem_send(senddata, sendlen, led);
|
||||
break;
|
||||
case USB_CONFIG_ECM:
|
||||
case USB_CONFIG_ECM_DEBUG:
|
||||
ret = ecm_send(senddata, sendlen, led);
|
||||
break;
|
||||
}
|
||||
|
||||
bail:
|
||||
|
||||
if(!ret) // Hit the watchdog if we have a successful send.
|
||||
watchdog_periodic();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
usb_eth_set_active(uint8_t active) {
|
||||
if(usb_eth_is_active!=active) {
|
||||
switch(usb_configuration_nb) {
|
||||
case USB_CONFIG_RNDIS_DEBUG:
|
||||
case USB_CONFIG_RNDIS:
|
||||
usb_eth_is_active = active;
|
||||
rndis_send_interrupt();
|
||||
break;
|
||||
case USB_CONFIG_EEM:
|
||||
break;
|
||||
case USB_CONFIG_ECM:
|
||||
case USB_CONFIG_ECM_DEBUG:
|
||||
cdc_ecm_set_active(active);
|
||||
usb_eth_is_active = active;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Send a single ethernet frame using EEM
|
||||
*/
|
||||
uint8_t eem_send(uint8_t * senddata, uint16_t sendlen, uint8_t led)
|
||||
{
|
||||
//Check device is set up
|
||||
if (Is_device_enumerated() == 0)
|
||||
return 0;
|
||||
|
||||
//Make a header
|
||||
uint8_t header[2];
|
||||
|
||||
//Fake CRC! Add 4 to length for CRC
|
||||
sendlen += 4;
|
||||
header[0] = (sendlen >> 8) & 0x3f;
|
||||
header[1] = sendlen & 0xff;
|
||||
|
||||
//We send CRC seperatly..
|
||||
sendlen -= 4;
|
||||
|
||||
//Send Data
|
||||
Usb_select_endpoint(TX_EP);
|
||||
//Usb_send_in();
|
||||
|
||||
//Wait for ready
|
||||
while(!Is_usb_write_enabled());
|
||||
|
||||
//Send header (LSB then MSB)
|
||||
Usb_write_byte(header[1]);
|
||||
Usb_write_byte(header[0]);
|
||||
|
||||
//Send packet
|
||||
while(sendlen) {
|
||||
Usb_write_byte(*senddata);
|
||||
senddata++;
|
||||
sendlen--;
|
||||
|
||||
//If endpoint is full, send data in
|
||||
//And then wait for data to transfer
|
||||
if (!Is_usb_write_enabled()) {
|
||||
Usb_send_in();
|
||||
|
||||
while(!Is_usb_write_enabled());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//CRC = 0xdeadbeef
|
||||
//Linux kernel 2.6.31 needs 0xdeadbeef in wrong order,
|
||||
//like this: uint8_t crc[4] = {0xef, 0xbe, 0xad, 0xde};
|
||||
//This is fixed in 2.6.32 to the correct order (0xde, 0xad, 0xbe, 0xef)
|
||||
uint8_t crc[4] = {0xde, 0xad, 0xbe, 0xef};
|
||||
|
||||
sendlen = 4;
|
||||
uint8_t i = 0;
|
||||
|
||||
//Send fake CRC
|
||||
while(sendlen) {
|
||||
Usb_write_byte(crc[i]);
|
||||
i++;
|
||||
sendlen--;
|
||||
|
||||
//If endpoint is full, send data in
|
||||
//And then wait for data to transfer
|
||||
if (!Is_usb_write_enabled()) {
|
||||
Usb_send_in();
|
||||
|
||||
while(!Is_usb_write_enabled());
|
||||
}
|
||||
|
||||
if (led) {
|
||||
tx_end_led();
|
||||
}
|
||||
}
|
||||
|
||||
//Send last data in - also handles sending a ZLP if needed
|
||||
Usb_send_in();
|
||||
|
||||
//Wait for ready
|
||||
while(!Is_usb_write_enabled());
|
||||
|
||||
return 1;
|
||||
void
|
||||
usb_eth_get_mac_address(uint8_t dest[6]) {
|
||||
memcpy(dest,&usb_ethernet_addr,6);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Send data over RNDIS interface, data is in uipbuf and length is uiplen
|
||||
*/
|
||||
uint8_t rndis_send(uint8_t * senddata, uint16_t sendlen, uint8_t led)
|
||||
{
|
||||
|
||||
|
||||
uint16_t i;
|
||||
|
||||
//Setup Header
|
||||
PBUF->MessageType = REMOTE_NDIS_PACKET_MSG;
|
||||
PBUF->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_MessageType_t) - sizeof(rndis_MessageLength_t);
|
||||
PBUF->DataLength = sendlen;
|
||||
PBUF->OOBDataLength = 0;
|
||||
PBUF->OOBDataOffset = 0;
|
||||
PBUF->NumOOBDataElements = 0;
|
||||
PBUF->PerPacketInfoOffset = 0;
|
||||
PBUF->PerPacketInfoLength = 0;
|
||||
PBUF->DeviceVcHandle = 0;
|
||||
PBUF->Reserved = 0;
|
||||
PBUF->MessageLength = sizeof(rndis_data_packet_t) + PBUF->DataLength;
|
||||
|
||||
//Send Data
|
||||
Usb_select_endpoint(TX_EP);
|
||||
Usb_send_in();
|
||||
|
||||
//Wait for ready
|
||||
while(!Is_usb_write_enabled());
|
||||
|
||||
//Setup first part of transfer...
|
||||
for(i = 0; i < sizeof(rndis_data_packet_t); i++) {
|
||||
Usb_write_byte(data_buffer[i]);
|
||||
}
|
||||
|
||||
//Send packet
|
||||
while(sendlen) {
|
||||
Usb_write_byte(*senddata);
|
||||
senddata++;
|
||||
sendlen--;
|
||||
|
||||
//If endpoint is full, send data in
|
||||
//And then wait for data to transfer
|
||||
if (!Is_usb_write_enabled()) {
|
||||
Usb_send_in();
|
||||
|
||||
while(!Is_usb_write_enabled());
|
||||
}
|
||||
|
||||
if (led) {
|
||||
tx_end_led();
|
||||
}
|
||||
}
|
||||
|
||||
Usb_send_in();
|
||||
|
||||
return 1;
|
||||
void
|
||||
usb_eth_set_mac_address(const uint8_t src[6]) {
|
||||
memcpy(&usb_ethernet_addr,src,6);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief This will enable the RX_START LED for a period
|
||||
*/
|
||||
void rx_start_led(void)
|
||||
{
|
||||
Led1_on();
|
||||
led1_timer = 10;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief This will enable the TRX_END LED for a period
|
||||
*/
|
||||
void tx_end_led(void)
|
||||
{
|
||||
Led2_on();
|
||||
led2_timer = 10;
|
||||
}
|
||||
/** @} */
|
||||
|
|
|
@ -52,22 +52,72 @@
|
|||
|
||||
|
||||
#include "config.h"
|
||||
#include "../conf_usb.h"
|
||||
|
||||
//_____ M A C R O S ________________________________________________________
|
||||
|
||||
#define USB_ETH_MTU UIP_BUFSIZE+4
|
||||
|
||||
|
||||
/*! Hook Documentation
|
||||
** USB_ETH_HOOK_RX_START()
|
||||
** USB_ETH_HOOK_RX_END()
|
||||
** USB_ETH_HOOK_RX_ERROR(string_reason)
|
||||
**
|
||||
** USB_ETH_HOOK_TX_START()
|
||||
** USB_ETH_HOOK_TX_END()
|
||||
** USB_ETH_HOOK_TX_ERROR(string_reason)
|
||||
**
|
||||
** USB_ETH_HOOK_INITIALIZED()
|
||||
** USB_ETH_HOOK_UNINITIALIZED()
|
||||
**
|
||||
** USB_ETH_HOOK_INIT()
|
||||
**
|
||||
** USB_ETH_HOOK_SET_PROMISCIOUS_MODE(bool)
|
||||
**
|
||||
** USB_ETH_HOOK_HANDLE_INBOUND_PACKET(buffer,len)
|
||||
** USB_ETH_HOOK_IS_READY_FOR_INBOUND_PACKET()
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef USB_ETH_HOOK_RX_START
|
||||
void rx_start_led(void);
|
||||
#define USB_ETH_HOOK_RX_START() rx_start_led()
|
||||
#endif
|
||||
|
||||
#ifndef USB_ETH_HOOK_TX_END
|
||||
void tx_end_led(void);
|
||||
#define USB_ETH_HOOK_TX_END() tx_end_led()
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifndef USB_ETH_HOOK_TX_ERROR
|
||||
#define USB_ETH_HOOK_TX_ERROR(string) do { } while(0)
|
||||
#endif
|
||||
|
||||
#ifndef USB_ETH_HOOK_RX_ERROR
|
||||
#define USB_ETH_HOOK_RX_ERROR(string) do { } while(0)
|
||||
#endif
|
||||
|
||||
//_____ D E C L A R A T I O N S ____________________________________________
|
||||
|
||||
|
||||
uint8_t usb_eth_send(uint8_t * senddata, uint16_t sendlen, uint8_t led);
|
||||
uint8_t usb_eth_set_active(uint8_t active);
|
||||
uint8_t usb_eth_ready_for_next_packet();
|
||||
|
||||
void sof_action(void);
|
||||
void rx_start_led(void);
|
||||
void tx_end_led(void);
|
||||
|
||||
extern char usb_busy;
|
||||
extern uint8_t usb_eth_is_active;
|
||||
|
||||
PROCESS_NAME(rndis_process);
|
||||
// TIP: Avoid using usb_ethernet_addr directly and use the get/set mac_address functions below.
|
||||
extern uint64_t usb_ethernet_addr;
|
||||
void usb_eth_get_mac_address(uint8_t dest[6]);
|
||||
void usb_eth_set_mac_address(const uint8_t src[6]);
|
||||
|
||||
PROCESS_NAME(usb_eth_process);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
|
|
@ -1,383 +0,0 @@
|
|||
/* This file has been prepared for Doxygen automatic documentation generation.*/
|
||||
/*! \file cdc_task.c **********************************************************
|
||||
*
|
||||
* \brief
|
||||
* Manages the CDC-ACM Virtual Serial Port Dataclass for the USB Device
|
||||
*
|
||||
* \addtogroup usbstick
|
||||
*
|
||||
* \author
|
||||
* Colin O'Flynn <coflynn@newae.com>
|
||||
*
|
||||
******************************************************************************/
|
||||
/* Copyright (c) 2008 ATMEL Corporation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of the copyright holders nor the names of
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
\ingroup usbstick
|
||||
\defgroup cdctask CDC Task
|
||||
@{
|
||||
*/
|
||||
|
||||
//_____ I N C L U D E S ___________________________________________________
|
||||
|
||||
|
||||
#include "contiki.h"
|
||||
#include "usb_drv.h"
|
||||
#include "usb_descriptors.h"
|
||||
#include "usb_specific_request.h"
|
||||
#include "serial/cdc_task.h"
|
||||
#include "serial/uart_usb_lib.h"
|
||||
#include "rndis/rndis_protocol.h"
|
||||
#include "sicslow_ethernet.h"
|
||||
#if RF230BB
|
||||
extern void rf230_set_channel(int channel);
|
||||
extern int rf230_get_channel(void);
|
||||
#else
|
||||
#include "radio.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/eeprom.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
#define BUF ((struct uip_eth_hdr *)&uip_buf[0])
|
||||
#define PRINTF printf
|
||||
#define PRINTF_P printf_P
|
||||
|
||||
//_____ M A C R O S ________________________________________________________
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//_____ D E F I N I T I O N S ______________________________________________
|
||||
|
||||
|
||||
#define IAD_TIMEOUT_DETACH 300
|
||||
#define IAD_TIMEOUT_ATTACH 600
|
||||
#define PBUF ((rndis_data_packet_t *) data_buffer)
|
||||
|
||||
//_____ D E C L A R A T I O N S ____________________________________________
|
||||
|
||||
|
||||
void menu_print(void);
|
||||
void menu_process(char c);
|
||||
|
||||
extern char usb_busy;
|
||||
|
||||
//! Counter for USB Serial port
|
||||
extern U8 tx_counter;
|
||||
|
||||
//! Timers for LEDs
|
||||
uint8_t led3_timer;
|
||||
|
||||
|
||||
//! Was USB device *just* enumerated?
|
||||
uint8_t justenumerated = 1;
|
||||
|
||||
|
||||
static uint8_t timer = 0;
|
||||
static struct etimer et;
|
||||
|
||||
|
||||
PROCESS(cdc_process, "CDC process");
|
||||
|
||||
/**
|
||||
* \brief Communication Data Class (CDC) Process
|
||||
*
|
||||
* This is the link between USB and the "good stuff". In this routine data
|
||||
* is received and processed by CDC-ACM Class
|
||||
*/
|
||||
PROCESS_THREAD(cdc_process, ev, data_proc)
|
||||
{
|
||||
|
||||
PROCESS_BEGIN();
|
||||
uart_usb_init();
|
||||
|
||||
while(1) {
|
||||
|
||||
|
||||
// turn off LED's if necessary
|
||||
if (led3_timer) led3_timer--;
|
||||
else Led3_off();
|
||||
|
||||
if(Is_device_enumerated() && (usb_mode == rndis_debug) && rndis_state && (!usb_busy)) {
|
||||
|
||||
if (justenumerated) {
|
||||
|
||||
//If we have serial port, set it as output
|
||||
if (usb_mode == rndis_debug) {
|
||||
uart_usb_set_stdout();
|
||||
menu_print();
|
||||
}
|
||||
justenumerated = 0;
|
||||
}
|
||||
|
||||
//Flush buffer if timeout
|
||||
if(timer >= 4 && tx_counter!=0 ){
|
||||
timer = 0;
|
||||
uart_usb_flush();
|
||||
} else {
|
||||
timer++;
|
||||
}
|
||||
|
||||
while (uart_usb_test_hit()){
|
||||
menu_process(uart_usb_getchar()); // See what they want
|
||||
}
|
||||
|
||||
|
||||
}//if (Is_device_enumerated())
|
||||
|
||||
|
||||
if (usb_mode == rndis_debug) {
|
||||
etimer_set(&et, CLOCK_SECOND/80);
|
||||
} else {
|
||||
etimer_set(&et, CLOCK_SECOND);
|
||||
}
|
||||
|
||||
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
|
||||
|
||||
} // while(1)
|
||||
|
||||
PROCESS_END();
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Print debug menu
|
||||
*/
|
||||
void menu_print(void)
|
||||
{
|
||||
PRINTF_P(PSTR("\n\n\r********** Jackdaw Menu ******************\n\r"));
|
||||
PRINTF_P(PSTR("* *\n\r"));
|
||||
PRINTF_P(PSTR("* Main Menu: *\n\r"));
|
||||
PRINTF_P(PSTR("* h,? Print this menu *\n\r"));
|
||||
PRINTF_P(PSTR("* m Print current mode *\n\r"));
|
||||
PRINTF_P(PSTR("* s Set to sniffer mode *\n\r"));
|
||||
PRINTF_P(PSTR("* n Set to network mode *\n\r"));
|
||||
PRINTF_P(PSTR("* c Set RF channel *\n\r"));
|
||||
PRINTF_P(PSTR("* 6 Toggle 6lowpan *\n\r"));
|
||||
PRINTF_P(PSTR("* r Toggle raw mode *\n\r"));
|
||||
PRINTF_P(PSTR("* u Switch to mass-storage*\n\r"));
|
||||
PRINTF_P(PSTR("* *\n\r"));
|
||||
PRINTF_P(PSTR("* Make selection at any time by pressing *\n\r"));
|
||||
PRINTF_P(PSTR("* your choice on keyboard. *\n\r"));
|
||||
PRINTF_P(PSTR("******************************************\n\r"));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Process incomming char on debug port
|
||||
*/
|
||||
void menu_process(char c)
|
||||
{
|
||||
|
||||
static enum menustate_enum /* Defines an enumeration type */
|
||||
{
|
||||
normal,
|
||||
channel
|
||||
} menustate = normal;
|
||||
|
||||
static char channel_string[3];
|
||||
static uint8_t channel_string_i = 0;
|
||||
|
||||
int tempchannel;
|
||||
|
||||
|
||||
if (menustate == channel) {
|
||||
|
||||
switch(c) {
|
||||
case '\r':
|
||||
case '\n':
|
||||
channel_string[channel_string_i] = 0;
|
||||
|
||||
//Will return zero in event of error...
|
||||
tempchannel = atoi(channel_string);
|
||||
|
||||
//Bounds check only if user had real input
|
||||
if ( ((channel_string_i) && (tempchannel < 11)) || (tempchannel > 26)) {
|
||||
PRINTF_P(PSTR("\n\rInvalid input\n\r"));
|
||||
}
|
||||
|
||||
//If valid input, change it
|
||||
if (tempchannel) {
|
||||
#if RF230BB
|
||||
rf230_set_channel(tempchannel);
|
||||
#else
|
||||
radio_set_operating_channel(tempchannel);
|
||||
#endif
|
||||
// eeprom_write_byte((uint8_t *) 9, tempchannel); //Write channel
|
||||
// eeprom_write_byte((uint8_t *)10, ~tempchannel); //Bit inverse as check
|
||||
}
|
||||
|
||||
menustate = normal;
|
||||
break;
|
||||
|
||||
case '\b':
|
||||
|
||||
if (channel_string_i)
|
||||
channel_string_i--;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
if (channel_string_i > 1) {
|
||||
menustate = normal;
|
||||
PRINTF_P(PSTR("\n\rInput too long!\n\r"));
|
||||
break;
|
||||
}
|
||||
|
||||
channel_string[channel_string_i] = c;
|
||||
channel_string_i++;
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
uint8_t i;
|
||||
switch(c) {
|
||||
case '\r':
|
||||
case '\n':
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
case '?':
|
||||
menu_print();
|
||||
break;
|
||||
|
||||
case 's':
|
||||
PRINTF_P(PSTR("Jackdaw now in sniffer mode\n\r"));
|
||||
usbstick_mode.sendToRf = 0;
|
||||
usbstick_mode.translate = 0;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
PRINTF_P(PSTR("Jackdaw now in network mode\n\r"));
|
||||
usbstick_mode.sendToRf = 1;
|
||||
usbstick_mode.translate = 1;
|
||||
break;
|
||||
|
||||
case '6':
|
||||
if (usbstick_mode.sicslowpan) {
|
||||
PRINTF_P(PSTR("Jackdaw does not perform 6lowpan translation\n\r"));
|
||||
usbstick_mode.sicslowpan = 0;
|
||||
} else {
|
||||
PRINTF_P(PSTR("Jackdaw now performs 6lowpan translations\n\r"));
|
||||
usbstick_mode.sicslowpan = 1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
if (usbstick_mode.raw) {
|
||||
PRINTF_P(PSTR("Jackdaw does not capture raw frames\n\r"));
|
||||
usbstick_mode.raw = 0;
|
||||
} else {
|
||||
PRINTF_P(PSTR("Jackdaw now captures raw frames\n\r"));
|
||||
usbstick_mode.raw = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
#if RF230BB
|
||||
PRINTF_P(PSTR("Select 802.15.4 Channel in range 11-26 [%d]: "), rf230_get_channel());
|
||||
#else
|
||||
PRINTF_P(PSTR("Select 802.15.4 Channel in range 11-26 [%d]: "), radio_get_operating_channel());
|
||||
#endif
|
||||
menustate = channel;
|
||||
channel_string_i = 0;
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case 'm':
|
||||
PRINTF_P(PSTR("Currently Jackdaw:\n\r * Will "));
|
||||
if (usbstick_mode.sendToRf == 0) { PRINTF_P(PSTR("not "));}
|
||||
PRINTF_P(PSTR("send data over RF\n\r * Will "));
|
||||
if (usbstick_mode.translate == 0) { PRINTF_P(PSTR("not "));}
|
||||
PRINTF_P(PSTR("change link-local addresses inside IP messages\n\r * Will "));
|
||||
if (usbstick_mode.sicslowpan == 0) { PRINTF_P(PSTR("not "));}
|
||||
PRINTF_P(PSTR("decompress 6lowpan headers\n\r * Will "));
|
||||
if (usbstick_mode.raw == 0) { PRINTF_P(PSTR("not "));}
|
||||
PRINTF_P(PSTR("Output raw 802.15.4 frames\n\r "));
|
||||
#if RF230BB
|
||||
PRINTF_P(PSTR(" * Operates on channel %d\n\r "), rf230_get_channel());
|
||||
#else
|
||||
PRINTF_P(PSTR(" * Operates on channel %d\n\r "), radio_get_operating_channel());
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
|
||||
//Mass storage mode
|
||||
usb_mode = mass_storage;
|
||||
|
||||
//No more serial port
|
||||
stdout = NULL;
|
||||
|
||||
//RNDIS is over
|
||||
rndis_state = rndis_uninitialized;
|
||||
Leds_off();
|
||||
|
||||
//Deatch USB
|
||||
Usb_detach();
|
||||
|
||||
//Wait a few seconds
|
||||
for(i = 0; i < 50; i++)
|
||||
_delay_ms(100);
|
||||
|
||||
//Attach USB
|
||||
Usb_attach();
|
||||
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
PRINTF_P(PSTR("%c is not a valid option! h for menu\n\r"), c);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief This will enable the VCP_TRX_END LED for a period
|
||||
*/
|
||||
void vcptx_end_led(void)
|
||||
{
|
||||
Led3_on();
|
||||
led3_timer = 10;
|
||||
}
|
||||
/** @} */
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
/* This file has been prepared for Doxygen automatic documentation generation.*/
|
||||
/*! \file cdc_task.h ************************************************************
|
||||
*
|
||||
* \brief
|
||||
* This file manages the CDC task for the virtual COM port.
|
||||
*
|
||||
* \addtogroup usbstick
|
||||
*
|
||||
* \author
|
||||
* Colin O'Flynn <coflynn@newae.com>
|
||||
*
|
||||
******************************************************************************/
|
||||
/* Copyright (c) 2008 ATMEL Corporation
|
||||
Copyright (c) 2008 Colin O'Flynn
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of the copyright holders nor the names of
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _CDC_TASK_H_
|
||||
#define _CDC_TASK_H_
|
||||
|
||||
/**
|
||||
\addtogroup cdctask
|
||||
@{
|
||||
*/
|
||||
|
||||
//_____ I N C L U D E S ____________________________________________________
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
//_____ M A C R O S ________________________________________________________
|
||||
|
||||
|
||||
|
||||
//_____ D E C L A R A T I O N S ____________________________________________
|
||||
|
||||
|
||||
void sof_action(void);
|
||||
void vcptx_end_led(void);
|
||||
|
||||
void rawmode_enable(void);
|
||||
void rawmode_disable(void);
|
||||
|
||||
PROCESS_NAME(cdc_process);
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* _CDC_TASK_H_ */
|
||||
|
|
@ -45,7 +45,6 @@
|
|||
#include "config.h"
|
||||
#include "usb_drv.h"
|
||||
#include "usb_descriptors.h"
|
||||
#include "serial/cdc_task.h"
|
||||
#include "serial/uart_usb_lib.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
@ -56,6 +55,26 @@
|
|||
|
||||
/*_____ M A C R O S ________________________________________________________*/
|
||||
|
||||
#ifndef USB_CDC_ACM_HOOK_TX_START
|
||||
#define USB_CDC_ACM_HOOK_TX_START(char)
|
||||
#endif
|
||||
|
||||
#ifndef USB_CDC_ACM_HOOK_TX_END
|
||||
#define USB_CDC_ACM_HOOK_TX_END(char)
|
||||
#endif
|
||||
|
||||
#ifndef USB_CDC_ACM_HOOK_CLS_CHANGED
|
||||
#define USB_CDC_ACM_HOOK_CLS_CHANGED(state)
|
||||
#endif
|
||||
|
||||
#ifndef USB_CDC_ACM_HOOK_CONFIGURED
|
||||
#define USB_CDC_ACM_HOOK_CONFIGURED()
|
||||
#endif
|
||||
|
||||
#ifndef USB_CDC_ACM_CONF_LOCAL_ECHO
|
||||
#define USB_CDC_ACM_CONF_LOCAL_ECHO 0
|
||||
#endif
|
||||
|
||||
/*_____ D E F I N I T I O N ________________________________________________*/
|
||||
|
||||
Uchar tx_counter;
|
||||
|
@ -64,22 +83,65 @@ S_line_coding line_coding;
|
|||
|
||||
/*_____ D E C L A R A T I O N ______________________________________________*/
|
||||
|
||||
void uart_usb_configure_endpoints() {
|
||||
usb_configure_endpoint(
|
||||
VCP_INT_EP,
|
||||
TYPE_INTERRUPT,
|
||||
DIRECTION_IN,
|
||||
SIZE_32,
|
||||
ONE_BANK,
|
||||
NYET_ENABLED
|
||||
);
|
||||
|
||||
usb_configure_endpoint(
|
||||
VCP_TX_EP,
|
||||
TYPE_BULK,
|
||||
DIRECTION_IN,
|
||||
SIZE_32,
|
||||
TWO_BANKS,
|
||||
NYET_ENABLED
|
||||
);
|
||||
|
||||
usb_configure_endpoint(
|
||||
VCP_RX_EP,
|
||||
TYPE_BULK,
|
||||
DIRECTION_OUT,
|
||||
SIZE_32,
|
||||
TWO_BANKS,
|
||||
NYET_ENABLED
|
||||
);
|
||||
|
||||
Usb_reset_endpoint(VCP_INT_EP);
|
||||
Usb_reset_endpoint(VCP_TX_EP);
|
||||
Usb_reset_endpoint(VCP_RX_EP);
|
||||
|
||||
USB_CDC_ACM_HOOK_CONFIGURED();
|
||||
}
|
||||
|
||||
|
||||
int usb_stdout_putchar(char c, FILE *stream)
|
||||
{
|
||||
// send to USB port
|
||||
// don't send anything if USB can't accept chars
|
||||
Usb_select_endpoint(TX_EP);
|
||||
if (!uart_usb_tx_ready())
|
||||
return 0;
|
||||
|
||||
// turn on LED
|
||||
vcptx_end_led();
|
||||
{
|
||||
// Preserve the currently selected endpoint
|
||||
uint8_t uenum = UENUM;
|
||||
|
||||
// send to USB port
|
||||
// don't send anything if USB can't accept chars
|
||||
Usb_select_endpoint(VCP_TX_EP);
|
||||
|
||||
if(usb_endpoint_wait_for_write_enabled()!=0)
|
||||
return 0;
|
||||
|
||||
if(c=='\n')
|
||||
uart_usb_putchar('\r');
|
||||
|
||||
if(c!='\r')
|
||||
uart_usb_putchar(c);
|
||||
|
||||
// Restore previously selected endpoint
|
||||
UENUM = uenum;
|
||||
|
||||
uart_usb_putchar(c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static FILE usb_stdout = FDEV_SETUP_STREAM(usb_stdout_putchar,
|
||||
NULL,
|
||||
|
@ -100,6 +162,20 @@ void uart_usb_set_stdout(void)
|
|||
}
|
||||
|
||||
|
||||
static uint8_t uart_usb_control_line_state = 0;
|
||||
|
||||
uint8_t uart_usb_get_control_line_state(void) {
|
||||
return uart_usb_control_line_state;
|
||||
}
|
||||
|
||||
|
||||
void uart_usb_set_control_line_state(uint8_t control_line_state)
|
||||
{
|
||||
uart_usb_control_line_state = control_line_state;
|
||||
USB_CDC_ACM_HOOK_CLS_CHANGED(control_line_state);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function checks if the USB emission buffer is ready to accept at
|
||||
* at least 1 byte
|
||||
|
@ -109,6 +185,7 @@ void uart_usb_set_stdout(void)
|
|||
*/
|
||||
bit uart_usb_tx_ready(void)
|
||||
{
|
||||
Usb_select_endpoint(VCP_TX_EP);
|
||||
if (!Is_usb_write_enabled())
|
||||
{
|
||||
return FALSE;
|
||||
|
@ -127,16 +204,31 @@ bit uart_usb_tx_ready(void)
|
|||
*/
|
||||
int uart_usb_putchar(int data_to_send)
|
||||
{
|
||||
Usb_select_endpoint(VCP_TX_EP);
|
||||
|
||||
if(!uart_usb_tx_ready()) return -1;
|
||||
|
||||
// Preserve the currently selected endpoint
|
||||
uint8_t uenum = UENUM;
|
||||
|
||||
USB_CDC_ACM_HOOK_TX_START(data_to_send);
|
||||
|
||||
Usb_select_endpoint(VCP_TX_EP);
|
||||
|
||||
if(!uart_usb_tx_ready()) {
|
||||
data_to_send=-1;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
Usb_write_byte(data_to_send);
|
||||
tx_counter++;
|
||||
if(!Is_usb_write_enabled()) //If Endpoint full -> flush
|
||||
{
|
||||
uart_usb_flush();
|
||||
}
|
||||
|
||||
//If Endpoint full -> flush
|
||||
if(!Is_usb_write_enabled())
|
||||
uart_usb_flush();
|
||||
|
||||
USB_CDC_ACM_HOOK_TX_END(data_to_send);
|
||||
|
||||
bail:
|
||||
// Restore previously selected endpoint
|
||||
UENUM = uenum;
|
||||
|
||||
return data_to_send;
|
||||
}
|
||||
|
||||
|
@ -149,6 +241,8 @@ bit uart_usb_test_hit(void)
|
|||
{
|
||||
if (!rx_counter)
|
||||
{
|
||||
// Preserve the currently selected endpoint
|
||||
uint8_t uenum = UENUM;
|
||||
Usb_select_endpoint(VCP_RX_EP);
|
||||
if (Is_usb_receive_out())
|
||||
{
|
||||
|
@ -158,6 +252,8 @@ bit uart_usb_test_hit(void)
|
|||
Usb_ack_receive_out();
|
||||
}
|
||||
}
|
||||
// Restore previously selected endpoint
|
||||
UENUM = uenum;
|
||||
}
|
||||
return (rx_counter!=0);
|
||||
}
|
||||
|
@ -174,15 +270,23 @@ char uart_usb_getchar(void)
|
|||
{
|
||||
register Uchar data_rx;
|
||||
|
||||
// Preserve the currently selected endpoint
|
||||
uint8_t uenum = UENUM;
|
||||
|
||||
Usb_select_endpoint(VCP_RX_EP);
|
||||
if (!rx_counter) while (!uart_usb_test_hit());
|
||||
data_rx=Usb_read_byte();
|
||||
rx_counter--;
|
||||
if (!rx_counter) Usb_ack_receive_out();
|
||||
|
||||
#if USB_CDC_ACM_CONF_LOCAL_ECHO
|
||||
//Local echo
|
||||
uart_usb_putchar(data_rx);
|
||||
#endif
|
||||
|
||||
// Restore previously selected endpoint
|
||||
UENUM = uenum;
|
||||
|
||||
return data_rx;
|
||||
}
|
||||
|
||||
|
@ -193,9 +297,16 @@ char uart_usb_getchar(void)
|
|||
*/
|
||||
void uart_usb_flush (void)
|
||||
{
|
||||
Usb_select_endpoint(VCP_TX_EP);
|
||||
Usb_send_in();
|
||||
// Preserve the currently selected endpoint
|
||||
uint8_t uenum = UENUM;
|
||||
|
||||
Usb_select_endpoint(VCP_TX_EP);
|
||||
Usb_send_in();
|
||||
tx_counter = 0;
|
||||
usb_endpoint_wait_for_write_enabled();
|
||||
|
||||
// Restore previously selected endpoint
|
||||
UENUM = uenum;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -78,6 +78,10 @@ void uart_usb_flush(void);
|
|||
bit uart_usb_test_hit(void);
|
||||
char uart_usb_getchar(void);
|
||||
void uart_usb_set_stdout(void);
|
||||
uint8_t uart_usb_get_control_line_state(void);
|
||||
void uart_usb_set_control_line_state(uint8_t control_line_state);
|
||||
|
||||
extern void uart_usb_configure_endpoints();
|
||||
|
||||
/** @} **/
|
||||
|
||||
|
|
|
@ -55,17 +55,252 @@
|
|||
#include "usb_drv.h"
|
||||
#include "usb_descriptors.h"
|
||||
#include "usb_specific_request.h"
|
||||
#include "rndis/rndis_task.h"
|
||||
|
||||
|
||||
//_____ M A C R O S ________________________________________________________
|
||||
|
||||
|
||||
#define USB_ETH_NET_FUNC_DESC(MACAddrString,etherStat,maxSegmentSize,nMCFilters,nPowerFilters) \
|
||||
{ sizeof(S_usb_ethernet_networking_functional_descriptor) \
|
||||
, 0x24, 0x0F \
|
||||
, MACAddrString \
|
||||
, etherStat \
|
||||
, Usb_write_word_enum_struc(maxSegmentSize) \
|
||||
, Usb_write_word_enum_struc(nMCFilters) \
|
||||
, nPowerFilters \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define USB_CONFIG_DESC(totalsize,interfaceCount,value,stringIndex,attr,power) \
|
||||
{ sizeof(S_usb_configuration_descriptor) \
|
||||
, CONFIGURATION_DESCRIPTOR \
|
||||
, Usb_write_word_enum_struc(totalsize) \
|
||||
, interfaceCount \
|
||||
, value \
|
||||
, stringIndex \
|
||||
, attr \
|
||||
, power \
|
||||
}
|
||||
|
||||
#define USB_ENDPOINT(nb,attr,maxpktsize,interval) \
|
||||
{ sizeof(S_usb_endpoint_descriptor) \
|
||||
, ENDPOINT_DESCRIPTOR \
|
||||
, nb \
|
||||
, attr \
|
||||
, Usb_write_word_enum_struc(maxpktsize) \
|
||||
, interval \
|
||||
}
|
||||
|
||||
#define USB_IAD(firstinterface,interfacecount,funcClass,funcSubClass,funcProto,stringIndex) \
|
||||
{ \
|
||||
sizeof(S_usb_interface_association_descriptor), \
|
||||
DSC_TYPE_IAD, \
|
||||
firstinterface, \
|
||||
interfacecount, \
|
||||
funcClass, \
|
||||
funcSubClass, \
|
||||
funcProto, \
|
||||
stringIndex \
|
||||
}
|
||||
|
||||
#define USB_INTERFACEDESC(nb,altsetting,endpointCount,interfaceClass,interfaceSubClass,interfaceProto,stringIndex) \
|
||||
{ sizeof(S_usb_interface_descriptor) \
|
||||
, INTERFACE_DESCRIPTOR \
|
||||
, nb \
|
||||
, altsetting \
|
||||
, endpointCount \
|
||||
, interfaceClass \
|
||||
, interfaceSubClass \
|
||||
, interfaceProto \
|
||||
, stringIndex \
|
||||
}
|
||||
|
||||
|
||||
#define FUNC_DESC_HEADER \
|
||||
0x05, /* bFunctionLength, Descriptor size in bytes*/ \
|
||||
0x24, /* bDescriptorType, CS_INTERFACE */ \
|
||||
0x00, /* bDescriptorSubtype, Header Functional Descriptor */ \
|
||||
0x10,0x01 /* bcdCDC, CDC specification release number in BCD format (1,1) */
|
||||
|
||||
#define FUNC_DESC_CALL_MANAGEMENT(caps,dataInterface) \
|
||||
0x05, /* bFunctionLength, Descriptor size in bytes */ \
|
||||
0x24, /* bDescriptorType, CS_INTERFACE */ \
|
||||
0x01, /* bDescriptorSubtype, Call Management Functional Descriptor */ \
|
||||
caps, /* bmCapabilities */ \
|
||||
dataInterface /* bDataInterface, Interface used for call management */
|
||||
|
||||
/* Abstract Control Management Functional Descriptor */
|
||||
#define FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT(caps) \
|
||||
0x04, /* bFunctionLength, Descriptor size in bytes */ \
|
||||
0x24, /* bDescriptorType, CS_INTERFACE */ \
|
||||
0x02, /* bDescriptorSubtype, Call Management Functional Descriptor */ \
|
||||
caps /* bmCapabilities */
|
||||
|
||||
/* Union Functional Descriptor */ \
|
||||
#define FUNC_DESC_UNION(masterInterface,slaveInterface) \
|
||||
0x05, /* bFunctionLength, Descriptor size in bytes */ \
|
||||
0x24, /* bDescriptorType, CS_INTERFACE */ \
|
||||
0x06, /* bDescriptorSubtype, Union Functional Descriptor */ \
|
||||
masterInterface, /* bMasterInterface, The controlling interface for the union (bInterfaceNumber of a Communication or Data Class interface in this configuration) */ \
|
||||
slaveInterface /* bSlaveInterface0, The controlled interace in the union (bInterfaceNumber of an interface in this configuration) */ \
|
||||
|
||||
|
||||
#define RNDIS_INTERFACES \
|
||||
USB_INTERFACEDESC( \
|
||||
INTERFACE0_NB, \
|
||||
ALTERNATE0, \
|
||||
NB_ENDPOINT0, \
|
||||
INTERFACE0_CLASS, \
|
||||
INTERFACE0_SUB_CLASS, \
|
||||
INTERFACE0_PROTOCOL, \
|
||||
USB_STRING_INTERFACE_RNDIS \
|
||||
), \
|
||||
{ \
|
||||
FUNC_DESC_HEADER, \
|
||||
FUNC_DESC_CALL_MANAGEMENT(0x00/*caps*/,0x00/*dataInterface*/), \
|
||||
FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT(0x00), \
|
||||
FUNC_DESC_UNION(0x00,0x01), \
|
||||
}, \
|
||||
USB_ENDPOINT(ENDPOINT_NB_1,EP_ATTRIBUTES_1,EP_SIZE_1,EP_INTERVAL_1), \
|
||||
\
|
||||
USB_INTERFACEDESC( \
|
||||
INTERFACE1_NB, \
|
||||
ALTERNATE1, \
|
||||
NB_ENDPOINT1, \
|
||||
INTERFACE1_CLASS, \
|
||||
INTERFACE1_SUB_CLASS, \
|
||||
INTERFACE1_PROTOCOL, \
|
||||
USB_STRING_NONE \
|
||||
), \
|
||||
USB_ENDPOINT(ENDPOINT_NB_2,EP_ATTRIBUTES_2,EP_SIZE_2,EP_INTERVAL_2), \
|
||||
USB_ENDPOINT(ENDPOINT_NB_3,EP_ATTRIBUTES_3,EP_SIZE_3,EP_INTERVAL_3)
|
||||
|
||||
|
||||
|
||||
#define CDC_SERIAL_INTERFACES \
|
||||
USB_INTERFACEDESC( \
|
||||
INTERFACE2_NB, \
|
||||
ALTERNATE2, \
|
||||
NB_ENDPOINT2, \
|
||||
INTERFACE2_CLASS, \
|
||||
INTERFACE2_SUB_CLASS, \
|
||||
INTERFACE2_PROTOCOL, \
|
||||
USB_STRING_INTERFACE_SERIAL \
|
||||
), \
|
||||
{ \
|
||||
FUNC_DESC_HEADER, \
|
||||
FUNC_DESC_CALL_MANAGEMENT(0x03/*caps*/,0x03/*dataInterface*/), \
|
||||
FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT(0x02), \
|
||||
FUNC_DESC_UNION(0x02,0x03), \
|
||||
}, \
|
||||
USB_ENDPOINT(ENDPOINT_NB_4,EP_ATTRIBUTES_4,EP_SIZE_4,EP_INTERVAL_4), \
|
||||
USB_INTERFACEDESC( \
|
||||
INTERFACE3_NB, \
|
||||
ALTERNATE3, \
|
||||
NB_ENDPOINT3, \
|
||||
INTERFACE3_CLASS, \
|
||||
INTERFACE3_SUB_CLASS, \
|
||||
INTERFACE3_PROTOCOL, \
|
||||
USB_STRING_NONE \
|
||||
), \
|
||||
USB_ENDPOINT(ENDPOINT_NB_5,EP_ATTRIBUTES_5,EP_SIZE_5,EP_INTERVAL_5), \
|
||||
USB_ENDPOINT(ENDPOINT_NB_6,EP_ATTRIBUTES_6,EP_SIZE_6,EP_INTERVAL_6)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define CDC_EEM_INTERFACES \
|
||||
USB_INTERFACEDESC( \
|
||||
EEM_INTERFACE0_NB, \
|
||||
EEM_ALTERNATE0, \
|
||||
EEM_NB_ENDPOINT0, \
|
||||
EEM_INTERFACE0_CLASS, \
|
||||
EEM_INTERFACE0_SUB_CLASS, \
|
||||
EEM_INTERFACE0_PROTOCOL, \
|
||||
USB_STRING_INTERFACE_EEM \
|
||||
), \
|
||||
USB_ENDPOINT(ENDPOINT_NB_1,EP_ATTRIBUTES_1,EP_SIZE_1,EP_INTERVAL_1), \
|
||||
USB_ENDPOINT(ENDPOINT_NB_2,EP_ATTRIBUTES_2,EP_SIZE_2,EP_INTERVAL_2)
|
||||
|
||||
|
||||
|
||||
|
||||
#if CDC_ECM_USES_INTERRUPT_ENDPOINT
|
||||
#define CDC_ECM_CONTROL_ENDPOINT_COUNT 1
|
||||
#define CDC_ECM_CONTROL_ENDPOINT USB_ENDPOINT(ENDPOINT_NB_1,EP_ATTRIBUTES_1,EP_SIZE_1,EP_INTERVAL_1),
|
||||
#else
|
||||
#define CDC_ECM_CONTROL_ENDPOINT_COUNT 0
|
||||
#define CDC_ECM_CONTROL_ENDPOINT
|
||||
#endif
|
||||
|
||||
|
||||
#define CDC_ECM_INTERFACES \
|
||||
USB_INTERFACEDESC( \
|
||||
ECM_INTERFACE0_NB, \
|
||||
ECM_ALTERNATE0, \
|
||||
CDC_ECM_CONTROL_ENDPOINT_COUNT, \
|
||||
ECM_INTERFACE0_CLASS, \
|
||||
ECM_INTERFACE0_SUB_CLASS, \
|
||||
ECM_INTERFACE0_PROTOCOL, \
|
||||
USB_STRING_INTERFACE_ECM \
|
||||
), \
|
||||
{ \
|
||||
FUNC_DESC_HEADER, \
|
||||
FUNC_DESC_UNION(0x00,0x01), \
|
||||
}, \
|
||||
USB_ETH_NET_FUNC_DESC( \
|
||||
USB_STRING_MAC_ADDRESS, \
|
||||
0, /* Support no stats for now */ \
|
||||
USB_ETH_MTU, /* maxSegmentSize */ \
|
||||
0, /* nMCFilters*/ \
|
||||
0 /*nPowerFilters*/ \
|
||||
), \
|
||||
CDC_ECM_CONTROL_ENDPOINT \
|
||||
USB_INTERFACEDESC( \
|
||||
ECM_INTERFACE0_NB+1, \
|
||||
0, \
|
||||
2, \
|
||||
10, \
|
||||
0, \
|
||||
0, \
|
||||
USB_STRING_NONE \
|
||||
), \
|
||||
USB_ENDPOINT(ENDPOINT_NB_2,EP_ATTRIBUTES_2,EP_SIZE_2,EP_INTERVAL_2), \
|
||||
USB_ENDPOINT(ENDPOINT_NB_3,EP_ATTRIBUTES_3,EP_SIZE_3,EP_INTERVAL_3)
|
||||
|
||||
/*
|
||||
USB_INTERFACEDESC( \
|
||||
ECM_INTERFACE0_NB+1, \
|
||||
0, \
|
||||
0, \
|
||||
10, \
|
||||
0, \
|
||||
0, \
|
||||
USB_STRING_NONE \
|
||||
), \
|
||||
*/
|
||||
|
||||
|
||||
|
||||
//_____ D E F I N I T I O N ________________________________________________
|
||||
|
||||
/************* COMPOSITE DEVICE DESCRIPTORS (using IAD) **********/
|
||||
|
||||
FLASH uint8_t usb_dev_config_order[] = {
|
||||
// USB_CONFIG_RNDIS_DEBUG, //Enable here for Windows COM port debugging? (USB_CONF_CDC=1)
|
||||
USB_CONFIG_RNDIS,
|
||||
USB_CONFIG_ECM_DEBUG,
|
||||
USB_CONFIG_RNDIS_DEBUG, //Enable here for macintosh CDC-ECM enumeration
|
||||
USB_CONFIG_ECM,
|
||||
USB_CONFIG_EEM,
|
||||
#if USB_CONF_STORAGE
|
||||
USB_CONFIG_MS,
|
||||
#endif
|
||||
};
|
||||
|
||||
// usb_user_device_descriptor
|
||||
FLASH S_usb_device_descriptor usb_dev_desc_composite =
|
||||
{
|
||||
|
@ -79,204 +314,46 @@ FLASH S_usb_device_descriptor usb_dev_desc_composite =
|
|||
, Usb_write_word_enum_struc(VENDOR_ID)
|
||||
, Usb_write_word_enum_struc(COMPOSITE_PRODUCT_ID)
|
||||
, Usb_write_word_enum_struc(RELEASE_NUMBER)
|
||||
, MAN_INDEX
|
||||
, PROD_INDEX
|
||||
, SN_INDEX
|
||||
, NB_CONFIGURATION
|
||||
, USB_STRING_MAN
|
||||
, USB_STRING_PRODUCT
|
||||
, USB_STRING_SERIAL
|
||||
, (sizeof(usb_dev_config_order)/sizeof(*usb_dev_config_order))
|
||||
};
|
||||
|
||||
|
||||
// usb_user_configuration_descriptor FS
|
||||
FLASH S_usb_user_configuration_descriptor_composite usb_conf_desc_composite = {
|
||||
{ sizeof(S_usb_configuration_descriptor)
|
||||
, CONFIGURATION_DESCRIPTOR
|
||||
, Usb_write_word_enum_struc(sizeof(S_usb_user_configuration_descriptor_composite))
|
||||
//, 0x0043 //TODO: Change to generic codewith sizeof
|
||||
, COMPOSITE_NB_INTERFACE
|
||||
, CONF_NB
|
||||
, CONF_INDEX
|
||||
, CONF_ATTRIBUTES
|
||||
, MAX_POWER
|
||||
},//9
|
||||
USB_CONFIG_DESC(
|
||||
sizeof(usb_conf_desc_composite),
|
||||
COMPOSITE_NB_INTERFACE,
|
||||
USB_CONFIG_RNDIS_DEBUG,
|
||||
USB_STRING_CONFIG_COMPOSITE,
|
||||
CONF_ATTRIBUTES,
|
||||
MAX_POWER
|
||||
),
|
||||
|
||||
// --------------------------- IAD ----------------------------
|
||||
{ // Interface Association Descriptor
|
||||
sizeof(S_usb_interface_association_descriptor), // bLength
|
||||
DSC_TYPE_IAD, // bDescriptorType = 11
|
||||
0x00, // bFirstInterface
|
||||
0x02, // bInterfaceCount
|
||||
0x02, // bFunctionClass (Communication Class)
|
||||
0x02, // bFunctionSubClass (Abstract Control Model)
|
||||
0xFF, // bFunctionProcotol (Vendor specific)
|
||||
0x00 // iInterface
|
||||
},//8
|
||||
|
||||
/// RNDIS DEVICE
|
||||
{ sizeof(S_usb_interface_descriptor)
|
||||
, INTERFACE_DESCRIPTOR
|
||||
, INTERFACE0_NB
|
||||
, ALTERNATE0
|
||||
, NB_ENDPOINT0
|
||||
, INTERFACE0_CLASS
|
||||
, INTERFACE0_SUB_CLASS
|
||||
, INTERFACE0_PROTOCOL
|
||||
, INTERFACE0_INDEX
|
||||
} //9
|
||||
,
|
||||
{
|
||||
// Header Functional Descriptor (marks beginning of the concatenated set of Functional Descriptors)
|
||||
0x05, // bFunctionLength, Descriptor size in bytes
|
||||
0x24, // bDescriptorType, CS_INTERFACE
|
||||
0x00, // bDescriptorSubtype, Header Functional Descriptor
|
||||
0x10,0x01, // bcdCDC, CDC specification release number in BCD format (1,1)
|
||||
|
||||
// Call Management Functional Descriptor
|
||||
0x05, // bFunctionLength, Descriptor size in bytes
|
||||
0x24, // bDescriptorType, CS_INTERFACE
|
||||
0x01, // bDescriptorSubtype, Call Management Functional Descriptor
|
||||
0x00, // bmCapabilities
|
||||
0x01, // bDataInterface, Interface used for call management
|
||||
|
||||
// Abstract Control Management Functional Descriptor
|
||||
0x04, // bDescriptorLength, Descriptor size in bytes
|
||||
0x24, // bDescriptorType, CS_INTERFACE
|
||||
0x02, // bDescriptorSubtype, Abstract Control Management Functional Descriptor
|
||||
0x00, // bmCapabilities
|
||||
|
||||
// Union Functional Descriptor
|
||||
0x05, // bFunctionLength, Descriptor size in bytes
|
||||
0x24, // bDescriptorType, CS_INTERFACE
|
||||
0x06, // bDescriptorSubtype, Union Functional Descriptor
|
||||
0x00, // bMasterInterface, The controlling interface for the union (bInterfaceNumber of a Communication or Data Class interface in this configuration)
|
||||
0x01, // bSlaveInterface0, The controlled interace in the union (bInterfaceNumber of an interface in this configuration)
|
||||
},
|
||||
{ sizeof(S_usb_endpoint_descriptor)
|
||||
, ENDPOINT_DESCRIPTOR
|
||||
, ENDPOINT_NB_1
|
||||
, EP_ATTRIBUTES_1
|
||||
, Usb_write_word_enum_struc(EP_SIZE_1)
|
||||
, EP_INTERVAL_1
|
||||
} //7
|
||||
,
|
||||
{ sizeof(S_usb_interface_descriptor)
|
||||
, INTERFACE_DESCRIPTOR
|
||||
, INTERFACE1_NB
|
||||
, ALTERNATE1
|
||||
, NB_ENDPOINT1
|
||||
, INTERFACE1_CLASS
|
||||
, INTERFACE1_SUB_CLASS
|
||||
, INTERFACE1_PROTOCOL
|
||||
, INTERFACE1_INDEX
|
||||
},
|
||||
{ sizeof(S_usb_endpoint_descriptor)
|
||||
, ENDPOINT_DESCRIPTOR
|
||||
, ENDPOINT_NB_2
|
||||
, EP_ATTRIBUTES_2
|
||||
, Usb_write_word_enum_struc(EP_SIZE_2)
|
||||
, EP_INTERVAL_2
|
||||
},
|
||||
{ sizeof(S_usb_endpoint_descriptor)
|
||||
, ENDPOINT_DESCRIPTOR
|
||||
, ENDPOINT_NB_3
|
||||
, EP_ATTRIBUTES_3
|
||||
, Usb_write_word_enum_struc(EP_SIZE_3)
|
||||
, EP_INTERVAL_3
|
||||
},
|
||||
|
||||
// --------------------------- IAD ----------------------------
|
||||
{ // Interface Association Descriptor
|
||||
sizeof(S_usb_interface_association_descriptor), // bLength
|
||||
DSC_TYPE_IAD, // bDescriptorType = 11
|
||||
0x02, // bFirstInterface
|
||||
0x02, // bInterfaceCount
|
||||
0x02, // bFunctionClass (Communication Class)
|
||||
0x02, // bFunctionSubClass (Abstract Control Model)
|
||||
0x01, // bFunctionProcotol (V.25ter, Common AT commands)
|
||||
0x00 // iInterface
|
||||
},//8
|
||||
|
||||
/// SERIAL PORT DEVICE
|
||||
|
||||
{ sizeof(S_usb_interface_descriptor)
|
||||
, INTERFACE_DESCRIPTOR
|
||||
, INTERFACE2_NB
|
||||
, ALTERNATE2
|
||||
, NB_ENDPOINT2
|
||||
, INTERFACE2_CLASS
|
||||
, INTERFACE2_SUB_CLASS
|
||||
, INTERFACE2_PROTOCOL
|
||||
, INTERFACE2_INDEX
|
||||
}//9
|
||||
,
|
||||
{
|
||||
// Header Functional Descriptor (marks beginning of the concatenated set of Functional Descriptors)
|
||||
0x05, // bFunctionLength, Descriptor size in bytes
|
||||
0x24, // bDescriptorType, CS_INTERFACE
|
||||
0x00, // bDescriptorSubtype, Header Functional Descriptor
|
||||
0x10,0x01, // bcdCDC, CDC specification release number in BCD format (1,1)
|
||||
|
||||
// Call Management Functional Descriptor
|
||||
0x05, // bFunctionLength, Descriptor size in bytes
|
||||
0x24, // bDescriptorType, CS_INTERFACE
|
||||
0x01, // bDescriptorSubtype, Call Management Functional Descriptor
|
||||
0x03, // bmCapabilities, can do calls on it's own
|
||||
0x03, // bDataInterface, Interface used for call management
|
||||
|
||||
// Abstract Control Management Functional Descriptor
|
||||
0x04, // bDescriptorLength, Descriptor size in bytes
|
||||
0x24, // bDescriptorType, CS_INTERFACE
|
||||
0x02, // bDescriptorSubtype, Abstract Control Management Functional Descriptor
|
||||
0x00, // bmCapabilities, support nothing!!! Deal with it
|
||||
|
||||
//Old was 0x06 indicating support for the GET/SET_LINE_CODING, BREAK & SET_CONTROL_LINE_STATE (2->6)
|
||||
|
||||
// Union Functional Descriptor
|
||||
0x05, // bFunctionLength, Descriptor size in bytes
|
||||
0x24, // bDescriptorType, CS_INTERFACE
|
||||
0x06, // bDescriptorSubtype, Union Functional Descriptor
|
||||
0x02, // bMasterInterface, The controlling interface for the union (bInterfaceNumber of a Communication or Data Class interface in this configuration)
|
||||
0x03, // bSlaveInterface0, The controlled interace in the union (bInterfaceNumber of an interface in this configuration)
|
||||
|
||||
},
|
||||
{ sizeof(S_usb_endpoint_descriptor)
|
||||
, ENDPOINT_DESCRIPTOR
|
||||
, ENDPOINT_NB_4
|
||||
, EP_ATTRIBUTES_4
|
||||
, Usb_write_word_enum_struc(EP_SIZE_4)
|
||||
, EP_INTERVAL_4
|
||||
} //7
|
||||
,
|
||||
{ sizeof(S_usb_interface_descriptor)
|
||||
, INTERFACE_DESCRIPTOR
|
||||
, INTERFACE3_NB
|
||||
, ALTERNATE3
|
||||
, NB_ENDPOINT3
|
||||
, INTERFACE3_CLASS
|
||||
, INTERFACE3_SUB_CLASS
|
||||
, INTERFACE3_PROTOCOL
|
||||
, INTERFACE3_INDEX
|
||||
}
|
||||
,
|
||||
{ sizeof(S_usb_endpoint_descriptor)
|
||||
, ENDPOINT_DESCRIPTOR
|
||||
, ENDPOINT_NB_5
|
||||
, EP_ATTRIBUTES_5
|
||||
, Usb_write_word_enum_struc(EP_SIZE_5)
|
||||
, EP_INTERVAL_5
|
||||
}
|
||||
,
|
||||
{ sizeof(S_usb_endpoint_descriptor)
|
||||
, ENDPOINT_DESCRIPTOR
|
||||
, ENDPOINT_NB_6
|
||||
, EP_ATTRIBUTES_6
|
||||
, Usb_write_word_enum_struc(EP_SIZE_6)
|
||||
, EP_INTERVAL_6
|
||||
}
|
||||
USB_IAD(
|
||||
0x00, // First interface
|
||||
0x02, // Interface count
|
||||
0x02, // Function Class
|
||||
0x02, // Function Subclass
|
||||
0xFF, // Function Protocol
|
||||
USB_STRING_INTERFACE_RNDIS
|
||||
),RNDIS_INTERFACES,
|
||||
|
||||
USB_IAD(
|
||||
0x02, // First interface
|
||||
0x02, // Interface count
|
||||
0x02, // Function Class
|
||||
0x02, // Function Subclass
|
||||
0x01, // Function Protocol
|
||||
USB_STRING_INTERFACE_SERIAL
|
||||
),CDC_SERIAL_INTERFACES
|
||||
};
|
||||
|
||||
/****************** NETWORK-ONLY DEVICE DESCRIPTORS **************************/
|
||||
|
||||
/*
|
||||
FLASH S_usb_device_descriptor usb_dev_desc_network =
|
||||
{
|
||||
sizeof(usb_dev_desc_network)
|
||||
|
@ -289,101 +366,115 @@ FLASH S_usb_device_descriptor usb_dev_desc_network =
|
|||
, Usb_write_word_enum_struc(VENDOR_ID)
|
||||
, Usb_write_word_enum_struc(NETWORK_PRODUCT_ID)
|
||||
, Usb_write_word_enum_struc(RELEASE_NUMBER)
|
||||
, MAN_INDEX
|
||||
, PROD_INDEX
|
||||
, SN_INDEX
|
||||
, USB_STRING_MAN
|
||||
, USB_STRING_PRODUCT
|
||||
, USB_STRING_SERIAL
|
||||
, NB_CONFIGURATION
|
||||
};
|
||||
*/
|
||||
|
||||
// usb_user_configuration_descriptor FS
|
||||
FLASH S_usb_user_configuration_descriptor_network usb_conf_desc_network = {
|
||||
{ sizeof(S_usb_configuration_descriptor)
|
||||
, CONFIGURATION_DESCRIPTOR
|
||||
, Usb_write_word_enum_struc(sizeof(S_usb_user_configuration_descriptor_network))
|
||||
//, 0x0043 //TODO: Change to generic codewith sizeof
|
||||
, NETWORK_NB_INTERFACE
|
||||
, CONF_NB
|
||||
, CONF_INDEX
|
||||
, CONF_ATTRIBUTES
|
||||
, MAX_POWER
|
||||
},//9
|
||||
|
||||
/// RNDIS DEVICE
|
||||
{ sizeof(S_usb_interface_descriptor)
|
||||
, INTERFACE_DESCRIPTOR
|
||||
, INTERFACE0_NB
|
||||
, ALTERNATE0
|
||||
, NB_ENDPOINT0
|
||||
, INTERFACE0_CLASS
|
||||
, INTERFACE0_SUB_CLASS
|
||||
, INTERFACE0_PROTOCOL
|
||||
, INTERFACE0_INDEX
|
||||
} //9
|
||||
,
|
||||
{
|
||||
// Header Functional Descriptor (marks beginning of the concatenated set of Functional Descriptors)
|
||||
0x05, // bFunctionLength, Descriptor size in bytes
|
||||
0x24, // bDescriptorType, CS_INTERFACE
|
||||
0x00, // bDescriptorSubtype, Header Functional Descriptor
|
||||
0x10,0x01, // bcdCDC, CDC specification release number in BCD format (1,1)
|
||||
|
||||
// Call Management Functional Descriptor
|
||||
0x05, // bFunctionLength, Descriptor size in bytes
|
||||
0x24, // bDescriptorType, CS_INTERFACE
|
||||
0x01, // bDescriptorSubtype, Call Management Functional Descriptor
|
||||
0x00, // bmCapabilities
|
||||
0x01, // bDataInterface, Interface used for call management
|
||||
|
||||
// Abstract Control Management Functional Descriptor
|
||||
0x04, // bDescriptorLength, Descriptor size in bytes
|
||||
0x24, // bDescriptorType, CS_INTERFACE
|
||||
0x02, // bDescriptorSubtype, Abstract Control Management Functional Descriptor
|
||||
0x00, // bmCapabilities
|
||||
|
||||
// Union Functional Descriptor
|
||||
0x05, // bFunctionLength, Descriptor size in bytes
|
||||
0x24, // bDescriptorType, CS_INTERFACE
|
||||
0x06, // bDescriptorSubtype, Union Functional Descriptor
|
||||
0x00, // bMasterInterface, The controlling interface for the union (bInterfaceNumber of a Communication or Data Class interface in this configuration)
|
||||
0x01, // bSlaveInterface0, The controlled interace in the union (bInterfaceNumber of an interface in this configuration)
|
||||
},
|
||||
{ sizeof(S_usb_endpoint_descriptor)
|
||||
, ENDPOINT_DESCRIPTOR
|
||||
, ENDPOINT_NB_1
|
||||
, EP_ATTRIBUTES_1
|
||||
, Usb_write_word_enum_struc(EP_SIZE_1)
|
||||
, EP_INTERVAL_1
|
||||
} //7
|
||||
,
|
||||
{ sizeof(S_usb_interface_descriptor)
|
||||
, INTERFACE_DESCRIPTOR
|
||||
, INTERFACE1_NB
|
||||
, ALTERNATE1
|
||||
, NB_ENDPOINT1
|
||||
, INTERFACE1_CLASS
|
||||
, INTERFACE1_SUB_CLASS
|
||||
, INTERFACE1_PROTOCOL
|
||||
, INTERFACE1_INDEX
|
||||
},
|
||||
{ sizeof(S_usb_endpoint_descriptor)
|
||||
, ENDPOINT_DESCRIPTOR
|
||||
, ENDPOINT_NB_2
|
||||
, EP_ATTRIBUTES_2
|
||||
, Usb_write_word_enum_struc(EP_SIZE_2)
|
||||
, EP_INTERVAL_2
|
||||
},
|
||||
{ sizeof(S_usb_endpoint_descriptor)
|
||||
, ENDPOINT_DESCRIPTOR
|
||||
, ENDPOINT_NB_3
|
||||
, EP_ATTRIBUTES_3
|
||||
, Usb_write_word_enum_struc(EP_SIZE_3)
|
||||
, EP_INTERVAL_3
|
||||
}
|
||||
USB_CONFIG_DESC(
|
||||
sizeof(usb_conf_desc_network),
|
||||
NETWORK_NB_INTERFACE,
|
||||
CONF_NB, // value
|
||||
USB_STRING_CONFIG_RNDIS,
|
||||
CONF_ATTRIBUTES,
|
||||
MAX_POWER
|
||||
),
|
||||
RNDIS_INTERFACES
|
||||
};
|
||||
|
||||
|
||||
|
||||
/************* EEM-ONLY ***************/
|
||||
|
||||
// usb_user_device_descriptor
|
||||
/*
|
||||
FLASH S_usb_device_descriptor usb_dev_desc_eem =
|
||||
{
|
||||
sizeof(usb_dev_desc_composite)
|
||||
, DEVICE_DESCRIPTOR
|
||||
, Usb_write_word_enum_struc(USB_SPECIFICATION)
|
||||
, EEM_DEVICE_CLASS
|
||||
, EEM_DEVICE_SUB_CLASS
|
||||
, EEM_DEVICE_PROTOCOL
|
||||
, EP_CONTROL_LENGTH
|
||||
, Usb_write_word_enum_struc(VENDOR_ID)
|
||||
, Usb_write_word_enum_struc(COMPOSITE_PRODUCT_ID)
|
||||
, Usb_write_word_enum_struc(RELEASE_NUMBER)
|
||||
, USB_STRING_MAN
|
||||
, USB_STRING_PRODUCT
|
||||
, USB_STRING_SERIAL
|
||||
, NB_CONFIGURATION
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
// usb_user_configuration_descriptor FS
|
||||
FLASH S_usb_user_configuration_descriptor_eem usb_conf_desc_eem = {
|
||||
USB_CONFIG_DESC(
|
||||
sizeof(usb_conf_desc_eem),
|
||||
EEM_NB_INTERFACE,
|
||||
USB_CONFIG_EEM, // value
|
||||
USB_STRING_CONFIG_EEM,
|
||||
CONF_ATTRIBUTES,
|
||||
MAX_POWER
|
||||
),
|
||||
CDC_EEM_INTERFACES
|
||||
};
|
||||
|
||||
|
||||
FLASH S_usb_user_configuration_descriptor_ecm usb_conf_desc_ecm = {
|
||||
USB_CONFIG_DESC(
|
||||
sizeof(usb_conf_desc_ecm),
|
||||
2, // Interface Count
|
||||
USB_CONFIG_ECM, // value
|
||||
USB_STRING_CONFIG_ECM,
|
||||
CONF_ATTRIBUTES,
|
||||
MAX_POWER
|
||||
),
|
||||
CDC_ECM_INTERFACES
|
||||
};
|
||||
|
||||
FLASH S_usb_user_configuration_descriptor_ecm_debug usb_conf_desc_ecm_debug = {
|
||||
USB_CONFIG_DESC(
|
||||
sizeof(usb_conf_desc_ecm_debug),
|
||||
4, // Interface Count
|
||||
USB_CONFIG_ECM_DEBUG, // value
|
||||
USB_STRING_CONFIG_ECM_DEBUG,
|
||||
CONF_ATTRIBUTES,
|
||||
MAX_POWER
|
||||
),
|
||||
|
||||
USB_IAD(
|
||||
0x00, // First interface
|
||||
0x02, // Interface count
|
||||
0x02, // Function Class
|
||||
0x06, // Function Subclass
|
||||
0x00, // Function Protocol
|
||||
USB_STRING_INTERFACE_ECM
|
||||
),CDC_ECM_INTERFACES,
|
||||
|
||||
USB_IAD(
|
||||
0x02, // First interface
|
||||
0x02, // Interface count
|
||||
0x02, // Function Class
|
||||
0x02, // Function Subclass
|
||||
0x01, // Function Protocol
|
||||
USB_STRING_INTERFACE_SERIAL
|
||||
),CDC_SERIAL_INTERFACES
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/****************** MASS-STORAGE DEVICE DESCRIPTORS **************************/
|
||||
|
||||
/*
|
||||
FLASH S_usb_device_descriptor usb_dev_desc_mass =
|
||||
{
|
||||
sizeof(usb_dev_desc_mass)
|
||||
|
@ -396,11 +487,13 @@ FLASH S_usb_device_descriptor usb_dev_desc_mass =
|
|||
, Usb_write_word_enum_struc(VENDOR_ID)
|
||||
, Usb_write_word_enum_struc(MASS_PRODUCT_ID)
|
||||
, Usb_write_word_enum_struc(RELEASE_NUMBER)
|
||||
, MAN_INDEX
|
||||
, PROD_INDEX
|
||||
, SN_INDEX
|
||||
, USB_STRING_MAN
|
||||
, USB_STRING_PRODUCT
|
||||
, USB_STRING_SERIAL
|
||||
, NB_CONFIGURATION
|
||||
};
|
||||
*/
|
||||
#if USB_CONF_STORAGE
|
||||
|
||||
// usb_user_configuration_descriptor FS
|
||||
FLASH S_usb_user_configuration_descriptor_mass usb_conf_desc_mass = {
|
||||
|
@ -409,7 +502,7 @@ FLASH S_usb_user_configuration_descriptor_mass usb_conf_desc_mass = {
|
|||
, Usb_write_word_enum_struc(sizeof(S_usb_user_configuration_descriptor_mass))
|
||||
, MASS_NB_INTERFACE
|
||||
, CONF_NB
|
||||
, CONF_INDEX
|
||||
, USB_STRING_CONFIG_MS
|
||||
, CONF_ATTRIBUTES
|
||||
, MAX_POWER
|
||||
},//9
|
||||
|
@ -423,7 +516,7 @@ FLASH S_usb_user_configuration_descriptor_mass usb_conf_desc_mass = {
|
|||
, MS_INTERFACE_CLASS
|
||||
, MS_INTERFACE_SUB_CLASS
|
||||
, MS_INTERFACE_PROTOCOL
|
||||
, MS_INTERFACE_INDEX
|
||||
, USB_STRING_INTERFACE_MS
|
||||
} //9
|
||||
,
|
||||
{ sizeof(S_usb_endpoint_descriptor)
|
||||
|
@ -443,96 +536,11 @@ FLASH S_usb_user_configuration_descriptor_mass usb_conf_desc_mass = {
|
|||
}
|
||||
};
|
||||
|
||||
/************* EEM-ONLY ***************/
|
||||
|
||||
// usb_user_device_descriptor
|
||||
FLASH S_usb_device_descriptor usb_dev_desc_eem =
|
||||
{
|
||||
sizeof(usb_dev_desc_composite)
|
||||
, DEVICE_DESCRIPTOR
|
||||
, Usb_write_word_enum_struc(USB_SPECIFICATION)
|
||||
, EEM_DEVICE_CLASS
|
||||
, EEM_DEVICE_SUB_CLASS
|
||||
, EEM_DEVICE_PROTOCOL
|
||||
, EP_CONTROL_LENGTH
|
||||
, Usb_write_word_enum_struc(VENDOR_ID)
|
||||
, Usb_write_word_enum_struc(COMPOSITE_PRODUCT_ID)
|
||||
, Usb_write_word_enum_struc(RELEASE_NUMBER)
|
||||
, MAN_INDEX
|
||||
, PROD_INDEX
|
||||
, SN_INDEX
|
||||
, NB_CONFIGURATION
|
||||
};
|
||||
|
||||
|
||||
// usb_user_configuration_descriptor FS
|
||||
FLASH S_usb_user_configuration_descriptor_eem usb_conf_desc_eem = {
|
||||
{ sizeof(S_usb_configuration_descriptor)
|
||||
, CONFIGURATION_DESCRIPTOR
|
||||
, Usb_write_word_enum_struc(sizeof(S_usb_user_configuration_descriptor_eem))
|
||||
, EEM_NB_INTERFACE
|
||||
, CONF_NB
|
||||
, CONF_INDEX
|
||||
, CONF_ATTRIBUTES
|
||||
, MAX_POWER
|
||||
},//9
|
||||
/// EEM DEVICE
|
||||
{ sizeof(S_usb_interface_descriptor)
|
||||
, INTERFACE_DESCRIPTOR
|
||||
, EEM_INTERFACE0_NB
|
||||
, EEM_ALTERNATE0
|
||||
, EEM_NB_ENDPOINT0
|
||||
, EEM_INTERFACE0_CLASS
|
||||
, EEM_INTERFACE0_SUB_CLASS
|
||||
, EEM_INTERFACE0_PROTOCOL
|
||||
, EEM_INTERFACE0_INDEX
|
||||
} //9
|
||||
,
|
||||
{ sizeof(S_usb_endpoint_descriptor)
|
||||
, ENDPOINT_DESCRIPTOR
|
||||
, EEM_ENDPOINT_NB_1
|
||||
, EEM_EP_ATTRIBUTES_1
|
||||
, Usb_write_word_enum_struc(EEM_EP_SIZE_1)
|
||||
, EEM_EP_INTERVAL_1
|
||||
} //7
|
||||
,
|
||||
{ sizeof(S_usb_endpoint_descriptor)
|
||||
, ENDPOINT_DESCRIPTOR
|
||||
, EEM_ENDPOINT_NB_2
|
||||
, EEM_EP_ATTRIBUTES_2
|
||||
, Usb_write_word_enum_struc(EEM_EP_SIZE_2)
|
||||
, EEM_EP_INTERVAL_2
|
||||
} //7
|
||||
};
|
||||
#endif
|
||||
|
||||
/************* COMMON *****************/
|
||||
|
||||
|
||||
// usb_user_manufacturer_string_descriptor
|
||||
FLASH S_usb_manufacturer_string_descriptor usb_user_manufacturer_string_descriptor = {
|
||||
sizeof(usb_user_manufacturer_string_descriptor)
|
||||
, STRING_DESCRIPTOR
|
||||
, USB_MANUFACTURER_NAME
|
||||
};
|
||||
|
||||
|
||||
// usb_user_product_string_descriptor
|
||||
|
||||
FLASH S_usb_product_string_descriptor usb_user_product_string_descriptor = {
|
||||
sizeof(usb_user_product_string_descriptor)
|
||||
, STRING_DESCRIPTOR
|
||||
, USB_PRODUCT_NAME
|
||||
};
|
||||
|
||||
|
||||
// usb_user_serial_number
|
||||
|
||||
FLASH S_usb_serial_number usb_user_serial_number = {
|
||||
sizeof(usb_user_serial_number)
|
||||
, STRING_DESCRIPTOR
|
||||
, USB_SERIAL_NUMBER
|
||||
};
|
||||
|
||||
|
||||
// usb_user_language_id
|
||||
|
||||
|
@ -548,6 +556,8 @@ FLASH S_usb_language_id usb_user_language_id = {
|
|||
|
||||
PGM_VOID_P Usb_get_dev_desc_pointer(void)
|
||||
{
|
||||
return &(usb_dev_desc_composite.bLength);
|
||||
/*
|
||||
if (usb_mode == rndis_only)
|
||||
return &(usb_dev_desc_network.bLength);
|
||||
|
||||
|
@ -558,11 +568,14 @@ PGM_VOID_P Usb_get_dev_desc_pointer(void)
|
|||
return &(usb_dev_desc_eem.bLength);
|
||||
|
||||
return &(usb_dev_desc_mass.bLength);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
U8 Usb_get_dev_desc_length(void)
|
||||
{
|
||||
return sizeof(usb_dev_desc_composite);
|
||||
/*
|
||||
|
||||
if (usb_mode == rndis_only)
|
||||
return sizeof(usb_dev_desc_network);
|
||||
|
@ -574,37 +587,54 @@ U8 Usb_get_dev_desc_length(void)
|
|||
return sizeof(usb_dev_desc_eem);
|
||||
|
||||
return sizeof(usb_dev_desc_mass);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
PGM_VOID_P Usb_get_conf_desc_pointer(void)
|
||||
PGM_VOID_P Usb_get_conf_desc_pointer(U8 index)
|
||||
{
|
||||
if (usb_mode == rndis_only)
|
||||
return &(usb_conf_desc_network.cfg.bLength);
|
||||
|
||||
if (usb_mode == rndis_debug)
|
||||
return &(usb_conf_desc_composite.cfg.bLength);
|
||||
|
||||
if (usb_mode == eem)
|
||||
return &(usb_conf_desc_eem.cfg.bLength);
|
||||
|
||||
return &(usb_conf_desc_mass.cfg.bLength);
|
||||
|
||||
switch(pgm_read_byte_near(&usb_dev_config_order[index])) {
|
||||
case USB_CONFIG_ECM:
|
||||
return &(usb_conf_desc_ecm.cfg.bLength);
|
||||
case USB_CONFIG_ECM_DEBUG:
|
||||
return &(usb_conf_desc_ecm_debug.cfg.bLength);
|
||||
case USB_CONFIG_RNDIS_DEBUG:
|
||||
return &(usb_conf_desc_composite.cfg.bLength);
|
||||
case USB_CONFIG_RNDIS:
|
||||
return &(usb_conf_desc_network.cfg.bLength);
|
||||
case USB_CONFIG_EEM:
|
||||
return &(usb_conf_desc_eem.cfg.bLength);
|
||||
#if USB_CONF_STORAGE
|
||||
case USB_CONFIG_MS:
|
||||
return &(usb_conf_desc_mass.cfg.bLength);
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
U8 Usb_get_conf_desc_length(void)
|
||||
U8 Usb_get_conf_desc_length(U8 index)
|
||||
{
|
||||
|
||||
if (usb_mode == rndis_only)
|
||||
return sizeof (usb_conf_desc_network);
|
||||
|
||||
if (usb_mode == rndis_debug)
|
||||
return sizeof(usb_conf_desc_composite);
|
||||
|
||||
if (usb_mode == eem)
|
||||
return sizeof(usb_conf_desc_eem);
|
||||
|
||||
return sizeof(usb_conf_desc_mass);
|
||||
switch(pgm_read_byte_near(&usb_dev_config_order[index])) {
|
||||
case USB_CONFIG_ECM:
|
||||
return sizeof(usb_conf_desc_ecm);
|
||||
case USB_CONFIG_ECM_DEBUG:
|
||||
return sizeof(usb_conf_desc_ecm_debug);
|
||||
case USB_CONFIG_RNDIS_DEBUG:
|
||||
return sizeof(usb_conf_desc_composite);
|
||||
case USB_CONFIG_RNDIS:
|
||||
return sizeof (usb_conf_desc_network);
|
||||
case USB_CONFIG_EEM:
|
||||
return sizeof(usb_conf_desc_eem);
|
||||
#if USB_CONF_STORAGE
|
||||
case USB_CONFIG_MS:
|
||||
return sizeof(usb_conf_desc_mass);
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -66,9 +66,9 @@
|
|||
// USB Device descriptor
|
||||
#define USB_SPECIFICATION 0x0200
|
||||
|
||||
#define COMPOSITE_DEVICE_CLASS 0xEF // Misc
|
||||
#define COMPOSITE_DEVICE_SUB_CLASS 0x02 // Common
|
||||
#define COMPOSITE_DEVICE_PROTOCOL 0x01 // IAD
|
||||
#define COMPOSITE_DEVICE_CLASS 0x02 // Misc
|
||||
#define COMPOSITE_DEVICE_SUB_CLASS 0x00 // Common
|
||||
#define COMPOSITE_DEVICE_PROTOCOL 0x00 // IAD
|
||||
|
||||
#define NETWORK_DEVICE_CLASS 0x02 // CDC ACM
|
||||
#define NETWORK_DEVICE_SUB_CLASS 0x02 //
|
||||
|
@ -88,10 +88,49 @@
|
|||
#define NETWORK_PRODUCT_ID 0x2019 //Product ID for just RNDIS device
|
||||
#define MASS_PRODUCT_ID 0x202F //Product ID for mass storage
|
||||
#define RELEASE_NUMBER 0x1000
|
||||
#define MAN_INDEX 0x01
|
||||
#define PROD_INDEX 0x02
|
||||
#define SN_INDEX 0x03
|
||||
#define NB_CONFIGURATION 1
|
||||
|
||||
enum {
|
||||
USB_STRING_NONE = 0,
|
||||
USB_STRING_MAN = 1,
|
||||
USB_STRING_PRODUCT,
|
||||
USB_STRING_SERIAL,
|
||||
USB_STRING_MAC_ADDRESS,
|
||||
USB_STRING_CONFIG_COMPOSITE,
|
||||
USB_STRING_CONFIG_RNDIS,
|
||||
USB_STRING_CONFIG_EEM,
|
||||
USB_STRING_CONFIG_ECM,
|
||||
USB_STRING_CONFIG_ECM_DEBUG,
|
||||
USB_STRING_CONFIG_MS,
|
||||
USB_STRING_INTERFACE_RNDIS,
|
||||
USB_STRING_INTERFACE_EEM,
|
||||
USB_STRING_INTERFACE_ECM,
|
||||
USB_STRING_INTERFACE_ECM_ATTACHED,
|
||||
USB_STRING_INTERFACE_ECM_DETACHED,
|
||||
USB_STRING_INTERFACE_SERIAL,
|
||||
USB_STRING_INTERFACE_MS,
|
||||
|
||||
};
|
||||
|
||||
enum {
|
||||
USB_CONFIG_UNCONFIGURED = 0,
|
||||
|
||||
USB_CONFIG_RNDIS = 1,
|
||||
USB_CONFIG_RNDIS_DEBUG = 1+(1<<7),
|
||||
|
||||
USB_CONFIG_ECM = 2,
|
||||
USB_CONFIG_ECM_DEBUG = 2+(1<<7),
|
||||
|
||||
USB_CONFIG_EEM = 3,
|
||||
|
||||
#if USB_CONF_STORAGE
|
||||
USB_CONFIG_MS = 4,
|
||||
#endif
|
||||
};
|
||||
|
||||
#define USB_CONFIG_HAS_DEBUG_PORT(x) ((x==USB_CONFIG_ECM_DEBUG)||(x==USB_CONFIG_RNDIS_DEBUG))
|
||||
|
||||
//#define USB_CONFIG_COUNT (USB_CONFIG_COUNT_PLUS_ONE-1)
|
||||
//#define NB_CONFIGURATION USB_CONFIG_COUNT
|
||||
|
||||
#define NETWORK_NB_INTERFACE 2
|
||||
#define COMPOSITE_NB_INTERFACE 4
|
||||
|
@ -134,14 +173,14 @@
|
|||
#define ENDPOINT_NB_2 0x80 | TX_EP
|
||||
#define EP_ATTRIBUTES_2 0x02 // BULK = 0x02, INTERUPT = 0x03
|
||||
#define EP_SIZE_2 0x40 //64 byte max size
|
||||
#define EP_INTERVAL_2 0x00
|
||||
#define EP_INTERVAL_2 0x01
|
||||
|
||||
// USB Endpoint 2 descriptor
|
||||
//Bulk OUT RX endpoint
|
||||
#define ENDPOINT_NB_3 RX_EP
|
||||
#define EP_ATTRIBUTES_3 0x02 // BULK = 0x02, INTERUPT = 0x03
|
||||
#define EP_SIZE_3 0x40 //64 byte max size
|
||||
#define EP_INTERVAL_3 0x00
|
||||
#define EP_INTERVAL_3 0x01
|
||||
|
||||
/*** CDC Virtual Serial Port ***/
|
||||
|
||||
|
@ -176,14 +215,14 @@
|
|||
#define ENDPOINT_NB_5 0x80 | VCP_TX_EP
|
||||
#define EP_ATTRIBUTES_5 0x02 // BULK = 0x02, INTERUPT = 0x03
|
||||
#define EP_SIZE_5 0x20
|
||||
#define EP_INTERVAL_5 0x00
|
||||
#define EP_INTERVAL_5 0x01
|
||||
|
||||
// USB Endpoint 6 descriptor
|
||||
// Bulk OUT
|
||||
#define ENDPOINT_NB_6 VCP_RX_EP
|
||||
#define EP_ATTRIBUTES_6 0x02 // BULK = 0x02, INTERUPT = 0x03
|
||||
#define EP_SIZE_6 0x20
|
||||
#define EP_INTERVAL_6 0x00
|
||||
#define EP_INTERVAL_6 0x01
|
||||
|
||||
|
||||
/*** Mass Storage ***/
|
||||
|
@ -227,61 +266,34 @@
|
|||
#define EEM_ENDPOINT_NB_1 0x80 | TX_EP
|
||||
#define EEM_EP_ATTRIBUTES_1 0x02 // BULK = 0x02, INTERUPT = 0x03
|
||||
#define EEM_EP_SIZE_1 0x40 //64 byte max size
|
||||
#define EEM_EP_INTERVAL_1 0x00
|
||||
#define EEM_EP_INTERVAL_1 0x01
|
||||
|
||||
// USB Endpoint 2 descriptor
|
||||
// Bulk OUT
|
||||
#define EEM_ENDPOINT_NB_2 RX_EP
|
||||
#define EEM_EP_ATTRIBUTES_2 0x02 // BULK = 0x02, INTERUPT = 0x03
|
||||
#define EEM_EP_SIZE_2 0x40 //64 byte max size
|
||||
#define EEM_EP_INTERVAL_2 0x00
|
||||
#define EEM_EP_INTERVAL_2 0x01
|
||||
|
||||
|
||||
/******* ECM Configuration *******/
|
||||
|
||||
// Interface 0 descriptor
|
||||
#define ECM_INTERFACE0_NB 0
|
||||
#define ECM_ALTERNATE0 0
|
||||
#define ECM_NB_ENDPOINT0 2
|
||||
#define ECM_INTERFACE0_CLASS 0x02 // CDC ACM Com
|
||||
#define ECM_INTERFACE0_SUB_CLASS 0x06 // ECM
|
||||
#define ECM_INTERFACE0_PROTOCOL 0x00 // Empty
|
||||
#define ECM_INTERFACE0_INDEX 0
|
||||
|
||||
|
||||
|
||||
#define DEVICE_STATUS 0x00 // TBD
|
||||
#define INTERFACE_STATUS 0x00 // TBD
|
||||
|
||||
#define LANG_ID 0x00
|
||||
|
||||
|
||||
|
||||
|
||||
#define USB_MN_LENGTH 5
|
||||
#define USB_MANUFACTURER_NAME \
|
||||
{ Usb_unicode('A') \
|
||||
, Usb_unicode('t') \
|
||||
, Usb_unicode('m') \
|
||||
, Usb_unicode('e') \
|
||||
, Usb_unicode('l') \
|
||||
}
|
||||
|
||||
#define USB_PN_LENGTH 16
|
||||
#define USB_PRODUCT_NAME \
|
||||
{ Usb_unicode('R') \
|
||||
,Usb_unicode('Z') \
|
||||
,Usb_unicode('R') \
|
||||
,Usb_unicode('A') \
|
||||
,Usb_unicode('V') \
|
||||
,Usb_unicode('E') \
|
||||
,Usb_unicode('N') \
|
||||
,Usb_unicode(' ') \
|
||||
,Usb_unicode('U') \
|
||||
,Usb_unicode('S') \
|
||||
,Usb_unicode('B') \
|
||||
,Usb_unicode(' ') \
|
||||
,Usb_unicode('D') \
|
||||
,Usb_unicode('E') \
|
||||
,Usb_unicode('M') \
|
||||
,Usb_unicode('O') \
|
||||
}
|
||||
|
||||
#define USB_SN_LENGTH 0x05
|
||||
#define USB_SERIAL_NUMBER \
|
||||
{Usb_unicode('1') \
|
||||
,Usb_unicode('.') \
|
||||
,Usb_unicode('0') \
|
||||
,Usb_unicode('.') \
|
||||
,Usb_unicode('0') \
|
||||
}
|
||||
|
||||
#define LANGUAGE_ID 0x0409
|
||||
|
||||
//! Usb Request
|
||||
|
@ -373,39 +385,6 @@ typedef struct {
|
|||
} S_usb_language_id;
|
||||
|
||||
|
||||
//_____ U S B M A N U F A C T U R E R D E S C R I P T O R _______________
|
||||
|
||||
|
||||
//struct usb_st_manufacturer
|
||||
typedef struct {
|
||||
U8 bLength; // size of this descriptor in bytes
|
||||
U8 bDescriptorType; // STRING descriptor type
|
||||
U16 wstring[USB_MN_LENGTH];// unicode characters
|
||||
} S_usb_manufacturer_string_descriptor;
|
||||
|
||||
|
||||
//_____ U S B P R O D U C T D E S C R I P T O R _________________________
|
||||
|
||||
|
||||
//struct usb_st_product
|
||||
typedef struct {
|
||||
U8 bLength; // size of this descriptor in bytes
|
||||
U8 bDescriptorType; // STRING descriptor type
|
||||
U16 wstring[USB_PN_LENGTH];// unicode characters
|
||||
} S_usb_product_string_descriptor;
|
||||
|
||||
|
||||
//_____ U S B S E R I A L N U M B E R D E S C R I P T O R _____________
|
||||
|
||||
|
||||
//struct usb_st_serial_number
|
||||
typedef struct {
|
||||
U8 bLength; // size of this descriptor in bytes
|
||||
U8 bDescriptorType; // STRING descriptor type
|
||||
U16 wstring[USB_SN_LENGTH];// unicode characters
|
||||
} S_usb_serial_number;
|
||||
|
||||
|
||||
/*_____ U S B I A D _______________________________________________________*/
|
||||
|
||||
#define DSC_TYPE_IAD 11
|
||||
|
@ -460,6 +439,79 @@ typedef struct
|
|||
|
||||
} S_usb_user_configuration_descriptor_network;
|
||||
|
||||
/* EEM */
|
||||
typedef struct
|
||||
{
|
||||
S_usb_configuration_descriptor cfg;
|
||||
S_usb_interface_descriptor ifc0;
|
||||
S_usb_endpoint_descriptor ep1;
|
||||
S_usb_endpoint_descriptor ep2;
|
||||
} S_usb_user_configuration_descriptor_eem;
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
U8 bLength;
|
||||
U8 bDescriptorType;
|
||||
U8 bDescriptorSubtype;
|
||||
U8 iMACAddress;
|
||||
U32 bmEthernetStatistics;
|
||||
U16 wMaxSegmentSize;
|
||||
U16 wNumberMCFilters;
|
||||
U8 bNumberPowerFilters;
|
||||
} S_usb_ethernet_networking_functional_descriptor;
|
||||
|
||||
|
||||
/* ECM */
|
||||
typedef struct
|
||||
{
|
||||
S_usb_configuration_descriptor cfg;
|
||||
S_usb_interface_descriptor ifc0;
|
||||
U8 CS1_INTERFACE[5+5];
|
||||
S_usb_ethernet_networking_functional_descriptor fd0;
|
||||
#if CDC_ECM_USES_INTERRUPT_ENDPOINT
|
||||
S_usb_endpoint_descriptor ep1;
|
||||
#endif
|
||||
#if 0
|
||||
S_usb_interface_descriptor ifc1_0;
|
||||
#endif
|
||||
S_usb_interface_descriptor ifc1_1;
|
||||
S_usb_endpoint_descriptor ep2;
|
||||
S_usb_endpoint_descriptor ep3;
|
||||
} S_usb_user_configuration_descriptor_ecm;
|
||||
|
||||
|
||||
/* ECM + Serial Port */
|
||||
typedef struct
|
||||
{
|
||||
S_usb_configuration_descriptor cfg;
|
||||
S_usb_interface_association_descriptor iad0;
|
||||
S_usb_interface_descriptor ifc0;
|
||||
U8 CS1_INTERFACE[5+5];
|
||||
S_usb_ethernet_networking_functional_descriptor fd0;
|
||||
#if CDC_ECM_USES_INTERRUPT_ENDPOINT
|
||||
S_usb_endpoint_descriptor ep1;
|
||||
#endif
|
||||
#if 0
|
||||
S_usb_interface_descriptor ifc1_0;
|
||||
#endif
|
||||
S_usb_interface_descriptor ifc1_1;
|
||||
S_usb_endpoint_descriptor ep2;
|
||||
S_usb_endpoint_descriptor ep3;
|
||||
|
||||
S_usb_interface_association_descriptor iad1;
|
||||
S_usb_interface_descriptor ifc2;
|
||||
U8 CS2_INTERFACE[19];
|
||||
S_usb_endpoint_descriptor ep4;
|
||||
S_usb_interface_descriptor ifc3;
|
||||
S_usb_endpoint_descriptor ep5;
|
||||
S_usb_endpoint_descriptor ep6;
|
||||
|
||||
} S_usb_user_configuration_descriptor_ecm_debug;
|
||||
|
||||
|
||||
/* Mass Storage */
|
||||
|
||||
typedef struct
|
||||
|
@ -471,20 +523,12 @@ typedef struct
|
|||
|
||||
} S_usb_user_configuration_descriptor_mass;
|
||||
|
||||
/* EEM */
|
||||
typedef struct
|
||||
{
|
||||
S_usb_configuration_descriptor cfg;
|
||||
S_usb_interface_descriptor ifc0;
|
||||
S_usb_endpoint_descriptor ep1;
|
||||
S_usb_endpoint_descriptor ep2;
|
||||
} S_usb_user_configuration_descriptor_eem;
|
||||
|
||||
|
||||
PGM_VOID_P Usb_get_dev_desc_pointer(void);
|
||||
U8 Usb_get_dev_desc_length(void);
|
||||
PGM_VOID_P Usb_get_conf_desc_pointer(void) ;
|
||||
U8 Usb_get_conf_desc_length(void);
|
||||
PGM_VOID_P Usb_get_conf_desc_pointer(U8 index) ;
|
||||
U8 Usb_get_conf_desc_length(U8 index);
|
||||
|
||||
#endif // _USB_USERCONFIG_H_
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "config.h"
|
||||
#include "conf_usb.h"
|
||||
#include "usb_drv.h"
|
||||
#include <util/delay.h>
|
||||
|
||||
//_____ M A C R O S ________________________________________________________
|
||||
|
||||
|
@ -61,6 +62,102 @@
|
|||
|
||||
#if (USB_DEVICE_FEATURE == ENABLED)
|
||||
|
||||
#define USB_ENDPOINT_WAIT_TIMEOUT 250
|
||||
|
||||
U8 usb_endpoint_wait_for_write_enabled() {
|
||||
#if USB_ENDPOINT_WAIT_TIMEOUT
|
||||
U16 timeout=USB_ENDPOINT_WAIT_TIMEOUT;
|
||||
while(timeout) {
|
||||
if(Is_usb_sof()) {
|
||||
Usb_ack_sof();
|
||||
timeout--;
|
||||
}
|
||||
#else
|
||||
while(1) {
|
||||
#endif
|
||||
if(Is_usb_write_enabled())
|
||||
return 0;
|
||||
if((!Is_usb_enabled()) || Is_usb_detached())
|
||||
return 1;
|
||||
if(!Is_usb_endpoint_enabled())
|
||||
return 2;
|
||||
if(Is_usb_endpoint_stall_requested())
|
||||
return 3;
|
||||
}
|
||||
return 10;
|
||||
}
|
||||
|
||||
U8 usb_endpoint_wait_for_read_control_enabled() {
|
||||
#if USB_ENDPOINT_WAIT_TIMEOUT
|
||||
U16 timeout=USB_ENDPOINT_WAIT_TIMEOUT;
|
||||
while(timeout) {
|
||||
if(Is_usb_sof()) {
|
||||
Usb_ack_sof();
|
||||
timeout--;
|
||||
}
|
||||
#else
|
||||
while(1) {
|
||||
#endif
|
||||
if(Is_usb_read_control_enabled())
|
||||
return 0;
|
||||
if((!Is_usb_enabled()) || Is_usb_detached())
|
||||
return 1;
|
||||
if(!Is_usb_endpoint_enabled())
|
||||
return 2;
|
||||
if(Is_usb_endpoint_stall_requested())
|
||||
return 3;
|
||||
}
|
||||
return 10;
|
||||
}
|
||||
|
||||
|
||||
U8 usb_endpoint_wait_for_IN_ready() {
|
||||
#if USB_ENDPOINT_WAIT_TIMEOUT
|
||||
U16 timeout=USB_ENDPOINT_WAIT_TIMEOUT;
|
||||
while(timeout) {
|
||||
if(Is_usb_sof()) {
|
||||
Usb_ack_sof();
|
||||
timeout--;
|
||||
}
|
||||
#else
|
||||
while(1) {
|
||||
#endif
|
||||
if(Is_usb_in_ready())
|
||||
return 0;
|
||||
if((!Is_usb_enabled()) || Is_usb_detached())
|
||||
return 1;
|
||||
if(!Is_usb_endpoint_enabled())
|
||||
return 2;
|
||||
if(Is_usb_endpoint_stall_requested())
|
||||
return 3;
|
||||
}
|
||||
return 10;
|
||||
}
|
||||
|
||||
|
||||
U8 usb_endpoint_wait_for_receive_out() {
|
||||
#if USB_ENDPOINT_WAIT_TIMEOUT
|
||||
U16 timeout=USB_ENDPOINT_WAIT_TIMEOUT;
|
||||
while(timeout) {
|
||||
if(Is_usb_sof()) {
|
||||
Usb_ack_sof();
|
||||
timeout--;
|
||||
}
|
||||
#else
|
||||
while(1) {
|
||||
#endif
|
||||
if(Is_usb_receive_out())
|
||||
return 0;
|
||||
if((!Is_usb_enabled()) || Is_usb_detached())
|
||||
return 1;
|
||||
if(!Is_usb_endpoint_enabled())
|
||||
return 2;
|
||||
if(Is_usb_endpoint_stall_requested())
|
||||
return 3;
|
||||
}
|
||||
return 10;
|
||||
}
|
||||
|
||||
//! usb_configure_endpoint.
|
||||
//!
|
||||
//! This function configures an endpoint with the selected type.
|
||||
|
|
|
@ -160,7 +160,7 @@ typedef enum endpoint_parameter{ep_num, ep_type, ep_direction, ep_size, ep_bank,
|
|||
//! @defgroup Endpoints_configuration Configuration macros for endpoints
|
||||
//! List of the standard macro used to configure pipes and endpoints
|
||||
//! @{
|
||||
#define Usb_build_ep_config0(type, dir, nyet) ((type<<6) | (nyet<<1) | (dir))
|
||||
#define Usb_build_ep_config0(type, dir, nyet) ((type<<6) /*| (nyet<<1)*/ | (dir))
|
||||
#define Usb_build_ep_config1(size, bank ) ((size<<4) | (bank<<2) )
|
||||
#define usb_configure_endpoint(num, type, dir, size, bank, nyet) \
|
||||
( Usb_select_endpoint(num), \
|
||||
|
@ -929,6 +929,13 @@ U8 host_determine_pipe_size (U16);
|
|||
void host_disable_all_pipe (void);
|
||||
U8 usb_get_nb_pipe_interrupt (void);
|
||||
|
||||
U8 usb_endpoint_wait_for_read_control_enabled();
|
||||
U8 usb_endpoint_wait_for_write_enabled();
|
||||
U8 usb_endpoint_wait_for_receive_out();
|
||||
U8 usb_endpoint_wait_for_IN_ready();
|
||||
|
||||
#define usb_endpoint_wait_for_read_enabled usb_endpoint_wait_for_write_enabled
|
||||
|
||||
#endif // _USB_DRV_H_
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -50,10 +50,12 @@
|
|||
#include "usb_descriptors.h"
|
||||
#include "usb_specific_request.h"
|
||||
#include "rndis/rndis_protocol.h"
|
||||
#include "rndis/cdc_ecm.h"
|
||||
#include "serial/uart_usb_lib.h"
|
||||
#include "storage/ctrl_access.h"
|
||||
#include "uip.h"
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/eeprom.h>
|
||||
#include <string.h>
|
||||
|
||||
//_____ M A C R O S ________________________________________________________
|
||||
|
@ -85,30 +87,44 @@ Bool usb_user_read_request(U8 type, U8 request)
|
|||
{
|
||||
U16 wLength;
|
||||
|
||||
//Both protocols have two bytes we throw away
|
||||
Usb_read_byte();
|
||||
Usb_read_byte();
|
||||
|
||||
switch(request)
|
||||
{
|
||||
case SEND_ENCAPSULATED_COMMAND:
|
||||
Usb_read_byte();
|
||||
Usb_read_byte();
|
||||
Usb_read_byte();//wIndex LSB
|
||||
Usb_read_byte();//wIndex MSB
|
||||
|
||||
LSB(wLength) = Usb_read_byte();
|
||||
MSB(wLength) = Usb_read_byte();
|
||||
return send_encapsulated_command(wLength);
|
||||
if((usb_configuration_nb==USB_CONFIG_RNDIS)||(usb_configuration_nb==USB_CONFIG_RNDIS_DEBUG))
|
||||
return rndis_send_encapsulated_command(wLength);
|
||||
else
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
case GET_ENCAPSULATED_COMMAND:
|
||||
Usb_read_byte();
|
||||
Usb_read_byte();
|
||||
Usb_read_byte();//wIndex LSB
|
||||
Usb_read_byte();//wIndex MSB
|
||||
|
||||
LSB(wLength) = Usb_read_byte();
|
||||
MSB(wLength) = Usb_read_byte();
|
||||
return get_encapsulated_command();
|
||||
if((usb_configuration_nb==USB_CONFIG_RNDIS)||(usb_configuration_nb==USB_CONFIG_RNDIS_DEBUG))
|
||||
return rndis_get_encapsulated_command();
|
||||
else
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
case SET_ETHERNET_PACKET_FILTER:
|
||||
if((usb_configuration_nb==USB_CONFIG_ECM) || (usb_configuration_nb==USB_CONFIG_ECM_DEBUG)) {
|
||||
cdc_ecm_set_ethernet_packet_filter();
|
||||
return TRUE;
|
||||
} else
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
#if USB_CONF_STORAGE
|
||||
case MASS_STORAGE_RESET:
|
||||
Usb_ack_receive_setup();
|
||||
|
@ -130,18 +146,34 @@ Bool usb_user_read_request(U8 type, U8 request)
|
|||
/* We don't have a real serial port - so these aren't applicable. We
|
||||
advertise that we support nothing, so shouldn't get them anyway */
|
||||
case GET_LINE_CODING:
|
||||
cdc_get_line_coding();
|
||||
return TRUE;
|
||||
Usb_read_byte();
|
||||
Usb_read_byte();
|
||||
if(USB_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) {
|
||||
cdc_get_line_coding();
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case SET_LINE_CODING:
|
||||
cdc_set_line_coding();
|
||||
return TRUE;
|
||||
Usb_read_byte();
|
||||
Usb_read_byte();
|
||||
if(USB_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) {
|
||||
cdc_set_line_coding();
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case SET_CONTROL_LINE_STATE:
|
||||
cdc_set_control_line_state();
|
||||
return TRUE;
|
||||
if(USB_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) {
|
||||
cdc_set_control_line_state();
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
#endif /* USB_CONF_CDC */
|
||||
default:
|
||||
|
@ -174,21 +206,6 @@ Bool usb_user_get_descriptor(U8 type, U8 string)
|
|||
pbuffer = &(usb_user_language_id.bLength);
|
||||
return TRUE;
|
||||
break;
|
||||
case MAN_INDEX:
|
||||
data_to_transfer = sizeof (usb_user_manufacturer_string_descriptor);
|
||||
pbuffer = &(usb_user_manufacturer_string_descriptor.bLength);
|
||||
return TRUE;
|
||||
break;
|
||||
case PROD_INDEX:
|
||||
data_to_transfer = sizeof (usb_user_product_string_descriptor);
|
||||
pbuffer = &(usb_user_product_string_descriptor.bLength);
|
||||
return TRUE;
|
||||
break;
|
||||
case SN_INDEX:
|
||||
data_to_transfer = sizeof (usb_user_serial_number);
|
||||
pbuffer = &(usb_user_serial_number.bLength);
|
||||
return TRUE;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -198,6 +215,94 @@ Bool usb_user_get_descriptor(U8 type, U8 string)
|
|||
|
||||
return FALSE;
|
||||
}
|
||||
static char itoh(unsigned char i) {
|
||||
char ret;
|
||||
ret = pgm_read_byte_near(PSTR("0123456789abcdef")+(i&0xF));
|
||||
return ret;
|
||||
}
|
||||
const char* usb_user_get_string_sram(U8 string_type) {
|
||||
static char serial[13];
|
||||
uint8_t i;
|
||||
|
||||
switch (string_type)
|
||||
{
|
||||
case USB_STRING_SERIAL:
|
||||
case USB_STRING_MAC_ADDRESS:
|
||||
{
|
||||
uint8_t mac_address[6];
|
||||
usb_eth_get_mac_address(mac_address);
|
||||
|
||||
for(i=0;i<6;i++) {
|
||||
serial[i*2] = itoh(mac_address[i]>>4);
|
||||
serial[i*2+1] = itoh(mac_address[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
serial[0] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return serial;
|
||||
}
|
||||
|
||||
PGM_P usb_user_get_string(U8 string_type) {
|
||||
switch (string_type)
|
||||
{
|
||||
case USB_STRING_MAN:
|
||||
return PSTR("Atmel");
|
||||
|
||||
case USB_STRING_PRODUCT:
|
||||
return PSTR("Jackdaw 6LoWPAN Adaptor");
|
||||
|
||||
case USB_STRING_CONFIG_COMPOSITE:
|
||||
return PSTR("RNDIS+Debug");
|
||||
|
||||
case USB_STRING_CONFIG_RNDIS:
|
||||
case USB_STRING_INTERFACE_RNDIS:
|
||||
return PSTR("RNDIS");
|
||||
|
||||
case USB_STRING_CONFIG_EEM:
|
||||
case USB_STRING_INTERFACE_EEM:
|
||||
return PSTR("CDC-EEM");
|
||||
|
||||
case USB_STRING_CONFIG_ECM:
|
||||
case USB_STRING_INTERFACE_ECM:
|
||||
return PSTR("CDC-ECM");
|
||||
|
||||
case USB_STRING_CONFIG_ECM_DEBUG:
|
||||
return PSTR("CDC-ECM+DEBUG");
|
||||
|
||||
case USB_STRING_INTERFACE_SERIAL:
|
||||
return PSTR("Debug Port");
|
||||
/*
|
||||
case USB_STRING_INTERFACE_ECM_ATTACHED:
|
||||
return PSTR("Attached");
|
||||
case USB_STRING_INTERFACE_ECM_DETACHED:
|
||||
return PSTR("Detached");
|
||||
*/
|
||||
#if USB_CONF_STORAGE
|
||||
case USB_STRING_CONFIG_MS:
|
||||
case USB_STRING_INTERFACE_MS:
|
||||
return PSTR("Mass Storage");
|
||||
#endif
|
||||
|
||||
/*
|
||||
// This is now handled by usb_user_get_string_sram.
|
||||
case USB_STRING_SERIAL:
|
||||
return PSTR("JD01");
|
||||
|
||||
case USB_STRING_MAC_ADDRESS:
|
||||
return PSTR("021213141516");
|
||||
|
||||
*/
|
||||
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! usb_user_endpoint_init.
|
||||
//!
|
||||
|
@ -206,115 +311,54 @@ Bool usb_user_get_descriptor(U8 type, U8 string)
|
|||
//! @param conf_nb Not used
|
||||
void usb_user_endpoint_init(U8 conf_nb)
|
||||
{
|
||||
if(USB_CONFIG_HAS_DEBUG_PORT(conf_nb)) {
|
||||
uart_usb_configure_endpoints();
|
||||
}
|
||||
|
||||
/* If we use RNDIS endpoints */
|
||||
if ((usb_mode == rndis_only) || (usb_mode == rndis_debug)) {
|
||||
switch(conf_nb) {
|
||||
case USB_CONFIG_ECM:
|
||||
case USB_CONFIG_ECM_DEBUG:
|
||||
cdc_ecm_configure_endpoints();
|
||||
break;
|
||||
|
||||
usb_configure_endpoint(INT_EP, \
|
||||
TYPE_INTERRUPT, \
|
||||
DIRECTION_IN, \
|
||||
SIZE_64, \
|
||||
ONE_BANK, \
|
||||
NYET_ENABLED);
|
||||
case USB_CONFIG_RNDIS_DEBUG:
|
||||
case USB_CONFIG_RNDIS:
|
||||
rndis_configure_endpoints();
|
||||
break;
|
||||
case USB_CONFIG_EEM:
|
||||
cdc_ecm_configure_endpoints();
|
||||
|
||||
usb_configure_endpoint(TX_EP, \
|
||||
TYPE_BULK, \
|
||||
DIRECTION_IN, \
|
||||
SIZE_64, \
|
||||
TWO_BANKS, \
|
||||
NYET_ENABLED);
|
||||
break;
|
||||
#if USB_CONF_STORAGE
|
||||
case USB_CONFIG_MS:
|
||||
usb_configure_endpoint(VCP_INT_EP, \
|
||||
TYPE_INTERRUPT, \
|
||||
DIRECTION_IN, \
|
||||
SIZE_32, \
|
||||
ONE_BANK, \
|
||||
NYET_ENABLED);
|
||||
|
||||
usb_configure_endpoint(RX_EP, \
|
||||
TYPE_BULK, \
|
||||
DIRECTION_OUT, \
|
||||
SIZE_64, \
|
||||
TWO_BANKS, \
|
||||
NYET_ENABLED);
|
||||
usb_configure_endpoint(VCP_TX_EP, \
|
||||
TYPE_BULK, \
|
||||
DIRECTION_IN, \
|
||||
SIZE_32, \
|
||||
TWO_BANKS, \
|
||||
NYET_ENABLED);
|
||||
|
||||
}
|
||||
|
||||
/* If we use virtual comm port (VCP) endpoints */
|
||||
if (usb_mode == rndis_debug) {
|
||||
usb_configure_endpoint(VCP_INT_EP, \
|
||||
TYPE_INTERRUPT, \
|
||||
DIRECTION_IN, \
|
||||
SIZE_32, \
|
||||
ONE_BANK, \
|
||||
NYET_ENABLED);
|
||||
|
||||
usb_configure_endpoint(VCP_TX_EP, \
|
||||
TYPE_BULK, \
|
||||
DIRECTION_IN, \
|
||||
SIZE_32, \
|
||||
TWO_BANKS, \
|
||||
NYET_ENABLED);
|
||||
|
||||
usb_configure_endpoint(VCP_RX_EP, \
|
||||
TYPE_BULK, \
|
||||
DIRECTION_OUT, \
|
||||
SIZE_32, \
|
||||
TWO_BANKS, \
|
||||
NYET_ENABLED);
|
||||
}
|
||||
|
||||
/* If we use mass storage endpoints */
|
||||
if (usb_mode == mass_storage) {
|
||||
|
||||
usb_configure_endpoint(MS_IN_EP, \
|
||||
TYPE_BULK, \
|
||||
DIRECTION_IN, \
|
||||
SIZE_64, \
|
||||
ONE_BANK, \
|
||||
NYET_ENABLED);
|
||||
|
||||
usb_configure_endpoint(MS_OUT_EP, \
|
||||
TYPE_BULK, \
|
||||
DIRECTION_OUT, \
|
||||
SIZE_64, \
|
||||
ONE_BANK, \
|
||||
NYET_ENABLED);
|
||||
}
|
||||
|
||||
if (usb_mode == eem ) {
|
||||
usb_configure_endpoint(TX_EP, \
|
||||
TYPE_BULK, \
|
||||
DIRECTION_IN, \
|
||||
SIZE_64, \
|
||||
TWO_BANKS, \
|
||||
NYET_ENABLED);
|
||||
|
||||
usb_configure_endpoint(RX_EP, \
|
||||
TYPE_BULK, \
|
||||
DIRECTION_OUT, \
|
||||
SIZE_64, \
|
||||
TWO_BANKS, \
|
||||
NYET_ENABLED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ((usb_mode == rndis_only) || (usb_mode == rndis_debug)) {
|
||||
Usb_reset_endpoint(INT_EP);
|
||||
Usb_reset_endpoint(TX_EP);
|
||||
Usb_reset_endpoint(RX_EP);
|
||||
}
|
||||
|
||||
if (usb_mode == rndis_debug){
|
||||
Usb_reset_endpoint(VCP_INT_EP);
|
||||
Usb_reset_endpoint(VCP_TX_EP);
|
||||
Usb_reset_endpoint(VCP_RX_EP);
|
||||
}
|
||||
|
||||
if (usb_mode == mass_storage) {
|
||||
Usb_reset_endpoint(VCP_TX_EP);
|
||||
Usb_reset_endpoint(VCP_RX_EP);
|
||||
}
|
||||
|
||||
if (usb_mode == eem){
|
||||
Usb_reset_endpoint(TX_EP);
|
||||
Usb_reset_endpoint(RX_EP);
|
||||
}
|
||||
usb_configure_endpoint(VCP_RX_EP, \
|
||||
TYPE_BULK, \
|
||||
DIRECTION_OUT, \
|
||||
SIZE_32, \
|
||||
TWO_BANKS, \
|
||||
NYET_ENABLED);
|
||||
Usb_reset_endpoint(VCP_INT_EP);
|
||||
Usb_reset_endpoint(VCP_TX_EP);
|
||||
Usb_reset_endpoint(VCP_RX_EP);
|
||||
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
Led0_on();
|
||||
}
|
||||
|
||||
#if USB_CONF_CDC
|
||||
|
@ -337,12 +381,7 @@ void cdc_get_line_coding(void)
|
|||
Usb_write_byte(line_coding.bParityType);
|
||||
Usb_write_byte(line_coding.bDataBits);
|
||||
|
||||
Usb_send_control_in();
|
||||
while(!(Is_usb_read_control_enabled()));
|
||||
//Usb_clear_tx_complete();
|
||||
|
||||
while(!Is_usb_receive_out());
|
||||
Usb_ack_receive_out();
|
||||
Usb_send_control_in();
|
||||
}
|
||||
|
||||
|
||||
|
@ -352,19 +391,20 @@ void cdc_get_line_coding(void)
|
|||
//!
|
||||
void cdc_set_line_coding (void)
|
||||
{
|
||||
Usb_ack_receive_setup();
|
||||
while (!(Is_usb_receive_out()));
|
||||
LSB0(line_coding.dwDTERate) = Usb_read_byte();
|
||||
LSB1(line_coding.dwDTERate) = Usb_read_byte();
|
||||
LSB2(line_coding.dwDTERate) = Usb_read_byte();
|
||||
LSB3(line_coding.dwDTERate) = Usb_read_byte();
|
||||
line_coding.bCharFormat = Usb_read_byte();
|
||||
line_coding.bParityType = Usb_read_byte();
|
||||
line_coding.bDataBits = Usb_read_byte();
|
||||
Usb_ack_receive_out();
|
||||
Usb_ack_receive_setup();
|
||||
if(usb_endpoint_wait_for_receive_out()==0) {
|
||||
LSB0(line_coding.dwDTERate) = Usb_read_byte();
|
||||
LSB1(line_coding.dwDTERate) = Usb_read_byte();
|
||||
LSB2(line_coding.dwDTERate) = Usb_read_byte();
|
||||
LSB3(line_coding.dwDTERate) = Usb_read_byte();
|
||||
line_coding.bCharFormat = Usb_read_byte();
|
||||
line_coding.bParityType = Usb_read_byte();
|
||||
line_coding.bDataBits = Usb_read_byte();
|
||||
Usb_ack_receive_out();
|
||||
|
||||
Usb_send_control_in(); // send a ZLP for STATUS phase
|
||||
while(!(Is_usb_read_control_enabled()));
|
||||
Usb_send_control_in(); // send a ZLP for STATUS phase
|
||||
usb_endpoint_wait_for_read_control_enabled();
|
||||
}
|
||||
}
|
||||
|
||||
//! cdc_set_control_line_state.
|
||||
|
@ -375,8 +415,27 @@ void cdc_set_line_coding (void)
|
|||
//!
|
||||
void cdc_set_control_line_state (void)
|
||||
{
|
||||
U8 controlLineState = Usb_read_byte();
|
||||
U8 dummy = Usb_read_byte();
|
||||
U8 interface = Usb_read_byte();
|
||||
|
||||
Usb_ack_receive_setup();
|
||||
Usb_send_control_in();
|
||||
while(!(Is_usb_read_control_enabled()));
|
||||
usb_endpoint_wait_for_read_control_enabled();
|
||||
|
||||
if(interface == INTERFACE2_NB) {
|
||||
uart_usb_set_control_line_state(controlLineState);
|
||||
}
|
||||
}
|
||||
#endif /* USB_CONF_CDC */
|
||||
|
||||
Bool usb_user_set_alt_interface(U8 interface, U8 alt_setting) {
|
||||
return FALSE;
|
||||
if((interface==ECM_INTERFACE0_NB) && ((usb_configuration_nb==USB_CONFIG_ECM) || (usb_configuration_nb==USB_CONFIG_ECM_DEBUG))) {
|
||||
// The alt_setting in this case corresponds to
|
||||
// if the interface is enabled or not.
|
||||
usb_eth_set_active(alt_setting);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,9 +65,6 @@ extern FLASH S_usb_device_descriptor usb_dev_desc_network;
|
|||
extern FLASH S_usb_user_configuration_descriptor_composite usb_conf_desc_composite;
|
||||
extern FLASH S_usb_user_configuration_descriptor_network usb_conf_desc_network;
|
||||
extern FLASH S_usb_device_qualifier_descriptor usb_qual_desc;
|
||||
extern FLASH S_usb_manufacturer_string_descriptor usb_user_manufacturer_string_descriptor;
|
||||
extern FLASH S_usb_product_string_descriptor usb_user_product_string_descriptor;
|
||||
extern FLASH S_usb_serial_number usb_user_serial_number;
|
||||
extern FLASH S_usb_language_id usb_user_language_id;
|
||||
|
||||
|
||||
|
@ -76,6 +73,10 @@ extern FLASH S_usb_language_id usb_user_language_id;
|
|||
Bool usb_user_read_request(U8, U8);
|
||||
Bool usb_user_get_descriptor(U8 , U8);
|
||||
void usb_user_endpoint_init(U8);
|
||||
Bool usb_user_set_alt_interface(U8 interface, U8 alt_setting);
|
||||
|
||||
PGM_P usb_user_get_string(U8 string_type);
|
||||
const char* usb_user_get_string_sram(U8 string_type);
|
||||
|
||||
void cdc_get_line_coding();
|
||||
void cdc_set_line_coding();
|
||||
|
|
|
@ -52,11 +52,14 @@
|
|||
#include "usb_drv.h"
|
||||
#include "usb_descriptors.h"
|
||||
#include "usb_specific_request.h"
|
||||
#include <string.h>
|
||||
|
||||
//_____ M A C R O S ________________________________________________________
|
||||
|
||||
|
||||
//_____ D E F I N I T I O N ________________________________________________
|
||||
#define PRINTF printf
|
||||
#define PRINTF_P printf_P
|
||||
|
||||
//_____ P R I V A T E D E C L A R A T I O N ______________________________
|
||||
|
||||
|
@ -123,43 +126,43 @@ void usb_process_request(void)
|
|||
{
|
||||
case GET_DESCRIPTOR:
|
||||
if (0x80 == bmRequestType) { usb_get_descriptor(); }
|
||||
else { usb_user_read_request(bmRequestType, bmRequest); }
|
||||
else goto user_read;
|
||||
break;
|
||||
|
||||
case GET_CONFIGURATION:
|
||||
if (0x80 == bmRequestType) { usb_get_configuration(); }
|
||||
else { usb_user_read_request(bmRequestType, bmRequest); }
|
||||
else goto user_read;
|
||||
break;
|
||||
|
||||
case SET_ADDRESS:
|
||||
if (0x00 == bmRequestType) { usb_set_address(); }
|
||||
else { usb_user_read_request(bmRequestType, bmRequest); }
|
||||
else goto user_read;
|
||||
break;
|
||||
|
||||
case SET_CONFIGURATION:
|
||||
if (0x00 == bmRequestType) { usb_set_configuration(); }
|
||||
else { usb_user_read_request(bmRequestType, bmRequest); }
|
||||
else goto user_read;
|
||||
break;
|
||||
|
||||
case CLEAR_FEATURE:
|
||||
if (0x02 >= bmRequestType) { usb_clear_feature(); }
|
||||
else { usb_user_read_request(bmRequestType, bmRequest); }
|
||||
else goto user_read;
|
||||
break;
|
||||
|
||||
case SET_FEATURE:
|
||||
if (0x02 >= bmRequestType) { usb_set_feature(); }
|
||||
else { usb_user_read_request(bmRequestType, bmRequest); }
|
||||
else goto user_read;
|
||||
break;
|
||||
|
||||
case GET_STATUS:
|
||||
if ((0x7F < bmRequestType) & (0x82 >= bmRequestType))
|
||||
{ usb_get_status(); }
|
||||
else { usb_user_read_request(bmRequestType, bmRequest); }
|
||||
else goto user_read;
|
||||
break;
|
||||
|
||||
case GET_INTERFACE:
|
||||
if (bmRequestType == 0x81) { usb_get_interface(); }
|
||||
else { usb_user_read_request(bmRequestType, bmRequest); }
|
||||
else goto user_read;
|
||||
break;
|
||||
|
||||
|
||||
|
@ -170,14 +173,23 @@ void usb_process_request(void)
|
|||
case SET_DESCRIPTOR:
|
||||
case SYNCH_FRAME:
|
||||
default: //!< un-supported request => call to user read request
|
||||
if(usb_user_read_request(bmRequestType, bmRequest) == FALSE)
|
||||
{
|
||||
Usb_enable_stall_handshake();
|
||||
Usb_ack_receive_setup();
|
||||
return;
|
||||
}
|
||||
user_read:
|
||||
usb_user_read_request(bmRequestType, bmRequest);
|
||||
break;
|
||||
}
|
||||
|
||||
Usb_select_endpoint(EP_CONTROL);
|
||||
|
||||
// If the receive setup flag hasn't been cleared
|
||||
// by this point then we can assume that we didn't
|
||||
// support this request and should stall.
|
||||
if(Is_usb_receive_setup())
|
||||
Usb_enable_stall_handshake();
|
||||
|
||||
// Clear some flags.
|
||||
Usb_ack_receive_setup();
|
||||
Usb_ack_receive_out();
|
||||
Usb_ack_in_ready();
|
||||
}
|
||||
|
||||
//! usb_set_address.
|
||||
|
@ -214,26 +226,205 @@ U8 configuration_number;
|
|||
|
||||
configuration_number = Usb_read_byte();
|
||||
|
||||
if (configuration_number <= NB_CONFIGURATION)
|
||||
{
|
||||
Usb_ack_receive_setup();
|
||||
usb_configuration_nb = configuration_number;
|
||||
}
|
||||
else
|
||||
{
|
||||
//!< keep that order (set StallRq/clear RxSetup) or a
|
||||
//!< OUT request following the SETUP may be acknowledged
|
||||
Usb_enable_stall_handshake();
|
||||
Usb_ack_receive_setup();
|
||||
return;
|
||||
}
|
||||
// TODO: Verify configuration_number!
|
||||
Usb_ack_receive_setup();
|
||||
usb_configuration_nb = configuration_number;
|
||||
|
||||
Usb_send_control_in(); //!< send a ZLP for STATUS phase
|
||||
while(!Is_usb_in_ready());
|
||||
|
||||
usb_user_endpoint_init(usb_configuration_nb); //!< endpoint configuration
|
||||
Usb_set_configuration_action();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void usb_get_string_descriptor_sram(U8 string_type) {
|
||||
U16 requested_length;
|
||||
U8 dummy;
|
||||
const char* user_str;
|
||||
|
||||
user_str = usb_user_get_string_sram(string_type);
|
||||
|
||||
dummy = Usb_read_byte(); //!< don't care of wIndex field
|
||||
dummy = Usb_read_byte();
|
||||
requested_length = Usb_read_byte(); //!< read wLength
|
||||
requested_length |= Usb_read_byte()<<8;
|
||||
|
||||
if(!user_str)
|
||||
return;
|
||||
|
||||
const U8 actual_descriptor_size = 2+strlen(user_str)*2;
|
||||
|
||||
if (requested_length > actual_descriptor_size) {
|
||||
zlp = ((actual_descriptor_size % EP_CONTROL_LENGTH) == 0);
|
||||
requested_length = actual_descriptor_size;
|
||||
}
|
||||
|
||||
Usb_ack_receive_setup() ; //!< clear the receive setup flag
|
||||
|
||||
if(usb_endpoint_wait_for_read_control_enabled()!=0) {
|
||||
Usb_enable_stall_handshake();
|
||||
return;
|
||||
}
|
||||
|
||||
// Output the length
|
||||
Usb_write_byte(actual_descriptor_size);
|
||||
|
||||
// Output the type
|
||||
Usb_write_byte(STRING_DESCRIPTOR);
|
||||
|
||||
requested_length -= 2;
|
||||
U8 nb_byte = 2;
|
||||
|
||||
if(!requested_length) {
|
||||
Usb_send_control_in();
|
||||
}
|
||||
|
||||
while((requested_length != 0) && (!Is_usb_receive_out()))
|
||||
{
|
||||
if(usb_endpoint_wait_for_read_control_enabled()!=0) {
|
||||
Usb_enable_stall_handshake();
|
||||
break;
|
||||
}
|
||||
|
||||
while(requested_length != 0) //!< Send data until necessary
|
||||
{
|
||||
if(nb_byte==EP_CONTROL_LENGTH) //!< Check endpoint 0 size
|
||||
{
|
||||
nb_byte=0;
|
||||
break;
|
||||
}
|
||||
|
||||
Usb_write_byte(*user_str);
|
||||
Usb_write_byte(0);
|
||||
user_str++;
|
||||
requested_length -=2;
|
||||
nb_byte+=2;
|
||||
}
|
||||
Usb_send_control_in();
|
||||
}
|
||||
|
||||
bail:
|
||||
if(Is_usb_receive_out()) {
|
||||
//! abort from Host
|
||||
Usb_ack_receive_out();
|
||||
return;
|
||||
}
|
||||
|
||||
if(zlp == TRUE) {
|
||||
if(usb_endpoint_wait_for_read_control_enabled()!=0) {
|
||||
Usb_enable_stall_handshake();
|
||||
return;
|
||||
}
|
||||
Usb_send_control_in();
|
||||
}
|
||||
|
||||
usb_endpoint_wait_for_receive_out();
|
||||
Usb_ack_receive_out();
|
||||
}
|
||||
|
||||
|
||||
void usb_get_string_descriptor(U8 string_type) {
|
||||
U16 requested_length;
|
||||
U8 dummy;
|
||||
PGM_P user_str;
|
||||
|
||||
user_str = usb_user_get_string(string_type);
|
||||
|
||||
if(!user_str) {
|
||||
usb_get_string_descriptor_sram(string_type);
|
||||
return;
|
||||
}
|
||||
|
||||
dummy = Usb_read_byte(); //!< don't care of wIndex field
|
||||
dummy = Usb_read_byte();
|
||||
requested_length = Usb_read_byte(); //!< read wLength
|
||||
requested_length |= Usb_read_byte()<<8;
|
||||
|
||||
|
||||
const U8 actual_descriptor_size = 2+strlen_P(user_str)*2;
|
||||
|
||||
if (requested_length > actual_descriptor_size) {
|
||||
zlp = ((actual_descriptor_size % EP_CONTROL_LENGTH) == 0);
|
||||
requested_length = actual_descriptor_size;
|
||||
}
|
||||
|
||||
Usb_ack_receive_setup() ; //!< clear the receive setup flag
|
||||
|
||||
if(usb_endpoint_wait_for_read_control_enabled()!=0) {
|
||||
Usb_enable_stall_handshake();
|
||||
return;
|
||||
}
|
||||
U8 nb_byte = 0;
|
||||
|
||||
// Output the length
|
||||
if(requested_length) {
|
||||
Usb_write_byte(actual_descriptor_size);
|
||||
requested_length--;
|
||||
nb_byte++;
|
||||
}
|
||||
|
||||
// Output the type
|
||||
if(requested_length) {
|
||||
Usb_write_byte(STRING_DESCRIPTOR);
|
||||
requested_length--;
|
||||
nb_byte++;
|
||||
}
|
||||
|
||||
if(!requested_length) {
|
||||
Usb_send_control_in();
|
||||
}
|
||||
|
||||
while((requested_length != 0) && (!Is_usb_receive_out()))
|
||||
{
|
||||
if(usb_endpoint_wait_for_read_control_enabled()!=0) {
|
||||
Usb_enable_stall_handshake();
|
||||
break;
|
||||
}
|
||||
|
||||
while(requested_length != 0) //!< Send data until necessary
|
||||
{
|
||||
if(nb_byte==EP_CONTROL_LENGTH) { //!< Check endpoint 0 size
|
||||
nb_byte=0;
|
||||
break;
|
||||
}
|
||||
|
||||
Usb_write_byte(pgm_read_byte_near((unsigned int)user_str++));
|
||||
requested_length--;
|
||||
nb_byte++;
|
||||
if(requested_length) {
|
||||
Usb_write_byte(0);
|
||||
requested_length--;
|
||||
nb_byte++;
|
||||
}
|
||||
}
|
||||
Usb_send_control_in();
|
||||
}
|
||||
|
||||
bail:
|
||||
|
||||
if(Is_usb_receive_out()) {
|
||||
//! abort from Host
|
||||
Usb_ack_receive_out();
|
||||
return;
|
||||
}
|
||||
|
||||
if(zlp == TRUE) {
|
||||
if(usb_endpoint_wait_for_read_control_enabled()!=0) {
|
||||
Usb_enable_stall_handshake();
|
||||
return;
|
||||
}
|
||||
Usb_send_control_in();
|
||||
}
|
||||
|
||||
usb_endpoint_wait_for_receive_out();
|
||||
Usb_ack_receive_out();
|
||||
}
|
||||
|
||||
|
||||
//! usb_get_descriptor.
|
||||
//!
|
||||
//! This function manages the GET DESCRIPTOR request. The device descriptor,
|
||||
|
@ -246,91 +437,93 @@ U8 configuration_number;
|
|||
//!
|
||||
void usb_get_descriptor(void)
|
||||
{
|
||||
U8 LSBwLength, MSBwLength;
|
||||
U8 descriptor_type ;
|
||||
U8 string_type ;
|
||||
U8 dummy;
|
||||
U8 nb_byte;
|
||||
U8 LSBwLength, MSBwLength;
|
||||
U8 descriptor_type ;
|
||||
U8 string_type ;
|
||||
U8 dummy;
|
||||
|
||||
zlp = FALSE; /* no zero length packet */
|
||||
string_type = Usb_read_byte(); /* read LSB of wValue */
|
||||
descriptor_type = Usb_read_byte(); /* read MSB of wValue */
|
||||
zlp = FALSE; /* no zero length packet */
|
||||
string_type = Usb_read_byte(); /* read LSB of wValue */
|
||||
descriptor_type = Usb_read_byte(); /* read MSB of wValue */
|
||||
|
||||
dummy = Usb_read_byte(); //!< don't care of wIndex field
|
||||
dummy = Usb_read_byte();
|
||||
LSBwLength = Usb_read_byte(); //!< read wLength
|
||||
MSBwLength = Usb_read_byte();
|
||||
switch (descriptor_type)
|
||||
{
|
||||
case DEVICE_DESCRIPTOR:
|
||||
data_to_transfer = Usb_get_dev_desc_length(); //!< sizeof (usb_user_device_descriptor);
|
||||
pbuffer = Usb_get_dev_desc_pointer();
|
||||
break;
|
||||
case CONFIGURATION_DESCRIPTOR:
|
||||
data_to_transfer = Usb_get_conf_desc_length(string_type); //!< sizeof (usb_user_configuration_descriptor);
|
||||
pbuffer = Usb_get_conf_desc_pointer(string_type);
|
||||
break;
|
||||
case STRING_DESCRIPTOR:
|
||||
if(string_type!=LANG_ID) {
|
||||
usb_get_string_descriptor(string_type);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
dummy = Usb_read_byte();
|
||||
dummy = Usb_read_byte();
|
||||
dummy = Usb_read_byte();
|
||||
dummy = Usb_read_byte();
|
||||
if( usb_user_get_descriptor(descriptor_type, string_type)==FALSE )
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (descriptor_type)
|
||||
{
|
||||
case DEVICE_DESCRIPTOR:
|
||||
data_to_transfer = Usb_get_dev_desc_length(); //!< sizeof (usb_user_device_descriptor);
|
||||
pbuffer = Usb_get_dev_desc_pointer();
|
||||
break;
|
||||
case CONFIGURATION_DESCRIPTOR:
|
||||
data_to_transfer = Usb_get_conf_desc_length(); //!< sizeof (usb_user_configuration_descriptor);
|
||||
pbuffer = Usb_get_conf_desc_pointer();
|
||||
break;
|
||||
default:
|
||||
if( usb_user_get_descriptor(descriptor_type, string_type)==FALSE )
|
||||
{
|
||||
Usb_enable_stall_handshake();
|
||||
Usb_ack_receive_setup();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
dummy = Usb_read_byte(); //!< don't care of wIndex field
|
||||
dummy = Usb_read_byte();
|
||||
LSBwLength = Usb_read_byte(); //!< read wLength
|
||||
MSBwLength = Usb_read_byte();
|
||||
|
||||
Usb_ack_receive_setup() ; //!< clear the receive setup flag
|
||||
|
||||
Usb_ack_receive_setup() ; //!< clear the receive setup flag
|
||||
if ((LSBwLength > data_to_transfer) || (MSBwLength)) {
|
||||
if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
|
||||
else { zlp = FALSE; } //!< no need of zero length packet
|
||||
|
||||
if ((LSBwLength > data_to_transfer) || (MSBwLength))
|
||||
{
|
||||
if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
|
||||
else { zlp = FALSE; } //!< no need of zero length packet
|
||||
LSBwLength = data_to_transfer;
|
||||
MSBwLength = 0x00;
|
||||
} else {
|
||||
data_to_transfer = LSBwLength; //!< send only requested number of data
|
||||
}
|
||||
|
||||
while((data_to_transfer != 0) && (!Is_usb_receive_out())) {
|
||||
U8 nb_byte = 0;
|
||||
if(usb_endpoint_wait_for_read_control_enabled()!=0) {
|
||||
Usb_enable_stall_handshake();
|
||||
break;
|
||||
}
|
||||
|
||||
LSBwLength = data_to_transfer;
|
||||
MSBwLength = 0x00;
|
||||
}
|
||||
else
|
||||
{
|
||||
data_to_transfer = LSBwLength; //!< send only requested number of data
|
||||
}
|
||||
//! Send data until necessary
|
||||
while(data_to_transfer != 0) {
|
||||
// if(Is_usb_write_enabled()) //!< Check endpoint 0 size
|
||||
if(nb_byte++==EP_CONTROL_LENGTH) //!< Check endpoint 0 size
|
||||
break;
|
||||
|
||||
Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++));
|
||||
data_to_transfer --;
|
||||
|
||||
while((data_to_transfer != 0) && (!Is_usb_receive_out()))
|
||||
{
|
||||
while(!Is_usb_read_control_enabled());
|
||||
}
|
||||
Usb_send_control_in();
|
||||
}
|
||||
|
||||
nb_byte=0;
|
||||
while(data_to_transfer != 0) //!< Send data until necessary
|
||||
{
|
||||
if(nb_byte++==EP_CONTROL_LENGTH) //!< Check endpoint 0 size
|
||||
{
|
||||
break;
|
||||
}
|
||||
if(Is_usb_receive_out()) {
|
||||
//! abort from Host
|
||||
Usb_ack_receive_out();
|
||||
return;
|
||||
}
|
||||
|
||||
if(zlp == TRUE) {
|
||||
if(usb_endpoint_wait_for_read_control_enabled()!=0) {
|
||||
Usb_enable_stall_handshake();
|
||||
return;
|
||||
}
|
||||
Usb_send_control_in();
|
||||
}
|
||||
|
||||
//#ifndef AVRGCC
|
||||
// Usb_write_byte(*pbuffer++);
|
||||
//#else // AVRGCC does not support point to PGM space
|
||||
//#warning AVRGCC assumes devices descriptors are stored in the lower 64Kbytes of on-chip flash memory
|
||||
Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++));
|
||||
//#endif
|
||||
data_to_transfer --;
|
||||
|
||||
}
|
||||
Usb_send_control_in();
|
||||
}
|
||||
|
||||
if(Is_usb_receive_out()) { Usb_ack_receive_out(); return; } //!< abort from Host
|
||||
if(zlp == TRUE)
|
||||
{
|
||||
while(!Is_usb_read_control_enabled());
|
||||
Usb_send_control_in();
|
||||
}
|
||||
|
||||
while(!Is_usb_receive_out());
|
||||
Usb_ack_receive_out();
|
||||
usb_endpoint_wait_for_receive_out();
|
||||
Usb_ack_receive_out();
|
||||
}
|
||||
|
||||
//! usb_get_configuration.
|
||||
|
@ -345,9 +538,9 @@ void usb_get_configuration(void)
|
|||
Usb_ack_receive_setup();
|
||||
|
||||
Usb_write_byte(usb_configuration_nb);
|
||||
Usb_ack_in_ready();
|
||||
Usb_send_control_in();
|
||||
|
||||
while( !Is_usb_receive_out() );
|
||||
usb_endpoint_wait_for_receive_out();
|
||||
Usb_ack_receive_out();
|
||||
}
|
||||
|
||||
|
@ -390,7 +583,7 @@ U8 dummy;
|
|||
Usb_write_byte(0x00);
|
||||
Usb_send_control_in();
|
||||
|
||||
while( !Is_usb_receive_out() );
|
||||
usb_endpoint_wait_for_receive_out();
|
||||
Usb_ack_receive_out();
|
||||
}
|
||||
|
||||
|
@ -409,10 +602,6 @@ U8 dummy;
|
|||
|
||||
if (bmRequestType == INTERFACE_TYPE)
|
||||
{
|
||||
//!< keep that order (set StallRq/clear RxSetup) or a
|
||||
//!< OUT request following the SETUP may be acknowledged
|
||||
Usb_enable_stall_handshake();
|
||||
Usb_ack_receive_setup();
|
||||
return;
|
||||
}
|
||||
else if (bmRequestType == ENDPOINT_TYPE)
|
||||
|
@ -426,8 +615,6 @@ U8 dummy;
|
|||
|
||||
if (wIndex == EP_CONTROL)
|
||||
{
|
||||
Usb_enable_stall_handshake();
|
||||
Usb_ack_receive_setup();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -443,15 +630,11 @@ U8 dummy;
|
|||
else
|
||||
{
|
||||
Usb_select_endpoint(EP_CONTROL);
|
||||
Usb_enable_stall_handshake();
|
||||
Usb_ack_receive_setup();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Usb_enable_stall_handshake();
|
||||
Usb_ack_receive_setup();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -471,18 +654,10 @@ U8 dummy;
|
|||
|
||||
if (bmRequestType == ZERO_TYPE)
|
||||
{
|
||||
//!< keep that order (set StallRq/clear RxSetup) or a
|
||||
//!< OUT request following the SETUP may be acknowledged
|
||||
Usb_enable_stall_handshake();
|
||||
Usb_ack_receive_setup();
|
||||
return;
|
||||
}
|
||||
else if (bmRequestType == INTERFACE_TYPE)
|
||||
{
|
||||
//!< keep that order (set StallRq/clear RxSetup) or a
|
||||
//!< OUT request following the SETUP may be acknowledged
|
||||
Usb_enable_stall_handshake();
|
||||
Usb_ack_receive_setup();
|
||||
return;
|
||||
}
|
||||
else if (bmRequestType == ENDPOINT_TYPE)
|
||||
|
@ -507,19 +682,15 @@ U8 dummy;
|
|||
endpoint_status[wIndex] = 0x00;
|
||||
Usb_ack_receive_setup();
|
||||
Usb_send_control_in();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Usb_select_endpoint(EP_CONTROL);
|
||||
Usb_enable_stall_handshake();
|
||||
Usb_ack_receive_setup();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Usb_enable_stall_handshake();
|
||||
Usb_ack_receive_setup();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -533,8 +704,7 @@ U8 dummy;
|
|||
//!
|
||||
void usb_get_interface (void)
|
||||
{
|
||||
Usb_enable_stall_handshake();
|
||||
Usb_ack_receive_setup();
|
||||
// Not yet implemented.
|
||||
}
|
||||
|
||||
//! usb_set_interface.
|
||||
|
@ -545,7 +715,21 @@ void usb_get_interface (void)
|
|||
//!
|
||||
void usb_set_interface (void)
|
||||
{
|
||||
Usb_ack_receive_setup();
|
||||
Usb_send_control_in(); //!< send a ZLP for STATUS phase
|
||||
while(!Is_usb_in_ready());
|
||||
U8 alt_setting;
|
||||
U8 dummy;
|
||||
U8 interface;
|
||||
|
||||
alt_setting = Usb_read_byte();
|
||||
dummy = Usb_read_byte();
|
||||
interface = Usb_read_byte();
|
||||
|
||||
if(usb_user_set_alt_interface(interface, alt_setting)) {
|
||||
Usb_ack_receive_setup();
|
||||
Usb_send_control_in(); //!< send a ZLP for STATUS phase
|
||||
while(!Is_usb_in_ready());
|
||||
|
||||
usb_endpoint_wait_for_receive_out();
|
||||
Usb_ack_receive_out();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -166,53 +166,44 @@ void usb_start_device (void)
|
|||
*/
|
||||
static void pollhandler(void)
|
||||
{
|
||||
/* Check for setup packets */
|
||||
Usb_select_endpoint(EP_CONTROL);
|
||||
if (Is_usb_receive_setup()) {
|
||||
usb_process_request();
|
||||
}
|
||||
|
||||
/* The previous call might have requested we send
|
||||
out something to the RNDIS interrupt endpoint */
|
||||
if (schedule_interrupt) {
|
||||
Usb_select_endpoint(INT_EP);
|
||||
|
||||
//RNDIS needs a delay where this isn't called, as it will switch endpoints
|
||||
//and screw up the data transfers
|
||||
if (!usb_busy) {
|
||||
//Linux is a bunch of lies, and won't read
|
||||
//the interrupt endpoint. Hence if this isn't ready just exit
|
||||
//while(!Is_usb_write_enabled());
|
||||
|
||||
/* Check for setup packets */
|
||||
Usb_select_endpoint(EP_CONTROL);
|
||||
if (Is_usb_receive_setup()) {
|
||||
usb_process_request();
|
||||
if (Is_usb_write_enabled()) {
|
||||
|
||||
// Only valid interrupt is:
|
||||
// 0x00000001 0x00000000
|
||||
//
|
||||
Usb_write_byte(0x01);
|
||||
Usb_write_byte(0x00);
|
||||
Usb_write_byte(0x00);
|
||||
Usb_write_byte(0x00);
|
||||
Usb_write_byte(0x00);
|
||||
Usb_write_byte(0x00);
|
||||
Usb_write_byte(0x00);
|
||||
Usb_write_byte(0x00);
|
||||
|
||||
//Send back
|
||||
Usb_send_in();
|
||||
|
||||
schedule_interrupt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* The previous call might have requested we send
|
||||
out something to the RNDIS interrupt endpoint */
|
||||
if (schedule_interrupt) {
|
||||
Usb_select_endpoint(INT_EP);
|
||||
|
||||
//Linux is a bunch of lies, and won't read
|
||||
//the interrupt endpoint. Hence if this isn't ready just exit
|
||||
//while(!Is_usb_write_enabled());
|
||||
|
||||
if (Is_usb_write_enabled()) {
|
||||
|
||||
// Only valid interrupt is:
|
||||
// 0x00000001 0x00000000
|
||||
//
|
||||
Usb_write_byte(0x01);
|
||||
Usb_write_byte(0x00);
|
||||
Usb_write_byte(0x00);
|
||||
Usb_write_byte(0x00);
|
||||
Usb_write_byte(0x00);
|
||||
Usb_write_byte(0x00);
|
||||
Usb_write_byte(0x00);
|
||||
Usb_write_byte(0x00);
|
||||
|
||||
//Send back
|
||||
Usb_send_in();
|
||||
|
||||
schedule_interrupt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Continue polling */
|
||||
process_poll(&usb_process);
|
||||
/* Continue polling */
|
||||
process_poll(&usb_process);
|
||||
|
||||
}
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue