linux/drivers/net/can/usb/gs_usb.c

// SPDX-License-Identifier: GPL-2.0-only
/* CAN driver for Geschwister Schneider USB/CAN devices
 * and bytewerk.org candleLight USB CAN interfaces.
 *
 * Copyright (C) 2013-2016 Geschwister Schneider Technologie-,
 * Entwicklungs- und Vertriebs UG (Haftungsbeschränkt).
 * Copyright (C) 2016 Hubert Denkmair
 * Copyright (c) 2023 Pengutronix, Marc Kleine-Budde <[email protected]>
 *
 * Many thanks to all socketcan devs!
 */

#include <linux/bitfield.h>
#include <linux/clocksource.h>
#include <linux/ethtool.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/signal.h>
#include <linux/timecounter.h>
#include <linux/units.h>
#include <linux/usb.h>
#include <linux/workqueue.h>

#include <linux/can.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
#include <linux/can/rx-offload.h>

/* Device specific constants */
#define USB_GS_USB_1_VENDOR_ID
#define USB_GS_USB_1_PRODUCT_ID

#define USB_CANDLELIGHT_VENDOR_ID
#define USB_CANDLELIGHT_PRODUCT_ID

#define USB_CES_CANEXT_FD_VENDOR_ID
#define USB_CES_CANEXT_FD_PRODUCT_ID

#define USB_ABE_CANDEBUGGER_FD_VENDOR_ID
#define USB_ABE_CANDEBUGGER_FD_PRODUCT_ID

#define USB_XYLANTA_SAINT3_VENDOR_ID
#define USB_XYLANTA_SAINT3_PRODUCT_ID

#define GS_USB_ENDPOINT_IN
#define GS_USB_ENDPOINT_OUT

/* Timestamp 32 bit timer runs at 1 MHz (1 µs tick). Worker accounts
 * for timer overflow (will be after ~71 minutes)
 */
#define GS_USB_TIMESTAMP_TIMER_HZ
#define GS_USB_TIMESTAMP_WORK_DELAY_SEC
static_assert();

/* Device specific constants */
enum gs_usb_breq {};

enum gs_can_mode {};

enum gs_can_state {};

enum gs_can_identify_mode {};

enum gs_can_termination_state {};

#define GS_USB_TERMINATION_DISABLED
#define GS_USB_TERMINATION_ENABLED

/* data types passed between host and device */

/* The firmware on the original USB2CAN by Geschwister Schneider
 * Technologie Entwicklungs- und Vertriebs UG exchanges all data
 * between the host and the device in host byte order. This is done
 * with the struct gs_host_config::byte_order member, which is sent
 * first to indicate the desired byte order.
 *
 * The widely used open source firmware candleLight doesn't support
 * this feature and exchanges the data in little endian byte order.
 */
struct gs_host_config {} __packed;

struct gs_device_config {} __packed;

#define GS_CAN_MODE_NORMAL
#define GS_CAN_MODE_LISTEN_ONLY
#define GS_CAN_MODE_LOOP_BACK
#define GS_CAN_MODE_TRIPLE_SAMPLE
#define GS_CAN_MODE_ONE_SHOT
#define GS_CAN_MODE_HW_TIMESTAMP
/* GS_CAN_FEATURE_IDENTIFY BIT(5) */
/* GS_CAN_FEATURE_USER_ID BIT(6) */
#define GS_CAN_MODE_PAD_PKTS_TO_MAX_PKT_SIZE
#define GS_CAN_MODE_FD
/* GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX BIT(9) */
/* GS_CAN_FEATURE_BT_CONST_EXT BIT(10) */
/* GS_CAN_FEATURE_TERMINATION BIT(11) */
#define GS_CAN_MODE_BERR_REPORTING
/* GS_CAN_FEATURE_GET_STATE BIT(13) */

struct gs_device_mode {} __packed;

struct gs_device_state {} __packed;

struct gs_device_bittiming {} __packed;

struct gs_identify_mode {} __packed;

struct gs_device_termination_state {} __packed;

#define GS_CAN_FEATURE_LISTEN_ONLY
#define GS_CAN_FEATURE_LOOP_BACK
#define GS_CAN_FEATURE_TRIPLE_SAMPLE
#define GS_CAN_FEATURE_ONE_SHOT
#define GS_CAN_FEATURE_HW_TIMESTAMP
#define GS_CAN_FEATURE_IDENTIFY
#define GS_CAN_FEATURE_USER_ID
#define GS_CAN_FEATURE_PAD_PKTS_TO_MAX_PKT_SIZE
#define GS_CAN_FEATURE_FD
#define GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX
#define GS_CAN_FEATURE_BT_CONST_EXT
#define GS_CAN_FEATURE_TERMINATION
#define GS_CAN_FEATURE_BERR_REPORTING
#define GS_CAN_FEATURE_GET_STATE
#define GS_CAN_FEATURE_MASK

/* internal quirks - keep in GS_CAN_FEATURE space for now */

/* CANtact Pro original firmware:
 * BREQ DATA_BITTIMING overlaps with GET_USER_ID
 */
