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
This commit is contained in:
parent
fddf5990bd
commit
cac342af6b
|
@ -56,6 +56,7 @@ HEADERS_app=\
|
|||
usb_dev.h \
|
||||
usb_e1.h \
|
||||
usb_gps.h \
|
||||
usb_gpsdo.h \
|
||||
usb_str_app.gen.h \
|
||||
$(NULL)
|
||||
|
||||
|
@ -69,6 +70,7 @@ SOURCES_app=\
|
|||
usb_dev.c \
|
||||
usb_e1.c \
|
||||
usb_gps.c \
|
||||
usb_gpsdo.c \
|
||||
$(NULL)
|
||||
|
||||
|
||||
|
|
|
@ -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 @@ void main()
|
|||
usb_dfu_rt_init();
|
||||
usb_e1_init();
|
||||
usb_gps_init();
|
||||
usb_gpsdo_init();
|
||||
|
||||
/* Start */
|
||||
led_state(true);
|
||||
|
|
|
@ -96,7 +96,7 @@ gpsdo_get_status(struct e1usb_gpsdo_status *status)
|
|||
};
|
||||
|
||||
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;
|
||||
|
|
|
@ -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_tune {
|
|||
|
||||
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 @@ struct e1usb_gpsdo_status {
|
|||
} __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
|
||||
|
|
|
@ -53,6 +53,11 @@ static const struct {
|
|||
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 @@ static const struct {
|
|||
.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 @@ static const struct {
|
|||
.bInterfaceClass = 0xfe,
|
||||
.bInterfaceSubClass = 0x01,
|
||||
.bInterfaceProtocol = 0x01,
|
||||
.iInterface = 11,
|
||||
.iInterface = 12,
|
||||
},
|
||||
.func = {
|
||||
.bLength = sizeof(struct usb_dfu_func_desc),
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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 @@ _usb_dev_ctrl_req(struct usb_ctrl_req *req, struct usb_xfer *xfer)
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -8,4 +8,5 @@ E1 port 1 (disabled)
|
|||
E1 port 1
|
||||
GPS (CDC control)
|
||||
GPS (CDC data)
|
||||
GPS-DO control
|
||||
DFU runtime
|
||||
|
|
Loading…
Reference in New Issue