parent
67bf9ec10e
commit
0e55eb0947
12 changed files with 1577 additions and 0 deletions
60
cpu/cc253x/usb/Makefile.usb
Normal file
60
cpu/cc253x/usb/Makefile.usb
Normal file
|
@ -0,0 +1,60 @@
|
|||
### Put generated sources in a separate directory
|
||||
BUILTSRCDIR = src_$(TARGET)
|
||||
ifeq (${wildcard $(BUILTSRCDIR)},)
|
||||
DUMMY := ${shell mkdir $(BUILTSRCDIR)}
|
||||
endif
|
||||
|
||||
STRUCTGEN = structgen
|
||||
|
||||
PROJECTDIRS += $(BUILTSRCDIR)
|
||||
|
||||
USB_STRING_DESCRIPTORS ?= $(CONTIKI_CPU_ARM)/common/usb/cdc-acm/string-descriptors.xml
|
||||
|
||||
XMLDIRS=
|
||||
|
||||
USB = usb-arch.c usb-core.c
|
||||
|
||||
ifdef USB_CDC_ACM_CLASS
|
||||
CONTIKI_CPU_DIRS += ../common/usb/cdc-acm
|
||||
USB += cdc-acm.c cdc-acm-descriptors.c cdc-acm-string-descriptors.c
|
||||
XMLDIRS += $(CONTIKI_CPU_ARM)/common/usb/cdc-acm/
|
||||
endif
|
||||
|
||||
ifdef USB_CDC_ETH_CLASS
|
||||
CONTIKI_CPU_DIRS += ../common/usb/cdc-eth
|
||||
USB += cdc-eth.c cdc-eth-descriptors.c cdc-eth-string-descriptors.c dhcps.c
|
||||
XMLDIRS += $(CONTIKI_CPU_ARM)/common/usb/cdc-eth/
|
||||
endif
|
||||
|
||||
ifdef USB_MASS_STORAGE_CLASS
|
||||
CONTIKI_CPU_DIRS += ../common/usb/msc
|
||||
USB += usb-msc-bulk.c usb-rbc.c msc-descriptors-consts.c msc-descriptors.c
|
||||
XMLDIRS += $(CONTIKI_CPU_ARM)/common/usb/msc
|
||||
endif
|
||||
|
||||
ifdef USB_MSC_QIC157
|
||||
CONTIKI_CPU_DIRS += ../common/usb/msc
|
||||
USB += usb-msc-bulk.c usb-qic157.c msc-qic157-descriptors.c msc-qic157-string-descriptors.c
|
||||
XMLDIRS += $(CONTIKI_CPU_ARM)/common/usb/msc
|
||||
endif
|
||||
|
||||
ifdef USB_MSC_STREAMING
|
||||
CONTIKI_CPU_DIRS += ../common/usb/msc
|
||||
USB += usb-msc-bulk.c usb-streaming.c msc-scsi-streaming-descriptors-consts.c msc-scsi-streaming-descriptors.c
|
||||
XMLDIRS += $(CONTIKI_CPU_ARM)/common/usb/msc
|
||||
endif
|
||||
|
||||
ifdef USB_MTP_CLASS
|
||||
CONTIKI_CPU_DIRS += ../common/usb/mtp
|
||||
USB += usb-mtp.c mtp-descriptors-consts.c mtp-descriptors.c
|
||||
STRUCTGENDIRS += $(CONTIKI_CPU_ARM)/common/usb/mtp
|
||||
endif
|
||||
|
||||
vpath %.xml $(XMLDIRS)
|
||||
vpath %.gen.c $(STRUCTGENDIRS)
|
||||
|
||||
%.c: %.xml
|
||||
$(XSLTPROC) $(CONTIKI_CPU_ARM)/common/usb/string-descriptors.xslt $^ >$(BUILTSRCDIR)/$@
|
||||
|
||||
%-consts.c: %.gen.c
|
||||
$(CPP) -I$(CFLAGS) $< | $(STRUCTGEN) --output $(BUILTSRCDIR)/$*-consts.c
|
126
cpu/cc253x/usb/cdc-acm-descriptors.c
Normal file
126
cpu/cc253x/usb/cdc-acm-descriptors.c
Normal file
|
@ -0,0 +1,126 @@
|
|||
#include "descriptors.h"
|
||||
#include "contiki-conf.h"
|
||||
#include "cdc.h"
|
||||
#include "usb-arch.h"
|
||||
|
||||
const struct usb_st_device_descriptor device_descriptor =
|
||||
{
|
||||
sizeof(struct usb_st_device_descriptor),
|
||||
DEVICE,
|
||||
0x0210,
|
||||
CDC,
|
||||
0,
|
||||
0,
|
||||
CTRL_EP_SIZE,
|
||||
0xffff,
|
||||
0xffff,
|
||||
0x0030,
|
||||
2,
|
||||
1,
|
||||
3,
|
||||
1
|
||||
};
|
||||
|
||||
const struct configuration_st {
|
||||
struct usb_st_configuration_descriptor configuration;
|
||||
struct usb_st_interface_descriptor comm;
|
||||
struct usb_cdc_header_func_descriptor header;
|
||||
struct usb_cdc_abstract_ctrl_mgmnt_func_descriptor abstract_ctrl;
|
||||
struct usb_cdc_union_func_descriptor union_descr;
|
||||
struct usb_cdc_call_mgmnt_func_descriptor call_mgmt;
|
||||
#if 1
|
||||
struct usb_st_endpoint_descriptor ep_notification;
|
||||
#endif
|
||||
struct usb_st_interface_descriptor data;
|
||||
struct usb_st_endpoint_descriptor ep_in;
|
||||
struct usb_st_endpoint_descriptor ep_out;
|
||||
} BYTE_ALIGNED configuration_block =
|
||||
{
|
||||
/* Configuration */
|
||||
{
|
||||
sizeof(configuration_block.configuration),
|
||||
CONFIGURATION,
|
||||
sizeof(configuration_block),
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0x80,
|
||||
50
|
||||
},
|
||||
{
|
||||
sizeof(configuration_block.comm),
|
||||
INTERFACE,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
CDC,
|
||||
ABSTRACT_CONTROL_MODEL,
|
||||
V_25TER_PROTOCOL,
|
||||
0
|
||||
},
|
||||
{
|
||||
sizeof(configuration_block.header),
|
||||
CS_INTERFACE,
|
||||
CDC_FUNC_DESCR_HEADER,
|
||||
0x0110
|
||||
},
|
||||
{
|
||||
sizeof(configuration_block.abstract_ctrl),
|
||||
CS_INTERFACE,
|
||||
CDC_FUNC_DESCR_ABSTRACT_CTRL_MGMNT,
|
||||
0
|
||||
},
|
||||
{
|
||||
sizeof(configuration_block.union_descr),
|
||||
CS_INTERFACE,
|
||||
CDC_FUNC_DESCR_UNION,
|
||||
0, /* Master */
|
||||
{1} /* Slave */
|
||||
},
|
||||
{
|
||||
sizeof(configuration_block.call_mgmt),
|
||||
CS_INTERFACE,
|
||||
CDC_FUNC_DESCR_CALL_MGMNT,
|
||||
0x02,
|
||||
1 /* data interface */
|
||||
},
|
||||
{
|
||||
sizeof(configuration_block.ep_notification),
|
||||
ENDPOINT,
|
||||
0x83,
|
||||
0x03,
|
||||
USB_EP3_SIZE,
|
||||
100
|
||||
},
|
||||
{
|
||||
sizeof(configuration_block.data),
|
||||
INTERFACE,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
CDC_DATA,
|
||||
0,
|
||||
TRANSPARENT_PROTOCOL,
|
||||
0
|
||||
},
|
||||
{
|
||||
sizeof(configuration_block.ep_in),
|
||||
ENDPOINT,
|
||||
0x81,
|
||||
0x02,
|
||||
USB_EP1_SIZE,
|
||||
0
|
||||
},
|
||||
{
|
||||
sizeof(configuration_block.ep_out),
|
||||
ENDPOINT,
|
||||
0x02,
|
||||
0x02,
|
||||
USB_EP2_SIZE,
|
||||
0
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const struct usb_st_configuration_descriptor const *configuration_head =
|
||||
(struct usb_st_configuration_descriptor const*)&configuration_block;
|
111
cpu/cc253x/usb/common/cdc-acm/cdc-acm.c
Normal file
111
cpu/cc253x/usb/common/cdc-acm/cdc-acm.c
Normal file
|
@ -0,0 +1,111 @@
|
|||
#include "cdc-acm.h"
|
||||
#include "cdc.h"
|
||||
#include "usb-api.h"
|
||||
#include "usb-core.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static uint8_t usb_ctrl_data_buffer[32];
|
||||
|
||||
static void
|
||||
encapsulated_command(uint8_t *data, unsigned int length)
|
||||
{
|
||||
printf("Got CDC command: length %d\n", length);
|
||||
usb_send_ctrl_status();
|
||||
}
|
||||
static void
|
||||
set_line_encoding(uint8_t *data, unsigned int length)
|
||||
{
|
||||
if (length == 7) {
|
||||
static const char parity_char[] = {'N', 'O', 'E', 'M', 'S'};
|
||||
static const char *stop_bits_str[] = {"1","1.5","2"};
|
||||
const struct usb_cdc_line_coding *coding =
|
||||
(const struct usb_cdc_line_coding *)usb_ctrl_data_buffer;
|
||||
char parity = ((coding->bParityType > 4)
|
||||
? '?' : parity_char[coding->bParityType]);
|
||||
const char *stop_bits = ((coding->bCharFormat > 2)
|
||||
? "?" : stop_bits_str[coding->bCharFormat]);
|
||||
printf("Got CDC line coding: %ld/%d/%c/%s\n",
|
||||
coding->dwDTERate, coding->bDataBits, parity, stop_bits);
|
||||
usb_send_ctrl_status();
|
||||
} else {
|
||||
usb_error_stall();
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
handle_cdc_acm_requests()
|
||||
{
|
||||
printf("CDC request %02x %02x\n", usb_setup_buffer.bmRequestType, usb_setup_buffer.bRequest);
|
||||
switch(usb_setup_buffer.bmRequestType) {
|
||||
case 0x21: /* CDC interface OUT requests */
|
||||
/* Check if it's the right interface */
|
||||
if (usb_setup_buffer.wIndex != 0) return 0;
|
||||
switch(usb_setup_buffer.bRequest) {
|
||||
case SET_CONTROL_LINE_STATE:
|
||||
if (usb_setup_buffer.wValue & 0x02) {
|
||||
puts("Carrier on");
|
||||
} else {
|
||||
puts("Carrier off");
|
||||
}
|
||||
if (usb_setup_buffer.wValue & 0x01) {
|
||||
puts("DTE on");
|
||||
} else {
|
||||
puts("DTE off");
|
||||
}
|
||||
usb_send_ctrl_status();
|
||||
return 1;
|
||||
|
||||
case SEND_ENCAPSULATED_COMMAND:
|
||||
{
|
||||
unsigned int len = usb_setup_buffer.wLength;
|
||||
if (len > sizeof(usb_ctrl_data_buffer))
|
||||
len = sizeof(usb_ctrl_data_buffer);
|
||||
usb_get_ctrl_data(usb_ctrl_data_buffer, len,
|
||||
encapsulated_command);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
|
||||
case SET_LINE_CODING:
|
||||
{
|
||||
unsigned int len = usb_setup_buffer.wLength;
|
||||
if (len > sizeof(usb_ctrl_data_buffer))
|
||||
len = sizeof(usb_ctrl_data_buffer);
|
||||
usb_get_ctrl_data(usb_ctrl_data_buffer, len,
|
||||
set_line_encoding);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 0xa1: /* CDC interface IN requests */
|
||||
if (usb_setup_buffer.wIndex != 0) return 0;
|
||||
switch(usb_setup_buffer.bRequest) {
|
||||
case GET_ENCAPSULATED_RESPONSE:
|
||||
printf("CDC response");
|
||||
usb_send_ctrl_status();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct USBRequestHandler cdc_acm_request_handler =
|
||||
{
|
||||
0x21, 0x7f,
|
||||
0x00, 0x00,
|
||||
handle_cdc_acm_requests
|
||||
};
|
||||
|
||||
static struct USBRequestHandlerHook cdc_acm_request_hook =
|
||||
{
|
||||
NULL,
|
||||
&cdc_acm_request_handler
|
||||
};
|
||||
|
||||
void
|
||||
usb_cdc_acm_setup()
|
||||
{
|
||||
usb_register_request_handler(&cdc_acm_request_hook);
|
||||
}
|
7
cpu/cc253x/usb/common/cdc-acm/cdc-acm.h
Normal file
7
cpu/cc253x/usb/common/cdc-acm/cdc-acm.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#ifndef __CDC_ACM_H__UFV6K50827__
|
||||
#define __CDC_ACM_H__UFV6K50827__
|
||||
|
||||
void
|
||||
usb_cdc_acm_setup();
|
||||
|
||||
#endif /* __CDC_ACM_H__UFV6K50827__ */
|
203
cpu/cc253x/usb/common/cdc-acm/cdc.h
Normal file
203
cpu/cc253x/usb/common/cdc-acm/cdc.h
Normal file
|
@ -0,0 +1,203 @@
|
|||
#ifndef __CDC_H__K1Q26ESJOC__
|
||||
#define __CDC_H__K1Q26ESJOC__
|
||||
#include "usb.h"
|
||||
/* Communication Class */
|
||||
/* Class code */
|
||||
#define CDC 0x02
|
||||
|
||||
/* Interface subclass codes */
|
||||
#define CDC_RESERVED 0x00
|
||||
#define DIRECT_LINE_CONTROL_MODEL 0x01
|
||||
#define ABSTRACT_CONTROL_MODEL 0x02
|
||||
#define TELEPHONE_CONTROL_MODEL 0x03
|
||||
#define MULTI_CHANNEL_CONTROL_MODEL 0x04
|
||||
#define CAPI_CONTROL_MODEL 0x05
|
||||
#define ETHERNET_NETWORKING_CONTROL_MODEL 0x06
|
||||
#define ATM_NETWORKING_CONTROL_MODEL 0x07
|
||||
|
||||
/* Protocols */
|
||||
#define V_25TER_PROTOCOL 0x01
|
||||
|
||||
/* Requests */
|
||||
#define SEND_ENCAPSULATED_COMMAND 0x00
|
||||
#define GET_ENCAPSULATED_RESPONSE 0x01
|
||||
#define SET_COMM_FEATURE 0x02
|
||||
#define GET_COMM_FEATURE 0x03
|
||||
#define CLEAR_COMM_FEATURE 0x04
|
||||
|
||||
#define SET_AUX_LINE_STATE 0x10
|
||||
#define SET_HOOK_STATE 0x11
|
||||
#define PULSE_SETUP 0x12
|
||||
#define SEND_PULSE 0x13
|
||||
#define SET_PULSE_TIME 0x14
|
||||
#define RING_AUX_JACK 0x15
|
||||
|
||||
#define SET_LINE_CODING 0x20
|
||||
#define GET_LINE_CODING 0x21
|
||||
#define SET_CONTROL_LINE_STATE 0x22
|
||||
#define SEND_BREAK 0x23
|
||||
|
||||
#define SET_RINGER_PARMS 0x30
|
||||
#define GET_RINGER_PARMS 0x31
|
||||
#define SET_OPERATION_PARMS 0x32
|
||||
#define GET_OPERATION_PARMS 0x33
|
||||
#define SET_LINE_PARMS 0x34
|
||||
#define GET_LINE_PARMS 0x35
|
||||
#define DIAL_DIGITS 0x36
|
||||
|
||||
#define SET_UNIT_PARAMETER 0x37
|
||||
#define GET_UNIT_PARAMETER 0x38
|
||||
#define CLEAR_UNIT_PARAMETER 0x39
|
||||
|
||||
#define GET_PROFILE 0x3a
|
||||
|
||||
#define SET_ETHERNET_MULTICAST_FILTERS 0x40
|
||||
#define GET_ETHERNET_MULTICAST_FILTERS 0x41
|
||||
#define GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER 0x42
|
||||
#define SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER 0x43
|
||||
#define GET_ETHERNET_STATISTIC 0x44
|
||||
|
||||
#define SET_ATM_D ATA_FORMAT 0x50
|
||||
#define GET_ATM_DEVICE_STATISTICS 0x51
|
||||
#define SET_ATM_DEFAULT_VC 0x52
|
||||
#define GET_ATM_VC_STATISTICS 0x53
|
||||
|
||||
|
||||
/* Notifications */
|
||||
#define NETWORK_CONNECTION 0x00
|
||||
#define RESPONSE_AVAILABLE 0x01
|
||||
|
||||
#define AUX_JACK_HOOK_STATE 0x08
|
||||
#define RING_DETECT 0x09
|
||||
|
||||
#define SERIAL_STATE 0x20
|
||||
|
||||
#define CALL_STATE_CHANGE 0x28
|
||||
#define LINE_STATE_CHANGE 0x29
|
||||
#define CONNECTION_SPEED_CHANGE 0x2a
|
||||
|
||||
/* Data interface */
|
||||
|
||||
/* Class code */
|
||||
#define CDC_DATA 0x0a
|
||||
|
||||
/* Protocols */
|
||||
#define I_430_PROTOCOL 0x30
|
||||
#define ISO_IEC_3_1993_PROTOCOL 0x31
|
||||
#define TRANSPARENT_PROTOCOL 0x32
|
||||
#define Q_921M_PROTOCOL 0x50
|
||||
#define Q_921_PROTOCOL 0x51
|
||||
#define Q_921TM_PROTOCOL 0x52
|
||||
#define V_42BIS_PROTOCOL 0x90
|
||||
#define Q_931_PROTOCOL 0x91
|
||||
#define V_120_PROTOCOL 0x93
|
||||
#define CDC_PROTOCOL 0xfe
|
||||
|
||||
/* Descriptor subtypes */
|
||||
|
||||
#define CDC_FUNC_DESCR_HEADER 0x00
|
||||
#define CDC_FUNC_DESCR_CALL_MGMNT 0x01
|
||||
#define CDC_FUNC_DESCR_ABSTRACT_CTRL_MGMNT 0x02
|
||||
#define CDC_FUNC_DESCR_DIRECT_LINE_MGMNT 0x03
|
||||
#define CDC_FUNC_DESCR_RINGER_MGMNT 0x04
|
||||
#define CDC_FUNC_DESCR_TEL_STATE 0x05
|
||||
#define CDC_FUNC_DESCR_UNION 0x06
|
||||
#define CDC_FUNC_DESCR_COUNTRY 0x07
|
||||
#define CDC_FUNC_DESCR_TEL_MODE 0x08
|
||||
#define CDC_FUNC_DESCR_USB_TERM 0x09
|
||||
#define CDC_FUNC_DESCR_NET_TERM 0x0a
|
||||
#define CDC_FUNC_DESCR_PROTOCOL_UNIT 0x0b
|
||||
#define CDC_FUNC_DESCR_EXTENSION_UNIT 0x0c
|
||||
#define CDC_FUNC_DESCR_MULTICH_MGMNT 0x0d
|
||||
#define CDC_FUNC_DESCR_CAPI_MGMNT 0x0e
|
||||
#define CDC_FUNC_DESCR_ETHERNET 0x0f
|
||||
#define CDC_FUNC_DESCR_ATM 0x10
|
||||
|
||||
|
||||
|
||||
struct usb_cdc_header_func_descriptor {
|
||||
Uchar bLength; /* Size of this descriptor in bytes */
|
||||
Uchar bDescriptorType; /* CS_INTERFACE descriptor type */
|
||||
Uchar bDescriptorSubtype; /* CDC_FUNC_DESCR_HEADER subtype */
|
||||
Uint16 bcdCDC; /* Revision of class specification */
|
||||
} BYTE_ALIGNED;
|
||||
|
||||
struct usb_cdc_call_mgmnt_func_descriptor {
|
||||
Uchar bLength; /* Size of this descriptor in bytes */
|
||||
Uchar bDescriptorType; /* CS_INTERFACE descriptor type */
|
||||
Uchar bDescriptorSubtype; /* CDC_FUNC_DESCR_CALL_MGMNT subtype */
|
||||
Uchar bmCapabilities; /* Capabilities */
|
||||
Uchar bDataInterface; /* Management data interface */
|
||||
} BYTE_ALIGNED;
|
||||
|
||||
struct usb_cdc_abstract_ctrl_mgmnt_func_descriptor {
|
||||
Uchar bLength; /* Size of this descriptor in bytes */
|
||||
Uchar bDescriptorType; /* CS_INTERFACE descriptor type */
|
||||
Uchar bDescriptorSubtype; /* CDC_FUNC_DESCR_ABSTRACT_CTRL_MGMNT subtype */
|
||||
Uchar bmCapabilities; /* Capabilities */
|
||||
} BYTE_ALIGNED;
|
||||
|
||||
struct usb_cdc_direct_line_mgmnt_func_descriptor {
|
||||
Uchar bLength; /* Size of this descriptor in bytes */
|
||||
Uchar bDescriptorType; /* CS_INTERFACE descriptor type */
|
||||
Uchar bDescriptorSubtype; /* CDC_FUNC_DESCR_DIRECT_LINE_MGMNT subtype */
|
||||
Uchar bmCapabilities; /* Capabilities */
|
||||
} BYTE_ALIGNED;
|
||||
|
||||
struct usb_cdc_ringer_mgmnt_func_descriptor {
|
||||
Uchar bLength; /* Size of this descriptor in bytes */
|
||||
Uchar bDescriptorType; /* CS_INTERFACE descriptor type */
|
||||
Uchar bDescriptorSubtype; /* CDC_FUNC_DESCR_RINGER_MGMNT subtype */
|
||||
Uchar bRingerVolSteps; /* Ringer volume steps */
|
||||
Uchar bNumRingerPatterns; /* Number of ringer patterns supported */
|
||||
} BYTE_ALIGNED;
|
||||
|
||||
struct usb_cdc_tel_mode_func_descriptor {
|
||||
Uchar bLength; /* Size of this descriptor in bytes */
|
||||
Uchar bDescriptorType; /* CS_INTERFACE descriptor type */
|
||||
Uchar bDescriptorSubtype; /* CDC_FUNC_DESCR_TEL_MODE subtype */
|
||||
Uchar bmCapabilities; /* Capabilities */
|
||||
} BYTE_ALIGNED;
|
||||
|
||||
struct usb_cdc_tel_state_func_descriptor {
|
||||
Uchar bLength; /* Size of this descriptor in bytes */
|
||||
Uchar bDescriptorType; /* CS_INTERFACE descriptor type */
|
||||
Uchar bDescriptorSubtype; /* CDC_FUNC_DESCR_TEL_STATE subtype */
|
||||
Uchar bmCapabilities; /* Capabilities */
|
||||
} BYTE_ALIGNED;
|
||||
|
||||
struct usb_cdc_union_func_descriptor {
|
||||
Uchar bLength; /* Size of this descriptor in bytes */
|
||||
Uchar bDescriptorType; /* CS_INTERFACE descriptor type */
|
||||
Uchar bDescriptorSubtype; /* CDC_FUNC_DESCR_UNION subtype */
|
||||
Uchar bMasterInterface; /* Master interface for union */
|
||||
Uchar bSlaveInterface[1]; /* Slave interfaces in union */
|
||||
} BYTE_ALIGNED;
|
||||
|
||||
struct usb_cdc_country_func_descriptor {
|
||||
Uchar bLength; /* Size of this descriptor in bytes */
|
||||
Uchar bDescriptorType; /* CS_INTERFACE descriptor type */
|
||||
Uchar bDescriptorSubtype; /* CDC_FUNC_DESCR_COUNTRY subtype */
|
||||
Uchar iCountryCodeRelDate; /* Release date for country codes */
|
||||
Uint16 wCountryCode[1]; /* Country codes */
|
||||
} BYTE_ALIGNED;
|
||||
|
||||
struct usb_cdc_ethernet_func_descriptor {
|
||||
Uchar bLength; /* Size of this descriptor in bytes */
|
||||
Uchar bDescriptorType; /* CS_INTERFACE descriptor type */
|
||||
Uchar bDescriptorSubtype; /* CDC_FUNC_DESCR_ETHERNET subtype */
|
||||
Uchar iMACAddress; /* MAC address string descriptor */
|
||||
Uint32 bmEthernetStatistics; /* Supported statistics */
|
||||
Uint16 wMaxSegmentSize;
|
||||
Uint16 wNumberMCFilters; /* Number of multicast filters */
|
||||
Uchar bNumberPowerFilters; /* Number of wake-up pattern filters */
|
||||
} BYTE_ALIGNED;
|
||||
|
||||
struct usb_cdc_line_coding {
|
||||
Uint32 dwDTERate;
|
||||
Uchar bCharFormat;
|
||||
Uchar bParityType;
|
||||
Uchar bDataBits;
|
||||
} BYTE_ALIGNED;
|
||||
|
||||
#endif /* __CDC_H__K1Q26ESJOC__ */
|
10
cpu/cc253x/usb/common/descriptors.h
Normal file
10
cpu/cc253x/usb/common/descriptors.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef __DESCRIPTORS_H__RPFUB8O7OV__
|
||||
#define __DESCRIPTORS_H__RPFUB8O7OV__
|
||||
|
||||
#ifndef STRUCTGEN
|
||||
#include "usb.h"
|
||||
#endif
|
||||
|
||||
extern const struct usb_st_device_descriptor device_descriptor;
|
||||
extern const struct usb_st_configuration_descriptor const *configuration_head;
|
||||
#endif /* __DESCRIPTORS_H__RPFUB8O7OV__ */
|
20
cpu/cc253x/usb/common/string-descriptors.h
Normal file
20
cpu/cc253x/usb/common/string-descriptors.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef STRUCTGEN
|
||||
#include "usb.h"
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
struct usb_st_string_language_map {
|
||||
uint16_t lang_id;
|
||||
const struct usb_st_string_descriptor *const *descriptors;
|
||||
};
|
||||
|
||||
struct usb_st_string_languages {
|
||||
uint8_t num_lang;
|
||||
uint8_t max_index;
|
||||
const struct usb_st_language_descriptor *lang_descr;
|
||||
const struct usb_st_string_language_map map[1];
|
||||
};
|
||||
|
||||
extern const struct usb_st_string_languages *const string_languages;
|
||||
|
||||
const uint8_t *usb_class_get_string_descriptor(uint16_t lang, uint8_t index);
|
127
cpu/cc253x/usb/common/usb-api.h
Normal file
127
cpu/cc253x/usb/common/usb-api.h
Normal file
|
@ -0,0 +1,127 @@
|
|||
#ifndef __USB_API_H__SYN81IFYBN__
|
||||
#define __USB_API_H__SYN81IFYBN__
|
||||
|
||||
#include "sys/process.h"
|
||||
|
||||
typedef struct _USBBuffer USBBuffer;
|
||||
|
||||
struct _USBBuffer {
|
||||
USBBuffer *next; /* Pointer to next buffer in chain */
|
||||
uint8_t *data; /* Where to read/write data next */
|
||||
uint16_t left; /* Remaining length of buffer. */
|
||||
uint16_t flags;
|
||||
uint32_t id; /* User data */
|
||||
};
|
||||
|
||||
/* Buffer owned by the USB code, cleared when done */
|
||||
#define USB_BUFFER_SUBMITTED 0x01
|
||||
|
||||
/* Write a short packet at end of buffer or release buffer when a
|
||||
short packet is received. */
|
||||
#define USB_BUFFER_SHORT_END 0x02
|
||||
|
||||
/* Release buffer as soon as any received data has been written in it. */
|
||||
#define USB_BUFFER_PACKET_END 0x04
|
||||
|
||||
/* Notify the user when the buffer is released */
|
||||
#define USB_BUFFER_NOTIFY 0x08
|
||||
|
||||
/* Packet should be sent to host. */
|
||||
#define USB_BUFFER_IN 0x40
|
||||
|
||||
/* Used for receiving SETUP packets. If a SETUP packet is received and
|
||||
the next buffers doesn't have this flag set, they will be skipped
|
||||
until one is found. The associated buffer must be at least 8 bytes */
|
||||
#define USB_BUFFER_SETUP 0x20
|
||||
|
||||
/* HALT the endpoint at this point. Only valid for bulk and interrupt
|
||||
endpoints */
|
||||
#define USB_BUFFER_HALT 0x100
|
||||
|
||||
/* Flags set by system */
|
||||
|
||||
/* The last packet written to this buffer was short. */
|
||||
#define USB_BUFFER_SHORT_PACKET 0x10
|
||||
|
||||
/* The operation associated with this buffer failed. I.e. it was discarded since it didn't match the received SETUP packet. */
|
||||
#define USB_BUFFER_FAILED 0x80
|
||||
|
||||
/* Architecture specific flags */
|
||||
#define USB_BUFFER_ARCH_FLAG_1 0x1000
|
||||
#define USB_BUFFER_ARCH_FLAG_2 0x2000
|
||||
#define USB_BUFFER_ARCH_FLAG_3 0x4000
|
||||
#define USB_BUFFER_ARCH_FLAG_4 0x8000
|
||||
|
||||
void usb_setup(void);
|
||||
|
||||
|
||||
/* Read only */
|
||||
struct USBRequestHandler {
|
||||
uint8_t request_type;
|
||||
uint8_t request_type_mask;
|
||||
uint8_t request;
|
||||
uint8_t request_mask;
|
||||
/* Returns true if it handled the request, if false let another handler try */
|
||||
unsigned int (*handler_func) ();
|
||||
};
|
||||
|
||||
/* Must be writeable */
|
||||
struct USBRequestHandlerHook {
|
||||
struct USBRequestHandlerHook *next;
|
||||
const struct USBRequestHandler *const handler;
|
||||
};
|
||||
|
||||
void usb_register_request_handler(struct USBRequestHandlerHook *hook);
|
||||
|
||||
void usb_prepend_request_handler(struct USBRequestHandlerHook *hook);
|
||||
|
||||
void usb_setup_bulk_endpoint(uint8_t addr);
|
||||
|
||||
void usb_setup_interrupt_endpoint(uint8_t addr);
|
||||
|
||||
/* Submit a chain of buffers to be filled with received data. Last
|
||||
buffer must have next set to NULL. */
|
||||
void usb_submit_recv_buffer(uint8_t ep_addr, USBBuffer * buffer);
|
||||
|
||||
/* Submit a chain of buffers to be sent. Last buffer must have next
|
||||
set to NULL. When submitting packets to receive or send data in on
|
||||
a control enpoint, all packets in the data stage must be submitted
|
||||
at the same time. */
|
||||
void usb_submit_xmit_buffer(uint8_t ep_addr, USBBuffer * buffer);
|
||||
|
||||
/* Return true if not all data has been sent to the host */
|
||||
int usb_send_pending(uint8_t ep_addr);
|
||||
|
||||
/* Release all buffers submitted to the endpoint and discard any
|
||||
buffered data. */
|
||||
void usb_discard_all_buffers(uint8_t ep_addr);
|
||||
|
||||
void usb_disable_endpoint(uint8_t addr);
|
||||
|
||||
/* Set or remove a HALT condition on an endpoint */
|
||||
void usb_halt_endpoint(uint8_t addr, int halt);
|
||||
|
||||
/* Select what process should be polled when buffers with the
|
||||
USB_BUFFER_NOTIFY flag set is released from the endpoint */
|
||||
void usb_set_ep_event_process(uint8_t addr, struct process *p);
|
||||
|
||||
/* Select what process should be polled when a global event occurs */
|
||||
void usb_set_global_event_process(struct process *p);
|
||||
|
||||
/* Global events */
|
||||
#define USB_EVENT_CONFIG 0x01
|
||||
#define USB_EVENT_SUSPEND 0x02
|
||||
#define USB_EVENT_RESUME 0x04
|
||||
#define USB_EVENT_RESET 0x08
|
||||
|
||||
/* Returns global events that has occured since last time this
|
||||
function was called */
|
||||
unsigned int usb_get_global_events(void);
|
||||
|
||||
|
||||
#define USB_EP_EVENT_NOTIFICATION 0x01
|
||||
unsigned int usb_get_ep_events(uint8_t addr);
|
||||
|
||||
unsigned int usb_get_current_configuration(void);
|
||||
|
||||
#endif /* __USB_API_H__SYN81IFYBN__ */
|
77
cpu/cc253x/usb/common/usb-arch.h
Normal file
77
cpu/cc253x/usb/common/usb-arch.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
#ifndef __USB_ARCH_H__0Z52ZDP0H6__
|
||||
#define __USB_ARCH_H__0Z52ZDP0H6__
|
||||
|
||||
#include "contiki-conf.h"
|
||||
#include "usb-api.h"
|
||||
|
||||
|
||||
/* Includes control endpoint 0 */
|
||||
#ifndef USB_MAX_ENDPOINTS
|
||||
#define USB_MAX_ENDPOINTS 4
|
||||
#endif
|
||||
|
||||
#ifndef CTRL_EP_SIZE
|
||||
#define CTRL_EP_SIZE 8
|
||||
#endif
|
||||
|
||||
#ifndef USB_EP1_SIZE
|
||||
#define USB_EP1_SIZE 8
|
||||
#endif
|
||||
#ifndef USB_EP2_SIZE
|
||||
#define USB_EP2_SIZE 8
|
||||
#endif
|
||||
#ifndef USB_EP3_SIZE
|
||||
#define USB_EP3_SIZE 8
|
||||
#endif
|
||||
#ifndef USB_EP4_SIZE
|
||||
#define USB_EP4_SIZE 0
|
||||
#endif
|
||||
#ifndef USB_EP5_SIZE
|
||||
#define USB_EP5_SIZE 0
|
||||
#endif
|
||||
#ifndef USB_EP6_SIZE
|
||||
#define USB_EP6_SIZE 0
|
||||
#endif
|
||||
#ifndef USB_EP7_SIZE
|
||||
#define USB_EP7_SIZE 0
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef MAX_CTRL_DATA
|
||||
#define MAX_CTRL_DATA 128
|
||||
#endif
|
||||
|
||||
void usb_arch_setup(void);
|
||||
|
||||
void usb_arch_setup_control_endpoint(uint8_t addr);
|
||||
|
||||
void usb_arch_setup_bulk_endpoint(uint8_t addr);
|
||||
|
||||
void usb_arch_setup_interrupt_endpoint(uint8_t addr);
|
||||
|
||||
void usb_arch_disable_endpoint(uint8_t addr);
|
||||
|
||||
void usb_arch_discard_all_buffers(uint8_t addr);
|
||||
|
||||
/* Stall a control endpoint. The stall will be cleared when the next
|
||||
* SETUP token arrives. */
|
||||
void usb_arch_control_stall(uint8_t addr);
|
||||
|
||||
/* Set or remove a HALT condition on an endpoint */
|
||||
void usb_arch_halt_endpoint(uint8_t addr, int halt);
|
||||
|
||||
void usb_arch_set_configuration(uint8_t usb_configuration_value);
|
||||
|
||||
uint16_t usb_arch_get_ep_status(uint8_t addr);
|
||||
|
||||
void usb_arch_set_address(uint8_t addr);
|
||||
|
||||
/* Select what process should be polled when a global event occurs. Intended for the protocol handler. Applications should use usb_set_global_event_process */
|
||||
void usb_arch_set_global_event_process(struct process *p);
|
||||
|
||||
unsigned int usb_arch_get_global_events(void);
|
||||
|
||||
/* Return true if not all data has been sent to the host */
|
||||
int usb_arch_send_pending(uint8_t ep_addr);
|
||||
|
||||
#endif /* __USB_ARCH_H__0Z52ZDP0H6__ */
|
632
cpu/cc253x/usb/common/usb-core.c
Normal file
632
cpu/cc253x/usb/common/usb-core.c
Normal file
|
@ -0,0 +1,632 @@
|
|||
#include "usb-core.h"
|
||||
#include "usb.h"
|
||||
#include "usb-arch.h"
|
||||
#include "usb-api.h"
|
||||
#include "sys/process.h"
|
||||
#include "descriptors.h"
|
||||
#include "string-descriptors.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define DEBUG
|
||||
#ifdef DEBUG
|
||||
#define PRINTF(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define PRINTF(...)
|
||||
#endif
|
||||
|
||||
|
||||
struct USB_request_st usb_setup_buffer;
|
||||
static USBBuffer ctrl_buffer;
|
||||
|
||||
#define SETUP_ID 1
|
||||
#define OUT_ID 2
|
||||
#define IN_ID 3
|
||||
#define STATUS_OUT_ID 4
|
||||
#define STATUS_IN_ID 5
|
||||
|
||||
static uint16_t usb_device_status;
|
||||
static uint8_t usb_configuration_value;
|
||||
|
||||
static struct USBRequestHandlerHook *usb_request_handler_hooks = NULL;
|
||||
|
||||
static const unsigned char zero_byte = 0;
|
||||
static const unsigned short zero_word = 0;
|
||||
|
||||
static unsigned char usb_flags = 0;
|
||||
#define USB_FLAG_ADDRESS_PENDING 0x01
|
||||
|
||||
static struct process *global_user_event_pocess = NULL;
|
||||
static unsigned int global_user_events = 0;
|
||||
|
||||
void
|
||||
usb_set_global_event_process(struct process *p)
|
||||
{
|
||||
global_user_event_pocess = p;
|
||||
}
|
||||
unsigned int
|
||||
usb_get_global_events(void)
|
||||
{
|
||||
unsigned int e = global_user_events;
|
||||
global_user_events = 0;
|
||||
return e;
|
||||
}
|
||||
|
||||
static void
|
||||
notify_user(unsigned int e)
|
||||
{
|
||||
global_user_events |= e;
|
||||
if(global_user_event_pocess) {
|
||||
process_poll(global_user_event_pocess);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usb_send_ctrl_response(const uint8_t * data, unsigned int len)
|
||||
{
|
||||
if(ctrl_buffer.flags & USB_BUFFER_SUBMITTED)
|
||||
return;
|
||||
if(len >= usb_setup_buffer.wLength) {
|
||||
len = usb_setup_buffer.wLength; /* Truncate if too long */
|
||||
}
|
||||
ctrl_buffer.flags = USB_BUFFER_NOTIFY | USB_BUFFER_IN;
|
||||
if(len < usb_setup_buffer.wLength) {
|
||||
ctrl_buffer.flags |= USB_BUFFER_SHORT_END;
|
||||
}
|
||||
ctrl_buffer.next = NULL;
|
||||
ctrl_buffer.data = (uint8_t *) data;
|
||||
ctrl_buffer.left = len;
|
||||
ctrl_buffer.id = IN_ID;
|
||||
usb_submit_xmit_buffer(0, &ctrl_buffer);
|
||||
}
|
||||
|
||||
static uint8_t error_stall = 0;
|
||||
|
||||
void
|
||||
usb_error_stall()
|
||||
{
|
||||
error_stall = 1;
|
||||
usb_arch_control_stall(0);
|
||||
}
|
||||
|
||||
void
|
||||
usb_send_ctrl_status()
|
||||
{
|
||||
if(ctrl_buffer.flags & USB_BUFFER_SUBMITTED)
|
||||
return;
|
||||
ctrl_buffer.flags = USB_BUFFER_NOTIFY | USB_BUFFER_IN;
|
||||
ctrl_buffer.next = NULL;
|
||||
ctrl_buffer.data = NULL;
|
||||
ctrl_buffer.left = 0;
|
||||
ctrl_buffer.id = STATUS_IN_ID;
|
||||
usb_submit_xmit_buffer(0, &ctrl_buffer);
|
||||
}
|
||||
|
||||
static usb_ctrl_data_callback data_callback = NULL;
|
||||
|
||||
static uint8_t *ctrl_data = NULL;
|
||||
|
||||
static unsigned int ctrl_data_len = 0;
|
||||
|
||||
void
|
||||
usb_get_ctrl_data(uint8_t * data, unsigned int length,
|
||||
usb_ctrl_data_callback cb)
|
||||
{
|
||||
if(ctrl_buffer.flags & USB_BUFFER_SUBMITTED)
|
||||
return;
|
||||
PRINTF("usb_get_ctrl_data: %d\n", length);
|
||||
data_callback = cb;
|
||||
ctrl_data = data;
|
||||
ctrl_data_len = length;
|
||||
ctrl_buffer.flags = USB_BUFFER_NOTIFY;
|
||||
ctrl_buffer.next = NULL;
|
||||
ctrl_buffer.data = data;
|
||||
ctrl_buffer.left = length;
|
||||
ctrl_buffer.id = OUT_ID;
|
||||
usb_submit_recv_buffer(0, &ctrl_buffer);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
void
|
||||
usb_set_user_process(struct process *p)
|
||||
{
|
||||
user_process = p;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
get_device_descriptor()
|
||||
{
|
||||
usb_send_ctrl_response((unsigned char *)&device_descriptor,
|
||||
sizeof(device_descriptor));
|
||||
}
|
||||
|
||||
static void
|
||||
get_string_descriptor()
|
||||
{
|
||||
#if OLD_STRING_DESCR
|
||||
if(LOW_BYTE(usb_setup_buffer.wValue) == 0) {
|
||||
usb_send_ctrl_response((const unsigned char *)string_languages->
|
||||
lang_descr, string_languages->lang_descr->bLength);
|
||||
} else {
|
||||
const struct usb_st_string_descriptor *descriptor;
|
||||
|
||||
unsigned char l;
|
||||
|
||||
const struct usb_st_string_descriptor *const *table;
|
||||
|
||||
const struct usb_st_string_language_map *map;
|
||||
|
||||
if(LOW_BYTE(usb_setup_buffer.wValue) > string_languages->max_index) {
|
||||
usb_error_stall();
|
||||
return;
|
||||
}
|
||||
l = string_languages->num_lang;
|
||||
map = string_languages->map;
|
||||
table = map->descriptors; /* Use first table if language not found */
|
||||
while(l > 0) {
|
||||
if(map->lang_id == usb_setup_buffer.wIndex) {
|
||||
table = map->descriptors;
|
||||
break;
|
||||
}
|
||||
map++;
|
||||
l--;
|
||||
}
|
||||
PRINTF("Lang id %04x = table %p\n", usb_setup_buffer.wIndex,
|
||||
(void *)table);
|
||||
descriptor = table[LOW_BYTE(usb_setup_buffer.wValue) - 1];
|
||||
usb_send_ctrl_response((const unsigned char *)descriptor,
|
||||
descriptor->bLength);
|
||||
}
|
||||
#else
|
||||
const struct usb_st_string_descriptor *descriptor;
|
||||
|
||||
descriptor = (struct usb_st_string_descriptor *)
|
||||
usb_class_get_string_descriptor(usb_setup_buffer.wIndex,
|
||||
LOW_BYTE(usb_setup_buffer.wValue));
|
||||
if(!descriptor) {
|
||||
usb_error_stall();
|
||||
return;
|
||||
}
|
||||
usb_send_ctrl_response((const unsigned char *)descriptor,
|
||||
descriptor->bLength);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
get_configuration_descriptor()
|
||||
{
|
||||
usb_send_ctrl_response((unsigned char *)configuration_head,
|
||||
configuration_head->wTotalLength);
|
||||
}
|
||||
|
||||
static void
|
||||
get_configuration()
|
||||
{
|
||||
usb_send_ctrl_response((unsigned char *)&usb_configuration_value,
|
||||
sizeof(usb_configuration_value));
|
||||
}
|
||||
|
||||
/* Returns true if the configuration value changed */
|
||||
static int
|
||||
set_configuration()
|
||||
{
|
||||
notify_user(USB_EVENT_CONFIG);
|
||||
if(usb_configuration_value != LOW_BYTE(usb_setup_buffer.wValue)) {
|
||||
usb_configuration_value = LOW_BYTE(usb_setup_buffer.wValue);
|
||||
usb_arch_set_configuration(usb_configuration_value);
|
||||
usb_send_ctrl_status();
|
||||
return 1;
|
||||
} else {
|
||||
usb_send_ctrl_status();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_device_status()
|
||||
{
|
||||
PRINTF("get_device_status\n");
|
||||
usb_send_ctrl_response((const unsigned char *)&usb_device_status,
|
||||
sizeof(usb_device_status));
|
||||
}
|
||||
|
||||
static void
|
||||
get_endpoint_status()
|
||||
{
|
||||
static uint16_t status;
|
||||
|
||||
PRINTF("get_endpoint_status\n");
|
||||
if((usb_setup_buffer.wIndex & 0x7f) == 0) {
|
||||
usb_send_ctrl_response((const unsigned char *)&zero_word,
|
||||
sizeof(zero_word));
|
||||
} else {
|
||||
status = usb_arch_get_ep_status(usb_setup_buffer.wIndex);
|
||||
usb_send_ctrl_response((uint8_t *) & status, sizeof(status));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_interface_status()
|
||||
{
|
||||
PRINTF("get_interface_status\n");
|
||||
usb_send_ctrl_response((const unsigned char *)&zero_word,
|
||||
sizeof(zero_word));
|
||||
}
|
||||
|
||||
static void
|
||||
get_interface()
|
||||
{
|
||||
PRINTF("get_interface\n");
|
||||
if(usb_configuration_value == 0)
|
||||
usb_error_stall();
|
||||
else {
|
||||
usb_send_ctrl_response(&zero_byte, sizeof(zero_byte));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static unsigned int
|
||||
handle_standard_requests()
|
||||
{
|
||||
switch (usb_setup_buffer.bmRequestType) {
|
||||
case 0x80: /* standard device IN requests */
|
||||
switch (usb_setup_buffer.bRequest) {
|
||||
case GET_DESCRIPTOR:
|
||||
switch (HIGH_BYTE(usb_setup_buffer.wValue)) {
|
||||
case DEVICE:
|
||||
get_device_descriptor();
|
||||
break;
|
||||
case CONFIGURATION:
|
||||
get_configuration_descriptor();
|
||||
break;
|
||||
case STRING:
|
||||
get_string_descriptor();
|
||||
break;
|
||||
default:
|
||||
/* Unknown descriptor */
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case GET_CONFIGURATION:
|
||||
get_configuration();
|
||||
break;
|
||||
case GET_STATUS:
|
||||
get_device_status();
|
||||
break;
|
||||
case GET_INTERFACE:
|
||||
get_interface();
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 0x81: /* standard interface IN requests */
|
||||
switch (usb_setup_buffer.bRequest) {
|
||||
case GET_STATUS:
|
||||
get_interface_status();
|
||||
break;
|
||||
#ifdef HID_ENABLED
|
||||
case GET_DESCRIPTOR:
|
||||
switch (USB_setup_buffer.wValue.byte.high) {
|
||||
case REPORT:
|
||||
get_report_descriptor();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 0x82: /* standard endpoint IN requests */
|
||||
switch (usb_setup_buffer.bRequest) {
|
||||
case GET_STATUS:
|
||||
get_endpoint_status();
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 0x00: /* standard device OUT requests */
|
||||
switch (usb_setup_buffer.bRequest) {
|
||||
case SET_ADDRESS:
|
||||
PRINTF("Address: %d\n", LOW_BYTE(usb_setup_buffer.wValue));
|
||||
usb_flags |= USB_FLAG_ADDRESS_PENDING;
|
||||
/* The actual setting of the address is done when the status packet
|
||||
is sent. */
|
||||
usb_send_ctrl_status();
|
||||
break;
|
||||
#if SETABLE_STRING_DESCRIPTORS > 0
|
||||
case SET_DESCRIPTOR:
|
||||
if(usb_setup_buffer.wValue.byte.high == STRING) {
|
||||
set_string_descriptor();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case SET_CONFIGURATION:
|
||||
if(set_configuration()) {
|
||||
#if 0
|
||||
config_msg.data.config = LOW_BYTE(usb_setup_buffer.wValue);
|
||||
notify_user(&config_msg);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 0x01: /* standard interface OUT requests */
|
||||
switch (usb_setup_buffer.bRequest) {
|
||||
case SET_INTERFACE:
|
||||
/* Change interface here if we support more than one */
|
||||
usb_send_ctrl_status();
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 0x02: /* standard endpoint OUT requests */
|
||||
switch (usb_setup_buffer.bRequest) {
|
||||
case SET_FEATURE:
|
||||
case CLEAR_FEATURE:
|
||||
if(usb_setup_buffer.wValue == ENDPOINT_HALT_FEATURE) {
|
||||
usb_arch_halt_endpoint(usb_setup_buffer.wIndex,
|
||||
usb_setup_buffer.bRequest == SET_FEATURE);
|
||||
usb_send_ctrl_status();
|
||||
} else {
|
||||
usb_error_stall();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
#ifdef HID_ENABLED
|
||||
case 0xa1: /* class specific interface IN request */
|
||||
switch (USB_setup_buffer.bRequest) {
|
||||
case GET_HID_REPORT:
|
||||
PRINTF("Get report\n");
|
||||
send_ctrl_response((code u_int8_t *) & zero_byte, sizeof(zero_byte));
|
||||
break;
|
||||
case GET_HID_IDLE:
|
||||
PRINTF("Get idle\n");
|
||||
send_ctrl_response((code u_int8_t *) & zero_byte, sizeof(zero_byte));
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 0x21: /* class specific interface OUT request */
|
||||
switch (USB_setup_buffer.bRequest) {
|
||||
case SET_HID_IDLE:
|
||||
PRINTF("Set idle\n");
|
||||
send_ctrl_status();
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct USBRequestHandler standard_request_handler = {
|
||||
0x00,
|
||||
0x60,
|
||||
0x00,
|
||||
0x00,
|
||||
handle_standard_requests
|
||||
};
|
||||
|
||||
static struct USBRequestHandlerHook standard_request_hook = {
|
||||
NULL,
|
||||
&standard_request_handler
|
||||
};
|
||||
|
||||
static void
|
||||
submit_setup(void)
|
||||
{
|
||||
ctrl_buffer.next = NULL;
|
||||
ctrl_buffer.data = (uint8_t *) & usb_setup_buffer;
|
||||
ctrl_buffer.left = sizeof(usb_setup_buffer);
|
||||
ctrl_buffer.flags = (USB_BUFFER_PACKET_END | USB_BUFFER_SETUP
|
||||
| USB_BUFFER_NOTIFY);
|
||||
ctrl_buffer.id = SETUP_ID;
|
||||
usb_submit_recv_buffer(0, &ctrl_buffer);
|
||||
}
|
||||
|
||||
PROCESS(usb_process, "USB");
|
||||
|
||||
PROCESS_THREAD(usb_process, ev, data)
|
||||
{
|
||||
PROCESS_BEGIN();
|
||||
PRINTF("USB process started\n");
|
||||
while(1) {
|
||||
PROCESS_WAIT_EVENT();
|
||||
if(ev == PROCESS_EVENT_EXIT)
|
||||
break;
|
||||
if(ev == PROCESS_EVENT_POLL) {
|
||||
unsigned int events = usb_arch_get_global_events();
|
||||
|
||||
if(events) {
|
||||
if(events & USB_EVENT_RESET) {
|
||||
submit_setup();
|
||||
usb_configuration_value = 0;
|
||||
notify_user(USB_EVENT_RESET);
|
||||
}
|
||||
if(events & USB_EVENT_SUSPEND) {
|
||||
notify_user(USB_EVENT_SUSPEND);
|
||||
}
|
||||
if(events & USB_EVENT_RESUME) {
|
||||
notify_user(USB_EVENT_RESUME);
|
||||
}
|
||||
|
||||
}
|
||||
events = usb_get_ep_events(0);
|
||||
if(events) {
|
||||
if((events & USB_EP_EVENT_NOTIFICATION)
|
||||
&& !(ctrl_buffer.flags & USB_BUFFER_SUBMITTED)) {
|
||||
/* PRINTF("Endpoint 0\n"); */
|
||||
if(ctrl_buffer.flags & USB_BUFFER_FAILED) {
|
||||
/* Something went wrong with the buffer, just wait for a
|
||||
new SETUP packet */
|
||||
PRINTF("Discarded\n");
|
||||
submit_setup();
|
||||
} else if(ctrl_buffer.flags & USB_BUFFER_SETUP) {
|
||||
struct USBRequestHandlerHook *hook = usb_request_handler_hooks;
|
||||
|
||||
PRINTF("Setup\n");
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for(i = 0; i < 8; i++)
|
||||
PRINTF(" %02x", ((unsigned char *)&usb_setup_buffer)[i]);
|
||||
PRINTF("\n");
|
||||
}
|
||||
|
||||
while(hook) {
|
||||
const struct USBRequestHandler *handler = hook->handler;
|
||||
|
||||
/* Check if the handler matches the request */
|
||||
if(((handler->request_type ^ usb_setup_buffer.bmRequestType)
|
||||
& handler->request_type_mask) == 0
|
||||
&& ((handler->request ^ usb_setup_buffer.bRequest)
|
||||
& handler->request_mask) == 0) {
|
||||
if(handler->handler_func())
|
||||
break;
|
||||
}
|
||||
hook = hook->next;
|
||||
}
|
||||
if(!hook) {
|
||||
/* No handler found */
|
||||
usb_error_stall();
|
||||
PRINTF("Unhandled setup: %02x %02x %04x %04x %04x\n",
|
||||
usb_setup_buffer.bmRequestType,
|
||||
usb_setup_buffer.bRequest, usb_setup_buffer.wValue,
|
||||
usb_setup_buffer.wIndex, usb_setup_buffer.wLength);
|
||||
}
|
||||
/* Check if any handler stalled the pipe, if so prepare for
|
||||
next setup */
|
||||
if(error_stall) {
|
||||
error_stall = 0;
|
||||
submit_setup();
|
||||
}
|
||||
} else {
|
||||
if(ctrl_buffer.id == IN_ID) {
|
||||
/* Receive status stage */
|
||||
PRINTF("Status OUT\n");
|
||||
ctrl_buffer.flags = USB_BUFFER_NOTIFY;
|
||||
ctrl_buffer.next = NULL;
|
||||
ctrl_buffer.data = NULL;
|
||||
ctrl_buffer.left = 0;
|
||||
ctrl_buffer.id = STATUS_OUT_ID;
|
||||
usb_submit_recv_buffer(0, &ctrl_buffer);
|
||||
} else if(ctrl_buffer.id == STATUS_OUT_ID) {
|
||||
PRINTF("Status OUT done\n");
|
||||
submit_setup();
|
||||
} else if(ctrl_buffer.id == STATUS_IN_ID) {
|
||||
PRINTF("Status IN done\n");
|
||||
if(usb_flags & USB_FLAG_ADDRESS_PENDING) {
|
||||
while(usb_send_pending(0));
|
||||
usb_arch_set_address(LOW_BYTE(usb_setup_buffer.wValue));
|
||||
usb_flags &= ~USB_FLAG_ADDRESS_PENDING;
|
||||
}
|
||||
submit_setup();
|
||||
} else if(ctrl_buffer.id == OUT_ID) {
|
||||
PRINTF("OUT\n");
|
||||
if(data_callback) {
|
||||
data_callback(ctrl_data, ctrl_data_len - ctrl_buffer.left);
|
||||
} else {
|
||||
usb_send_ctrl_status();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PROCESS_END();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
usb_setup(void)
|
||||
{
|
||||
usb_arch_setup();
|
||||
process_start(&usb_process, NULL);
|
||||
usb_arch_set_global_event_process(&usb_process);
|
||||
usb_set_ep_event_process(0, &usb_process);
|
||||
|
||||
usb_register_request_handler(&standard_request_hook);
|
||||
}
|
||||
|
||||
void
|
||||
usb_register_request_handler(struct USBRequestHandlerHook *hook)
|
||||
{
|
||||
struct USBRequestHandlerHook **prevp = &usb_request_handler_hooks;
|
||||
/* Find last hook */
|
||||
while(*prevp) {
|
||||
prevp = &(*prevp)->next;
|
||||
}
|
||||
/* Add last */
|
||||
*prevp = hook;
|
||||
hook->next = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
usb_prepend_request_handler(struct USBRequestHandlerHook *hook)
|
||||
{
|
||||
hook->next = usb_request_handler_hooks;
|
||||
usb_request_handler_hooks = hook;
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
usb_get_current_configuration(void)
|
||||
{
|
||||
return usb_configuration_value;
|
||||
}
|
||||
|
||||
void
|
||||
usb_setup_bulk_endpoint(unsigned char addr)
|
||||
{
|
||||
usb_arch_setup_bulk_endpoint(addr);
|
||||
}
|
||||
|
||||
void
|
||||
usb_setup_interrupt_endpoint(unsigned char addr)
|
||||
{
|
||||
usb_arch_setup_interrupt_endpoint(addr);
|
||||
}
|
||||
|
||||
void
|
||||
usb_disable_endpoint(uint8_t addr)
|
||||
{
|
||||
usb_arch_discard_all_buffers(addr);
|
||||
usb_arch_disable_endpoint(addr);
|
||||
}
|
||||
|
||||
void
|
||||
usb_discard_all_buffers(uint8_t addr)
|
||||
{
|
||||
usb_arch_discard_all_buffers(addr);
|
||||
}
|
||||
|
||||
void
|
||||
usb_halt_endpoint(uint8_t addr, int halt)
|
||||
{
|
||||
usb_arch_halt_endpoint(addr, halt);
|
||||
}
|
||||
|
||||
int
|
||||
usb_send_pending(uint8_t addr)
|
||||
{
|
||||
return usb_arch_send_pending(addr);
|
||||
}
|
19
cpu/cc253x/usb/common/usb-core.h
Normal file
19
cpu/cc253x/usb/common/usb-core.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
#ifndef __USB_CORE_H__YIKJDA7S1X__
|
||||
#define __USB_CORE_H__YIKJDA7S1X__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern struct USB_request_st usb_setup_buffer;
|
||||
|
||||
void usb_send_ctrl_response(const uint8_t *data, unsigned int len);
|
||||
|
||||
void usb_error_stall();
|
||||
|
||||
void usb_send_ctrl_status();
|
||||
|
||||
typedef void (*usb_ctrl_data_callback)(uint8_t *data, unsigned int length);
|
||||
|
||||
void usb_get_ctrl_data(uint8_t *data, unsigned int length,
|
||||
usb_ctrl_data_callback cb);
|
||||
|
||||
#endif /* __USB_CORE_H__YIKJDA7S1X__ */
|
185
cpu/cc253x/usb/common/usb.h
Normal file
185
cpu/cc253x/usb/common/usb.h
Normal file
|
@ -0,0 +1,185 @@
|
|||
#ifndef __USB_H__6PFTDPIMZM__
|
||||
#define __USB_H__6PFTDPIMZM__
|
||||
#include <stdint.h>
|
||||
|
||||
/* Adapted from usb_kbd_enum.h in c5131-usb-kbd-light-1_0_2 package from
|
||||
Atmel */
|
||||
|
||||
/* These definitions assume a little endian architecture */
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define BYTE_ALIGNED __attribute__ ((__packed__))
|
||||
#else
|
||||
#define BYTE_ALIGNED
|
||||
#endif
|
||||
|
||||
#define LOW_BYTE(x) ((unsigned char)x)
|
||||
#define HIGH_BYTE(x) ((unsigned char)(x>>8))
|
||||
|
||||
typedef uint8_t Uchar;
|
||||
typedef uint16_t Uint16;
|
||||
typedef uint32_t Uint32;
|
||||
|
||||
/*_____ S T A N D A R D R E Q U E S T S __________________________________*/
|
||||
|
||||
#define GET_STATUS 0x00
|
||||
#define GET_DEVICE 0x01
|
||||
#define CLEAR_FEATURE 0x01 /* see FEATURES below */
|
||||
#define GET_STRING 0x03
|
||||
#define SET_FEATURE 0x03 /* see FEATURES below */
|
||||
#define SET_ADDRESS 0x05
|
||||
#define GET_DESCRIPTOR 0x06
|
||||
#define SET_DESCRIPTOR 0x07
|
||||
#define GET_CONFIGURATION 0x08
|
||||
#define SET_CONFIGURATION 0x09
|
||||
#define GET_INTERFACE 0x0A
|
||||
#define SET_INTERFACE 0x0B
|
||||
#define SYNCH_FRAME 0x0C
|
||||
|
||||
#define GET_DEVICE_DESCRIPTOR 1
|
||||
#define GET_CONFIGURATION_DESCRIPTOR 4
|
||||
|
||||
#define REQUEST_DEVICE_STATUS 0x80
|
||||
#define REQUEST_INTERFACE_STATUS 0x81
|
||||
#define REQUEST_ENDPOINT_STATUS 0x82
|
||||
#define ZERO_TYPE 0x00
|
||||
#define INTERFACE_TYPE 0x01
|
||||
#define ENDPOINT_TYPE 0x02
|
||||
|
||||
/*_____ D E S C R I P T O R T Y P E S ____________________________________*/
|
||||
|
||||
#define DEVICE 0x01
|
||||
#define CONFIGURATION 0x02
|
||||
#define STRING 0x03
|
||||
#define INTERFACE 0x04
|
||||
#define ENDPOINT 0x05
|
||||
|
||||
/* HID specific */
|
||||
#define HID 0x21
|
||||
#define REPORT 0x22
|
||||
/* *** */
|
||||
|
||||
/*_____ S T A N D A R D F E A T U R E S __________________________________*/
|
||||
|
||||
#define DEVICE_REMOTE_WAKEUP_FEATURE 0x01
|
||||
#define ENDPOINT_HALT_FEATURE 0x00
|
||||
|
||||
/*_____ D E V I C E S T A T U S ___________________________________________*/
|
||||
|
||||
#define SELF_POWERED 1
|
||||
|
||||
/*_____ D E V I C E S T A T E _____________________________________________*/
|
||||
|
||||
#define ATTACHED 0
|
||||
#define POWERED 1
|
||||
#define DEFAULT 2
|
||||
#define ADDRESSED 3
|
||||
#define CONFIGURED 4
|
||||
#define SUSPENDED 5
|
||||
|
||||
#define USB_CONFIG_BUSPOWERED 0x80
|
||||
#define USB_CONFIG_SELFPOWERED 0x40
|
||||
#define USB_CONFIG_REMOTEWAKEUP 0x20
|
||||
|
||||
/* Class specific */
|
||||
#define CS_INTERFACE 0x24
|
||||
#define CS_ENDPOINT 0x25
|
||||
|
||||
/*_________________________________________________________ S T R U C T _____*/
|
||||
/*_____ U S B D E V I C E R E Q U E S T _________________________________*/
|
||||
|
||||
struct USB_request_st
|
||||
{
|
||||
Uchar bmRequestType; /* Characteristics of the request */
|
||||
Uchar bRequest; /* Specific request */
|
||||
Uint16 wValue;
|
||||
Uint16 wIndex; /* field that varies according to request */
|
||||
Uint16 wLength; /* Number of bytes to transfer if Data */
|
||||
};
|
||||
|
||||
|
||||
/*_____ U S B D E V I C E D E S C R I P T O R ___________________________*/
|
||||
|
||||
struct usb_st_device_descriptor
|
||||
{
|
||||
Uchar bLength; /* Size of this descriptor in bytes */
|
||||
Uchar bDescriptorType; /* DEVICE descriptor type */
|
||||
Uint16 bscUSB; /* Binay Coded Decimal Spec. release */
|
||||
Uchar bDeviceClass; /* Class code assigned by the USB */
|
||||
Uchar bDeviceSubClass; /* Sub-class code assigned by the USB */
|
||||
Uchar bDeviceProtocol; /* Protocol code assigned by the USB */
|
||||
Uchar bMaxPacketSize0; /* Max packet size for EP0 */
|
||||
Uint16 idVendor; /* Vendor ID. ATMEL = 0x03EB */
|
||||
Uint16 idProduct; /* Product ID assigned by the manufacturer */
|
||||
Uint16 bcdDevice; /* Device release number */
|
||||
Uchar iManufacturer; /* Index of manu. string descriptor */
|
||||
Uchar iProduct; /* Index of prod. string descriptor */
|
||||
Uchar iSerialNumber; /* Index of S.N. string descriptor */
|
||||
Uchar bNumConfigurations; /* Number of possible configurations */
|
||||
} BYTE_ALIGNED;
|
||||
|
||||
|
||||
/*_____ U S B C O N F I G U R A T I O N D E S C R I P T O R _____________*/
|
||||
|
||||
struct usb_st_configuration_descriptor
|
||||
{
|
||||
Uchar bLength; /* size of this descriptor in bytes */
|
||||
Uchar bDescriptorType; /* CONFIGURATION descriptor type */
|
||||
Uint16 wTotalLength; /* total length of data returned */
|
||||
Uchar bNumInterfaces; /* number of interfaces for this conf. */
|
||||
Uchar bConfigurationValue; /* value for SetConfiguration resquest */
|
||||
Uchar iConfiguration; /* index of string descriptor */
|
||||
Uchar bmAttibutes; /* Configuration characteristics */
|
||||
Uchar MaxPower; /* maximum power consumption */
|
||||
} BYTE_ALIGNED;
|
||||
|
||||
|
||||
/*_____ U S B I N T E R F A C E D E S C R I P T O R _____________________*/
|
||||
|
||||
struct usb_st_interface_descriptor
|
||||
{
|
||||
Uchar bLength; /* size of this descriptor in bytes */
|
||||
Uchar bDescriptorType; /* INTERFACE descriptor type */
|
||||
Uchar bInterfaceNumber; /* Number of interface */
|
||||
Uchar bAlternateSetting; /* value to select alternate setting */
|
||||
Uchar bNumEndpoints; /* Number of EP except EP 0 */
|
||||
Uchar bInterfaceClass; /* Class code assigned by the USB */
|
||||
Uchar bInterfaceSubClass; /* Sub-class code assigned by the USB */
|
||||
Uchar bInterfaceProtocol; /* Protocol code assigned by the USB */
|
||||
Uchar iInterface; /* Index of string descriptor */
|
||||
} BYTE_ALIGNED;
|
||||
|
||||
|
||||
/*_____ U S B E N D P O I N T D E S C R I P T O R _______________________*/
|
||||
|
||||
struct usb_st_endpoint_descriptor
|
||||
{
|
||||
Uchar bLength; /* Size of this descriptor in bytes */
|
||||
Uchar bDescriptorType; /* ENDPOINT descriptor type */
|
||||
Uchar bEndpointAddress; /* Address of the endpoint */
|
||||
Uchar bmAttributes; /* Endpoint's attributes */
|
||||
Uint16 wMaxPacketSize; /* Maximum packet size for this EP */
|
||||
Uchar bInterval; /* Interval for polling EP in ms */
|
||||
/* Uchar bRefresh; */
|
||||
/* Uchar bSynchAddress; */
|
||||
} BYTE_ALIGNED;
|
||||
|
||||
|
||||
/*_____ U S B S T R I N G D E S C R I P T O R _______________*/
|
||||
|
||||
struct usb_st_string_descriptor
|
||||
{
|
||||
Uchar bLength; /* size of this descriptor in bytes */
|
||||
Uchar bDescriptorType; /* STRING descriptor type */
|
||||
Uint16 wstring[1];/* unicode characters */
|
||||
} BYTE_ALIGNED;
|
||||
|
||||
|
||||
struct usb_st_language_descriptor
|
||||
{
|
||||
Uchar bLength; /* size of this descriptor in bytes */
|
||||
Uchar bDescriptorType; /* STRING descriptor type */
|
||||
Uint16 wlangid[1]; /* language id */
|
||||
} BYTE_ALIGNED;
|
||||
|
||||
#endif /* __USB_H__6PFTDPIMZM__ */
|
Loading…
Reference in a new issue