laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-e1-hardware/+/27017 )
Change subject: icE1usb: Move GPS-DO USB control to separate USB interface ......................................................................
icE1usb: Move GPS-DO USB control to separate USB interface
doing so significantly simplifies the development of a Linux kernel driver, as the GPS-DO only exists once (not twice, like the per-E1-line interface), and Linux kernel USB drivers typically are for an interface.
There is an option to write a usb_device_driver, but doing so will exclude the per-interface drivers from still being probed in their usual fashion.
While we introduce this new USB Interface for the GPS-DO, we also move the related control endpoint requests from the device level to the interface level.
Finally, some naming inconsistency between "enum ice1usb_gpsdo_antenna_state" vs. the member name antenna_status is resolved.
Change-Id: Icd6555a14896c38626fb147b78af44ff719f2254 --- M firmware/ice40-riscv/icE1usb/Makefile M firmware/ice40-riscv/icE1usb/fw_app.c M firmware/ice40-riscv/icE1usb/gpsdo.c M firmware/ice40-riscv/icE1usb/ice1usb_proto.h M firmware/ice40-riscv/icE1usb/usb_desc_app.c M firmware/ice40-riscv/icE1usb/usb_desc_ids.h M firmware/ice40-riscv/icE1usb/usb_dev.c A firmware/ice40-riscv/icE1usb/usb_gpsdo.c A firmware/ice40-riscv/icE1usb/usb_gpsdo.h M firmware/ice40-riscv/icE1usb/usb_str_app.txt 10 files changed, 172 insertions(+), 82 deletions(-)
Approvals: Jenkins Builder: Verified tnt: Looks good to me, but someone else must approve laforge: Looks good to me, approved
diff --git a/firmware/ice40-riscv/icE1usb/Makefile b/firmware/ice40-riscv/icE1usb/Makefile index 25c65d1..ed765f6 100644 --- a/firmware/ice40-riscv/icE1usb/Makefile +++ b/firmware/ice40-riscv/icE1usb/Makefile @@ -56,6 +56,7 @@ usb_dev.h \ usb_e1.h \ usb_gps.h \ + usb_gpsdo.h \ usb_str_app.gen.h \ $(NULL)
@@ -69,6 +70,7 @@ usb_dev.c \ usb_e1.c \ usb_gps.c \ + usb_gpsdo.c \ $(NULL)
diff --git a/firmware/ice40-riscv/icE1usb/fw_app.c b/firmware/ice40-riscv/icE1usb/fw_app.c index c1fe295..540eda2 100644 --- a/firmware/ice40-riscv/icE1usb/fw_app.c +++ b/firmware/ice40-riscv/icE1usb/fw_app.c @@ -23,6 +23,7 @@ #include "usb_dev.h" #include "usb_e1.h" #include "usb_gps.h" +#include "usb_gpsdo.h" #include "utils.h"
@@ -109,6 +110,7 @@ usb_dfu_rt_init(); usb_e1_init(); usb_gps_init(); + usb_gpsdo_init();
/* Start */ led_state(true); diff --git a/firmware/ice40-riscv/icE1usb/gpsdo.c b/firmware/ice40-riscv/icE1usb/gpsdo.c index ae131d4..8e32627 100644 --- a/firmware/ice40-riscv/icE1usb/gpsdo.c +++ b/firmware/ice40-riscv/icE1usb/gpsdo.c @@ -96,7 +96,7 @@ };
status->state = state_map[g_gpsdo.state]; - status->antenna_status = ant_map[gps_antenna_status()]; + status->antenna_state = ant_map[gps_antenna_status()]; status->valid_fix = gps_has_valid_fix(); status->mode = (g_gpsdo.state == STATE_DISABLED) ? ICE1USB_GPSDO_MODE_DISABLED : ICE1USB_GPSDO_MODE_AUTO; status->tune.coarse = g_gpsdo.tune.coarse; diff --git a/firmware/ice40-riscv/icE1usb/ice1usb_proto.h b/firmware/ice40-riscv/icE1usb/ice1usb_proto.h index a249537..3170d55 100644 --- a/firmware/ice40-riscv/icE1usb/ice1usb_proto.h +++ b/firmware/ice40-riscv/icE1usb/ice1usb_proto.h @@ -17,17 +17,22 @@ /*! returns a bit-mask of optional device capabilities (see enum e1usb_dev_capability) */ #define ICE1USB_DEV_GET_CAPABILITIES 0x01 #define ICE1USB_DEV_GET_FW_BUILD 0x02 -#define ICE1USB_DEV_GET_GPSDO_STATUS 0x10 -#define ICE1USB_DEV_GET_GPSDO_MODE 0x12 /*!< uint8_t */ -#define ICE1USB_DEV_SET_GPSDO_MODE 0x13 /*!< wValue = mode */ -#define ICE1USB_DEV_GET_GPSDO_TUNE 0x14 /*!< data = struct e1usb_gpsdo_tune */ -#define ICE1USB_DEV_SET_GPSDO_TUNE 0x15 /*!< data = struct e1usb_gpsdo_tune */
enum e1usb_dev_capability { /*! Does this board have a GPS-DO */ ICE1USB_DEV_CAP_GPSDO, };
+/*********************************************************************** + * Control Endpoint / GPS-DO Interface Requests + ***********************************************************************/ + +#define ICE1USB_INTF_GET_GPSDO_STATUS 0x10 +#define ICE1USB_INTF_GET_GPSDO_MODE 0x12 /*!< uint8_t */ +#define ICE1USB_INTF_SET_GPSDO_MODE 0x13 /*!< wValue = mode */ +#define ICE1USB_INTF_GET_GPSDO_TUNE 0x14 /*!< data = struct e1usb_gpsdo_tune */ +#define ICE1USB_INTF_SET_GPSDO_TUNE 0x15 /*!< data = struct e1usb_gpsdo_tune */ + enum ice1usb_gpsdo_mode { ICE1USB_GPSDO_MODE_DISABLED = 0, ICE1USB_GPSDO_MODE_AUTO = 1, @@ -55,7 +60,7 @@
struct e1usb_gpsdo_status { uint8_t state; - uint8_t antenna_status; /*!< Antenna status */ + uint8_t antenna_state; /*!< Antenna state */ uint8_t valid_fix; /*!< Valid GPS Fix (0/1) */ uint8_t mode; /*!< Current configured operating mode */ struct e1usb_gpsdo_tune tune; /*!< Current VCXO tuning values */ @@ -63,7 +68,9 @@ } __attribute__((packed));
-/* Interface Requests */ +/*********************************************************************** + * Control Endpoint / E1 Interface Requests + ***********************************************************************/
/*! returns a bit-mask of optional device capabilities (see enum e1usb_intf_capability) */ #define ICE1USB_INTF_GET_CAPABILITIES 0x01 diff --git a/firmware/ice40-riscv/icE1usb/usb_desc_app.c b/firmware/ice40-riscv/icE1usb/usb_desc_app.c index e0edf80..25472e0 100644 --- a/firmware/ice40-riscv/icE1usb/usb_desc_app.c +++ b/firmware/ice40-riscv/icE1usb/usb_desc_app.c @@ -53,6 +53,11 @@ struct usb_ep_desc ep_data_in; } __attribute__ ((packed)) cdc;
+ /* GPS-DO (control EP only) */ + struct { + struct usb_intf_desc intf; + } __attribute__ ((packed)) gpsdo; + /* DFU Runtime */ struct { struct usb_intf_desc intf; @@ -275,6 +280,19 @@ .bInterval = 0x00, }, }, + .gpsdo = { + .intf = { + .bLength = sizeof(struct usb_intf_desc), + .bDescriptorType = USB_DT_INTF, + .bInterfaceNumber = USB_INTF_GPSDO, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xe1, + .bInterfaceProtocol = 0xd0, + .iInterface = 11, + } + }, .dfu = { .intf = { .bLength = sizeof(struct usb_intf_desc), @@ -285,7 +303,7 @@ .bInterfaceClass = 0xfe, .bInterfaceSubClass = 0x01, .bInterfaceProtocol = 0x01, - .iInterface = 11, + .iInterface = 12, }, .func = { .bLength = sizeof(struct usb_dfu_func_desc), diff --git a/firmware/ice40-riscv/icE1usb/usb_desc_ids.h b/firmware/ice40-riscv/icE1usb/usb_desc_ids.h index dadf4c6..192092e 100644 --- a/firmware/ice40-riscv/icE1usb/usb_desc_ids.h +++ b/firmware/ice40-riscv/icE1usb/usb_desc_ids.h @@ -10,8 +10,9 @@ #define USB_INTF_E1(p) (0 + (p)) #define USB_INTF_GPS_CDC_CTL 2 #define USB_INTF_GPS_CDC_DATA 3 -#define USB_INTF_DFU 4 -#define USB_INTF_NUM 5 +#define USB_INTF_GPSDO 4 +#define USB_INTF_DFU 5 +#define USB_INTF_NUM 6
#define USB_EP_E1_IN(p) (0x82 + (3 * (p))) #define USB_EP_E1_OUT(p) (0x01 + (3 * (p))) diff --git a/firmware/ice40-riscv/icE1usb/usb_dev.c b/firmware/ice40-riscv/icE1usb/usb_dev.c index 2997a33..e19d9a0 100644 --- a/firmware/ice40-riscv/icE1usb/usb_dev.c +++ b/firmware/ice40-riscv/icE1usb/usb_dev.c @@ -12,7 +12,6 @@ #include <no2usb/usb_proto.h>
#include "console.h" -#include "gpsdo.h" #include "misc.h"
#include "ice1usb_proto.h" @@ -21,61 +20,6 @@ const char *fw_build_str = BUILD_INFO;
-static void -_get_gpsdo_status(struct usb_ctrl_req *req, struct usb_xfer *xfer) -{ - struct e1usb_gpsdo_status status; - - gpsdo_get_status(&status); - - memcpy(xfer->data, &status, sizeof(struct e1usb_gpsdo_status)); - xfer->len = sizeof(struct e1usb_gpsdo_status); -} - -static void -_get_gpsdo_mode(struct usb_ctrl_req *req, struct usb_xfer *xfer) -{ - xfer->data[0] = gpsdo_enabled() ? ICE1USB_GPSDO_MODE_DISABLED : ICE1USB_GPSDO_MODE_AUTO; - xfer->len = 1; -} - -static void -_set_gpsdo_mode(struct usb_ctrl_req *req, struct usb_xfer *xfer) -{ - gpsdo_enable(req->wValue != ICE1USB_GPSDO_MODE_DISABLED); -} - -static void -_get_gpsdo_tune(struct usb_ctrl_req *req, struct usb_xfer *xfer) -{ - uint16_t coarse, fine; - struct e1usb_gpsdo_tune tune; - - gpsdo_get_tune(&coarse, &fine); - tune.coarse = coarse; - tune.fine = fine; - - memcpy(xfer->data, &tune, sizeof(struct e1usb_gpsdo_tune)); - xfer->len = sizeof(struct e1usb_gpsdo_tune); -} - -static bool -_set_gpsdo_tune_done(struct usb_xfer *xfer) -{ - const struct e1usb_gpsdo_tune *tune = (const void *) xfer->data; - gpsdo_set_tune(tune->coarse, tune->fine); - return true; -} - -static void -_set_gpsdo_tune(struct usb_ctrl_req *req, struct usb_xfer *xfer) -{ - xfer->cb_done = _set_gpsdo_tune_done; - xfer->cb_ctx = req; - xfer->len = sizeof(struct e1usb_gpsdo_tune); -} - - static enum usb_fnd_resp _usb_dev_ctrl_req(struct usb_ctrl_req *req, struct usb_xfer *xfer) { @@ -93,21 +37,6 @@ xfer->data = (void*) fw_build_str; xfer->len = strlen(fw_build_str); break; - case ICE1USB_DEV_GET_GPSDO_STATUS: - _get_gpsdo_status(req, xfer); - break; - case ICE1USB_DEV_GET_GPSDO_MODE: - _get_gpsdo_mode(req, xfer); - break; - case ICE1USB_DEV_SET_GPSDO_MODE: - _set_gpsdo_mode(req, xfer); - break; - case ICE1USB_DEV_GET_GPSDO_TUNE: - _get_gpsdo_tune(req, xfer); - break; - case ICE1USB_DEV_SET_GPSDO_TUNE: - _set_gpsdo_tune(req, xfer); - break; default: return USB_FND_ERROR; } diff --git a/firmware/ice40-riscv/icE1usb/usb_gpsdo.c b/firmware/ice40-riscv/icE1usb/usb_gpsdo.c new file mode 100644 index 0000000..4dd8913 --- /dev/null +++ b/firmware/ice40-riscv/icE1usb/usb_gpsdo.c @@ -0,0 +1,120 @@ +/* + * usb_gpsdo.c + * + * Copyright (C) 2019-2022 Sylvain Munaut tnt@246tNt.com + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include <stdint.h> +#include <stdbool.h> +#include <string.h> + +#include <no2usb/usb.h> +#include <no2usb/usb_hw.h> +#include <no2usb/usb_priv.h> + +#include <no2usb/usb_proto.h> + +#include "usb_desc_ids.h" +#include "gpsdo.h" + +#include "ice1usb_proto.h" + +static void +_get_gpsdo_status(struct usb_ctrl_req *req, struct usb_xfer *xfer) +{ + struct e1usb_gpsdo_status status; + + gpsdo_get_status(&status); + + memcpy(xfer->data, &status, sizeof(struct e1usb_gpsdo_status)); + xfer->len = sizeof(struct e1usb_gpsdo_status); +} + +static void +_get_gpsdo_mode(struct usb_ctrl_req *req, struct usb_xfer *xfer) +{ + xfer->data[0] = gpsdo_enabled() ? ICE1USB_GPSDO_MODE_DISABLED : ICE1USB_GPSDO_MODE_AUTO; + xfer->len = 1; +} + +static void +_set_gpsdo_mode(struct usb_ctrl_req *req, struct usb_xfer *xfer) +{ + gpsdo_enable(req->wValue != ICE1USB_GPSDO_MODE_DISABLED); +} + +static void +_get_gpsdo_tune(struct usb_ctrl_req *req, struct usb_xfer *xfer) +{ + uint16_t coarse, fine; + struct e1usb_gpsdo_tune tune; + + gpsdo_get_tune(&coarse, &fine); + tune.coarse = coarse; + tune.fine = fine; + + memcpy(xfer->data, &tune, sizeof(struct e1usb_gpsdo_tune)); + xfer->len = sizeof(struct e1usb_gpsdo_tune); +} + +static bool +_set_gpsdo_tune_done(struct usb_xfer *xfer) +{ + const struct e1usb_gpsdo_tune *tune = (const void *) xfer->data; + gpsdo_set_tune(tune->coarse, tune->fine); + return true; +} + +static void +_set_gpsdo_tune(struct usb_ctrl_req *req, struct usb_xfer *xfer) +{ + xfer->cb_done = _set_gpsdo_tune_done; + xfer->cb_ctx = req; + xfer->len = sizeof(struct e1usb_gpsdo_tune); +} + + +static enum usb_fnd_resp +_gpsdo_ctrl_req(struct usb_ctrl_req *req, struct usb_xfer *xfer) +{ + /* Check it's for an interface */ + if (USB_REQ_TYPE_RCPT(req) != (USB_REQ_TYPE_VENDOR | USB_REQ_RCPT_INTF)) + return USB_FND_CONTINUE; + + /* Check it's for the GPS-DO interface */ + if (req->wIndex != USB_INTF_GPSDO) + return USB_FND_CONTINUE; + + switch (req->bRequest) { + case ICE1USB_INTF_GET_GPSDO_STATUS: + _get_gpsdo_status(req, xfer); + break; + case ICE1USB_INTF_GET_GPSDO_MODE: + _get_gpsdo_mode(req, xfer); + break; + case ICE1USB_INTF_SET_GPSDO_MODE: + _set_gpsdo_mode(req, xfer); + break; + case ICE1USB_INTF_GET_GPSDO_TUNE: + _get_gpsdo_tune(req, xfer); + break; + case ICE1USB_INTF_SET_GPSDO_TUNE: + _set_gpsdo_tune(req, xfer); + break; + default: + return USB_FND_ERROR; + } + + return USB_FND_SUCCESS; +} + +static struct usb_fn_drv _gpsdo_drv = { + .ctrl_req = _gpsdo_ctrl_req, +}; + +void +usb_gpsdo_init(void) +{ + usb_register_function_driver(&_gpsdo_drv); +} diff --git a/firmware/ice40-riscv/icE1usb/usb_gpsdo.h b/firmware/ice40-riscv/icE1usb/usb_gpsdo.h new file mode 100644 index 0000000..4cf4203 --- /dev/null +++ b/firmware/ice40-riscv/icE1usb/usb_gpsdo.h @@ -0,0 +1,10 @@ +/* + * usb_gpsdo.h + * + * Copyright (C) 2022 Harald Welte laforge@osmocom.org + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#pragma once + +void usb_gpsdo_init(void); diff --git a/firmware/ice40-riscv/icE1usb/usb_str_app.txt b/firmware/ice40-riscv/icE1usb/usb_str_app.txt index 3aa6b4a..5f062d3 100644 --- a/firmware/ice40-riscv/icE1usb/usb_str_app.txt +++ b/firmware/ice40-riscv/icE1usb/usb_str_app.txt @@ -8,4 +8,5 @@ E1 port 1 GPS (CDC control) GPS (CDC data) +GPS-DO control DFU runtime