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

// SPDX-License-Identifier: GPL-2.0

/* Driver for Theobroma Systems UCAN devices, Protocol Version 3
 *
 * Copyright (C) 2018 Theobroma Systems Design und Consulting GmbH
 *
 *
 * General Description:
 *
 * The USB Device uses three Endpoints:
 *
 *   CONTROL Endpoint: Is used the setup the device (start, stop,
 *   info, configure).
 *
 *   IN Endpoint: The device sends CAN Frame Messages and Device
 *   Information using the IN endpoint.
 *
 *   OUT Endpoint: The driver sends configuration requests, and CAN
 *   Frames on the out endpoint.
 *
 * Error Handling:
 *
 *   If error reporting is turned on the device encodes error into CAN
 *   error frames (see uapi/linux/can/error.h) and sends it using the
 *   IN Endpoint. The driver updates statistics and forward it.
 */

#include <linux/can.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
#include <linux/ethtool.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/signal.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/usb.h>

#define UCAN_DRIVER_NAME
#define UCAN_MAX_RX_URBS
/* the CAN controller needs a while to enable/disable the bus */
#define UCAN_USB_CTL_PIPE_TIMEOUT
/* this driver currently supports protocol version 3 only */
#define UCAN_PROTOCOL_VERSION_MIN
#define UCAN_PROTOCOL_VERSION_MAX

/* UCAN Message Definitions
 * ------------------------
 *
 *  ucan_message_out_t and ucan_message_in_t define the messages
 *  transmitted on the OUT and IN endpoint.
 *
 *  Multibyte fields are transmitted with little endianness
 *
 *  INTR Endpoint: a single uint32_t storing the current space in the fifo
 *
 *  OUT Endpoint: single message of type ucan_message_out_t is
 *    transmitted on the out endpoint
 *
 *  IN Endpoint: multiple messages ucan_message_in_t concateted in
 *    the following way:
 *
 *	m[n].len <=> the length if message n(including the header in bytes)
 *	m[n] is is aligned to a 4 byte boundary, hence
 *	  offset(m[0])	 := 0;
 *	  offset(m[n+1]) := offset(m[n]) + (m[n].len + 3) & 3
 *
 *	this implies that
 *	  offset(m[n]) % 4 <=> 0
 */

/* Device Global Commands */
enum {};

/* UCAN Commands */
enum {};

/* UCAN_COMMAND_START and UCAN_COMMAND_GET_INFO operation modes (bitmap).
 * Undefined bits must be set to 0.
 */
enum {};

/* UCAN_COMMAND_GET subcommands */
enum {};

/* UCAN_COMMAND_FILTER subcommands */
enum {};

/* OUT endpoint message types */
enum {};

/* IN endpoint message types */
enum {};

struct ucan_ctl_cmd_start {} __packed;

struct ucan_ctl_cmd_set_bittiming {} __packed;

struct ucan_ctl_cmd_device_info {} __packed;

struct ucan_ctl_cmd_get_protocol_version {} __packed;

ucan_ctl_payload __packed;

enum {};

/* Transmission Complete within ucan_message_in */
struct ucan_tx_complete_entry_t {} __packed __aligned();

/* CAN Data message format within ucan_message_in/out */
struct ucan_can_msg {} __packed;

/* OUT Endpoint, outbound messages */
struct ucan_message_out {} __packed __aligned();

/* IN Endpoint, inbound messages */
struct ucan_message_in {} __packed __aligned();

/* Macros to calculate message lengths */
#define UCAN_OUT_HDR_SIZE

#define UCAN_IN_HDR_SIZE
#define UCAN_IN_LEN(member)

struct ucan_priv;

/* Context Information for transmission URBs */
struct ucan_urb_context {};

/* Information reported by the USB device */
struct ucan_device_info {};

/* Driver private data */
struct ucan_priv {};

static u8 ucan_can_cc_dlc2len(struct ucan_can_msg *msg, u16 len)
{}

