Merge CDC-ECM, RNG, DFU bootloader, watchdog, settings manager, energy scan routines of Robert Quattlebaum

This commit is contained in:
dak664 2010-09-17 21:59:09 +00:00
parent 7b529cac03
commit 110bc0242e
42 changed files with 4739 additions and 2669 deletions

View file

@ -1,4 +1,4 @@
# $Id: Makefile.avr,v 1.24 2010/06/22 17:11:38 dak664 Exp $ # $Id: Makefile.avr,v 1.25 2010/09/17 21:59:09 dak664 Exp $
### Check if we are running under Windows ### Check if we are running under Windows
@ -23,7 +23,7 @@ CONTIKI_CPU=$(CONTIKI)/cpu/avr
### These directories will be searched for the specified source files ### These directories will be searched for the specified source files
### TARGETLIBS are platform-specific routines in the contiki library path ### TARGETLIBS are platform-specific routines in the contiki library path
CONTIKI_CPU_DIRS = . dev CONTIKI_CPU_DIRS = . dev
AVR = clock.c mtarch.c eeprom.c flash.c rs232.c leds-arch.c watchdog.c rtimer-arch.c AVR = clock.c mtarch.c eeprom.c flash.c rs232.c leds-arch.c watchdog.c rtimer-arch.c bootloader.c settings.c
ELFLOADER = elfloader.c elfloader-avr.c symtab-avr.c ELFLOADER = elfloader.c elfloader-avr.c symtab-avr.c
TARGETLIBS = random.c leds.c TARGETLIBS = random.c leds.c

59
cpu/avr/bootloader.c Normal file
View file

@ -0,0 +1,59 @@
#include "bootloader.h"
#include "dev/watchdog.h"
#include <util/delay.h>
#include <avr/wdt.h>
#include "dev/usb/usb_drv.h"
volatile uint32_t Boot_Key ATTR_NO_INIT;
bool
bootloader_is_present(void) {
return pgm_read_word_far(BOOTLOADER_START_ADDRESS)!=0xFFFF;
}
void
Jump_To_Bootloader(void)
{
uint8_t i;
#ifdef UDCON
// If USB is used, detach from the bus
Usb_detach();
#endif
// Disable all interrupts
cli();
// Set the bootloader key to the magic value and force a reset
Boot_Key = MAGIC_BOOT_KEY;
// Wait two seconds for the USB detachment to register on the host
for (i = 0; i < 128; i++)
_delay_ms(16);
// Set the bootloader key to the magic value and force a reset
Boot_Key = MAGIC_BOOT_KEY;
watchdog_reboot();
}
extern void Bootloader_Jump_Check(void) ATTR_INIT_SECTION(3);
void
Bootloader_Jump_Check(void)
{
// If the reset source was the bootloader and the key is correct, clear it and jump to the bootloader
if(MCUSR & (1<<WDRF)) {
MCUSR = 0;
if(Boot_Key == MAGIC_BOOT_KEY) {
Boot_Key = 0;
wdt_disable();
((void (*)(void))BOOTLOADER_START_ADDRESS)();
} else {
Boot_Key++;
}
} else {
Boot_Key = MAGIC_BOOT_KEY-4;
}
}

24
cpu/avr/bootloader.h Normal file
View file

@ -0,0 +1,24 @@
#ifndef __AVR_BOOTLOADER_H__
#define __AVR_BOOTLOADER_H__
#include <inttypes.h>
#include <avr/io.h>
#include <stdbool.h>
#define ATTR_INIT_SECTION(SectionIndex) __attribute__ ((naked, section (".init" #SectionIndex )))
#define ATTR_NO_INIT __attribute__ ((section (".noinit")))
#ifndef BOOTLOADER_SEC_SIZE_BYTES
#define BOOTLOADER_SEC_SIZE_BYTES (0x1000)
#endif
#ifndef BOOTLOADER_START_ADDRESS
#define BOOTLOADER_START_ADDRESS (FLASHEND-BOOTLOADER_SEC_SIZE_BYTES+1)
#endif
#define MAGIC_BOOT_KEY 0xDC42ACCA
extern void Jump_To_Bootloader(void);
extern bool bootloader_is_present(void);
#endif

View file

@ -94,6 +94,14 @@
/** USB RNDIS / Virtual com port setup **/ /** 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 NB_ENDPOINTS 7 //! number of endpoints in the application including control endpoint
#define VCP_RX_EP 0x06 #define VCP_RX_EP 0x06
#define VCP_TX_EP 0x05 #define VCP_TX_EP 0x05

View 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;
}

View 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__

View 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;
}

View 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__

View file

@ -58,6 +58,7 @@ RNDIS Status Information:
//_____ I N C L U D E S ____________________________________________________ //_____ I N C L U D E S ____________________________________________________
#include <stdbool.h>
#include "radio.h" #include "radio.h"
#include "contiki.h" #include "contiki.h"
#include "config.h" #include "config.h"
@ -65,12 +66,18 @@ RNDIS Status Information:
#include "usb_descriptors.h" #include "usb_descriptors.h"
#include "usb_specific_request.h" #include "usb_specific_request.h"
#include "rndis/rndis_protocol.h" #include "rndis/rndis_protocol.h"
#include "rndis/rndis_task.h"
#include "uip.h" #include "uip.h"
#include "serial/uart_usb_lib.h" #include "serial/uart_usb_lib.h"
#include "sicslow_ethernet.h" #include "sicslow_ethernet.h"
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#include <string.h> #include <string.h>
#include <stdio.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
//_____ M A C R O S ________________________________________________________ //_____ M A C R O S ________________________________________________________
//_____ D E F I N I T I O N ________________________________________________ //_____ D E F I N I T I O N ________________________________________________
@ -80,14 +87,10 @@ RNDIS Status Information:
extern PGM_VOID_P pbuffer; extern PGM_VOID_P pbuffer;
extern U8 data_to_transfer; 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 * \brief List of supported RNDIS OID's
*/ */
prog_uint32_t OIDSupportedList[OID_LIST_LENGTH] = { prog_uint32_t OIDSupportedList[] = {
/* Required General */ /* Required General */
OID_GEN_SUPPORTED_LIST , OID_GEN_SUPPORTED_LIST ,
OID_GEN_HARDWARE_STATUS , 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 /*802.11 OID's not fully implemented yet. Hence do not say we
support them */ support them */
#ifdef DONOTEVERDEFINETHISORBADSTUFFHAPPENS #if USB_ETH_EMULATE_WIFI
/* 802.11 OIDs */ /* 802.11 OIDs */
OID_802_11_BSSID , OID_802_11_BSSID ,
OID_802_11_SSID , OID_802_11_SSID ,
@ -156,18 +159,17 @@ prog_uint32_t OIDSupportedList[OID_LIST_LENGTH] = {
OID_PNP_ENABLE_WAKE_UP , OID_PNP_ENABLE_WAKE_UP ,
OID_PNP_ADD_WAKE_UP_PATTERN , OID_PNP_ADD_WAKE_UP_PATTERN ,
OID_PNP_REMOVE_WAKE_UP_PATTERN OID_PNP_REMOVE_WAKE_UP_PATTERN
};
}; #define OID_LIST_LENGTH sizeof(OIDSupportedList)/sizeof(*OIDSupportedList)
rndis_state_t rndis_state; rndis_state_t rndis_state;
rndis_stat_t rndis_stat; usb_eth_stat_t usb_eth_stat;
uint8_t schedule_interrupt = 0; uint8_t schedule_interrupt = 0;
uint64_t rndis_ethernet_addr = 0x203478928323ULL;
//_____ D E C L A R A T I O N ______________________________________________ //_____ 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. * \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; U8 i = 0;
@ -200,12 +202,6 @@ uint8_t send_encapsulated_command(uint16_t wLength)
if (wLength > ENC_BUF_SIZE) if (wLength > ENC_BUF_SIZE)
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... //Read in all the bytes...
uint8_t nb_counter; uint8_t nb_counter;
@ -256,9 +252,13 @@ uint8_t send_encapsulated_command(uint16_t wLength)
m->MinorVersion = RNDIS_MAJOR_VERSION; m->MinorVersion = RNDIS_MAJOR_VERSION;
m->Status = RNDIS_STATUS_SUCCESS; m->Status = RNDIS_STATUS_SUCCESS;
m->DeviceFlags = RNDIS_DF_CONNECTIONLESS; m->DeviceFlags = RNDIS_DF_CONNECTIONLESS;
#if USB_ETH_EMULATE_WIFI
m->Medium = NDIS_MEDIUM_WIRELESS_LAN;
#else
m->Medium = RNDIS_MEDIUM_802_3; m->Medium = RNDIS_MEDIUM_802_3;
#endif // USB_ETH_EMULATE_WIFI
m->MaxPacketsPerTransfer = 1; 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 */ RNDIS messages */
m->PacketAlignmentFactor = 3; m->PacketAlignmentFactor = 3;
m->AfListOffset = 0; m->AfListOffset = 0;
@ -353,7 +353,9 @@ void rndis_send_interrupt(void)
uint32_t oid_packet_filter = 0x0000000; uint32_t oid_packet_filter = 0x0000000;
#if USB_ETH_EMULATE_WIFI
uint16_t panid = 0xbaad; uint16_t panid = 0xbaad;
#endif
/** /**
* \brief Function to handle a RNDIS "QUERY" command in the encapsulated_buffer * \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_SUPPORTED:
case OID_GEN_MEDIA_IN_USE: 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; break;
case OID_GEN_MAXIMUM_FRAME_SIZE: 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; break;
case OID_GEN_LINK_SPEED: 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; break;
case OID_GEN_TRANSMIT_BLOCK_SIZE: case OID_GEN_TRANSMIT_BLOCK_SIZE:
@ -422,57 +429,35 @@ void rndis_query_process(void)
break; break;
case OID_GEN_MAXIMUM_TOTAL_SIZE: case OID_GEN_MAXIMUM_TOTAL_SIZE:
*INFBUF = (uint32_t) 1300; //127; *INFBUF = (uint32_t) USB_ETH_MTU; //127;
break; break;
case OID_GEN_MEDIA_CONNECT_STATUS: 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; break;
case OID_GEN_VENDOR_DRIVER_VERSION: case OID_GEN_VENDOR_DRIVER_VERSION:
*INFBUF = 0x00001000; *INFBUF = 0x00001000;
break; break;
case OID_GEN_PHYSICAL_MEDIUM:
*INFBUF = NDIS_MEDIUM_802_3; /*NDIS_MEDIUM_WIRELESS_LAN;*/
break;
case OID_GEN_CURRENT_LOOKAHEAD: 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) *******/ /******* 802.3 (Ethernet) *******/
/*The address of the NIC encoded in the hardware.*/ /*The address of the NIC encoded in the hardware.*/
case OID_802_3_PERMANENT_ADDRESS: 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: case OID_802_3_CURRENT_ADDRESS:
//Clear unused bytes //Clear unused bytes
*(INFBUF + 1) = 0; *(INFBUF + 1) = 0;
//Set address //get address
*((uint8_t *)INFBUF + 0) = *(((uint8_t * ) &rndis_ethernet_addr) + 5); usb_eth_get_mac_address((uint8_t*)INFBUF);
*((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 */ /*4+2 = 6 Bytes of eth address */
c->InformationBufferLength += 2; c->InformationBufferLength += 2;
@ -495,20 +480,14 @@ void rndis_query_process(void)
/* Frames received with alignment error */ /* Frames received with alignment error */
case OID_802_3_RCV_ERROR_ALIGNMENT: case OID_802_3_RCV_ERROR_ALIGNMENT:
*INFBUF = 0;
break;
/* Frames transmitted with one collision */ /* Frames transmitted with one collision */
case OID_802_3_XMIT_ONE_COLLISION: case OID_802_3_XMIT_ONE_COLLISION:
*INFBUF = 0;
break;
/* Frames transmitted with more than one collision */ /* Frames transmitted with more than one collision */
case OID_802_3_XMIT_MORE_COLLISIONS: case OID_802_3_XMIT_MORE_COLLISIONS:
*INFBUF = 0; *INFBUF = 0;
break; break;
#if USB_ETH_EMULATE_WIFI
/*** 802.11 OIDs ***/ /*** 802.11 OIDs ***/
case OID_802_11_BSSID: case OID_802_11_BSSID:
*INFBUF = (uint32_t)panid; *INFBUF = (uint32_t)panid;
@ -543,27 +522,28 @@ void rndis_query_process(void)
case OID_802_11_WEP_STATUS: case OID_802_11_WEP_STATUS:
case OID_802_11_AUTHENTICATION_MODE: case OID_802_11_AUTHENTICATION_MODE:
break; break;
#endif //USB_ETH_EMULATE_WIFI
/*** Statistical ***/ /*** Statistical ***/
/* Frames transmitted without errors */ /* Frames transmitted without errors */
case OID_GEN_XMIT_OK: case OID_GEN_XMIT_OK:
*INFBUF = rndis_stat.txok; *INFBUF = usb_eth_stat.txok;
break; break;
/* Frames received without errors */ /* Frames received without errors */
case OID_GEN_RCV_OK: case OID_GEN_RCV_OK:
*INFBUF = rndis_stat.rxok; *INFBUF = usb_eth_stat.rxok;
break; break;
/* Frames received with errors */ /* Frames received with errors */
case OID_GEN_RCV_ERROR: case OID_GEN_RCV_ERROR:
*INFBUF = rndis_stat.rxbad; *INFBUF = usb_eth_stat.rxbad;
break; break;
/* Frames transmitted with errors */ /* Frames transmitted with errors */
case OID_GEN_XMIT_ERROR: case OID_GEN_XMIT_ERROR:
*INFBUF = rndis_stat.txbad; *INFBUF = usb_eth_stat.txbad;
break; break;
/* Frames dropped due to lack of buffer space */ /* 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 CFGBUF ((rndis_config_parameter_t *) INFBUF)
#define PARMNAME ((uint8_t *)CFGBUF + CFGBUF->ParameterNameOffset) #define PARMNAME ((uint8_t *)CFGBUF + CFGBUF->ParameterNameOffset)
#define PARMVALUE ((uint8_t *)CFGBUF + CFGBUF->ParameterValueOffset) #define PARMVALUE ((uint8_t *)CFGBUF + CFGBUF->ParameterValueOffset)
#define PARMVALUELENGTH CFGBUF->ParameterValueLength
#define PARM_NAME_LENGTH 25 /* Maximum parameter name length */ #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 * \brief Function to deal with a RNDIS "SET" command present in the
* encapsulated_buffer * encapsulated_buffer
@ -664,13 +656,7 @@ void rndis_set_process(void)
Parameter type: single octet Parameter type: single octet
Parameter values: '0' = disabled, '1' = enabled Parameter values: '0' = disabled, '1' = enabled
*/ */
if (strncmp_P(parmname, PSTR("rawmode"), 7) == 0) { rndis_handle_config_parm(parmname,PARMVALUE,PARMVALUELENGTH);
if (*PARMVALUE == '0') {
usbstick_mode.raw = 0;
} else {
usbstick_mode.raw = 1;
}
}
break; break;
@ -700,6 +686,7 @@ void rndis_set_process(void)
case OID_802_3_MULTICAST_LIST: case OID_802_3_MULTICAST_LIST:
break; break;
#if USB_ETH_EMULATE_WIFI
/* Mandatory 802.11 OIDs */ /* Mandatory 802.11 OIDs */
case OID_802_11_BSSID: case OID_802_11_BSSID:
panid = *INFBUF; panid = *INFBUF;
@ -708,6 +695,7 @@ void rndis_set_process(void)
case OID_802_11_SSID: case OID_802_11_SSID:
break; break;
//TODO: rest of 802.11 //TODO: rest of 802.11
#endif // USB_ETH_EMULATE_WIFI
/* Power Managment: fails for now */ /* Power Managment: fails for now */
case OID_PNP_ADD_WAKE_UP_PATTERN: case OID_PNP_ADD_WAKE_UP_PATTERN:
@ -743,7 +731,7 @@ void rndis_set_process(void)
* the "SEND ENCAPSULATED COMMAND" message, which will trigger * the "SEND ENCAPSULATED COMMAND" message, which will trigger
* and interrupt on the host so it knows data is ready. * 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; U8 nb_byte, zlp, i;
@ -828,6 +816,261 @@ uint8_t rndis_send_status(rndis_Status_t stat)
return 0; 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 ****************/ /****************** Radio Interface ****************/
@ -837,15 +1080,11 @@ uint8_t rndis_send_status(rndis_Status_t stat)
*/ */
void rndis_packetFilter(uint32_t newfilter) void rndis_packetFilter(uint32_t newfilter)
{ {
#if !RF230BB
if (newfilter & NDIS_PACKET_TYPE_PROMISCUOUS) { if (newfilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
rxMode = RX_ON; USB_ETH_HOOK_SET_PROMISCIOUS_MODE(true);
radio_set_trx_state(RX_ON);
} else { } else {
rxMode = RX_AACK_ON; USB_ETH_HOOK_SET_PROMISCIOUS_MODE(false);
radio_set_trx_state(RX_AACK_ON);
} }
#endif
} }
/** @} */ /** @} */

View file

@ -303,22 +303,23 @@ typedef struct{
uint32_t rxok; uint32_t rxok;
uint32_t txbad; uint32_t txbad;
uint32_t rxbad; 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 rndis_state_t rndis_state;
extern uint8_t schedule_interrupt; extern uint8_t schedule_interrupt;
extern uint64_t rndis_ethernet_addr; uint8_t rndis_send_encapsulated_command(uint16_t wLength);
uint8_t rndis_get_encapsulated_command(void);
uint8_t send_encapsulated_command(uint16_t wLength);
uint8_t get_encapsulated_command(void);
void rndis_send_interrupt(void); void rndis_send_interrupt(void);
void rndis_query_process(void); void rndis_query_process(void);
void rndis_set_process(void); void rndis_set_process(void);
uint8_t rndis_send_status(rndis_Status_t stat); 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 #endif //_RNDIS_H

View file

@ -59,6 +59,9 @@
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#include <util/delay.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 BUF ((struct uip_eth_hdr *)&uip_buf[0])
#define PRINTF printf #define PRINTF printf
#define PRINTF_P printf_P #define PRINTF_P printf_P
@ -66,12 +69,6 @@
//_____ M A C R O S ________________________________________________________ //_____ 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_DETACH 900
#define RNDIS_TIMEOUT_ATTACH 1000 #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 ____________________________________________ //_____ 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 //! Timers for LEDs
uint8_t led1_timer, led2_timer; uint8_t led1_timer, led2_timer;
//! Temp data buffer when adding RNDIS headers uint8_t usb_eth_is_active = 1;
uint8_t data_buffer[64];
//! Usb is busy with RNDIS
char usb_busy = 0;
static struct etimer et; uint8_t usb_eth_packet_is_available() {
static struct timer flood_timer; 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 * \brief RNDIS Process
* *
* This is the link between USB and the "good stuff". In this routine data * 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(); PROCESS_BEGIN();
uint8_t bytecounter, headercounter;
uint16_t i, dataoffset;
clock_time_t timediff;
clock_time_t thetime;
while(1) { while(1) {
rxtx_led_update();
// turn off LED's if necessary #if USB_ETH_CONF_MASS_STORAGE_FALLBACK
if (led1_timer) led1_timer--; usb_eth_setup_timeout_fallback_check();
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
#endif #endif
switch(usb_configuration_nb) {
if(rndis_state == rndis_data_initialized) //Enumeration processs OK ? case USB_CONFIG_RNDIS_DEBUG:
{ case USB_CONFIG_RNDIS:
if (doInit) { if(Is_device_enumerated()) {
//start flood timer if(rndis_process()) {
timer_set(&flood_timer, CLOCK_SECOND / 5); etimer_set(&et, CLOCK_SECOND/80);
} else {
mac_ethernetSetup(); Led0_toggle();
doInit = 0; etimer_set(&et, CLOCK_SECOND/8);
}
//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;
}
} }
} }
break;
//Ack final data packet case USB_CONFIG_EEM:
Usb_ack_receive_out(); if(Is_device_enumerated())
cdc_eem_process();
//Packet has CRC, nobody wants that garbage etimer_set(&et, CLOCK_SECOND/80);
datalength -= 4; break;
case USB_CONFIG_ECM:
//Send data over RF or to local stack case USB_CONFIG_ECM_DEBUG:
uip_len = datalength; //uip_len includes LLH_LEN if(Is_device_enumerated()) {
mac_ethernetToLowpan(uip_buf); if(cdc_ecm_process()) {
etimer_set(&et, CLOCK_SECOND/80);
} //if (datalength) } else {
} //if(Is_usb_receive_out() && (uip_len == 0)) Led0_toggle();
} // if (Is_device_enumerated()) etimer_set(&et, CLOCK_SECOND/8);
}
if ((usb_mode == rndis_only) || (usb_mode == rndis_debug) || (usb_mode == eem)) { }
etimer_set(&et, CLOCK_SECOND/80); break;
} else { default:
etimer_set(&et, CLOCK_SECOND); 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) } // while(1)
PROCESS_END(); 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) uint8_t usb_eth_send(uint8_t * senddata, uint16_t sendlen, uint8_t led)
{ {
if (usb_mode == eem) uint8_t ret = 0;
return eem_send(senddata, sendlen, led);
if(!usb_eth_is_active) {
USB_ETH_HOOK_TX_ERROR("Inactive");
goto bail;
}
if ((usb_mode == rndis_only) || (usb_mode == rndis_debug)) //Check device is set up
return rndis_send(senddata, sendlen, led); 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; return 0;
} }
/** void
\brief Send a single ethernet frame using EEM usb_eth_get_mac_address(uint8_t dest[6]) {
*/ memcpy(dest,&usb_ethernet_addr,6);
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
\brief Send data over RNDIS interface, data is in uipbuf and length is uiplen usb_eth_set_mac_address(const uint8_t src[6]) {
*/ memcpy(&usb_ethernet_addr,src,6);
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;
} }
/**
@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;
}
/** @} */ /** @} */

View file

@ -52,22 +52,72 @@
#include "config.h" #include "config.h"
#include "../conf_usb.h"
//_____ M A C R O S ________________________________________________________ //_____ 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 ____________________________________________ //_____ 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_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 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);
/** @} */ /** @} */

View file

@ -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;
}
/** @} */

View file

@ -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_ */

View file

