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
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);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue