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

@ -94,6 +94,14 @@
/** USB RNDIS / Virtual com port setup **/
#ifndef CDC_ECM_USES_INTERRUPT_ENDPOINT
#define CDC_ECM_USES_INTERRUPT_ENDPOINT 0
#endif
#ifndef USB_ETH_EMULATE_WIFI
#define USB_ETH_EMULATE_WIFI 0
#endif
#define NB_ENDPOINTS 7 //! number of endpoints in the application including control endpoint
#define VCP_RX_EP 0x06
#define VCP_TX_EP 0x05

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 ____________________________________________________
#include <stdbool.h>
#include "radio.h"
#include "contiki.h"
#include "config.h"
@ -65,12 +66,18 @@ RNDIS Status Information:
#include "usb_descriptors.h"
#include "usb_specific_request.h"
#include "rndis/rndis_protocol.h"
#include "rndis/rndis_task.h"
#include "uip.h"
#include "serial/uart_usb_lib.h"
#include "sicslow_ethernet.h"
#include <avr/pgmspace.h>
#include <string.h>
#include <stdio.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
//_____ M A C R O S ________________________________________________________
//_____ D E F I N I T I O N ________________________________________________
@ -80,14 +87,10 @@ RNDIS Status Information:
extern PGM_VOID_P pbuffer;
extern U8 data_to_transfer;
//NB: If you change the OID list be sure to update this!!!
//#define OID_LIST_LENGTH 50
#define OID_LIST_LENGTH 35
/**
* \brief List of supported RNDIS OID's
*/
prog_uint32_t OIDSupportedList[OID_LIST_LENGTH] = {
prog_uint32_t OIDSupportedList[] = {
/* Required General */
OID_GEN_SUPPORTED_LIST ,
OID_GEN_HARDWARE_STATUS ,
@ -128,7 +131,7 @@ prog_uint32_t OIDSupportedList[OID_LIST_LENGTH] = {
/*802.11 OID's not fully implemented yet. Hence do not say we
support them */
#ifdef DONOTEVERDEFINETHISORBADSTUFFHAPPENS
#if USB_ETH_EMULATE_WIFI
/* 802.11 OIDs */
OID_802_11_BSSID ,
OID_802_11_SSID ,
@ -156,18 +159,17 @@ prog_uint32_t OIDSupportedList[OID_LIST_LENGTH] = {
OID_PNP_ENABLE_WAKE_UP ,
OID_PNP_ADD_WAKE_UP_PATTERN ,
OID_PNP_REMOVE_WAKE_UP_PATTERN
};
};
#define OID_LIST_LENGTH sizeof(OIDSupportedList)/sizeof(*OIDSupportedList)
rndis_state_t rndis_state;
rndis_stat_t rndis_stat;
usb_eth_stat_t usb_eth_stat;
uint8_t schedule_interrupt = 0;
uint64_t rndis_ethernet_addr = 0x203478928323ULL;
//_____ D E C L A R A T I O N ______________________________________________
@ -188,7 +190,7 @@ U8 data_to_send = 0x00;
*
* \return True on success, false on failure.
*/
uint8_t send_encapsulated_command(uint16_t wLength)
uint8_t rndis_send_encapsulated_command(uint16_t wLength)
{
U8 i = 0;
@ -200,12 +202,6 @@ uint8_t send_encapsulated_command(uint16_t wLength)
if (wLength > ENC_BUF_SIZE)
wLength = ENC_BUF_SIZE;
//For debugging: this shouldn't happen, just checked it didn't
//if (data_to_send) {
// while(1);
//}
//Read in all the bytes...
uint8_t nb_counter;
@ -256,9 +252,13 @@ uint8_t send_encapsulated_command(uint16_t wLength)
m->MinorVersion = RNDIS_MAJOR_VERSION;
m->Status = RNDIS_STATUS_SUCCESS;
m->DeviceFlags = RNDIS_DF_CONNECTIONLESS;
#if USB_ETH_EMULATE_WIFI
m->Medium = NDIS_MEDIUM_WIRELESS_LAN;
#else
m->Medium = RNDIS_MEDIUM_802_3;
#endif // USB_ETH_EMULATE_WIFI
m->MaxPacketsPerTransfer = 1;
m->MaxTransferSize = 1338; /* Space for 1280 IP buffer, Ethernet Header,
m->MaxTransferSize = USB_ETH_MTU + 58; /* Space for 1280 IP buffer, Ethernet Header,
RNDIS messages */
m->PacketAlignmentFactor = 3;
m->AfListOffset = 0;
@ -353,7 +353,9 @@ void rndis_send_interrupt(void)
uint32_t oid_packet_filter = 0x0000000;
#if USB_ETH_EMULATE_WIFI
uint16_t panid = 0xbaad;
#endif
/**
* \brief Function to handle a RNDIS "QUERY" command in the encapsulated_buffer
@ -392,15 +394,20 @@ void rndis_query_process(void)
case OID_GEN_MEDIA_SUPPORTED:
case OID_GEN_MEDIA_IN_USE:
*INFBUF = NDIS_MEDIUM_802_3; /* NDIS_MEDIUM_WIRELESS_LAN instead? */
case OID_GEN_PHYSICAL_MEDIUM:
#if USB_ETH_EMULATE_WIFI
*INFBUF = NDIS_MEDIUM_WIRELESS_LAN;
#else
*INFBUF = NDIS_MEDIUM_802_3;
#endif
break;
case OID_GEN_MAXIMUM_FRAME_SIZE:
*INFBUF = (uint32_t) 1280; //1280 //102; /* Assume 25 octet header on 15.4 */
*INFBUF = (uint32_t) USB_ETH_MTU-14; //1280 //102; /* Assume 25 octet header on 15.4 */
break;
case OID_GEN_LINK_SPEED:
*INFBUF = (uint32_t) 100; /* in 100 bytes/sec units.. this is kinda a lie */
*INFBUF = (uint32_t) 250000/100; /* in 100 bytes/sec units.. this is kinda a lie */
break;
case OID_GEN_TRANSMIT_BLOCK_SIZE:
@ -422,57 +429,35 @@ void rndis_query_process(void)
break;
case OID_GEN_MAXIMUM_TOTAL_SIZE:
*INFBUF = (uint32_t) 1300; //127;
*INFBUF = (uint32_t) USB_ETH_MTU; //127;
break;
case OID_GEN_MEDIA_CONNECT_STATUS:
*INFBUF = NDIS_MEDIA_STATE_CONNECTED;
*INFBUF = usb_eth_is_active?NDIS_MEDIA_STATE_CONNECTED:NDIS_MEDIA_STATE_DISCONNECTED;
break;
case OID_GEN_VENDOR_DRIVER_VERSION:
*INFBUF = 0x00001000;
break;
case OID_GEN_PHYSICAL_MEDIUM:
*INFBUF = NDIS_MEDIUM_802_3; /*NDIS_MEDIUM_WIRELESS_LAN;*/
break;
case OID_GEN_CURRENT_LOOKAHEAD:
*INFBUF = (uint32_t) 1280; //102;
*INFBUF = (uint32_t) USB_ETH_MTU-14; //102;
// case OID_GEN_RNDIS_CONFIG_PARAMETER:
// break;
/******* 802.3 (Ethernet) *******/
/*The address of the NIC encoded in the hardware.*/
case OID_802_3_PERMANENT_ADDRESS:
//Clear unused bytes
*(INFBUF + 1) = 0;
//Set address
*((uint8_t *)INFBUF + 0) = *(((uint8_t * ) &rndis_ethernet_addr) + 5);
*((uint8_t *)INFBUF + 1) = *(((uint8_t * ) &rndis_ethernet_addr) + 4);
*((uint8_t *)INFBUF + 2) = *(((uint8_t * ) &rndis_ethernet_addr) + 3);
*((uint8_t *)INFBUF + 3) = *(((uint8_t * ) &rndis_ethernet_addr) + 2);
*((uint8_t *)INFBUF + 4) = *(((uint8_t * ) &rndis_ethernet_addr) + 1);
*((uint8_t *)INFBUF + 5) = *(((uint8_t * ) &rndis_ethernet_addr) + 0);
/*4+2 = 6 Bytes of eth address */
c->InformationBufferLength += 2;
break;
/*The address the NIC is currently using.*/
case OID_802_3_CURRENT_ADDRESS:
//Clear unused bytes
*(INFBUF + 1) = 0;
//Set address
*((uint8_t *)INFBUF + 0) = *(((uint8_t * ) &rndis_ethernet_addr) + 5);
*((uint8_t *)INFBUF + 1) = *(((uint8_t * ) &rndis_ethernet_addr) + 4);
*((uint8_t *)INFBUF + 2) = *(((uint8_t * ) &rndis_ethernet_addr) + 3);
*((uint8_t *)INFBUF + 3) = *(((uint8_t * ) &rndis_ethernet_addr) + 2);
*((uint8_t *)INFBUF + 4) = *(((uint8_t * ) &rndis_ethernet_addr) + 1);
*((uint8_t *)INFBUF + 5) = *(((uint8_t * ) &rndis_ethernet_addr) + 0);
//get address
usb_eth_get_mac_address((uint8_t*)INFBUF);
/*4+2 = 6 Bytes of eth address */
c->InformationBufferLength += 2;
@ -495,20 +480,14 @@ void rndis_query_process(void)
/* Frames received with alignment error */
case OID_802_3_RCV_ERROR_ALIGNMENT:
*INFBUF = 0;
break;
/* Frames transmitted with one collision */
case OID_802_3_XMIT_ONE_COLLISION:
*INFBUF = 0;
break;
/* Frames transmitted with more than one collision */
case OID_802_3_XMIT_MORE_COLLISIONS:
*INFBUF = 0;
break;
#if USB_ETH_EMULATE_WIFI
/*** 802.11 OIDs ***/
case OID_802_11_BSSID:
*INFBUF = (uint32_t)panid;
@ -543,27 +522,28 @@ void rndis_query_process(void)
case OID_802_11_WEP_STATUS:
case OID_802_11_AUTHENTICATION_MODE:
break;
#endif //USB_ETH_EMULATE_WIFI
/*** Statistical ***/
/* Frames transmitted without errors */
case OID_GEN_XMIT_OK:
*INFBUF = rndis_stat.txok;
*INFBUF = usb_eth_stat.txok;
break;
/* Frames received without errors */
case OID_GEN_RCV_OK:
*INFBUF = rndis_stat.rxok;
*INFBUF = usb_eth_stat.rxok;
break;
/* Frames received with errors */
case OID_GEN_RCV_ERROR:
*INFBUF = rndis_stat.rxbad;
*INFBUF = usb_eth_stat.rxbad;
break;
/* Frames transmitted with errors */
case OID_GEN_XMIT_ERROR:
*INFBUF = rndis_stat.txbad;
*INFBUF = usb_eth_stat.txbad;
break;
/* Frames dropped due to lack of buffer space */
@ -617,9 +597,21 @@ void rndis_query_process(void)
#define CFGBUF ((rndis_config_parameter_t *) INFBUF)
#define PARMNAME ((uint8_t *)CFGBUF + CFGBUF->ParameterNameOffset)
#define PARMVALUE ((uint8_t *)CFGBUF + CFGBUF->ParameterValueOffset)
#define PARMVALUELENGTH CFGBUF->ParameterValueLength
#define PARM_NAME_LENGTH 25 /* Maximum parameter name length */
bool
rndis_handle_config_parm(const char* parmname,const uint8_t* parmvalue,size_t parmlength) {
if (strncmp_P(parmname, PSTR("rawmode"), 7) == 0) {
if (parmvalue[0] == '0') {
usbstick_mode.raw = 0;
} else {
usbstick_mode.raw = 1;
}
}
}
/**
* \brief Function to deal with a RNDIS "SET" command present in the
* encapsulated_buffer
@ -664,13 +656,7 @@ void rndis_set_process(void)
Parameter type: single octet
Parameter values: '0' = disabled, '1' = enabled
*/
if (strncmp_P(parmname, PSTR("rawmode"), 7) == 0) {
if (*PARMVALUE == '0') {
usbstick_mode.raw = 0;
} else {
usbstick_mode.raw = 1;
}
}
rndis_handle_config_parm(parmname,PARMVALUE,PARMVALUELENGTH);
break;
@ -700,6 +686,7 @@ void rndis_set_process(void)
case OID_802_3_MULTICAST_LIST:
break;
#if USB_ETH_EMULATE_WIFI
/* Mandatory 802.11 OIDs */
case OID_802_11_BSSID:
panid = *INFBUF;
@ -708,6 +695,7 @@ void rndis_set_process(void)
case OID_802_11_SSID:
break;
//TODO: rest of 802.11
#endif // USB_ETH_EMULATE_WIFI
/* Power Managment: fails for now */
case OID_PNP_ADD_WAKE_UP_PATTERN:
@ -743,7 +731,7 @@ void rndis_set_process(void)
* the "SEND ENCAPSULATED COMMAND" message, which will trigger
* and interrupt on the host so it knows data is ready.
*/
uint8_t get_encapsulated_command(void)
uint8_t rndis_get_encapsulated_command(void)
{
U8 nb_byte, zlp, i;
@ -828,6 +816,261 @@ uint8_t rndis_send_status(rndis_Status_t stat)
return 0;
}
void rndis_configure_endpoints() {
usb_configure_endpoint(INT_EP, \
TYPE_INTERRUPT, \
DIRECTION_IN, \
SIZE_8, \
ONE_BANK, \
NYET_ENABLED);
usb_configure_endpoint(TX_EP, \
TYPE_BULK, \
DIRECTION_IN, \
SIZE_64, \
TWO_BANKS, \
NYET_ENABLED);
usb_configure_endpoint(RX_EP, \
TYPE_BULK, \
DIRECTION_OUT, \
SIZE_64, \
TWO_BANKS, \
NYET_ENABLED);
Usb_reset_endpoint(INT_EP);
Usb_reset_endpoint(TX_EP);
Usb_reset_endpoint(RX_EP);
}
extern char usb_busy;
extern uint8_t usb_eth_data_buffer[64];
#define PBUF ((rndis_data_packet_t *) usb_eth_data_buffer)
uint8_t rndis_process(void)
{
uint8_t bytecounter, headercounter;
uint16_t i, dataoffset;
if(rndis_state != rndis_data_initialized) { //Enumeration processs OK ?
return 0;
}
#ifdef USB_ETH_HOOK_INIT
static uint8_t doInit = 1;
if (doInit) {
USB_ETH_HOOK_INIT();
doInit = 0;
}
#endif
//Connected!
Led0_on();
Usb_select_endpoint(RX_EP);
//If we have data and a free buffer
if(Is_usb_receive_out() && (uip_len == 0)) {
//Read how much (endpoint only stores up to 64 bytes anyway)
bytecounter = Usb_byte_counter_8();
//Try and read the header in
headercounter = sizeof(rndis_data_packet_t);
uint8_t fail = 0;
//Hmm.. what's going on here
if (bytecounter < headercounter) {
Usb_ack_receive_out();
fail = 1;
}
i = 0;
while (headercounter) {
usb_eth_data_buffer[i] = Usb_read_byte();
bytecounter--;
headercounter--;
i++;
}
//This is no good. Probably lost syncronization... just drop it for now
if(PBUF->MessageType != REMOTE_NDIS_PACKET_MSG) {
Usb_ack_receive_out();
fail = 1;
}
//802.3 does not have OOB data, and we don't care about per-packet data
//so that just leave regular packet data...
if (PBUF->DataLength && (fail == 0)) {
//Looks like we've got a live one
#ifdef USB_ETH_HOOK_RX_START
USB_ETH_HOOK_RX_START();
#endif
//Get offset
dataoffset = PBUF->DataOffset;
//Make it offset from start of message, not DataOffset field
dataoffset += (sizeof(rndis_MessageType_t) + sizeof(rndis_MessageLength_t));
//Subtract what we already took
dataoffset -= sizeof(rndis_data_packet_t);
//Clear this flag
Usb_ack_nak_out();
//Read to the start of data
while(dataoffset) {
Usb_read_byte();
dataoffset--;
bytecounter--;
//If endpoint is done
if (bytecounter == 0) {
Usb_ack_receive_out();
//Wait for new data
while (!Is_usb_receive_out() && (!Is_usb_receive_nak_out()));
//Check for NAK
// TODO: darco: What in the world is this for?
if (Is_usb_receive_nak_out()) {
Usb_ack_nak_out();
break;
}
bytecounter = Usb_byte_counter_8();
//ZLP?
if (bytecounter == 0)
break;
}
}
//Read the data itself in
uint8_t * uipdata = uip_buf;
uint16_t datalen = PBUF->DataLength;
while(datalen) {
*uipdata++ = Usb_read_byte();
datalen--;
bytecounter--;
//If endpoint is done
if (bytecounter == 0) {
//Might be everything we need!
if (datalen) {
Usb_ack_receive_out();
//Wait for new data
if(usb_endpoint_wait_for_receive_out()!=0) {
USB_ETH_HOOK_RX_ERROR("Timeout: receive out");
goto bail;
}
bytecounter = Usb_byte_counter_8();
}
}
}
//Ack final data packet
Usb_ack_receive_out();
#ifdef USB_ETH_HOOK_RX_END
USB_ETH_HOOK_RX_END();
#endif
//Send data over RF or to local stack
if(PBUF->DataLength <= USB_ETH_MTU) {
USB_ETH_HOOK_HANDLE_INBOUND_PACKET(uip_buf,PBUF->DataLength);
} else {
USB_ETH_HOOK_RX_ERROR("Oversized packet");
}
} //if (PBUF->DataLength)
}
bail:
return 1;
}
/**
\brief Send data over RNDIS interface, data is in uipbuf and length is uiplen
*/
uint8_t rndis_send(uint8_t * senddata, uint16_t sendlen, uint8_t led)
{
uint16_t i;
//Setup Header
PBUF->MessageType = REMOTE_NDIS_PACKET_MSG;
PBUF->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_MessageType_t) - sizeof(rndis_MessageLength_t);
PBUF->DataLength = sendlen;
PBUF->OOBDataLength = 0;
PBUF->OOBDataOffset = 0;
PBUF->NumOOBDataElements = 0;
PBUF->PerPacketInfoOffset = 0;
PBUF->PerPacketInfoLength = 0;
PBUF->DeviceVcHandle = 0;
PBUF->Reserved = 0;
PBUF->MessageLength = sizeof(rndis_data_packet_t) + PBUF->DataLength;
//Send Data
Usb_select_endpoint(TX_EP);
Usb_send_in();
//Wait for ready
if(usb_endpoint_wait_for_write_enabled()!=0) {
USB_ETH_HOOK_TX_ERROR("Timeout: write enabled");
return 0;
}
#ifdef USB_ETH_HOOK_TX_START
USB_ETH_HOOK_TX_START();
#endif
//Setup first part of transfer...
for(i = 0; i < sizeof(rndis_data_packet_t); i++) {
Usb_write_byte(usb_eth_data_buffer[i]);
}
//Send packet
while(sendlen) {
Usb_write_byte(*senddata);
senddata++;
sendlen--;
//If endpoint is full, send data in
//And then wait for data to transfer
if (!Is_usb_write_enabled()) {
Usb_send_in();
if(usb_endpoint_wait_for_write_enabled()!=0) {
USB_ETH_HOOK_TX_ERROR("Timeout: write enabled");
return 0;
}
}
}
Usb_send_in();
#ifdef USB_ETH_HOOK_TX_END
USB_ETH_HOOK_TX_END();
#endif
//Wait for ready
if(usb_endpoint_wait_for_IN_ready()!=0) {
USB_ETH_HOOK_TX_ERROR("Timeout: IN ready");
return 0;
}
return 1;
}
/****************** Radio Interface ****************/
@ -837,15 +1080,11 @@ uint8_t rndis_send_status(rndis_Status_t stat)
*/
void rndis_packetFilter(uint32_t newfilter)
{
#if !RF230BB
if (newfilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
rxMode = RX_ON;
radio_set_trx_state(RX_ON);
USB_ETH_HOOK_SET_PROMISCIOUS_MODE(true);
} else {
rxMode = RX_AACK_ON;
radio_set_trx_state(RX_AACK_ON);
USB_ETH_HOOK_SET_PROMISCIOUS_MODE(false);
}
#endif
}
/** @} */

View file

@ -303,22 +303,23 @@ typedef struct{
uint32_t rxok;
uint32_t txbad;
uint32_t rxbad;
} rndis_stat_t;
} usb_eth_stat_t;
extern rndis_stat_t rndis_stat;
extern usb_eth_stat_t usb_eth_stat;
extern rndis_state_t rndis_state;
extern uint8_t schedule_interrupt;
extern uint64_t rndis_ethernet_addr;
uint8_t send_encapsulated_command(uint16_t wLength);
uint8_t get_encapsulated_command(void);
uint8_t rndis_send_encapsulated_command(uint16_t wLength);
uint8_t rndis_get_encapsulated_command(void);
void rndis_send_interrupt(void);
void rndis_query_process(void);
void rndis_set_process(void);
uint8_t rndis_send_status(rndis_Status_t stat);
uint8_t rndis_process(void);
uint8_t rndis_send(uint8_t * senddata, uint16_t sendlen, uint8_t led);
extern void rndis_configure_endpoints();
#endif //_RNDIS_H

View file

@ -59,6 +59,9 @@
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "rndis/cdc_ecm.h"
#include "rndis/cdc_eem.h"
#define BUF ((struct uip_eth_hdr *)&uip_buf[0])
#define PRINTF printf
#define PRINTF_P printf_P
@ -66,12 +69,6 @@
//_____ M A C R O S ________________________________________________________
#define EEMCMD_ECHO 0x00 ///bmEEMCmd Echo
#define EEMCMD_ECHO_RESPONSE 0x01 ///bmEEMCmd Echo Response
#define EEMCMD_SUSPEND_HINT 0x02 ///bmEEMCmd Suspend Hint
#define EEMCMD_RESPONSE_HINT 0x03 ///bmEEMCmd Response Hint
#define EEMCMD_RESPONSE_COMPLETE_HINT 0x04 ///bmEEMCmd Response Complete Hint
#define EEMCMD_TICKLE 0x05 ///bmEEMCmd Tickle
@ -84,436 +81,210 @@
#define RNDIS_TIMEOUT_DETACH 900
#define RNDIS_TIMEOUT_ATTACH 1000
#define PBUF ((rndis_data_packet_t *) data_buffer)
#define PBUF ((rndis_data_packet_t *) usb_eth_data_buffer)
//! Temp data buffer when adding RNDIS headers
uint8_t usb_eth_data_buffer[64];
uint64_t usb_ethernet_addr = 0x010000000002ULL;
//_____ D E C L A R A T I O N S ____________________________________________
uint8_t eem_send(uint8_t * senddata, uint16_t sendlen, uint8_t led);
uint8_t rndis_send(uint8_t * senddata, uint16_t sendlen, uint8_t led);
//! Timers for LEDs
uint8_t led1_timer, led2_timer;
//! Temp data buffer when adding RNDIS headers
uint8_t data_buffer[64];
//! Usb is busy with RNDIS
char usb_busy = 0;
uint8_t usb_eth_is_active = 1;
static struct etimer et;
static struct timer flood_timer;
uint8_t usb_eth_packet_is_available() {
Usb_select_endpoint(RX_EP);
return Is_usb_read_enabled();
}
static uint8_t doInit = 1;
extern uint8_t fingerPresent;
uint8_t usb_eth_ready_for_next_packet() {
#ifdef USB_ETH_HOOK_IS_READY_FOR_INBOUND_PACKET
return USB_ETH_HOOK_IS_READY_FOR_INBOUND_PACKET();
#else
return 1;
#endif
PROCESS(rndis_process, "RNDIS process");
return 1;
}
void rxtx_led_update(void)
{
// turn off LED's if necessary
if (led1_timer) {
led1_timer--;
if(led1_timer&(1<<2))
Led1_on();
else
Led1_off();
}
else
Led1_off();
if (led2_timer) {
led2_timer--;
if(led2_timer&(1<<2))
Led2_on();
else
Led2_off();
}
else
Led2_off();
}
/**
@brief This will enable the RX_START LED for a period
*/
void rx_start_led(void)
{
led1_timer|=(1<<3);
if(((led1_timer-1)&(1<<2)))
Led1_on();
}
/**
@brief This will enable the TRX_END LED for a period
*/
void tx_end_led(void)
{
led2_timer|=(1<<3);
if(((led2_timer-1)&(1<<2)))
Led1_on();
}
#if USB_ETH_CONF_MASS_STORAGE_FALLBACK
static void
usb_eth_setup_timeout_fallback_check() {
extern uint8_t fingerPresent;
/* Device is Enumerated but RNDIS not loading. We might
have a system that does not support IAD (winXP). If so
count the timeout then switch to just network interface. */
static uint16_t iad_fail_timeout, rndis_fail_timeout;
if (usb_mode == rndis_debug) {
//If we have timed out, detach
if (iad_fail_timeout == IAD_TIMEOUT_DETACH) {
//Failed - BUT we are using "reverse logic", hence we force device
//into this mode. This is used to allow Windows Vista have time to
//install the drivers
if (fingerPresent && (rndis_state != rndis_data_initialized) && Is_device_enumerated() ) {
iad_fail_timeout = 0;
} else {
stdout = NULL;
Usb_detach();
doInit = 1; //Also mark system as needing intilizing
}
//Then wait a few before re-attaching
} else if (iad_fail_timeout == IAD_TIMEOUT_ATTACH) {
if (fingerPresent) {
usb_mode = mass_storage;
} else {
usb_mode = rndis_only;
}
Usb_attach();
}
//Increment timeout when device is not initializing, OR we have already detached,
//OR the user had their finger on the device, indicating a reverse of logic
if ( ( (rndis_state != rndis_data_initialized) && Is_device_enumerated() ) ||
(iad_fail_timeout > IAD_TIMEOUT_DETACH) ||
(fingerPresent) ) {
iad_fail_timeout++;
} else {
iad_fail_timeout = 0;
}
} //usb_mode == rndis_debug
/* Device is Enumerated but RNDIS STIL not loading. We just
have RNDIS interface, so obviously no drivers on target.
Just go ahead and mount ourselves as mass storage... */
if (usb_mode == rndis_only) {
//If we have timed out, detach
if (rndis_fail_timeout == RNDIS_TIMEOUT_DETACH) {
Usb_detach();
//Then wait a few before re-attaching
} else if (rndis_fail_timeout == RNDIS_TIMEOUT_ATTACH) {
usb_mode = mass_storage;
Usb_attach();
}
//Increment timeout when device is not initializing, OR we are already
//counting to detach
if ( ( (rndis_state != rndis_data_initialized)) ||
(rndis_fail_timeout > RNDIS_TIMEOUT_DETACH) ) {
rndis_fail_timeout++;
} else {
rndis_fail_timeout = 0;
}
}//usb_mode == rnids_only
}
#endif
PROCESS(usb_eth_process, "USB Ethernet process");
/**
* \brief RNDIS Process
*
* This is the link between USB and the "good stuff". In this routine data
* is received and processed by RNDIS
* is received and processed by RNDIS, CDC-ECM, or CDC-EEM
*/
PROCESS_THREAD(rndis_process, ev, data_proc)
PROCESS_THREAD(usb_eth_process, ev, data_proc)
{
static struct etimer et;
PROCESS_BEGIN();
uint8_t bytecounter, headercounter;
uint16_t i, dataoffset;
clock_time_t timediff;
clock_time_t thetime;
while(1) {
rxtx_led_update();
// turn off LED's if necessary
if (led1_timer) led1_timer--;
else Led1_off();
if (led2_timer) led2_timer--;
else Led2_off();
/* Device is Enumerated but RNDIS not loading. We might
have a system that does not support IAD (winXP). If so
count the timeout then switch to just network interface. */
#if 0
static uint16_t iad_fail_timeout, rndis_fail_timeout;
if (usb_mode == rndis_debug) {
//If we have timed out, detach
if (iad_fail_timeout == IAD_TIMEOUT_DETACH) {
//Failed - BUT we are using "reverse logic", hence we force device
//into this mode. This is used to allow Windows Vista have time to
//install the drivers
if (fingerPresent && (rndis_state != rndis_data_initialized) && Is_device_enumerated() ) {
iad_fail_timeout = 0;
} else {
stdout = NULL;
Usb_detach();
doInit = 1; //Also mark system as needing intilizing
}
//Then wait a few before re-attaching
} else if (iad_fail_timeout == IAD_TIMEOUT_ATTACH) {
if (fingerPresent) {
usb_mode = mass_storage;
} else {
usb_mode = rndis_only;
}
Usb_attach();
}
//Increment timeout when device is not initializing, OR we have already detached,
//OR the user had their finger on the device, indicating a reverse of logic
if ( ( (rndis_state != rndis_data_initialized) && Is_device_enumerated() ) ||
(iad_fail_timeout > IAD_TIMEOUT_DETACH) ||
(fingerPresent) ) {
iad_fail_timeout++;
} else {
iad_fail_timeout = 0;
}
} //usb_mode == rndis_debug
/* Device is Enumerated but RNDIS STIL not loading. We just
have RNDIS interface, so obviously no drivers on target.
Just go ahead and mount ourselves as mass storage... */
if (usb_mode == rndis_only) {
//If we have timed out, detach
if (rndis_fail_timeout == RNDIS_TIMEOUT_DETACH) {
Usb_detach();
//Then wait a few before re-attaching
} else if (rndis_fail_timeout == RNDIS_TIMEOUT_ATTACH) {
usb_mode = mass_storage;
Usb_attach();
}
//Increment timeout when device is not initializing, OR we are already
//counting to detach
if ( ( (rndis_state != rndis_data_initialized)) ||
(rndis_fail_timeout > RNDIS_TIMEOUT_DETACH) ) {
rndis_fail_timeout++;
} else {
rndis_fail_timeout = 0;
}
}//usb_mode == rnids_only
#if USB_ETH_CONF_MASS_STORAGE_FALLBACK
usb_eth_setup_timeout_fallback_check();
#endif
if(rndis_state == rndis_data_initialized) //Enumeration processs OK ?
{
if (doInit) {
//start flood timer
timer_set(&flood_timer, CLOCK_SECOND / 5);
mac_ethernetSetup();
doInit = 0;
}
//Connected!
Led0_on();
Usb_select_endpoint(RX_EP);
//If we have data and a free buffer
if(Is_usb_receive_out() && (uip_len == 0)) {
//TODO: Fix this some better way
//If you need a delay in RNDIS to slow down super-fast sending, insert it here
//Also mark the USB as "in use"
//This is done as "flood control" by only allowing one IP packet per time limit
thetime = clock_time();
timediff = thetime - flood_timer.start;
//Oops, timer wrapped! Just ignore it for now
if (thetime < flood_timer.start) {
timediff = flood_timer.interval;
}
//If timer not yet expired
//if (timediff < flood_timer.interval) {
if (!timer_expired(&flood_timer)) {
//Wait until timer expiers
usb_busy = 1;
etimer_set(&et, flood_timer.interval - timediff);
//Try commenting out the next line if Jackdaw stops RF transmission in Windows after a 5 minute idle period - dak
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
//Reselect endpoint in case we lost it
Usb_select_endpoint(RX_EP);
usb_busy = 0;
}
//Restart flood timer
timer_restart(&flood_timer);
//Read how much (endpoint only stores up to 64 bytes anyway)
bytecounter = Usb_byte_counter_8();
//Try and read the header in
headercounter = sizeof(rndis_data_packet_t);
uint8_t fail = 0;
//Hmm.. what's going on here
if (bytecounter < headercounter) {
Usb_ack_receive_out();
fail = 1;
}
i = 0;
while (headercounter) {
data_buffer[i] = Usb_read_byte();
bytecounter--;
headercounter--;
i++;
}
//This is no good. Probably lost syncronization... just drop it for now
if(PBUF->MessageType != REMOTE_NDIS_PACKET_MSG) {
Usb_ack_receive_out();
fail = 1;
}
//802.3 does not have OOB data, and we don't care about per-packet data
//so that just leave regular packet data...
if (PBUF->DataLength && (fail == 0)) {
//Looks like we've got a live one
rx_start_led();
//Get offset
dataoffset = PBUF->DataOffset;
//Make it offset from start of message, not DataOffset field
dataoffset += (sizeof(rndis_MessageType_t) + sizeof(rndis_MessageLength_t));
//Subtract what we already took
dataoffset -= sizeof(rndis_data_packet_t);
//Clear this flag
Usb_ack_nak_out();
//Read to the start of data
while(dataoffset) {
Usb_read_byte();
dataoffset--;
bytecounter--;
//If endpoint is done
if (bytecounter == 0) {
Usb_ack_receive_out();
//Wait for new data
while (!Is_usb_receive_out() && (!Is_usb_receive_nak_out()));
//Check for NAK
if (Is_usb_receive_nak_out()) {
Usb_ack_nak_out();
break;
}
bytecounter = Usb_byte_counter_8();
//ZLP?
if (bytecounter == 0)
break;
}
}
//Read the data itself in
uint8_t * uipdata = uip_buf;
uint16_t datalen = PBUF->DataLength;
while(datalen) {
*uipdata++ = Usb_read_byte();
datalen--;
bytecounter--;
//If endpoint is done
if (bytecounter == 0) {
//Might be everything we need!
if (datalen) {
Usb_ack_receive_out();
//Wait for new data
while (!Is_usb_receive_out());
bytecounter = Usb_byte_counter_8();
}
}
}
//Ack final data packet
Usb_ack_receive_out();
//Send data over RF or to local stack
uip_len = PBUF->DataLength; //uip_len includes LLH_LEN
mac_ethernetToLowpan(uip_buf);
} //if (PBUF->DataLength)
} //if(Is_usb_receive_out() && (uip_len == 0))
} // if (rndis_data_intialized)
else if(Is_device_enumerated() && //Enumeration processs OK &&
(usb_mode == eem) ) //USB Stick is using EEM
{
uint16_t datalength;
if (doInit) {
mac_ethernetSetup();
doInit = 0;
}
//Connected!
Led0_on();
Usb_select_endpoint(RX_EP);
//If we have data and a free buffer
if(Is_usb_receive_out() && (uip_len == 0)) {
//Read how much (endpoint only stores up to 64 bytes anyway)
bytecounter = Usb_byte_counter_8();
//EEM uses 2 bytes as a header
headercounter = 2;
uint8_t fail = 0;
//Hmm.. what's going on here?
if (bytecounter < headercounter) {
Usb_ack_receive_out();
//TODO CO done = 1;
}
//Read EEM Header
i = 0;
while (headercounter) {
data_buffer[i] = Usb_read_byte();
bytecounter--;
headercounter--;
i++;
}
//Order is LSB/MSB, so MSN is in data_buffer[1]
//Bit 15 indicates command packet when set
if (data_buffer[1] & 0x80) {
//not a data payload
datalength = 0;
} else {
//'0' indicates data packet
//Length is lower 14 bits
datalength = data_buffer[0] | ((data_buffer[1] & 0x3F) << 8);
}
/* EEM Command Packet */
if ((datalength == 0) && (fail == 0))
{
uint8_t command;
uint16_t echoLength;
//Strip command off
command = data_buffer[1] & 0x38;
command = command >> 3;
//Decode command type
switch (command)
{
/* Echo Request */
case EEMCMD_ECHO:
//Get echo length
echoLength = (data_buffer[1] & 0x07) << 8; //MSB
echoLength |= data_buffer[0]; //LSB
//TODO: everything. oops.
break;
/* Everything else: Whatever. */
case EEMCMD_ECHO_RESPONSE:
case EEMCMD_SUSPEND_HINT:
case EEMCMD_RESPONSE_HINT:
case EEMCMD_RESPONSE_COMPLETE_HINT:
case EEMCMD_TICKLE:
break;
default: break;
}
}
/* EEM Data Packet */
else if (datalength && (fail == 0))
{
//Looks like we've got a live one
rx_start_led();
uint16_t bytes_received = 0;
uint16_t dataleft = datalength;
U8 * buffer = uip_buf;
while(dataleft)
{
*buffer++ = Usb_read_byte();
dataleft--;
bytecounter--;
bytes_received++;
//Check if endpoint is done but we are expecting more data
if ((bytecounter == 0) && (dataleft))
{
//ACK previous data
Usb_ack_receive_out();
//Wait for new data
while (!Is_usb_receive_out());
//Get new data
bytecounter = Usb_byte_counter_8();
//ZLP?
if (bytecounter == 0)
{
//Incomplete!!
break;
}
switch(usb_configuration_nb) {
case USB_CONFIG_RNDIS_DEBUG:
case USB_CONFIG_RNDIS:
if(Is_device_enumerated()) {
if(rndis_process()) {
etimer_set(&et, CLOCK_SECOND/80);
} else {
Led0_toggle();
etimer_set(&et, CLOCK_SECOND/8);
}
}
//Ack final data packet
Usb_ack_receive_out();
//Packet has CRC, nobody wants that garbage
datalength -= 4;
//Send data over RF or to local stack
uip_len = datalength; //uip_len includes LLH_LEN
mac_ethernetToLowpan(uip_buf);
} //if (datalength)
} //if(Is_usb_receive_out() && (uip_len == 0))
} // if (Is_device_enumerated())
if ((usb_mode == rndis_only) || (usb_mode == rndis_debug) || (usb_mode == eem)) {
etimer_set(&et, CLOCK_SECOND/80);
} else {
etimer_set(&et, CLOCK_SECOND);
break;
case USB_CONFIG_EEM:
if(Is_device_enumerated())
cdc_eem_process();
etimer_set(&et, CLOCK_SECOND/80);
break;
case USB_CONFIG_ECM:
case USB_CONFIG_ECM_DEBUG:
if(Is_device_enumerated()) {
if(cdc_ecm_process()) {
etimer_set(&et, CLOCK_SECOND/80);
} else {
Led0_toggle();
etimer_set(&et, CLOCK_SECOND/8);
}
}
break;
default:
Led0_toggle();
etimer_set(&et, CLOCK_SECOND/4);
break;
}
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)||(usb_eth_packet_is_available()&&usb_eth_ready_for_next_packet()));
} // while(1)
PROCESS_END();
@ -527,172 +298,70 @@ static uint16_t iad_fail_timeout, rndis_fail_timeout;
*/
uint8_t usb_eth_send(uint8_t * senddata, uint16_t sendlen, uint8_t led)
{
if (usb_mode == eem)
return eem_send(senddata, sendlen, led);
uint8_t ret = 0;
if(!usb_eth_is_active) {
USB_ETH_HOOK_TX_ERROR("Inactive");
goto bail;
}
if ((usb_mode == rndis_only) || (usb_mode == rndis_debug))
return rndis_send(senddata, sendlen, led);
//Check device is set up
if (Is_device_enumerated() == 0) {
USB_ETH_HOOK_TX_ERROR("Device not enumerated");
goto bail;
}
switch(usb_configuration_nb) {
case USB_CONFIG_RNDIS_DEBUG:
case USB_CONFIG_RNDIS:
ret = rndis_send(senddata, sendlen, led);
break;
case USB_CONFIG_EEM:
ret = eem_send(senddata, sendlen, led);
break;
case USB_CONFIG_ECM:
case USB_CONFIG_ECM_DEBUG:
ret = ecm_send(senddata, sendlen, led);
break;
}
bail:
if(!ret) // Hit the watchdog if we have a successful send.
watchdog_periodic();
return ret;
}
uint8_t
usb_eth_set_active(uint8_t active) {
if(usb_eth_is_active!=active) {
switch(usb_configuration_nb) {
case USB_CONFIG_RNDIS_DEBUG:
case USB_CONFIG_RNDIS:
usb_eth_is_active = active;
rndis_send_interrupt();
break;
case USB_CONFIG_EEM:
break;
case USB_CONFIG_ECM:
case USB_CONFIG_ECM_DEBUG:
cdc_ecm_set_active(active);
usb_eth_is_active = active;
break;
}
}
return 0;
}
/**
\brief Send a single ethernet frame using EEM
*/
uint8_t eem_send(uint8_t * senddata, uint16_t sendlen, uint8_t led)
{
//Check device is set up
if (Is_device_enumerated() == 0)
return 0;
//Make a header
uint8_t header[2];
//Fake CRC! Add 4 to length for CRC
sendlen += 4;
header[0] = (sendlen >> 8) & 0x3f;
header[1] = sendlen & 0xff;
//We send CRC seperatly..
sendlen -= 4;
//Send Data
Usb_select_endpoint(TX_EP);
//Usb_send_in();
//Wait for ready
while(!Is_usb_write_enabled());
//Send header (LSB then MSB)
Usb_write_byte(header[1]);
Usb_write_byte(header[0]);
//Send packet
while(sendlen) {
Usb_write_byte(*senddata);
senddata++;
sendlen--;
//If endpoint is full, send data in
//And then wait for data to transfer
if (!Is_usb_write_enabled()) {
Usb_send_in();
while(!Is_usb_write_enabled());
}
}
//CRC = 0xdeadbeef
//Linux kernel 2.6.31 needs 0xdeadbeef in wrong order,
//like this: uint8_t crc[4] = {0xef, 0xbe, 0xad, 0xde};
//This is fixed in 2.6.32 to the correct order (0xde, 0xad, 0xbe, 0xef)
uint8_t crc[4] = {0xde, 0xad, 0xbe, 0xef};
sendlen = 4;
uint8_t i = 0;
//Send fake CRC
while(sendlen) {
Usb_write_byte(crc[i]);
i++;
sendlen--;
//If endpoint is full, send data in
//And then wait for data to transfer
if (!Is_usb_write_enabled()) {
Usb_send_in();
while(!Is_usb_write_enabled());
}
if (led) {
tx_end_led();
}
}
//Send last data in - also handles sending a ZLP if needed
Usb_send_in();
//Wait for ready
while(!Is_usb_write_enabled());
return 1;
void
usb_eth_get_mac_address(uint8_t dest[6]) {
memcpy(dest,&usb_ethernet_addr,6);
}
/**
\brief Send data over RNDIS interface, data is in uipbuf and length is uiplen
*/
uint8_t rndis_send(uint8_t * senddata, uint16_t sendlen, uint8_t led)
{
uint16_t i;
//Setup Header
PBUF->MessageType = REMOTE_NDIS_PACKET_MSG;
PBUF->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_MessageType_t) - sizeof(rndis_MessageLength_t);
PBUF->DataLength = sendlen;
PBUF->OOBDataLength = 0;
PBUF->OOBDataOffset = 0;
PBUF->NumOOBDataElements = 0;
PBUF->PerPacketInfoOffset = 0;
PBUF->PerPacketInfoLength = 0;
PBUF->DeviceVcHandle = 0;
PBUF->Reserved = 0;
PBUF->MessageLength = sizeof(rndis_data_packet_t) + PBUF->DataLength;
//Send Data
Usb_select_endpoint(TX_EP);
Usb_send_in();
//Wait for ready
while(!Is_usb_write_enabled());
//Setup first part of transfer...
for(i = 0; i < sizeof(rndis_data_packet_t); i++) {
Usb_write_byte(data_buffer[i]);
}
//Send packet
while(sendlen) {
Usb_write_byte(*senddata);
senddata++;
sendlen--;
//If endpoint is full, send data in
//And then wait for data to transfer
if (!Is_usb_write_enabled()) {
Usb_send_in();
while(!Is_usb_write_enabled());
}
if (led) {
tx_end_led();
}
}
Usb_send_in();
return 1;
void
usb_eth_set_mac_address(const uint8_t src[6]) {
memcpy(&usb_ethernet_addr,src,6);
}
/**
@brief This will enable the RX_START LED for a period
*/
void rx_start_led(void)
{
Led1_on();
led1_timer = 10;
}
/**
@brief This will enable the TRX_END LED for a period
*/
void tx_end_led(void)
{
Led2_on();
led2_timer = 10;
}
/** @} */

View file

@ -52,22 +52,72 @@
#include "config.h"
#include "../conf_usb.h"
//_____ M A C R O S ________________________________________________________
#define USB_ETH_MTU UIP_BUFSIZE+4
/*! Hook Documentation
** USB_ETH_HOOK_RX_START()
** USB_ETH_HOOK_RX_END()
** USB_ETH_HOOK_RX_ERROR(string_reason)
**
** USB_ETH_HOOK_TX_START()
** USB_ETH_HOOK_TX_END()
** USB_ETH_HOOK_TX_ERROR(string_reason)
**
** USB_ETH_HOOK_INITIALIZED()
** USB_ETH_HOOK_UNINITIALIZED()
**
** USB_ETH_HOOK_INIT()
**
** USB_ETH_HOOK_SET_PROMISCIOUS_MODE(bool)
**
** USB_ETH_HOOK_HANDLE_INBOUND_PACKET(buffer,len)
** USB_ETH_HOOK_IS_READY_FOR_INBOUND_PACKET()
*/
#ifndef USB_ETH_HOOK_RX_START
void rx_start_led(void);
#define USB_ETH_HOOK_RX_START() rx_start_led()
#endif
#ifndef USB_ETH_HOOK_TX_END
void tx_end_led(void);
#define USB_ETH_HOOK_TX_END() tx_end_led()
#endif
#ifndef USB_ETH_HOOK_TX_ERROR
#define USB_ETH_HOOK_TX_ERROR(string) do { } while(0)
#endif
#ifndef USB_ETH_HOOK_RX_ERROR
#define USB_ETH_HOOK_RX_ERROR(string) do { } while(0)
#endif
//_____ D E C L A R A T I O N S ____________________________________________
uint8_t usb_eth_send(uint8_t * senddata, uint16_t sendlen, uint8_t led);
uint8_t usb_eth_set_active(uint8_t active);
uint8_t usb_eth_ready_for_next_packet();
void sof_action(void);
void rx_start_led(void);
void tx_end_led(void);
extern char usb_busy;
extern uint8_t usb_eth_is_active;
PROCESS_NAME(rndis_process);
// TIP: Avoid using usb_ethernet_addr directly and use the get/set mac_address functions below.
extern uint64_t usb_ethernet_addr;
void usb_eth_get_mac_address(uint8_t dest[6]);
void usb_eth_set_mac_address(const uint8_t src[6]);
PROCESS_NAME(usb_eth_process);
/** @} */

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

View file

@ -78,6 +78,10 @@ void uart_usb_flush(void);
bit uart_usb_test_hit(void);
char uart_usb_getchar(void);
void uart_usb_set_stdout(void);
uint8_t uart_usb_get_control_line_state(void);
void uart_usb_set_control_line_state(uint8_t control_line_state);
extern void uart_usb_configure_endpoints();
/** @} **/

View file

@ -55,17 +55,252 @@
#include "usb_drv.h"
#include "usb_descriptors.h"
#include "usb_specific_request.h"
#include "rndis/rndis_task.h"
//_____ M A C R O S ________________________________________________________
#define USB_ETH_NET_FUNC_DESC(MACAddrString,etherStat,maxSegmentSize,nMCFilters,nPowerFilters) \
{ sizeof(S_usb_ethernet_networking_functional_descriptor) \
, 0x24, 0x0F \
, MACAddrString \
, etherStat \
, Usb_write_word_enum_struc(maxSegmentSize) \
, Usb_write_word_enum_struc(nMCFilters) \
, nPowerFilters \
}
#define USB_CONFIG_DESC(totalsize,interfaceCount,value,stringIndex,attr,power) \
{ sizeof(S_usb_configuration_descriptor) \
, CONFIGURATION_DESCRIPTOR \
, Usb_write_word_enum_struc(totalsize) \
, interfaceCount \
, value \
, stringIndex \
, attr \
, power \
}
#define USB_ENDPOINT(nb,attr,maxpktsize,interval) \
{ sizeof(S_usb_endpoint_descriptor) \
, ENDPOINT_DESCRIPTOR \
, nb \
, attr \
, Usb_write_word_enum_struc(maxpktsize) \
, interval \
}
#define USB_IAD(firstinterface,interfacecount,funcClass,funcSubClass,funcProto,stringIndex) \
{ \
sizeof(S_usb_interface_association_descriptor), \
DSC_TYPE_IAD, \
firstinterface, \
interfacecount, \
funcClass, \
funcSubClass, \
funcProto, \
stringIndex \
}
#define USB_INTERFACEDESC(nb,altsetting,endpointCount,interfaceClass,interfaceSubClass,interfaceProto,stringIndex) \
{ sizeof(S_usb_interface_descriptor) \
, INTERFACE_DESCRIPTOR \
, nb \
, altsetting \
, endpointCount \
, interfaceClass \
, interfaceSubClass \
, interfaceProto \
, stringIndex \
}
#define FUNC_DESC_HEADER \
0x05, /* bFunctionLength, Descriptor size in bytes*/ \
0x24, /* bDescriptorType, CS_INTERFACE */ \
0x00, /* bDescriptorSubtype, Header Functional Descriptor */ \
0x10,0x01 /* bcdCDC, CDC specification release number in BCD format (1,1) */
#define FUNC_DESC_CALL_MANAGEMENT(caps,dataInterface) \
0x05, /* bFunctionLength, Descriptor size in bytes */ \
0x24, /* bDescriptorType, CS_INTERFACE */ \
0x01, /* bDescriptorSubtype, Call Management Functional Descriptor */ \
caps, /* bmCapabilities */ \
dataInterface /* bDataInterface, Interface used for call management */
/* Abstract Control Management Functional Descriptor */
#define FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT(caps) \
0x04, /* bFunctionLength, Descriptor size in bytes */ \
0x24, /* bDescriptorType, CS_INTERFACE */ \
0x02, /* bDescriptorSubtype, Call Management Functional Descriptor */ \
caps /* bmCapabilities */
/* Union Functional Descriptor */ \
#define FUNC_DESC_UNION(masterInterface,slaveInterface) \
0x05, /* bFunctionLength, Descriptor size in bytes */ \
0x24, /* bDescriptorType, CS_INTERFACE */ \
0x06, /* bDescriptorSubtype, Union Functional Descriptor */ \
masterInterface, /* bMasterInterface, The controlling interface for the union (bInterfaceNumber of a Communication or Data Class interface in this configuration) */ \
slaveInterface /* bSlaveInterface0, The controlled interace in the union (bInterfaceNumber of an interface in this configuration) */ \
#define RNDIS_INTERFACES \
USB_INTERFACEDESC( \
INTERFACE0_NB, \
ALTERNATE0, \
NB_ENDPOINT0, \
INTERFACE0_CLASS, \
INTERFACE0_SUB_CLASS, \
INTERFACE0_PROTOCOL, \
USB_STRING_INTERFACE_RNDIS \
), \
{ \
FUNC_DESC_HEADER, \
FUNC_DESC_CALL_MANAGEMENT(0x00/*caps*/,0x00/*dataInterface*/), \
FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT(0x00), \
FUNC_DESC_UNION(0x00,0x01), \
}, \
USB_ENDPOINT(ENDPOINT_NB_1,EP_ATTRIBUTES_1,EP_SIZE_1,EP_INTERVAL_1), \
\
USB_INTERFACEDESC( \
INTERFACE1_NB, \
ALTERNATE1, \
NB_ENDPOINT1, \
INTERFACE1_CLASS, \
INTERFACE1_SUB_CLASS, \
INTERFACE1_PROTOCOL, \
USB_STRING_NONE \
), \
USB_ENDPOINT(ENDPOINT_NB_2,EP_ATTRIBUTES_2,EP_SIZE_2,EP_INTERVAL_2), \
USB_ENDPOINT(ENDPOINT_NB_3,EP_ATTRIBUTES_3,EP_SIZE_3,EP_INTERVAL_3)
#define CDC_SERIAL_INTERFACES \
USB_INTERFACEDESC( \
INTERFACE2_NB, \
ALTERNATE2, \
NB_ENDPOINT2, \
INTERFACE2_CLASS, \
INTERFACE2_SUB_CLASS, \
INTERFACE2_PROTOCOL, \
USB_STRING_INTERFACE_SERIAL \
), \
{ \
FUNC_DESC_HEADER, \
FUNC_DESC_CALL_MANAGEMENT(0x03/*caps*/,0x03/*dataInterface*/), \
FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT(0x02), \
FUNC_DESC_UNION(0x02,0x03), \
}, \
USB_ENDPOINT(ENDPOINT_NB_4,EP_ATTRIBUTES_4,EP_SIZE_4,EP_INTERVAL_4), \
USB_INTERFACEDESC( \
INTERFACE3_NB, \
ALTERNATE3, \
NB_ENDPOINT3, \
INTERFACE3_CLASS, \
INTERFACE3_SUB_CLASS, \
INTERFACE3_PROTOCOL, \
USB_STRING_NONE \
), \
USB_ENDPOINT(ENDPOINT_NB_5,EP_ATTRIBUTES_5,EP_SIZE_5,EP_INTERVAL_5), \
USB_ENDPOINT(ENDPOINT_NB_6,EP_ATTRIBUTES_6,EP_SIZE_6,EP_INTERVAL_6)
#define CDC_EEM_INTERFACES \
USB_INTERFACEDESC( \
EEM_INTERFACE0_NB, \
EEM_ALTERNATE0, \
EEM_NB_ENDPOINT0, \
EEM_INTERFACE0_CLASS, \
EEM_INTERFACE0_SUB_CLASS, \
EEM_INTERFACE0_PROTOCOL, \
USB_STRING_INTERFACE_EEM \
), \
USB_ENDPOINT(ENDPOINT_NB_1,EP_ATTRIBUTES_1,EP_SIZE_1,EP_INTERVAL_1), \
USB_ENDPOINT(ENDPOINT_NB_2,EP_ATTRIBUTES_2,EP_SIZE_2,EP_INTERVAL_2)
#if CDC_ECM_USES_INTERRUPT_ENDPOINT
#define CDC_ECM_CONTROL_ENDPOINT_COUNT 1
#define CDC_ECM_CONTROL_ENDPOINT USB_ENDPOINT(ENDPOINT_NB_1,EP_ATTRIBUTES_1,EP_SIZE_1,EP_INTERVAL_1),
#else
#define CDC_ECM_CONTROL_ENDPOINT_COUNT 0
#define CDC_ECM_CONTROL_ENDPOINT
#endif
#define CDC_ECM_INTERFACES \
USB_INTERFACEDESC( \
ECM_INTERFACE0_NB, \
ECM_ALTERNATE0, \
CDC_ECM_CONTROL_ENDPOINT_COUNT, \
ECM_INTERFACE0_CLASS, \
ECM_INTERFACE0_SUB_CLASS, \
ECM_INTERFACE0_PROTOCOL, \
USB_STRING_INTERFACE_ECM \
), \
{ \
FUNC_DESC_HEADER, \
FUNC_DESC_UNION(0x00,0x01), \
}, \
USB_ETH_NET_FUNC_DESC( \
USB_STRING_MAC_ADDRESS, \
0, /* Support no stats for now */ \
USB_ETH_MTU, /* maxSegmentSize */ \
0, /* nMCFilters*/ \
0 /*nPowerFilters*/ \
), \
CDC_ECM_CONTROL_ENDPOINT \
USB_INTERFACEDESC( \
ECM_INTERFACE0_NB+1, \
0, \
2, \
10, \
0, \
0, \
USB_STRING_NONE \
), \
USB_ENDPOINT(ENDPOINT_NB_2,EP_ATTRIBUTES_2,EP_SIZE_2,EP_INTERVAL_2), \
USB_ENDPOINT(ENDPOINT_NB_3,EP_ATTRIBUTES_3,EP_SIZE_3,EP_INTERVAL_3)
/*
USB_INTERFACEDESC( \
ECM_INTERFACE0_NB+1, \
0, \
0, \
10, \
0, \
0, \
USB_STRING_NONE \
), \
*/
//_____ D E F I N I T I O N ________________________________________________
/************* COMPOSITE DEVICE DESCRIPTORS (using IAD) **********/
FLASH uint8_t usb_dev_config_order[] = {
// USB_CONFIG_RNDIS_DEBUG, //Enable here for Windows COM port debugging? (USB_CONF_CDC=1)
USB_CONFIG_RNDIS,
USB_CONFIG_ECM_DEBUG,
USB_CONFIG_RNDIS_DEBUG, //Enable here for macintosh CDC-ECM enumeration
USB_CONFIG_ECM,
USB_CONFIG_EEM,
#if USB_CONF_STORAGE
USB_CONFIG_MS,
#endif
};
// usb_user_device_descriptor
FLASH S_usb_device_descriptor usb_dev_desc_composite =
{
@ -79,204 +314,46 @@ FLASH S_usb_device_descriptor usb_dev_desc_composite =
, Usb_write_word_enum_struc(VENDOR_ID)
, Usb_write_word_enum_struc(COMPOSITE_PRODUCT_ID)
, Usb_write_word_enum_struc(RELEASE_NUMBER)
, MAN_INDEX
, PROD_INDEX
, SN_INDEX
, NB_CONFIGURATION
, USB_STRING_MAN
, USB_STRING_PRODUCT
, USB_STRING_SERIAL
, (sizeof(usb_dev_config_order)/sizeof(*usb_dev_config_order))
};
// usb_user_configuration_descriptor FS
FLASH S_usb_user_configuration_descriptor_composite usb_conf_desc_composite = {
{ sizeof(S_usb_configuration_descriptor)
, CONFIGURATION_DESCRIPTOR
, Usb_write_word_enum_struc(sizeof(S_usb_user_configuration_descriptor_composite))
//, 0x0043 //TODO: Change to generic codewith sizeof
, COMPOSITE_NB_INTERFACE
, CONF_NB
, CONF_INDEX
, CONF_ATTRIBUTES
, MAX_POWER
},//9
USB_CONFIG_DESC(
sizeof(usb_conf_desc_composite),
COMPOSITE_NB_INTERFACE,
USB_CONFIG_RNDIS_DEBUG,
USB_STRING_CONFIG_COMPOSITE,
CONF_ATTRIBUTES,
MAX_POWER
),
// --------------------------- IAD ----------------------------
{ // Interface Association Descriptor
sizeof(S_usb_interface_association_descriptor), // bLength
DSC_TYPE_IAD, // bDescriptorType = 11
0x00, // bFirstInterface
0x02, // bInterfaceCount
0x02, // bFunctionClass (Communication Class)
0x02, // bFunctionSubClass (Abstract Control Model)
0xFF, // bFunctionProcotol (Vendor specific)
0x00 // iInterface
},//8
/// RNDIS DEVICE
{ sizeof(S_usb_interface_descriptor)
, INTERFACE_DESCRIPTOR
, INTERFACE0_NB
, ALTERNATE0
, NB_ENDPOINT0
, INTERFACE0_CLASS
, INTERFACE0_SUB_CLASS
, INTERFACE0_PROTOCOL
, INTERFACE0_INDEX
} //9
,
{
// Header Functional Descriptor (marks beginning of the concatenated set of Functional Descriptors)
0x05, // bFunctionLength, Descriptor size in bytes
0x24, // bDescriptorType, CS_INTERFACE
0x00, // bDescriptorSubtype, Header Functional Descriptor
0x10,0x01, // bcdCDC, CDC specification release number in BCD format (1,1)
// Call Management Functional Descriptor
0x05, // bFunctionLength, Descriptor size in bytes
0x24, // bDescriptorType, CS_INTERFACE
0x01, // bDescriptorSubtype, Call Management Functional Descriptor
0x00, // bmCapabilities
0x01, // bDataInterface, Interface used for call management
// Abstract Control Management Functional Descriptor
0x04, // bDescriptorLength, Descriptor size in bytes
0x24, // bDescriptorType, CS_INTERFACE
0x02, // bDescriptorSubtype, Abstract Control Management Functional Descriptor
0x00, // bmCapabilities
// Union Functional Descriptor
0x05, // bFunctionLength, Descriptor size in bytes
0x24, // bDescriptorType, CS_INTERFACE
0x06, // bDescriptorSubtype, Union Functional Descriptor
0x00, // bMasterInterface, The controlling interface for the union (bInterfaceNumber of a Communication or Data Class interface in this configuration)
0x01, // bSlaveInterface0, The controlled interace in the union (bInterfaceNumber of an interface in this configuration)
},
{ sizeof(S_usb_endpoint_descriptor)
, ENDPOINT_DESCRIPTOR
, ENDPOINT_NB_1
, EP_ATTRIBUTES_1
, Usb_write_word_enum_struc(EP_SIZE_1)
, EP_INTERVAL_1
} //7
,
{ sizeof(S_usb_interface_descriptor)
, INTERFACE_DESCRIPTOR
, INTERFACE1_NB
, ALTERNATE1
, NB_ENDPOINT1
, INTERFACE1_CLASS
, INTERFACE1_SUB_CLASS
, INTERFACE1_PROTOCOL
, INTERFACE1_INDEX
},
{ sizeof(S_usb_endpoint_descriptor)
, ENDPOINT_DESCRIPTOR
, ENDPOINT_NB_2
, EP_ATTRIBUTES_2
, Usb_write_word_enum_struc(EP_SIZE_2)
, EP_INTERVAL_2
},
{ sizeof(S_usb_endpoint_descriptor)
, ENDPOINT_DESCRIPTOR
, ENDPOINT_NB_3
, EP_ATTRIBUTES_3
, Usb_write_word_enum_struc(EP_SIZE_3)
, EP_INTERVAL_3
},
// --------------------------- IAD ----------------------------
{ // Interface Association Descriptor
sizeof(S_usb_interface_association_descriptor), // bLength
DSC_TYPE_IAD, // bDescriptorType = 11
0x02, // bFirstInterface
0x02, // bInterfaceCount
0x02, // bFunctionClass (Communication Class)
0x02, // bFunctionSubClass (Abstract Control Model)
0x01, // bFunctionProcotol (V.25ter, Common AT commands)
0x00 // iInterface
},//8
/// SERIAL PORT DEVICE
{ sizeof(S_usb_interface_descriptor)
, INTERFACE_DESCRIPTOR
, INTERFACE2_NB
, ALTERNATE2
, NB_ENDPOINT2
, INTERFACE2_CLASS
, INTERFACE2_SUB_CLASS
, INTERFACE2_PROTOCOL
, INTERFACE2_INDEX
}//9
,
{
// Header Functional Descriptor (marks beginning of the concatenated set of Functional Descriptors)
0x05, // bFunctionLength, Descriptor size in bytes
0x24, // bDescriptorType, CS_INTERFACE
0x00, // bDescriptorSubtype, Header Functional Descriptor
0x10,0x01, // bcdCDC, CDC specification release number in BCD format (1,1)
// Call Management Functional Descriptor
0x05, // bFunctionLength, Descriptor size in bytes
0x24, // bDescriptorType, CS_INTERFACE
0x01, // bDescriptorSubtype, Call Management Functional Descriptor
0x03, // bmCapabilities, can do calls on it's own
0x03, // bDataInterface, Interface used for call management
// Abstract Control Management Functional Descriptor
0x04, // bDescriptorLength, Descriptor size in bytes
0x24, // bDescriptorType, CS_INTERFACE
0x02, // bDescriptorSubtype, Abstract Control Management Functional Descriptor
0x00, // bmCapabilities, support nothing!!! Deal with it
//Old was 0x06 indicating support for the GET/SET_LINE_CODING, BREAK & SET_CONTROL_LINE_STATE (2->6)
// Union Functional Descriptor
0x05, // bFunctionLength, Descriptor size in bytes
0x24, // bDescriptorType, CS_INTERFACE
0x06, // bDescriptorSubtype, Union Functional Descriptor
0x02, // bMasterInterface, The controlling interface for the union (bInterfaceNumber of a Communication or Data Class interface in this configuration)
0x03, // bSlaveInterface0, The controlled interace in the union (bInterfaceNumber of an interface in this configuration)
},
{ sizeof(S_usb_endpoint_descriptor)
, ENDPOINT_DESCRIPTOR
, ENDPOINT_NB_4
, EP_ATTRIBUTES_4
, Usb_write_word_enum_struc(EP_SIZE_4)
, EP_INTERVAL_4
} //7
,
{ sizeof(S_usb_interface_descriptor)
, INTERFACE_DESCRIPTOR
, INTERFACE3_NB
, ALTERNATE3
, NB_ENDPOINT3
, INTERFACE3_CLASS
, INTERFACE3_SUB_CLASS
, INTERFACE3_PROTOCOL
, INTERFACE3_INDEX
}
,
{ sizeof(S_usb_endpoint_descriptor)
, ENDPOINT_DESCRIPTOR
, ENDPOINT_NB_5
, EP_ATTRIBUTES_5
, Usb_write_word_enum_struc(EP_SIZE_5)
, EP_INTERVAL_5
}
,
{ sizeof(S_usb_endpoint_descriptor)
, ENDPOINT_DESCRIPTOR
, ENDPOINT_NB_6
, EP_ATTRIBUTES_6
, Usb_write_word_enum_struc(EP_SIZE_6)
, EP_INTERVAL_6
}
USB_IAD(
0x00, // First interface
0x02, // Interface count
0x02, // Function Class
0x02, // Function Subclass
0xFF, // Function Protocol
USB_STRING_INTERFACE_RNDIS
),RNDIS_INTERFACES,
USB_IAD(
0x02, // First interface
0x02, // Interface count
0x02, // Function Class
0x02, // Function Subclass
0x01, // Function Protocol
USB_STRING_INTERFACE_SERIAL
),CDC_SERIAL_INTERFACES
};
/****************** NETWORK-ONLY DEVICE DESCRIPTORS **************************/
/*
FLASH S_usb_device_descriptor usb_dev_desc_network =
{
sizeof(usb_dev_desc_network)
@ -289,101 +366,115 @@ FLASH S_usb_device_descriptor usb_dev_desc_network =
, Usb_write_word_enum_struc(VENDOR_ID)
, Usb_write_word_enum_struc(NETWORK_PRODUCT_ID)
, Usb_write_word_enum_struc(RELEASE_NUMBER)
, MAN_INDEX
, PROD_INDEX
, SN_INDEX
, USB_STRING_MAN
, USB_STRING_PRODUCT
, USB_STRING_SERIAL
, NB_CONFIGURATION
};
*/
// usb_user_configuration_descriptor FS
FLASH S_usb_user_configuration_descriptor_network usb_conf_desc_network = {
{ sizeof(S_usb_configuration_descriptor)
, CONFIGURATION_DESCRIPTOR
, Usb_write_word_enum_struc(sizeof(S_usb_user_configuration_descriptor_network))
//, 0x0043 //TODO: Change to generic codewith sizeof
, NETWORK_NB_INTERFACE
, CONF_NB
, CONF_INDEX
, CONF_ATTRIBUTES
, MAX_POWER
},//9
/// RNDIS DEVICE
{ sizeof(S_usb_interface_descriptor)
, INTERFACE_DESCRIPTOR
, INTERFACE0_NB
, ALTERNATE0
, NB_ENDPOINT0
, INTERFACE0_CLASS
, INTERFACE0_SUB_CLASS
, INTERFACE0_PROTOCOL
, INTERFACE0_INDEX
} //9
,
{
// Header Functional Descriptor (marks beginning of the concatenated set of Functional Descriptors)
0x05, // bFunctionLength, Descriptor size in bytes
0x24, // bDescriptorType, CS_INTERFACE
0x00, // bDescriptorSubtype, Header Functional Descriptor
0x10,0x01, // bcdCDC, CDC specification release number in BCD format (1,1)
// Call Management Functional Descriptor
0x05, // bFunctionLength, Descriptor size in bytes
0x24, // bDescriptorType, CS_INTERFACE
0x01, // bDescriptorSubtype, Call Management Functional Descriptor
0x00, // bmCapabilities
0x01, // bDataInterface, Interface used for call management
// Abstract Control Management Functional Descriptor
0x04, // bDescriptorLength, Descriptor size in bytes
0x24, // bDescriptorType, CS_INTERFACE
0x02, // bDescriptorSubtype, Abstract Control Management Functional Descriptor
0x00, // bmCapabilities
// Union Functional Descriptor
0x05, // bFunctionLength, Descriptor size in bytes
0x24, // bDescriptorType, CS_INTERFACE
0x06, // bDescriptorSubtype, Union Functional Descriptor
0x00, // bMasterInterface, The controlling interface for the union (bInterfaceNumber of a Communication or Data Class interface in this configuration)
0x01, // bSlaveInterface0, The controlled interace in the union (bInterfaceNumber of an interface in this configuration)
},
{ sizeof(S_usb_endpoint_descriptor)
, ENDPOINT_DESCRIPTOR
, ENDPOINT_NB_1
, EP_ATTRIBUTES_1
, Usb_write_word_enum_struc(EP_SIZE_1)
, EP_INTERVAL_1
} //7
,
{ sizeof(S_usb_interface_descriptor)
, INTERFACE_DESCRIPTOR
, INTERFACE1_NB
, ALTERNATE1
, NB_ENDPOINT1
, INTERFACE1_CLASS
, INTERFACE1_SUB_CLASS
, INTERFACE1_PROTOCOL
, INTERFACE1_INDEX
},
{ sizeof(S_usb_endpoint_descriptor)
, ENDPOINT_DESCRIPTOR
, ENDPOINT_NB_2
, EP_ATTRIBUTES_2
, Usb_write_word_enum_struc(EP_SIZE_2)
, EP_INTERVAL_2
},
{ sizeof(S_usb_endpoint_descriptor)
, ENDPOINT_DESCRIPTOR
, ENDPOINT_NB_3
, EP_ATTRIBUTES_3
, Usb_write_word_enum_struc(EP_SIZE_3)
, EP_INTERVAL_3
}
USB_CONFIG_DESC(
sizeof(usb_conf_desc_network),
NETWORK_NB_INTERFACE,
CONF_NB, // value
USB_STRING_CONFIG_RNDIS,
CONF_ATTRIBUTES,
MAX_POWER
),
RNDIS_INTERFACES
};
/************* EEM-ONLY ***************/
// usb_user_device_descriptor
/*
FLASH S_usb_device_descriptor usb_dev_desc_eem =
{
sizeof(usb_dev_desc_composite)
, DEVICE_DESCRIPTOR
, Usb_write_word_enum_struc(USB_SPECIFICATION)
, EEM_DEVICE_CLASS
, EEM_DEVICE_SUB_CLASS
, EEM_DEVICE_PROTOCOL
, EP_CONTROL_LENGTH
, Usb_write_word_enum_struc(VENDOR_ID)
, Usb_write_word_enum_struc(COMPOSITE_PRODUCT_ID)
, Usb_write_word_enum_struc(RELEASE_NUMBER)
, USB_STRING_MAN
, USB_STRING_PRODUCT
, USB_STRING_SERIAL
, NB_CONFIGURATION
};
*/
// usb_user_configuration_descriptor FS
FLASH S_usb_user_configuration_descriptor_eem usb_conf_desc_eem = {
USB_CONFIG_DESC(
sizeof(usb_conf_desc_eem),
EEM_NB_INTERFACE,
USB_CONFIG_EEM, // value
USB_STRING_CONFIG_EEM,
CONF_ATTRIBUTES,
MAX_POWER
),
CDC_EEM_INTERFACES
};
FLASH S_usb_user_configuration_descriptor_ecm usb_conf_desc_ecm = {
USB_CONFIG_DESC(
sizeof(usb_conf_desc_ecm),
2, // Interface Count
USB_CONFIG_ECM, // value
USB_STRING_CONFIG_ECM,
CONF_ATTRIBUTES,
MAX_POWER
),
CDC_ECM_INTERFACES
};
FLASH S_usb_user_configuration_descriptor_ecm_debug usb_conf_desc_ecm_debug = {
USB_CONFIG_DESC(
sizeof(usb_conf_desc_ecm_debug),
4, // Interface Count
USB_CONFIG_ECM_DEBUG, // value
USB_STRING_CONFIG_ECM_DEBUG,
CONF_ATTRIBUTES,
MAX_POWER
),
USB_IAD(
0x00, // First interface
0x02, // Interface count
0x02, // Function Class
0x06, // Function Subclass
0x00, // Function Protocol
USB_STRING_INTERFACE_ECM
),CDC_ECM_INTERFACES,
USB_IAD(
0x02, // First interface
0x02, // Interface count
0x02, // Function Class
0x02, // Function Subclass
0x01, // Function Protocol
USB_STRING_INTERFACE_SERIAL
),CDC_SERIAL_INTERFACES
};
/****************** MASS-STORAGE DEVICE DESCRIPTORS **************************/
/*
FLASH S_usb_device_descriptor usb_dev_desc_mass =
{
sizeof(usb_dev_desc_mass)
@ -396,11 +487,13 @@ FLASH S_usb_device_descriptor usb_dev_desc_mass =
, Usb_write_word_enum_struc(VENDOR_ID)
, Usb_write_word_enum_struc(MASS_PRODUCT_ID)
, Usb_write_word_enum_struc(RELEASE_NUMBER)
, MAN_INDEX
, PROD_INDEX
, SN_INDEX
, USB_STRING_MAN
, USB_STRING_PRODUCT
, USB_STRING_SERIAL
, NB_CONFIGURATION
};
*/
#if USB_CONF_STORAGE
// usb_user_configuration_descriptor FS
FLASH S_usb_user_configuration_descriptor_mass usb_conf_desc_mass = {
@ -409,7 +502,7 @@ FLASH S_usb_user_configuration_descriptor_mass usb_conf_desc_mass = {
, Usb_write_word_enum_struc(sizeof(S_usb_user_configuration_descriptor_mass))
, MASS_NB_INTERFACE
, CONF_NB
, CONF_INDEX
, USB_STRING_CONFIG_MS
, CONF_ATTRIBUTES
, MAX_POWER
},//9
@ -423,7 +516,7 @@ FLASH S_usb_user_configuration_descriptor_mass usb_conf_desc_mass = {
, MS_INTERFACE_CLASS
, MS_INTERFACE_SUB_CLASS
, MS_INTERFACE_PROTOCOL
, MS_INTERFACE_INDEX
, USB_STRING_INTERFACE_MS
} //9
,
{ sizeof(S_usb_endpoint_descriptor)
@ -443,96 +536,11 @@ FLASH S_usb_user_configuration_descriptor_mass usb_conf_desc_mass = {
}
};
/************* EEM-ONLY ***************/
// usb_user_device_descriptor
FLASH S_usb_device_descriptor usb_dev_desc_eem =
{
sizeof(usb_dev_desc_composite)
, DEVICE_DESCRIPTOR
, Usb_write_word_enum_struc(USB_SPECIFICATION)
, EEM_DEVICE_CLASS
, EEM_DEVICE_SUB_CLASS
, EEM_DEVICE_PROTOCOL
, EP_CONTROL_LENGTH
, Usb_write_word_enum_struc(VENDOR_ID)
, Usb_write_word_enum_struc(COMPOSITE_PRODUCT_ID)
, Usb_write_word_enum_struc(RELEASE_NUMBER)
, MAN_INDEX
, PROD_INDEX
, SN_INDEX
, NB_CONFIGURATION
};
// usb_user_configuration_descriptor FS
FLASH S_usb_user_configuration_descriptor_eem usb_conf_desc_eem = {
{ sizeof(S_usb_configuration_descriptor)
, CONFIGURATION_DESCRIPTOR
, Usb_write_word_enum_struc(sizeof(S_usb_user_configuration_descriptor_eem))
, EEM_NB_INTERFACE
, CONF_NB
, CONF_INDEX
, CONF_ATTRIBUTES
, MAX_POWER
},//9
/// EEM DEVICE
{ sizeof(S_usb_interface_descriptor)
, INTERFACE_DESCRIPTOR
, EEM_INTERFACE0_NB
, EEM_ALTERNATE0
, EEM_NB_ENDPOINT0
, EEM_INTERFACE0_CLASS
, EEM_INTERFACE0_SUB_CLASS
, EEM_INTERFACE0_PROTOCOL
, EEM_INTERFACE0_INDEX
} //9
,
{ sizeof(S_usb_endpoint_descriptor)
, ENDPOINT_DESCRIPTOR
, EEM_ENDPOINT_NB_1
, EEM_EP_ATTRIBUTES_1
, Usb_write_word_enum_struc(EEM_EP_SIZE_1)
, EEM_EP_INTERVAL_1
} //7
,
{ sizeof(S_usb_endpoint_descriptor)
, ENDPOINT_DESCRIPTOR
, EEM_ENDPOINT_NB_2
, EEM_EP_ATTRIBUTES_2
, Usb_write_word_enum_struc(EEM_EP_SIZE_2)
, EEM_EP_INTERVAL_2
} //7
};
#endif
/************* COMMON *****************/
// usb_user_manufacturer_string_descriptor
FLASH S_usb_manufacturer_string_descriptor usb_user_manufacturer_string_descriptor = {
sizeof(usb_user_manufacturer_string_descriptor)
, STRING_DESCRIPTOR
, USB_MANUFACTURER_NAME
};
// usb_user_product_string_descriptor
FLASH S_usb_product_string_descriptor usb_user_product_string_descriptor = {
sizeof(usb_user_product_string_descriptor)
, STRING_DESCRIPTOR
, USB_PRODUCT_NAME
};
// usb_user_serial_number
FLASH S_usb_serial_number usb_user_serial_number = {
sizeof(usb_user_serial_number)
, STRING_DESCRIPTOR
, USB_SERIAL_NUMBER
};
// usb_user_language_id
@ -548,6 +556,8 @@ FLASH S_usb_language_id usb_user_language_id = {
PGM_VOID_P Usb_get_dev_desc_pointer(void)
{
return &(usb_dev_desc_composite.bLength);
/*
if (usb_mode == rndis_only)
return &(usb_dev_desc_network.bLength);
@ -558,11 +568,14 @@ PGM_VOID_P Usb_get_dev_desc_pointer(void)
return &(usb_dev_desc_eem.bLength);
return &(usb_dev_desc_mass.bLength);
*/
}
U8 Usb_get_dev_desc_length(void)
{
return sizeof(usb_dev_desc_composite);
/*
if (usb_mode == rndis_only)
return sizeof(usb_dev_desc_network);
@ -574,37 +587,54 @@ U8 Usb_get_dev_desc_length(void)
return sizeof(usb_dev_desc_eem);
return sizeof(usb_dev_desc_mass);
*/
}
PGM_VOID_P Usb_get_conf_desc_pointer(void)
PGM_VOID_P Usb_get_conf_desc_pointer(U8 index)
{
if (usb_mode == rndis_only)
return &(usb_conf_desc_network.cfg.bLength);
if (usb_mode == rndis_debug)
return &(usb_conf_desc_composite.cfg.bLength);
if (usb_mode == eem)
return &(usb_conf_desc_eem.cfg.bLength);
return &(usb_conf_desc_mass.cfg.bLength);
switch(pgm_read_byte_near(&usb_dev_config_order[index])) {
case USB_CONFIG_ECM:
return &(usb_conf_desc_ecm.cfg.bLength);
case USB_CONFIG_ECM_DEBUG:
return &(usb_conf_desc_ecm_debug.cfg.bLength);
case USB_CONFIG_RNDIS_DEBUG:
return &(usb_conf_desc_composite.cfg.bLength);
case USB_CONFIG_RNDIS:
return &(usb_conf_desc_network.cfg.bLength);
case USB_CONFIG_EEM:
return &(usb_conf_desc_eem.cfg.bLength);
#if USB_CONF_STORAGE
case USB_CONFIG_MS:
return &(usb_conf_desc_mass.cfg.bLength);
#endif
default:
return 0;
}
}
U8 Usb_get_conf_desc_length(void)
U8 Usb_get_conf_desc_length(U8 index)
{
if (usb_mode == rndis_only)
return sizeof (usb_conf_desc_network);
if (usb_mode == rndis_debug)
return sizeof(usb_conf_desc_composite);
if (usb_mode == eem)
return sizeof(usb_conf_desc_eem);
return sizeof(usb_conf_desc_mass);
switch(pgm_read_byte_near(&usb_dev_config_order[index])) {
case USB_CONFIG_ECM:
return sizeof(usb_conf_desc_ecm);
case USB_CONFIG_ECM_DEBUG:
return sizeof(usb_conf_desc_ecm_debug);
case USB_CONFIG_RNDIS_DEBUG:
return sizeof(usb_conf_desc_composite);
case USB_CONFIG_RNDIS:
return sizeof (usb_conf_desc_network);
case USB_CONFIG_EEM:
return sizeof(usb_conf_desc_eem);
#if USB_CONF_STORAGE
case USB_CONFIG_MS:
return sizeof(usb_conf_desc_mass);
#endif
default:
return 0;
}
}
/** @} */

View file

@ -66,9 +66,9 @@
// USB Device descriptor
#define USB_SPECIFICATION 0x0200
#define COMPOSITE_DEVICE_CLASS 0xEF // Misc
#define COMPOSITE_DEVICE_SUB_CLASS 0x02 // Common
#define COMPOSITE_DEVICE_PROTOCOL 0x01 // IAD
#define COMPOSITE_DEVICE_CLASS 0x02 // Misc
#define COMPOSITE_DEVICE_SUB_CLASS 0x00 // Common
#define COMPOSITE_DEVICE_PROTOCOL 0x00 // IAD
#define NETWORK_DEVICE_CLASS 0x02 // CDC ACM
#define NETWORK_DEVICE_SUB_CLASS 0x02 //
@ -88,10 +88,49 @@
#define NETWORK_PRODUCT_ID 0x2019 //Product ID for just RNDIS device
#define MASS_PRODUCT_ID 0x202F //Product ID for mass storage
#define RELEASE_NUMBER 0x1000
#define MAN_INDEX 0x01
#define PROD_INDEX 0x02
#define SN_INDEX 0x03
#define NB_CONFIGURATION 1
enum {
USB_STRING_NONE = 0,
USB_STRING_MAN = 1,
USB_STRING_PRODUCT,
USB_STRING_SERIAL,
USB_STRING_MAC_ADDRESS,
USB_STRING_CONFIG_COMPOSITE,
USB_STRING_CONFIG_RNDIS,
USB_STRING_CONFIG_EEM,
USB_STRING_CONFIG_ECM,
USB_STRING_CONFIG_ECM_DEBUG,
USB_STRING_CONFIG_MS,
USB_STRING_INTERFACE_RNDIS,
USB_STRING_INTERFACE_EEM,
USB_STRING_INTERFACE_ECM,
USB_STRING_INTERFACE_ECM_ATTACHED,
USB_STRING_INTERFACE_ECM_DETACHED,
USB_STRING_INTERFACE_SERIAL,
USB_STRING_INTERFACE_MS,
};
enum {
USB_CONFIG_UNCONFIGURED = 0,
USB_CONFIG_RNDIS = 1,
USB_CONFIG_RNDIS_DEBUG = 1+(1<<7),
USB_CONFIG_ECM = 2,
USB_CONFIG_ECM_DEBUG = 2+(1<<7),
USB_CONFIG_EEM = 3,
#if USB_CONF_STORAGE
USB_CONFIG_MS = 4,
#endif
};
#define USB_CONFIG_HAS_DEBUG_PORT(x) ((x==USB_CONFIG_ECM_DEBUG)||(x==USB_CONFIG_RNDIS_DEBUG))
//#define USB_CONFIG_COUNT (USB_CONFIG_COUNT_PLUS_ONE-1)
//#define NB_CONFIGURATION USB_CONFIG_COUNT
#define NETWORK_NB_INTERFACE 2
#define COMPOSITE_NB_INTERFACE 4
@ -134,14 +173,14 @@
#define ENDPOINT_NB_2 0x80 | TX_EP
#define EP_ATTRIBUTES_2 0x02 // BULK = 0x02, INTERUPT = 0x03
#define EP_SIZE_2 0x40 //64 byte max size
#define EP_INTERVAL_2 0x00
#define EP_INTERVAL_2 0x01
// USB Endpoint 2 descriptor
//Bulk OUT RX endpoint
#define ENDPOINT_NB_3 RX_EP
#define EP_ATTRIBUTES_3 0x02 // BULK = 0x02, INTERUPT = 0x03
#define EP_SIZE_3 0x40 //64 byte max size
#define EP_INTERVAL_3 0x00
#define EP_INTERVAL_3 0x01
/*** CDC Virtual Serial Port ***/
@ -176,14 +215,14 @@
#define ENDPOINT_NB_5 0x80 | VCP_TX_EP
#define EP_ATTRIBUTES_5 0x02 // BULK = 0x02, INTERUPT = 0x03
#define EP_SIZE_5 0x20
#define EP_INTERVAL_5 0x00
#define EP_INTERVAL_5 0x01
// USB Endpoint 6 descriptor
// Bulk OUT
#define ENDPOINT_NB_6 VCP_RX_EP
#define EP_ATTRIBUTES_6 0x02 // BULK = 0x02, INTERUPT = 0x03
#define EP_SIZE_6 0x20
#define EP_INTERVAL_6 0x00
#define EP_INTERVAL_6 0x01
/*** Mass Storage ***/
@ -227,61 +266,34 @@
#define EEM_ENDPOINT_NB_1 0x80 | TX_EP
#define EEM_EP_ATTRIBUTES_1 0x02 // BULK = 0x02, INTERUPT = 0x03
#define EEM_EP_SIZE_1 0x40 //64 byte max size
#define EEM_EP_INTERVAL_1 0x00
#define EEM_EP_INTERVAL_1 0x01
// USB Endpoint 2 descriptor
// Bulk OUT
#define EEM_ENDPOINT_NB_2 RX_EP
#define EEM_EP_ATTRIBUTES_2 0x02 // BULK = 0x02, INTERUPT = 0x03
#define EEM_EP_SIZE_2 0x40 //64 byte max size
#define EEM_EP_INTERVAL_2 0x00
#define EEM_EP_INTERVAL_2 0x01
/******* ECM Configuration *******/
// Interface 0 descriptor
#define ECM_INTERFACE0_NB 0
#define ECM_ALTERNATE0 0
#define ECM_NB_ENDPOINT0 2
#define ECM_INTERFACE0_CLASS 0x02 // CDC ACM Com
#define ECM_INTERFACE0_SUB_CLASS 0x06 // ECM
#define ECM_INTERFACE0_PROTOCOL 0x00 // Empty
#define ECM_INTERFACE0_INDEX 0
#define DEVICE_STATUS 0x00 // TBD
#define INTERFACE_STATUS 0x00 // TBD
#define LANG_ID 0x00
#define USB_MN_LENGTH 5
#define USB_MANUFACTURER_NAME \
{ Usb_unicode('A') \
, Usb_unicode('t') \
, Usb_unicode('m') \
, Usb_unicode('e') \
, Usb_unicode('l') \
}
#define USB_PN_LENGTH 16
#define USB_PRODUCT_NAME \
{ Usb_unicode('R') \
,Usb_unicode('Z') \
,Usb_unicode('R') \
,Usb_unicode('A') \
,Usb_unicode('V') \
,Usb_unicode('E') \
,Usb_unicode('N') \
,Usb_unicode(' ') \
,Usb_unicode('U') \
,Usb_unicode('S') \
,Usb_unicode('B') \
,Usb_unicode(' ') \
,Usb_unicode('D') \
,Usb_unicode('E') \
,Usb_unicode('M') \
,Usb_unicode('O') \
}
#define USB_SN_LENGTH 0x05
#define USB_SERIAL_NUMBER \
{Usb_unicode('1') \
,Usb_unicode('.') \
,Usb_unicode('0') \
,Usb_unicode('.') \
,Usb_unicode('0') \
}
#define LANGUAGE_ID 0x0409
//! Usb Request
@ -373,39 +385,6 @@ typedef struct {
} S_usb_language_id;
//_____ U S B M A N U F A C T U R E R D E S C R I P T O R _______________
//struct usb_st_manufacturer
typedef struct {
U8 bLength; // size of this descriptor in bytes
U8 bDescriptorType; // STRING descriptor type
U16 wstring[USB_MN_LENGTH];// unicode characters
} S_usb_manufacturer_string_descriptor;
//_____ U S B P R O D U C T D E S C R I P T O R _________________________
//struct usb_st_product
typedef struct {
U8 bLength; // size of this descriptor in bytes
U8 bDescriptorType; // STRING descriptor type
U16 wstring[USB_PN_LENGTH];// unicode characters
} S_usb_product_string_descriptor;
//_____ U S B S E R I A L N U M B E R D E S C R I P T O R _____________
//struct usb_st_serial_number
typedef struct {
U8 bLength; // size of this descriptor in bytes
U8 bDescriptorType; // STRING descriptor type
U16 wstring[USB_SN_LENGTH];// unicode characters
} S_usb_serial_number;
/*_____ U S B I A D _______________________________________________________*/
#define DSC_TYPE_IAD 11
@ -460,6 +439,79 @@ typedef struct
} S_usb_user_configuration_descriptor_network;
/* EEM */
typedef struct
{
S_usb_configuration_descriptor cfg;
S_usb_interface_descriptor ifc0;
S_usb_endpoint_descriptor ep1;
S_usb_endpoint_descriptor ep2;
} S_usb_user_configuration_descriptor_eem;
typedef struct
{
U8 bLength;
U8 bDescriptorType;
U8 bDescriptorSubtype;
U8 iMACAddress;
U32 bmEthernetStatistics;
U16 wMaxSegmentSize;
U16 wNumberMCFilters;
U8 bNumberPowerFilters;
} S_usb_ethernet_networking_functional_descriptor;
/* ECM */
typedef struct
{
S_usb_configuration_descriptor cfg;
S_usb_interface_descriptor ifc0;
U8 CS1_INTERFACE[5+5];
S_usb_ethernet_networking_functional_descriptor fd0;
#if CDC_ECM_USES_INTERRUPT_ENDPOINT
S_usb_endpoint_descriptor ep1;
#endif
#if 0
S_usb_interface_descriptor ifc1_0;
#endif
S_usb_interface_descriptor ifc1_1;
S_usb_endpoint_descriptor ep2;
S_usb_endpoint_descriptor ep3;
} S_usb_user_configuration_descriptor_ecm;
/* ECM + Serial Port */
typedef struct
{
S_usb_configuration_descriptor cfg;
S_usb_interface_association_descriptor iad0;
S_usb_interface_descriptor ifc0;
U8 CS1_INTERFACE[5+5];
S_usb_ethernet_networking_functional_descriptor fd0;
#if CDC_ECM_USES_INTERRUPT_ENDPOINT
S_usb_endpoint_descriptor ep1;
#endif
#if 0
S_usb_interface_descriptor ifc1_0;
#endif
S_usb_interface_descriptor ifc1_1;
S_usb_endpoint_descriptor ep2;
S_usb_endpoint_descriptor ep3;
S_usb_interface_association_descriptor iad1;
S_usb_interface_descriptor ifc2;
U8 CS2_INTERFACE[19];
S_usb_endpoint_descriptor ep4;
S_usb_interface_descriptor ifc3;
S_usb_endpoint_descriptor ep5;
S_usb_endpoint_descriptor ep6;
} S_usb_user_configuration_descriptor_ecm_debug;
/* Mass Storage */
typedef struct
@ -471,20 +523,12 @@ typedef struct
} S_usb_user_configuration_descriptor_mass;
/* EEM */
typedef struct
{
S_usb_configuration_descriptor cfg;
S_usb_interface_descriptor ifc0;
S_usb_endpoint_descriptor ep1;
S_usb_endpoint_descriptor ep2;
} S_usb_user_configuration_descriptor_eem;
PGM_VOID_P Usb_get_dev_desc_pointer(void);
U8 Usb_get_dev_desc_length(void);
PGM_VOID_P Usb_get_conf_desc_pointer(void) ;
U8 Usb_get_conf_desc_length(void);
PGM_VOID_P Usb_get_conf_desc_pointer(U8 index) ;
U8 Usb_get_conf_desc_length(U8 index);
#endif // _USB_USERCONFIG_H_

View file

@ -50,6 +50,7 @@
#include "config.h"
#include "conf_usb.h"
#include "usb_drv.h"
#include <util/delay.h>
//_____ M A C R O S ________________________________________________________
@ -61,6 +62,102 @@
#if (USB_DEVICE_FEATURE == ENABLED)
#define USB_ENDPOINT_WAIT_TIMEOUT 250
U8 usb_endpoint_wait_for_write_enabled() {
#if USB_ENDPOINT_WAIT_TIMEOUT
U16 timeout=USB_ENDPOINT_WAIT_TIMEOUT;
while(timeout) {
if(Is_usb_sof()) {
Usb_ack_sof();
timeout--;
}
#else
while(1) {
#endif
if(Is_usb_write_enabled())
return 0;
if((!Is_usb_enabled()) || Is_usb_detached())
return 1;
if(!Is_usb_endpoint_enabled())
return 2;
if(Is_usb_endpoint_stall_requested())
return 3;
}
return 10;
}
U8 usb_endpoint_wait_for_read_control_enabled() {
#if USB_ENDPOINT_WAIT_TIMEOUT
U16 timeout=USB_ENDPOINT_WAIT_TIMEOUT;
while(timeout) {
if(Is_usb_sof()) {
Usb_ack_sof();
timeout--;
}
#else
while(1) {
#endif
if(Is_usb_read_control_enabled())
return 0;
if((!Is_usb_enabled()) || Is_usb_detached())
return 1;
if(!Is_usb_endpoint_enabled())
return 2;
if(Is_usb_endpoint_stall_requested())
return 3;
}
return 10;
}
U8 usb_endpoint_wait_for_IN_ready() {
#if USB_ENDPOINT_WAIT_TIMEOUT
U16 timeout=USB_ENDPOINT_WAIT_TIMEOUT;
while(timeout) {
if(Is_usb_sof()) {
Usb_ack_sof();
timeout--;
}
#else
while(1) {
#endif
if(Is_usb_in_ready())
return 0;
if((!Is_usb_enabled()) || Is_usb_detached())
return 1;
if(!Is_usb_endpoint_enabled())
return 2;
if(Is_usb_endpoint_stall_requested())
return 3;
}
return 10;
}
U8 usb_endpoint_wait_for_receive_out() {
#if USB_ENDPOINT_WAIT_TIMEOUT
U16 timeout=USB_ENDPOINT_WAIT_TIMEOUT;
while(timeout) {
if(Is_usb_sof()) {
Usb_ack_sof();
timeout--;
}
#else
while(1) {
#endif
if(Is_usb_receive_out())
return 0;
if((!Is_usb_enabled()) || Is_usb_detached())
return 1;
if(!Is_usb_endpoint_enabled())
return 2;
if(Is_usb_endpoint_stall_requested())
return 3;
}
return 10;
}
//! usb_configure_endpoint.
//!
//! This function configures an endpoint with the selected type.

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
//! List of the standard macro used to configure pipes and endpoints
//! @{
#define Usb_build_ep_config0(type, dir, nyet) ((type<<6) | (nyet<<1) | (dir))
#define Usb_build_ep_config0(type, dir, nyet) ((type<<6) /*| (nyet<<1)*/ | (dir))
#define Usb_build_ep_config1(size, bank ) ((size<<4) | (bank<<2) )
#define usb_configure_endpoint(num, type, dir, size, bank, nyet) \
( Usb_select_endpoint(num), \
@ -929,6 +929,13 @@ U8 host_determine_pipe_size (U16);
void host_disable_all_pipe (void);
U8 usb_get_nb_pipe_interrupt (void);
U8 usb_endpoint_wait_for_read_control_enabled();
U8 usb_endpoint_wait_for_write_enabled();
U8 usb_endpoint_wait_for_receive_out();
U8 usb_endpoint_wait_for_IN_ready();
#define usb_endpoint_wait_for_read_enabled usb_endpoint_wait_for_write_enabled
#endif // _USB_DRV_H_
/** @} */

View file

@ -50,10 +50,12 @@
#include "usb_descriptors.h"
#include "usb_specific_request.h"
#include "rndis/rndis_protocol.h"
#include "rndis/cdc_ecm.h"
#include "serial/uart_usb_lib.h"
#include "storage/ctrl_access.h"
#include "uip.h"
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <string.h>
//_____ M A C R O S ________________________________________________________
@ -85,30 +87,44 @@ Bool usb_user_read_request(U8 type, U8 request)
{
U16 wLength;
//Both protocols have two bytes we throw away
Usb_read_byte();
Usb_read_byte();
switch(request)
{
case SEND_ENCAPSULATED_COMMAND:
Usb_read_byte();
Usb_read_byte();
Usb_read_byte();//wIndex LSB
Usb_read_byte();//wIndex MSB
LSB(wLength) = Usb_read_byte();
MSB(wLength) = Usb_read_byte();
return send_encapsulated_command(wLength);
if((usb_configuration_nb==USB_CONFIG_RNDIS)||(usb_configuration_nb==USB_CONFIG_RNDIS_DEBUG))
return rndis_send_encapsulated_command(wLength);
else
return FALSE;
break;
case GET_ENCAPSULATED_COMMAND:
Usb_read_byte();
Usb_read_byte();
Usb_read_byte();//wIndex LSB
Usb_read_byte();//wIndex MSB
LSB(wLength) = Usb_read_byte();
MSB(wLength) = Usb_read_byte();
return get_encapsulated_command();
if((usb_configuration_nb==USB_CONFIG_RNDIS)||(usb_configuration_nb==USB_CONFIG_RNDIS_DEBUG))
return rndis_get_encapsulated_command();
else
return FALSE;
break;
case SET_ETHERNET_PACKET_FILTER:
if((usb_configuration_nb==USB_CONFIG_ECM) || (usb_configuration_nb==USB_CONFIG_ECM_DEBUG)) {
cdc_ecm_set_ethernet_packet_filter();
return TRUE;
} else
return FALSE;
break;
#if USB_CONF_STORAGE
case MASS_STORAGE_RESET:
Usb_ack_receive_setup();
@ -130,18 +146,34 @@ Bool usb_user_read_request(U8 type, U8 request)
/* We don't have a real serial port - so these aren't applicable. We
advertise that we support nothing, so shouldn't get them anyway */
case GET_LINE_CODING:
cdc_get_line_coding();
return TRUE;
Usb_read_byte();
Usb_read_byte();
if(USB_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) {
cdc_get_line_coding();
return TRUE;
} else {
return FALSE;
}
break;
case SET_LINE_CODING:
cdc_set_line_coding();
return TRUE;
Usb_read_byte();
Usb_read_byte();
if(USB_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) {
cdc_set_line_coding();
return TRUE;
} else {
return FALSE;
}
break;
case SET_CONTROL_LINE_STATE:
cdc_set_control_line_state();
return TRUE;
if(USB_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) {
cdc_set_control_line_state();
return TRUE;
} else {
return FALSE;
}
break;
#endif /* USB_CONF_CDC */
default:
@ -174,21 +206,6 @@ Bool usb_user_get_descriptor(U8 type, U8 string)
pbuffer = &(usb_user_language_id.bLength);
return TRUE;
break;
case MAN_INDEX:
data_to_transfer = sizeof (usb_user_manufacturer_string_descriptor);
pbuffer = &(usb_user_manufacturer_string_descriptor.bLength);
return TRUE;
break;
case PROD_INDEX:
data_to_transfer = sizeof (usb_user_product_string_descriptor);
pbuffer = &(usb_user_product_string_descriptor.bLength);
return TRUE;
break;
case SN_INDEX:
data_to_transfer = sizeof (usb_user_serial_number);
pbuffer = &(usb_user_serial_number.bLength);
return TRUE;
break;
default:
return FALSE;
}
@ -198,6 +215,94 @@ Bool usb_user_get_descriptor(U8 type, U8 string)
return FALSE;
}
static char itoh(unsigned char i) {
char ret;
ret = pgm_read_byte_near(PSTR("0123456789abcdef")+(i&0xF));
return ret;
}
const char* usb_user_get_string_sram(U8 string_type) {
static char serial[13];
uint8_t i;
switch (string_type)
{
case USB_STRING_SERIAL:
case USB_STRING_MAC_ADDRESS:
{
uint8_t mac_address[6];
usb_eth_get_mac_address(mac_address);
for(i=0;i<6;i++) {
serial[i*2] = itoh(mac_address[i]>>4);
serial[i*2+1] = itoh(mac_address[i]);
}
}
break;
default:
serial[0] = 0;
break;
}
return serial;
}
PGM_P usb_user_get_string(U8 string_type) {
switch (string_type)
{
case USB_STRING_MAN:
return PSTR("Atmel");
case USB_STRING_PRODUCT:
return PSTR("Jackdaw 6LoWPAN Adaptor");
case USB_STRING_CONFIG_COMPOSITE:
return PSTR("RNDIS+Debug");
case USB_STRING_CONFIG_RNDIS:
case USB_STRING_INTERFACE_RNDIS:
return PSTR("RNDIS");
case USB_STRING_CONFIG_EEM:
case USB_STRING_INTERFACE_EEM:
return PSTR("CDC-EEM");
case USB_STRING_CONFIG_ECM:
case USB_STRING_INTERFACE_ECM:
return PSTR("CDC-ECM");
case USB_STRING_CONFIG_ECM_DEBUG:
return PSTR("CDC-ECM+DEBUG");
case USB_STRING_INTERFACE_SERIAL:
return PSTR("Debug Port");
/*
case USB_STRING_INTERFACE_ECM_ATTACHED:
return PSTR("Attached");
case USB_STRING_INTERFACE_ECM_DETACHED:
return PSTR("Detached");
*/
#if USB_CONF_STORAGE
case USB_STRING_CONFIG_MS:
case USB_STRING_INTERFACE_MS:
return PSTR("Mass Storage");
#endif
/*
// This is now handled by usb_user_get_string_sram.
case USB_STRING_SERIAL:
return PSTR("JD01");
case USB_STRING_MAC_ADDRESS:
return PSTR("021213141516");
*/
default:
return NULL;
}
}
//! usb_user_endpoint_init.
//!
@ -206,115 +311,54 @@ Bool usb_user_get_descriptor(U8 type, U8 string)
//! @param conf_nb Not used
void usb_user_endpoint_init(U8 conf_nb)
{
if(USB_CONFIG_HAS_DEBUG_PORT(conf_nb)) {
uart_usb_configure_endpoints();
}
/* If we use RNDIS endpoints */
if ((usb_mode == rndis_only) || (usb_mode == rndis_debug)) {
switch(conf_nb) {
case USB_CONFIG_ECM:
case USB_CONFIG_ECM_DEBUG:
cdc_ecm_configure_endpoints();
break;
usb_configure_endpoint(INT_EP, \
TYPE_INTERRUPT, \
DIRECTION_IN, \
SIZE_64, \
ONE_BANK, \
NYET_ENABLED);
case USB_CONFIG_RNDIS_DEBUG:
case USB_CONFIG_RNDIS:
rndis_configure_endpoints();
break;
case USB_CONFIG_EEM:
cdc_ecm_configure_endpoints();
usb_configure_endpoint(TX_EP, \
TYPE_BULK, \
DIRECTION_IN, \
SIZE_64, \
TWO_BANKS, \
NYET_ENABLED);
break;
#if USB_CONF_STORAGE
case USB_CONFIG_MS:
usb_configure_endpoint(VCP_INT_EP, \
TYPE_INTERRUPT, \
DIRECTION_IN, \
SIZE_32, \
ONE_BANK, \
NYET_ENABLED);
usb_configure_endpoint(RX_EP, \
TYPE_BULK, \
DIRECTION_OUT, \
SIZE_64, \
TWO_BANKS, \
NYET_ENABLED);
usb_configure_endpoint(VCP_TX_EP, \
TYPE_BULK, \
DIRECTION_IN, \
SIZE_32, \
TWO_BANKS, \
NYET_ENABLED);
}
/* If we use virtual comm port (VCP) endpoints */
if (usb_mode == rndis_debug) {
usb_configure_endpoint(VCP_INT_EP, \
TYPE_INTERRUPT, \
DIRECTION_IN, \
SIZE_32, \
ONE_BANK, \
NYET_ENABLED);
usb_configure_endpoint(VCP_TX_EP, \
TYPE_BULK, \
DIRECTION_IN, \
SIZE_32, \
TWO_BANKS, \
NYET_ENABLED);
usb_configure_endpoint(VCP_RX_EP, \
TYPE_BULK, \
DIRECTION_OUT, \
SIZE_32, \
TWO_BANKS, \
NYET_ENABLED);
}
/* If we use mass storage endpoints */
if (usb_mode == mass_storage) {
usb_configure_endpoint(MS_IN_EP, \
TYPE_BULK, \
DIRECTION_IN, \
SIZE_64, \
ONE_BANK, \
NYET_ENABLED);
usb_configure_endpoint(MS_OUT_EP, \
TYPE_BULK, \
DIRECTION_OUT, \
SIZE_64, \
ONE_BANK, \
NYET_ENABLED);
}
if (usb_mode == eem ) {
usb_configure_endpoint(TX_EP, \
TYPE_BULK, \
DIRECTION_IN, \
SIZE_64, \
TWO_BANKS, \
NYET_ENABLED);
usb_configure_endpoint(RX_EP, \
TYPE_BULK, \
DIRECTION_OUT, \
SIZE_64, \
TWO_BANKS, \
NYET_ENABLED);
}
if ((usb_mode == rndis_only) || (usb_mode == rndis_debug)) {
Usb_reset_endpoint(INT_EP);
Usb_reset_endpoint(TX_EP);
Usb_reset_endpoint(RX_EP);
}
if (usb_mode == rndis_debug){
Usb_reset_endpoint(VCP_INT_EP);
Usb_reset_endpoint(VCP_TX_EP);
Usb_reset_endpoint(VCP_RX_EP);
}
if (usb_mode == mass_storage) {
Usb_reset_endpoint(VCP_TX_EP);
Usb_reset_endpoint(VCP_RX_EP);
}
if (usb_mode == eem){
Usb_reset_endpoint(TX_EP);
Usb_reset_endpoint(RX_EP);
}
usb_configure_endpoint(VCP_RX_EP, \
TYPE_BULK, \
DIRECTION_OUT, \
SIZE_32, \
TWO_BANKS, \
NYET_ENABLED);
Usb_reset_endpoint(VCP_INT_EP);
Usb_reset_endpoint(VCP_TX_EP);
Usb_reset_endpoint(VCP_RX_EP);
break;
#endif
}
Led0_on();
}
#if USB_CONF_CDC
@ -337,12 +381,7 @@ void cdc_get_line_coding(void)
Usb_write_byte(line_coding.bParityType);
Usb_write_byte(line_coding.bDataBits);
Usb_send_control_in();
while(!(Is_usb_read_control_enabled()));
//Usb_clear_tx_complete();
while(!Is_usb_receive_out());
Usb_ack_receive_out();
Usb_send_control_in();
}
@ -352,19 +391,20 @@ void cdc_get_line_coding(void)
//!
void cdc_set_line_coding (void)
{
Usb_ack_receive_setup();
while (!(Is_usb_receive_out()));
LSB0(line_coding.dwDTERate) = Usb_read_byte();
LSB1(line_coding.dwDTERate) = Usb_read_byte();
LSB2(line_coding.dwDTERate) = Usb_read_byte();
LSB3(line_coding.dwDTERate) = Usb_read_byte();
line_coding.bCharFormat = Usb_read_byte();
line_coding.bParityType = Usb_read_byte();
line_coding.bDataBits = Usb_read_byte();
Usb_ack_receive_out();
Usb_ack_receive_setup();
if(usb_endpoint_wait_for_receive_out()==0) {
LSB0(line_coding.dwDTERate) = Usb_read_byte();
LSB1(line_coding.dwDTERate) = Usb_read_byte();
LSB2(line_coding.dwDTERate) = Usb_read_byte();
LSB3(line_coding.dwDTERate) = Usb_read_byte();
line_coding.bCharFormat = Usb_read_byte();
line_coding.bParityType = Usb_read_byte();
line_coding.bDataBits = Usb_read_byte();
Usb_ack_receive_out();
Usb_send_control_in(); // send a ZLP for STATUS phase
while(!(Is_usb_read_control_enabled()));
Usb_send_control_in(); // send a ZLP for STATUS phase
usb_endpoint_wait_for_read_control_enabled();
}
}
//! cdc_set_control_line_state.
@ -375,8 +415,27 @@ void cdc_set_line_coding (void)
//!
void cdc_set_control_line_state (void)
{
U8 controlLineState = Usb_read_byte();
U8 dummy = Usb_read_byte();
U8 interface = Usb_read_byte();
Usb_ack_receive_setup();
Usb_send_control_in();
while(!(Is_usb_read_control_enabled()));
usb_endpoint_wait_for_read_control_enabled();
if(interface == INTERFACE2_NB) {
uart_usb_set_control_line_state(controlLineState);
}
}
#endif /* USB_CONF_CDC */
Bool usb_user_set_alt_interface(U8 interface, U8 alt_setting) {
return FALSE;
if((interface==ECM_INTERFACE0_NB) && ((usb_configuration_nb==USB_CONFIG_ECM) || (usb_configuration_nb==USB_CONFIG_ECM_DEBUG))) {
// The alt_setting in this case corresponds to
// if the interface is enabled or not.
usb_eth_set_active(alt_setting);
}
return TRUE;
}

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_network usb_conf_desc_network;
extern FLASH S_usb_device_qualifier_descriptor usb_qual_desc;
extern FLASH S_usb_manufacturer_string_descriptor usb_user_manufacturer_string_descriptor;
extern FLASH S_usb_product_string_descriptor usb_user_product_string_descriptor;
extern FLASH S_usb_serial_number usb_user_serial_number;
extern FLASH S_usb_language_id usb_user_language_id;
@ -76,6 +73,10 @@ extern FLASH S_usb_language_id usb_user_language_id;
Bool usb_user_read_request(U8, U8);
Bool usb_user_get_descriptor(U8 , U8);
void usb_user_endpoint_init(U8);
Bool usb_user_set_alt_interface(U8 interface, U8 alt_setting);
PGM_P usb_user_get_string(U8 string_type);
const char* usb_user_get_string_sram(U8 string_type);
void cdc_get_line_coding();
void cdc_set_line_coding();

View file

@ -52,11 +52,14 @@
#include "usb_drv.h"
#include "usb_descriptors.h"
#include "usb_specific_request.h"
#include <string.h>
//_____ M A C R O S ________________________________________________________
//_____ D E F I N I T I O N ________________________________________________
#define PRINTF printf
#define PRINTF_P printf_P
//_____ P R I V A T E D E C L A R A T I O N ______________________________
@ -123,43 +126,43 @@ void usb_process_request(void)
{
case GET_DESCRIPTOR:
if (0x80 == bmRequestType) { usb_get_descriptor(); }
else { usb_user_read_request(bmRequestType, bmRequest); }
else goto user_read;
break;
case GET_CONFIGURATION:
if (0x80 == bmRequestType) { usb_get_configuration(); }
else { usb_user_read_request(bmRequestType, bmRequest); }
else goto user_read;
break;
case SET_ADDRESS:
if (0x00 == bmRequestType) { usb_set_address(); }
else { usb_user_read_request(bmRequestType, bmRequest); }
else goto user_read;
break;
case SET_CONFIGURATION:
if (0x00 == bmRequestType) { usb_set_configuration(); }
else { usb_user_read_request(bmRequestType, bmRequest); }
else goto user_read;
break;
case CLEAR_FEATURE:
if (0x02 >= bmRequestType) { usb_clear_feature(); }
else { usb_user_read_request(bmRequestType, bmRequest); }
else goto user_read;
break;
case SET_FEATURE:
if (0x02 >= bmRequestType) { usb_set_feature(); }
else { usb_user_read_request(bmRequestType, bmRequest); }
else goto user_read;
break;
case GET_STATUS:
if ((0x7F < bmRequestType) & (0x82 >= bmRequestType))
{ usb_get_status(); }
else { usb_user_read_request(bmRequestType, bmRequest); }
else goto user_read;
break;
case GET_INTERFACE:
if (bmRequestType == 0x81) { usb_get_interface(); }
else { usb_user_read_request(bmRequestType, bmRequest); }
else goto user_read;
break;
@ -170,14 +173,23 @@ void usb_process_request(void)
case SET_DESCRIPTOR:
case SYNCH_FRAME:
default: //!< un-supported request => call to user read request
if(usb_user_read_request(bmRequestType, bmRequest) == FALSE)
{
Usb_enable_stall_handshake();
Usb_ack_receive_setup();
return;
}
user_read:
usb_user_read_request(bmRequestType, bmRequest);
break;
}
Usb_select_endpoint(EP_CONTROL);
// If the receive setup flag hasn't been cleared
// by this point then we can assume that we didn't
// support this request and should stall.
if(Is_usb_receive_setup())
Usb_enable_stall_handshake();
// Clear some flags.
Usb_ack_receive_setup();
Usb_ack_receive_out();
Usb_ack_in_ready();
}
//! usb_set_address.
@ -214,26 +226,205 @@ U8 configuration_number;
configuration_number = Usb_read_byte();
if (configuration_number <= NB_CONFIGURATION)
{
Usb_ack_receive_setup();
usb_configuration_nb = configuration_number;
}
else
{
//!< keep that order (set StallRq/clear RxSetup) or a
//!< OUT request following the SETUP may be acknowledged
Usb_enable_stall_handshake();
Usb_ack_receive_setup();
return;
}
// TODO: Verify configuration_number!
Usb_ack_receive_setup();
usb_configuration_nb = configuration_number;
Usb_send_control_in(); //!< send a ZLP for STATUS phase
while(!Is_usb_in_ready());
usb_user_endpoint_init(usb_configuration_nb); //!< endpoint configuration
Usb_set_configuration_action();
}
void usb_get_string_descriptor_sram(U8 string_type) {
U16 requested_length;
U8 dummy;
const char* user_str;
user_str = usb_user_get_string_sram(string_type);
dummy = Usb_read_byte(); //!< don't care of wIndex field
dummy = Usb_read_byte();
requested_length = Usb_read_byte(); //!< read wLength
requested_length |= Usb_read_byte()<<8;
if(!user_str)
return;
const U8 actual_descriptor_size = 2+strlen(user_str)*2;
if (requested_length > actual_descriptor_size) {
zlp = ((actual_descriptor_size % EP_CONTROL_LENGTH) == 0);
requested_length = actual_descriptor_size;
}
Usb_ack_receive_setup() ; //!< clear the receive setup flag
if(usb_endpoint_wait_for_read_control_enabled()!=0) {
Usb_enable_stall_handshake();
return;
}
// Output the length
Usb_write_byte(actual_descriptor_size);
// Output the type
Usb_write_byte(STRING_DESCRIPTOR);
requested_length -= 2;
U8 nb_byte = 2;
if(!requested_length) {
Usb_send_control_in();
}
while((requested_length != 0) && (!Is_usb_receive_out()))
{
if(usb_endpoint_wait_for_read_control_enabled()!=0) {
Usb_enable_stall_handshake();
break;
}
while(requested_length != 0) //!< Send data until necessary
{
if(nb_byte==EP_CONTROL_LENGTH) //!< Check endpoint 0 size
{
nb_byte=0;
break;
}
Usb_write_byte(*user_str);
Usb_write_byte(0);
user_str++;
requested_length -=2;
nb_byte+=2;
}
Usb_send_control_in();
}
bail:
if(Is_usb_receive_out()) {
//! abort from Host
Usb_ack_receive_out();
return;
}
if(zlp == TRUE) {
if(usb_endpoint_wait_for_read_control_enabled()!=0) {
Usb_enable_stall_handshake();
return;
}
Usb_send_control_in();
}
usb_endpoint_wait_for_receive_out();
Usb_ack_receive_out();
}
void usb_get_string_descriptor(U8 string_type) {
U16 requested_length;
U8 dummy;
PGM_P user_str;
user_str = usb_user_get_string(string_type);
if(!user_str) {
usb_get_string_descriptor_sram(string_type);
return;
}
dummy = Usb_read_byte(); //!< don't care of wIndex field
dummy = Usb_read_byte();
requested_length = Usb_read_byte(); //!< read wLength
requested_length |= Usb_read_byte()<<8;
const U8 actual_descriptor_size = 2+strlen_P(user_str)*2;
if (requested_length > actual_descriptor_size) {
zlp = ((actual_descriptor_size % EP_CONTROL_LENGTH) == 0);
requested_length = actual_descriptor_size;
}
Usb_ack_receive_setup() ; //!< clear the receive setup flag
if(usb_endpoint_wait_for_read_control_enabled()!=0) {
Usb_enable_stall_handshake();
return;
}
U8 nb_byte = 0;
// Output the length
if(requested_length) {
Usb_write_byte(actual_descriptor_size);
requested_length--;
nb_byte++;
}
// Output the type
if(requested_length) {
Usb_write_byte(STRING_DESCRIPTOR);
requested_length--;
nb_byte++;
}
if(!requested_length) {
Usb_send_control_in();
}
while((requested_length != 0) && (!Is_usb_receive_out()))
{
if(usb_endpoint_wait_for_read_control_enabled()!=0) {
Usb_enable_stall_handshake();
break;
}
while(requested_length != 0) //!< Send data until necessary
{
if(nb_byte==EP_CONTROL_LENGTH) { //!< Check endpoint 0 size
nb_byte=0;
break;
}
Usb_write_byte(pgm_read_byte_near((unsigned int)user_str++));
requested_length--;
nb_byte++;
if(requested_length) {
Usb_write_byte(0);
requested_length--;
nb_byte++;
}
}
Usb_send_control_in();
}
bail:
if(Is_usb_receive_out()) {
//! abort from Host
Usb_ack_receive_out();
return;
}
if(zlp == TRUE) {
if(usb_endpoint_wait_for_read_control_enabled()!=0) {
Usb_enable_stall_handshake();
return;
}
Usb_send_control_in();
}
usb_endpoint_wait_for_receive_out();
Usb_ack_receive_out();
}
//! usb_get_descriptor.
//!
//! This function manages the GET DESCRIPTOR request. The device descriptor,
@ -246,91 +437,93 @@ U8 configuration_number;
//!
void usb_get_descriptor(void)
{
U8 LSBwLength, MSBwLength;
U8 descriptor_type ;
U8 string_type ;
U8 dummy;
U8 nb_byte;
U8 LSBwLength, MSBwLength;
U8 descriptor_type ;
U8 string_type ;
U8 dummy;
zlp = FALSE; /* no zero length packet */
string_type = Usb_read_byte(); /* read LSB of wValue */
descriptor_type = Usb_read_byte(); /* read MSB of wValue */
zlp = FALSE; /* no zero length packet */
string_type = Usb_read_byte(); /* read LSB of wValue */
descriptor_type = Usb_read_byte(); /* read MSB of wValue */
dummy = Usb_read_byte(); //!< don't care of wIndex field
dummy = Usb_read_byte();
LSBwLength = Usb_read_byte(); //!< read wLength
MSBwLength = Usb_read_byte();
switch (descriptor_type)
{
case DEVICE_DESCRIPTOR:
data_to_transfer = Usb_get_dev_desc_length(); //!< sizeof (usb_user_device_descriptor);
pbuffer = Usb_get_dev_desc_pointer();
break;
case CONFIGURATION_DESCRIPTOR:
data_to_transfer = Usb_get_conf_desc_length(string_type); //!< sizeof (usb_user_configuration_descriptor);
pbuffer = Usb_get_conf_desc_pointer(string_type);
break;
case STRING_DESCRIPTOR:
if(string_type!=LANG_ID) {
usb_get_string_descriptor(string_type);
return;
}
default:
dummy = Usb_read_byte();
dummy = Usb_read_byte();
dummy = Usb_read_byte();
dummy = Usb_read_byte();
if( usb_user_get_descriptor(descriptor_type, string_type)==FALSE )
return;
break;
}
switch (descriptor_type)
{
case DEVICE_DESCRIPTOR:
data_to_transfer = Usb_get_dev_desc_length(); //!< sizeof (usb_user_device_descriptor);
pbuffer = Usb_get_dev_desc_pointer();
break;
case CONFIGURATION_DESCRIPTOR:
data_to_transfer = Usb_get_conf_desc_length(); //!< sizeof (usb_user_configuration_descriptor);
pbuffer = Usb_get_conf_desc_pointer();
break;
default:
if( usb_user_get_descriptor(descriptor_type, string_type)==FALSE )
{
Usb_enable_stall_handshake();
Usb_ack_receive_setup();
return;
}
break;
}
dummy = Usb_read_byte(); //!< don't care of wIndex field
dummy = Usb_read_byte();
LSBwLength = Usb_read_byte(); //!< read wLength
MSBwLength = Usb_read_byte();
Usb_ack_receive_setup() ; //!< clear the receive setup flag
Usb_ack_receive_setup() ; //!< clear the receive setup flag
if ((LSBwLength > data_to_transfer) || (MSBwLength)) {
if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
else { zlp = FALSE; } //!< no need of zero length packet
if ((LSBwLength > data_to_transfer) || (MSBwLength))
{
if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
else { zlp = FALSE; } //!< no need of zero length packet
LSBwLength = data_to_transfer;
MSBwLength = 0x00;
} else {
data_to_transfer = LSBwLength; //!< send only requested number of data
}
while((data_to_transfer != 0) && (!Is_usb_receive_out())) {
U8 nb_byte = 0;
if(usb_endpoint_wait_for_read_control_enabled()!=0) {
Usb_enable_stall_handshake();
break;
}
LSBwLength = data_to_transfer;
MSBwLength = 0x00;
}
else
{
data_to_transfer = LSBwLength; //!< send only requested number of data
}
//! Send data until necessary
while(data_to_transfer != 0) {
// if(Is_usb_write_enabled()) //!< Check endpoint 0 size
if(nb_byte++==EP_CONTROL_LENGTH) //!< Check endpoint 0 size
break;
Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++));
data_to_transfer --;
while((data_to_transfer != 0) && (!Is_usb_receive_out()))
{
while(!Is_usb_read_control_enabled());
}
Usb_send_control_in();
}
nb_byte=0;
while(data_to_transfer != 0) //!< Send data until necessary
{
if(nb_byte++==EP_CONTROL_LENGTH) //!< Check endpoint 0 size
{
break;
}
if(Is_usb_receive_out()) {
//! abort from Host
Usb_ack_receive_out();
return;
}
if(zlp == TRUE) {
if(usb_endpoint_wait_for_read_control_enabled()!=0) {
Usb_enable_stall_handshake();
return;
}
Usb_send_control_in();
}
//#ifndef AVRGCC
// Usb_write_byte(*pbuffer++);
//#else // AVRGCC does not support point to PGM space
//#warning AVRGCC assumes devices descriptors are stored in the lower 64Kbytes of on-chip flash memory
Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++));
//#endif
data_to_transfer --;
}
Usb_send_control_in();
}
if(Is_usb_receive_out()) { Usb_ack_receive_out(); return; } //!< abort from Host
if(zlp == TRUE)
{
while(!Is_usb_read_control_enabled());
Usb_send_control_in();
}
while(!Is_usb_receive_out());
Usb_ack_receive_out();
usb_endpoint_wait_for_receive_out();
Usb_ack_receive_out();
}
//! usb_get_configuration.
@ -345,9 +538,9 @@ void usb_get_configuration(void)
Usb_ack_receive_setup();
Usb_write_byte(usb_configuration_nb);
Usb_ack_in_ready();
Usb_send_control_in();
while( !Is_usb_receive_out() );
usb_endpoint_wait_for_receive_out();
Usb_ack_receive_out();
}
@ -390,7 +583,7 @@ U8 dummy;
Usb_write_byte(0x00);
Usb_send_control_in();
while( !Is_usb_receive_out() );
usb_endpoint_wait_for_receive_out();
Usb_ack_receive_out();
}
@ -409,10 +602,6 @@ U8 dummy;
if (bmRequestType == INTERFACE_TYPE)
{
//!< keep that order (set StallRq/clear RxSetup) or a
//!< OUT request following the SETUP may be acknowledged
Usb_enable_stall_handshake();
Usb_ack_receive_setup();
return;
}
else if (bmRequestType == ENDPOINT_TYPE)
@ -426,8 +615,6 @@ U8 dummy;
if (wIndex == EP_CONTROL)
{
Usb_enable_stall_handshake();
Usb_ack_receive_setup();
return;
}
@ -443,15 +630,11 @@ U8 dummy;
else
{
Usb_select_endpoint(EP_CONTROL);
Usb_enable_stall_handshake();
Usb_ack_receive_setup();
return;
}
}
else
{
Usb_enable_stall_handshake();
Usb_ack_receive_setup();
return;
}
}
@ -471,18 +654,10 @@ U8 dummy;
if (bmRequestType == ZERO_TYPE)
{
//!< keep that order (set StallRq/clear RxSetup) or a
//!< OUT request following the SETUP may be acknowledged
Usb_enable_stall_handshake();
Usb_ack_receive_setup();
return;
}
else if (bmRequestType == INTERFACE_TYPE)
{
//!< keep that order (set StallRq/clear RxSetup) or a
//!< OUT request following the SETUP may be acknowledged
Usb_enable_stall_handshake();
Usb_ack_receive_setup();
return;
}
else if (bmRequestType == ENDPOINT_TYPE)
@ -507,19 +682,15 @@ U8 dummy;
endpoint_status[wIndex] = 0x00;
Usb_ack_receive_setup();
Usb_send_control_in();
}
else
{
Usb_select_endpoint(EP_CONTROL);
Usb_enable_stall_handshake();
Usb_ack_receive_setup();
return;
}
}
else
{
Usb_enable_stall_handshake();
Usb_ack_receive_setup();
return;
}
}
@ -533,8 +704,7 @@ U8 dummy;
//!
void usb_get_interface (void)
{
Usb_enable_stall_handshake();
Usb_ack_receive_setup();
// Not yet implemented.
}
//! usb_set_interface.
@ -545,7 +715,21 @@ void usb_get_interface (void)
//!
void usb_set_interface (void)
{
Usb_ack_receive_setup();
Usb_send_control_in(); //!< send a ZLP for STATUS phase
while(!Is_usb_in_ready());
U8 alt_setting;
U8 dummy;
U8 interface;
alt_setting = Usb_read_byte();
dummy = Usb_read_byte();
interface = Usb_read_byte();
if(usb_user_set_alt_interface(interface, alt_setting)) {
Usb_ack_receive_setup();
Usb_send_control_in(); //!< send a ZLP for STATUS phase
while(!Is_usb_in_ready());
usb_endpoint_wait_for_receive_out();
Usb_ack_receive_out();
}
}

View file

@ -166,53 +166,44 @@ void usb_start_device (void)
*/
static void pollhandler(void)
{
/* Check for setup packets */
Usb_select_endpoint(EP_CONTROL);
if (Is_usb_receive_setup()) {
usb_process_request();
}
/* The previous call might have requested we send
out something to the RNDIS interrupt endpoint */
if (schedule_interrupt) {
Usb_select_endpoint(INT_EP);
//RNDIS needs a delay where this isn't called, as it will switch endpoints
//and screw up the data transfers
if (!usb_busy) {
//Linux is a bunch of lies, and won't read
//the interrupt endpoint. Hence if this isn't ready just exit
//while(!Is_usb_write_enabled());
/* Check for setup packets */
Usb_select_endpoint(EP_CONTROL);
if (Is_usb_receive_setup()) {
usb_process_request();
if (Is_usb_write_enabled()) {
// Only valid interrupt is:
// 0x00000001 0x00000000
//
Usb_write_byte(0x01);
Usb_write_byte(0x00);
Usb_write_byte(0x00);
Usb_write_byte(0x00);
Usb_write_byte(0x00);
Usb_write_byte(0x00);
Usb_write_byte(0x00);
Usb_write_byte(0x00);
//Send back
Usb_send_in();
schedule_interrupt = 0;
}
}
/* The previous call might have requested we send
out something to the RNDIS interrupt endpoint */
if (schedule_interrupt) {
Usb_select_endpoint(INT_EP);
//Linux is a bunch of lies, and won't read
//the interrupt endpoint. Hence if this isn't ready just exit
//while(!Is_usb_write_enabled());
if (Is_usb_write_enabled()) {
// Only valid interrupt is:
// 0x00000001 0x00000000
//
Usb_write_byte(0x01);
Usb_write_byte(0x00);
Usb_write_byte(0x00);
Usb_write_byte(0x00);
Usb_write_byte(0x00);
Usb_write_byte(0x00);
Usb_write_byte(0x00);
Usb_write_byte(0x00);
//Send back
Usb_send_in();
schedule_interrupt = 0;
}
}
}
/* Continue polling */
process_poll(&usb_process);
/* Continue polling */
process_poll(&usb_process);
}
/**