@ -45,7 +45,6 @@
#include "config.h" #include "config.h"
#include "usb_drv.h" #include "usb_drv.h"
#include "usb_descriptors.h" #include "usb_descriptors.h"
#include "serial/cdc_task.h"
#include "serial/uart_usb_lib.h" #include "serial/uart_usb_lib.h"
#include <stdio.h> #include <stdio.h>
@ -56,6 +55,26 @@
/*_____ M A C R O S ________________________________________________________*/ /*_____ 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 ________________________________________________*/ /*_____ D E F I N I T I O N ________________________________________________*/
Uchar tx_counter; Uchar tx_counter;
@ -64,22 +83,65 @@ S_line_coding line_coding;
/*_____ D E C L A R A T I O N ______________________________________________*/ /*_____ 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) int usb_stdout_putchar(char c, FILE *stream)
{ {
// send to USB port // Preserve the currently selected endpoint
// don't send anything if USB can't accept chars uint8_t uenum = UENUM;
Usb_select_endpoint(TX_EP);
if (!uart_usb_tx_ready()) // send to USB port
return 0; // don't send anything if USB can't accept chars
Usb_select_endpoint(VCP_TX_EP);
// turn on LED
vcptx_end_led(); 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; return 0;
} }
static FILE usb_stdout = FDEV_SETUP_STREAM(usb_stdout_putchar, static FILE usb_stdout = FDEV_SETUP_STREAM(usb_stdout_putchar,
NULL, 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 * @brief This function checks if the USB emission buffer is ready to accept at
* at least 1 byte * at least 1 byte
@ -109,6 +185,7 @@ void uart_usb_set_stdout(void)
*/ */
bit uart_usb_tx_ready(void) bit uart_usb_tx_ready(void)
{ {
Usb_select_endpoint(VCP_TX_EP);
if (!Is_usb_write_enabled()) if (!Is_usb_write_enabled())
{ {
return FALSE; return FALSE;
@ -127,16 +204,31 @@ bit uart_usb_tx_ready(void)
*/ */
int uart_usb_putchar(int data_to_send) int uart_usb_putchar(int data_to_send)
{ {
Usb_select_endpoint(VCP_TX_EP); // Preserve the currently selected endpoint
uint8_t uenum = UENUM;
if(!uart_usb_tx_ready()) return -1;
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); Usb_write_byte(data_to_send);
tx_counter++; tx_counter++;
if(!Is_usb_write_enabled()) //If Endpoint full -> flush
{ //If Endpoint full -> flush
uart_usb_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; return data_to_send;
} }
@ -149,6 +241,8 @@ bit uart_usb_test_hit(void)
{ {
if (!rx_counter) if (!rx_counter)
{ {
// Preserve the currently selected endpoint
uint8_t uenum = UENUM;
Usb_select_endpoint(VCP_RX_EP); Usb_select_endpoint(VCP_RX_EP);
if (Is_usb_receive_out()) if (Is_usb_receive_out())
{ {
@ -158,6 +252,8 @@ bit uart_usb_test_hit(void)
Usb_ack_receive_out(); Usb_ack_receive_out();
} }
} }
// Restore previously selected endpoint
UENUM = uenum;
} }
return (rx_counter!=0); return (rx_counter!=0);
} }
@ -174,15 +270,23 @@ char uart_usb_getchar(void)
{ {
register Uchar data_rx; register Uchar data_rx;
// Preserve the currently selected endpoint
uint8_t uenum = UENUM;
Usb_select_endpoint(VCP_RX_EP); Usb_select_endpoint(VCP_RX_EP);
if (!rx_counter) while (!uart_usb_test_hit()); if (!rx_counter) while (!uart_usb_test_hit());
data_rx=Usb_read_byte(); data_rx=Usb_read_byte();
rx_counter--; rx_counter--;
if (!rx_counter) Usb_ack_receive_out(); if (!rx_counter) Usb_ack_receive_out();
#if USB_CDC_ACM_CONF_LOCAL_ECHO
//Local echo //Local echo
uart_usb_putchar(data_rx); uart_usb_putchar(data_rx);
#endif
// Restore previously selected endpoint
UENUM = uenum;
return data_rx; return data_rx;
} }
@ -193,9 +297,16 @@ char uart_usb_getchar(void)
*/ */
void uart_usb_flush (void) void uart_usb_flush (void)
{ {
Usb_select_endpoint(VCP_TX_EP); // Preserve the currently selected endpoint
Usb_send_in(); uint8_t uenum = UENUM;
Usb_select_endpoint(VCP_TX_EP);
Usb_send_in();
tx_counter = 0; tx_counter = 0;
usb_endpoint_wait_for_write_enabled();
// Restore previously selected endpoint
UENUM = uenum;
} }
/** @} */ /** @} */

View file

@ -78,6 +78,10 @@ void uart_usb_flush(void);
bit uart_usb_test_hit(void); bit uart_usb_test_hit(void);
char uart_usb_getchar(void); char uart_usb_getchar(void);
void uart_usb_set_stdout(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();
/** @} **/ /** @} **/

View file

@ -55,17 +55,252 @@
#include "usb_drv.h" #include "usb_drv.h"
#include "usb_descriptors.h" #include "usb_descriptors.h"
#include "usb_specific_request.h" #include "usb_specific_request.h"
#include "rndis/rndis_task.h"
//_____ M A C R O S ________________________________________________________ //_____ 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 ________________________________________________ //_____ D E F I N I T I O N ________________________________________________
/************* COMPOSITE DEVICE DESCRIPTORS (using IAD) **********/ /************* 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 // usb_user_device_descriptor
FLASH S_usb_device_descriptor usb_dev_desc_composite = 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(VENDOR_ID)
, Usb_write_word_enum_struc(COMPOSITE_PRODUCT_ID) , Usb_write_word_enum_struc(COMPOSITE_PRODUCT_ID)
, Usb_write_word_enum_struc(RELEASE_NUMBER) , Usb_write_word_enum_struc(RELEASE_NUMBER)
, MAN_INDEX , USB_STRING_MAN
, PROD_INDEX , USB_STRING_PRODUCT
, SN_INDEX , USB_STRING_SERIAL
, NB_CONFIGURATION , (sizeof(usb_dev_config_order)/sizeof(*usb_dev_config_order))
}; };
// usb_user_configuration_descriptor FS // usb_user_configuration_descriptor FS
FLASH S_usb_user_configuration_descriptor_composite usb_conf_desc_composite = { FLASH S_usb_user_configuration_descriptor_composite usb_conf_desc_composite = {
{ sizeof(S_usb_configuration_descriptor) USB_CONFIG_DESC(
, CONFIGURATION_DESCRIPTOR sizeof(usb_conf_desc_composite),
, Usb_write_word_enum_struc(sizeof(S_usb_user_configuration_descriptor_composite)) COMPOSITE_NB_INTERFACE,
//, 0x0043 //TODO: Change to generic codewith sizeof USB_CONFIG_RNDIS_DEBUG,
, COMPOSITE_NB_INTERFACE USB_STRING_CONFIG_COMPOSITE,
, CONF_NB CONF_ATTRIBUTES,
, CONF_INDEX MAX_POWER
, CONF_ATTRIBUTES ),
, MAX_POWER
},//9
// --------------------------- IAD ---------------------------- USB_IAD(
{ // Interface Association Descriptor 0x00, // First interface
sizeof(S_usb_interface_association_descriptor), // bLength 0x02, // Interface count
DSC_TYPE_IAD, // bDescriptorType = 11 0x02, // Function Class
0x00, // bFirstInterface 0x02, // Function Subclass
0x02, // bInterfaceCount 0xFF, // Function Protocol
0x02, // bFunctionClass (Communication Class) USB_STRING_INTERFACE_RNDIS
0x02, // bFunctionSubClass (Abstract Control Model) ),RNDIS_INTERFACES,
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(
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 **************************/ /****************** NETWORK-ONLY DEVICE DESCRIPTORS **************************/
/*
FLASH S_usb_device_descriptor usb_dev_desc_network = FLASH S_usb_device_descriptor usb_dev_desc_network =
{ {
sizeof(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(VENDOR_ID)
, Usb_write_word_enum_struc(NETWORK_PRODUCT_ID) , Usb_write_word_enum_struc(NETWORK_PRODUCT_ID)
, Usb_write_word_enum_struc(RELEASE_NUMBER) , Usb_write_word_enum_struc(RELEASE_NUMBER)
, MAN_INDEX , USB_STRING_MAN
, PROD_INDEX , USB_STRING_PRODUCT
, SN_INDEX , USB_STRING_SERIAL
, NB_CONFIGURATION , NB_CONFIGURATION
}; };
*/
// usb_user_configuration_descriptor FS // usb_user_configuration_descriptor FS
FLASH S_usb_user_configuration_descriptor_network usb_conf_desc_network = { FLASH S_usb_user_configuration_descriptor_network usb_conf_desc_network = {
{ sizeof(S_usb_configuration_descriptor) USB_CONFIG_DESC(
, CONFIGURATION_DESCRIPTOR sizeof(usb_conf_desc_network),
, Usb_write_word_enum_struc(sizeof(S_usb_user_configuration_descriptor_network)) NETWORK_NB_INTERFACE,
//, 0x0043 //TODO: Change to generic codewith sizeof CONF_NB, // value
, NETWORK_NB_INTERFACE USB_STRING_CONFIG_RNDIS,
, CONF_NB CONF_ATTRIBUTES,
, CONF_INDEX MAX_POWER
, CONF_ATTRIBUTES ),
, MAX_POWER RNDIS_INTERFACES
},//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
}
}; };
/************* 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 **************************/ /****************** MASS-STORAGE DEVICE DESCRIPTORS **************************/
/*
FLASH S_usb_device_descriptor usb_dev_desc_mass = FLASH S_usb_device_descriptor usb_dev_desc_mass =
{ {
sizeof(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(VENDOR_ID)
, Usb_write_word_enum_struc(MASS_PRODUCT_ID) , Usb_write_word_enum_struc(MASS_PRODUCT_ID)
, Usb_write_word_enum_struc(RELEASE_NUMBER) , Usb_write_word_enum_struc(RELEASE_NUMBER)
, MAN_INDEX , USB_STRING_MAN
, PROD_INDEX , USB_STRING_PRODUCT
, SN_INDEX , USB_STRING_SERIAL
, NB_CONFIGURATION , NB_CONFIGURATION
}; };
*/
#if USB_CONF_STORAGE
// usb_user_configuration_descriptor FS // usb_user_configuration_descriptor FS
FLASH S_usb_user_configuration_descriptor_mass usb_conf_desc_mass = { 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)) , Usb_write_word_enum_struc(sizeof(S_usb_user_configuration_descriptor_mass))
, MASS_NB_INTERFACE , MASS_NB_INTERFACE
, CONF_NB , CONF_NB
, CONF_INDEX , USB_STRING_CONFIG_MS
, CONF_ATTRIBUTES , CONF_ATTRIBUTES
, MAX_POWER , MAX_POWER
},//9 },//9
@ -423,7 +516,7 @@ FLASH S_usb_user_configuration_descriptor_mass usb_conf_desc_mass = {
, MS_INTERFACE_CLASS , MS_INTERFACE_CLASS
, MS_INTERFACE_SUB_CLASS , MS_INTERFACE_SUB_CLASS
, MS_INTERFACE_PROTOCOL , MS_INTERFACE_PROTOCOL
, MS_INTERFACE_INDEX , USB_STRING_INTERFACE_MS
} //9 } //9
, ,
{ sizeof(S_usb_endpoint_descriptor) { sizeof(S_usb_endpoint_descriptor)
@ -443,96 +536,11 @@ FLASH S_usb_user_configuration_descriptor_mass usb_conf_desc_mass = {
} }
}; };
/************* EEM-ONLY ***************/ #endif
// 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
};
/************* COMMON *****************/ /************* 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 // 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) PGM_VOID_P Usb_get_dev_desc_pointer(void)
{ {
return &(usb_dev_desc_composite.bLength);
/*
if (usb_mode == rndis_only) if (usb_mode == rndis_only)
return &(usb_dev_desc_network.bLength); 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_eem.bLength);
return &(usb_dev_desc_mass.bLength); return &(usb_dev_desc_mass.bLength);
*/
} }
U8 Usb_get_dev_desc_length(void) U8 Usb_get_dev_desc_length(void)
{ {
return sizeof(usb_dev_desc_composite);
/*
if (usb_mode == rndis_only) if (usb_mode == rndis_only)
return sizeof(usb_dev_desc_network); 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_eem);
return sizeof(usb_dev_desc_mass); 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); switch(pgm_read_byte_near(&usb_dev_config_order[index])) {
case USB_CONFIG_ECM:
if (usb_mode == rndis_debug) return &(usb_conf_desc_ecm.cfg.bLength);
return &(usb_conf_desc_composite.cfg.bLength); case USB_CONFIG_ECM_DEBUG:
return &(usb_conf_desc_ecm_debug.cfg.bLength);
if (usb_mode == eem) case USB_CONFIG_RNDIS_DEBUG:
return &(usb_conf_desc_eem.cfg.bLength); return &(usb_conf_desc_composite.cfg.bLength);
case USB_CONFIG_RNDIS:
return &(usb_conf_desc_mass.cfg.bLength); 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)
{ {
switch(pgm_read_byte_near(&usb_dev_config_order[index])) {
if (usb_mode == rndis_only) case USB_CONFIG_ECM:
return sizeof (usb_conf_desc_network); return sizeof(usb_conf_desc_ecm);
case USB_CONFIG_ECM_DEBUG:
if (usb_mode == rndis_debug) return sizeof(usb_conf_desc_ecm_debug);
return sizeof(usb_conf_desc_composite); case USB_CONFIG_RNDIS_DEBUG:
return sizeof(usb_conf_desc_composite);
if (usb_mode == eem) case USB_CONFIG_RNDIS:
return sizeof(usb_conf_desc_eem); return sizeof (usb_conf_desc_network);
case USB_CONFIG_EEM:
return sizeof(usb_conf_desc_mass); return sizeof(usb_conf_desc_eem);
#if USB_CONF_STORAGE
case USB_CONFIG_MS:
return sizeof(usb_conf_desc_mass);
#endif
default:
return 0;
}
} }
/** @} */ /** @} */

View file

@ -66,9 +66,9 @@
// USB Device descriptor // USB Device descriptor
#define USB_SPECIFICATION 0x0200 #define USB_SPECIFICATION 0x0200
#define COMPOSITE_DEVICE_CLASS 0xEF // Misc #define COMPOSITE_DEVICE_CLASS 0x02 // Misc
#define COMPOSITE_DEVICE_SUB_CLASS 0x02 // Common #define COMPOSITE_DEVICE_SUB_CLASS 0x00 // Common
#define COMPOSITE_DEVICE_PROTOCOL 0x01 // IAD #define COMPOSITE_DEVICE_PROTOCOL 0x00 // IAD
#define NETWORK_DEVICE_CLASS 0x02 // CDC ACM #define NETWORK_DEVICE_CLASS 0x02 // CDC ACM
#define NETWORK_DEVICE_SUB_CLASS 0x02 // #define NETWORK_DEVICE_SUB_CLASS 0x02 //
@ -88,10 +88,49 @@
#define NETWORK_PRODUCT_ID 0x2019 //Product ID for just RNDIS device #define NETWORK_PRODUCT_ID 0x2019 //Product ID for just RNDIS device
#define MASS_PRODUCT_ID 0x202F //Product ID for mass storage #define MASS_PRODUCT_ID 0x202F //Product ID for mass storage
#define RELEASE_NUMBER 0x1000 #define RELEASE_NUMBER 0x1000
#define MAN_INDEX 0x01
#define PROD_INDEX 0x02 enum {
#define SN_INDEX 0x03 USB_STRING_NONE = 0,
#define NB_CONFIGURATION 1 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 NETWORK_NB_INTERFACE 2
#define COMPOSITE_NB_INTERFACE 4 #define COMPOSITE_NB_INTERFACE 4
@ -134,14 +173,14 @@
#define ENDPOINT_NB_2 0x80 | TX_EP #define ENDPOINT_NB_2 0x80 | TX_EP
#define EP_ATTRIBUTES_2 0x02 // BULK = 0x02, INTERUPT = 0x03 #define EP_ATTRIBUTES_2 0x02 // BULK = 0x02, INTERUPT = 0x03
#define EP_SIZE_2 0x40 //64 byte max size #define EP_SIZE_2 0x40 //64 byte max size
#define EP_INTERVAL_2 0x00 #define EP_INTERVAL_2 0x01
// USB Endpoint 2 descriptor // USB Endpoint 2 descriptor
//Bulk OUT RX endpoint //Bulk OUT RX endpoint
#define ENDPOINT_NB_3 RX_EP #define ENDPOINT_NB_3 RX_EP
#define EP_ATTRIBUTES_3 0x02 // BULK = 0x02, INTERUPT = 0x03 #define EP_ATTRIBUTES_3 0x02 // BULK = 0x02, INTERUPT = 0x03
#define EP_SIZE_3 0x40 //64 byte max size #define EP_SIZE_3 0x40 //64 byte max size
#define EP_INTERVAL_3 0x00 #define EP_INTERVAL_3 0x01
/*** CDC Virtual Serial Port ***/ /*** CDC Virtual Serial Port ***/
@ -176,14 +215,14 @@
#define ENDPOINT_NB_5 0x80 | VCP_TX_EP #define ENDPOINT_NB_5 0x80 | VCP_TX_EP
#define EP_ATTRIBUTES_5 0x02 // BULK = 0x02, INTERUPT = 0x03 #define EP_ATTRIBUTES_5 0x02 // BULK = 0x02, INTERUPT = 0x03
#define EP_SIZE_5 0x20 #define EP_SIZE_5 0x20
#define EP_INTERVAL_5 0x00 #define EP_INTERVAL_5 0x01
// USB Endpoint 6 descriptor // USB Endpoint 6 descriptor
// Bulk OUT // Bulk OUT
#define ENDPOINT_NB_6 VCP_RX_EP #define ENDPOINT_NB_6 VCP_RX_EP
#define EP_ATTRIBUTES_6 0x02 // BULK = 0x02, INTERUPT = 0x03 #define EP_ATTRIBUTES_6 0x02 // BULK = 0x02, INTERUPT = 0x03
#define EP_SIZE_6 0x20 #define EP_SIZE_6 0x20
#define EP_INTERVAL_6 0x00 #define EP_INTERVAL_6 0x01
/*** Mass Storage ***/ /*** Mass Storage ***/
@ -227,61 +266,34 @@
#define EEM_ENDPOINT_NB_1 0x80 | TX_EP #define EEM_ENDPOINT_NB_1 0x80 | TX_EP
#define EEM_EP_ATTRIBUTES_1 0x02 // BULK = 0x02, INTERUPT = 0x03 #define EEM_EP_ATTRIBUTES_1 0x02 // BULK = 0x02, INTERUPT = 0x03
#define EEM_EP_SIZE_1 0x40 //64 byte max size #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 // USB Endpoint 2 descriptor
// Bulk OUT // Bulk OUT
#define EEM_ENDPOINT_NB_2 RX_EP #define EEM_ENDPOINT_NB_2 RX_EP
#define EEM_EP_ATTRIBUTES_2 0x02 // BULK = 0x02, INTERUPT = 0x03 #define EEM_EP_ATTRIBUTES_2 0x02 // BULK = 0x02, INTERUPT = 0x03
#define EEM_EP_SIZE_2 0x40 //64 byte max size #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 DEVICE_STATUS 0x00 // TBD
#define INTERFACE_STATUS 0x00 // TBD #define INTERFACE_STATUS 0x00 // TBD
#define LANG_ID 0x00 #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 #define LANGUAGE_ID 0x0409
//! Usb Request //! Usb Request
@ -373,39 +385,6 @@ typedef struct {
} S_usb_language_id; } 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 _______________________________________________________*/ /*_____ U S B I A D _______________________________________________________*/
#define DSC_TYPE_IAD 11 #define DSC_TYPE_IAD 11
@ -460,6 +439,79 @@ typedef struct
} S_usb_user_configuration_descriptor_network; } 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 */ /* Mass Storage */
typedef struct typedef struct
@ -471,20 +523,12 @@ typedef struct
} S_usb_user_configuration_descriptor_mass; } 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); PGM_VOID_P Usb_get_dev_desc_pointer(void);
U8 Usb_get_dev_desc_length(void); U8 Usb_get_dev_desc_length(void);
PGM_VOID_P Usb_get_conf_desc_pointer(void) ; PGM_VOID_P Usb_get_conf_desc_pointer(U8 index) ;
U8 Usb_get_conf_desc_length(void); U8 Usb_get_conf_desc_length(U8 index);
#endif // _USB_USERCONFIG_H_ #endif // _USB_USERCONFIG_H_

View file

@ -50,6 +50,7 @@
#include "config.h" #include "config.h"
#include "conf_usb.h" #include "conf_usb.h"
#include "usb_drv.h" #include "usb_drv.h"
#include <util/delay.h>
//_____ M A C R O S ________________________________________________________ //_____ M A C R O S ________________________________________________________
@ -61,6 +62,102 @@
#if (USB_DEVICE_FEATURE == ENABLED) #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. //! usb_configure_endpoint.
//! //!
//! This function configures an endpoint with the selected type. //! This function configures an endpoint with the selected type.

View file