static void ucan_release_context_array(struct ucan_priv *up)
{}

static int ucan_alloc_context_array(struct ucan_priv *up)
{}

static struct ucan_urb_context *ucan_alloc_context(struct ucan_priv *up)
{}

static bool ucan_release_context(struct ucan_priv *up,
				 struct ucan_urb_context *ctx)
{}

static int ucan_ctrl_command_out(struct ucan_priv *up,
				 u8 cmd, u16 subcmd, u16 datalen)
{}

static int ucan_device_request_in(struct ucan_priv *up,
				  u8 cmd, u16 subcmd, u16 datalen)
{}

/* Parse the device information structure reported by the device and
 * setup private variables accordingly
 */
static void ucan_parse_device_info(struct ucan_priv *up,
				   struct ucan_ctl_cmd_device_info *device_info)
{}

/* Handle a CAN error frame that we have received from the device.
 * Returns true if the can state has changed.
 */
static bool ucan_handle_error_frame(struct ucan_priv *up,
				    struct ucan_message_in *m,
				    canid_t canid)
{}

/* Callback on reception of a can frame via the IN endpoint
 *
 * This function allocates an skb and transferres it to the Linux
 * network stack
 */
static void ucan_rx_can_msg(struct ucan_priv *up, struct ucan_message_in *m)
{}

/* callback indicating completed transmission */
static void ucan_tx_complete_msg(struct ucan_priv *up,
				 struct ucan_message_in *m)
{}

/* callback on reception of a USB message */
static void ucan_read_bulk_callback(struct urb *urb)
{}

/* callback after transmission of a USB message */
static void ucan_write_bulk_callback(struct urb *urb)
{}

static void ucan_cleanup_rx_urbs(struct ucan_priv *up, struct urb **urbs)
{}

static int ucan_prepare_and_anchor_rx_urbs(struct ucan_priv *up,
					   struct urb **urbs)
{}

/* Submits rx urbs with the semantic: Either submit all, or cleanup
 * everything. I case of errors submitted urbs are killed and all urbs in
 * the array are freed. I case of no errors every entry in the urb
 * array is set to NULL.
 */
static int ucan_submit_rx_urbs(struct ucan_priv *up, struct urb **urbs)
{}

/* Open the network device */
static int ucan_open(struct net_device *netdev)
{}

static struct urb *ucan_prepare_tx_urb(struct ucan_priv *up,
				       struct ucan_urb_context *context,
				       struct can_frame *cf,
				       u8 echo_index)
{}

static void ucan_clean_up_tx_urb(struct ucan_priv *up, struct urb *urb)
{}

/* callback when Linux needs to send a can frame */
static netdev_tx_t ucan_start_xmit(struct sk_buff *skb,
				   struct net_device *netdev)
{}

/* Device goes down
 *
 * Clean up used resources
 */
static int ucan_close(struct net_device *netdev)
{}

/* CAN driver callbacks */
static const struct net_device_ops ucan_netdev_ops =;

static const struct ethtool_ops ucan_ethtool_ops =;

/* Request to set bittiming
 *
 * This function generates an USB set bittiming message and transmits
 * it to the device
 */
static int ucan_set_bittiming(struct net_device *netdev)
{}

/* Restart the device to get it out of BUS-OFF state.
 * Called when the user runs "ip link set can1 type can restart".
 */
static int ucan_set_mode(struct net_device *netdev, enum can_mode mode)
{}

/* Probe the device, reset it and gather general device information */
static int ucan_probe(struct usb_interface *intf,
		      const struct usb_device_id *id)
{}

/* disconnect the device */
static void ucan_disconnect(struct usb_interface *intf)
{}

static struct usb_device_id ucan_table[] =;

MODULE_DEVICE_TABLE(usb, ucan_table);
/* driver callbacks */
static struct usb_driver ucan_driver =;

module_usb_driver();

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