#define GS_CAN_FEATURE_QUIRK_BREQ_CANTACT_PRO

struct gs_device_bt_const {} __packed;

struct gs_device_bt_const_extended {} __packed;

#define GS_CAN_FLAG_OVERFLOW
#define GS_CAN_FLAG_FD
#define GS_CAN_FLAG_BRS
#define GS_CAN_FLAG_ESI

struct classic_can {} __packed;

struct classic_can_ts {} __packed;

struct classic_can_quirk {} __packed;

struct canfd {} __packed;

struct canfd_ts {} __packed;

struct canfd_quirk {} __packed;

struct gs_host_frame {} __packed;
/* The GS USB devices make use of the same flags and masks as in
 * linux/can.h and linux/can/error.h, and no additional mapping is necessary.
 */

/* Only send a max of GS_MAX_TX_URBS frames per channel at a time. */
#define GS_MAX_TX_URBS
/* Only launch a max of GS_MAX_RX_URBS usb requests at a time. */
#define GS_MAX_RX_URBS
#define GS_NAPI_WEIGHT

/* Maximum number of interfaces the driver supports per device.
 * Current hardware only supports 3 interfaces. The future may vary.
 */
#define GS_MAX_INTF

struct gs_tx_context {};

struct gs_can {};

/* usb interface struct */
struct gs_usb {};

/* 'allocate' a tx context.
 * returns a valid tx context or NULL if there is no space.
 */
static struct gs_tx_context *gs_alloc_tx_context(struct gs_can *dev)
{}

/* releases a tx context
 */
static void gs_free_tx_context(struct gs_tx_context *txc)
{}

/* Get a tx context by id.
 */
static struct gs_tx_context *gs_get_tx_context(struct gs_can *dev,
					       unsigned int id)
{}

static int gs_cmd_reset(struct gs_can *dev)
{}

static inline int gs_usb_get_timestamp(const struct gs_usb *parent,
				       u32 *timestamp_p)
{}

static u64 gs_usb_timestamp_read(const struct cyclecounter *cc) __must_hold(&dev->tc_lock)
{}

static void gs_usb_timestamp_work(struct work_struct *work)
{}

static void gs_usb_skb_set_timestamp(struct gs_can *dev,
				     struct sk_buff *skb, u32 timestamp)
{}

static void gs_usb_timestamp_init(struct gs_usb *parent)
{}

static void gs_usb_timestamp_stop(struct gs_usb *parent)
{}

static void gs_update_state(struct gs_can *dev, struct can_frame *cf)
{}

static u32 gs_usb_set_timestamp(struct gs_can *dev, struct sk_buff *skb,
				const struct gs_host_frame *hf)
{}

static void gs_usb_rx_offload(struct gs_can *dev, struct sk_buff *skb,
			      const struct gs_host_frame *hf)
{}

static unsigned int
gs_usb_get_echo_skb(struct gs_can *dev, struct sk_buff *skb,
		    const struct gs_host_frame *hf)
{}

static void gs_usb_receive_bulk_callback(struct urb *urb)
{}

static int gs_usb_set_bittiming(struct net_device *netdev)
{}

static int gs_usb_set_data_bittiming(struct net_device *netdev)
{}

static void gs_usb_xmit_callback(struct urb *urb)
{}

static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
				     struct net_device *netdev)
{}

static int gs_can_open(struct net_device *netdev)
{}

static int gs_usb_get_state(const struct net_device *netdev,
			    struct can_berr_counter *bec,
			    enum can_state *state)
{}

static int gs_usb_can_get_berr_counter(const struct net_device *netdev,
				       struct can_berr_counter *bec)
{}

static int gs_can_close(struct net_device *netdev)
{}

static int gs_can_eth_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
{}

static const struct net_device_ops gs_usb_netdev_ops =;

static int gs_usb_set_identify(struct net_device *netdev, bool do_identify)
{}

/* blink LED's for finding the this interface */
static int gs_usb_set_phys_id(struct net_device *netdev,
			      enum ethtool_phys_id_state state)
{}

static int gs_usb_get_ts_info(struct net_device *netdev,
			      struct kernel_ethtool_ts_info *info)
{}

static const struct ethtool_ops gs_usb_ethtool_ops =;

static int gs_usb_get_termination(struct net_device *netdev, u16 *term)
{}

static int gs_usb_set_termination(struct net_device *netdev, u16 term)
{}

static const u16 gs_usb_termination_const[] =;

static struct gs_can *gs_make_candev(unsigned int channel,
				     struct usb_interface *intf,
				     struct gs_device_config *dconf)
{}

static void gs_destroy_candev(struct gs_can *dev)
{}

static int gs_usb_probe(struct usb_interface *intf,
			const struct usb_device_id *id)
{}

static void gs_usb_disconnect(struct usb_interface *intf)
{}

static const struct usb_device_id gs_usb_table[] =;

MODULE_DEVICE_TABLE(usb, gs_usb_table);

static struct usb_driver gs_usb_driver =;

module_usb_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();