@ -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 //! @defgroup Endpoints_configuration Configuration macros for endpoints
//! List of the standard macro used to configure pipes and 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_build_ep_config1(size, bank ) ((size<<4) | (bank<<2) )
#define usb_configure_endpoint(num, type, dir, size, bank, nyet) \ #define usb_configure_endpoint(num, type, dir, size, bank, nyet) \
( Usb_select_endpoint(num), \ ( Usb_select_endpoint(num), \
@ -929,6 +929,13 @@ U8 host_determine_pipe_size (U16);
void host_disable_all_pipe (void); void host_disable_all_pipe (void);
U8 usb_get_nb_pipe_interrupt (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_ #endif // _USB_DRV_H_
/** @} */ /** @} */

View file

@ -50,10 +50,12 @@
#include "usb_descriptors.h" #include "usb_descriptors.h"
#include "usb_specific_request.h" #include "usb_specific_request.h"
#include "rndis/rndis_protocol.h" #include "rndis/rndis_protocol.h"
#include "rndis/cdc_ecm.h"
#include "serial/uart_usb_lib.h" #include "serial/uart_usb_lib.h"
#include "storage/ctrl_access.h" #include "storage/ctrl_access.h"
#include "uip.h" #include "uip.h"
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <string.h> #include <string.h>
//_____ M A C R O S ________________________________________________________ //_____ M A C R O S ________________________________________________________
@ -85,30 +87,44 @@ Bool usb_user_read_request(U8 type, U8 request)
{ {
U16 wLength; U16 wLength;
//Both protocols have two bytes we throw away
Usb_read_byte();
Usb_read_byte();
switch(request) switch(request)
{ {
case SEND_ENCAPSULATED_COMMAND: case SEND_ENCAPSULATED_COMMAND:
Usb_read_byte();
Usb_read_byte();
Usb_read_byte();//wIndex LSB Usb_read_byte();//wIndex LSB
Usb_read_byte();//wIndex MSB Usb_read_byte();//wIndex MSB
LSB(wLength) = Usb_read_byte(); LSB(wLength) = Usb_read_byte();
MSB(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; break;
case GET_ENCAPSULATED_COMMAND: case GET_ENCAPSULATED_COMMAND:
Usb_read_byte();
Usb_read_byte();
Usb_read_byte();//wIndex LSB Usb_read_byte();//wIndex LSB
Usb_read_byte();//wIndex MSB Usb_read_byte();//wIndex MSB
LSB(wLength) = Usb_read_byte(); LSB(wLength) = Usb_read_byte();
MSB(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; 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 #if USB_CONF_STORAGE
case MASS_STORAGE_RESET: case MASS_STORAGE_RESET:
Usb_ack_receive_setup(); 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 /* 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 */ advertise that we support nothing, so shouldn't get them anyway */
case GET_LINE_CODING: case GET_LINE_CODING:
cdc_get_line_coding(); Usb_read_byte();
return TRUE; Usb_read_byte();
if(USB_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) {
cdc_get_line_coding();
return TRUE;
} else {
return FALSE;
}
break; break;
case SET_LINE_CODING: case SET_LINE_CODING:
cdc_set_line_coding(); Usb_read_byte();
return TRUE; Usb_read_byte();
if(USB_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) {
cdc_set_line_coding();
return TRUE;
} else {
return FALSE;
}
break; break;
case SET_CONTROL_LINE_STATE: case SET_CONTROL_LINE_STATE:
cdc_set_control_line_state(); if(USB_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) {
return TRUE; cdc_set_control_line_state();
return TRUE;
} else {
return FALSE;
}
break; break;
#endif /* USB_CONF_CDC */ #endif /* USB_CONF_CDC */
default: default:
@ -174,21 +206,6 @@ Bool usb_user_get_descriptor(U8 type, U8 string)
pbuffer = &(usb_user_language_id.bLength); pbuffer = &(usb_user_language_id.bLength);
return TRUE; return TRUE;
break; 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: default:
return FALSE; return FALSE;
} }
@ -198,6 +215,94 @@ Bool usb_user_get_descriptor(U8 type, U8 string)
return FALSE; 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. //! usb_user_endpoint_init.
//! //!
@ -206,115 +311,54 @@ Bool usb_user_get_descriptor(U8 type, U8 string)
//! @param conf_nb Not used //! @param conf_nb Not used
void usb_user_endpoint_init(U8 conf_nb) 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 */ switch(conf_nb) {
if ((usb_mode == rndis_only) || (usb_mode == rndis_debug)) { case USB_CONFIG_ECM:
case USB_CONFIG_ECM_DEBUG:
cdc_ecm_configure_endpoints();
break;
usb_configure_endpoint(INT_EP, \ case USB_CONFIG_RNDIS_DEBUG:
TYPE_INTERRUPT, \ case USB_CONFIG_RNDIS:
DIRECTION_IN, \ rndis_configure_endpoints();
SIZE_64, \ break;
ONE_BANK, \ case USB_CONFIG_EEM:
NYET_ENABLED); cdc_ecm_configure_endpoints();
usb_configure_endpoint(TX_EP, \ break;
TYPE_BULK, \ #if USB_CONF_STORAGE
DIRECTION_IN, \ case USB_CONFIG_MS:
SIZE_64, \ usb_configure_endpoint(VCP_INT_EP, \
TWO_BANKS, \ TYPE_INTERRUPT, \
NYET_ENABLED); DIRECTION_IN, \
SIZE_32, \
ONE_BANK, \
NYET_ENABLED);
usb_configure_endpoint(RX_EP, \ usb_configure_endpoint(VCP_TX_EP, \
TYPE_BULK, \ TYPE_BULK, \
DIRECTION_OUT, \ DIRECTION_IN, \
SIZE_64, \ SIZE_32, \
TWO_BANKS, \ TWO_BANKS, \
NYET_ENABLED); NYET_ENABLED);
} usb_configure_endpoint(VCP_RX_EP, \
TYPE_BULK, \
/* If we use virtual comm port (VCP) endpoints */ DIRECTION_OUT, \
if (usb_mode == rndis_debug) { SIZE_32, \
usb_configure_endpoint(VCP_INT_EP, \ TWO_BANKS, \
TYPE_INTERRUPT, \ NYET_ENABLED);
DIRECTION_IN, \ Usb_reset_endpoint(VCP_INT_EP);
SIZE_32, \ Usb_reset_endpoint(VCP_TX_EP);
ONE_BANK, \ Usb_reset_endpoint(VCP_RX_EP);
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);
}
break;
#endif
}
Led0_on();
} }
#if USB_CONF_CDC #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.bParityType);
Usb_write_byte(line_coding.bDataBits); Usb_write_byte(line_coding.bDataBits);
Usb_send_control_in(); Usb_send_control_in();
while(!(Is_usb_read_control_enabled()));
//Usb_clear_tx_complete();
while(!Is_usb_receive_out());
Usb_ack_receive_out();
} }
@ -352,19 +391,20 @@ void cdc_get_line_coding(void)
//! //!
void cdc_set_line_coding (void) void cdc_set_line_coding (void)
{ {
Usb_ack_receive_setup(); Usb_ack_receive_setup();
while (!(Is_usb_receive_out())); if(usb_endpoint_wait_for_receive_out()==0) {
LSB0(line_coding.dwDTERate) = Usb_read_byte(); LSB0(line_coding.dwDTERate) = Usb_read_byte();
LSB1(line_coding.dwDTERate) = Usb_read_byte(); LSB1(line_coding.dwDTERate) = Usb_read_byte();
LSB2(line_coding.dwDTERate) = Usb_read_byte(); LSB2(line_coding.dwDTERate) = Usb_read_byte();
LSB3(line_coding.dwDTERate) = Usb_read_byte(); LSB3(line_coding.dwDTERate) = Usb_read_byte();
line_coding.bCharFormat = Usb_read_byte(); line_coding.bCharFormat = Usb_read_byte();
line_coding.bParityType = Usb_read_byte(); line_coding.bParityType = Usb_read_byte();
line_coding.bDataBits = Usb_read_byte(); line_coding.bDataBits = Usb_read_byte();
Usb_ack_receive_out(); Usb_ack_receive_out();
Usb_send_control_in(); // send a ZLP for STATUS phase Usb_send_control_in(); // send a ZLP for STATUS phase
while(!(Is_usb_read_control_enabled())); usb_endpoint_wait_for_read_control_enabled();
}
} }
//! cdc_set_control_line_state. //! cdc_set_control_line_state.
@ -375,8 +415,27 @@ void cdc_set_line_coding (void)
//! //!
void cdc_set_control_line_state (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_ack_receive_setup();
Usb_send_control_in(); 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 */ #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;
}

View file

@ -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_composite usb_conf_desc_composite;
extern FLASH S_usb_user_configuration_descriptor_network usb_conf_desc_network; 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_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; 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_read_request(U8, U8);
Bool usb_user_get_descriptor(U8 , U8); Bool usb_user_get_descriptor(U8 , U8);
void usb_user_endpoint_init(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_get_line_coding();
void cdc_set_line_coding(); void cdc_set_line_coding();

View file

@ -52,11 +52,14 @@
#include "usb_drv.h" #include "usb_drv.h"
#include "usb_descriptors.h" #include "usb_descriptors.h"
#include "usb_specific_request.h" #include "usb_specific_request.h"
#include <string.h>
//_____ M A C R O S ________________________________________________________ //_____ M A C R O S ________________________________________________________
//_____ D E F I N I T I O N ________________________________________________ //_____ 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 ______________________________ //_____ 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: case GET_DESCRIPTOR:
if (0x80 == bmRequestType) { usb_get_descriptor(); } if (0x80 == bmRequestType) { usb_get_descriptor(); }
else { usb_user_read_request(bmRequestType, bmRequest); } else goto user_read;
break; break;
case GET_CONFIGURATION: case GET_CONFIGURATION:
if (0x80 == bmRequestType) { usb_get_configuration(); } if (0x80 == bmRequestType) { usb_get_configuration(); }
else { usb_user_read_request(bmRequestType, bmRequest); } else goto user_read;
break; break;
case SET_ADDRESS: case SET_ADDRESS:
if (0x00 == bmRequestType) { usb_set_address(); } if (0x00 == bmRequestType) { usb_set_address(); }
else { usb_user_read_request(bmRequestType, bmRequest); } else goto user_read;
break; break;
case SET_CONFIGURATION: case SET_CONFIGURATION:
if (0x00 == bmRequestType) { usb_set_configuration(); } if (0x00 == bmRequestType) { usb_set_configuration(); }
else { usb_user_read_request(bmRequestType, bmRequest); } else goto user_read;
break; break;
case CLEAR_FEATURE: case CLEAR_FEATURE:
if (0x02 >= bmRequestType) { usb_clear_feature(); } if (0x02 >= bmRequestType) { usb_clear_feature(); }
else { usb_user_read_request(bmRequestType, bmRequest); } else goto user_read;
break; break;
case SET_FEATURE: case SET_FEATURE:
if (0x02 >= bmRequestType) { usb_set_feature(); } if (0x02 >= bmRequestType) { usb_set_feature(); }
else { usb_user_read_request(bmRequestType, bmRequest); } else goto user_read;
break; break;
case GET_STATUS: case GET_STATUS:
if ((0x7F < bmRequestType) & (0x82 >= bmRequestType)) if ((0x7F < bmRequestType) & (0x82 >= bmRequestType))
{ usb_get_status(); } { usb_get_status(); }
else { usb_user_read_request(bmRequestType, bmRequest); } else goto user_read;
break; break;
case GET_INTERFACE: case GET_INTERFACE:
if (bmRequestType == 0x81) { usb_get_interface(); } if (bmRequestType == 0x81) { usb_get_interface(); }
else { usb_user_read_request(bmRequestType, bmRequest); } else goto user_read;
break; break;
@ -170,14 +173,23 @@ void usb_process_request(void)
case SET_DESCRIPTOR: case SET_DESCRIPTOR:
case SYNCH_FRAME: case SYNCH_FRAME:
default: //!< un-supported request => call to user read request default: //!< un-supported request => call to user read request
if(usb_user_read_request(bmRequestType, bmRequest) == FALSE) user_read:
{ usb_user_read_request(bmRequestType, bmRequest);
Usb_enable_stall_handshake();
Usb_ack_receive_setup();
return;
}
break; 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. //! usb_set_address.
@ -214,26 +226,205 @@ U8 configuration_number;
configuration_number = Usb_read_byte(); configuration_number = Usb_read_byte();
if (configuration_number <= NB_CONFIGURATION) // TODO: Verify configuration_number!
{ Usb_ack_receive_setup();
Usb_ack_receive_setup(); usb_configuration_nb = configuration_number;
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;
}
Usb_send_control_in(); //!< send a ZLP for STATUS phase 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_user_endpoint_init(usb_configuration_nb); //!< endpoint configuration
Usb_set_configuration_action(); 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. //! usb_get_descriptor.
//! //!
//! This function manages the GET DESCRIPTOR request. The device descriptor, //! This function manages the GET DESCRIPTOR request. The device descriptor,
@ -246,91 +437,93 @@ U8 configuration_number;
//! //!
void usb_get_descriptor(void) void usb_get_descriptor(void)
{ {
U8 LSBwLength, MSBwLength; U8 LSBwLength, MSBwLength;
U8 descriptor_type ; U8 descriptor_type ;
U8 string_type ; U8 string_type ;
U8 dummy; U8 dummy;
U8 nb_byte;
zlp = FALSE; /* no zero length packet */ zlp = FALSE; /* no zero length packet */
string_type = Usb_read_byte(); /* read LSB of wValue */ string_type = Usb_read_byte(); /* read LSB of wValue */
descriptor_type = Usb_read_byte(); /* read MSB of wValue */ descriptor_type = Usb_read_byte(); /* read MSB of wValue */
dummy = Usb_read_byte(); //!< don't care of wIndex field switch (descriptor_type)
dummy = Usb_read_byte(); {
LSBwLength = Usb_read_byte(); //!< read wLength case DEVICE_DESCRIPTOR:
MSBwLength = Usb_read_byte(); 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) dummy = Usb_read_byte(); //!< don't care of wIndex field
{ dummy = Usb_read_byte();
case DEVICE_DESCRIPTOR: LSBwLength = Usb_read_byte(); //!< read wLength
data_to_transfer = Usb_get_dev_desc_length(); //!< sizeof (usb_user_device_descriptor); MSBwLength = Usb_read_byte();
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;
}
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)) LSBwLength = data_to_transfer;
{ MSBwLength = 0x00;
if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; } } else {
else { zlp = FALSE; } //!< no need of zero length packet 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; //! Send data until necessary
MSBwLength = 0x00; while(data_to_transfer != 0) {
} // if(Is_usb_write_enabled()) //!< Check endpoint 0 size
else if(nb_byte++==EP_CONTROL_LENGTH) //!< Check endpoint 0 size
{ break;
data_to_transfer = LSBwLength; //!< send only requested number of data
}
Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++));
data_to_transfer --;
while((data_to_transfer != 0) && (!Is_usb_receive_out())) }
{ Usb_send_control_in();
while(!Is_usb_read_control_enabled()); }
nb_byte=0; if(Is_usb_receive_out()) {
while(data_to_transfer != 0) //!< Send data until necessary //! abort from Host
{ Usb_ack_receive_out();
if(nb_byte++==EP_CONTROL_LENGTH) //!< Check endpoint 0 size return;
{ }
break;
} if(zlp == TRUE) {
if(usb_endpoint_wait_for_read_control_enabled()!=0) {
Usb_enable_stall_handshake();
return;
}
Usb_send_control_in();
}
//#ifndef AVRGCC usb_endpoint_wait_for_receive_out();
// Usb_write_byte(*pbuffer++); Usb_ack_receive_out();
//#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_get_configuration. //! usb_get_configuration.
@ -345,9 +538,9 @@ void usb_get_configuration(void)
Usb_ack_receive_setup(); Usb_ack_receive_setup();
Usb_write_byte(usb_configuration_nb); 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(); Usb_ack_receive_out();
} }
@ -390,7 +583,7 @@ U8 dummy;
Usb_write_byte(0x00); Usb_write_byte(0x00);
Usb_send_control_in(); Usb_send_control_in();
while( !Is_usb_receive_out() ); usb_endpoint_wait_for_receive_out();
Usb_ack_receive_out(); Usb_ack_receive_out();
} }
@ -409,10 +602,6 @@ U8 dummy;
if (bmRequestType == INTERFACE_TYPE) 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; return;
} }
else if (bmRequestType == ENDPOINT_TYPE) else if (bmRequestType == ENDPOINT_TYPE)
@ -426,8 +615,6 @@ U8 dummy;
if (wIndex == EP_CONTROL) if (wIndex == EP_CONTROL)
{ {
Usb_enable_stall_handshake();
Usb_ack_receive_setup();
return; return;
} }
@ -443,15 +630,11 @@ U8 dummy;
else else
{ {
Usb_select_endpoint(EP_CONTROL); Usb_select_endpoint(EP_CONTROL);
Usb_enable_stall_handshake();
Usb_ack_receive_setup();
return; return;
} }
} }
else else
{ {
Usb_enable_stall_handshake();
Usb_ack_receive_setup();
return; return;
} }
} }
@ -471,18 +654,10 @@ U8 dummy;
if (bmRequestType == ZERO_TYPE) 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; return;
} }
else if (bmRequestType == INTERFACE_TYPE) 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; return;
} }
else if (bmRequestType == ENDPOINT_TYPE) else if (bmRequestType == ENDPOINT_TYPE)
@ -507,19 +682,15 @@ U8 dummy;
endpoint_status[wIndex] = 0x00; endpoint_status[wIndex] = 0x00;
Usb_ack_receive_setup(); Usb_ack_receive_setup();
Usb_send_control_in(); Usb_send_control_in();
} }
else else
{ {
Usb_select_endpoint(EP_CONTROL);
Usb_enable_stall_handshake();
Usb_ack_receive_setup();
return; return;
} }
} }
else else
{ {
Usb_enable_stall_handshake();
Usb_ack_receive_setup();
return; return;
} }
} }
@ -533,8 +704,7 @@ U8 dummy;
//! //!
void usb_get_interface (void) void usb_get_interface (void)
{ {
Usb_enable_stall_handshake(); // Not yet implemented.
Usb_ack_receive_setup();
} }
//! usb_set_interface. //! usb_set_interface.
@ -545,7 +715,21 @@ void usb_get_interface (void)
//! //!
void usb_set_interface (void) void usb_set_interface (void)
{ {
Usb_ack_receive_setup(); U8 alt_setting;
Usb_send_control_in(); //!< send a ZLP for STATUS phase U8 dummy;
while(!Is_usb_in_ready()); 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();
}
} }

View file

