hackrf_usb: Port to use usb_queue
This commit is contained in:
@ -39,6 +39,7 @@
|
||||
|
||||
#include "usb.h"
|
||||
#include "usb_type.h"
|
||||
#include "usb_queue.h"
|
||||
#include "usb_request.h"
|
||||
#include "usb_descriptor.h"
|
||||
#include "usb_standard_request.h"
|
||||
@ -49,9 +50,6 @@ uint8_t* const usb_bulk_buffer = (uint8_t*)0x20004000;
|
||||
static volatile uint32_t usb_bulk_buffer_offset = 0;
|
||||
static const uint32_t usb_bulk_buffer_mask = 32768 - 1;
|
||||
|
||||
usb_transfer_descriptor_t usb_td_bulk[2] ATTR_ALIGNED(64);
|
||||
const uint_fast8_t usb_td_bulk_count = sizeof(usb_td_bulk) / sizeof(usb_td_bulk[0]);
|
||||
|
||||
/* TODO remove this big buffer and use streaming for CPLD */
|
||||
#define CPLD_XSVF_MAX_LEN (65536)
|
||||
uint8_t cpld_xsvf_buffer[CPLD_XSVF_MAX_LEN];
|
||||
@ -181,50 +179,6 @@ bool set_freq(uint32_t freq_mhz, uint32_t freq_hz)
|
||||
return success;
|
||||
}
|
||||
|
||||
static void usb_init_buffers_bulk() {
|
||||
usb_td_bulk[0].next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE;
|
||||
usb_td_bulk[0].total_bytes
|
||||
= USB_TD_DTD_TOKEN_TOTAL_BYTES(16384)
|
||||
| USB_TD_DTD_TOKEN_MULTO(0)
|
||||
;
|
||||
usb_td_bulk[0].buffer_pointer_page[0] = (uint32_t)&usb_bulk_buffer[0x0000];
|
||||
usb_td_bulk[0].buffer_pointer_page[1] = (uint32_t)&usb_bulk_buffer[0x1000];
|
||||
usb_td_bulk[0].buffer_pointer_page[2] = (uint32_t)&usb_bulk_buffer[0x2000];
|
||||
usb_td_bulk[0].buffer_pointer_page[3] = (uint32_t)&usb_bulk_buffer[0x3000];
|
||||
usb_td_bulk[0].buffer_pointer_page[4] = (uint32_t)&usb_bulk_buffer[0x4000];
|
||||
|
||||
usb_td_bulk[1].next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE;
|
||||
usb_td_bulk[1].total_bytes
|
||||
= USB_TD_DTD_TOKEN_TOTAL_BYTES(16384)
|
||||
| USB_TD_DTD_TOKEN_MULTO(0)
|
||||
;
|
||||
usb_td_bulk[1].buffer_pointer_page[0] = (uint32_t)&usb_bulk_buffer[0x4000];
|
||||
usb_td_bulk[1].buffer_pointer_page[1] = (uint32_t)&usb_bulk_buffer[0x5000];
|
||||
usb_td_bulk[1].buffer_pointer_page[2] = (uint32_t)&usb_bulk_buffer[0x6000];
|
||||
usb_td_bulk[1].buffer_pointer_page[3] = (uint32_t)&usb_bulk_buffer[0x7000];
|
||||
usb_td_bulk[1].buffer_pointer_page[4] = (uint32_t)&usb_bulk_buffer[0x8000];
|
||||
}
|
||||
|
||||
void usb_endpoint_schedule_no_int(
|
||||
const usb_endpoint_t* const endpoint,
|
||||
usb_transfer_descriptor_t* const td
|
||||
) {
|
||||
// Ensure that endpoint is ready to be primed.
|
||||
// It may have been flushed due to an aborted transaction.
|
||||
// TODO: This should be preceded by a flush?
|
||||
while( usb_endpoint_is_ready(endpoint) );
|
||||
|
||||
// Configure a transfer.
|
||||
td->total_bytes =
|
||||
USB_TD_DTD_TOKEN_TOTAL_BYTES(16384)
|
||||
/*| USB_TD_DTD_TOKEN_IOC*/
|
||||
| USB_TD_DTD_TOKEN_MULTO(0)
|
||||
| USB_TD_DTD_TOKEN_STATUS_ACTIVE
|
||||
;
|
||||
|
||||
usb_endpoint_prime(endpoint, td);
|
||||
}
|
||||
|
||||
usb_configuration_t usb_configuration_high_speed = {
|
||||
.number = 1,
|
||||
.speed = USB_SPEED_HIGH,
|
||||
@ -260,6 +214,7 @@ usb_endpoint_t usb_endpoint_control_out = {
|
||||
.setup_complete = usb_setup_complete,
|
||||
.transfer_complete = usb_control_out_complete,
|
||||
};
|
||||
USB_DEFINE_QUEUE(usb_endpoint_control_out, 4);
|
||||
|
||||
usb_endpoint_t usb_endpoint_control_in = {
|
||||
.address = 0x80,
|
||||
@ -269,6 +224,7 @@ usb_endpoint_t usb_endpoint_control_in = {
|
||||
.setup_complete = 0,
|
||||
.transfer_complete = usb_control_in_complete,
|
||||
};
|
||||
static USB_DEFINE_QUEUE(usb_endpoint_control_in, 4);
|
||||
|
||||
// NOTE: Endpoint number for IN and OUT are different. I wish I had some
|
||||
// evidence that having BULK IN and OUT on separate endpoint numbers was
|
||||
@ -280,8 +236,9 @@ usb_endpoint_t usb_endpoint_bulk_in = {
|
||||
.in = &usb_endpoint_bulk_in,
|
||||
.out = 0,
|
||||
.setup_complete = 0,
|
||||
.transfer_complete = 0,
|
||||
.transfer_complete = usb_queue_transfer_complete
|
||||
};
|
||||
static USB_DEFINE_QUEUE(usb_endpoint_bulk_in, 4);
|
||||
|
||||
usb_endpoint_t usb_endpoint_bulk_out = {
|
||||
.address = 0x02,
|
||||
@ -289,8 +246,9 @@ usb_endpoint_t usb_endpoint_bulk_out = {
|
||||
.in = 0,
|
||||
.out = &usb_endpoint_bulk_out,
|
||||
.setup_complete = 0,
|
||||
.transfer_complete = 0,
|
||||
.transfer_complete = usb_queue_transfer_complete
|
||||
};
|
||||
static USB_DEFINE_QUEUE(usb_endpoint_bulk_out, 4);
|
||||
|
||||
void baseband_streaming_disable() {
|
||||
sgpio_cpld_stream_disable();
|
||||
@ -306,8 +264,6 @@ void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) {
|
||||
|
||||
transceiver_mode = new_transceiver_mode;
|
||||
|
||||
usb_init_buffers_bulk();
|
||||
|
||||
if( transceiver_mode == TRANSCEIVER_MODE_RX ) {
|
||||
gpio_clear(PORT_LED1_3, PIN_LED3);
|
||||
gpio_set(PORT_LED1_3, PIN_LED2);
|
||||
@ -339,7 +295,7 @@ void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) {
|
||||
nvic_enable_irq(NVIC_SGPIO_IRQ);
|
||||
SGPIO_SET_EN_1 = (1 << SGPIO_SLICE_A);
|
||||
|
||||
sgpio_cpld_stream_enable();
|
||||
sgpio_cpld_stream_enable();
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_set_transceiver_mode(
|
||||
@ -352,7 +308,7 @@ usb_request_status_t usb_vendor_request_set_transceiver_mode(
|
||||
case TRANSCEIVER_MODE_RX:
|
||||
case TRANSCEIVER_MODE_TX:
|
||||
set_transceiver_mode(endpoint->setup.value);
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
default:
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
@ -370,7 +326,7 @@ usb_request_status_t usb_vendor_request_write_max2837(
|
||||
if( endpoint->setup.index < MAX2837_NUM_REGS ) {
|
||||
if( endpoint->setup.value < MAX2837_DATA_REGS_MAX_VALUE ) {
|
||||
max2837_reg_write(endpoint->setup.index, endpoint->setup.value);
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
@ -389,8 +345,9 @@ usb_request_status_t usb_vendor_request_read_max2837(
|
||||
const uint16_t value = max2837_reg_read(endpoint->setup.index);
|
||||
endpoint->buffer[0] = value & 0xff;
|
||||
endpoint->buffer[1] = value >> 8;
|
||||
usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 2);
|
||||
usb_endpoint_schedule_ack(endpoint->out);
|
||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 2,
|
||||
NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
@ -407,7 +364,7 @@ usb_request_status_t usb_vendor_request_write_si5351c(
|
||||
if( endpoint->setup.index < 256 ) {
|
||||
if( endpoint->setup.value < 256 ) {
|
||||
si5351c_write_single(endpoint->setup.index, endpoint->setup.value);
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
@ -425,8 +382,9 @@ usb_request_status_t usb_vendor_request_read_si5351c(
|
||||
if( endpoint->setup.index < 256 ) {
|
||||
const uint8_t value = si5351c_read_single(endpoint->setup.index);
|
||||
endpoint->buffer[0] = value;
|
||||
usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 1);
|
||||
usb_endpoint_schedule_ack(endpoint->out);
|
||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1,
|
||||
NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
@ -442,7 +400,7 @@ usb_request_status_t usb_vendor_request_set_baseband_filter_bandwidth(
|
||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||
const uint32_t bandwidth = (endpoint->setup.index << 16) | endpoint->setup.value;
|
||||
if( baseband_filter_bandwidth_set(bandwidth) ) {
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
@ -460,7 +418,7 @@ usb_request_status_t usb_vendor_request_write_rffc5071(
|
||||
if( endpoint->setup.index < RFFC5071_NUM_REGS )
|
||||
{
|
||||
rffc5071_reg_write(endpoint->setup.index, endpoint->setup.value);
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
@ -481,8 +439,9 @@ usb_request_status_t usb_vendor_request_read_rffc5071(
|
||||
value = rffc5071_reg_read(endpoint->setup.index);
|
||||
endpoint->buffer[0] = value & 0xff;
|
||||
endpoint->buffer[1] = value >> 8;
|
||||
usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 2);
|
||||
usb_endpoint_schedule_ack(endpoint->out);
|
||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 2,
|
||||
NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
@ -500,7 +459,7 @@ usb_request_status_t usb_vendor_request_erase_spiflash(
|
||||
w25q80bv_setup();
|
||||
/* only chip erase is implemented */
|
||||
w25q80bv_chip_erase();
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
//FIXME probably should undo w25q80bv_setup()
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
@ -521,7 +480,8 @@ usb_request_status_t usb_vendor_request_write_spiflash(
|
||||
|| ((addr + len) > W25Q80BV_NUM_BYTES)) {
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else {
|
||||
usb_endpoint_schedule(endpoint->out, &spiflash_buffer[0], len);
|
||||
usb_transfer_schedule_block(endpoint->out, &spiflash_buffer[0], len,
|
||||
NULL, NULL);
|
||||
w25q80bv_setup();
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
@ -534,7 +494,7 @@ usb_request_status_t usb_vendor_request_write_spiflash(
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else {
|
||||
w25q80bv_program(addr, len, &spiflash_buffer[0]);
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
//FIXME probably should undo w25q80bv_setup()
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
@ -556,7 +516,7 @@ usb_request_status_t usb_vendor_request_read_spiflash(
|
||||
addr = (endpoint->setup.value << 16) | endpoint->setup.index;
|
||||
len = endpoint->setup.length;
|
||||
if ((len > W25Q80BV_PAGE_LEN) || (addr > W25Q80BV_NUM_BYTES)
|
||||
|| ((addr + len) > W25Q80BV_NUM_BYTES)) {
|
||||
|| ((addr + len) > W25Q80BV_NUM_BYTES)) {
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else {
|
||||
/* TODO flush SPIFI "cache" before to read the SPIFI memory */
|
||||
@ -565,7 +525,8 @@ usb_request_status_t usb_vendor_request_read_spiflash(
|
||||
{
|
||||
spiflash_buffer[i] = u8_addr_pt[i];
|
||||
}
|
||||
usb_endpoint_schedule(endpoint->in, &spiflash_buffer[0], len);
|
||||
usb_transfer_schedule_block(endpoint->in, &spiflash_buffer[0], len,
|
||||
NULL, NULL);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
} else if (stage == USB_TRANSFER_STAGE_DATA)
|
||||
@ -579,7 +540,7 @@ usb_request_status_t usb_vendor_request_read_spiflash(
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else
|
||||
{
|
||||
usb_endpoint_schedule_ack(endpoint->out);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
} else
|
||||
@ -603,7 +564,8 @@ usb_request_status_t usb_vendor_request_write_cpld(
|
||||
// len is limited to 64KB 16bits no overflow can happen
|
||||
total_len = endpoint->setup.value;
|
||||
len = endpoint->setup.length;
|
||||
usb_endpoint_schedule(endpoint->out, &cpld_xsvf_buffer[write_cpld_idx], len);
|
||||
usb_transfer_schedule_block(endpoint->out, &cpld_xsvf_buffer[write_cpld_idx], len,
|
||||
NULL, NULL);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
} else if (stage == USB_TRANSFER_STAGE_DATA)
|
||||
{
|
||||
@ -619,7 +581,7 @@ usb_request_status_t usb_vendor_request_write_cpld(
|
||||
// TO FIX ACK shall be not delayed so much as cpld prog can take up to 5s.
|
||||
if(error == 0)
|
||||
{
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
|
||||
/* blink LED1, LED2, and LED3 on success */
|
||||
while (1)
|
||||
@ -641,7 +603,7 @@ usb_request_status_t usb_vendor_request_write_cpld(
|
||||
}
|
||||
}else
|
||||
{
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
} else
|
||||
@ -655,8 +617,8 @@ usb_request_status_t usb_vendor_request_read_board_id(
|
||||
{
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||
endpoint->buffer[0] = BOARD_ID;
|
||||
usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 1);
|
||||
usb_endpoint_schedule_ack(endpoint->out);
|
||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1, NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
@ -668,8 +630,8 @@ usb_request_status_t usb_vendor_request_read_version_string(
|
||||
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||
length = (uint8_t)strlen(version_string);
|
||||
usb_endpoint_schedule(endpoint->in, version_string, length);
|
||||
usb_endpoint_schedule_ack(endpoint->out);
|
||||
usb_transfer_schedule_block(endpoint->in, version_string, length, NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
@ -680,13 +642,14 @@ usb_request_status_t usb_vendor_request_set_freq(
|
||||
{
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP)
|
||||
{
|
||||
usb_endpoint_schedule(endpoint->out, &set_freq_params, sizeof(set_freq_params_t));
|
||||
usb_transfer_schedule_block(endpoint->out, &set_freq_params, sizeof(set_freq_params_t),
|
||||
NULL, NULL);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
} else if (stage == USB_TRANSFER_STAGE_DATA)
|
||||
{
|
||||
if( set_freq(set_freq_params.freq_mhz, set_freq_params.freq_hz) )
|
||||
{
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
@ -702,13 +665,14 @@ usb_request_status_t usb_vendor_request_set_sample_rate_frac(
|
||||
{
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP)
|
||||
{
|
||||
usb_endpoint_schedule(endpoint->out, &set_sample_r_params, sizeof(set_sample_r_params_t));
|
||||
usb_transfer_schedule_block(endpoint->out, &set_sample_r_params, sizeof(set_sample_r_params_t),
|
||||
NULL, NULL);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
} else if (stage == USB_TRANSFER_STAGE_DATA)
|
||||
{
|
||||
if( sample_rate_frac_set(set_sample_r_params.freq_hz * 2, set_sample_r_params.divider ) )
|
||||
{
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
@ -726,12 +690,12 @@ usb_request_status_t usb_vendor_request_set_amp_enable(
|
||||
case 0:
|
||||
switchctrl |= SWITCHCTRL_AMP_BYPASS;
|
||||
update_switches();
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
case 1:
|
||||
switchctrl &= ~SWITCHCTRL_AMP_BYPASS;
|
||||
update_switches();
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
default:
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
@ -776,20 +740,23 @@ usb_request_status_t usb_vendor_request_read_partid_serialno(
|
||||
read_partid_serialno.serial_no[3] = iap_cmd_res.status_res.iap_result[3];
|
||||
|
||||
length = (uint8_t)sizeof(read_partid_serialno_t);
|
||||
usb_endpoint_schedule(endpoint->in, &read_partid_serialno, length);
|
||||
usb_endpoint_schedule_ack(endpoint->out);
|
||||
usb_transfer_schedule_block(endpoint->in, &read_partid_serialno, length,
|
||||
NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_set_lna_gain(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage)
|
||||
{
|
||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||
const uint8_t value = max2837_set_lna_gain(endpoint->setup.index);
|
||||
endpoint->buffer[0] = value;
|
||||
usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 1);
|
||||
usb_endpoint_schedule_ack(endpoint->out);
|
||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1,
|
||||
NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
@ -801,8 +768,9 @@ usb_request_status_t usb_vendor_request_set_vga_gain(
|
||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||
const uint8_t value = max2837_set_vga_gain(endpoint->setup.index);
|
||||
endpoint->buffer[0] = value;
|
||||
usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 1);
|
||||
usb_endpoint_schedule_ack(endpoint->out);
|
||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1,
|
||||
NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
@ -814,8 +782,9 @@ usb_request_status_t usb_vendor_request_set_txvga_gain(
|
||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||
const uint8_t value = max2837_set_txvga_gain(endpoint->setup.index);
|
||||
endpoint->buffer[0] = value;
|
||||
usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 1);
|
||||
usb_endpoint_schedule_ack(endpoint->out);
|
||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1,
|
||||
NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
@ -827,7 +796,7 @@ usb_request_status_t usb_vendor_request_set_if_freq(
|
||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||
MAX2837_FREQ_NOMINAL_HZ = (uint32_t)endpoint->setup.index * 1000 * 1000;
|
||||
set_freq(freq_mhz_cache, freq_hz_cache);
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
@ -966,10 +935,16 @@ int main(void) {
|
||||
enable_1v8_power();
|
||||
cpu_clock_init();
|
||||
|
||||
usb_set_configuration_changed_cb(usb_configuration_changed);
|
||||
usb_peripheral_reset();
|
||||
|
||||
usb_device_init(0, &usb_device);
|
||||
|
||||
usb_queue_init(&usb_endpoint_control_out_queue);
|
||||
usb_queue_init(&usb_endpoint_control_in_queue);
|
||||
usb_queue_init(&usb_endpoint_bulk_out_queue);
|
||||
usb_queue_init(&usb_endpoint_bulk_in_queue);
|
||||
|
||||
usb_endpoint_init(&usb_endpoint_control_out);
|
||||
usb_endpoint_init(&usb_endpoint_control_in);
|
||||
|
||||
@ -977,7 +952,7 @@ int main(void) {
|
||||
|
||||
usb_run(&usb_device);
|
||||
|
||||
ssp1_init();
|
||||
ssp1_init();
|
||||
ssp1_set_mode_max5864();
|
||||
max5864_xcvr();
|
||||
|
||||
@ -996,21 +971,29 @@ int main(void) {
|
||||
while( usb_bulk_buffer_offset < 16384 );
|
||||
|
||||
// Set up IN transfer of buffer 0.
|
||||
usb_endpoint_schedule_no_int(
|
||||
(transceiver_mode == TRANSCEIVER_MODE_RX)
|
||||
? &usb_endpoint_bulk_in : &usb_endpoint_bulk_out,
|
||||
&usb_td_bulk[0]
|
||||
);
|
||||
if (transceiver_mode != TRANSCEIVER_MODE_OFF) {
|
||||
usb_transfer_schedule_block(
|
||||
(transceiver_mode == TRANSCEIVER_MODE_RX)
|
||||
? &usb_endpoint_bulk_in : &usb_endpoint_bulk_out,
|
||||
&usb_bulk_buffer[0x0000],
|
||||
0x4000,
|
||||
NULL, NULL
|
||||
);
|
||||
}
|
||||
|
||||
// Wait until buffer 1 is transmitted/received.
|
||||
while( usb_bulk_buffer_offset >= 16384 );
|
||||
|
||||
// Set up IN transfer of buffer 1.
|
||||
usb_endpoint_schedule_no_int(
|
||||
(transceiver_mode == TRANSCEIVER_MODE_RX)
|
||||
? &usb_endpoint_bulk_in : &usb_endpoint_bulk_out,
|
||||
&usb_td_bulk[1]
|
||||
);
|
||||
if (transceiver_mode != TRANSCEIVER_MODE_OFF) {
|
||||
usb_transfer_schedule_block(
|
||||
(transceiver_mode == TRANSCEIVER_MODE_RX)
|
||||
? &usb_endpoint_bulk_in : &usb_endpoint_bulk_out,
|
||||
&usb_bulk_buffer[0x4000],
|
||||
0x4000,
|
||||
NULL, NULL
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "usb.h"
|
||||
#include "usb_type.h"
|
||||
#include "usb_queue.h"
|
||||
#include "usb_standard_request.h"
|
||||
|
||||
#include <libopencm3/lpc43xx/creg.h>
|
||||
@ -34,10 +35,8 @@
|
||||
usb_device_t* usb_device_usb0 = 0;
|
||||
|
||||
usb_queue_head_t usb_qh[12] ATTR_ALIGNED(2048);
|
||||
usb_transfer_descriptor_t usb_td[12] ATTR_ALIGNED(64);
|
||||
|
||||
#define USB_QH_INDEX(endpoint_address) (((endpoint_address & 0xF) * 2) + ((endpoint_address >> 7) & 1))
|
||||
#define USB_TD_INDEX(endpoint_address) (((endpoint_address & 0xF) * 2) + ((endpoint_address >> 7) & 1))
|
||||
|
||||
usb_queue_head_t* usb_queue_head(
|
||||
const uint_fast8_t endpoint_address
|
||||
@ -45,12 +44,6 @@ usb_queue_head_t* usb_queue_head(
|
||||
return &usb_qh[USB_QH_INDEX(endpoint_address)];
|
||||
}
|
||||
|
||||
usb_transfer_descriptor_t* usb_transfer_descriptor(
|
||||
const uint_fast8_t endpoint_address
|
||||
) {
|
||||
return &usb_td[USB_TD_INDEX(endpoint_address)];
|
||||
}
|
||||
|
||||
static usb_endpoint_t* usb_endpoint_from_address(
|
||||
const uint_fast8_t endpoint_address
|
||||
) {
|
||||
@ -98,25 +91,25 @@ static void usb_clear_all_pending_interrupts() {
|
||||
static void usb_wait_for_endpoint_priming_to_finish(const uint32_t mask) {
|
||||
// Wait until controller has parsed new transfer descriptors and prepared
|
||||
// receive buffers.
|
||||
while( USB0_ENDPTPRIME & mask );
|
||||
while( USB0_ENDPTPRIME & mask );
|
||||
}
|
||||
|
||||
static void usb_flush_endpoints(const uint32_t mask) {
|
||||
// Clear any primed buffers. If a packet is in progress, that transfer
|
||||
// will continue until completion.
|
||||
USB0_ENDPTFLUSH = mask;
|
||||
USB0_ENDPTFLUSH = mask;
|
||||
}
|
||||
|
||||
static void usb_wait_for_endpoint_flushing_to_finish(const uint32_t mask) {
|
||||
// Wait until controller has flushed all endpoints / cleared any primed
|
||||
// buffers.
|
||||
while( USB0_ENDPTFLUSH & mask );
|
||||
while( USB0_ENDPTFLUSH & mask );
|
||||
}
|
||||
|
||||
static void usb_flush_primed_endpoints(const uint32_t mask) {
|
||||
usb_wait_for_endpoint_priming_to_finish(mask);
|
||||
usb_wait_for_endpoint_priming_to_finish(mask);
|
||||
usb_flush_endpoints(mask);
|
||||
usb_wait_for_endpoint_flushing_to_finish(mask);
|
||||
usb_wait_for_endpoint_flushing_to_finish(mask);
|
||||
}
|
||||
|
||||
static void usb_flush_all_primed_endpoints() {
|
||||
@ -171,6 +164,7 @@ void usb_endpoint_disable(
|
||||
} else {
|
||||
USB0_ENDPTCTRL(endpoint_number) &= ~(USB0_ENDPTCTRL_RXE);
|
||||
}
|
||||
usb_queue_flush_endpoint(endpoint);
|
||||
usb_endpoint_clear_pending_interrupts(endpoint);
|
||||
usb_endpoint_flush(endpoint);
|
||||
}
|
||||
@ -196,39 +190,6 @@ void usb_endpoint_prime(
|
||||
}
|
||||
}
|
||||
|
||||
// Schedule an already filled-up transfer descriptor for execution on
|
||||
// the given endpoint. Note that this requires that one knows the tail
|
||||
// of the endpoint's TD queue
|
||||
void usb_endpoint_append_td(
|
||||
const usb_endpoint_t* const endpoint,
|
||||
usb_transfer_descriptor_t* const tail_td,
|
||||
usb_transfer_descriptor_t* const new_td
|
||||
) {
|
||||
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
|
||||
bool done;
|
||||
|
||||
tail_td->next_dtd_pointer = new_td;
|
||||
|
||||
do {
|
||||
if( usb_endpoint_is_in(endpoint->address) ) {
|
||||
if (USB0_ENDPTPRIME & USB0_ENDPTPRIME_PETB(1 << endpoint_number) )
|
||||
return;
|
||||
} else {
|
||||
if (USB0_ENDPTPRIME & USB0_ENDPTPRIME_PERB(1 << endpoint_number) )
|
||||
return;
|
||||
}
|
||||
|
||||
USB0_USBCMD_D |= USB0_USBCMD_D_ATDTW;
|
||||
done = usb_endpoint_is_ready(endpoint);
|
||||
} while (!(USB0_USBCMD_D & USB0_USBCMD_D_ATDTW));
|
||||
|
||||
USB0_USBCMD_D &= ~USB0_USBCMD_D_ATDTW;
|
||||
if(!done) {
|
||||
usb_endpoint_prime(endpoint, new_td);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
static bool usb_endpoint_is_priming(
|
||||
const usb_endpoint_t* const endpoint
|
||||
) {
|
||||
@ -239,11 +200,57 @@ static bool usb_endpoint_is_priming(
|
||||
return USB0_ENDPTPRIME & USB0_ENDPTPRIME_PERB(1 << endpoint_number);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Schedule an already filled-in transfer descriptor for execution on
|
||||
// the given endpoint, waiting until the endpoint has finished.
|
||||
void usb_endpoint_schedule_wait(
|
||||
const usb_endpoint_t* const endpoint,
|
||||
usb_transfer_descriptor_t* const td
|
||||
) {
|
||||
// Ensure that endpoint is ready to be primed.
|
||||
// It may have been flushed due to an aborted transaction.
|
||||
// TODO: This should be preceded by a flush?
|
||||
while( usb_endpoint_is_ready(endpoint) );
|
||||
|
||||
td->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE;
|
||||
|
||||
usb_endpoint_prime(endpoint, td);
|
||||
}
|
||||
|
||||
// Schedule an already filled-in transfer descriptor for execution on
|
||||
// the given endpoint, appending to the end of the endpoint's queue if
|
||||
// there are pending TDs. Note that this requires that one knows the
|
||||
// tail of the endpoint's TD queue. Moreover, the user is responsible
|
||||
// for setting the TERMINATE bit of next_dtd_pointer if needed.
|
||||
void usb_endpoint_schedule_append(
|
||||
const usb_endpoint_t* const endpoint,
|
||||
usb_transfer_descriptor_t* const tail_td,
|
||||
usb_transfer_descriptor_t* const new_td
|
||||
) {
|
||||
bool done;
|
||||
|
||||
tail_td->next_dtd_pointer = new_td;
|
||||
|
||||
if (usb_endpoint_is_priming(endpoint)) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
USB0_USBCMD_D |= USB0_USBCMD_D_ATDTW;
|
||||
done = usb_endpoint_is_ready(endpoint);
|
||||
} while (!(USB0_USBCMD_D & USB0_USBCMD_D_ATDTW));
|
||||
|
||||
USB0_USBCMD_D &= ~USB0_USBCMD_D_ATDTW;
|
||||
if(!done) {
|
||||
usb_endpoint_prime(endpoint, new_td);
|
||||
}
|
||||
}
|
||||
|
||||
void usb_endpoint_flush(
|
||||
const usb_endpoint_t* const endpoint
|
||||
) {
|
||||
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
|
||||
usb_queue_flush_endpoint(endpoint);
|
||||
if( usb_endpoint_is_in(endpoint->address) ) {
|
||||
usb_flush_primed_endpoints(USB0_ENDPTFLUSH_FETB(1 << endpoint_number));
|
||||
} else {
|
||||
@ -543,48 +550,13 @@ void usb_endpoint_init(
|
||||
usb_endpoint_enable(endpoint);
|
||||
}
|
||||
|
||||
void usb_endpoint_schedule(
|
||||
const usb_endpoint_t* const endpoint,
|
||||
void* const data,
|
||||
const uint32_t maximum_length
|
||||
) {
|
||||
usb_transfer_descriptor_t* const td = usb_transfer_descriptor(endpoint->address);
|
||||
|
||||
// Ensure that endpoint is ready to be primed.
|
||||
// It may have been flushed due to an aborted transaction.
|
||||
// TODO: This should be preceded by a flush?
|
||||
while( usb_endpoint_is_ready(endpoint) );
|
||||
|
||||
// Configure a transfer.
|
||||
td->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE;
|
||||
td->total_bytes =
|
||||
USB_TD_DTD_TOKEN_TOTAL_BYTES(maximum_length)
|
||||
| USB_TD_DTD_TOKEN_IOC
|
||||
| USB_TD_DTD_TOKEN_MULTO(0)
|
||||
| USB_TD_DTD_TOKEN_STATUS_ACTIVE
|
||||
;
|
||||
td->buffer_pointer_page[0] = (uint32_t)data;
|
||||
td->buffer_pointer_page[1] = ((uint32_t)data + 0x1000) & 0xfffff000;
|
||||
td->buffer_pointer_page[2] = ((uint32_t)data + 0x2000) & 0xfffff000;
|
||||
td->buffer_pointer_page[3] = ((uint32_t)data + 0x3000) & 0xfffff000;
|
||||
td->buffer_pointer_page[4] = ((uint32_t)data + 0x4000) & 0xfffff000;
|
||||
|
||||
usb_endpoint_prime(endpoint, td);
|
||||
}
|
||||
|
||||
void usb_endpoint_schedule_ack(
|
||||
const usb_endpoint_t* const endpoint
|
||||
) {
|
||||
usb_endpoint_schedule(endpoint, 0, 0);
|
||||
}
|
||||
|
||||
static void usb_check_for_setup_events() {
|
||||
const uint32_t endptsetupstat = usb_get_endpoint_setup_status();
|
||||
if( endptsetupstat ) {
|
||||
for( uint_fast8_t i=0; i<6; i++ ) {
|
||||
const uint32_t endptsetupstat_bit = USB0_ENDPTSETUPSTAT_ENDPTSETUPSTAT(1 << i);
|
||||
if( endptsetupstat & endptsetupstat_bit ) {
|
||||
usb_endpoint_t* const endpoint =
|
||||
usb_endpoint_t* const endpoint =
|
||||
usb_endpoint_from_address(
|
||||
usb_endpoint_address(USB_TRANSFER_DIRECTION_OUT, i)
|
||||
);
|
||||
|
@ -61,16 +61,6 @@ void usb_endpoint_init(
|
||||
const usb_endpoint_t* const endpoint
|
||||
);
|
||||
|
||||
void usb_endpoint_schedule(
|
||||
const usb_endpoint_t* const endpoint,
|
||||
void* const data,
|
||||
const uint32_t maximum_length
|
||||
);
|
||||
|
||||
void usb_endpoint_schedule_ack(
|
||||
const usb_endpoint_t* const endpoint
|
||||
);
|
||||
|
||||
void usb_endpoint_stall(
|
||||
const usb_endpoint_t* const endpoint
|
||||
);
|
||||
@ -92,7 +82,12 @@ void usb_endpoint_prime(
|
||||
usb_transfer_descriptor_t* const first_td
|
||||
);
|
||||
|
||||
void usb_endpoint_append_td(
|
||||
void usb_endpoint_schedule_wait(
|
||||
const usb_endpoint_t* const endpoint,
|
||||
usb_transfer_descriptor_t* const td
|
||||
);
|
||||
|
||||
void usb_endpoint_schedule_append(
|
||||
const usb_endpoint_t* const endpoint,
|
||||
usb_transfer_descriptor_t* const tail_td,
|
||||
usb_transfer_descriptor_t* const new_td
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "usb.h"
|
||||
#include "usb_request.h"
|
||||
#include "usb_queue.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
@ -75,6 +76,7 @@ void usb_control_out_complete(
|
||||
} else {
|
||||
usb_request(endpoint, USB_TRANSFER_STAGE_DATA);
|
||||
}
|
||||
usb_queue_transfer_complete(endpoint);
|
||||
}
|
||||
|
||||
void usb_control_in_complete(
|
||||
@ -87,5 +89,6 @@ void usb_control_in_complete(
|
||||
} else {
|
||||
usb_request(endpoint, USB_TRANSFER_STAGE_STATUS);
|
||||
}
|
||||
usb_queue_transfer_complete(endpoint);
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "usb.h"
|
||||
#include "usb_type.h"
|
||||
#include "usb_descriptor.h"
|
||||
#include "usb_queue.h"
|
||||
|
||||
const uint8_t* usb_endpoint_descriptor(
|
||||
const usb_endpoint_t* const endpoint
|
||||
@ -99,9 +100,11 @@ bool usb_set_configuration(
|
||||
if( new_configuration != device->configuration ) {
|
||||
// Configuration changed.
|
||||
device->configuration = new_configuration;
|
||||
if (usb_configuration_changed_cb)
|
||||
usb_configuration_changed_cb(device);
|
||||
}
|
||||
|
||||
if (usb_configuration_changed_cb)
|
||||
usb_configuration_changed_cb(device);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -114,12 +117,13 @@ static usb_request_status_t usb_send_descriptor(
|
||||
if( descriptor_data[1] == USB_DESCRIPTOR_TYPE_CONFIGURATION ) {
|
||||
descriptor_length = (descriptor_data[3] << 8) | descriptor_data[2];
|
||||
}
|
||||
usb_endpoint_schedule(
|
||||
usb_transfer_schedule_block(
|
||||
endpoint->in,
|
||||
descriptor_data,
|
||||
(setup_length > descriptor_length) ? descriptor_length : setup_length
|
||||
(setup_length > descriptor_length) ? descriptor_length : setup_length,
|
||||
NULL, NULL
|
||||
);
|
||||
usb_endpoint_schedule_ack(endpoint->out);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
||||
@ -195,7 +199,7 @@ 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);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
||||
@ -231,7 +235,7 @@ static usb_request_status_t usb_standard_request_set_configuration_setup(
|
||||
// TODO: Should this be done immediately?
|
||||
usb_set_address_immediate(endpoint->device, 0);
|
||||
}
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
} else {
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
@ -265,8 +269,8 @@ static usb_request_status_t usb_standard_request_get_configuration_setup(
|
||||
if( endpoint->device->configuration ) {
|
||||
endpoint->buffer[0] = endpoint->device->configuration->number;
|
||||
}
|
||||
usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 1);
|
||||
usb_endpoint_schedule_ack(endpoint->out);
|
||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1, NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
} else {
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
|
Submodule firmware/libopencm3 updated: d7fdcefbd7...f04d6dd82b
Reference in New Issue
Block a user