Add typed request return value that indicates request is OK or requires endpoint STALL.
Changed vendor request to a lookup table, instead of an ever-growing switch statement.
This commit is contained in:
@ -196,7 +196,7 @@ void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) {
|
||||
sgpio_cpld_stream_enable();
|
||||
}
|
||||
|
||||
bool usb_vendor_request_set_transceiver_mode(
|
||||
usb_request_status_t usb_vendor_request_set_transceiver_mode(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
@ -205,22 +205,22 @@ bool usb_vendor_request_set_transceiver_mode(
|
||||
case 1:
|
||||
set_transceiver_mode(TRANSCEIVER_MODE_RX);
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
return true;
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
|
||||
case 2:
|
||||
set_transceiver_mode(TRANSCEIVER_MODE_TX);
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
return true;
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
|
||||
default:
|
||||
return false;
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
bool usb_vendor_request_write_max2837(
|
||||
usb_request_status_t usb_vendor_request_write_max2837(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
@ -229,16 +229,16 @@ bool usb_vendor_request_write_max2837(
|
||||
if( endpoint->setup.value < 0x3ff ) {
|
||||
max2837_reg_write(endpoint->setup.index, endpoint->setup.value);
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
return true;
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else {
|
||||
return true;
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
bool usb_vendor_request_read_max2837(
|
||||
usb_request_status_t usb_vendor_request_read_max2837(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
@ -249,15 +249,15 @@ bool usb_vendor_request_read_max2837(
|
||||
endpoint->buffer[1] = value >> 8;
|
||||
usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 2);
|
||||
usb_endpoint_schedule_ack(endpoint->out);
|
||||
return true;
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return false;
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else {
|
||||
return true;
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
bool usb_vendor_request_write_si5351c(
|
||||
usb_request_status_t usb_vendor_request_write_si5351c(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
@ -266,16 +266,16 @@ bool usb_vendor_request_write_si5351c(
|
||||
if( endpoint->setup.value < 256 ) {
|
||||
si5351c_write_single(endpoint->setup.index, endpoint->setup.value);
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
return true;
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else {
|
||||
return true;
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
bool usb_vendor_request_read_si5351c(
|
||||
usb_request_status_t usb_vendor_request_read_si5351c(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
@ -285,15 +285,15 @@ bool usb_vendor_request_read_si5351c(
|
||||
endpoint->buffer[0] = value;
|
||||
usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 1);
|
||||
usb_endpoint_schedule_ack(endpoint->out);
|
||||
return true;
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return false;
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else {
|
||||
return true;
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
bool usb_vendor_request_set_sample_rate(
|
||||
usb_request_status_t usb_vendor_request_set_sample_rate(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
@ -301,15 +301,15 @@ bool usb_vendor_request_set_sample_rate(
|
||||
const uint32_t sample_rate = (endpoint->setup.index << 16) | endpoint->setup.value;
|
||||
if( sample_rate_set(sample_rate) ) {
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
return true;
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return false;
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else {
|
||||
return true;
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
bool usb_vendor_request_set_baseband_filter_bandwidth(
|
||||
usb_request_status_t usb_vendor_request_set_baseband_filter_bandwidth(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
@ -317,56 +317,42 @@ bool usb_vendor_request_set_baseband_filter_bandwidth(
|
||||
const uint32_t bandwidth = (endpoint->setup.index << 16) | endpoint->setup.value;
|
||||
if( baseband_filter_bandwidth_set(bandwidth) ) {
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
return true;
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return false;
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else {
|
||||
return true;
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
void usb_vendor_request(
|
||||
static const usb_request_handler_fn vendor_request_handler[] = {
|
||||
NULL,
|
||||
usb_vendor_request_set_transceiver_mode,
|
||||
usb_vendor_request_write_max2837,
|
||||
usb_vendor_request_read_max2837,
|
||||
usb_vendor_request_write_si5351c,
|
||||
usb_vendor_request_read_si5351c,
|
||||
usb_vendor_request_set_sample_rate,
|
||||
usb_vendor_request_set_baseband_filter_bandwidth,
|
||||
};
|
||||
|
||||
static const uint32_t vendor_request_handler_count =
|
||||
sizeof(vendor_request_handler) / sizeof(vendor_request_handler[0]);
|
||||
|
||||
usb_request_status_t usb_vendor_request(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
bool success = false;
|
||||
usb_request_status_t status = USB_REQUEST_STATUS_STALL;
|
||||
|
||||
switch(endpoint->setup.request) {
|
||||
case 1:
|
||||
success = usb_vendor_request_set_transceiver_mode(endpoint, stage);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
success = usb_vendor_request_write_max2837(endpoint, stage);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
success = usb_vendor_request_read_max2837(endpoint, stage);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
success = usb_vendor_request_write_si5351c(endpoint, stage);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
success = usb_vendor_request_read_si5351c(endpoint, stage);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
success = usb_vendor_request_set_sample_rate(endpoint, stage);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
success = usb_vendor_request_set_baseband_filter_bandwidth(endpoint, stage);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
if( endpoint->setup.request < vendor_request_handler_count ) {
|
||||
usb_request_handler_fn handler = vendor_request_handler[endpoint->setup.request];
|
||||
if( handler ) {
|
||||
status = handler(endpoint, stage);
|
||||
}
|
||||
}
|
||||
|
||||
if( success != true ) {
|
||||
usb_endpoint_stall(endpoint);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
const usb_request_handlers_t usb_request_handlers = {
|
||||
|
@ -28,6 +28,7 @@ static void usb_request(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
usb_request_status_t status = USB_REQUEST_STATUS_STALL;
|
||||
usb_request_handler_fn handler = 0;
|
||||
|
||||
switch( endpoint->setup.request_type & USB_SETUP_REQUEST_TYPE_mask ) {
|
||||
@ -49,8 +50,10 @@ static void usb_request(
|
||||
}
|
||||
|
||||
if( handler ) {
|
||||
handler(endpoint, stage);
|
||||
} else {
|
||||
status = handler(endpoint, stage);
|
||||
}
|
||||
|
||||
if( status != USB_REQUEST_STATUS_OK ) {
|
||||
// USB 2.0 section 9.2.7 "Request Error"
|
||||
usb_endpoint_stall(endpoint);
|
||||
}
|
||||
|
@ -37,7 +37,12 @@ typedef enum {
|
||||
USB_TRANSFER_STAGE_STATUS,
|
||||
} usb_transfer_stage_t;
|
||||
|
||||
typedef void (*usb_request_handler_fn)(
|
||||
typedef enum {
|
||||
USB_REQUEST_STATUS_OK = 0,
|
||||
USB_REQUEST_STATUS_STALL = 1,
|
||||
} usb_request_status_t;
|
||||
|
||||
typedef usb_request_status_t (*usb_request_handler_fn)(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
);
|
||||
|
@ -63,7 +63,7 @@ extern bool usb_set_configuration(
|
||||
const uint_fast8_t configuration_number
|
||||
);
|
||||
|
||||
static void usb_send_descriptor(
|
||||
static usb_request_status_t usb_send_descriptor(
|
||||
usb_endpoint_t* const endpoint,
|
||||
uint8_t* const descriptor_data
|
||||
) {
|
||||
@ -77,113 +77,110 @@ static void usb_send_descriptor(
|
||||
descriptor_data,
|
||||
(setup_length > descriptor_length) ? descriptor_length : setup_length
|
||||
);
|
||||
usb_endpoint_schedule_ack(endpoint->out);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
||||
static void usb_send_descriptor_string(
|
||||
static usb_request_status_t usb_send_descriptor_string(
|
||||
usb_endpoint_t* const endpoint
|
||||
) {
|
||||
uint_fast8_t index = endpoint->setup.value_l;
|
||||
for( uint_fast8_t i=0; usb_descriptor_strings[i] != 0; i++ ) {
|
||||
if( i == index ) {
|
||||
usb_send_descriptor(endpoint, usb_descriptor_strings[i]);
|
||||
return;
|
||||
return usb_send_descriptor(endpoint, usb_descriptor_strings[i]);
|
||||
}
|
||||
}
|
||||
|
||||
usb_endpoint_stall(endpoint);
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
}
|
||||
|
||||
static void usb_standard_request_get_descriptor_setup(
|
||||
static usb_request_status_t usb_standard_request_get_descriptor_setup(
|
||||
usb_endpoint_t* const endpoint
|
||||
) {
|
||||
switch( endpoint->setup.value_h ) {
|
||||
case USB_DESCRIPTOR_TYPE_DEVICE:
|
||||
usb_send_descriptor(endpoint, usb_descriptor_device);
|
||||
break;
|
||||
return usb_send_descriptor(endpoint, usb_descriptor_device);
|
||||
|
||||
case USB_DESCRIPTOR_TYPE_CONFIGURATION:
|
||||
// TODO: Duplicated code. Refactor.
|
||||
if( usb_speed(endpoint->device) == USB_SPEED_HIGH ) {
|
||||
usb_send_descriptor(endpoint, usb_descriptor_configuration_high_speed);
|
||||
return usb_send_descriptor(endpoint, usb_descriptor_configuration_high_speed);
|
||||
} else {
|
||||
usb_send_descriptor(endpoint, usb_descriptor_configuration_full_speed);
|
||||
return usb_send_descriptor(endpoint, usb_descriptor_configuration_full_speed);
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:
|
||||
usb_send_descriptor(endpoint, usb_descriptor_device_qualifier);
|
||||
break;
|
||||
return usb_send_descriptor(endpoint, usb_descriptor_device_qualifier);
|
||||
|
||||
case USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION:
|
||||
// TODO: Duplicated code. Refactor.
|
||||
if( usb_speed(endpoint->device) == USB_SPEED_HIGH ) {
|
||||
usb_send_descriptor(endpoint, usb_descriptor_configuration_full_speed);
|
||||
return usb_send_descriptor(endpoint, usb_descriptor_configuration_full_speed);
|
||||
} else {
|
||||
usb_send_descriptor(endpoint, usb_descriptor_configuration_high_speed);
|
||||
return usb_send_descriptor(endpoint, usb_descriptor_configuration_high_speed);
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_DESCRIPTOR_TYPE_STRING:
|
||||
usb_send_descriptor_string(endpoint);
|
||||
break;
|
||||
return usb_send_descriptor_string(endpoint);
|
||||
|
||||
case USB_DESCRIPTOR_TYPE_INTERFACE:
|
||||
case USB_DESCRIPTOR_TYPE_ENDPOINT:
|
||||
default:
|
||||
usb_endpoint_stall(endpoint);
|
||||
break;
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_standard_request_get_descriptor(
|
||||
static usb_request_status_t usb_standard_request_get_descriptor(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
switch( stage ) {
|
||||
case USB_TRANSFER_STAGE_SETUP:
|
||||
usb_standard_request_get_descriptor_setup(endpoint);
|
||||
usb_endpoint_schedule_ack(endpoint->out);
|
||||
break;
|
||||
return usb_standard_request_get_descriptor_setup(endpoint);
|
||||
|
||||
case USB_TRANSFER_STAGE_DATA:
|
||||
break;
|
||||
|
||||
case USB_TRANSFER_STAGE_STATUS:
|
||||
break;
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
|
||||
default:
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
static void usb_standard_request_set_address(
|
||||
static usb_request_status_t usb_standard_request_set_address_setup(
|
||||
usb_endpoint_t* const endpoint
|
||||
) {
|
||||
usb_set_address_deferred(endpoint->device, endpoint->setup.value_l);
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
||||
static usb_request_status_t usb_standard_request_set_address(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
switch( stage ) {
|
||||
case USB_TRANSFER_STAGE_SETUP:
|
||||
usb_set_address_deferred(endpoint->device, endpoint->setup.value_l);
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
break;
|
||||
return usb_standard_request_set_address_setup(endpoint);
|
||||
|
||||
case USB_TRANSFER_STAGE_DATA:
|
||||
break;
|
||||
|
||||
case USB_TRANSFER_STAGE_STATUS:
|
||||
/* NOTE: Not necessary to set address here, as DEVICEADR.USBADRA bit
|
||||
* will cause controller to automatically perform set address
|
||||
* operation on IN ACK.
|
||||
*/
|
||||
break;
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
|
||||
default:
|
||||
break;
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
static void usb_standard_request_set_configuration_setup(
|
||||
static usb_request_status_t usb_standard_request_set_configuration_setup(
|
||||
usb_endpoint_t* const endpoint
|
||||
) {
|
||||
const uint8_t usb_configuration = endpoint->setup.value_l;
|
||||
@ -193,32 +190,32 @@ static void usb_standard_request_set_configuration_setup(
|
||||
usb_set_address_immediate(endpoint->device, 0);
|
||||
}
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
} else {
|
||||
usb_endpoint_stall(endpoint);
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_standard_request_set_configuration(
|
||||
static usb_request_status_t usb_standard_request_set_configuration(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
switch( stage ) {
|
||||
case USB_TRANSFER_STAGE_SETUP:
|
||||
usb_standard_request_set_configuration_setup(endpoint);
|
||||
break;
|
||||
return usb_standard_request_set_configuration_setup(endpoint);
|
||||
|
||||
case USB_TRANSFER_STAGE_DATA:
|
||||
break;
|
||||
|
||||
case USB_TRANSFER_STAGE_STATUS:
|
||||
break;
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
|
||||
default:
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
static void usb_standard_request_get_configuration_setup(
|
||||
static usb_request_status_t usb_standard_request_get_configuration_setup(
|
||||
usb_endpoint_t* const endpoint
|
||||
) {
|
||||
if( endpoint->setup.length == 1 ) {
|
||||
@ -227,52 +224,50 @@ static void usb_standard_request_get_configuration_setup(
|
||||
endpoint->buffer[0] = endpoint->device->configuration->number;
|
||||
}
|
||||
usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 1);
|
||||
usb_endpoint_schedule_ack(endpoint->out);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
} else {
|
||||
usb_endpoint_stall(endpoint);
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_standard_request_get_configuration(
|
||||
static usb_request_status_t usb_standard_request_get_configuration(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
switch( stage ) {
|
||||
case USB_TRANSFER_STAGE_SETUP:
|
||||
usb_standard_request_get_configuration_setup(endpoint);
|
||||
usb_endpoint_schedule_ack(endpoint->out);
|
||||
break;
|
||||
return usb_standard_request_get_configuration_setup(endpoint);
|
||||
|
||||
case USB_TRANSFER_STAGE_DATA:
|
||||
break;
|
||||
|
||||
case USB_TRANSFER_STAGE_STATUS:
|
||||
break;
|
||||
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
|
||||
default:
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
void usb_standard_request(
|
||||
usb_request_status_t usb_standard_request(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
switch( endpoint->setup.request ) {
|
||||
case USB_STANDARD_REQUEST_GET_DESCRIPTOR:
|
||||
usb_standard_request_get_descriptor(endpoint, stage);
|
||||
break;
|
||||
return usb_standard_request_get_descriptor(endpoint, stage);
|
||||
|
||||
case USB_STANDARD_REQUEST_SET_ADDRESS:
|
||||
usb_standard_request_set_address(endpoint, stage);
|
||||
break;
|
||||
return usb_standard_request_set_address(endpoint, stage);
|
||||
|
||||
case USB_STANDARD_REQUEST_SET_CONFIGURATION:
|
||||
usb_standard_request_set_configuration(endpoint, stage);
|
||||
break;
|
||||
return usb_standard_request_set_configuration(endpoint, stage);
|
||||
|
||||
case USB_STANDARD_REQUEST_GET_CONFIGURATION:
|
||||
usb_standard_request_get_configuration(endpoint, stage);
|
||||
break;
|
||||
|
||||
return usb_standard_request_get_configuration(endpoint, stage);
|
||||
|
||||
default:
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "usb_type.h"
|
||||
#include "usb_request.h"
|
||||
|
||||
void usb_standard_request(
|
||||
usb_request_status_t usb_standard_request(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
);
|
||||
|
Reference in New Issue
Block a user