@ -166,53 +166,44 @@ void usb_start_device (void)
*/ */
static void pollhandler(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 //Linux is a bunch of lies, and won't read
//and screw up the data transfers //the interrupt endpoint. Hence if this isn't ready just exit
if (!usb_busy) { //while(!Is_usb_write_enabled());
/* Check for setup packets */ if (Is_usb_write_enabled()) {
Usb_select_endpoint(EP_CONTROL);
if (Is_usb_receive_setup()) { // Only valid interrupt is:
usb_process_request(); // 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 /* Continue polling */
out something to the RNDIS interrupt endpoint */ process_poll(&usb_process);
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);
} }
/** /**

View file

@ -28,7 +28,7 @@
* *
* This file is part of the Contiki operating system. * This file is part of the Contiki operating system.
* *
* @(#)$Id: rf230bb.c,v 1.11 2010/06/18 15:44:53 dak664 Exp $ * @(#)$Id: rf230bb.c,v 1.12 2010/09/17 21:59:09 dak664 Exp $
*/ */
/* /*
* This code is almost device independent and should be easy to port. * This code is almost device independent and should be easy to port.
@ -56,20 +56,6 @@
#include "net/rime/rimestats.h" #include "net/rime/rimestats.h"
#include "net/netstack.h" #include "net/netstack.h"
#if JACKDAW
#include "sicslow_ethernet.h"
#include "uip.h"
#include "uip_arp.h" //For ethernet header structure
#define ETHBUF(x) ((struct uip_eth_hdr *)x)
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
/* 6lowpan max size + ethernet header size + 1 */
static uint8_t raw_buf[127+ UIP_LLH_LEN +1];
extern uint8_t mac_createEthernetAddr(uint8_t * ethernet, uip_lladdr_t * lowpan);
extern rimeaddr_t macLongAddr;
#include "rndis/rndis_task.h"
#endif
#include "sys/timetable.h" #include "sys/timetable.h"
#define WITH_SEND_CCA 0 #define WITH_SEND_CCA 0
@ -91,17 +77,19 @@ extern rimeaddr_t macLongAddr;
#define RF230_CONF_AUTOACK 1 #define RF230_CONF_AUTOACK 1
#endif /* RF230_CONF_AUTOACK */ #endif /* RF230_CONF_AUTOACK */
#if RF230_CONF_AUTOACK
static bool is_promiscuous;
#endif
#ifndef RF230_CONF_AUTORETRIES #ifndef RF230_CONF_AUTORETRIES
#define RF230_CONF_AUTORETRIES 2 #define RF230_CONF_AUTORETRIES 2
#endif /* RF230_CONF_AUTOACK */ #endif /* RF230_CONF_AUTOACK */
//Automatic and manual CRC both append 2 bytes to packets //Automatic and manual CRC both append 2 bytes to packets
#if RF230_CONF_CHECKSUM #if RF230_CONF_CHECKSUM || defined(RF230BB_HOOK_TX_PACKET)
#include "lib/crc16.h" #include "lib/crc16.h"
#define CHECKSUM_LEN 2
#else
#define CHECKSUM_LEN 2
#endif /* RF230_CONF_CHECKSUM */ #endif /* RF230_CONF_CHECKSUM */
#define CHECKSUM_LEN 2
#define AUX_LEN (CHECKSUM_LEN + TIMESTAMP_LEN + FOOTER_LEN) #define AUX_LEN (CHECKSUM_LEN + TIMESTAMP_LEN + FOOTER_LEN)
@ -212,7 +200,7 @@ const struct radio_driver rf230_driver =
}; };
uint8_t RF230_receive_on,RF230_sleeping; uint8_t RF230_receive_on,RF230_sleeping;
static int channel; static uint8_t channel;
/* Received frames are buffered to rxframe in the interrupt routine in hal.c */ /* Received frames are buffered to rxframe in the interrupt routine in hal.c */
hal_rx_frame_t rxframe; hal_rx_frame_t rxframe;
@ -424,6 +412,33 @@ radio_set_trx_state(uint8_t new_state)
return set_state_status; return set_state_status;
} }
void
rf230_set_promiscuous_mode(bool isPromiscuous) {
if(isPromiscuous) {
is_promiscuous = true;
#if RF230_CONF_AUTOACK
radio_set_trx_state(RX_ON);
#endif
} else {
is_promiscuous = false;
#if RF230_CONF_AUTOACK
radio_set_trx_state(RX_AACK_ON);
#endif
}
}
bool
rf230_is_ready_to_send() {
switch(radio_get_trx_state()) {
case BUSY_TX:
case BUSY_TX_ARET:
return false;
}
return true;
}
static void static void
flushrx(void) flushrx(void)
{ {
@ -436,20 +451,9 @@ static void
on(void) on(void)
{ {
ENERGEST_ON(ENERGEST_TYPE_LISTEN); ENERGEST_ON(ENERGEST_TYPE_LISTEN);
#if JACKDAW
//blue=0 red=1 green=2 yellow=3 #ifdef RF230BB_HOOK_RADIO_ON
#define Led0_on() (PORTD |= 0x80) RF230BB_HOOK_RADIO_ON();
#define Led1_on() (PORTD &= ~0x20)
#define Led2_on() (PORTE &= ~0x80)
#define Led3_on() (PORTE &= ~0x40)
#define Led0_off() (PORTD &= ~0x80)
#define Led1_off() (PORTD |= 0x20)
#define Led2_off() (PORTE |= 0x80)
#define Led3_off() (PORTE |= 0x40)
Led1_on();
#else
// PRINTSHORT("o");
// PRINTF("on\n");
#endif #endif
if (RF230_sleeping) { if (RF230_sleeping) {
@ -461,7 +465,7 @@ on(void)
rf230_waitidle(); rf230_waitidle();
#if RF230_CONF_AUTOACK #if RF230_CONF_AUTOACK
radio_set_trx_state(RX_AACK_ON); radio_set_trx_state(is_promiscuous?RX_ON:RX_AACK_ON);
#else #else
radio_set_trx_state(RX_ON); radio_set_trx_state(RX_ON);
#endif #endif
@ -475,10 +479,8 @@ off(void)
// rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL); // rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL);
RF230_receive_on = 0; RF230_receive_on = 0;
#if JACKDAW #ifdef RF230BB_HOOK_RADIO_OFF
Led1_off(); RF230BB_HOOK_RADIO_OFF();
#else
// PRINTSHORT("f");
#endif #endif
// DEBUGFLOW('F'); // DEBUGFLOW('F');
@ -581,7 +583,7 @@ rf230_init(void)
return 1; return 1;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static uint8_t buffer[RF230_MAX_TX_FRAME_LENGTH]; static uint8_t buffer[RF230_MAX_TX_FRAME_LENGTH+AUX_LEN];
static int static int
rf230_transmit(unsigned short payload_len) rf230_transmit(unsigned short payload_len)
{ {
@ -711,6 +713,7 @@ rf230_transmit(unsigned short payload_len)
static int static int
rf230_prepare(const void *payload, unsigned short payload_len) rf230_prepare(const void *payload, unsigned short payload_len)
{ {
int ret = 0;
uint8_t total_len,*pbuf; uint8_t total_len,*pbuf;
#if RF230_CONF_TIMESTAMPS #if RF230_CONF_TIMESTAMPS
struct timestamp timestamp; struct timestamp timestamp;
@ -736,8 +739,12 @@ rf230_prepare(const void *payload, unsigned short payload_len)
if (total_len > RF230_MAX_TX_FRAME_LENGTH){ if (total_len > RF230_MAX_TX_FRAME_LENGTH){
#if RADIOSTATS #if RADIOSTATS
RF230_sendfail++; RF230_sendfail++;
#endif #endif
return -1; #if DEBUG
printf_P(PSTR("rf230_prepare: packet too large (%d, max: %d)\n"),total_len,RF230_MAX_TX_FRAME_LENGTH);
#endif
ret = -1;
goto bail;
} }
pbuf=&buffer[0]; pbuf=&buffer[0];
memcpy(pbuf,payload,payload_len); memcpy(pbuf,payload,payload_len);
@ -755,66 +762,46 @@ rf230_prepare(const void *payload, unsigned short payload_len)
pbuf+=TIMESTAMP_LEN; pbuf+=TIMESTAMP_LEN;
#endif /* RF230_CONF_TIMESTAMPS */ #endif /* RF230_CONF_TIMESTAMPS */
/*------------------------------------------------------------*/ /*------------------------------------------------------------*/
/* If jackdaw report frame to ethernet interface */
#if JACKDAW
// mac_logTXtoEthernet(&params, &result);
if (usbstick_mode.raw != 0) {
uint8_t sendlen;
/* Get the raw frame */ #ifdef RF230BB_HOOK_TX_PACKET
memcpy(&raw_buf[UIP_LLH_LEN], buffer, total_len); #if !RF230_CONF_CHECKSUM
sendlen = total_len; { // Add a checksum before we log the packet out
uint16_t checksum;
/* Setup generic ethernet stuff */ checksum = crc16_data(payload, payload_len, 0);
ETHBUF(raw_buf)->type = htons(0x809A); //UIP_ETHTYPE_802154 0x809A memcpy(buffer+total_len-CHECKSUM_LEN,&checksum,CHECKSUM_LEN);
// uint64_t tempaddr;
/* Check for broadcast message */
if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) {
ETHBUF(raw_buf)->dest.addr[0] = 0x33;
ETHBUF(raw_buf)->dest.addr[1] = 0x33;
ETHBUF(raw_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12];
ETHBUF(raw_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13];
ETHBUF(raw_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14];
ETHBUF(raw_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15];
} else {
/* Otherwise we have a real address */
// tempaddr = p->dest_addr.addr64;
// byte_reverse((uint8_t *)&tempaddr, 8);
mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->dest.addr[0]),
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
}
// tempaddr = p->src_addr.addr64;
// memcpy(&tempaddr,packetbuf_addr(PACKETBUF_ADDR_SENDER),sizeof(tempaddr));
// byte_reverse((uint8_t *)&tempaddr, 8);
mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0]),(uip_lladdr_t *)&uip_lladdr.addr);
// printf("Low2Eth: Sending 802.15.4 packet to ethernet\n\r");
sendlen += UIP_LLH_LEN;
usb_eth_send(raw_buf, sendlen, 0);
// rndis_stat.rxok++;
} }
#endif /* JACKDAW */ #endif /* RF230_CONF_CHECKSUM */
RF230BB_HOOK_TX_PACKET(buffer,total_len);
#endif
bail:
RELEASE_LOCK(); RELEASE_LOCK();
return 0; return ret;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static int static int
rf230_send(const void *payload, unsigned short payload_len) rf230_send(const void *payload, unsigned short payload_len)
{ {
rf230_prepare(payload, payload_len); int ret = 0;
#if JACKDAW
// In sniffer mode we don't ever send anything #ifdef RF230BB_HOOK_IS_SEND_ENABLED
if (usbstick_mode.sendToRf == 0) { if(!RF230BB_HOOK_IS_SEND_ENABLED()) {
uip_len = 0; goto bail;
return 0; }
} #endif
#endif /* JACKDAW */
return rf230_transmit(payload_len); if((ret=rf230_prepare(payload, payload_len))) {
#if DEBUG
printf_P(PSTR("rf230_send: Unable to send, prep failed (%d)\n"),ret);
#endif
goto bail;
}
ret = rf230_transmit(payload_len);
bail:
return ret;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int int
@ -862,7 +849,7 @@ rf230_on(void)
return 1; return 1;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int uint8_t
rf230_get_channel(void) rf230_get_channel(void)
{ {
//jackdaw reads zero channel, raven reads correct channel? //jackdaw reads zero channel, raven reads correct channel?
@ -871,7 +858,7 @@ rf230_get_channel(void)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
rf230_set_channel(int c) rf230_set_channel(uint8_t c)
{ {
/* Wait for any transmission to end. */ /* Wait for any transmission to end. */
// PRINTF("rf230: Set Channel %u\n",c); // PRINTF("rf230: Set Channel %u\n",c);
@ -883,7 +870,7 @@ rf230_set_channel(int c)
void void
rf230_set_pan_addr(unsigned pan, rf230_set_pan_addr(unsigned pan,
unsigned addr, unsigned addr,
const uint8_t *ieee_addr) const uint8_t ieee_addr[8])
//rf230_set_pan_addr(uint16_t pan,uint16_t addr,uint8_t *ieee_addr) //rf230_set_pan_addr(uint16_t pan,uint16_t addr,uint8_t *ieee_addr)
{ {
PRINTF("rf230: PAN=%x Short Addr=%x\n",pan,addr); PRINTF("rf230: PAN=%x Short Addr=%x\n",pan,addr);
@ -1083,19 +1070,19 @@ if (RF230_receive_on) {
} }
/* Transfer the frame, stripping the footer */ /* Transfer the frame, stripping the footer */
framep=&(rxframe.data[0]); framep=&(rxframe.data[0]);
memcpy(buf,framep,len-AUX_LEN); memcpy(buf,framep,len-AUX_LEN+CHECKSUM_LEN);
framep+=len-AUX_LEN; framep+=len-AUX_LEN;
/* Clear the length field to allow buffering of the next packet */ /* Clear the length field to allow buffering of the next packet */
rxframe.length=0; rxframe.length=0;
#if RF230_CONF_CHECKSUM #if RF230_CONF_CHECKSUM
memcpy(&checksum,framep,CHECKSUM_LEN); memcpy(&checksum,framep,CHECKSUM_LEN);
framep+=CHECKSUM_LEN;
#endif /* RF230_CONF_CHECKSUM */ #endif /* RF230_CONF_CHECKSUM */
framep+=CHECKSUM_LEN;
#if RF230_CONF_TIMESTAMPS #if RF230_CONF_TIMESTAMPS
memcpy(&t,framep,TIMESTAMP_LEN); memcpy(&t,framep,TIMESTAMP_LEN);
framep+=TIMESTAMP_LEN;
#endif /* RF230_CONF_TIMESTAMPS */ #endif /* RF230_CONF_TIMESTAMPS */
framep+=TIMESTAMP_LEN;
#if FOOTER_LEN #if FOOTER_LEN
memcpy(footer,framep,FOOTER_LEN); memcpy(footer,framep,FOOTER_LEN);
#endif #endif
@ -1152,52 +1139,11 @@ if (RF230_receive_on) {
// } // }
// RELEASE_LOCK(); // RELEASE_LOCK();
if(len < AUX_LEN) {
return 0;
}
#if JACKDAW
/*------------------------------------------------------------*/
/* If jackdaw report frame to ethernet interface */
// mac_logRXtoEthernet(&params, &result);
if (usbstick_mode.raw != 0) {
uint8_t sendlen;
/* Get the raw frame */ #ifdef RF230BB_HOOK_RX_PACKET
memcpy(&raw_buf[UIP_LLH_LEN], buf, len); RF230BB_HOOK_RX_PACKET(buf,len);
sendlen = len; #endif
/* Setup generic ethernet stuff */
ETHBUF(raw_buf)->type = htons(0x809A); //UIP_ETHTYPE_802154 0x809A
// uint64_t tempaddr;
/* Check for broadcast message */
if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) {
ETHBUF(raw_buf)->dest.addr[0] = 0x33;
ETHBUF(raw_buf)->dest.addr[1] = 0x33;
ETHBUF(raw_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12];
ETHBUF(raw_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13];
ETHBUF(raw_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14];
ETHBUF(raw_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15];
} else {
/* Otherwise we have a real address */
// tempaddr = p->dest_addr.addr64;
// byte_reverse((uint8_t *)&tempaddr, 8);
mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->dest.addr[0]),
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
}
// tempaddr = p->src_addr.addr64;
// memcpy(&tempaddr,packetbuf_addr(PACKETBUF_ADDR_SENDER),sizeof(tempaddr));
// byte_reverse((uint8_t *)&tempaddr, 8);
mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0]),(uip_lladdr_t *)&uip_lladdr.addr);
// printf("Low2Eth: Sending 802.15.4 packet to ethernet\n\r");
sendlen += UIP_LLH_LEN;
usb_eth_send(raw_buf, sendlen, 0);
}
#endif /* JACKDAW */
return len - AUX_LEN; return len - AUX_LEN;
@ -1217,30 +1163,23 @@ rf230_set_txpower(uint8_t power)
RELEASE_LOCK(); RELEASE_LOCK();
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int uint8_t
rf230_get_txpower(void) rf230_get_txpower(void)
{ {
uint8_t power; uint8_t power = TX_PWR_UNDEFINED;
if (radio_is_sleeping() ==true) { if (radio_is_sleeping()) {
PRINTF("rf230_get_txpower:Sleeping"); PRINTF("rf230_get_txpower:Sleeping");
return 0; } else {
} else { power = hal_subregister_read(SR_TX_PWR);
// return hal_subregister_read(SR_TX_PWR); }
power=hal_subregister_read(SR_TX_PWR); return power;
if (power==0) {
PRINTSHORT("PZ");
return 1;
} else {
return power;
}
}
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int uint8_t
rf230_rssi(void) rf230_get_raw_rssi(void)
{ {
int rssi; uint8_t rssi;
int radio_was_off = 0; bool radio_was_off = 0;
/*The RSSI measurement should only be done in RX_ON or BUSY_RX.*/ /*The RSSI measurement should only be done in RX_ON or BUSY_RX.*/
if(!RF230_receive_on) { if(!RF230_receive_on) {
@ -1249,11 +1188,6 @@ rf230_rssi(void)
} }
rssi = (int)((signed char)hal_subregister_read(SR_RSSI)); rssi = (int)((signed char)hal_subregister_read(SR_RSSI));
if (rssi==0) {
DEBUGFLOW('r');
PRINTF("RSZ");
rssi=1;
}
if(radio_was_off) { if(radio_was_off) {
rf230_off(); rf230_off();

View file

@ -45,7 +45,7 @@
* \file * \file
* \brief This file contains radio driver code. * \brief This file contains radio driver code.
* *
* $Id: rf230bb.h,v 1.2 2010/02/22 22:23:18 dak664 Exp $ * $Id: rf230bb.h,v 1.3 2010/09/17 21:59:09 dak664 Exp $
*/ */
#ifndef RADIO_H #ifndef RADIO_H
@ -73,6 +73,11 @@
#define TX_PWR_3DBM ( 0 ) #define TX_PWR_3DBM ( 0 )
#define TX_PWR_17_2DBM ( 15 ) #define TX_PWR_17_2DBM ( 15 )
#define TX_PWR_MAX TX_PWR_3DBM
#define TX_PWR_MIN TX_PWR_17_2DBM
#define TX_PWR_UNDEFINED (TX_PWR_MIN+1)
#define BATTERY_MONITOR_HIGHEST_VOLTAGE ( 15 ) #define BATTERY_MONITOR_HIGHEST_VOLTAGE ( 15 )
#define BATTERY_MONITOR_VOLTAGE_UNDER_THRESHOLD ( 0 ) #define BATTERY_MONITOR_VOLTAGE_UNDER_THRESHOLD ( 0 )
#define BATTERY_MONITOR_HIGH_VOLTAGE ( 1 ) #define BATTERY_MONITOR_HIGH_VOLTAGE ( 1 )
@ -168,89 +173,44 @@ typedef enum{
}radio_clkm_speed_t; }radio_clkm_speed_t;
typedef void (*radio_rx_callback) (uint16_t data); typedef void (*radio_rx_callback) (uint16_t data);
extern uint8_t rxMode;
/* Hook Documentation
**
** Sniffing Hooks:
** RF230BB_HOOK_TX_PACKET(buffer,total_len)
** RF230BB_HOOK_RX_PACKET(buf,len)
**
** RF230BB_HOOK_IS_SEND_ENABLED()
** RF230BB_HOOK_RADIO_ON()
** RF230BB_HOOK_RADIO_OFF()
**
*/
/*============================ PROTOTYPES ====================================*/ /*============================ PROTOTYPES ====================================*/
const struct radio_driver rf230_driver; const struct radio_driver rf230_driver;
int rf230_init(void); int rf230_init(void);
//int rf230_on(void); //int rf230_on(void);
//int rf230_off(void); //int rf230_off(void);
void rf230_set_channel(int channel); void rf230_set_channel(uint8_t channel);
int rf230_get_channel(void); uint8_t rf230_get_channel(void);
void rf230_set_pan_addr(unsigned pan,unsigned addr,const uint8_t *ieee_addr); void rf230_set_pan_addr(unsigned pan,unsigned addr,const uint8_t ieee_addr[8]);
//void rf230_set_pan_addr(uint16_t pan,uint16_t addr,uint8_t *ieee_addr); void rf230_set_txpower(uint8_t power);
//void rf230_set_txpower(uint8_t power); uint8_t rf230_get_txpower(void);
int rf230_get_txpower(void);
//extern signed char rf230_last_rssi; void rf230_set_promiscuous_mode(bool isPromiscuous);
//extern uint8_t rf230_last_correlation; bool rf230_is_ready_to_send();
//int rf230_rssi(void); extern signed char rf230_last_rssi;
extern uint8_t rf230_last_correlation;
uint8_t rf230_get_raw_rssi(void);
#define rf230_rssi rf230_get_raw_rssi
//#define CC2420_TXPOWER_MAX 31
//#define CC2420_TXPOWER_MIN 0
/**
* Interrupt function, called from the simple-cc2420-arch driver.
*
*/
//int cc2420_interrupt(void);
/* XXX hack: these will be made as Chameleon packet attributes */
//extern rtimer_clock_t rf230_time_of_arrival,rf230_time_of_departure;
//extern int rf230_authority_level_of_sender;
//radio_status_t radio_init(bool cal_rc_osc,
// hal_rx_start_isr_event_handler_t rx_event,
// hal_trx_end_isr_event_handler_t trx_end_event,
// radio_rx_callback rx_callback);
//uint8_t radio_get_saved_rssi_value(void);
//uint8_t radio_get_operating_channel( void );
//radio_status_t radio_set_operating_channel( uint8_t channel );
//uint8_t radio_get_tx_power_level( void );
//radio_status_t radio_set_tx_power_level( uint8_t power_level );
//uint8_t radio_get_cca_mode( void );
//uint8_t radio_get_ed_threshold( void );
//radio_status_t radio_set_cca_mode( uint8_t mode, uint8_t ed_threshold );
//radio_status_t radio_do_cca( void );
//radio_status_t radio_get_rssi_value( uint8_t *rssi );
//uint8_t radio_batmon_get_voltage_threshold( void );
//uint8_t radio_batmon_get_voltage_range( void );
//radio_status_t radio_batmon_configure( bool range, uint8_t voltage_threshold );
//radio_status_t radio_batmon_get_status( void );
//uint8_t radio_get_clock_speed( void );
//radio_status_t radio_set_clock_speed( bool direct, uint8_t clock_speed );
//radio_status_t radio_calibrate_filter( void );
//radio_status_t radio_calibrate_pll( void );
//uint8_t radio_get_trx_state( void );
//radio_status_t radio_set_trx_state( uint8_t new_state );
//radio_status_t radio_enter_sleep_mode( void );
//radio_status_t radio_leave_sleep_mode( void );
//void radio_reset_state_machine( void );
//void radio_reset_trx( void );
//void radio_use_auto_tx_crc( bool auto_crc_on );
//radio_status_t radio_send_data( uint8_t data_length, uint8_t *data );
//uint8_t radio_get_device_role( void );
//void radio_set_device_role( bool i_am_coordinator );
//uint16_t radio_get_pan_id( void );
//void radio_set_pan_id( uint16_t new_pan_id );
//uint16_t radio_get_short_address( void );
//void radio_set_short_address( uint16_t new_short_address );
//void radio_get_extended_address( uint8_t *extended_address );
//void radio_set_extended_address( uint8_t *extended_address );
//radio_status_t radio_configure_csma( uint8_t seed0, uint8_t be_csma_seed1 );
//bool calibrate_rc_osc_clkm(void);
//void calibrate_rc_osc_32k(void);
//uint8_t * radio_frame_data(void);
//uint8_t radio_frame_length(void);
#define delay_us( us ) ( _delay_loop_2( ( F_CPU / 4000000UL ) * ( us ) ) ) #define delay_us( us ) ( _delay_loop_2( ( F_CPU / 4000000UL ) * ( us ) ) )
#endif #endif

275
cpu/avr/settings.c Normal file
View file

@ -0,0 +1,275 @@
#include <stdbool.h>
//#include <sys/param.h>
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#include <avr/io.h>
#include "settings.h"
#include "dev/eeprom.h"
#include <stdio.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <avr/wdt.h>
#include "contiki.h"
#ifndef SETTINGS_TOP_ADDR
#define SETTINGS_TOP_ADDR (E2END-4) //!< Defaults to end of EEPROM, minus 4 bytes for avrdude erase count
#endif
#ifndef SETTINGS_MAX_SIZE
#define SETTINGS_MAX_SIZE (1024) //!< Defaults to 1KB
#endif
//#pragma mark -
//#pragma mark Private Functions
typedef struct {
uint8_t size_extra;
uint8_t size_low;
uint8_t size_check;
settings_key_t key;
} item_header_t;
inline static bool
settings_is_item_valid_(eeprom_addr_t item_addr) {
item_header_t header = {};
if(item_addr==EEPROM_NULL)
return false;
// if((SETTINGS_TOP_ADDR-item_addr)>=SETTINGS_MAX_SIZE-3)
// return false;
eeprom_read(
item_addr+1-sizeof(header),
(unsigned char*)&header,
sizeof(header)
);
if((uint8_t)header.size_check!=(uint8_t)~header.size_low)
return false;
// TODO: Check length as well
return true;
}
inline static settings_key_t
settings_get_key_(eeprom_addr_t item_addr) {
item_header_t header;
eeprom_read(
item_addr+1-sizeof(header),
(unsigned char*)&header,
sizeof(header)
);
if((uint8_t)header.size_check!=(uint8_t)~header.size_low)
return SETTINGS_INVALID_KEY;
return header.key;
}
inline static size_t
settings_get_value_length_(eeprom_addr_t item_addr) {
item_header_t header;
size_t ret = 0;
eeprom_read(
item_addr+1-sizeof(header),
(unsigned char*)&header,
sizeof(header)
);
if((uint8_t)header.size_check!=(uint8_t)~header.size_low)
goto bail;
ret = header.size_low;
if(ret&(1<<7)) {
ret = ((ret&~(1<<7))<<8) | header.size_extra;
}
bail:
return ret;
}
inline static eeprom_addr_t
settings_get_value_addr_(eeprom_addr_t item_addr) {
size_t len = settings_get_value_length_(item_addr);
if(len>128)
return item_addr+1-sizeof(item_header_t)-len;
return item_addr+1-sizeof(item_header_t)+1-len;
}
inline static eeprom_addr_t
settings_next_item_(eeprom_addr_t item_addr) {
return settings_get_value_addr_(item_addr)-1;
}
//#pragma mark -
//#pragma mark Public Functions
bool
settings_check(settings_key_t key,uint8_t index) {
bool ret = false;
eeprom_addr_t current_item = SETTINGS_TOP_ADDR;
for(current_item=SETTINGS_TOP_ADDR;settings_is_item_valid_(current_item);current_item=settings_next_item_(current_item)) {
if(settings_get_key_(current_item)==key) {
if(!index) {
ret = true;
break;
} else {
// Nope, keep looking
index--;
}
}
}
return ret;
}
settings_status_t
settings_get(settings_key_t key,uint8_t index,unsigned char* value,size_t* value_size) {
settings_status_t ret = SETTINGS_STATUS_NOT_FOUND;
eeprom_addr_t current_item = SETTINGS_TOP_ADDR;
for(current_item=SETTINGS_TOP_ADDR;settings_is_item_valid_(current_item);current_item=settings_next_item_(current_item)) {
if(settings_get_key_(current_item)==key) {
if(!index) {
// We found it!
*value_size = MIN(*value_size,settings_get_value_length_(current_item));
eeprom_read(
settings_get_value_addr_(current_item),
value,
*value_size
);
ret = SETTINGS_STATUS_OK;
break;
} else {
// Nope, keep looking
index--;
}
}
}
return ret;
}
settings_status_t
settings_add(settings_key_t key,const unsigned char* value,size_t value_size) {
settings_status_t ret = SETTINGS_STATUS_FAILURE;
eeprom_addr_t current_item = SETTINGS_TOP_ADDR;
item_header_t header;
// Find end of list
for(current_item=SETTINGS_TOP_ADDR;settings_is_item_valid_(current_item);current_item=settings_next_item_(current_item));
if(current_item==EEPROM_NULL)
goto bail;
// TODO: size check!
header.key = key;
if(value_size<0x80) {
// If the value size is less than 128, then
// we can get away with only using one byte
// as the size.
header.size_low = value_size;
} else if(value_size<=SETTINGS_MAX_VALUE_SIZE) {
// If the value size of larger than 128,
// then we need to use two bytes. Store
// the most significant 7 bits in the first
// size byte (with MSB set) and store the
// least significant bits in the second
// byte (with LSB clear)
header.size_low = (value_size>>7) | 0x80;
header.size_extra = value_size & ~0x80;
} else {
// Value size way too big!
goto bail;
}
header.size_check = ~header.size_low;
// Write the header first
eeprom_write(
current_item+1-sizeof(header),
(unsigned char*)&header,
sizeof(header)
);
// Sanity check, remove once confident
if(settings_get_value_length_(current_item)!=value_size) {
goto bail;
}
// Now write the data
eeprom_write(
settings_get_value_addr_(current_item),
(unsigned char*)value,
value_size
);
ret = SETTINGS_STATUS_OK;
bail:
return ret;
}
settings_status_t
settings_set(settings_key_t key,const unsigned char* value,size_t value_size) {
settings_status_t ret = SETTINGS_STATUS_FAILURE;
eeprom_addr_t current_item = SETTINGS_TOP_ADDR;
for(current_item=SETTINGS_TOP_ADDR;settings_is_item_valid_(current_item);current_item=settings_next_item_(current_item)) {
if(settings_get_key_(current_item)==key) {
break;
}
}
if((current_item==EEPROM_NULL) || !settings_is_item_valid_(current_item)) {
ret = settings_add(key,value,value_size);
goto bail;
}
if(value_size!=settings_get_value_length_(current_item)) {
// Requires the settings store to be shifted. Currently unimplemented.
goto bail;
}
// Now write the data
eeprom_write(
settings_get_value_addr_(current_item),
(unsigned char*)value,
value_size
);
ret = SETTINGS_STATUS_OK;
bail:
return ret;
}
settings_status_t
settings_delete(settings_key_t key,uint8_t index) {
// Requires the settings store to be shifted. Currently unimplemented.
// TODO: Writeme!
return SETTINGS_STATUS_UNIMPLEMENTED;
}
void
settings_wipe(void) {
size_t i = SETTINGS_TOP_ADDR-SETTINGS_MAX_SIZE;
for(;i<=SETTINGS_TOP_ADDR;i++) {
eeprom_write_byte((uint8_t*)i,0xFF);
wdt_reset();
}
}

118
cpu/avr/settings.h Normal file
View file

@ -0,0 +1,118 @@
#ifndef __AVR_SETTINGS_H__
#define __AVR_SETTINGS_H__
#include <inttypes.h>
#include <stdlib.h>
#include <stdbool.h>
typedef uint16_t settings_key_t;
#define SETTINGS_KEY_EUI64 'E8' //!< Value always 8 bytes long
#define SETTINGS_KEY_EUI48 'E6' //!< Value always 6 bytes long
#define SETTINGS_KEY_CHANNEL 'CH' //!< Value always 1 byte long
#define SETTINGS_KEY_TXPOWER 'TP' //!< Value always 1 byte long
#define SETTINGS_KEY_PAN_ID 'PN' //!< Value always 2 bytes long
#define SETTINGS_KEY_PAN_ADDR 'PA' //!< Value always 2 bytes long
#define SETTINGS_KEY_AES128KEY 'SK' //!< Value always 16 bytes long
#define SETTINGS_KEY_AES128ENABLED 'SE' //!< Value always 16 bytes long
typedef enum {
SETTINGS_STATUS_OK=0,
SETTINGS_STATUS_INVALID_ARGUMENT,
SETTINGS_STATUS_NOT_FOUND,
SETTINGS_STATUS_OUT_OF_SPACE,
SETTINGS_STATUS_UNIMPLEMENTED,
SETTINGS_STATUS_FAILURE,
} settings_status_t;
// Use this when you want to retrieve the last item
#define SETTINGS_LAST_INDEX (0xFF)
#define SETTINGS_INVALID_KEY (0x00)
#define SETTINGS_MAX_VALUE_SIZE (0x3FFF) // 16383 bytes
extern settings_status_t settings_get(settings_key_t key,uint8_t index,unsigned char* value,size_t* value_size);
extern settings_status_t settings_add(settings_key_t key,const unsigned char* value,size_t value_size);
extern bool settings_check(settings_key_t key,uint8_t index);
extern void settings_wipe(void);
extern settings_status_t settings_set(settings_key_t key,const unsigned char* value,size_t value_size);
extern settings_status_t settings_delete(settings_key_t key,uint8_t index);
//#pragma mark -
//#pragma mark Inline convenience functions
static inline uint8_t
settings_get_uint8(settings_key_t key,uint8_t index) {
uint8_t ret = 0;
size_t sizeof_uint8 = sizeof(uint8_t);
settings_get(key,index,(unsigned char*)&ret,&sizeof_uint8);
return ret;
}
static inline settings_status_t
settings_add_uint8(settings_key_t key,uint8_t value) {
return settings_add(key,(const unsigned char*)&value,sizeof(uint8_t));
}
static inline settings_status_t
settings_set_uint8(settings_key_t key,uint8_t value) {
return settings_set(key,(const unsigned char*)&value,sizeof(uint8_t));
}
static inline uint16_t
settings_get_uint16(settings_key_t key,uint8_t index) {
uint16_t ret = 0;
size_t sizeof_uint16 = sizeof(uint16_t);
settings_get(key,index,(unsigned char*)&ret,&sizeof_uint16);
return ret;
}
static inline settings_status_t
settings_add_uint16(settings_key_t key,uint16_t value) {
return settings_add(key,(const unsigned char*)&value,sizeof(uint16_t));
}
static inline settings_status_t
settings_set_uint16(settings_key_t key,uint16_t value) {
return settings_set(key,(const unsigned char*)&value,sizeof(uint16_t));
}
static inline uint32_t
settings_get_uint32(settings_key_t key,uint8_t index) {
uint32_t ret = 0;
size_t sizeof_uint32 = sizeof(uint32_t);
settings_get(key,index,(unsigned char*)&ret,&sizeof_uint32);
return ret;
}
static inline settings_status_t
settings_add_uint32(settings_key_t key,uint32_t value) {
return settings_add(key,(const unsigned char*)&value,sizeof(uint32_t));
}
static inline settings_status_t
settings_set_uint32(settings_key_t key,uint32_t value) {
return settings_set(key,(const unsigned char*)&value,sizeof(uint32_t));
}
static inline uint64_t
settings_get_uint64(settings_key_t key,uint8_t index) {
uint64_t ret = 0;
size_t sizeof_uint64 = sizeof(uint64_t);
settings_get(key,index,(unsigned char*)&ret,&sizeof_uint64);
return ret;
}
static inline settings_status_t
settings_add_uint64(settings_key_t key,uint64_t value) {
return settings_add(key,(const unsigned char*)&value,sizeof(uint64_t));
}
static inline settings_status_t
settings_set_uint64(settings_key_t key,uint64_t value) {
return settings_set(key,(const unsigned char*)&value,sizeof(uint64_t));
}
#endif

View file

@ -28,35 +28,52 @@
* *
* This file is part of the Contiki operating system. * This file is part of the Contiki operating system.
* *
* @(#)$Id: watchdog.c,v 1.1 2010/02/07 07:43:35 adamdunkels Exp $ * @(#)$Id: watchdog.c,v 1.2 2010/09/17 21:59:09 dak664 Exp $
*/ */
/* Dummy watchdog routines for the Raven 1284p */ /* Dummy watchdog routines for the Raven 1284p */
#include "dev/watchdog.h" #include "dev/watchdog.h"
#include <avr/wdt.h>
#include <avr/interrupt.h>
static int stopped = 0;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
watchdog_init(void) watchdog_init(void)
{ {
MCUSR&=~(1<<WDRF);
stopped = 0;
watchdog_stop();
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
watchdog_start(void) watchdog_start(void)
{ {
stopped--;
if(!stopped)
wdt_enable(WDTO_2S);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
watchdog_periodic(void) watchdog_periodic(void)
{ {
if(!stopped)
wdt_reset();
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
watchdog_stop(void) watchdog_stop(void)
{ {
stopped++;
wdt_disable();
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
watchdog_reboot(void) watchdog_reboot(void)
{ {
cli();
wdt_enable(WDTO_15MS); //wd on,250ms
while(1); //loop
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/

View file

@ -115,12 +115,43 @@ extern uint8_t domain_name[30];
uint8_t mac_address[8] EEMEM = {0x02, 0x11, 0x22, 0xff, 0xfe, 0x33, 0x44, 0x55}; uint8_t mac_address[8] EEMEM = {0x02, 0x11, 0x22, 0xff, 0xfe, 0x33, 0x44, 0x55};
#endif #endif
static uint8_t get_channel_from_eeprom() {
uint8_t eeprom_channel;
uint8_t eeprom_check;
eeprom_channel = eeprom_read_byte((uint8_t *)9);
eeprom_check = eeprom_read_byte((uint8_t *)10);
if(eeprom_channel==~eeprom_check)
return eeprom_channel;
return 26;
}
static bool get_mac_from_eeprom(uint8_t* macptr) {
eeprom_read_block ((void *)macptr, &mac_address, 8);
return true;
}
static uint16_t get_panid_from_eeprom(void) {
// TODO: Writeme!
return IEEE802154_PANID;
}
static uint16_t get_panaddr_from_eeprom(void) {
// TODO: Writeme!
return 0;
}
/*-------------------------Low level initialization------------------------*/ /*-------------------------Low level initialization------------------------*/
/*------Done in a subroutine to keep main routine stack usage small--------*/ /*------Done in a subroutine to keep main routine stack usage small--------*/
void initialize(void) void initialize(void)
{ {
//calibrate_rc_osc_32k(); //CO: Had to comment this out //calibrate_rc_osc_32k(); //CO: Had to comment this out
watchdog_init();
watchdog_start();
#ifdef RAVEN_LCD_INTERFACE #ifdef RAVEN_LCD_INTERFACE
/* First rs232 port for Raven 3290 port */ /* First rs232 port for Raven 3290 port */
rs232_init(RS232_PORT_0, USART_BAUD_38400,USART_PARITY_NONE | USART_STOP_BITS_1 | USART_DATA_BITS_8); rs232_init(RS232_PORT_0, USART_BAUD_38400,USART_PARITY_NONE | USART_STOP_BITS_1 | USART_DATA_BITS_8);
@ -155,13 +186,15 @@ void initialize(void)
rimeaddr_t addr; rimeaddr_t addr;
memset(&addr, 0, sizeof(rimeaddr_t)); memset(&addr, 0, sizeof(rimeaddr_t));
AVR_ENTER_CRITICAL_REGION(); get_mac_from_eeprom(addr.u8);
eeprom_read_block ((void *)&addr.u8, &mac_address, 8);
AVR_LEAVE_CRITICAL_REGION();
memcpy(&uip_lladdr.addr, &addr.u8, 8); memcpy(&uip_lladdr.addr, &addr.u8, 8);
rf230_set_pan_addr(IEEE802154_PANID, 0, (uint8_t *)&addr.u8); rf230_set_pan_addr(
rf230_set_channel(26); get_panid_from_eeprom(),
get_panaddr_from_eeprom(),
(uint8_t *)&addr.u8
);
rf230_set_channel(get_channel_from_eeprom());
rimeaddr_set_node_addr(&addr); rimeaddr_set_node_addr(&addr);
@ -312,7 +345,7 @@ main(void)
// len = rf230_read(packetbuf_dataptr(), PACKETBUF_SIZE); // len = rf230_read(packetbuf_dataptr(), PACKETBUF_SIZE);
// packetbuf_set_datalen(42); // packetbuf_set_datalen(42);
// NETSTACK_RDC.input(); // NETSTACK_RDC.input();
watchdog_periodic();
#if TESTRTIMER #if TESTRTIMER
if (rtimerflag) { //8 seconds is maximum interval, my raven 6% slow if (rtimerflag) { //8 seconds is maximum interval, my raven 6% slow
rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL); rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL);

View file

@ -7,15 +7,16 @@ USB = uart_usb_lib.c \
cdc_task.c \ cdc_task.c \
rndis_task.c \ rndis_task.c \
rndis.c \ rndis.c \
cdc_eem.c \
cdc_ecm.c \
usb_descriptors.c \ usb_descriptors.c \
usb_drv.c \ usb_drv.c \
usb_specific_request.c \ usb_specific_request.c \
usb_standard_request.c \ usb_standard_request.c \
usb_task.c \ usb_task.c
scsi_decoder.c \
ctrl_access.c \ #Files needed for USB Mass storage device enumeration
storage_task.c \ USB += scsi_decoder.c ctrl_access.c storage_task.c avr_flash.c
avr_flash.c
#As of September 2010 the following are needed for rpl. They need explicit inclusion if CONTIKI_NO_NET=1 #As of September 2010 the following are needed for rpl. They need explicit inclusion if CONTIKI_NO_NET=1
#If CONTIKI_NO_NET=1 the tcpip_input routine in tcpip.c must be commented out; it expects a tcpip process and conflicts with the one in fakeuip.c #If CONTIKI_NO_NET=1 the tcpip_input routine in tcpip.c must be commented out; it expects a tcpip process and conflicts with the one in fakeuip.c
@ -24,7 +25,7 @@ USB = uart_usb_lib.c \
CONTIKI_TARGET_SOURCEFILES += cfs-eeprom.c eeprom.c random.c \ CONTIKI_TARGET_SOURCEFILES += cfs-eeprom.c eeprom.c random.c \
mmem.c contiki-raven-default-init-lowlevel.c \ mmem.c contiki-raven-default-init-lowlevel.c \
contiki-raven-default-init-net.c contiki-raven-main.c httpd-simple-avr.c \ contiki-raven-default-init-net.c contiki-raven-main.c httpd-simple-avr.c \
sicslow_ethernet.c queuebuf.c packetbuf.c \ sicslow_ethernet.c queuebuf.c packetbuf.c rng.c \
$(RPL) \ $(RPL) \
$(USB) $(USB)

View file

@ -0,0 +1,578 @@
/* 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 "cdc_task.h"
#include "serial/uart_usb_lib.h"
#include "rndis/rndis_protocol.h"
#include "rndis/rndis_task.h"
#include "sicslow_ethernet.h"
#if RF230BB
#include "rf230bb.h"
#else
#include "radio.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include "dev/watchdog.h"
#include "rng.h"
#include "bootloader.h"
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <avr/wdt.h>
#include <util/delay.h>
#if JACKDAW_CONF_USE_SETTINGS
#include "settings.h"
#endif
#define BUF ((struct uip_eth_hdr *)&uip_buf[0])
#define PRINTF printf
#define PRINTF_P printf_P
//_____ M A C R O S ________________________________________________________
#define bzero(ptr,size) memset(ptr,0,size)
//_____ D E F I N I T I O N S ______________________________________________
#define IAD_TIMEOUT_DETACH 300
#define IAD_TIMEOUT_ATTACH 600
//_____ 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;
//! previous configuration
static uint8_t previous_uart_usb_control_line_state = 0;
static uint8_t timer = 0;
static struct etimer et;
PROCESS(cdc_process, "CDC serial 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();
while(1) {
// turn off LED's if necessary
if (led3_timer) led3_timer--;
else Led3_off();
if(Is_device_enumerated()) {
// If the configuration is different than the last time we checked...
if((uart_usb_get_control_line_state()&1)!=previous_uart_usb_control_line_state) {
previous_uart_usb_control_line_state = uart_usb_get_control_line_state()&1;
static FILE* previous_stdout;
if(previous_uart_usb_control_line_state&1) {
previous_stdout = stdout;
uart_usb_init();
uart_usb_set_stdout();
menu_print();
} else {
stdout = previous_stdout;
}
}
//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_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) {
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\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("* e Energy Scan *\n\r"));
#if USB_CONF_STORAGE
PRINTF_P(PSTR("* u Switch to mass-storage*\n\r"));
#endif
if(bootloader_is_present())
PRINTF_P(PSTR("* D Switch to DFU mode *\n\r"));
PRINTF_P(PSTR("* R Reset (via WDT) *\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"));
PRINTF_P(PSTR("[Built "__DATE__"]\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':
if (channel_string_i) {
channel_string[channel_string_i] = 0;
tempchannel = atoi(channel_string);
#if RF230BB
if ((tempchannel < 11) || (tempchannel > 26)) {
PRINTF_P(PSTR("\n\rInvalid input\n\r"));
} else {
rf230_set_channel(tempchannel);
#else
if(radio_set_operating_channel(tempchannel)!=RADIO_SUCCESS) {
PRINTF_P(PSTR("\n\rInvalid input\n\r"));
} else {
#endif
#if JACKDAW_CONF_USE_SETTINGS
if(settings_set_uint8(SETTINGS_KEY_CHANNEL, tempchannel)!=SETTINGS_STATUS_OK) {
PRINTF_P(PSTR("\n\rChannel changed to %d, but unable to store in EEPROM!\n\r"),tempchannel);
} else
#else
AVR_ENTER_CRITICAL_REGION();
eeprom_write_byte((uint8_t *) 9, tempchannel); //Write channel
eeprom_write_byte((uint8_t *)10, ~tempchannel); //Bit inverse as check
AVR_LEAVE_CRITICAL_REGION();
#endif
PRINTF_P(PSTR("\n\rChannel changed to %d and stored in EEPROM.\n\r"),tempchannel);
}
} else {
PRINTF_P(PSTR("\n\rChannel unchanged.\n\r"));
}
menustate = normal;
break;
case '\b':
if (channel_string_i) {
channel_string_i--;
PRINTF_P(PSTR("\b \b"));
}
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (channel_string_i > 1) {
// This time the user has gone too far.
// Beep at them.
putc('\a', stdout);
//uart_usb_putchar('\a');
break;
}
putc(c, stdout);
//uart_usb_putchar(c);
channel_string[channel_string_i] = c;
channel_string_i++;
break;
default:
break;
}
} else {
uint8_t i;
switch(c) {
case '\r':
case '\n':
break;
case 'h':
case '?':
menu_print();
break;
case '-':
PRINTF_P(PSTR("Bringing interface down\n\r"));
usb_eth_set_active(0);
break;
case '=':
case '+':
PRINTF_P(PSTR("Bringing interface up\n\r"));
usb_eth_set_active(1);
break;
case 't':
// I added this to test my "strong" random number generator.
PRINTF_P(PSTR("RNG Output: "));
{
uint8_t value = rng_get_uint8();
uint8_t i;
for(i=0;i<8;i++) {
uart_usb_putchar(((value>>(7-i))&1)?'1':'0');
}
PRINTF_P(PSTR("\n\r"));
uart_usb_flush();
watchdog_periodic();
}
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"));
PRINTF_P(PSTR(" * USB Ethernet MAC: %02x:%02x:%02x:%02x:%02x:%02x\n"),
((uint8_t *)&usb_ethernet_addr)[0],
((uint8_t *)&usb_ethernet_addr)[1],
((uint8_t *)&usb_ethernet_addr)[2],
((uint8_t *)&usb_ethernet_addr)[3],
((uint8_t *)&usb_ethernet_addr)[4],
((uint8_t *)&usb_ethernet_addr)[5]
);
extern uint64_t macLongAddr;
PRINTF_P(PSTR(" * 802.15.4 EUI-64: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n"),
((uint8_t *)&macLongAddr)[0],
((uint8_t *)&macLongAddr)[1],
((uint8_t *)&macLongAddr)[2],
((uint8_t *)&macLongAddr)[3],
((uint8_t *)&macLongAddr)[4],
((uint8_t *)&macLongAddr)[5],
((uint8_t *)&macLongAddr)[6],
((uint8_t *)&macLongAddr)[7]
);
#if RF230BB
PRINTF_P(PSTR(" * Operates on channel %d\n\r"), rf230_get_channel());
PRINTF_P(PSTR(" * TX Power Level: 0x%02X\n\r"), rf230_get_txpower());
PRINTF_P(PSTR(" * Current RSSI: %ddB\n\r"), -91+3*(rf230_rssi()-1));
PRINTF_P(PSTR(" * Last RSSI: %ddB\n\r"), -91+3*(rf230_last_rssi-1));
#else // RF230BB
PRINTF_P(PSTR(" * Operates on channel %d\n\r"), radio_get_operating_channel());
PRINTF_P(PSTR(" * TX Power Level: 0x%02X\n\r"), radio_get_tx_power_level());
{
PRINTF_P(PSTR(" * Current RSSI: "));
int8_t rssi = 0;
if(radio_get_rssi_value(&rssi)==RADIO_SUCCESS)
PRINTF_P(PSTR("%ddB\n\r"), -91+3*(rssi-1));
else
PRINTF_P(PSTR("Unknown\n\r"));
}
#endif // !RF230BB
PRINTF_P(PSTR(" * Configuration: %d\n\r"), usb_configuration_nb);
PRINTF_P(PSTR(" * usb_eth_is_active: %d\n\r"), usb_eth_is_active);
break;
case 'e':
PRINTF_P(PSTR("Energy Scan:\n"));
uart_usb_flush();
{
uint8_t i;
uint16_t j;
#if RF230BB
uint8_t previous_channel = rf230_get_channel();
#else // RF230BB
uint8_t previous_channel = radio_get_operating_channel();
#endif
int8_t RSSI, maxRSSI[17];
uint16_t accRSSI[17];
bzero((void*)accRSSI,sizeof(accRSSI));
bzero((void*)maxRSSI,sizeof(maxRSSI));
for(j=0;j<(1<<12);j++) {
for(i=11;i<=26;i++) {
#if RF230BB
rf230_set_channel(i);
#else // RF230BB
radio_set_operating_channel(i);
#endif
_delay_us(3*10);
#if RF230BB
RSSI = rf230_rssi();
#else // RF230BB
radio_get_rssi_value(&RSSI);
#endif
maxRSSI[i-11]=Max(maxRSSI[i-11],RSSI);
accRSSI[i-11]+=RSSI;
}
if(j&(1<<7)) {
Led3_on();
if(!(j&((1<<7)-1))) {
PRINTF_P(PSTR("."));
uart_usb_flush();
}
}
else
Led3_off();
watchdog_periodic();
}
#if RF230BB
rf230_set_channel(previous_channel);
#else // RF230BB
radio_set_operating_channel(previous_channel);
#endif
PRINTF_P(PSTR("\n"));
for(i=11;i<=26;i++) {
uint8_t activity=Min(maxRSSI[i-11],accRSSI[i-11]/(1<<7));
PRINTF_P(PSTR(" %d: %02ddB "),i, -91+3*(maxRSSI[i-11]-1));
for(;activity--;maxRSSI[i-11]--) {
PRINTF_P(PSTR("#"));
}
for(;maxRSSI[i-11]>0;maxRSSI[i-11]--) {
PRINTF_P(PSTR(":"));
}
PRINTF_P(PSTR("\n"));
uart_usb_flush();
}
}
PRINTF_P(PSTR("Done.\n"));
uart_usb_flush();
break;
case 'D':
{
PRINTF_P(PSTR("Entering DFU Mode...\n\r"));
uart_usb_flush();
Leds_on();
for(i = 0; i < 10; i++)_delay_ms(100);
Leds_off();
Jump_To_Bootloader();
}
break;
case 'R':
{
PRINTF_P(PSTR("Resetting...\n\r"));
uart_usb_flush();
Leds_on();
for(i = 0; i < 10; i++)_delay_ms(100);
Usb_detach();
for(i = 0; i < 20; i++)_delay_ms(100);
watchdog_reboot();
}
break;
#if USB_CONF_STORAGE
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;
#endif
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 = 5;
}
/** @} */

View file

@ -0,0 +1,74 @@
/* 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_ */

View file

@ -43,6 +43,14 @@
#ifndef __CONTIKI_CONF_H__ #ifndef __CONTIKI_CONF_H__
#define __CONTIKI_CONF_H__ #define __CONTIKI_CONF_H__
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
/* ************************************************************************** */
//#pragma mark Basic Configuration
/* ************************************************************************** */
/* MCU and clock rate */ /* MCU and clock rate */
#define MCU_MHZ 8 #define MCU_MHZ 8
#define PLATFORM PLATFORM_AVR #define PLATFORM PLATFORM_AVR
@ -51,6 +59,14 @@
/* Clock ticks per second */ /* Clock ticks per second */
#define CLOCK_CONF_SECOND 125 #define CLOCK_CONF_SECOND 125
/* Mac address, RF channel, PANID from EEPROM settings manager */
/* Generate random MAC address on first startup */
/* Random number from radio clock skew or ADC noise */
#define JACKDAW_CONF_USE_SETTINGS 1
#define JACKDAW_CONF_RANDOM_MAC 0
#define RNG_CONF_USE_RADIO_CLOCK 1
//#define RNG_CONF_USE_ADC 1
/* Since clock_time_t is 16 bits, maximum interval is 524 seconds */ /* Since clock_time_t is 16 bits, maximum interval is 524 seconds */
#define RIME_CONF_BROADCAST_ANNOUNCEMENT_MAX_TIME CLOCK_CONF_SECOND * 524UL /*Default uses 600*/ #define RIME_CONF_BROADCAST_ANNOUNCEMENT_MAX_TIME CLOCK_CONF_SECOND * 524UL /*Default uses 600*/
@ -74,13 +90,71 @@
#define CCIF #define CCIF
#define CLIF #define CLIF
#define RIMEADDR_CONF_SIZE 8 /* ************************************************************************** */
//#pragma mark USB Ethernet Hooks
/* ************************************************************************** */
#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 #ifndef USB_ETH_HOOK_IS_READY_FOR_INBOUND_PACKET
#define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 #if RF230BB
#define USB_ETH_HOOK_IS_READY_FOR_INBOUND_PACKET() rf230_is_ready_to_send()
#else
static inline uint8_t radio_is_ready_to_send_() {
switch(radio_get_trx_state()) {
case BUSY_TX:
case BUSY_TX_ARET:
return 0;
}
return 1;
}
#define USB_ETH_HOOK_IS_READY_FOR_INBOUND_PACKET() radio_is_ready_to_send_()
#endif
#endif
#ifndef USB_ETH_HOOK_HANDLE_INBOUND_PACKET
#define USB_ETH_HOOK_HANDLE_INBOUND_PACKET(buffer,len) do { uip_len = len ; mac_ethernetToLowpan(buffer); } while(0)
#endif
#ifndef USB_ETH_HOOK_SET_PROMISCIOUS_MODE
#if RF230BB
#define USB_ETH_HOOK_SET_PROMISCIOUS_MODE(value) rf230_set_promiscuous_mode(value)
#else
#define USB_ETH_HOOK_SET_PROMISCIOUS_MODE(value) radio_set_trx_state(value?RX_ON:RX_AACK_ON)
#endif
#endif
#ifndef USB_ETH_HOOK_INIT
#define USB_ETH_HOOK_INIT() mac_ethernetSetup()
#endif
/* ************************************************************************** */
//#pragma mark RF230BB Hooks
/* ************************************************************************** */
//#define RF230BB_HOOK_RADIO_OFF() Led1_off()
//#define RF230BB_HOOK_RADIO_ON() Led1_on()
#define RF230BB_HOOK_TX_PACKET(buffer,total_len) mac_log_802_15_4_tx(buffer,total_len)
#define RF230BB_HOOK_RX_PACKET(buffer,total_len) mac_log_802_15_4_rx(buffer,total_len)
#define RF230BB_HOOK_IS_SEND_ENABLED() mac_is_send_enabled()
extern bool mac_is_send_enabled(void);
extern void mac_log_802_15_4_tx(const uint8_t* buffer, size_t total_len);
extern void mac_log_802_15_4_rx(const uint8_t* buffer, size_t total_len);
/* ************************************************************************** */
//#pragma mark USB CDC-ACM (UART) Hooks
/* ************************************************************************** */
#define USB_CDC_ACM_HOOK_TX_END(char) vcptx_end_led()
#define USB_CDC_ACM_HOOK_CLS_CHANGED(state) vcptx_end_led()
#define USB_CDC_ACM_HOOK_CONFIGURED() vcptx_end_led()
/* ************************************************************************** */
//#pragma mark UIP Settings
/* ************************************************************************** */
#define UIP_CONF_LL_802154 1 #define UIP_CONF_LL_802154 1
#define UIP_CONF_LLH_LEN 14 #define UIP_CONF_LLH_LEN 14
#define UIP_CONF_BUFSIZE UIP_LINK_MTU + UIP_LLH_LEN + 4 // +4 for vlan on macosx
#define UIP_CONF_MAX_CONNECTIONS 4 #define UIP_CONF_MAX_CONNECTIONS 4
#define UIP_CONF_MAX_LISTENPORTS 4 #define UIP_CONF_MAX_LISTENPORTS 4
@ -104,15 +178,38 @@
#define UIP_CONF_TCP_SPLIT 1 #define UIP_CONF_TCP_SPLIT 1
#define UIP_CONF_STATISTICS 1 #define UIP_CONF_STATISTICS 1
/* Disable mass storage enumeration for more debug string space */
//#define USB_CONF_STORAGE 1
/* Use either USB CDC or RS232 for stdout (or neither) */
//#define USB_CONF_CDC 1
#define USB_CONF_RS232 1
/* ************************************************************************** */
//#pragma mark Serial Port Settings
/* ************************************************************************** */
/* Disable mass storage enumeration for more program space */
/* TODO: Mass storage is currently broken */
#define USB_CONF_STORAGE 0
/* Use either USB CDC or RS232 for stdout (or neither) */
/* TODO:CDC is currently broken on windows/linux, use RS232 */
#define USB_CONF_CDC 1
//#define USB_CONF_RS232 1
/* ************************************************************************** */
//#pragma mark RIME Settings
/* ************************************************************************** */
#define RIMEADDR_CONF_SIZE 8
/* ************************************************************************** */
//#pragma mark SICSLOWPAN Settings
/* ************************************************************************** */
#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06
#define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2
#ifdef RF230BB #ifdef RF230BB
#define SICSLOWPAN_CONF_CONVENTIONAL_MAC 1 //for barebones driver, sicslowpan calls radio->read function #define SICSLOWPAN_CONF_CONVENTIONAL_MAC 1 //for barebones driver, sicslowpan calls radio->read function
/* ************************************************************************** */
//#pragma mark NETSTACK Settings
/* ************************************************************************** */
#if 1 /* Network setup */ #if 1 /* Network setup */
/* No radio cycling */ /* No radio cycling */
#define NETSTACK_CONF_NETWORK sicslowpan_driver #define NETSTACK_CONF_NETWORK sicslowpan_driver
@ -158,12 +255,19 @@
#error Network configuration not specified! #error Network configuration not specified!
#endif /* Network setup */ #endif /* Network setup */
#if 0 /* RPL */
/* ************************************************************************** */
//#pragma mark RPL Settings
/* ************************************************************************** */
#define UIP_CONF_IPV6_RPL 0
#if UIP_CONF_IPV6_RPL
/* Not completely working yet. Link local pings work but address prefixes do not get assigned */ /* Not completely working yet. Link local pings work but address prefixes do not get assigned */
/* RPL requires the uip stack. Change #CONTIKI_NO_NET=1 to UIP_CONF_IPV6=1 in the examples makefile, /* RPL requires the uip stack. Change #CONTIKI_NO_NET=1 to UIP_CONF_IPV6=1 in the examples makefile,
or include the needed source files in /plaftorm/avr-ravenusb/Makefile.avr-ravenusb */ or include the needed source files in /plaftorm/avr-ravenusb/Makefile.avr-ravenusb */
#define UIP_CONF_IPV6_RPL 1
#define UIP_CONF_ROUTER 1 #define UIP_CONF_ROUTER 1
#define RPL_CONF_STATS 0 #define RPL_CONF_STATS 0
#define PROCESS_CONF_NO_PROCESS_NAMES 0 #define PROCESS_CONF_NO_PROCESS_NAMES 0
@ -212,11 +316,13 @@ or include the needed source files in /plaftorm/avr-ravenusb/Makefile.avr-ravenu
#define UIP_CONF_PINGADDRCONF 0 #define UIP_CONF_PINGADDRCONF 0
#define UIP_CONF_LOGGING 0 #define UIP_CONF_LOGGING 0
#endif #endif
#endif /* RPL */ #endif /* UIP_CONF_IPV6_RPL */
#endif /* RF230BB */ #endif /* RF230BB */
/* ************************************************************************** */
//#pragma mark Other Settings
/* ************************************************************************** */
/* Route-Under-MAC uses 16-bit short addresses */ /* Route-Under-MAC uses 16-bit short addresses */
#if UIP_CONF_USE_RUM #if UIP_CONF_USE_RUM
#undef UIP_CONF_LL_802154 #undef UIP_CONF_LL_802154

View file

@ -39,6 +39,7 @@
#include "usb_descriptors.h" #include "usb_descriptors.h"
#include "usb_specific_request.h" #include "usb_specific_request.h"
#include <util/delay.h> #include <util/delay.h>
#include "bootloader.h"
uint8_t checkForFinger(void); uint8_t checkForFinger(void);
@ -54,6 +55,8 @@ init_lowlevel(void)
Leds_off(); Leds_off();
if (checkForFinger()) { if (checkForFinger()) {
if(bootloader_is_present())
Jump_To_Bootloader();
#ifdef WINXPSP2 #ifdef WINXPSP2
usb_mode = mass_storage; usb_mode = mass_storage;
#else #else

View file

@ -35,36 +35,64 @@
#include "contiki-raven.h" #include "contiki-raven.h"
#if !RF230BB #if !RF230BB
#include "zmac.h" #include "zmac.h"
#else
extern uint64_t macLongAddr;
#endif #endif
#include "sicslowpan.h" #include "sicslowpan.h"
extern uint64_t rndis_ethernet_addr; #include "sicslow_ethernet.h"
#include "rndis/rndis_task.h"
void byte_reverse(uint8_t * bytes, uint8_t num)
{
uint8_t tempbyte;
uint8_t i, j;
i = 0;
j = num - 1;
while(i < j) {
tempbyte = bytes[i];
bytes[i] = bytes[j];
bytes[j] = tempbyte;
j--;
i++;
}
return;
}
void void
init_net(void) init_net(void)
{ {
extern uint64_t macLongAddr;
uint64_t usb_ethernet_addr;
// Because all of the logic below is done using little-endian
// 64-bit integers, we need to reverse the byte order before
// we can continue;
byte_reverse((uint8_t*)&macLongAddr,8);
/* Set local bit, Clear translate bit, Clear Multicast bit */
macLongAddr &= ~(0x0700000000000000ULL);
/* Set local bit, Clear translate bit, Clear Multicast bit */ macLongAddr |= 0x0200000000000000ULL;
macLongAddr &= ~(0x0700000000000000ULL);
macLongAddr |= 0x0200000000000000ULL;
/* Set the Ethernet address to the 15.4 MAC address */ /* Set the Ethernet address to the 15.4 MAC address */
rndis_ethernet_addr = macLongAddr; usb_ethernet_addr = macLongAddr;
/* Remove the middle two bytes... */
rndis_ethernet_addr = (rndis_ethernet_addr & 0xffffffUL) | ((rndis_ethernet_addr & 0xffffff0000000000ULL) >> 16);
/* Change ieee802.15.4 address to correspond with what the ethernet's /* Remove the middle two bytes... */
IPv6 address will be. This will have ff:fe in the middle. */ usb_ethernet_addr = (usb_ethernet_addr & 0xffffffUL) | ((usb_ethernet_addr & 0xffffff0000000000ULL) >> 16);
macLongAddr = (macLongAddr & 0xffffff0000ffffffULL) | (0x000000fffe000000ULL);
/* Change ieee802.15.4 address to correspond with what the ethernet's
IPv6 address will be. This will have ff:fe in the middle. */
macLongAddr = (macLongAddr & 0xffffff0000ffffffULL) | (0x000000fffe000000ULL);
#if !RF230BB #if !RF230BB
ieee15_4ManagerAddress.set_long_addr(macLongAddr); ieee15_4ManagerAddress.set_long_addr(macLongAddr);
#endif #endif
byte_reverse((uint8_t*)&macLongAddr,8);
byte_reverse((uint8_t*)&usb_ethernet_addr,6);
usb_eth_set_mac_address((uint8_t*)&usb_ethernet_addr);
} }

View file

@ -50,6 +50,7 @@
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#include <avr/fuse.h> #include <avr/fuse.h>
#include <avr/eeprom.h> #include <avr/eeprom.h>
#include <avr/wdt.h>
#include <util/delay.h> #include <util/delay.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -68,7 +69,7 @@
#include "usb_task.h" #include "usb_task.h"
#if USB_CONF_CDC #if USB_CONF_CDC
#include "serial/cdc_task.h" #include "cdc_task.h"
#elif USB_CONF_RS232 #elif USB_CONF_RS232
#include "dev/rs232.h" #include "dev/rs232.h"
#endif #endif
@ -78,13 +79,21 @@
#include "storage/storage_task.h" #include "storage/storage_task.h"
#endif #endif
#include "dev/watchdog.h"
#include "dev/usb/usb_drv.h"
#if JACKDAW_CONF_USE_SETTINGS
#include "settings.h"
#endif
#if RF230BB //radio driver using contiki core mac #if RF230BB //radio driver using contiki core mac
#include "radio/rf230bb/rf230bb.h" #include "radio/rf230bb/rf230bb.h"
#include "net/mac/frame802154.h" #include "net/mac/frame802154.h"
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
extern int rf230_interrupt_flag; extern int rf230_interrupt_flag;
extern uint8_t rf230processflag; extern uint8_t rf230processflag;
rimeaddr_t addr,macLongAddr; rimeaddr_t macLongAddr;
#define tmp_addr macLongAddr
#else //legacy radio driver using Atmel/Cisco 802.15.4'ish MAC #else //legacy radio driver using Atmel/Cisco 802.15.4'ish MAC
#include <stdbool.h> #include <stdbool.h>
#include "mac.h" #include "mac.h"
@ -194,20 +203,101 @@ SIGNATURE = {
FUSES ={.low = 0xde, .high = 0x99, .extended = 0xff,}; FUSES ={.low = 0xde, .high = 0x99, .extended = 0xff,};
/* Put default MAC address in EEPROM */ /* Put default MAC address in EEPROM */
#if !JACKDAW_CONF_USE_SETTINGS
uint8_t mac_address[8] EEMEM = {0x02, 0x12, 0x13, 0xff, 0xfe, 0x14, 0x15, 0x16}; uint8_t mac_address[8] EEMEM = {0x02, 0x12, 0x13, 0xff, 0xfe, 0x14, 0x15, 0x16};
//uint8_t EEMEM mac_address[8]; //The raven webserver uses this EEMEM allocation #endif
//uint8_t EEMEM server_name[16];
//uint8_t EEMEM domain_name[30]; static uint8_t get_channel_from_eeprom() {
#if JACKDAW_CONF_USE_SETTINGS
uint8_t chan = settings_get_uint8(SETTINGS_KEY_CHANNEL, 0);
if(!chan)
chan = RF_CHANNEL;
return chan;
#else
uint8_t eeprom_channel;
uint8_t eeprom_check;
eeprom_channel = eeprom_read_byte((uint8_t *)9);
eeprom_check = eeprom_read_byte((uint8_t *)10);
if(eeprom_channel==~eeprom_check)
return eeprom_channel;
return 26;
#endif
}
static bool
get_eui64_from_eeprom(uint8_t macptr[8]) {
#if JACKDAW_CONF_USE_SETTINGS
size_t size = 8;
if(settings_get(SETTINGS_KEY_EUI64, 0, (unsigned char*)macptr, &size)==SETTINGS_STATUS_OK)
return true;
// Fallback to reading the traditional mac address
eeprom_read_block ((void *)macptr, 0, 8);
#else
eeprom_read_block ((void *)macptr, &mac_address, 8);
#endif
return macptr[0]!=0xFF;
}
static bool
set_eui64_to_eeprom(const uint8_t macptr[8]) {
#if JACKDAW_CONF_USE_SETTINGS
return settings_set(SETTINGS_KEY_EUI64, macptr, 8)==SETTINGS_STATUS_OK;
#else
eeprom_write_block((void *)macptr, &mac_address, 8);
return true;
#endif
}
static void
generate_new_eui64(uint8_t eui64[8]) {
eui64[0] = 0x02;
eui64[1] = rng_get_uint8();
eui64[2] = rng_get_uint8();
eui64[3] = 0xFF;
eui64[4] = 0xFE;
eui64[5] = rng_get_uint8();
eui64[6] = rng_get_uint8();
eui64[7] = rng_get_uint8();
}
static uint16_t
get_panid_from_eeprom(void) {
#if JACKDAW_CONF_USE_SETTINGS
uint16_t x = settings_get_uint16(SETTINGS_KEY_PAN_ID, 0);
if(!x)
x = IEEE802154_PANID;
return x;
#else
// TODO: Writeme!
return IEEE802154_PANID;
#endif
}
static uint16_t
get_panaddr_from_eeprom(void) {
#if JACKDAW_CONF_USE_SETTINGS
return settings_get_uint16(SETTINGS_KEY_PAN_ADDR, 0);
#else
// TODO: Writeme!
return 0;
#endif
}
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/*-----------------------------Low level initialization--------------------*/ /*-----------------------------Low level initialization--------------------*/
static void initialize(void) { static void initialize(void) {
watchdog_init();
watchdog_start();
/* Initialize hardware */ /* Initialize hardware */
// Currently only used for finger detection for mass storage mode // Checks for "finger", jumps to DFU if present.
#if USB_CONF_STORAGE
init_lowlevel(); init_lowlevel();
#endif
/* Clock */ /* Clock */
clock_init(); clock_init();
@ -221,7 +311,9 @@ static void initialize(void) {
printf_P(PSTR("\n\n\n********BOOTING CONTIKI*********\n")); printf_P(PSTR("\n\n\n********BOOTING CONTIKI*********\n"));
#endif #endif
#endif #endif
Leds_init();
/* rtimer init needed for low power protocols */ /* rtimer init needed for low power protocols */
rtimer_init(); rtimer_init();
@ -239,26 +331,52 @@ static void initialize(void) {
/* Set addresses BEFORE starting tcpip process */ /* Set addresses BEFORE starting tcpip process */
memset(&addr, 0, sizeof(rimeaddr_t)); memset(&tmp_addr, 0, sizeof(rimeaddr_t));
AVR_ENTER_CRITICAL_REGION(); if(!get_eui64_from_eeprom(tmp_addr.u8)) {
eeprom_read_block ((void *)&addr.u8, &mac_address, 8); #if JACKDAW_CONF_RANDOM_MAC
AVR_LEAVE_CRITICAL_REGION(); // It doesn't look like we have a valid EUI-64 address
//RNDIS needs the mac address in reverse byte order // so let's try to make a new one from scratch.
macLongAddr.u8[0]=addr.u8[7]; Leds_off();
macLongAddr.u8[1]=addr.u8[6]; Led2_on();
macLongAddr.u8[2]=addr.u8[5]; generate_new_eui64(tmp_addr.u8);
macLongAddr.u8[3]=addr.u8[4]; if(!set_eui64_to_eeprom(tmp_addr.u8)) {
macLongAddr.u8[4]=addr.u8[3]; watchdog_periodic();
macLongAddr.u8[5]=addr.u8[2]; int i;
macLongAddr.u8[6]=addr.u8[1]; for(i=0;i<20;i++) {
macLongAddr.u8[7]=addr.u8[0]; Led1_toggle();
_delay_ms(100);
memcpy(&uip_lladdr.addr, &addr.u8, 8); }
rf230_set_pan_addr(IEEE802154_PANID, 0, (uint8_t *)&addr.u8); Led1_off();
rf230_set_channel(26); }
Led2_off();
#else
tmp_addr.u8[0]=0x02;
tmp_addr.u8[1]=0x12;
tmp_addr.u8[2]=0x13;
tmp_addr.u8[3]=0xff;
tmp_addr.u8[4]=0xfe;
tmp_addr.u8[5]=0x14;
tmp_addr.u8[6]=0x15;
tmp_addr.u8[7]=0x16;
#endif /* JACKDAW_CONF_RANDOM_MAC */
}
rimeaddr_set_node_addr(&addr); //Fix MAC address
// set_rime_addr(); init_net();
memcpy(&uip_lladdr.addr, &tmp_addr.u8, 8);
rf230_set_pan_addr(
get_panid_from_eeprom(),
get_panaddr_from_eeprom(),
(uint8_t *)&tmp_addr.u8
);
#if JACKDAW_CONF_USE_SETTINGS
rf230_set_txpower(settings_get_uint8(SETTINGS_KEY_TXPOWER,0));
#endif
rimeaddr_set_node_addr(&tmp_addr);
/* Initialize stack protocols */ /* Initialize stack protocols */
queuebuf_init(); queuebuf_init();
@ -266,8 +384,10 @@ static void initialize(void) {
NETSTACK_MAC.init(); NETSTACK_MAC.init();
NETSTACK_NETWORK.init(); NETSTACK_NETWORK.init();
rf230_set_channel(get_channel_from_eeprom());
#if ANNOUNCE && USB_CONF_RS232 #if ANNOUNCE && USB_CONF_RS232
printf_P(PSTR("MAC address %x:%x:%x:%x:%x:%x:%x:%x\n"),addr.u8[0],addr.u8[1],addr.u8[2],addr.u8[3],addr.u8[4],addr.u8[5],addr.u8[6],addr.u8[7]); printf_P(PSTR("MAC address %x:%x:%x:%x:%x:%x:%x:%x\n\r"),tmp_addr.u8[0],tmp_addr.u8[1],tmp_addr.u8[2],tmp_addr.u8[3],tmp_addr.u8[4],tmp_addr.u8[5],tmp_addr.u8[6],tmp_addr.u8[7]);
printf_P(PSTR("%s %s, channel %u"),NETSTACK_MAC.name, NETSTACK_RDC.name,rf230_get_channel()); printf_P(PSTR("%s %s, channel %u"),NETSTACK_MAC.name, NETSTACK_RDC.name,rf230_get_channel());
if (NETSTACK_RDC.channel_check_interval) { if (NETSTACK_RDC.channel_check_interval) {
unsigned short tmp; unsigned short tmp;
@ -305,13 +425,10 @@ static void initialize(void) {
#if USB_CONF_CDC #if USB_CONF_CDC
process_start(&cdc_process, NULL); process_start(&cdc_process, NULL);
#endif #endif
process_start(&rndis_process, NULL); process_start(&usb_eth_process, NULL);
#if USB_CONF_STORAGE #if USB_CONF_STORAGE
process_start(&storage_process, NULL); process_start(&storage_process, NULL);
#endif #endif
//Fix MAC address
init_net();
#if ANNOUNCE #if ANNOUNCE
#if USB_CONF_CDC #if USB_CONF_CDC
@ -320,7 +437,7 @@ static void initialize(void) {
/* Allow USB CDC to keep up with printfs */ /* Allow USB CDC to keep up with printfs */
for (i=0;i<8000;i++) process_run(); for (i=0;i<8000;i++) process_run();
#if RF230BB #if RF230BB
printf_P(PSTR("MAC address %x:%x:%x:%x:%x:%x:%x:%x\n\r"),addr.u8[0],addr.u8[1],addr.u8[2],addr.u8[3],addr.u8[4],addr.u8[5],addr.u8[6],addr.u8[7]); printf_P(PSTR("MAC address %x:%x:%x:%x:%x:%x:%x:%x\n\r"),tmp_addr.u8[0],tmp_addr.u8[1],tmp_addr.u8[2],tmp_addr.u8[3],tmp_addr.u8[4],tmp_addr.u8[5],tmp_addr.u8[6],tmp_addr.u8[7]);
for (i=0;i<8000;i++) process_run(); for (i=0;i<8000;i++) process_run();
printf_P(PSTR("%s %s, channel %u"),NETSTACK_MAC.name, NETSTACK_RDC.name,rf230_get_channel()); printf_P(PSTR("%s %s, channel %u"),NETSTACK_MAC.name, NETSTACK_RDC.name,rf230_get_channel());
if (NETSTACK_RDC.channel_check_interval) { if (NETSTACK_RDC.channel_check_interval) {
@ -359,6 +476,8 @@ main(void)
while(1) { while(1) {
process_run(); process_run();
watchdog_periodic();
#if TESTRTIMER #if TESTRTIMER
if (rtimerflag) { //8 seconds is maximum interval, my jackdaw 4% slow if (rtimerflag) { //8 seconds is maximum interval, my jackdaw 4% slow
rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL); rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL);

View file

@ -45,8 +45,6 @@
// LED's for Raven USB // LED's for Raven USB
#define Leds_init() (DDRD |= 0xA0, DDRE |= 0xC0) #define Leds_init() (DDRD |= 0xA0, DDRE |= 0xC0)
#define Leds_on() (PORTD |= 0x80, PORTD &= ~0x40, PORTE &= ~0xC0)
#define Leds_off() (PORTD &= ~0x80, PORTD |= 0x20, PORTE |= 0xC0)
#define Led0_on() (PORTD |= 0x80) #define Led0_on() (PORTD |= 0x80)
#define Led1_on() (PORTD &= ~0x20) #define Led1_on() (PORTD &= ~0x20)
#define Led2_on() (PORTE &= ~0x80) #define Led2_on() (PORTE &= ~0x80)
@ -59,6 +57,8 @@
#define Led1_toggle() (PIND |= 0x20) #define Led1_toggle() (PIND |= 0x20)
#define Led2_toggle() (PINE |= 0x80) #define Led2_toggle() (PINE |= 0x80)
#define Led3_toggle() (PINE |= 0x40) #define Led3_toggle() (PINE |= 0x40)
#define Leds_on() (Led0_on(),Led1_on(),Led2_on(),Led3_on())
#define Leds_off() (Led0_off(),Led1_off(),Led2_off(),Led3_off())
void init_lowlevel(void); void init_lowlevel(void);

View file

@ -1,129 +0,0 @@
/* Various stub functions and uIP variables other code might need to
* compile. Allows you to save needing to compile all of uIP in just
* to get a few things */
#include "uip.h"
#include <string.h>
#if CONTIKI_NO_NET
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
uip_buf_t uip_aligned_buf;
u16_t uip_len;
struct uip_stats uip_stat;
uip_lladdr_t uip_lladdr;
static u8_t (* output)(uip_lladdr_t *);
u8_t tcpip_output(uip_lladdr_t * lladdr){
if(output != NULL) {
return output(lladdr);
}
return 0;
}
void tcpip_set_outputfunc(u8_t (* f)(uip_lladdr_t *)) {
output = f;
}
u16_t htons(u16_t val) { return HTONS(val);}
#if THEOLDWAY
/********** UIP_NETIF.c **********/
void
uip_netif_addr_autoconf_set(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
#else
/********** uip-ds6.c ************/
void
uip_ds6_set_addr_iid(uip_ipaddr_t * ipaddr, uip_lladdr_t * lladdr)
#endif /* THEOLDWAY */
{
/* We consider only links with IEEE EUI-64 identifier or
IEEE 48-bit MAC addresses */
#if (UIP_LLADDR_LEN == 8)
memcpy(ipaddr->u8 + 8, lladdr, UIP_LLADDR_LEN);
ipaddr->u8[8] ^= 0x02;
#elif (UIP_LLADDR_LEN == 6)
memcpy(ipaddr->u8 + 8, lladdr, 3);
ipaddr->u8[11] = 0xff;
ipaddr->u8[12] = 0xfe;
memcpy(ipaddr->u8 + 13, lladdr + 3, 3);
ipaddr->u8[8] ^= 0x02;
#else
#error cannot build interface address when UIP_LLADDR_LEN is not 6 or 8
/*
UIP_LOG("CAN NOT BUIL INTERFACE IDENTIFIER");
UIP_LOG("THE STACK IS GOING TO SHUT DOWN");
UIP_LOG("THE HOST WILL BE UNREACHABLE");
exit(-1);
*/
#endif
}
/********** UIP.c ****************/
static u16_t
chksum(u16_t sum, const u8_t *data, u16_t len)
{
u16_t t;
const u8_t *dataptr;
const u8_t *last_byte;
dataptr = data;
last_byte = data + len - 1;
while(dataptr < last_byte) { /* At least two more bytes */
t = (dataptr[0] << 8) + dataptr[1];
sum += t;
if(sum < t) {
sum++; /* carry */
}
dataptr += 2;
}
if(dataptr == last_byte) {
t = (dataptr[0] << 8) + 0;
sum += t;
if(sum < t) {
sum++; /* carry */
}
}
/* Return sum in host byte order. */
return sum;
}
static u16_t
upper_layer_chksum(u8_t proto)
{
u16_t upper_layer_len;
u16_t sum;
upper_layer_len = (((u16_t)(UIP_IP_BUF->len[0]) << 8) + UIP_IP_BUF->len[1]) ;
/* First sum pseudoheader. */
/* IP protocol and length fields. This addition cannot carry. */
sum = upper_layer_len + proto;
/* Sum IP source and destination addresses. */
sum = chksum(sum, (u8_t *)&UIP_IP_BUF->srcipaddr, 2 * sizeof(uip_ipaddr_t));
/* Sum TCP header and data. */
sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN],
upper_layer_len);
return (sum == 0) ? 0xffff : htons(sum);
}
/*---------------------------------------------------------------------------*/
u16_t
uip_icmp6chksum(void)
{
return upper_layer_chksum(UIP_PROTO_ICMP6);
}
#endif /* CONTIKI_NO_NET */

218
platform/avr-ravenusb/rng.c Normal file
View file

@ -0,0 +1,218 @@
// ADC-based strong RNG
// Very slow, but who cares---if you need fast random numbers, use a PRNG.
#include "rng.h"
#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>
#include "contiki.h"
#ifndef RNG_CONF_USE_ADC
#define RNG_CONF_USE_ADC (!RNG_CONF_USE_RADIO_CLOCK && defined(ADMUX) && defined(ADCSRA) && defined(ADCSRB) && defined(ADSC) && defined(ADEN))
#endif
#ifndef RNG_CONF_USE_RADIO_CLOCK
#define RNG_CONF_USE_RADIO_CLOCK ((!RNG_CONF_USE_ADC) && RF230BB)
#endif
#define TEMPORAL_AGITATION() do { static uint8_t agitator; agitator*=97; agitator+=101; _delay_us(agitator>>1); } while (0);
// -------------------------------------------------------------------------
#if RNG_CONF_USE_ADC
/* The hope is that there is enough noise in the LSB when pointing the
** ADC at the internal band-gap input and using the internal 2.56v
** AREF.
**
** TODO: Run some randomness tests on the output of this RNG!
*/
#define BITS_TO_SHIFT 9
#define ADC_CHAN_ADC1 ((0<<MUX4)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(1<<MUX0))
#define ADC_CHAN_BAND_GAP ((1<<MUX4)|(1<<MUX3)|(1<<MUX2)|(1<<MUX1)|(0<<MUX0))
#define ADC_REF_AREF ((0<<REFS1)|(0<<REFS0))
#define ADC_REF_AVCC ((0<<REFS1)|(1<<REFS0))
#define ADC_REF_INT ((1<<REFS1)|(1<<REFS0))
#define ADC_TRIG_FREE_RUN ((0<<ADTS2)|(0<<ADTS1)|(0<<ADTS0))
#define ADC_PS_128 ((1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0))
#define ADC_PS_2 ((0<<ADPS2)|(0<<ADPS1)|(1<<ADPS0))
#ifndef CONTIKI_CONF_RNG_ADC_CHANNEL
#define CONTIKI_CONF_RNG_ADC_CHANNEL ADC_CHAN_BAND_GAP
#endif
#ifndef CONTIKI_CONF_RNG_ADC_REF
#define CONTIKI_CONF_RNG_ADC_REF ADC_REF_INT
#endif
static uint8_t
extract_random_bit_() {
uint8_t ret = 0;
// Store the state so that we can restore it when we are done.
uint8_t sreg = SREG;
uint8_t adcsra = ADCSRA;
uint8_t admux = ADMUX;
uint8_t adcsrb = ADCSRB;
#ifdef PRR
uint8_t prr = PRR;
#endif
// Disable interrupts
cli();
#ifdef PRR
// Enable ADC module
PRR &= ~(1 << PRADC);
#endif
// Wait for any ADC conversion which
// might currently be happening to finish.
while(ADCSRA & (1<<ADSC));
// Configure the ADC module
ADCSRA = (1<<ADEN)|ADC_PS_128;
ADMUX = (uint8_t)CONTIKI_CONF_RNG_ADC_REF|(uint8_t)CONTIKI_CONF_RNG_ADC_CHANNEL;
ADCSRB = ADC_TRIG_FREE_RUN;
// This loop is where we try to come up with our
// random bit. Unfortunately, the time it takes
// for this to happen is non-deterministic, but
// the result should be non-biased random bit.
do {
// Start conversion for first bit
ADCSRA |= (1<<ADSC);
// Wait for conversion to complete.
while(ADCSRA & (1<<ADSC));
ret = (ADC&1);
ret <<= 1;
// Start conversion for second bit
ADCSRA |= (1<<ADSC);
// Wait for conversion to complete.
while(ADCSRA & (1<<ADSC));
ret |= (ADC&1);
// Toggling the reference voltage
// seems to help introduce noise.
ADMUX^=(1<<REFS1);
// We only want to exit the loop if the first
// and second sampled bits are different.
// This is preliminary conditioning.
} while((ret==0)||(ret==3));
// Toss out the other bit, we only care about one of them.
ret &= 1;
ADCSRA=0;
// Restore the state
ADCSRB = adcsrb;
ADMUX = admux;
ADCSRA = adcsra;
#ifdef PRR
PRR = prr;
#endif
SREG = sreg;
return ret;
}
// -------------------------------------------------------------------------
#elif RNG_CONF_USE_RADIO_CLOCK
/* Here we are hoping to find some noise in the clock skew
** of two different oscilating crystals. On the RZUSBstick,
** there are two such crystals: An 8MHz crystal for the
** microcontroller, and a 16MHz crystal and for the radio.
** The MCLK pin of the RF230 chip is conveniently connected
** to pin 6 of port D. First we need to have the radio
** output the 16MHz signal (it defaults to 1MHz), and then
** we can try to find some noise by sampling pin 6 of port D.
**
** The suitability of this method as a real random number
** generator has yet to be determined. It is entirely possible
** that the perceived randomness of the output is due to
** the temporal agitator mechanism that I have employed.
** Use with caution!
**
** TODO: Run some randomness tests on the output of this RNG!
*/
#define BITS_TO_SHIFT 8
#include "radio/rf230bb/hal.h"
#include "radio/rf230bb/at86rf230_registermap.h"
#ifndef TRX_CTRL_0
#define TRX_CTRL_0 0x03
#endif
static uint8_t
extract_random_bit_() {
uint8_t ret;
uint8_t trx_ctrl_0 = hal_register_read(TRX_CTRL_0);
// Set radio clock output to 8MHz
hal_register_write(TRX_CTRL_0,0x8|5);
do {
TEMPORAL_AGITATION(); // WARNING: This step may hide lack of entropy!
ret = !!(PIND&(1<<6));
ret <<= 1;
ret |= !!(PIND&(1<<6));
} while((ret==0)||(ret==3));
// Toss out the other bit, we only care about one of them.
ret &= 1;
// Restore the clkm state
hal_register_write(TRX_CTRL_0,trx_ctrl_0);
return ret;
}
#endif
// -------------------------------------------------------------------------
static uint8_t
extract_random_bit() {
uint8_t ret;
// These next two lines attempt to sync ourselves to
// any pattern that might happen to be present in the
// raw random source stream. After this, we use the
// bias removal mechanism below to filter out the first
// sign of noise.
while(extract_random_bit_()==1);
while(extract_random_bit_()==0);
do {
ret = extract_random_bit_();
ret <<= 1;
ret |= extract_random_bit_();
} while((ret==0)||(ret==3));
// Toss out the other bit, we only care about one of them.
ret &= 1;
return ret;
}
uint8_t
rng_get_uint8() {
uint8_t ret = 0, i;
for(i=0;i<BITS_TO_SHIFT;i++) {
// Leftshift.
ret <<= 1;
// Add a random bit.
ret |= extract_random_bit();
}
return ret;
}

View file

@ -0,0 +1,13 @@
#ifndef __AVR_RNG_H__
#define __AVR_RNG_H__
#include <inttypes.h>
//! Returns a byte with eight random bits.
/*! This function is very slow, and should only
** be used when true random entropy is required.
** The time it will take to complete is non-deterministic.
*/
extern uint8_t rng_get_uint8();
#endif

View file

@ -53,12 +53,14 @@
//TODO: Should be able to always use this SIMPLE mode, hence can remove the 'complex' mode permanently //TODO: Should be able to always use this SIMPLE mode, hence can remove the 'complex' mode permanently
//TODO: RF230BB !SIMPLE works on XP, Ubuntu. SIMPLE works on Vista, W7. Find out why! //TODO: RF230BB !SIMPLE works on XP, Ubuntu. SIMPLE works on Vista, W7. Find out why!
#if RF230BB
#define UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS 1
#else
#define UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS 1
#endif
#ifndef UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS
#define UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS 0
#endif // ifndef UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS
#ifndef UIP_CONF_AUTO_SUBSTITUTE_LOCAL_MAC_ADDR
#define UIP_CONF_AUTO_SUBSTITUTE_LOCAL_MAC_ADDR 1
#endif // ifndef UIP_CONF_AUTO_SUBSTITUTE_LOCAL_MAC_ADDR
#if UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS #if UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS
/** /**
@ -255,12 +257,10 @@
#define MSB(u16) (((uint8_t *)&(u16))[1]) //!< Most significant byte of \a u16. #define MSB(u16) (((uint8_t *)&(u16))[1]) //!< Most significant byte of \a u16.
#endif #endif
#if UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS static const uint64_t simple_trans_ethernet_addr = 0x3E3D3C3B3AF2ULL;
#define rndis_ethernet_addr local_ethernet_addr extern uint64_t usb_ethernet_addr;
static uint64_t local_ethernet_addr = 0x3A3B3C3D3E3FULL;
#else extern uint64_t macLongAddr;
extern uint64_t rndis_ethernet_addr;
#endif
#if !RF230BB #if !RF230BB
extern void (*pinput)(const struct mac_driver *r); extern void (*pinput)(const struct mac_driver *r);
@ -272,7 +272,6 @@ usbstick_mode_t usbstick_mode;
uint8_t mac_createSicslowpanLongAddr(uint8_t * ethernet, uip_lladdr_t * lowpan); uint8_t mac_createSicslowpanLongAddr(uint8_t * ethernet, uip_lladdr_t * lowpan);
uint8_t mac_createEthernetAddr(uint8_t * ethernet, uip_lladdr_t * lowpan); uint8_t mac_createEthernetAddr(uint8_t * ethernet, uip_lladdr_t * lowpan);
uint8_t mac_createDefaultEthernetAddr(uint8_t * ethernet); uint8_t mac_createDefaultEthernetAddr(uint8_t * ethernet);
uint8_t memcmp_reverse(uint8_t * a, uint8_t * b, uint8_t num);
void mac_ethhijack_nondata(const struct mac_driver *r); void mac_ethhijack_nondata(const struct mac_driver *r);
void mac_ethhijack(const struct mac_driver *r); void mac_ethhijack(const struct mac_driver *r);
@ -294,18 +293,6 @@ uint8_t prefixBuffer[PREFIX_BUFFER_SIZE][3];
/* 6lowpan max size + ethernet header size + 1 */ /* 6lowpan max size + ethernet header size + 1 */
uint8_t raw_buf[127+ UIP_LLH_LEN +1]; uint8_t raw_buf[127+ UIP_LLH_LEN +1];
/* RPL uses some core tcpip routines which includes another tcpip_input */
#if UIP_CONF_IPV6_RPL
#warning ---------------------------------------------------------------
#warning For RPL comment out the tcpip_input routine in core/net/tcpip.c
#warning ---------------------------------------------------------------
#endif
void tcpip_input( void )
{
// printf("tcpip_input");
mac_LowpanToEthernet();
}
/** /**
* \brief Perform any setup needed * \brief Perform any setup needed
*/ */
@ -340,26 +327,27 @@ void mac_ethernetToLowpan(uint8_t * ethHeader)
uip_lladdr_t destAddr; uip_lladdr_t destAddr;
uip_lladdr_t *destAddrPtr = NULL; uip_lladdr_t *destAddrPtr = NULL;
PRINTF("Packet type: %x\n\r", ((struct uip_eth_hdr *) ethHeader)->type); PRINTF("Packet type: 0x%04x\n\r", ntohs(((struct uip_eth_hdr *) ethHeader)->type));
//RUM doesn't support sending data //RUM doesn't support sending data
#if UIP_CONF_USE_RUM #if UIP_CONF_USE_RUM
return; return;
#endif #endif
//If not IPv6 we don't do anything // In sniffer mode we don't ever send anything
if (((struct uip_eth_hdr *) ethHeader)->type != HTONS(UIP_ETHTYPE_IPV6)) { if (usbstick_mode.sendToRf == 0) {
PRINTF("eth2low: Packet is not IPv6, dropping\n\r");
// printf("!ipv6");
#if !RF230BB
rndis_stat.txbad++;
#endif
uip_len = 0; uip_len = 0;
return; return;
} }
// In sniffer mode we don't ever send anything
if (usbstick_mode.sendToRf == 0) { //If not IPv6 we don't do anything
if (((struct uip_eth_hdr *) ethHeader)->type != HTONS(UIP_ETHTYPE_IPV6)) {
PRINTF("eth2low: Dropping packet w/type=0x%04x\n",ntohs(((struct uip_eth_hdr *) ethHeader)->type));
// printf("!ipv6");
#if !RF230BB
usb_eth_stat.txbad++;
#endif
uip_len = 0; uip_len = 0;
return; return;
} }
@ -377,21 +365,16 @@ void mac_ethernetToLowpan(uint8_t * ethHeader)
(((struct uip_eth_hdr *) ethHeader)->dest.addr[4] == 0xFF) && (((struct uip_eth_hdr *) ethHeader)->dest.addr[4] == 0xFF) &&
(((struct uip_eth_hdr *) ethHeader)->dest.addr[5] == 0xFF) ) { (((struct uip_eth_hdr *) ethHeader)->dest.addr[5] == 0xFF) ) {
/* IPv6 does not use broadcast addresses, hence this should not happen */ /* IPv6 does not use broadcast addresses, hence this should not happen */
PRINTF("eth2low: Ethernet broadcast address received, should not happen?\n\r"); PRINTF("eth2low: Dropping broadcast packet\n\r");
#if !RF230BB #if !RF230BB
rndis_stat.txbad++; usb_eth_stat.txbad++;
#endif #endif
uip_len = 0; uip_len = 0;
return; return;
} else { } else {
#if UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS /* Simple Address Translation */
/* Simple Address Translation */ if(memcmp((uint8_t *)&simple_trans_ethernet_addr, &(((struct uip_eth_hdr *) ethHeader)->dest.addr[0]), 6) == 0) {
#if RF230BB
if(memcmp((uint8_t *)&rndis_ethernet_addr, &(((struct uip_eth_hdr *) ethHeader)->dest.addr[0]), 6) == 0) {
#else
if(memcmp_reverse((uint8_t *)&rndis_ethernet_addr, &(((struct uip_eth_hdr *) ethHeader)->dest.addr[0]), 6) == 0) {
#endif
//Addressed to us: make 802.15.4 address from IPv6 Address //Addressed to us: make 802.15.4 address from IPv6 Address
destAddr.addr[0] = UIP_IP_BUF->destipaddr.u8[8] ^ 0x02; destAddr.addr[0] = UIP_IP_BUF->destipaddr.u8[8] ^ 0x02;
destAddr.addr[1] = UIP_IP_BUF->destipaddr.u8[9]; destAddr.addr[1] = UIP_IP_BUF->destipaddr.u8[9];
@ -403,20 +386,22 @@ void mac_ethernetToLowpan(uint8_t * ethHeader)
destAddr.addr[7] = UIP_IP_BUF->destipaddr.u8[15]; destAddr.addr[7] = UIP_IP_BUF->destipaddr.u8[15];
destAddrPtr = &destAddr; destAddrPtr = &destAddr;
} else { }
#if UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS
else {
//Not addressed to us //Not addressed to us
uip_len = 0; uip_len = 0;
return; return;
} }
#else
/* Complex Address Translation */ /* Complex Address Translation */
#else
PRINTF("eth2low: Addressed packet received... "); PRINTF("eth2low: Addressed packet received... ");
//Check this returns OK //Check this returns OK
if (mac_createSicslowpanLongAddr( &(((struct uip_eth_hdr *) ethHeader)->dest.addr[0]), &destAddr) == 0) { if (mac_createSicslowpanLongAddr( &(((struct uip_eth_hdr *) ethHeader)->dest.addr[0]), &destAddr) == 0) {
PRINTF(" translation failed\n\r"); PRINTF(" translation failed\n\r");
#if !RF230BB #if !RF230BB
rndis_stat.txbad++; usb_eth_stat.txbad++;
#endif #endif
uip_len = 0; uip_len = 0;
return; return;
@ -441,13 +426,11 @@ void mac_ethernetToLowpan(uint8_t * ethHeader)
#endif #endif
} }
if (usbstick_mode.sendToRf){ tcpip_output(destAddrPtr);
tcpip_output(destAddrPtr);
#if !RF230BB #if !RF230BB
rndis_stat.txok++; usb_eth_stat.txok++;
#endif #endif
}
uip_len = 0; uip_len = 0;
} }
@ -488,13 +471,16 @@ void mac_LowpanToEthernet(void)
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
} }
#if UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS #if !UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS
mac_createDefaultEthernetAddr((uint8_t *) &(ETHBUF(uip_buf)->src.addr[0]));
#else
//Source ethernet depends on node //Source ethernet depends on node
mac_createEthernetAddr((uint8_t *) &(ETHBUF(uip_buf)->src.addr[0]), if(!mac_createEthernetAddr(
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); (uint8_t *) &(ETHBUF(uip_buf)->src.addr[0]),
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)
))
#endif #endif
{
mac_createDefaultEthernetAddr((uint8_t *) &(ETHBUF(uip_buf)->src.addr[0]));
}
//We only do address translation in network mode! //We only do address translation in network mode!
if (usbstick_mode.translate) { if (usbstick_mode.translate) {
@ -508,7 +494,7 @@ void mac_LowpanToEthernet(void)
usb_eth_send(uip_buf, uip_len, 1); usb_eth_send(uip_buf, uip_len, 1);
#if !RF230BB #if !RF230BB
rndis_stat.rxok++; usb_eth_stat.rxok++;
#endif #endif
uip_len = 0; uip_len = 0;
} }
@ -653,13 +639,10 @@ int8_t mac_translateIcmpLinkLayer(lltype_t target)
// printf("createsicslowpanlongaddr"); // printf("createsicslowpanlongaddr");
mac_createSicslowpanLongAddr(llbuf, (uip_lladdr_t *)UIP_ICMP_OPTS(icmp_opt_offset)->data); mac_createSicslowpanLongAddr(llbuf, (uip_lladdr_t *)UIP_ICMP_OPTS(icmp_opt_offset)->data);
} else { } else {
if (UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS) { #if !UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS
//Simple address translation always sets this as default if(!mac_createEthernetAddr(UIP_ICMP_OPTS(icmp_opt_offset)->data, (uip_lladdr_t *)llbuf))
#endif
mac_createDefaultEthernetAddr(UIP_ICMP_OPTS(icmp_opt_offset)->data); mac_createDefaultEthernetAddr(UIP_ICMP_OPTS(icmp_opt_offset)->data);
} else {
//Complex address translation sets this as something special
mac_createEthernetAddr(UIP_ICMP_OPTS(icmp_opt_offset)->data, (uip_lladdr_t *)llbuf);
}
} }
//Adjust the length //Adjust the length
@ -715,6 +698,15 @@ int8_t mac_translateIcmpLinkLayer(lltype_t target)
*/ */
uint8_t mac_createSicslowpanLongAddr(uint8_t * ethernet, uip_lladdr_t * lowpan) uint8_t mac_createSicslowpanLongAddr(uint8_t * ethernet, uip_lladdr_t * lowpan)
{ {
#if UIP_CONF_AUTO_SUBSTITUTE_LOCAL_MAC_ADDR
//Special case - if the address is our address, we just copy over what we know to be
//our 802.15.4 address
if (memcmp((uint8_t *)&usb_ethernet_addr, ethernet, 6) == 0)
{
memcpy((uint8_t *)lowpan, &macLongAddr, UIP_LLADDR_LEN);
return 1;
}
#endif
#if UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS #if UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS
@ -733,56 +725,36 @@ uint8_t mac_createSicslowpanLongAddr(uint8_t * ethernet, uip_lladdr_t * lowpan)
uint8_t index; uint8_t index;
#if UIP_LLADDR_LEN == 8 #if UIP_LLADDR_LEN == 8
//Special case - if the address is our address, we just copy over what we know to be
//our 802.15.4 address
#if RF230BB
if (memcmp((uint8_t *)&uip_lladdr.addr[2], ethernet, 6) == 0) {
// printf("here1");
memcpy((uint8_t *)lowpan, uip_lladdr.addr, 8);
#else
if (memcmp_reverse((uint8_t *)&rndis_ethernet_addr, ethernet, 6) == 0) {
memcpy((uint8_t *)lowpan, &macLongAddr, 8);
byte_reverse((uint8_t *)lowpan, 8);
#endif
return 1;
}
//Check if translate bit is set, hence we have to look up the prefix //Check if translate bit is set, hence we have to look up the prefix
if (ethernet[0] & TRANSLATE_BIT_MASK) { if((ethernet[0]&(TRANSLATE_BIT_MASK|MULTICAST_BIT_MASK|LOCAL_BIT_MASK)) == (TRANSLATE_BIT_MASK|LOCAL_BIT_MASK)) {
//Get top bits //Get top bits
index = ethernet[0] >> 3; index = ethernet[0] >> 3;
//Check this is plausible...
if (index >= prefixCounter) {
return 0;
}
//Copy over prefix //Copy over prefix
lowpan->addr[0] = prefixBuffer[index][0]; lowpan->addr[0] = prefixBuffer[index][0];
lowpan->addr[3] = prefixBuffer[index][1]; lowpan->addr[1] = prefixBuffer[index][1];
lowpan->addr[4] = prefixBuffer[index][2]; lowpan->addr[2] = prefixBuffer[index][2];
lowpan->addr[3] = ethernet[1];
//Bit is clear lowpan->addr[4] = ethernet[2];
//so we copy all six
//Check this is plausible...
if (index >= prefixCounter)
return 0;
} else { } else {
// printf("here3");
lowpan->addr[0] = ethernet[0]; lowpan->addr[0] = ethernet[0];
lowpan->addr[1] = ethernet[1];
lowpan->addr[2] = ethernet[2];
lowpan->addr[3] = 0xff; lowpan->addr[3] = 0xff;
lowpan->addr[4] = 0xfe; lowpan->addr[4] = 0xfe;
} }
//Copy over reamining five bytes lowpan->addr[5] = ethernet[3];
lowpan->addr[1] = ethernet[1]; lowpan->addr[6] = ethernet[4];
lowpan->addr[2] = ethernet[2]; lowpan->addr[7] = ethernet[5];
lowpan->addr[5] = ethernet[3];
lowpan->addr[6] = ethernet[4];
lowpan->addr[7] = ethernet[5];
#else //UIP_LLADDR != 8 #else //UIP_LLADDR != 8
// Not sure when we would ever hit this case...
uint8_t i; uint8_t i;
// printf("here4");
for(i = 0; i < UIP_LLADDR_LEN; i++) { for(i = 0; i < UIP_LLADDR_LEN; i++) {
lowpan->addr[i] = ethernet[i]; lowpan->addr[i] = ethernet[i];
} }
@ -801,6 +773,14 @@ uint8_t mac_createSicslowpanLongAddr(uint8_t * ethernet, uip_lladdr_t * lowpan)
*/ */
uint8_t mac_createEthernetAddr(uint8_t * ethernet, uip_lladdr_t * lowpan) uint8_t mac_createEthernetAddr(uint8_t * ethernet, uip_lladdr_t * lowpan)
{ {
#if UIP_CONF_AUTO_SUBSTITUTE_LOCAL_MAC_ADDR
//Special case - if the address is our address, we just copy over what we know to be
//our 802.3 address
if (memcmp((uint8_t *)&macLongAddr, (uint8_t *)lowpan, UIP_LLADDR_LEN) == 0) {
usb_eth_get_mac_address(ethernet);
return 1;
}
#endif
#if UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS #if UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS
@ -819,26 +799,11 @@ uint8_t mac_createEthernetAddr(uint8_t * ethernet, uip_lladdr_t * lowpan)
#if UIP_LLADDR_LEN == 8 #if UIP_LLADDR_LEN == 8
//Special case - if the address is our address, we just copy over what we know to be //Check if we need to do anything:
//our 802.3 address if ((lowpan->addr[3] == 0xff) && (lowpan->addr[4] == 0xfe) &&
#if RF230BB ((lowpan->addr[0] & TRANSLATE_BIT_MASK) == 0) &&
if (memcmp(uip_lladdr.addr, (uint8_t *)lowpan, 8) == 0) { ((lowpan->addr[0] & MULTICAST_BIT_MASK) == 0) &&
memcpy(ethernet, &uip_lladdr.addr[2], 6); (lowpan->addr[0] & LOCAL_BIT_MASK)) {
#else
if (memcmp_reverse((uint8_t *)&macLongAddr, (uint8_t *)lowpan, 8) == 0) {
memcpy(ethernet, &rndis_ethernet_addr, 6);
byte_reverse(ethernet, 6);
#endif
return 1;
}
//Check if we need to do anything:
if ((lowpan->addr[3] == 0xff) && (lowpan->addr[4] == 0xfe) &&
((lowpan->addr[0] & TRANSLATE_BIT_MASK) == 0) &&
((lowpan->addr[0] & MULTICAST_BIT_MASK) == 0) &&
(lowpan->addr[0] & LOCAL_BIT_MASK)) {
/** Nope: just copy over 6 bytes **/ /** Nope: just copy over 6 bytes **/
ethernet[0] = lowpan->addr[0]; ethernet[0] = lowpan->addr[0];
@ -854,48 +819,45 @@ uint8_t mac_createEthernetAddr(uint8_t * ethernet, uip_lladdr_t * lowpan)
/** Yes: need to store prefix **/ /** Yes: need to store prefix **/
for (i = 0; i < prefixCounter; i++) { for (i = 0; i < prefixCounter; i++) {
//Check the current prefix - if it fails, check next one //Check the current prefix - if it fails, check next one
if ((lowpan->addr[0] == prefixBuffer[i][0]) &&
(lowpan->addr[1] == prefixBuffer[i][1]) &&
(lowpan->addr[2] == prefixBuffer[i][2])) {
if ((lowpan->addr[0] == prefixBuffer[i][0]) && break;
(lowpan->addr[3] == prefixBuffer[i][1]) && }
(lowpan->addr[4] == prefixBuffer[i][2])) { }
break;
}
}
index = i; index = i;
//Deal with overflow, iron-fist style if (index >= PREFIX_BUFFER_SIZE) {
if (index >= PREFIX_BUFFER_SIZE) { // Overflow. Fall back to simple translation.
index = 0; // TODO: Implement me!
prefixCounter = PREFIX_BUFFER_SIZE; ethernet[0] = lowpan->addr[0];
} else { ethernet[1] = lowpan->addr[1];
//Are we making a new one? ethernet[2] = lowpan->addr[2];
if (index == prefixCounter) { ethernet[3] = lowpan->addr[5];
prefixCounter++; ethernet[4] = lowpan->addr[6];
} ethernet[5] = lowpan->addr[7];
} return 0;
} else {
//Are we making a new one?
if (index == prefixCounter) {
prefixCounter++;
prefixBuffer[index][0] = lowpan->addr[0];
prefixBuffer[index][1] = lowpan->addr[1];
prefixBuffer[index][2] = lowpan->addr[2];
}
//Copy the prefix over, no matter if we have a new or old one //Create ethernet MAC address now
prefixBuffer[index][0] = lowpan->addr[0]; ethernet[0] = TRANSLATE_BIT_MASK | LOCAL_BIT_MASK | (index << 3);
prefixBuffer[index][1] = lowpan->addr[3]; ethernet[1] = lowpan->addr[3];
prefixBuffer[index][2] = lowpan->addr[4]; ethernet[2] = lowpan->addr[4];
ethernet[3] = lowpan->addr[5];
//Create ethernet MAC address now ethernet[4] = lowpan->addr[6];
ethernet[1] = lowpan->addr[1]; ethernet[5] = lowpan->addr[7];
ethernet[2] = lowpan->addr[2]; }
ethernet[3] = lowpan->addr[5]; }
ethernet[4] = lowpan->addr[6];
ethernet[5] = lowpan->addr[7];
ethernet[0] = TRANSLATE_BIT_MASK | LOCAL_BIT_MASK | (index << 3);
}
#else //UIP_LLADDR_LEN != 8 #else //UIP_LLADDR_LEN != 8
// Not sure when we would ever hit this case...
//Create ethernet MAC address now //Create ethernet MAC address now
for(i = 0; i < UIP_LLADDR_LEN; i++) { for(i = 0; i < UIP_LLADDR_LEN; i++) {
ethernet[i] = lowpan->addr[i]; ethernet[i] = lowpan->addr[i];
@ -906,20 +868,15 @@ uint8_t mac_createEthernetAddr(uint8_t * ethernet, uip_lladdr_t * lowpan)
return 1; return 1;
} }
#if UIP_CONF_SIMPLE_JACKDAW_ADDR_TRANS
/** /**
* \brief Create a 802.3 address (default) * \brief Create a 802.3 address (default)
* \param ethernet Pointer to ethernet address * \param ethernet Pointer to ethernet address
*/ */
uint8_t mac_createDefaultEthernetAddr(uint8_t * ethernet) uint8_t mac_createDefaultEthernetAddr(uint8_t * ethernet)
{ {
memcpy(ethernet, &rndis_ethernet_addr, 6); memcpy(ethernet, &simple_trans_ethernet_addr, 6);
#if !RF230BB
byte_reverse(ethernet, 6);
#endif
return 1; return 1;
} }
#endif
/** /**
* \brief Slide the pointed to memory up a certain amount, * \brief Slide the pointed to memory up a certain amount,
* growing/shrinking a buffer * growing/shrinking a buffer
@ -952,6 +909,104 @@ void slide(uint8_t * data, uint8_t length, int16_t slide)
} }
} }
//#define ETHBUF(x) ((struct uip_eth_hdr *)x)
//#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
void
mac_log_802_15_4_tx(const uint8_t* buffer, size_t total_len) {
if (usbstick_mode.raw != 0) {
uint8_t sendlen;
static uint8_t raw_buf[127+ UIP_LLH_LEN +1];
/* Get the raw frame */
memcpy(&raw_buf[UIP_LLH_LEN], buffer, total_len);
sendlen = total_len;
/* Setup generic ethernet stuff */
ETHBUF(raw_buf)->type = htons(0x809A); //UIP_ETHTYPE_802154 0x809A
/* Check for broadcast message */
if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) {
ETHBUF(raw_buf)->dest.addr[0] = 0x33;
ETHBUF(raw_buf)->dest.addr[1] = 0x33;
ETHBUF(raw_buf)->dest.addr[2] = 0x00;
ETHBUF(raw_buf)->dest.addr[3] = 0x00;
ETHBUF(raw_buf)->dest.addr[4] = 0x80;
ETHBUF(raw_buf)->dest.addr[5] = 0x9A;
/*
ETHBUF(raw_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12];
ETHBUF(raw_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13];
ETHBUF(raw_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14];
ETHBUF(raw_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15];
*/
} else {
/* Otherwise we have a real address */
mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->dest.addr[0]),
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
}
// mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0]),(uip_lladdr_t *)&uip_lladdr.addr);
mac_createDefaultEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0]));
sendlen += UIP_LLH_LEN;
usb_eth_send(raw_buf, sendlen, 0);
}
}
void
mac_log_802_15_4_rx(const uint8_t* buf, size_t len) {
if (usbstick_mode.raw != 0) {
uint8_t sendlen;
/* Get the raw frame */
memcpy(&raw_buf[UIP_LLH_LEN], buf, len);
sendlen = len;
/* Setup generic ethernet stuff */
ETHBUF(raw_buf)->type = htons(0x809A); //UIP_ETHTYPE_802154 0x809A
/* Check for broadcast message */
if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) {
ETHBUF(raw_buf)->dest.addr[0] = 0x33;
ETHBUF(raw_buf)->dest.addr[1] = 0x33;
ETHBUF(raw_buf)->dest.addr[2] = 0x00;
ETHBUF(raw_buf)->dest.addr[3] = 0x00;
ETHBUF(raw_buf)->dest.addr[4] = 0x80;
ETHBUF(raw_buf)->dest.addr[5] = 0x9A;
/*
ETHBUF(raw_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12];
ETHBUF(raw_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13];
ETHBUF(raw_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14];
ETHBUF(raw_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15];
*/
} else {
/* Otherwise we have a real address */
mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->dest.addr[0]),
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
}
// mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0]),(uip_lladdr_t *)&uip_lladdr.addr);
mac_createDefaultEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0]));
sendlen += UIP_LLH_LEN;
usb_eth_send(raw_buf, sendlen, 0);
}
}
bool
mac_is_send_enabled(void) {
return usbstick_mode.sendToRf;
}
/** @} */
/** @} */
#if !RF230BB #if !RF230BB
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
/** \brief Process a received 6lowpan packet. Hijack function. /** \brief Process a received 6lowpan packet. Hijack function.
@ -997,58 +1052,7 @@ void mac_ethhijack_nondata(const struct mac_driver *r)
*/ */
void mac_logTXtoEthernet(frame_create_params_t *p,frame_result_t *frame_result) void mac_logTXtoEthernet(frame_create_params_t *p,frame_result_t *frame_result)
{ {
uint8_t sendlen; mac_log_802_15_4_tx(frame_result->frame, frame_result->length);
/* Make sure we are supposed to do this */
if (usbstick_mode.raw == 0) return;
/* Get the raw frame */
memcpy(&raw_buf[UIP_LLH_LEN], frame_result->frame, frame_result->length);
sendlen = frame_result->length;
//Setup generic ethernet stuff
ETHBUF(raw_buf)->type = htons(UIP_ETHTYPE_802154);
uint64_t tempaddr;
//Check for broadcast message
//if(rimeaddr_cmp((const rimeaddr_t *)destAddr, &rimeaddr_null)) {
if( ( p->fcf.destAddrMode == SHORTADDRMODE) &&
( p->dest_addr.addr16 == 0xffff) ) {
ETHBUF(raw_buf)->dest.addr[0] = 0x33;
ETHBUF(raw_buf)->dest.addr[1] = 0x33;
ETHBUF(raw_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12];
ETHBUF(raw_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13];
ETHBUF(raw_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14];
ETHBUF(raw_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15];
} else {
tempaddr = p->dest_addr.addr64;
byte_reverse((uint8_t *)&tempaddr, 8);
//Otherwise we have a real address
mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->dest.addr[0]),
(uip_lladdr_t *)&tempaddr);
}
tempaddr = p->src_addr.addr64;
byte_reverse((uint8_t *)&tempaddr, 8);
mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0]),
(uip_lladdr_t *)&tempaddr);
PRINTF("Low2Eth: Sending 802.15.4 packet to ethernet\n\r");
sendlen += UIP_LLH_LEN;
usb_eth_send(raw_buf, sendlen, 0);
rndis_stat.rxok++;
return;
} }
@ -1059,67 +1063,11 @@ void mac_logTXtoEthernet(frame_create_params_t *p,frame_result_t *frame_result)
* The 6lowpan packet is put in packetbuf by the MAC. This routine passes * The 6lowpan packet is put in packetbuf by the MAC. This routine passes
* it directly to the ethernet layer without decompressing. * it directly to the ethernet layer without decompressing.
*/ */
void mac_802154raw(const struct mac_driver *r) void mac_802154raw(const struct mac_driver *r) {
{ mac_log_802_15_4_tx(radio_frame_data(), radio_frame_length());
uint8_t sendlen;
parsed_frame = sicslowmac_get_frame();
/* Get the raw frame */
memcpy(&raw_buf[UIP_LLH_LEN], radio_frame_data(), radio_frame_length());
sendlen = radio_frame_length();
//Setup generic ethernet stuff
ETHBUF(raw_buf)->type = htons(UIP_ETHTYPE_802154);
//Check for broadcast message
//if(rimeaddr_cmp((const rimeaddr_t *)destAddr, &rimeaddr_null)) {
if( ( parsed_frame->fcf->destAddrMode == SHORTADDRMODE) &&
( parsed_frame->dest_addr->addr16 == 0xffff) ) {
ETHBUF(raw_buf)->dest.addr[0] = 0x33;
ETHBUF(raw_buf)->dest.addr[1] = 0x33;
ETHBUF(raw_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12];
ETHBUF(raw_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13];
ETHBUF(raw_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14];
ETHBUF(raw_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15];
} else {
//Otherwise we have a real address
mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->dest.addr[0]),
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
}
mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0]),
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
PRINTF("Low2Eth: Sending 802.15.4 packet to ethernet\n\r");
sendlen += UIP_LLH_LEN;
usb_eth_send(raw_buf, sendlen, 1);
rndis_stat.rxok++;
return;
} }
uint8_t memcmp_reverse(uint8_t * a, uint8_t * b, uint8_t num)
{
uint8_t i = 0;
while(num) {
num--;
if (a[i] != b[num]) return 1;
i++;
}
return 0;
}
#endif /* !RF230BB */ #endif /* !RF230BB */
/** @} */
/** @} */