[Xenial SRU][PATCH 1/1] UBUNTU: SAUCE: (no-up) upgrade IXXAT USB SocketCAN driver
Shrirang Bagul
shrirang.bagul at canonical.com
Tue Jul 24 02:28:08 UTC 2018
BugLink: http://bugs.launchpad.net/bugs/1783241
The support for IXXAT USB SocketCAN devices was introduced in:
cddf58207a3c UBUNTU: SAUCE: (no-up) Support IXXAT USB SocketCAN device
This patch upgrades the driver with following changes:
- support adapters for CL1 (Communication Layer for legacy devices) and
CL2 (current devices)
- removed CAN-IDM100 support (Microchip Rev A microcontroller)
- add CAN-IDM101 support (Microchip Rev B microcontroller)
- add Error-Passive recognition
- move CAN message handling to the core module
- use ktime API for timestamps
- fixes Linux kernel coding style issues
Changes from HMS/Dell's original driver dump "arev-2018-07-04":
- driver name retained from "beta-2018-05-07" for debain packaging
compatibility
IXXAT_USB_DRIVER_NAME "ixxat_usb2can" ->"ixx_usb"
- source files renamed to retain the old names SRU'ed for "beta-2018-05-07"
renamed: ixxat_usb_cl1.c -> ixx_usb_cl1.c
renamed: ixxat_usb_cl2.c -> ixx_usb_cl2.c
renamed: ixxat_usb_core.c -> ixx_usb_core.c
renamed: ixxat_usb_core.h -> ixx_usb_core.h
deleted: ixx_usb_fd.c
deleted: ixx_usb_v2.c
Signed-off-by: Shrirang Bagul <shrirang.bagul at canonical.com>
---
ubuntu/ixxat/Makefile | 2 +-
ubuntu/ixxat/ixx_usb_cl1.c | 139 +++
ubuntu/ixxat/ixx_usb_cl2.c | 331 +++++++
ubuntu/ixxat/ixx_usb_core.c | 1582 ++++++++++++++++++++-------------
ubuntu/ixxat/ixx_usb_core.h | 821 ++++++++++++-----
ubuntu/ixxat/ixx_usb_fd.c | 1673 -----------------------------------
ubuntu/ixxat/ixx_usb_v2.c | 1450 ------------------------------
7 files changed, 2022 insertions(+), 3976 deletions(-)
create mode 100644 ubuntu/ixxat/ixx_usb_cl1.c
create mode 100644 ubuntu/ixxat/ixx_usb_cl2.c
delete mode 100644 ubuntu/ixxat/ixx_usb_fd.c
delete mode 100644 ubuntu/ixxat/ixx_usb_v2.c
diff --git a/ubuntu/ixxat/Makefile b/ubuntu/ixxat/Makefile
index d4ee67ebdd24..fcd48462d710 100644
--- a/ubuntu/ixxat/Makefile
+++ b/ubuntu/ixxat/Makefile
@@ -1,4 +1,4 @@
mod-name += ixx_usb
obj-m += ixx_usb.o
-ixx_usb-objs := ixx_usb_v2.o ixx_usb_fd.o ixx_usb_core.o
+ixx_usb-objs := ixx_usb_cl1.o ixx_usb_cl2.o ixx_usb_core.o
diff --git a/ubuntu/ixxat/ixx_usb_cl1.c b/ubuntu/ixxat/ixx_usb_cl1.c
new file mode 100644
index 000000000000..7e9e7b57dbe6
--- /dev/null
+++ b/ubuntu/ixxat/ixx_usb_cl1.c
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* CAN driver adapter for IXXAT USB-to-CAN CL1
+ *
+ * Copyright (C) 2018 HMS Industrial Networks <socketcan at hms-networks.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/can/dev.h>
+#include <linux/usb.h>
+
+#include "ixx_usb_core.h"
+
+#define IXXAT_USB_CLOCK 8000000
+
+#define IXXAT_USB_BUFFER_SIZE_RX 512
+#define IXXAT_USB_BUFFER_SIZE_TX 256
+
+#define IXXAT_USB_MODES (CAN_CTRLMODE_3_SAMPLES | \
+ CAN_CTRLMODE_BERR_REPORTING | \
+ CAN_CTRLMODE_LISTENONLY) \
+
+#define IXXAT_USB_BTMODE_TSM_CL1 0x80
+
+/* bittiming parameters */
+#define IXXAT_USB2CAN_NAME "ixxat_usb"
+
+#define IXXAT_USB2CAN_TSEG1_MIN 1
+#define IXXAT_USB2CAN_TSEG1_MAX 16
+#define IXXAT_USB2CAN_TSEG2_MIN 1
+#define IXXAT_USB2CAN_TSEG2_MAX 8
+#define IXXAT_USB2CAN_SJW_MAX 4
+#define IXXAT_USB2CAN_BRP_MIN 1
+#define IXXAT_USB2CAN_BRP_MAX 64
+#define IXXAT_USB2CAN_BRP_INC 1
+
+/* USB endpoint mapping for CL1 */
+#define IXXAT_USB2CAN_EP1_IN (1 | USB_DIR_IN)
+#define IXXAT_USB2CAN_EP2_IN (2 | USB_DIR_IN)
+#define IXXAT_USB2CAN_EP3_IN (3 | USB_DIR_IN)
+#define IXXAT_USB2CAN_EP4_IN (4 | USB_DIR_IN)
+#define IXXAT_USB2CAN_EP5_IN (5 | USB_DIR_IN)
+
+#define IXXAT_USB2CAN_EP1_OUT (1 | USB_DIR_OUT)
+#define IXXAT_USB2CAN_EP2_OUT (2 | USB_DIR_OUT)
+#define IXXAT_USB2CAN_EP3_OUT (3 | USB_DIR_OUT)
+#define IXXAT_USB2CAN_EP4_OUT (4 | USB_DIR_OUT)
+#define IXXAT_USB2CAN_EP5_OUT (5 | USB_DIR_OUT)
+
+#define IXXAT_USB_CAN_CMD_INIT 0x325
+
+static const struct can_bittiming_const usb2can_bt = {
+ .name = IXXAT_USB2CAN_NAME,
+ .tseg1_min = IXXAT_USB2CAN_TSEG1_MIN,
+ .tseg1_max = IXXAT_USB2CAN_TSEG1_MAX,
+ .tseg2_min = IXXAT_USB2CAN_TSEG2_MIN,
+ .tseg2_max = IXXAT_USB2CAN_TSEG2_MAX,
+ .sjw_max = IXXAT_USB2CAN_SJW_MAX,
+ .brp_min = IXXAT_USB2CAN_BRP_MIN,
+ .brp_max = IXXAT_USB2CAN_BRP_MAX,
+ .brp_inc = IXXAT_USB2CAN_BRP_INC,
+};
+
+static int ixxat_usb_init_ctrl(struct ixxat_usb_device *dev)
+{
+ int ret;
+ u8 data[IXXAT_USB_CMD_BUFFER_SIZE] = { 0 };
+ struct ixxat_usb_init_cmd *cmd = (struct ixxat_usb_init_cmd *)data;
+ struct ixxat_usb_init_cl1_req *req = &cmd->req_cl1;
+ struct ixxat_usb_init_res *res = &cmd->res;
+ u8 opmode = IXXAT_USB_OPMODE_EXTENDED | IXXAT_USB_OPMODE_STANDARD;
+ const struct can_bittiming *bt = &dev->can.bittiming;
+
+ /* Bittiming calculation from kernel
+ * (see can-utils/can-calc-bit-timing.c)
+ */
+ u8 btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6);
+ u8 btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) |
+ (((bt->phase_seg2 - 1) & 0x7) << 4);
+
+ if (dev->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
+ btr1 |= IXXAT_USB_BTMODE_TSM_CL1;
+ if (dev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
+ opmode |= IXXAT_USB_OPMODE_ERRFRAME;
+ if (dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+ opmode |= IXXAT_USB_OPMODE_LISTONLY;
+
+ ixxat_usb_setup_cmd(&req->dal_req, &res->dal_res);
+ req->dal_req.req_size = cpu_to_le32(sizeof(*req));
+ req->dal_req.req_code = cpu_to_le32(IXXAT_USB_CAN_CMD_INIT);
+ req->dal_req.req_port = cpu_to_le16(dev->ctrl_index);
+ req->mode = opmode;
+ req->btr0 = btr0;
+ req->btr1 = btr1;
+
+ ret = ixxat_usb_send_cmd(dev->udev, &req->dal_req);
+ if (ret < 0)
+ return ret;
+
+ ret = ixxat_usb_rcv_cmd(dev->udev, &res->dal_res, dev->ctrl_index);
+ if (ret < 0)
+ return ret;
+
+ return le32_to_cpu(res->dal_res.ret_code);
+}
+
+const struct ixxat_usb_adapter usb2can_cl1 = {
+ .clock = IXXAT_USB_CLOCK,
+ .bt = &usb2can_bt,
+ .btd = NULL,
+ .modes = IXXAT_USB_MODES,
+ .buffer_size_rx = IXXAT_USB_BUFFER_SIZE_RX,
+ .buffer_size_tx = IXXAT_USB_BUFFER_SIZE_TX,
+ .ep_msg_in = {
+ IXXAT_USB2CAN_EP1_IN,
+ IXXAT_USB2CAN_EP2_IN,
+ IXXAT_USB2CAN_EP3_IN,
+ IXXAT_USB2CAN_EP4_IN,
+ IXXAT_USB2CAN_EP5_IN
+ },
+ .ep_msg_out = {
+ IXXAT_USB2CAN_EP1_OUT,
+ IXXAT_USB2CAN_EP2_OUT,
+ IXXAT_USB2CAN_EP3_OUT,
+ IXXAT_USB2CAN_EP4_OUT,
+ IXXAT_USB2CAN_EP5_OUT
+ },
+ .ep_offs = 0,
+ .init_ctrl = ixxat_usb_init_ctrl
+};
diff --git a/ubuntu/ixxat/ixx_usb_cl2.c b/ubuntu/ixxat/ixx_usb_cl2.c
new file mode 100644
index 000000000000..f55e69c85d4f
--- /dev/null
+++ b/ubuntu/ixxat/ixx_usb_cl2.c
@@ -0,0 +1,331 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* CAN driver adapter for IXXAT USB-to-CAN CL2
+ *
+ * Copyright (C) 2018 HMS Industrial Networks <socketcan at hms-networks.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/can/dev.h>
+#include <linux/usb.h>
+
+#include "ixx_usb_core.h"
+
+#define IXXAT_USB_CLOCK 80000000
+
+#define IXXAT_USB_BUFFER_SIZE_RX 512
+#define IXXAT_USB_BUFFER_SIZE_TX 512
+
+#define IXXAT_USB_MODES (CAN_CTRLMODE_3_SAMPLES | \
+ CAN_CTRLMODE_LISTENONLY | \
+ CAN_CTRLMODE_BERR_REPORTING)
+
+#define IXXAT_USB_MODES_FD (IXXAT_USB_MODES | \
+ CAN_CTRLMODE_FD | \
+ CAN_CTRLMODE_FD_NON_ISO)
+
+/* bittiming parameters CL2 */
+#define IXXAT_USB2CAN_NAME "ifi_can"
+
+#define IXXAT_USB2CAN_TSEG1_MIN 1
+#define IXXAT_USB2CAN_TSEG1_MAX 256
+#define IXXAT_USB2CAN_TSEG2_MIN 1
+#define IXXAT_USB2CAN_TSEG2_MAX 256
+#define IXXAT_USB2CAN_SJW_MAX 128
+#define IXXAT_USB2CAN_BRP_MIN 2
+#define IXXAT_USB2CAN_BRP_MAX 513
+#define IXXAT_USB2CAN_BRP_INC 1
+
+#define IXXAT_USB2CAN_TSEG1_MIN_DATA 1
+#define IXXAT_USB2CAN_TSEG1_MAX_DATA 256
+#define IXXAT_USB2CAN_TSEG2_MIN_DATA 1
+#define IXXAT_USB2CAN_TSEG2_MAX_DATA 256
+#define IXXAT_USB2CAN_SJW_MAX_DATA 128
+#define IXXAT_USB2CAN_BRP_MIN_DATA 2
+#define IXXAT_USB2CAN_BRP_MAX_DATA 513
+#define IXXAT_USB2CAN_BRP_INC_DATA 1
+
+/* bittiming parameters CAN IDM100 */
+#define IXXAT_CANIDM_NAME "mcan"
+
+#define IXXAT_CANIDM100_TSEG1_MIN 1
+#define IXXAT_CANIDM100_TSEG1_MAX 64
+#define IXXAT_CANIDM100_TSEG2_MIN 1
+#define IXXAT_CANIDM100_TSEG2_MAX 16
+#define IXXAT_CANIDM100_SJW_MAX 16
+#define IXXAT_CANIDM100_BRP_MIN 1
+#define IXXAT_CANIDM100_BRP_MAX 1024
+#define IXXAT_CANIDM100_BRP_INC 1
+
+#define IXXAT_CANIDM100_TSEG1_MIN_DATA 1
+#define IXXAT_CANIDM100_TSEG1_MAX_DATA 16
+#define IXXAT_CANIDM100_TSEG2_MIN_DATA 1
+#define IXXAT_CANIDM100_TSEG2_MAX_DATA 8
+#define IXXAT_CANIDM100_SJW_MAX_DATA 4
+#define IXXAT_CANIDM100_BRP_MIN_DATA 1
+#define IXXAT_CANIDM100_BRP_MAX_DATA 32
+#define IXXAT_CANIDM100_BRP_INC_DATA 1
+
+/* bittiming parameters CAN IDM101 */
+#define IXXAT_CANIDM_NAME "mcan"
+
+#define IXXAT_CANIDM101_TSEG1_MIN 1
+#define IXXAT_CANIDM101_TSEG1_MAX 256
+#define IXXAT_CANIDM101_TSEG2_MIN 1
+#define IXXAT_CANIDM101_TSEG2_MAX 128
+#define IXXAT_CANIDM101_SJW_MAX 128
+#define IXXAT_CANIDM101_BRP_MIN 1
+#define IXXAT_CANIDM101_BRP_MAX 512
+#define IXXAT_CANIDM101_BRP_INC 1
+
+#define IXXAT_CANIDM101_TSEG1_MIN_DATA 1
+#define IXXAT_CANIDM101_TSEG1_MAX_DATA 32
+#define IXXAT_CANIDM101_TSEG2_MIN_DATA 1
+#define IXXAT_CANIDM101_TSEG2_MAX_DATA 16
+#define IXXAT_CANIDM101_SJW_MAX_DATA 8
+#define IXXAT_CANIDM101_BRP_MIN_DATA 1
+#define IXXAT_CANIDM101_BRP_MAX_DATA 32
+#define IXXAT_CANIDM101_BRP_INC_DATA 1
+
+/* USB endpoint mapping for CL2 */
+#define IXXAT_USB2CAN_EP1_IN (1 | USB_DIR_IN)
+#define IXXAT_USB2CAN_EP2_IN (2 | USB_DIR_IN)
+#define IXXAT_USB2CAN_EP3_IN (3 | USB_DIR_IN)
+#define IXXAT_USB2CAN_EP4_IN (4 | USB_DIR_IN)
+#define IXXAT_USB2CAN_EP5_IN (5 | USB_DIR_IN)
+
+#define IXXAT_USB2CAN_EP1_OUT (1 | USB_DIR_OUT)
+#define IXXAT_USB2CAN_EP2_OUT (2 | USB_DIR_OUT)
+#define IXXAT_USB2CAN_EP3_OUT (3 | USB_DIR_OUT)
+#define IXXAT_USB2CAN_EP4_OUT (4 | USB_DIR_OUT)
+#define IXXAT_USB2CAN_EP5_OUT (5 | USB_DIR_OUT)
+
+/* USB endpoint mapping for CAN IDM */
+#define IXXAT_CANIDM_EP1_IN (2 | USB_DIR_IN)
+#define IXXAT_CANIDM_EP2_IN (4 | USB_DIR_IN)
+#define IXXAT_CANIDM_EP3_IN (6 | USB_DIR_IN)
+#define IXXAT_CANIDM_EP4_IN (8 | USB_DIR_IN)
+#define IXXAT_CANIDM_EP5_IN (10 | USB_DIR_IN)
+
+#define IXXAT_CANIDM_EP1_OUT (1 | USB_DIR_OUT)
+#define IXXAT_CANIDM_EP2_OUT (3 | USB_DIR_OUT)
+#define IXXAT_CANIDM_EP3_OUT (5 | USB_DIR_OUT)
+#define IXXAT_CANIDM_EP4_OUT (7 | USB_DIR_OUT)
+#define IXXAT_CANIDM_EP5_OUT (9 | USB_DIR_OUT)
+
+#define IXXAT_USB_CAN_CMD_INIT 0x337
+
+static const struct can_bittiming_const usb2can_bt = {
+ .name = IXXAT_USB2CAN_NAME,
+ .tseg1_min = IXXAT_USB2CAN_TSEG1_MIN,
+ .tseg1_max = IXXAT_USB2CAN_TSEG1_MAX,
+ .tseg2_min = IXXAT_USB2CAN_TSEG2_MIN,
+ .tseg2_max = IXXAT_USB2CAN_TSEG2_MAX,
+ .sjw_max = IXXAT_USB2CAN_SJW_MAX,
+ .brp_min = IXXAT_USB2CAN_BRP_MIN,
+ .brp_max = IXXAT_USB2CAN_BRP_MAX,
+ .brp_inc = IXXAT_USB2CAN_BRP_INC,
+};
+
+static const struct can_bittiming_const usb2can_btd = {
+ .name = IXXAT_USB2CAN_NAME,
+ .tseg1_min = IXXAT_USB2CAN_TSEG1_MIN_DATA,
+ .tseg1_max = IXXAT_USB2CAN_TSEG1_MAX_DATA,
+ .tseg2_min = IXXAT_USB2CAN_TSEG2_MIN_DATA,
+ .tseg2_max = IXXAT_USB2CAN_TSEG2_MAX_DATA,
+ .sjw_max = IXXAT_USB2CAN_SJW_MAX_DATA,
+ .brp_min = IXXAT_USB2CAN_BRP_MIN_DATA,
+ .brp_max = IXXAT_USB2CAN_BRP_MAX_DATA,
+ .brp_inc = IXXAT_USB2CAN_BRP_INC_DATA,
+};
+
+static const struct can_bittiming_const canidm100_bt = {
+ .name = IXXAT_CANIDM_NAME,
+ .tseg1_min = IXXAT_CANIDM100_TSEG1_MIN,
+ .tseg1_max = IXXAT_CANIDM100_TSEG1_MAX,
+ .tseg2_min = IXXAT_CANIDM100_TSEG2_MIN,
+ .tseg2_max = IXXAT_CANIDM100_TSEG2_MAX,
+ .sjw_max = IXXAT_CANIDM100_SJW_MAX,
+ .brp_min = IXXAT_CANIDM100_BRP_MIN,
+ .brp_max = IXXAT_CANIDM100_BRP_MAX,
+ .brp_inc = IXXAT_CANIDM100_BRP_INC
+};
+
+static const struct can_bittiming_const canidm100_btd = {
+ .name = IXXAT_CANIDM_NAME,
+ .tseg1_min = IXXAT_CANIDM100_TSEG1_MIN_DATA,
+ .tseg1_max = IXXAT_CANIDM100_TSEG1_MAX_DATA,
+ .tseg2_min = IXXAT_CANIDM100_TSEG2_MIN_DATA,
+ .tseg2_max = IXXAT_CANIDM100_TSEG2_MAX_DATA,
+ .sjw_max = IXXAT_CANIDM100_SJW_MAX_DATA,
+ .brp_min = IXXAT_CANIDM100_BRP_MIN_DATA,
+ .brp_max = IXXAT_CANIDM100_BRP_MAX_DATA,
+ .brp_inc = IXXAT_CANIDM100_BRP_INC_DATA
+};
+
+static const struct can_bittiming_const canidm101_bt = {
+ .name = IXXAT_CANIDM_NAME,
+ .tseg1_min = IXXAT_CANIDM101_TSEG1_MIN,
+ .tseg1_max = IXXAT_CANIDM101_TSEG1_MAX,
+ .tseg2_min = IXXAT_CANIDM101_TSEG2_MIN,
+ .tseg2_max = IXXAT_CANIDM101_TSEG2_MAX,
+ .sjw_max = IXXAT_CANIDM101_SJW_MAX,
+ .brp_min = IXXAT_CANIDM101_BRP_MIN,
+ .brp_max = IXXAT_CANIDM101_BRP_MAX,
+ .brp_inc = IXXAT_CANIDM101_BRP_INC
+};
+
+static const struct can_bittiming_const canidm101_btd = {
+ .name = IXXAT_CANIDM_NAME,
+ .tseg1_min = IXXAT_CANIDM101_TSEG1_MIN_DATA,
+ .tseg1_max = IXXAT_CANIDM101_TSEG1_MAX_DATA,
+ .tseg2_min = IXXAT_CANIDM101_TSEG2_MIN_DATA,
+ .tseg2_max = IXXAT_CANIDM101_TSEG2_MAX_DATA,
+ .sjw_max = IXXAT_CANIDM101_SJW_MAX_DATA,
+ .brp_min = IXXAT_CANIDM101_BRP_MIN_DATA,
+ .brp_max = IXXAT_CANIDM101_BRP_MAX_DATA,
+ .brp_inc = IXXAT_CANIDM101_BRP_INC_DATA
+};
+
+static int ixxat_usb_init_ctrl(struct ixxat_usb_device *dev)
+{
+ int ret;
+ u8 data[IXXAT_USB_CMD_BUFFER_SIZE] = { 0 };
+ struct ixxat_usb_init_cmd *cmd = (struct ixxat_usb_init_cmd *)data;
+ struct ixxat_usb_init_cl2_req *req = &cmd->req_cl2;
+ struct ixxat_usb_init_res *res = &cmd->res;
+ u8 opmode = IXXAT_USB_OPMODE_EXTENDED | IXXAT_USB_OPMODE_STANDARD;
+ u8 exmode = 0;
+ u32 btmode = IXXAT_USB_BTMODE_NAT;
+ const struct can_bittiming *bt = &dev->can.bittiming;
+ const struct can_bittiming *btd = &dev->can.data_bittiming;
+
+ if (dev->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
+ btmode = IXXAT_USB_BTMODE_TSM;
+ if (dev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
+ opmode |= IXXAT_USB_OPMODE_ERRFRAME;
+ if (dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+ opmode |= IXXAT_USB_OPMODE_LISTONLY;
+ if ((CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO) & dev->can.ctrlmode)
+ exmode |= IXXAT_USB_EXMODE_EXTDATA | IXXAT_USB_EXMODE_FASTDATA;
+ if (!(CAN_CTRLMODE_FD_NON_ISO & dev->can.ctrlmode) && exmode)
+ exmode |= IXXAT_USB_EXMODE_ISOFD;
+
+ ixxat_usb_setup_cmd(&req->dal_req, &res->dal_res);
+
+ req->dal_req.req_size = cpu_to_le32(sizeof(*req));
+ req->dal_req.req_code = cpu_to_le32(IXXAT_USB_CAN_CMD_INIT);
+ req->dal_req.req_port = cpu_to_le16(dev->ctrl_index);
+ req->opmode = opmode;
+ req->exmode = exmode;
+ req->sdr.mode = cpu_to_le32(btmode);
+ req->sdr.bps = cpu_to_le32(bt->brp);
+ req->sdr.ts1 = cpu_to_le16(bt->prop_seg + bt->phase_seg1);
+ req->sdr.ts2 = cpu_to_le16(bt->phase_seg2);
+ req->sdr.sjw = cpu_to_le16(bt->sjw);
+ req->sdr.tdo = 0;
+
+ if (exmode) {
+ req->fdr.mode = cpu_to_le32(btmode);
+ req->fdr.bps = cpu_to_le32(btd->brp);
+ req->fdr.ts1 = cpu_to_le16(btd->prop_seg + btd->phase_seg1);
+ req->fdr.ts2 = cpu_to_le16(btd->phase_seg2);
+ req->fdr.sjw = cpu_to_le16(btd->sjw);
+ req->fdr.tdo = cpu_to_le16(btd->brp * (btd->phase_seg1 + 1 +
+ btd->prop_seg));
+ }
+
+ ret = ixxat_usb_send_cmd(dev->udev, &req->dal_req);
+ if (ret < 0)
+ return ret;
+
+ ret = ixxat_usb_rcv_cmd(dev->udev, &res->dal_res, dev->ctrl_index);
+ if (ret < 0)
+ return ret;
+
+ return le32_to_cpu(res->dal_res.ret_code);
+}
+
+const struct ixxat_usb_adapter usb2can_cl2 = {
+ .clock = IXXAT_USB_CLOCK,
+ .bt = &usb2can_bt,
+ .btd = &usb2can_btd,
+ .modes = IXXAT_USB_MODES_FD,
+ .buffer_size_rx = IXXAT_USB_BUFFER_SIZE_RX,
+ .buffer_size_tx = IXXAT_USB_BUFFER_SIZE_TX,
+ .ep_msg_in = {
+ IXXAT_USB2CAN_EP1_IN,
+ IXXAT_USB2CAN_EP2_IN,
+ IXXAT_USB2CAN_EP3_IN,
+ IXXAT_USB2CAN_EP4_IN,
+ IXXAT_USB2CAN_EP5_IN
+ },
+ .ep_msg_out = {
+ IXXAT_USB2CAN_EP1_OUT,
+ IXXAT_USB2CAN_EP2_OUT,
+ IXXAT_USB2CAN_EP3_OUT,
+ IXXAT_USB2CAN_EP4_OUT,
+ IXXAT_USB2CAN_EP5_OUT
+ },
+ .ep_offs = 1,
+ .init_ctrl = ixxat_usb_init_ctrl
+};
+
+const struct ixxat_usb_adapter can_idm100 = {
+ .clock = IXXAT_USB_CLOCK,
+ .bt = &canidm100_bt,
+ .btd = &canidm100_btd,
+ .modes = IXXAT_USB_MODES,
+ .buffer_size_rx = IXXAT_USB_BUFFER_SIZE_RX,
+ .buffer_size_tx = IXXAT_USB_BUFFER_SIZE_TX,
+ .ep_msg_in = {
+ IXXAT_CANIDM_EP1_IN,
+ IXXAT_CANIDM_EP2_IN,
+ IXXAT_CANIDM_EP3_IN,
+ IXXAT_CANIDM_EP4_IN,
+ IXXAT_CANIDM_EP5_IN
+ },
+ .ep_msg_out = {
+ IXXAT_CANIDM_EP1_OUT,
+ IXXAT_CANIDM_EP2_OUT,
+ IXXAT_CANIDM_EP3_OUT,
+ IXXAT_CANIDM_EP4_OUT,
+ IXXAT_CANIDM_EP5_OUT
+ },
+ .ep_offs = 0,
+ .init_ctrl = ixxat_usb_init_ctrl
+};
+
+const struct ixxat_usb_adapter can_idm101 = {
+ .clock = IXXAT_USB_CLOCK,
+ .bt = &canidm101_bt,
+ .btd = &canidm101_btd,
+ .modes = IXXAT_USB_MODES_FD,
+ .buffer_size_rx = IXXAT_USB_BUFFER_SIZE_RX,
+ .buffer_size_tx = IXXAT_USB_BUFFER_SIZE_TX,
+ .ep_msg_in = {
+ IXXAT_CANIDM_EP1_IN,
+ IXXAT_CANIDM_EP2_IN,
+ IXXAT_CANIDM_EP3_IN,
+ IXXAT_CANIDM_EP4_IN,
+ IXXAT_CANIDM_EP5_IN
+ },
+ .ep_msg_out = {
+ IXXAT_CANIDM_EP1_OUT,
+ IXXAT_CANIDM_EP2_OUT,
+ IXXAT_CANIDM_EP3_OUT,
+ IXXAT_CANIDM_EP4_OUT,
+ IXXAT_CANIDM_EP5_OUT
+ },
+ .ep_offs = 0,
+ .init_ctrl = ixxat_usb_init_ctrl
+};
diff --git a/ubuntu/ixxat/ixx_usb_core.c b/ubuntu/ixxat/ixx_usb_core.c
index d258b6e46453..5fba0a1480a5 100644
--- a/ubuntu/ixxat/ixx_usb_core.c
+++ b/ubuntu/ixxat/ixx_usb_core.c
@@ -1,9 +1,8 @@
-/*
- * CAN driver for IXXAT USB-to-CAN V2 adapters
- *
- * Copyright (C) 2003-2014 Michael Hengler IXXAT Automation GmbH
+// SPDX-License-Identifier: GPL-2.0
+
+/* CAN driver for IXXAT USB-to-CAN
*
- * Based on code originally by pcan_usb_core
+ * Copyright (C) 2018 HMS Industrial Networks <socketcan at hms-networks.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published
@@ -14,265 +13,775 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
-#include <linux/init.h>
-#include <linux/signal.h>
-#include <linux/slab.h>
+
#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/usb.h>
-#include <linux/errno.h>
-#include <linux/skbuff.h>
-#include <linux/types.h>
-#include <linux/can.h>
+#include <linux/kernel.h>
#include <linux/can/dev.h>
-#include <linux/can/error.h>
-#include <asm-generic/errno.h>
+#include <linux/kthread.h>
+#include <linux/usb.h>
#include "ixx_usb_core.h"
-MODULE_AUTHOR("Michael Hengler <mhengler at ixxat.de>");
-MODULE_DESCRIPTION("CAN driver for IXXAT USB-to-CAN V2 adapters");
+MODULE_AUTHOR("Marcel Schmidt <socketcan at hms-networks.de>");
+MODULE_DESCRIPTION("CAN driver for IXXAT USB-to-CAN FD adapters");
MODULE_LICENSE("GPL v2");
-#define IXXAT_USB_DRIVER_NAME "ixx_usb"
-
-#define IXXAT_USB_BUS_CAN 1 // CAN
-#define IXXAT_USB_BUS_TYPE(BusCtrl) (u8) ( ((BusCtrl) >> 8) & 0x00FF )
-#define IXXAT_USB_VENDOR_ID 0x08d8
-
-#define IXXAT_USB_STATE_CONNECTED 0x00000001
-#define IXXAT_USB_STATE_STARTED 0x00000002
-
-
/* Table of devices that work with this driver */
-static struct usb_device_id ixxat_usb_table[] = {
- {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_CAN_V2_COMPACT_PRODUCT_ID)},
- {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_CAN_V2_EMBEDDED_PRODUCT_ID)},
- {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_CAN_V2_PROFESSIONAL_PRODUCT_ID)},
- {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_CAN_V2_AUTOMOTIVE_PRODUCT_ID)},
- {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_LIN_V2_PRODUCT_ID)},
- {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_KLINE_V2_PRODUCT_ID)},
-#ifdef CANFD_CAPABLE
- {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_CAN_FD_AUTOMOTIVE_PRODUCT_ID)},
- {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_CAN_FD_COMPACT_PRODUCT_ID)},
- {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_CAN_FD_PROFESSIONAL_PRODUCT_ID)},
- {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_CAN_FD_PCIE_MINI_PRODUCT_ID)},
- {USB_DEVICE(IXXAT_USB_VENDOR_ID, USB_TO_CAR_ID)},
- {USB_DEVICE(IXXAT_USB_VENDOR_ID, DELL_EDGE_GW3002_PRODUCT_ID)},
-#endif
- {} /* Terminating entry */
+static const struct usb_device_id ixxat_usb_table[] = {
+ { USB_DEVICE(IXXAT_USB_VENDOR_ID, USB2CAN_COMPACT_PRODUCT_ID) },
+ { USB_DEVICE(IXXAT_USB_VENDOR_ID, USB2CAN_EMBEDDED_PRODUCT_ID) },
+ { USB_DEVICE(IXXAT_USB_VENDOR_ID, USB2CAN_PROFESSIONAL_PRODUCT_ID) },
+ { USB_DEVICE(IXXAT_USB_VENDOR_ID, USB2CAN_AUTOMOTIVE_PRODUCT_ID) },
+ { USB_DEVICE(IXXAT_USB_VENDOR_ID, USB2CAN_FD_COMPACT_PRODUCT_ID) },
+ { USB_DEVICE(IXXAT_USB_VENDOR_ID, USB2CAN_FD_PROFESSIONAL_PRODUCT_ID) },
+ { USB_DEVICE(IXXAT_USB_VENDOR_ID, USB2CAN_FD_AUTOMOTIVE_PRODUCT_ID) },
+ { USB_DEVICE(IXXAT_USB_VENDOR_ID, USB2CAN_FD_PCIE_MINI_PRODUCT_ID) },
+ { USB_DEVICE(IXXAT_USB_VENDOR_ID, USB2CAR_PRODUCT_ID) },
+ { USB_DEVICE(IXXAT_USB_VENDOR_ID, CAN_IDM100_PRODUCT_ID) },
+ { USB_DEVICE(IXXAT_USB_VENDOR_ID, CAN_IDM101_PRODUCT_ID) },
+ { } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, ixxat_usb_table);
-/* List of supported IXX-USB adapters (NULL terminated list) */
-static struct ixx_usb_adapter *ixx_usb_adapters_list[] = {
- &usb_to_can_v2_compact,
- &usb_to_can_v2_automotive,
- &usb_to_can_v2_embedded,
- &usb_to_can_v2_professional,
- &usb_to_can_v2_low_speed,
- &usb_to_can_v2_extended,
-#ifdef CANFD_CAPABLE
- &usb_to_can_fd_automotive,
- &usb_to_can_fd_compact,
- &usb_to_can_fd_professional,
- &usb_to_can_fd_pcie_mini,
- &usb_to_car,
- &dell_edge_gw3002,
-#endif
- NULL,
-};
+void ixxat_usb_setup_cmd(struct ixxat_usb_dal_req *req,
+ struct ixxat_usb_dal_res *res)
+{
+ req->req_size = sizeof(*req);
+ req->req_port = 0xffff;
+ req->req_socket = 0xffff;
+ req->req_code = 0;
+
+ res->res_size = sizeof(*res);
+ res->ret_size = 0;
+ res->ret_code = 0xffffffff;
+}
-/*
- * dump memory
- */
-#define DUMP_WIDTH 16
-void ixxat_dump_mem(char *prompt, void *p, int l)
+int ixxat_usb_send_cmd(struct usb_device *dev,
+ struct ixxat_usb_dal_req *dal_req)
{
- pr_info("%s dumping %s (%d bytes):\n",
- IXXAT_USB_DRIVER_NAME, prompt ? prompt : "memory", l);
- print_hex_dump(KERN_INFO, IXXAT_USB_DRIVER_NAME " ", DUMP_PREFIX_NONE,
- DUMP_WIDTH, 1, p, l, false);
+ int ret = 0;
+ int i;
+ u16 size = le32_to_cpu(dal_req->req_size) +
+ sizeof(struct ixxat_usb_dal_res);
+ u16 value = le16_to_cpu(dal_req->req_port);
+ u8 request = 0xff;
+ u8 requesttype = USB_TYPE_VENDOR | USB_DIR_OUT;
+ u8 *buf = kmalloc(size, GFP_KERNEL);
+
+ if (!buf)
+ return -ENOMEM;
+
+ memcpy(buf, dal_req, size);
+
+ for (i = 0; i < IXXAT_USB_MAX_COM_REQ; ++i) {
+ const int to = msecs_to_jiffies(IXXAT_USB_MSG_TIMEOUT);
+
+ ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request,
+ requesttype, value, 0, buf, size, to);
+
+ if (ret < 0)
+ msleep(IXXAT_USB_MSG_CYCLE);
+ else
+ break;
+ }
+
+ kfree(buf);
+
+ if (ret < 0)
+ dev_err(&dev->dev, "Error %d: Sending command failure\n", ret);
+
+ return ret;
}
-static void ixxat_usb_add_us(struct timeval *tv, u64 delta_us)
+int ixxat_usb_rcv_cmd(struct usb_device *dev,
+ struct ixxat_usb_dal_res *dal_res, int value)
{
- /* number of s. to add to final time */
- u32 delta_s = div_u64(delta_us, 1000000);
+ int ret;
+ int res_size = 0;
+ int i;
+ int size_to_read = le32_to_cpu(dal_res->res_size);
+ u8 req = 0xff;
+ u8 req_type = USB_TYPE_VENDOR | USB_DIR_IN;
+ u8 *buf = kmalloc(size_to_read, GFP_KERNEL);
+
+ if (!buf)
+ return -ENOMEM;
+
+ for (i = 0; i < IXXAT_USB_MAX_COM_REQ; ++i) {
+ const int to = msecs_to_jiffies(IXXAT_USB_MSG_TIMEOUT);
+ void *data = buf + (u8)res_size;
+ const int size = size_to_read - res_size;
+
+ ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ req, req_type, value, 0,
+ data, size, to);
+
+ if (ret < 0) {
+ msleep(IXXAT_USB_MSG_CYCLE);
+ continue;
+ }
+
+ res_size += ret;
+ if (res_size < size_to_read)
+ msleep(IXXAT_USB_MSG_CYCLE);
+ else
+ break;
+ }
- delta_us -= delta_s * 1000000;
+ if (res_size != size_to_read)
+ ret = -EBADMSG;
- tv->tv_usec += delta_us;
- if (tv->tv_usec >= 1000000) {
- tv->tv_usec -= 1000000;
- delta_s++;
+ if (ret < 0) {
+ dev_err(&dev->dev, "Error %d: Receiving command failure\n",
+ ret);
+ kfree(buf);
+ return ret;
}
- tv->tv_sec += delta_s;
+
+ memcpy(dal_res, buf, size_to_read);
+ kfree(buf);
+
+ return ret;
+}
+
+static void ixxat_usb_update_ts_now(struct ixxat_usb_device *dev, u32 ts_now)
+{
+ u32 *ts_dev = &dev->time_ref.ts_dev_0;
+ ktime_t *kt_host = &dev->time_ref.kt_host_0;
+ u64 timebase = (u64)0x00000000FFFFFFFF - (u64)(*ts_dev) + (u64)ts_now;
+
+ *kt_host = ktime_add_us(*kt_host, timebase);
+ *ts_dev = ts_now;
}
-void ixxat_usb_get_ts_tv(struct ixx_usb_device *dev, u32 ts, ktime_t *k_time)
+static void ixxat_usb_get_ts_tv(struct ixxat_usb_device *dev, u32 ts,
+ ktime_t *k_time)
{
- struct timeval tv = dev->time_ref.tv_host_0;
+ ktime_t tmp_time = dev->time_ref.kt_host_0;
- if (ts < dev->time_ref.ts_dev_last) {
+ if (ts < dev->time_ref.ts_dev_last)
ixxat_usb_update_ts_now(dev, ts);
- }
dev->time_ref.ts_dev_last = ts;
- ixxat_usb_add_us(&tv, ts - dev->time_ref.ts_dev_0);
+ tmp_time = ktime_add_us(tmp_time, ts - dev->time_ref.ts_dev_0);
+
+ if (k_time)
+ *k_time = tmp_time;
+}
+
+static void ixxat_usb_set_ts_now(struct ixxat_usb_device *dev, u32 ts_now)
+{
+ dev->time_ref.ts_dev_0 = ts_now;
+ dev->time_ref.kt_host_0 = ktime_get_real();
+ dev->time_ref.ts_dev_last = ts_now;
+}
+
+static int ixxat_usb_get_dev_caps(struct usb_device *dev,
+ struct ixxat_dev_caps *dev_caps)
+{
+ int i;
+ int ret;
+ u8 data[IXXAT_USB_CMD_BUFFER_SIZE] = { 0 };
+ struct ixxat_usb_caps_cmd *cmd = (struct ixxat_usb_caps_cmd *)data;
+ struct ixxat_usb_caps_req *req = &cmd->req;
+ struct ixxat_usb_caps_res *res = &cmd->res;
+
+ ixxat_usb_setup_cmd(&req->dal_req, &res->dal_res);
+ req->dal_req.req_code = cpu_to_le32(IXXAT_USB_BRD_CMD_GET_DEVCAPS);
+ res->dal_res.res_size = cpu_to_le32(sizeof(*res));
+
+ ret = ixxat_usb_send_cmd(dev, &req->dal_req);
+ if (ret < 0)
+ return ret;
+
+ ret = ixxat_usb_rcv_cmd(dev, &res->dal_res, 0xffff);
+ if (ret < 0)
+ return ret;
+
+ dev_caps->bus_ctrl_count = le16_to_cpu(res->dev_caps.bus_ctrl_count);
+ for (i = 0; i < dev_caps->bus_ctrl_count; ++i) {
+ u16 type = le16_to_cpu(res->dev_caps.bus_ctrl_types[i]);
- if(k_time)
- *k_time = timeval_to_ktime(tv);
+ dev_caps->bus_ctrl_types[i] = type;
+ }
+
+ return 0;
}
-void ixxat_usb_update_ts_now(struct ixx_usb_device *dev, u32 hw_time_base)
+static int ixxat_usb_get_dev_info(struct ixxat_usb_device *dev,
+ struct ixxat_dev_info *dev_info)
{
- u64 timebase;
+ int ret;
+ u8 data[IXXAT_USB_CMD_BUFFER_SIZE] = { 0 };
+ struct ixxat_usb_info_cmd *cmd = (struct ixxat_usb_info_cmd *)data;
+ struct ixxat_usb_info_req *req = &cmd->req;
+ struct ixxat_usb_info_res *res = &cmd->res;
+
+ ixxat_usb_setup_cmd(&req->dal_req, &res->dal_res);
+ req->dal_req.req_code = cpu_to_le32(IXXAT_USB_BRD_CMD_GET_DEVINFO);
+ res->dal_res.res_size = cpu_to_le32(sizeof(*res));
+
+ ret = ixxat_usb_send_cmd(dev->udev, &req->dal_req);
+ if (ret < 0)
+ return ret;
+
+ ret = ixxat_usb_rcv_cmd(dev->udev, &res->dal_res, 0xffff);
+ if (ret < 0)
+ return ret;
+
+ if (dev_info) {
+ const size_t id_size = sizeof(res->info.device_id);
+ const size_t nm_size = sizeof(res->info.device_name);
+ const u32 fpgav = le32_to_cpu(res->info.device_fpga_version);
+ const u16 devv = le16_to_cpu(res->info.device_version);
+
+ memcpy(dev_info->device_id, &res->info.device_id, id_size);
+ memcpy(dev_info->device_name, &res->info.device_name, nm_size);
+ dev_info->device_fpga_version = fpgav;
+ dev_info->device_version = devv;
+ }
- timebase = (u64)0x00000000FFFFFFFF - (u64)dev->time_ref.ts_dev_0 + (u64)hw_time_base;
+ return le32_to_cpu(res->dal_res.ret_code);
+}
- ixxat_usb_add_us(&dev->time_ref.tv_host_0, timebase);
+static int ixxat_usb_start_ctrl(struct ixxat_usb_device *dev, u32 *time_ref)
+{
+ int ret;
+ u8 data[IXXAT_USB_CMD_BUFFER_SIZE] = { 0 };
+ struct ixxat_usb_start_cmd *cmd = (struct ixxat_usb_start_cmd *)data;
+ struct ixxat_usb_start_req *req = &cmd->req;
+ struct ixxat_usb_start_res *res = &cmd->res;
+
+ ixxat_usb_setup_cmd(&req->dal_req, &res->dal_res);
+ req->dal_req.req_code = cpu_to_le32(IXXAT_USB_CAN_CMD_START);
+ req->dal_req.req_port = cpu_to_le16(dev->ctrl_index);
+ res->dal_res.res_size = cpu_to_le32(sizeof(*res));
+ res->start_time = 0;
+
+ ret = ixxat_usb_send_cmd(dev->udev, &req->dal_req);
+ if (ret < 0)
+ return ret;
+
+ ret = ixxat_usb_rcv_cmd(dev->udev, &res->dal_res, dev->ctrl_index);
+ if (ret < 0)
+ return ret;
+
+ if (time_ref)
+ *time_ref = le32_to_cpu(res->start_time);
+
+ return le32_to_cpu(res->dal_res.ret_code);
+}
- dev->time_ref.ts_dev_0 = hw_time_base;
+static int ixxat_usb_stop_ctrl(struct ixxat_usb_device *dev)
+{
+ int ret;
+ u8 data[IXXAT_USB_CMD_BUFFER_SIZE] = { 0 };
+ struct ixxat_usb_stop_cmd *cmd = (struct ixxat_usb_stop_cmd *)data;
+ struct ixxat_usb_stop_req *req = &cmd->req;
+ struct ixxat_usb_stop_res *res = &cmd->res;
+
+ ixxat_usb_setup_cmd(&req->dal_req, &res->dal_res);
+ req->dal_req.req_size = cpu_to_le32(sizeof(*req));
+ req->dal_req.req_code = cpu_to_le32(IXXAT_USB_CAN_CMD_STOP);
+ req->dal_req.req_port = cpu_to_le16(dev->ctrl_index);
+ req->action = cpu_to_le32(IXXAT_USB_STOP_ACTION_CLEARALL);
+
+ ret = ixxat_usb_send_cmd(dev->udev, &req->dal_req);
+ if (ret < 0)
+ return ret;
+
+ ret = ixxat_usb_rcv_cmd(dev->udev, &res->dal_res, dev->ctrl_index);
+ if (ret < 0)
+ return ret;
+
+ ret = le32_to_cpu(res->dal_res.ret_code);
+ if (!ret)
+ dev->can.state = CAN_STATE_STOPPED;
+
+ return ret;
}
-void ixxat_usb_set_ts_now(struct ixx_usb_device *dev, u32 hw_time_base)
+static int ixxat_usb_power_ctrl(struct usb_device *dev, u8 mode)
{
- dev->time_ref.ts_dev_0 = hw_time_base;
- do_gettimeofday(&dev->time_ref.tv_host_0);
- dev->time_ref.ts_dev_last = hw_time_base;
+ int ret;
+ u8 data[IXXAT_USB_CMD_BUFFER_SIZE] = { 0 };
+ struct ixxat_usb_power_cmd *cmd = (struct ixxat_usb_power_cmd *)data;
+ struct ixxat_usb_power_req *req = &cmd->req;
+ struct ixxat_usb_power_res *res = &cmd->res;
+
+ ixxat_usb_setup_cmd(&req->dal_req, &res->dal_res);
+ req->dal_req.req_size = cpu_to_le32(sizeof(*req));
+ req->dal_req.req_code = cpu_to_le32(IXXAT_USB_BRD_CMD_POWER);
+ req->mode = mode;
+
+ ret = ixxat_usb_send_cmd(dev, &req->dal_req);
+ if (ret < 0)
+ return ret;
+
+ ret = ixxat_usb_rcv_cmd(dev, &res->dal_res, 0xffff);
+ if (ret < 0)
+ return ret;
+
+ return le32_to_cpu(res->dal_res.ret_code);
}
-/*
- * callback for bulk Rx urb
- */
-static void ixxat_usb_read_bulk_callback(struct urb *urb)
+static int ixxat_usb_reset_ctrl(struct ixxat_usb_device *dev)
{
- struct ixx_usb_device *dev = urb->context;
- struct net_device *netdev;
- int err;
+ int ret;
+ u8 data[IXXAT_USB_CMD_BUFFER_SIZE] = { 0 };
+ struct ixxat_usb_dal_cmd *cmd = (struct ixxat_usb_dal_cmd *)data;
+ struct ixxat_usb_dal_req *req = &cmd->req;
+ struct ixxat_usb_dal_res *res = &cmd->res;
- netdev = dev->netdev;
+ ixxat_usb_setup_cmd(req, res);
+ req->req_code = cpu_to_le32(IXXAT_USB_CAN_CMD_RESET);
+ req->req_port = cpu_to_le16(dev->ctrl_index);
- if (!netif_device_present(netdev))
- return;
+ ret = ixxat_usb_send_cmd(dev->udev, req);
+ if (ret < 0)
+ return ret;
- /* check reception status */
- switch (urb->status) {
- case 0:
- /* success */
+ ret = ixxat_usb_rcv_cmd(dev->udev, res, dev->ctrl_index);
+ if (ret < 0)
+ return ret;
+
+ return le32_to_cpu(res->ret_code);
+}
+
+static void ixxat_usb_unlink_all_urbs(struct ixxat_usb_device *dev)
+{
+ usb_kill_anchored_urbs(&dev->rx_submitted);
+ usb_kill_anchored_urbs(&dev->tx_submitted);
+ atomic_set(&dev->active_tx_urbs, 0);
+}
+
+static int ixxat_usb_set_mode(struct net_device *netdev, enum can_mode mode)
+{
+ struct ixxat_usb_device *dev = netdev_priv(netdev);
+ u32 time_ref;
+
+ switch (mode) {
+ case CAN_MODE_START:
+ ixxat_usb_stop_ctrl(dev);
+ ixxat_usb_start_ctrl(dev, &time_ref);
+ break;
+ case CAN_MODE_STOP:
+ case CAN_MODE_SLEEP:
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int ixxat_usb_get_berr_counter(const struct net_device *netdev,
+ struct can_berr_counter *bec)
+{
+ struct ixxat_usb_device *dev = netdev_priv(netdev);
+
+ *bec = dev->bec;
+ return 0;
+}
+
+static int ixxat_usb_handle_canmsg(struct ixxat_usb_device *dev,
+ struct ixxat_can_msg *rx)
+{
+ struct net_device *netdev = dev->netdev;
+ union can_frame_union cfu;
+ struct sk_buff *skb;
+ const u32 flags = le32_to_cpu(rx->base.flags);
+ const u8 dlc = IXXAT_USB_DECODE_DLC(flags);
+
+ if (flags & IXXAT_USB_FDMSG_FLAGS_EDL)
+ skb = alloc_canfd_skb(netdev, &cfu.cfd);
+ else
+ skb = alloc_can_skb(netdev, &cfu.cf);
+
+ if (!skb)
+ return -ENOMEM;
+
+ if (flags & IXXAT_USB_FDMSG_FLAGS_EDL) {
+ if (flags & IXXAT_USB_FDMSG_FLAGS_FDR)
+ cfu.cfd->flags |= CANFD_BRS;
+
+ if (flags & IXXAT_USB_FDMSG_FLAGS_ESI)
+ cfu.cfd->flags |= CANFD_ESI;
+
+ cfu.cfd->len = can_dlc2len(get_canfd_dlc(dlc));
+ } else {
+ cfu.cf->can_dlc = get_can_dlc(dlc);
+ }
+
+ if (flags & IXXAT_USB_MSG_FLAGS_OVR) {
+ netdev->stats.rx_over_errors++;
+ netdev->stats.rx_errors++;
+ netdev_err(netdev, "Error: Message overflow\n");
+ }
+
+ cfu.cf->can_id = le32_to_cpu(rx->base.msg_id);
+
+ if (flags & IXXAT_USB_MSG_FLAGS_EXT)
+ cfu.cf->can_id |= CAN_EFF_FLAG;
+
+ if (flags & IXXAT_USB_MSG_FLAGS_RTR) {
+ cfu.cf->can_id |= CAN_RTR_FLAG;
+ } else {
+ if (dev->adapter == &usb2can_cl1)
+ memcpy(cfu.cfd->data, rx->cl1.data, cfu.cfd->len);
+ else
+ memcpy(cfu.cfd->data, rx->cl2.data, cfu.cfd->len);
+ }
+
+ ixxat_usb_get_ts_tv(dev, le32_to_cpu(rx->base.time), &skb->tstamp);
+
+ netdev->stats.rx_packets++;
+ netdev->stats.rx_bytes += cfu.cfd->len;
+ netif_rx(skb);
+
+ return 0;
+}
+
+static int ixxat_usb_handle_status(struct ixxat_usb_device *dev,
+ struct ixxat_can_msg *rx)
+{
+ struct net_device *netdev = dev->netdev;
+ struct can_frame *can_frame;
+ struct sk_buff *skb = alloc_can_err_skb(netdev, &can_frame);
+ enum can_state new_state = CAN_STATE_ERROR_ACTIVE;
+ u32 raw_status;
+
+ if (dev->adapter == &usb2can_cl1)
+ raw_status = le32_to_cpu(*(__le32 *)(rx->cl1.data));
+ else
+ raw_status = le32_to_cpu(*(__le32 *)(rx->cl2.data));
+
+ if (!skb)
+ return -ENOMEM;
+
+ if (raw_status == IXXAT_USB_CAN_STATUS_OK) {
+ dev->can.state = CAN_STATE_ERROR_ACTIVE;
+ can_frame->can_id |= CAN_ERR_CRTL;
+ can_frame->data[1] |= CAN_ERR_CRTL_ACTIVE;
+ } else if (raw_status & IXXAT_USB_CAN_STATUS_BUSOFF) {
+ can_frame->can_id |= CAN_ERR_BUSOFF;
+ dev->can.can_stats.bus_off++;
+ new_state = CAN_STATE_BUS_OFF;
+ can_bus_off(netdev);
+ } else {
+ if (raw_status & IXXAT_USB_CAN_STATUS_ERRLIM) {
+ can_frame->can_id |= CAN_ERR_CRTL;
+ can_frame->data[1] |= CAN_ERR_CRTL_TX_WARNING;
+ can_frame->data[1] |= CAN_ERR_CRTL_RX_WARNING;
+ dev->can.can_stats.error_warning++;
+ new_state = CAN_STATE_ERROR_WARNING;
+ }
+
+ if (raw_status & IXXAT_USB_CAN_STATUS_ERR_PAS) {
+ can_frame->can_id |= CAN_ERR_CRTL;
+ can_frame->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
+ can_frame->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
+ dev->can.can_stats.error_passive++;
+ new_state = CAN_STATE_ERROR_PASSIVE;
+ }
+
+ if (raw_status & IXXAT_USB_CAN_STATUS_OVERRUN) {
+ can_frame->can_id |= CAN_ERR_CRTL;
+ can_frame->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW;
+ new_state = CAN_STATE_MAX;
+ }
+ }
+
+ if (new_state == CAN_STATE_ERROR_ACTIVE) {
+ dev->bec.txerr = 0;
+ dev->bec.rxerr = 0;
+ }
+
+ if (new_state != CAN_STATE_MAX)
+ dev->can.state = new_state;
+
+ netdev->stats.rx_packets++;
+ netdev->stats.rx_bytes += can_frame->can_dlc;
+ netif_rx(skb);
+
+ return 0;
+}
+
+static int ixxat_usb_handle_error(struct ixxat_usb_device *dev,
+ struct ixxat_can_msg *rx)
+{
+ struct net_device *netdev = dev->netdev;
+ struct can_frame *can_frame;
+ struct sk_buff *skb = alloc_can_err_skb(netdev, &can_frame);
+ u8 raw_error;
+
+ if (dev->adapter == &usb2can_cl1) {
+ raw_error = rx->cl1.data[0];
+ dev->bec.rxerr = rx->cl1.data[3];
+ dev->bec.txerr = rx->cl1.data[4];
+ } else {
+ raw_error = rx->cl2.data[0];
+ dev->bec.rxerr = rx->cl2.data[3];
+ dev->bec.txerr = rx->cl2.data[4];
+ }
+
+ if (dev->can.state == CAN_STATE_BUS_OFF)
+ return 0;
+
+ if (!skb)
+ return -ENOMEM;
+
+ switch (raw_error) {
+ case IXXAT_USB_CAN_ERROR_ACK:
+ can_frame->can_id |= CAN_ERR_ACK;
+ netdev->stats.tx_errors++;
+ break;
+ case IXXAT_USB_CAN_ERROR_BIT:
+ can_frame->can_id |= CAN_ERR_PROT;
+ can_frame->data[2] |= CAN_ERR_PROT_BIT;
+ netdev->stats.rx_errors++;
+ break;
+ case IXXAT_USB_CAN_ERROR_CRC:
+ can_frame->can_id |= CAN_ERR_PROT;
+ can_frame->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ;
+ netdev->stats.rx_errors++;
+ break;
+ case IXXAT_USB_CAN_ERROR_FORM:
+ can_frame->can_id |= CAN_ERR_PROT;
+ can_frame->data[2] |= CAN_ERR_PROT_FORM;
+ netdev->stats.rx_errors++;
+ break;
+ case IXXAT_USB_CAN_ERROR_STUFF:
+ can_frame->can_id |= CAN_ERR_PROT;
+ can_frame->data[2] |= CAN_ERR_PROT_STUFF;
+ netdev->stats.rx_errors++;
+ break;
+ default:
+ can_frame->can_id |= CAN_ERR_PROT;
+ can_frame->data[2] |= CAN_ERR_PROT_UNSPEC;
+ netdev->stats.rx_errors++;
+ break;
+ }
+
+ netdev->stats.rx_packets++;
+ netdev->stats.rx_bytes += can_frame->can_dlc;
+ netif_rx(skb);
+
+ return 0;
+}
+
+static int ixxat_usb_decode_buf(struct urb *urb)
+{
+ struct ixxat_usb_device *dev = urb->context;
+ struct net_device *netdev = dev->netdev;
+ struct ixxat_can_msg *can_msg;
+ int ret = 0;
+ u32 msg_end = urb->actual_length;
+ u32 read_size = 0;
+ u8 *data = urb->transfer_buffer;
+
+ while (msg_end > 0) {
+ u8 msg_type;
+
+ can_msg = (struct ixxat_can_msg *)&data[read_size];
+
+ if (!can_msg || !can_msg->base.size) {
+ ret = -ENOTSUPP;
+ netdev_err(netdev, "Error %d: Unsupported usb msg\n",
+ ret);
break;
+ }
+
+ if ((read_size + can_msg->base.size + 1) > urb->actual_length) {
+ ret = -EBADMSG;
+ netdev_err(netdev,
+ "Error %d: Usb rx-buffer size unknown\n",
+ ret);
+ break;
+ }
- case -EILSEQ:
- case -ENOENT:
- case -ECONNRESET:
- case -ESHUTDOWN:
- return;
+ msg_type = le32_to_cpu(can_msg->base.flags);
+ msg_type &= IXXAT_USB_MSG_FLAGS_TYPE;
+ switch (msg_type) {
+ case IXXAT_USB_CAN_DATA:
+ ret = ixxat_usb_handle_canmsg(dev, can_msg);
+ if (ret < 0)
+ goto fail;
+ break;
+ case IXXAT_USB_CAN_STATUS:
+ ret = ixxat_usb_handle_status(dev, can_msg);
+ if (ret < 0)
+ goto fail;
+ break;
+ case IXXAT_USB_CAN_ERROR:
+ ret = ixxat_usb_handle_error(dev, can_msg);
+ if (ret < 0)
+ goto fail;
+ break;
+ case IXXAT_USB_CAN_TIMEOVR:
+ ixxat_usb_get_ts_tv(dev, can_msg->base.time, NULL);
+ break;
+ case IXXAT_USB_CAN_INFO:
+ case IXXAT_USB_CAN_WAKEUP:
+ case IXXAT_USB_CAN_TIMERST:
+ break;
default:
- if (net_ratelimit())
- netdev_err(netdev, "Rx urb aborted (%d)\n",
- urb->status);
- goto resubmit_urb;
+ netdev_err(netdev,
+ "Unhandled rec type 0x%02x (%d): ignored\n",
+ msg_type, msg_type);
+ break;
+ }
+
+ read_size += (can_msg->base.size + 1);
+ msg_end -= (can_msg->base.size + 1);
}
- /* protect from any incoming empty msgs */
- if ((urb->actual_length > 0) && (dev->adapter->dev_decode_buf)) {
- /* handle these kinds of msgs only if _start callback called */
- if (dev->state & IXXAT_USB_STATE_STARTED)
- err = dev->adapter->dev_decode_buf(dev, urb);
+fail:
+ if (ret < 0)
+ netdev_err(netdev, "Error %d: Buffer decoding failed\n", ret);
+
+ return ret;
+}
+
+static void ixxat_usb_read_bulk(struct urb *urb)
+{
+ struct ixxat_usb_device *dev = urb->context;
+ const struct ixxat_usb_adapter *adapter = dev->adapter;
+ struct net_device *netdev = dev->netdev;
+ struct usb_device *udev = dev->udev;
+ int ret;
+
+ if (!netif_device_present(netdev))
+ return;
+
+ switch (urb->status) {
+ case 0: /* success */
+ break;
+ case -EPROTO:
+ case -EILSEQ:
+ case -ENOENT:
+ case -ECONNRESET:
+ case -ESHUTDOWN:
+ return;
+ default:
+ netdev_err(netdev, "Rx urb aborted /(%d)\n", urb->status);
+ goto resubmit_urb;
}
-resubmit_urb: usb_fill_bulk_urb(urb, dev->udev,
- usb_rcvbulkpipe(dev->udev, dev->ep_msg_in),
- urb->transfer_buffer, dev->adapter->rx_buffer_size,
- ixxat_usb_read_bulk_callback, dev);
+ if (urb->actual_length > 0)
+ if (dev->state & IXXAT_USB_STATE_STARTED)
+ ret = ixxat_usb_decode_buf(urb);
+
+resubmit_urb:
+ usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, dev->ep_msg_in),
+ urb->transfer_buffer, adapter->buffer_size_rx,
+ ixxat_usb_read_bulk, dev);
- usb_anchor_urb(urb, &dev->rx_submitted);
- err = usb_submit_urb(urb, GFP_ATOMIC);
- if (!err)
- return;
+ usb_anchor_urb(urb, &dev->rx_submitted);
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret == 0)
+ return;
- usb_unanchor_urb(urb);
+ usb_unanchor_urb(urb);
- if (err == -ENODEV)
- netif_device_detach(netdev);
- else
- netdev_err(netdev, "failed resubmitting read bulk urb: %d\n",
- err);
+ if (ret == -ENODEV)
+ netif_device_detach(netdev);
+ else
+ netdev_err(netdev,
+ "Error %d: Failed to resubmit read bulk urb\n", ret);
}
-/*
- * callback for bulk Tx urb
- */
-static void ixxat_usb_write_bulk_callback(struct urb *urb)
+static void ixxat_usb_write_bulk(struct urb *urb)
{
- struct ixx_tx_urb_context *context = urb->context;
- struct ixx_usb_device *dev;
+ struct ixxat_tx_urb_context *context = urb->context;
+ struct ixxat_usb_device *dev;
struct net_device *netdev;
- BUG_ON(!context);
+ if (WARN_ON(!context))
+ return;
dev = context->dev;
netdev = dev->netdev;
-
atomic_dec(&dev->active_tx_urbs);
if (!netif_device_present(netdev))
return;
- /* check tx status */
- switch (urb->status) {
- case 0:
- /* transmission complete */
- netdev->stats.tx_packets += context->count;
- netdev->stats.tx_bytes += context->dlc;
-
- /* prevent tx timeout */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
- netif_trans_update(netdev);
-#else
- netdev->trans_start = jiffies;
-#endif
- break;
-
-
- case -EPROTO:
- case -ENOENT:
- case -ECONNRESET:
- case -ESHUTDOWN:
- break;
- default:
- if (net_ratelimit())
- netdev_err(netdev, "Tx urb aborted (%d)\n",
- urb->status);
- break;
+ if (!urb->status) {
+ netdev->stats.tx_packets += context->count;
+ netdev->stats.tx_bytes += context->dlc;
+ } else {
+ netdev_err(netdev, "Error %d: Tx urb aborted\n", urb->status);
}
- /* should always release echo skb and corresponding context */
can_get_echo_skb(netdev, context->echo_index);
context->echo_index = IXXAT_USB_MAX_TX_URBS;
- /* do wakeup tx queue in case of success only */
if (!urb->status)
netif_wake_queue(netdev);
}
-/*
- * called by netdev to send one skb on the CAN interface.
- */
-static netdev_tx_t ixxat_usb_ndo_start_xmit(struct sk_buff *skb,
- struct net_device *netdev)
+static void ixxat_usb_encode_msg(struct ixxat_usb_device *dev,
+ struct sk_buff *skb, u8 *obuf,
+ size_t *size)
+{
+ struct canfd_frame *cf = (struct canfd_frame *)skb->data;
+ struct ixxat_can_msg can_msg = {0};
+ struct ixxat_can_msg_base *msg_base = &can_msg.base;
+
+ if (cf->can_id & CAN_RTR_FLAG)
+ msg_base->flags |= IXXAT_USB_MSG_FLAGS_RTR;
+
+ if (cf->can_id & CAN_EFF_FLAG) {
+ msg_base->flags |= IXXAT_USB_MSG_FLAGS_EXT;
+ msg_base->msg_id = cf->can_id & CAN_EFF_MASK;
+ } else {
+ msg_base->msg_id = cf->can_id & CAN_SFF_MASK;
+ }
+
+ if (can_is_canfd_skb(skb)) {
+ msg_base->flags |= IXXAT_USB_FDMSG_FLAGS_EDL;
+
+ if (!(cf->can_id & CAN_RTR_FLAG) && (cf->flags & CANFD_BRS))
+ msg_base->flags |= IXXAT_USB_FDMSG_FLAGS_FDR;
+
+ msg_base->flags |= IXXAT_USB_ENCODE_DLC(can_len2dlc(cf->len));
+ } else {
+ msg_base->flags |= IXXAT_USB_ENCODE_DLC(cf->len);
+ }
+
+ le32_to_cpus(&msg_base->flags);
+ le32_to_cpus(&msg_base->msg_id);
+
+ msg_base->size = (u8)(sizeof(*msg_base) - 1);
+ if (dev->adapter == &usb2can_cl1) {
+ msg_base->size += (u8)(sizeof(can_msg.cl1) - CAN_MAX_DLEN);
+ msg_base->size += cf->len;
+ memcpy(can_msg.cl1.data, cf->data, cf->len);
+ } else {
+ msg_base->size += (u8)(sizeof(can_msg.cl2) - CANFD_MAX_DLEN);
+ msg_base->size += cf->len;
+ memcpy(can_msg.cl2.data, cf->data, cf->len);
+ }
+
+ *size = msg_base->size + 1;
+ memcpy(obuf, &can_msg, *size);
+ skb->data_len = *size;
+}
+
+static netdev_tx_t ixxat_usb_start_xmit(struct sk_buff *skb,
+ struct net_device *netdev)
{
- struct ixx_usb_device *dev = netdev_priv(netdev);
- struct ixx_tx_urb_context *context = NULL;
+ struct ixxat_usb_device *dev = netdev_priv(netdev);
+ struct ixxat_tx_urb_context *context = NULL;
struct net_device_stats *stats = &netdev->stats;
- struct canfd_frame *cf = (struct canfd_frame *) skb->data;
+ struct canfd_frame *cf = (struct canfd_frame *)skb->data;
struct urb *urb;
u8 *obuf;
- int i, err;
- size_t size = dev->adapter->tx_buffer_size;
+ int i;
+ int ret;
+ size_t size = dev->adapter->buffer_size_tx;
if (can_dropped_invalid_skb(netdev, skb))
return NETDEV_TX_OK;
@@ -284,68 +793,39 @@ static netdev_tx_t ixxat_usb_ndo_start_xmit(struct sk_buff *skb,
}
}
- if (!context) {
- /* should not occur except during restart */
+ if (WARN_ON_ONCE(!context))
return NETDEV_TX_BUSY;
- }
urb = context->urb;
obuf = urb->transfer_buffer;
- err = dev->adapter->dev_encode_msg(dev, skb, obuf, &size);
+ ixxat_usb_encode_msg(dev, skb, obuf, &size);
context->echo_index = i;
context->dlc = cf->len;
context->count = 1;
urb->transfer_buffer_length = size;
-
- if (err) {
- if (net_ratelimit())
- netdev_err(netdev, "packet dropped\n");
- dev_kfree_skb(skb);
- stats->tx_dropped++;
- return NETDEV_TX_OK;
- }
-
usb_anchor_urb(urb, &dev->tx_submitted);
-
can_put_echo_skb(skb, netdev, context->echo_index);
-
atomic_inc(&dev->active_tx_urbs);
- err = usb_submit_urb(urb, GFP_ATOMIC);
- if (err) {
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (unlikely(ret)) {
can_free_echo_skb(netdev, context->echo_index);
-
usb_unanchor_urb(urb);
+ atomic_dec(&dev->active_tx_urbs);
- /* this context is not used in fact */
context->echo_index = IXXAT_USB_MAX_TX_URBS;
- atomic_dec(&dev->active_tx_urbs);
-
- switch (err) {
- case -ENODEV:
- netif_device_detach(netdev);
- break;
- case -ENOENT:
- /* cable unplugged */
- stats->tx_dropped++;
- break;
- default:
- stats->tx_dropped++;
- netdev_warn(netdev, "tx urb submitting failed err=%d\n",
- err);
+ if (ret == -ENODEV) {
+ netif_device_detach(netdev);
+ } else {
+ stats->tx_dropped++;
+ netdev_err(netdev,
+ "Error %d: Submitting tx-urb failed\n", ret);
}
} else {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
- netif_trans_update(netdev);
-#else
- netdev->trans_start = jiffies;
-#endif
-
- /* slow down tx path */
if (atomic_read(&dev->active_tx_urbs) >= IXXAT_USB_MAX_TX_URBS)
netif_stop_queue(netdev);
}
@@ -353,86 +833,91 @@ static netdev_tx_t ixxat_usb_ndo_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
}
-/*
- * start the CAN interface.
- * Rx and Tx urbs are allocated here. Rx urbs are submitted here.
- */
-static int ixxat_usb_start(struct ixx_usb_device *dev)
+static int ixxat_usb_setup_rx_urbs(struct ixxat_usb_device *dev)
{
+ int i;
+ int ret = 0;
+ const struct ixxat_usb_adapter *adapter = dev->adapter;
struct net_device *netdev = dev->netdev;
- int err, i;
+ struct usb_device *udev = dev->udev;
for (i = 0; i < IXXAT_USB_MAX_RX_URBS; i++) {
struct urb *urb;
u8 *buf;
- /* create a URB, and a buffer for it, to receive usb messages */
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
- netdev_err(netdev, "No memory left for URBs\n");
- err = -ENOMEM;
+ ret = -ENOMEM;
+ netdev_err(netdev, "Error %d: No memory for URBs\n",
+ ret);
break;
}
- buf = kmalloc(dev->adapter->rx_buffer_size, GFP_KERNEL);
+ buf = kmalloc(adapter->buffer_size_rx, GFP_KERNEL);
if (!buf) {
usb_free_urb(urb);
- err = -ENOMEM;
+ ret = -ENOMEM;
+ netdev_err(netdev,
+ "Error %d: No memory for USB-buffer\n", ret);
break;
}
- usb_fill_bulk_urb(urb, dev->udev,
- usb_rcvbulkpipe(dev->udev, dev->ep_msg_in), buf,
- dev->adapter->rx_buffer_size,
- ixxat_usb_read_bulk_callback, dev);
+ usb_fill_bulk_urb(urb, udev,
+ usb_rcvbulkpipe(udev, dev->ep_msg_in), buf,
+ adapter->buffer_size_rx, ixxat_usb_read_bulk,
+ dev);
- /* ask last usb_free_urb() to also kfree() transfer_buffer */
urb->transfer_flags |= URB_FREE_BUFFER;
usb_anchor_urb(urb, &dev->rx_submitted);
- err = usb_submit_urb(urb, GFP_KERNEL);
- if (err) {
- if (err == -ENODEV)
- netif_device_detach(dev->netdev);
-
+ ret = usb_submit_urb(urb, GFP_KERNEL);
+ if (ret < 0) {
usb_unanchor_urb(urb);
kfree(buf);
usb_free_urb(urb);
+
+ if (ret == -ENODEV)
+ netif_device_detach(netdev);
+
break;
}
- /* drop reference, USB core will take care of freeing it */
usb_free_urb(urb);
}
- /* did we submit any URBs? Warn if we was not able to submit all urbs */
- if (i < IXXAT_USB_MAX_RX_URBS) {
- if (i == 0) {
- netdev_err(netdev, "couldn't setup any rx URB\n");
- return err;
- }
+ if (i == 0)
+ netdev_err(netdev, "Error: Couldn't setup any rx-URBs\n");
- netdev_warn(netdev, "rx performance may be slow\n");
- }
+ return ret;
+}
+
+static int ixxat_usb_setup_tx_urbs(struct ixxat_usb_device *dev)
+{
+ int i;
+ int ret = 0;
+ const struct ixxat_usb_adapter *adapter = dev->adapter;
+ struct net_device *netdev = dev->netdev;
+ struct usb_device *udev = dev->udev;
- /* pre-alloc tx buffers and corresponding urbs */
for (i = 0; i < IXXAT_USB_MAX_TX_URBS; i++) {
- struct ixx_tx_urb_context *context;
- struct urb *urb;
- u8 *buf;
+ struct ixxat_tx_urb_context *context;
+ struct urb *urb = NULL;
+ u8 *buf = NULL;
- /* create a URB and a buffer for it, to transmit usb messages */
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
- netdev_err(netdev, "No memory left for URBs\n");
- err = -ENOMEM;
+ ret = -ENOMEM;
+ netdev_err(netdev, "Error %d: No memory for URBs\n",
+ ret);
break;
}
- buf = kmalloc(dev->adapter->tx_buffer_size, GFP_KERNEL);
+ buf = kmalloc(adapter->buffer_size_tx, GFP_KERNEL);
if (!buf) {
usb_free_urb(urb);
- err = -ENOMEM;
+ ret = -ENOMEM;
+ netdev_err(netdev,
+ "Error %d: No memory for USB-buffer\n", ret);
break;
}
@@ -440,70 +925,111 @@ static int ixxat_usb_start(struct ixx_usb_device *dev)
context->dev = dev;
context->urb = urb;
- usb_fill_bulk_urb(urb, dev->udev,
- usb_sndbulkpipe(dev->udev, dev->ep_msg_out),
- buf, dev->adapter->tx_buffer_size,
- ixxat_usb_write_bulk_callback, context);
+ usb_fill_bulk_urb(urb, udev,
+ usb_sndbulkpipe(udev, dev->ep_msg_out), buf,
+ adapter->buffer_size_tx, ixxat_usb_write_bulk,
+ context);
- /* ask last usb_free_urb() to also kfree() transfer_buffer */
urb->transfer_flags |= URB_FREE_BUFFER;
}
- /* warn if we were not able to allocate enough tx contexts */
- if (i < IXXAT_USB_MAX_TX_URBS) {
- if (i == 0) {
- netdev_err(netdev, "couldn't setup any tx URB\n");
- goto err_tx;
- }
+ if (i == 0) {
+ netdev_err(netdev, "Error: Couldn't setup any tx-URBs\n");
+ usb_kill_anchored_urbs(&dev->rx_submitted);
+ }
+
+ return ret;
+}
+
+static void ixxat_usb_disconnect(struct usb_interface *intf)
+{
+ struct ixxat_usb_device *dev;
+ struct ixxat_usb_device *prev_dev;
+
+ /* unregister the given device and all previous devices */
+ for (dev = usb_get_intfdata(intf); dev; dev = prev_dev) {
+ prev_dev = dev->prev_dev;
+ unregister_netdev(dev->netdev);
+ free_candev(dev->netdev);
+ }
- netdev_warn(netdev, "tx performance may be slow\n");
+ usb_set_intfdata(intf, NULL);
+}
+
+static int ixxat_usb_start(struct ixxat_usb_device *dev)
+{
+ int ret;
+ int i;
+ u32 time_ref = 0;
+ const struct ixxat_usb_adapter *adapter = dev->adapter;
+
+ ret = ixxat_usb_setup_rx_urbs(dev);
+ if (ret < 0)
+ return ret;
+
+ ret = ixxat_usb_setup_tx_urbs(dev);
+ if (ret < 0)
+ return ret;
+
+ /* Try to reset the controller, in case it is already initialized
+ * from a previous unclean shutdown
+ */
+ ixxat_usb_reset_ctrl(dev);
+
+ if (adapter->init_ctrl) {
+ ret = adapter->init_ctrl(dev);
+ if (ret < 0)
+ goto fail;
}
- if (dev->adapter->dev_start) {
- err = dev->adapter->dev_start(dev);
- if (err)
- goto err_adapter;
+ if (dev->ctrl_opened_count == 0) {
+ ret = ixxat_usb_start_ctrl(dev, &time_ref);
+ if (ret < 0)
+ goto fail;
+
+ ixxat_usb_set_ts_now(dev, time_ref);
}
- dev->state |= IXXAT_USB_STATE_STARTED;
+ dev->ctrl_opened_count++;
+
+ dev->bec.txerr = 0;
+ dev->bec.rxerr = 0;
+ dev->state |= IXXAT_USB_STATE_STARTED;
dev->can.state = CAN_STATE_ERROR_ACTIVE;
return 0;
-err_adapter: if (err == -ENODEV)
- netif_device_detach(dev->netdev);
+fail:
+ if (ret == -ENODEV)
+ netif_device_detach(dev->netdev);
- netdev_warn(netdev, "couldn't submit control: %d\n", err);
+ netdev_err(dev->netdev, "Error %d: Couldn't submit control\n", ret);
- for (i = 0; i < IXXAT_USB_MAX_TX_URBS; i++) {
- usb_free_urb(dev->tx_contexts[i].urb);
- dev->tx_contexts[i].urb = NULL;
- }
-err_tx: usb_kill_anchored_urbs(&dev->rx_submitted);
+ for (i = 0; i < IXXAT_USB_MAX_TX_URBS; i++) {
+ usb_free_urb(dev->tx_contexts[i].urb);
+ dev->tx_contexts[i].urb = NULL;
+ }
- return err;
+ return ret;
}
-/*
- * called by netdev to open the corresponding CAN interface.
- */
-static int ixxat_usb_ndo_open(struct net_device *netdev)
+static int ixxat_usb_open(struct net_device *netdev)
{
- struct ixx_usb_device *dev = netdev_priv(netdev);
- int err;
+ struct ixxat_usb_device *dev = netdev_priv(netdev);
+ int ret;
/* common open */
- err = open_candev(netdev);
- if (err)
- return err;
+ ret = open_candev(netdev);
+ if (ret < 0)
+ return ret;
/* finally start device */
- err = ixxat_usb_start(dev);
- if (err) {
- netdev_err(netdev, "couldn't start device: %d\n", err);
+ ret = ixxat_usb_start(dev);
+ if (ret < 0) {
+ netdev_err(netdev, "Error %d: Couldn't start device.\n", ret);
close_candev(netdev);
- return err;
+ return ret;
}
netif_start_queue(netdev);
@@ -511,54 +1037,20 @@ static int ixxat_usb_ndo_open(struct net_device *netdev)
return 0;
}
-/*
- * unlink in-flight Rx and Tx urbs and free their memory.
- */
-static void ixxat_usb_unlink_all_urbs(struct ixx_usb_device *dev)
+static int ixxat_usb_stop(struct net_device *netdev)
{
- int i;
-
- /* free all Rx (submitted) urbs */
- usb_kill_anchored_urbs(&dev->rx_submitted);
-
- /* free unsubmitted Tx urbs first */
- for (i = 0; i < IXXAT_USB_MAX_TX_URBS; i++) {
- struct urb *urb = dev->tx_contexts[i].urb;
-
- if (!urb
- || dev->tx_contexts[i].echo_index
- != IXXAT_USB_MAX_TX_URBS) {
- /*
- * this urb is already released or always submitted,
- * let usb core free by itself
- */
- continue;
- }
+ int ret = 0;
+ struct ixxat_usb_device *dev = netdev_priv(netdev);
- usb_free_urb(urb);
- dev->tx_contexts[i].urb = NULL;
- }
-
- /* then free all submitted Tx urbs */
- usb_kill_anchored_urbs(&dev->tx_submitted);
- atomic_set(&dev->active_tx_urbs, 0);
-}
-
-/*
- * called by netdev to close the corresponding CAN interface.
- */
-static int ixxat_usb_ndo_stop(struct net_device *netdev)
-{
- struct ixx_usb_device *dev = netdev_priv(netdev);
-
- dev->state &= ~IXXAT_USB_STATE_STARTED;
netif_stop_queue(netdev);
-
- /* unlink all pending urbs and free used memory */
ixxat_usb_unlink_all_urbs(dev);
- if (dev->adapter->dev_stop)
- dev->adapter->dev_stop(dev);
+ if (dev->ctrl_opened_count == 1) {
+ ret = ixxat_usb_stop_ctrl(dev);
+ if (ret < 0)
+ return ret;
+ }
+ dev->ctrl_opened_count--;
close_candev(netdev);
@@ -567,357 +1059,193 @@ static int ixxat_usb_ndo_stop(struct net_device *netdev)
return 0;
}
-/*
- * handle end of waiting for the device to reset
- */
-void ixxat_usb_restart_complete(struct ixx_usb_device *dev)
-{
- /* finally MUST update can state */
- dev->can.state = CAN_STATE_ERROR_ACTIVE;
-
- /* netdev queue can be awaken now */
- netif_wake_queue(dev->netdev);
-}
-
-void ixxat_usb_async_complete(struct urb *urb)
-{
- kfree(urb->transfer_buffer);
- usb_free_urb(urb);
-}
-
-/*
- * candev callback used to change CAN mode.
- * Warning: this is called from a timer context!
- */
-static int ixxat_usb_set_mode(struct net_device *netdev, enum can_mode mode)
-{
- struct ixx_usb_device *dev = netdev_priv(netdev);
- int err = 0;
-
- switch (mode) {
- case CAN_MODE_START:
- dev->restart_flag = 1;
- wake_up_interruptible(&dev->wait_queue);
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return err;
-}
+static const struct net_device_ops ixxat_usb_netdev_ops = {
+ .ndo_open = ixxat_usb_open,
+ .ndo_stop = ixxat_usb_stop,
+ .ndo_start_xmit = ixxat_usb_start_xmit
+};
-/*
- * candev callback used to set device bitrate.
- */
-static int ixxat_usb_set_bittiming(struct net_device *netdev)
+static const struct ixxat_usb_adapter *ixxat_usb_get_adapter(const u16 id)
{
- struct ixx_usb_device* dev = (struct ixx_usb_device*) netdev_priv(
- netdev);
- struct can_bittiming *bt = &dev->can.bittiming;
-
- if (dev->adapter->dev_set_bittiming) {
- int err = dev->adapter->dev_set_bittiming(dev, bt);
-
- if (err)
- netdev_info(netdev, "couldn't set bitrate (err %d)\n",
- err);
- return err;
+ switch (id) {
+ case USB2CAN_COMPACT_PRODUCT_ID:
+ case USB2CAN_EMBEDDED_PRODUCT_ID:
+ case USB2CAN_PROFESSIONAL_PRODUCT_ID:
+ case USB2CAN_AUTOMOTIVE_PRODUCT_ID:
+ return &usb2can_cl1;
+ case USB2CAN_FD_COMPACT_PRODUCT_ID:
+ case USB2CAN_FD_PROFESSIONAL_PRODUCT_ID:
+ case USB2CAN_FD_AUTOMOTIVE_PRODUCT_ID:
+ case USB2CAN_FD_PCIE_MINI_PRODUCT_ID:
+ case USB2CAR_PRODUCT_ID:
+ return &usb2can_cl2;
+ case CAN_IDM100_PRODUCT_ID:
+ return &can_idm100;
+ case CAN_IDM101_PRODUCT_ID:
+ return &can_idm101;
+ default:
+ return NULL;
}
-
- return 0;
}
-/*
- * candev callback used to set error counters.
- */
-static int ixxat_usb_get_berr_counter(const struct net_device *netdev,
- struct can_berr_counter *bec)
-{
- struct ixx_usb_device* dev = (struct ixx_usb_device*) netdev_priv(
- netdev);
-
- *bec = dev->bec;
-
- return 0;
-}
-
-static const struct net_device_ops ixx_usb_netdev_ops = { .ndo_open =
- ixxat_usb_ndo_open, .ndo_stop = ixxat_usb_ndo_stop,
- .ndo_start_xmit = ixxat_usb_ndo_start_xmit,
-#ifdef CANFD_CAPABLE
- .ndo_change_mtu = can_change_mtu,
-#endif
-};
-
-/*
- * create one device which is attached to CAN controller #ctrl_idx of the
- * usb adapter.
- */
-static int ixxat_usb_create_dev(struct ixx_usb_adapter *ixx_usb_adapter,
- struct usb_interface *intf, int ctrl_idx)
+static int ixxat_usb_create_dev(struct usb_interface *intf,
+ const struct ixxat_usb_adapter *adapter,
+ u16 ctrl_index)
{
struct usb_device *usb_dev = interface_to_usbdev(intf);
- int sizeof_candev = ixx_usb_adapter->sizeof_dev_private;
- struct ixx_usb_device *dev;
+ struct ixxat_usb_device *dev;
struct net_device *netdev;
- int i, err = 0, ep_off = 0;
- u16 tmp16;
-
- if (sizeof_candev < sizeof(struct ixx_usb_device))
- sizeof_candev = sizeof(struct ixx_usb_device);
+ int ret;
+ int i;
- netdev = alloc_candev(sizeof_candev, IXXAT_USB_MAX_TX_URBS);
+ netdev = alloc_candev(sizeof(*dev), IXXAT_USB_MAX_TX_URBS);
if (!netdev) {
- dev_err(&intf->dev, "%s: couldn't alloc candev\n",
- IXXAT_USB_DRIVER_NAME);
+ dev_err(&intf->dev, "Cannot allocate candev\n");
return -ENOMEM;
}
dev = netdev_priv(netdev);
- dev->transmit_ptr = 0;
- dev->transmit_dlc = 0;
- dev->transmit_count = 0;
-
- dev->restart_flag = 0;
- dev->restart_task = 0;
- dev->must_quit = 0;
- init_waitqueue_head(&dev->wait_queue);
-
dev->ctrl_opened_count = 0;
-
dev->udev = usb_dev;
dev->netdev = netdev;
- dev->adapter = ixx_usb_adapter;
- dev->ctrl_idx = ctrl_idx;
+ dev->adapter = adapter;
+ dev->ctrl_index = ctrl_index;
dev->state = IXXAT_USB_STATE_CONNECTED;
- ep_off = ixx_usb_adapter->has_bgi_ep ? 1 : 0;
-
- /* Add +1 because of the bgi endpoint */
- dev->ep_msg_in = ixx_usb_adapter->ep_msg_in[ctrl_idx+ep_off];
- dev->ep_msg_out = ixx_usb_adapter->ep_msg_out[ctrl_idx+ep_off];
+ i = ctrl_index + adapter->ep_offs;
+ dev->ep_msg_in = adapter->ep_msg_in[i];
+ dev->ep_msg_out = adapter->ep_msg_out[i];
- dev->can.clock = ixx_usb_adapter->clock;
- dev->can.bittiming_const = &ixx_usb_adapter->bittiming_const;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 3)
- dev->can.data_bittiming_const = &ixx_usb_adapter->data_bittiming_const;
-#endif
+ dev->can.clock.freq = adapter->clock;
+ dev->can.bittiming_const = adapter->bt;
+ dev->can.data_bittiming_const = adapter->btd;
- dev->can.do_set_bittiming = ixxat_usb_set_bittiming;
dev->can.do_set_mode = ixxat_usb_set_mode;
dev->can.do_get_berr_counter = ixxat_usb_get_berr_counter;
- dev->can.ctrlmode_supported = ixx_usb_adapter->ctrlmode_supported;
+ dev->can.ctrlmode_supported = adapter->modes;
- netdev->netdev_ops = &ixx_usb_netdev_ops;
+ netdev->netdev_ops = &ixxat_usb_netdev_ops;
- netdev->flags |= IFF_ECHO; /* we support local echo */
+ netdev->flags |= IFF_ECHO;
init_usb_anchor(&dev->rx_submitted);
-
init_usb_anchor(&dev->tx_submitted);
+
atomic_set(&dev->active_tx_urbs, 0);
for (i = 0; i < IXXAT_USB_MAX_TX_URBS; i++)
dev->tx_contexts[i].echo_index = IXXAT_USB_MAX_TX_URBS;
- dev->prev_siblings = usb_get_intfdata(intf);
+ dev->prev_dev = usb_get_intfdata(intf);
usb_set_intfdata(intf, dev);
SET_NETDEV_DEV(netdev, &intf->dev);
-
- err = register_candev(netdev);
- if (err) {
- dev_err(&intf->dev, "couldn't register CAN device: %d\n", err);
- goto lbl_set_intf_data;
+ ret = register_candev(netdev);
+ if (ret < 0) {
+ dev_err(&intf->dev, "Error %d: Failed to register can device\n",
+ ret);
+ goto free_candev;
}
- if (dev->prev_siblings)
- (dev->prev_siblings)->next_siblings = dev;
+ if (dev->prev_dev)
+ (dev->prev_dev)->next_dev = dev;
- /* keep hw revision into the netdevice */
- tmp16 = le16_to_cpu(usb_dev->descriptor.bcdDevice);
- dev->device_rev = tmp16 >> 8;
-
- if (dev->adapter->dev_init) {
- err = dev->adapter->dev_init(dev);
- if (err)
- goto lbl_set_intf_data;
+ ret = ixxat_usb_get_dev_info(dev, &dev->dev_info);
+ if (ret < 0) {
+ dev_err(&intf->dev,
+ "Error %d: Failed to get device information\n", ret);
+ goto unreg_candev;
}
- if (dev->adapter->intf_get_info)
- dev->adapter->intf_get_info(dev,
- &dev->dev_info);
-
- netdev_info(netdev, "attached to %s channel %u (device %s)\n",
- dev->dev_info.device_name, ctrl_idx,
- dev->dev_info.device_id);
+ netdev_info(netdev, "%s: Connected Channel %u (device %s)\n",
+ dev->dev_info.device_name, ctrl_index,
+ dev->dev_info.device_id);
return 0;
-lbl_set_intf_data: usb_set_intfdata(intf, dev->prev_siblings);
- free_candev(netdev);
-
- return err;
+unreg_candev:
+ unregister_candev(netdev);
+free_candev:
+ usb_set_intfdata(intf, dev->prev_dev);
+ free_candev(netdev);
+ return ret;
}
-/*
- * called by the usb core when the device is unplugged from the system
- */
-static void ixxat_usb_disconnect(struct usb_interface *intf)
-{
- struct ixx_usb_device *dev;
- struct ixx_usb_device *dev_prev_siblings;
-
- /* unregister as many netdev devices as siblings */
- for (dev = usb_get_intfdata(intf); dev; dev = dev_prev_siblings) {
- struct net_device *netdev = dev->netdev;
- char name[IFNAMSIZ];
-
- dev_prev_siblings = dev->prev_siblings;
- dev->state &= ~IXXAT_USB_STATE_CONNECTED;
- strncpy(name, netdev->name, IFNAMSIZ);
-
- unregister_netdev(netdev);
-
- dev->next_siblings = NULL;
- if (dev->adapter->dev_free)
- dev->adapter->dev_free(dev);
-
- free_candev(netdev);
- dev_dbg(&intf->dev, "%s removed\n", name);
- }
-
- usb_set_intfdata(intf, NULL);
-}
-
-/*
- * probe function for new ixxat-usb devices
- */
static int ixxat_usb_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
+ const struct usb_device_id *id)
{
- struct usb_device *usb_dev = interface_to_usbdev(intf);
- struct ixx_usb_adapter *ixx_usb_adapter, **pp;
- int i, err = -ENOMEM;
- struct ixx_dev_caps dev_caps;
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct usb_host_interface *host_intf = intf->altsetting;
+ const struct ixxat_usb_adapter *adapter;
+ struct ixxat_dev_caps dev_caps;
+ u16 i;
+ int ret;
+
+ usb_reset_configuration(udev);
+
+ adapter = ixxat_usb_get_adapter(id->idProduct);
+ if (!adapter) {
+ dev_err(&intf->dev, "%s: Unknown device id %d\n",
+ IXXAT_USB_DRIVER_NAME, id->idProduct);
+ return -ENODEV;
+ }
- usb_dev = interface_to_usbdev(intf);
+ for (i = 0; i < host_intf->desc.bNumEndpoints; i++) {
+ const u8 epaddr = host_intf->endpoint[i].desc.bEndpointAddress;
+ int match;
+ u8 j;
- usb_reset_configuration(usb_dev);
+ /* Check if usb-endpoint address matches known usb-endpoints */
+ for (j = 0; j < IXXAT_USB_MAX_CHANNEL; j++) {
+ u8 ep_msg_in = adapter->ep_msg_in[j];
+ u8 ep_msg_out = adapter->ep_msg_in[j];
- /* get corresponding IXX-USB adapter */
- for (pp = ixx_usb_adapters_list; *pp; pp++)
- if ((*pp)->device_id == le16_to_cpu(usb_dev->descriptor.idProduct))
- break;
+ if (epaddr == ep_msg_in || epaddr == ep_msg_out) {
+ match = 1;
+ break;
+ }
+ }
- ixx_usb_adapter = *pp;
- if (!ixx_usb_adapter) {
- /* should never come except device_id bad usage in this file */
- pr_err("%s: didn't find device id. 0x%x in devices list\n",
- IXXAT_USB_DRIVER_NAME, le16_to_cpu(usb_dev->descriptor.idProduct));
- return -ENODEV;
+ if (!match)
+ return -ENODEV;
}
- /* got corresponding adapter: check if it handles current interface */
- if (ixx_usb_adapter->intf_probe) {
- err = ixx_usb_adapter->intf_probe(intf);
- if (err)
- return err;
- }
+ ret = ixxat_usb_power_ctrl(udev, IXXAT_USB_POWER_WAKEUP);
+ if (ret < 0)
+ return ret;
- if (ixx_usb_adapter->dev_power) {
- err = ixx_usb_adapter->dev_power(usb_dev, IXXAT_USB_POWER_WAKEUP);
- if (err)
- return err;
+ msleep(IXXAT_USB_POWER_WAKEUP_TIME);
- /* Give usb device some time to start its can controllers */
- msleep(500);
+ ret = ixxat_usb_get_dev_caps(udev, &dev_caps);
+ if (ret < 0) {
+ dev_err(&intf->dev, "Failed to get device capabilities\n");
+ return ret;
}
- /* got corresponding adapter: check the available controllers */
- if (ixx_usb_adapter->dev_get_dev_caps) {
- err = ixx_usb_adapter->dev_get_dev_caps(usb_dev, &dev_caps);
- if (err)
- return err;
+ ret = -ENODEV;
+ for (i = 0; i < dev_caps.bus_ctrl_count; i++) {
+ u8 bustype = IXXAT_USB_BUS_TYPE(dev_caps.bus_ctrl_types[i]);
- for (i = 0; i < dev_caps.bus_ctrl_count; i++) {
- if ( IXXAT_USB_BUS_CAN
- == IXXAT_USB_BUS_TYPE(dev_caps.bus_ctrl_types[i]))
- ixx_usb_adapter->ctrl_count++;
- }
+ if (bustype == IXXAT_USB_BUS_CAN)
+ ret = ixxat_usb_create_dev(intf, adapter, i);
- for (i = 0; i < dev_caps.bus_ctrl_count; i++) {
- if ( IXXAT_USB_BUS_CAN == IXXAT_USB_BUS_TYPE(dev_caps.bus_ctrl_types[i]))
- err = ixxat_usb_create_dev(ixx_usb_adapter, intf, i);
- if (err) {
- /* deregister already created devices */
- ixxat_usb_disconnect(intf);
- break;
- }
+ if (ret < 0) {
+ /* deregister already created devices */
+ ixxat_usb_disconnect(intf);
+ return ret;
}
}
- return err;
+ return ret;
}
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver ixx_usb_driver = {
+static struct usb_driver ixxat_usb_driver = {
.name = IXXAT_USB_DRIVER_NAME,
- .disconnect = ixxat_usb_disconnect,
.probe = ixxat_usb_probe,
+ .disconnect = ixxat_usb_disconnect,
.id_table = ixxat_usb_table,
};
-static int __init ixx_usb_init(void)
-{
- int err;
-
- /* register this driver with the USB subsystem */
- err = usb_register(&ixx_usb_driver);
- if (err)
- pr_err("%s: usb_register failed (err %d)\n",
- IXXAT_USB_DRIVER_NAME, err);
-
- return err;
-}
-
-static int ixxat_usb_do_device_exit(struct device *d, void *arg)
-{
- struct usb_interface
- *intf = (struct usb_interface*)to_usb_interface(d);
- struct ixx_usb_device *dev;
-
- /* stop as many netdev devices as siblings */
- for (dev = usb_get_intfdata(intf); dev; dev = dev->prev_siblings) {
- struct net_device *netdev = dev->netdev;
-
- if (netif_device_present(netdev))
- if (dev->adapter->dev_exit)
- dev->adapter->dev_exit(dev);
- }
-
- return 0;
-}
-
-static void __exit ixx_usb_exit(void)
-{
- int err;
-
- /* last chance do send any synchronous commands here */
- err = driver_for_each_device(&ixx_usb_driver.drvwrap.driver, NULL,
- NULL, ixxat_usb_do_device_exit);
- if (err)
- pr_err("%s: failed to stop all can devices (err %d)\n",
- IXXAT_USB_DRIVER_NAME, err);
-
- /* deregister this driver with the USB subsystem */
- usb_deregister(&ixx_usb_driver);
-
- pr_info("%s: IXX-USB interfaces driver unloaded\n",
- IXXAT_USB_DRIVER_NAME);
-}
-
-module_init(ixx_usb_init);
-module_exit(ixx_usb_exit);
+module_usb_driver(ixxat_usb_driver);
diff --git a/ubuntu/ixxat/ixx_usb_core.h b/ubuntu/ixxat/ixx_usb_core.h
index 79c11d8f1ea8..e57b435dd457 100644
--- a/ubuntu/ixxat/ixx_usb_core.h
+++ b/ubuntu/ixxat/ixx_usb_core.h
@@ -1,9 +1,8 @@
-/*
- * CAN driver for IXXAT USB-to-CAN V2 adapters
- *
- * Copyright (C) 2003-2014 Michael Hengler IXXAT Automation GmbH
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* CAN driver base for IXXAT USB-to-CAN
*
- * Based on code originally by pcan_usb_core
+ * Copyright (C) 2018 HMS Industrial Networks <socketcan at hms-networks.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published
@@ -14,276 +13,648 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
-#ifndef IXX_USB_CORE_H
-#define IXX_USB_CORE_H
-
-#include <linux/version.h>
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 3)
-#define CANFD_CAPABLE 1
-#endif
-
-extern struct ixx_usb_adapter usb_to_can_v2_compact;
-extern struct ixx_usb_adapter usb_to_can_v2_automotive;
-extern struct ixx_usb_adapter usb_to_can_v2_embedded;
-extern struct ixx_usb_adapter usb_to_can_v2_professional;
-extern struct ixx_usb_adapter usb_to_can_v2_low_speed;
-extern struct ixx_usb_adapter usb_to_can_v2_extended;
-
-#ifdef CANFD_CAPABLE
-extern struct ixx_usb_adapter usb_to_can_fd_automotive;
-extern struct ixx_usb_adapter usb_to_can_fd_compact;
-extern struct ixx_usb_adapter usb_to_can_fd_professional;
-extern struct ixx_usb_adapter usb_to_can_fd_pcie_mini;
-extern struct ixx_usb_adapter usb_to_car;
-extern struct ixx_usb_adapter dell_edge_gw3002;
-#endif
-
-#ifndef CAN_MAX_DLEN
-#define CAN_MAX_DLEN 8
-#endif
-
-#ifndef CANFD_MAX_DLEN
-#define CANFD_MAX_DLEN 64
-#endif
-
-
-/* supported device ids. */
-#define USB_TO_CAN_V2_COMPACT_PRODUCT_ID 0x0008
-#define USB_TO_CAN_V2_EMBEDDED_PRODUCT_ID 0x0009
-#define USB_TO_CAN_V2_PROFESSIONAL_PRODUCT_ID 0x000A
-#define USB_TO_CAN_V2_AUTOMOTIVE_PRODUCT_ID 0x000B
-#define USB_TO_LIN_V2_PRODUCT_ID 0x000C
-#define USB_TO_KLINE_V2_PRODUCT_ID 0x000D
-#define USB_TO_CAN_V2_LOW_SPEED_PRODUCT_ID 0xFFFF
-#define USB_TO_CAN_V2_EXTENDED_PRODUCT_ID 0x000E
-
-#define USB_TO_CAN_FD_COMPACT_PRODUCT_ID 0x0014
-#define USB_TO_CAN_FD_PROFESSIONAL_PRODUCT_ID 0x0016
-#define USB_TO_CAN_FD_AUTOMOTIVE_PRODUCT_ID 0x0017
-#define USB_TO_CAN_FD_PCIE_MINI_PRODUCT_ID 0x001B
-#define USB_TO_CAR_ID 0x001C
-#define DELL_EDGE_GW3002_PRODUCT_ID 0xFF11
-
-#define IXXAT_USB_MAX_CHANNEL 5
-
-/* number of urbs that are submitted for rx/tx per channel */
-#define IXXAT_USB_MAX_RX_URBS 4
-#define IXXAT_USB_MAX_TX_URBS 10
-
-#define IXX_BTMODE_NAT 0x01
-
-#define IXXAT_USB_POWER_WAKEUP 0
-#define IXXAT_USB_POWER_SLEEP 1
-
-struct ixx_usb_device;
-
-struct ixx_dev_caps
-{
- u16 bus_ctrl_count;
- u16 bus_ctrl_types[32];
-} __packed;
-struct ixx_ctrl_caps
-{
- u16 ctrl_type;
- u16 bus_coupling;
- u32 features;
- u32 clock_freq;
- u32 tsc_divisor;
- u32 cms_divisor;
- u32 cms_max_ticks;
- u32 dtx_divisor;
- u32 dtx_max_ticks;
-} __packed;
+#ifndef IXXAT_USB_CORE_H
+#define IXXAT_USB_CORE_H
-struct canbtp
-{
- u32 mode; // timing mode (see CAN_BTMODE_ const)
- u32 bps; // bits per second or prescaler (see CAN_BTMODE_)
- u16 ts1; // length of time segment 1 in quantas
- u16 ts2; // length of time segment 2 in quantas
- u16 sjw; // re-synchronisation jump width in quantas
- u16 tdo; // transceiver delay compensation offset in quantas
- // (0 = disabled)
-} __packed;
+#define IXXAT_USB_DRIVER_NAME "ixx_usb"
+
+#define IXXAT_USB_VENDOR_ID 0x08d8
+
+/* supported device ids: CL1 */
+#define USB2CAN_COMPACT_PRODUCT_ID 0x0008
+#define USB2CAN_EMBEDDED_PRODUCT_ID 0x0009
+#define USB2CAN_PROFESSIONAL_PRODUCT_ID 0x000A
+#define USB2CAN_AUTOMOTIVE_PRODUCT_ID 0x000B
+
+/* supported device ids: CL2 */
+#define USB2CAN_FD_COMPACT_PRODUCT_ID 0x0014
+#define USB2CAN_FD_PROFESSIONAL_PRODUCT_ID 0x0016
+#define USB2CAN_FD_AUTOMOTIVE_PRODUCT_ID 0x0017
+#define USB2CAN_FD_PCIE_MINI_PRODUCT_ID 0x001B
+#define USB2CAR_PRODUCT_ID 0x001C
+#define CAN_IDM100_PRODUCT_ID 0xFF11
+#define CAN_IDM101_PRODUCT_ID 0xFF12
+
+#define IXXAT_USB_BUS_CAN 1
+
+#define IXXAT_USB_BUS_TYPE(type) ((u8)(((type) >> 8) & 0x00FF))
+
+#define IXXAT_USB_STATE_CONNECTED 0x00000001
+#define IXXAT_USB_STATE_STARTED 0x00000002
+
+#define IXXAT_USB_MAX_CHANNEL 5
+#define IXXAT_USB_MAX_TYPES 32
+#define IXXAT_USB_MAX_RX_URBS 4
+#define IXXAT_USB_MAX_TX_URBS 10
+#define IXXAT_USB_MAX_COM_REQ 10
+
+#define IXXAT_USB_MSG_TIMEOUT 50
+#define IXXAT_USB_MSG_CYCLE 20
+
+#define IXXAT_USB_POWER_WAKEUP 0
+#define IXXAT_USB_POWER_WAKEUP_TIME 500
+
+#define IXXAT_USB_CMD_BUFFER_SIZE 256
+
+#define IXXAT_USB_OPMODE_STANDARD 0x01
+#define IXXAT_USB_OPMODE_EXTENDED 0x02
+#define IXXAT_USB_OPMODE_ERRFRAME 0x04
+#define IXXAT_USB_OPMODE_LISTONLY 0x08
+
+#define IXXAT_USB_EXMODE_EXTDATA 0x01
+#define IXXAT_USB_EXMODE_FASTDATA 0x02
+#define IXXAT_USB_EXMODE_ISOFD 0x04
+
+#define IXXAT_USB_BTMODE_NAT 0x00000001
+#define IXXAT_USB_BTMODE_TSM 0x00000002
+
+#define IXXAT_USB_STOP_ACTION_CLEARALL 3
+
+#define IXXAT_RESTART_TASK_CYCLE_TIME 20
-struct ixx_ctrl_caps_v2
-{
- u16 ctrl_type;
- u16 bus_coupling;
- u32 features;
+#define IXXAT_USB_CAN_DATA 0x00
+#define IXXAT_USB_CAN_INFO 0x01
+#define IXXAT_USB_CAN_ERROR 0x02
+#define IXXAT_USB_CAN_STATUS 0x03
+#define IXXAT_USB_CAN_WAKEUP 0x04
+#define IXXAT_USB_CAN_TIMEOVR 0x05
+#define IXXAT_USB_CAN_TIMERST 0x06
- u32 clock_freq;
- struct canbtp sdr_range_min;
- struct canbtp sdr_range_max;
- struct canbtp fdr_range_min;
- struct canbtp fdr_range_max;
+#define IXXAT_USB_CAN_STATUS_OK 0x00000000
+#define IXXAT_USB_CAN_STATUS_OVERRUN 0x00000002
+#define IXXAT_USB_CAN_STATUS_ERRLIM 0x00000004
+#define IXXAT_USB_CAN_STATUS_BUSOFF 0x00000008
+#define IXXAT_USB_CAN_STATUS_ERR_PAS 0x00002000
- u32 tsc_freq;
- u32 tsc_divisor;
+#define IXXAT_USB_CAN_ERROR_STUFF 1
+#define IXXAT_USB_CAN_ERROR_FORM 2
+#define IXXAT_USB_CAN_ERROR_ACK 3
+#define IXXAT_USB_CAN_ERROR_BIT 4
+#define IXXAT_USB_CAN_ERROR_CRC 6
- u32 cms_freq;
- u32 cms_divisor;
- u32 cms_max_ticks;
+#define IXXAT_USB_MSG_FLAGS_TYPE 0x000000FF
+#define IXXAT_USB_MSG_FLAGS_DLC 0x000F0000
+#define IXXAT_USB_MSG_FLAGS_OVR 0x00100000
+#define IXXAT_USB_MSG_FLAGS_RTR 0x00400000
+#define IXXAT_USB_MSG_FLAGS_EXT 0x00800000
- u32 dtx_freq;
- u32 dtx_divisor;
- u32 dtx_max_ticks;
+#define IXXAT_USB_DECODE_DLC(flags) (((flags) & IXXAT_USB_MSG_FLAGS_DLC) >> 16)
+#define IXXAT_USB_ENCODE_DLC(len) (((len) << 16) & IXXAT_USB_MSG_FLAGS_DLC)
+
+#define IXXAT_USB_FDMSG_FLAGS_EDL 0x00000400
+#define IXXAT_USB_FDMSG_FLAGS_FDR 0x00000800
+#define IXXAT_USB_FDMSG_FLAGS_ESI 0x00001000
+
+#define IXXAT_USB_CAN_CMD_START 0x326
+#define IXXAT_USB_CAN_CMD_STOP 0x327
+#define IXXAT_USB_CAN_CMD_RESET 0x328
+
+#define IXXAT_USB_BRD_CMD_GET_DEVCAPS 0x401
+#define IXXAT_USB_BRD_CMD_GET_DEVINFO 0x402
+#define IXXAT_USB_BRD_CMD_POWER 0x421
+
+/**
+ * union can_frame_union - Union for standard CAN / CAN FD pointers
+ * @cf: Pointer to standard CAN frame
+ * @cfd: Pointer to CAN FD frame
+ *
+ * Contains either a pointer to a standard CAN frame or a CAN FD frame
+ */
+union can_frame_union {
+ struct can_frame *cf;
+ struct canfd_frame *cfd;
+};
+
+/**
+ * struct ixxat_can_msg_base - IXXAT CAN message base (CL1/CL2)
+ * @size: Message size (this field excluded)
+ * @time: Message timestamp
+ * @msg_id: Message ID
+ * @flags: Message flags
+ *
+ * Contains the common fields of an IXXAT CAN message on both CL1 and CL2
+ * devices
+ */
+struct ixxat_can_msg_base {
+ u8 size;
+ __le32 time;
+ __le32 msg_id;
+ __le32 flags;
} __packed;
-struct ixx_intf_info
-{
- char device_name[16]; // device name
- char device_id[16]; // device identification ( unique device id)
- u16 device_version; // device version ( 0, 1, ...)
- u32 device_fpga_version; // device version of FPGA design
+/**
+ * struct ixxat_can_msg_cl1 - IXXAT CAN message (CL1)
+ * @data: Message data (standard CAN frame)
+ *
+ * Contains the fields of an IXXAT CAN message on CL1 devices
+ */
+struct ixxat_can_msg_cl1 {
+ u8 data[CAN_MAX_DLEN];
} __packed;
-struct ixx_intf_fw_info
-{
- u32 firmware_type; // type of currently running firmware
- u16 reserved; // reserved
- u16 major_version; // major firmware version number
- u16 minor_version; // minor firmware version number
- u16 build_version; // build firmware version number
+/**
+ * struct ixxat_can_msg_cl2 - IXXAT CAN message (CL2)
+ * @client_id: Client ID
+ * @data: Message data (CAN FD frame)
+ *
+ * Contains the fields of an IXXAT CAN message on CL2 devices
+ */
+struct ixxat_can_msg_cl2 {
+ __le32 client_id;
+ u8 data[CANFD_MAX_DLEN];
} __packed;
-struct ixx_usb_adapter {
- char *name;
- u32 device_id;
- struct can_clock clock;
- const struct can_bittiming_const bittiming_const;
- const struct can_bittiming_const data_bittiming_const;
-
- unsigned int ctrl_count;
-
- u32 ctrlmode_supported;
-
- int (*intf_probe)(struct usb_interface *intf);
-
- int (*dev_get_dev_caps)(struct usb_device *usb_dev, struct ixx_dev_caps* dev_caps);
- int (*dev_get_ctrl_caps)(struct usb_device *usb_dev, struct ixx_ctrl_caps* ctrl_caps, int index);
-
- int (*intf_get_info)(struct ixx_usb_device *dev, struct ixx_intf_info* intf_info);
- int (*intf_get_fw_info)(struct ixx_usb_device *dev, struct ixx_intf_fw_info* fw_info);
-
- int (*dev_init)(struct ixx_usb_device *dev);
- void (*dev_exit)(struct ixx_usb_device *dev);
- void (*dev_free)(struct ixx_usb_device *dev);
- int (*dev_open)(struct ixx_usb_device *dev);
- int (*dev_close)(struct ixx_usb_device *dev);
- int (*dev_set_bittiming)(struct ixx_usb_device *dev, struct can_bittiming *bt);
- int (*dev_set_bus)(struct ixx_usb_device *dev, u8 onoff);
- int (*dev_decode_buf)(struct ixx_usb_device *dev, struct urb *urb);
- int (*dev_encode_msg)(struct ixx_usb_device *dev, struct sk_buff *skb,
- u8 *obuf, size_t *size);
- int (*dev_start)(struct ixx_usb_device *dev);
- int (*dev_stop)(struct ixx_usb_device *dev);
- int (*dev_restart_async)(struct ixx_usb_device *dev, struct urb *urb,
- u8 *buf);
- int (*dev_power)(struct usb_device *usb_dev, u8 mode);
- u8 ep_msg_in[IXXAT_USB_MAX_CHANNEL];
- u8 ep_msg_out[IXXAT_USB_MAX_CHANNEL];
-
- int rx_buffer_size;
- int tx_buffer_size;
- int sizeof_dev_private;
-
- int has_bgi_ep;
+/**
+ * struct ixxat_can_msg - IXXAT CAN message
+ * @base: Base message
+ * @cl1: Cl1 message
+ * @cl2: Cl2 message
+ *
+ * Contains an IXXAT CAN message
+ */
+struct ixxat_can_msg {
+ struct ixxat_can_msg_base base;
+ union {
+ struct ixxat_can_msg_cl1 cl1;
+ struct ixxat_can_msg_cl2 cl2;
+ };
+} __packed;
-};
+/**
+ * struct ixxat_dev_caps - Device capabilities
+ * @bus_ctrl_count: Stores the bus controller counter
+ * @bus_ctrl_types: Stores the bus controller types
+ *
+ * Contains the device capabilities
+ */
+struct ixxat_dev_caps {
+ __le16 bus_ctrl_count;
+ __le16 bus_ctrl_types[IXXAT_USB_MAX_TYPES];
+} __packed;
+
+/**
+ * struct ixxat_canbtp Bittiming parameters (CL2)
+ * @mode: Operation mode
+ * @bps: Bits per second
+ * @ts1: TSEG 1
+ * @ts2: TSEG 2
+ * @sjw: Synchronization jump width
+ * @tdo: TDO
+ *
+ * Bittiming parameters of a CL2 initialization request
+ */
+struct ixxat_canbtp {
+ __le32 mode;
+ __le32 bps;
+ __le16 ts1;
+ __le16 ts2;
+ __le16 sjw;
+ __le16 tdo;
+} __packed;
-struct ixx_time_ref {
- struct timeval tv_host_0;
+/**
+ * struct ixxat_dev_info IXXAT usb device information
+ * @device_name: Name of the device
+ * @device_id: Device identification ( unique device id)
+ * @device_version: Device version ( 0, 1, ...)
+ * @device_fpga_version: Version of FPGA design
+ *
+ * Contains device information of IXXAT USB devices
+ */
+struct ixxat_dev_info {
+ char device_name[16];
+ char device_id[16];
+ __le16 device_version;
+ __le32 device_fpga_version;
+} __packed;
+
+/**
+ * struct ixxat_time_ref Time reference
+ * @kt_host_0: Latest time on the host
+ * @ts_dev_0: Latest time stamp on the device
+ * @ts_dev_last: Last device time stamp
+ *
+ * Contains time references of the device and the host
+ */
+struct ixxat_time_ref {
+ ktime_t kt_host_0;
u32 ts_dev_0;
u32 ts_dev_last;
};
-struct ixx_tx_urb_context {
- struct ixx_usb_device *dev;
+/**
+ * struct ixxat_tx_urb_context URB content for transmission
+ * @dev: IXXAT USB device
+ * echo_index: Echo index
+ * @dlc: Data length code
+ * @count: Counter
+ * @urb: USB request block
+ *
+ * Contains content for USB request block transmissions
+ */
+struct ixxat_tx_urb_context {
+ struct ixxat_usb_device *dev;
u32 echo_index;
u8 dlc;
u8 count;
struct urb *urb;
};
-/*IXXAT USB device */
-struct ixx_usb_device {
+/**
+ * struct ixxat_usb_device IXXAT USB device
+ * @can: CAN common private data
+ * @adapter: USB network descriptor
+ * @udev: USB device
+ * @netdev: Net_device
+ * @active_tx_urbs: Active tx urbs
+ * @tx_submitted: Submitted tx usb anchor
+ * @tx_contexts: Buffer for tx contexts
+ * @rx_submitted: Submitted rx usb anchor
+ * @state: Device state
+ * @ctrl_opened_count: Counter for opened controllers
+ * @ctrl_index: Controller index
+ * @ep_msg_in: USB endpoint for incoming messages
+ * @ep_msg_out: USB endpoint for outgoing messages
+ * @prev_dev: Previous opened device
+ * @next_dev: Next opened device in list
+ * @time_ref: Time reference
+ * @dev_info: Device information
+ * @bec: CAN error counter
+ *
+ * IXXAT USB-to-CAN device
+ */
+struct ixxat_usb_device {
struct can_priv can;
- struct ixx_usb_adapter *adapter;
- unsigned int ctrl_idx;
- u32 state;
-
- struct sk_buff *echo_skb[IXXAT_USB_MAX_TX_URBS];
-
+ const struct ixxat_usb_adapter *adapter;
struct usb_device *udev;
struct net_device *netdev;
atomic_t active_tx_urbs;
struct usb_anchor tx_submitted;
- struct ixx_tx_urb_context tx_contexts[IXXAT_USB_MAX_TX_URBS];
-
+ struct ixxat_tx_urb_context tx_contexts[IXXAT_USB_MAX_TX_URBS];
struct usb_anchor rx_submitted;
- u32 device_number;
- u8 device_rev;
+ u32 state;
+
+ u32 ctrl_opened_count;
+ u16 ctrl_index;
u8 ep_msg_in;
u8 ep_msg_out;
- u8 transmit_buffer[256];
- u8 transmit_ptr;
- u8 transmit_count;
- u8 transmit_dlc;
+ struct ixxat_usb_device *prev_dev;
+ struct ixxat_usb_device *next_dev;
+
+ struct ixxat_time_ref time_ref;
+ struct ixxat_dev_info dev_info;
+
+ struct can_berr_counter bec;
+};
+
+/**
+ * struct ixxat_usb_dal_req IXXAT device request block
+ * @req_size: Size of the request
+ * @req_port: Port of the request
+ * @req_socket: Socket of the request
+ * @req_code: Code of the request
+ *
+ * IXXAT device request block
+ */
+struct ixxat_usb_dal_req {
+ __le32 req_size;
+ __le16 req_port;
+ __le16 req_socket;
+ __le32 req_code;
+} __packed;
+
+/**
+ * struct ixxat_usb_dal_res IXXAT device response block
+ * @res_size: Size of the respond
+ * @ret_size: Size of the return
+ * @ret_code: Return code
+ *
+ * IXXAT device response block
+ */
+struct ixxat_usb_dal_res {
+ __le32 res_size;
+ __le32 ret_size;
+ __le32 ret_code;
+} __packed;
+
+/**
+ * struct ixxat_usb_dal_cmd IXXAT device command
+ * @req: Request block
+ * @req: Response block
+ *
+ * IXXAT device command
+ */
+struct ixxat_usb_dal_cmd {
+ struct ixxat_usb_dal_req req;
+ struct ixxat_usb_dal_res res;
+} __packed;
+
+/**
+ * struct ixxat_usb_caps_req Device capabilities request block
+ * @dal_req: Request block
+ *
+ * Device capabilities request block
+ */
+struct ixxat_usb_caps_req {
+ struct ixxat_usb_dal_req dal_req;
+} __packed;
- struct task_struct *restart_task;
- u8 restart_flag;
- u8 must_quit;
- wait_queue_head_t wait_queue;
+/**
+ * struct ixxat_usb_caps_res Device capabilities response block
+ * @dal_res: Response block
+ * @dev_caps: Device capabilities
+ *
+ * Device capabilities response block
+ */
+struct ixxat_usb_caps_res {
+ struct ixxat_usb_dal_res dal_res;
+ struct ixxat_dev_caps dev_caps;
+} __packed;
- struct ixx_usb_device *prev_siblings;
- struct ixx_usb_device *next_siblings;
+/**
+ * struct ixxat_usb_caps_cmd Device capabilities command
+ * @req: Request block
+ * @res: Response block
+ *
+ * Can be sent to a device to request its capabilities
+ */
+struct ixxat_usb_caps_cmd {
+ struct ixxat_usb_caps_req req;
+ struct ixxat_usb_caps_res res;
+} __packed;
+/**
+ * struct ixxat_usb_init_cl1_req Initialization request block (CL1)
+ * @dal_req: Request block
+ * @mode: Operation mode
+ * @btr0: Bittiming register 0
+ * @btr1: Bittiming register 1
+ *
+ * Initialization request block for CL1 devices
+ */
+struct ixxat_usb_init_cl1_req {
+ struct ixxat_usb_dal_req dal_req;
+ u8 mode;
u8 btr0;
u8 btr1;
+ u8 padding;
+} __packed;
+
+/**
+ * struct ixxat_usb_init_cl2_req Initialization request block (CL2)
+ * @dal_req: Request block
+ * @opmode: Operation mode
+ * @exmode: Extended mode
+ * @sdr: Stadard bittiming parameters
+ * @fdr: Fast data bittiming parameters
+ * @_padding: 2 bytes padding
+ *
+ * Initialization request block for CL2 devices
+ */
+struct ixxat_usb_init_cl2_req {
+ struct ixxat_usb_dal_req dal_req;
+ u8 opmode;
+ u8 exmode;
+ struct ixxat_canbtp sdr;
+ struct ixxat_canbtp fdr;
+ __le16 _padding;
+} __packed;
- int ctrl_opened_count;
+/**
+ * struct ixxat_usb_init_res Initialization response block
+ * @dal_res: Response block
+ *
+ * Initialization response block
+ */
+struct ixxat_usb_init_res {
+ struct ixxat_usb_dal_res dal_res;
+} __packed;
+
+/**
+ * struct ixxat_usb_init_cmd Initialization command
+ * @req_cl1: Request block for CL1 devices
+ * @req_cl2: Request block for CL2 devices
+ *
+ * Can be sent to a device to initialize it
+ */
+struct ixxat_usb_init_cmd {
+ union {
+ struct ixxat_usb_init_cl1_req req_cl1;
+ struct ixxat_usb_init_cl2_req req_cl2;
+ };
+ struct ixxat_usb_init_res res;
+} __packed;
- struct ixx_time_ref time_ref;
+/**
+ * struct ixxat_usb_start_req Controller start request block
+ * @dal_req: Request block
+ *
+ * Controller start request block
+ */
+struct ixxat_usb_start_req {
+ struct ixxat_usb_dal_req dal_req;
+} __packed;
- struct ixx_intf_info dev_info;
- struct ixx_intf_fw_info fw_info;
+/**
+ * struct ixxat_usb_start_res Controller start response block
+ * @dal_res: Response block
+ * @start_time: Device starting point
+ *
+ * Controller start response block
+ */
+struct ixxat_usb_start_res {
+ struct ixxat_usb_dal_res dal_res;
+ __le32 start_time;
+} __packed;
- struct can_berr_counter bec;
-};
+/**
+ * struct ixxat_usb_start_cmd Controller start command
+ * @req: Request block
+ * @res: Response block
+ *
+ * Can be sent to a device to start its controller
+ */
+struct ixxat_usb_start_cmd {
+ struct ixxat_usb_start_req req;
+ struct ixxat_usb_start_res res;
+} __packed;
-struct ixx_can_msg
-{
- u8 size;
- u32 time;
- u32 msg_id;
- u32 flags;
- u8 data[CAN_MAX_DLEN];
+/**
+ * struct ixxat_usb_stop_req Controller stop request block
+ * @dal_req: Request block
+ * @action: Requested action
+ *
+ * Controller stop request block
+ */
+struct ixxat_usb_stop_req {
+ struct ixxat_usb_dal_req dal_req;
+ __le32 action;
} __packed;
-struct ixx_can_msg_v2
-{
- u8 size;
- u32 time;
- u32 msg_id;
- u32 flags;
- u32 client_id;
- u8 data[CANFD_MAX_DLEN];
+/**
+ * struct ixxat_usb_stop_res Controller stop response block
+ * @dal_res: Response block
+ *
+ * Controller stop response block
+ */
+struct ixxat_usb_stop_res {
+ struct ixxat_usb_dal_res dal_res;
} __packed;
-void ixxat_dump_mem(char *prompt, void *p, int l);
+/**
+ * struct ixxat_usb_stop_cmd Controller stop command
+ * @req: Request block
+ * @res: Response block
+ *
+ * Can be sent to a device to start its controller
+ */
+struct ixxat_usb_stop_cmd {
+ struct ixxat_usb_stop_req req;
+ struct ixxat_usb_stop_res res;
+} __packed;
-void ixxat_usb_update_ts_now(struct ixx_usb_device *dev, u32 ts_now);
-void ixxat_usb_set_ts_now(struct ixx_usb_device *dev, u32 ts_now);
-void ixxat_usb_get_ts_tv(struct ixx_usb_device *dev, u32 ts,
- ktime_t* k_time);
+/**
+ * struct ixxat_usb_power_req Power request block
+ * @dal_req: Request block
+ * @mode: Power mode
+ * @_padding1: 1 byte padding
+ * @_padding2: 2 bytes padding
+ *
+ * Power request block
+ */
+struct ixxat_usb_power_req {
+ struct ixxat_usb_dal_req dal_req;
+ u8 mode;
+ u8 _padding1;
+ __le16 _padding2;
+} __packed;
+
+/**
+ * struct ixxat_usb_power_res Power response block
+ * @dal_res: Response block
+ *
+ * Power response block
+ */
+struct ixxat_usb_power_res {
+ struct ixxat_usb_dal_res dal_res;
+} __packed;
+
+/**
+ * struct ixxat_usb_power_cmd Power command
+ * @req: Request block
+ * @res: Response block
+ *
+ * Can be sent to a device to set its power mode
+ */
+struct ixxat_usb_power_cmd {
+ struct ixxat_usb_power_req req;
+ struct ixxat_usb_power_res res;
+} __packed;
+
+/**
+ * struct ixxat_usb_info_req Device information request block
+ * @dal_req: Request block
+ *
+ * Device information request block
+ */
+struct ixxat_usb_info_req {
+ struct ixxat_usb_dal_req dal_req;
+} __packed;
+
+/**
+ * struct ixxat_usb_info_res Device information response block
+ * @dal_res: Response block
+ * @info: Device information
+ *
+ * Device information response block
+ */
+struct ixxat_usb_info_res {
+ struct ixxat_usb_dal_res dal_res;
+ struct ixxat_dev_info info;
+} __packed;
+
+/**
+ * struct ixxat_usb_info_cmd Device information command
+ * @req: Request block
+ * @res: Response block
+ *
+ * Can be sent to a device to request its device information
+ */
+struct ixxat_usb_info_cmd {
+ struct ixxat_usb_info_req req;
+ struct ixxat_usb_info_res res;
+} __packed;
+
+/**
+ * struct ixxat_usb_adapter IXXAT USB device adapter
+ * @clock: Clock frequency
+ * @bt: Bittiming constants
+ * @btd: Data bittiming constants
+ * @modes: Supported modes
+ * @buffer_size_rx: Buffer size for receiving
+ * @buffer_size_tx: Buffer size for transfer
+ * @ep_msg_in: USB endpoint buffer for incoming messages
+ * @ep_msg_out: USB endpoint buffer for outgoing messages
+ * @ep_offs: Endpoint offset (device depended)
+ *
+ * Device Adapter for IXXAT USB devices
+ */
+struct ixxat_usb_adapter {
+ const u32 clock;
+ const struct can_bittiming_const *bt;
+ const struct can_bittiming_const *btd;
+ const u32 modes;
+ const u16 buffer_size_rx;
+ const u16 buffer_size_tx;
+ const u8 ep_msg_in[IXXAT_USB_MAX_CHANNEL];
+ const u8 ep_msg_out[IXXAT_USB_MAX_CHANNEL];
+ const u8 ep_offs;
+ int (*init_ctrl)(struct ixxat_usb_device *dev);
+};
+
+extern const struct ixxat_usb_adapter usb2can_cl1;
+extern const struct ixxat_usb_adapter usb2can_cl2;
+extern const struct ixxat_usb_adapter can_idm100;
+extern const struct ixxat_usb_adapter can_idm101;
+
+/**
+ * ixxat_usb_setup_cmd() - Setup a device command
+ * @req: Request block
+ * @res: Response block
+ *
+ * This function sets the default values in the request and the response block
+ * of a device command
+ */
+void ixxat_usb_setup_cmd(struct ixxat_usb_dal_req *req,
+ struct ixxat_usb_dal_res *res);
+
+/**
+ * ixxat_usb_send_cmd() - Send a command to the device
+ * @dev: USB device
+ * @dal_req: Requested command
+ *
+ * This function sends a specific command to the device.
+ *
+ * Return: Error, if one occurred else 0
+ */
+int ixxat_usb_send_cmd(struct usb_device *dev, struct ixxat_usb_dal_req *req);
+
+/**
+ * ixxat_usb_rcv_cmd() - Receive a command from the device
+ * @dev: USB device
+ * @dal_req: Responded command
+ * @value: Requested values
+ *
+ * This function receives a response to a device request
+ *
+ * Return: Error, if one occurred else 0
+ */
+int ixxat_usb_rcv_cmd(struct usb_device *dev, struct ixxat_usb_dal_res *res,
+ int value);
-void ixxat_usb_async_complete(struct urb *urb);
-void ixxat_usb_restart_complete(struct ixx_usb_device *dev);
-#endif
+#endif /* IXXAT_USB_CORE_H */
diff --git a/ubuntu/ixxat/ixx_usb_fd.c b/ubuntu/ixxat/ixx_usb_fd.c
deleted file mode 100644
index 63d5b9944a85..000000000000
--- a/ubuntu/ixxat/ixx_usb_fd.c
+++ /dev/null
@@ -1,1673 +0,0 @@
-/*
- * CAN driver for IXXAT USB-to-CAN FD
- *
- * Copyright (C) 2017 Michael Hengler <mhengler at ixxat.de>
- *
- * Based on code originally by pcan_usb_core
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#include <linux/netdevice.h>
-#include <linux/usb.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/can.h>
-#include <linux/can/dev.h>
-#include <linux/can/error.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/types.h>
-#include <linux/gfp.h>
-#include <asm-generic/errno.h>
-#include <stdarg.h>
-
-#include "ixx_usb_core.h"
-
-#ifdef CANFD_CAPABLE
-
-MODULE_SUPPORTED_DEVICE("IXXAT Automation GmbH USB-to-CAN FD");
-
-/* use ifi can fd clock due to internal bittiming calculations */
-#define IFIFD_CRYSTAL_HZ 80000000
-
-/* usb-to-can fd Endpoints */
-#define IXXAT_USBFD_EP_CMDOUT 0
-#define IXXAT_USBFD_EP_CMDIN (IXXAT_USBFD_EP_CMDOUT | USB_DIR_IN)
-#define IXXAT_USBFD_EP_MSGOUT_0 1
-#define IXXAT_USBFD_EP_MSGIN_0 (IXXAT_USBFD_EP_MSGOUT_0 | USB_DIR_IN)
-#define IXXAT_USBFD_EP_MSGOUT_1 2
-#define IXXAT_USBFD_EP_MSGIN_1 (IXXAT_USBFD_EP_MSGOUT_1 | USB_DIR_IN)
-#define IXXAT_USBFD_EP_MSGOUT_2 3
-#define IXXAT_USBFD_EP_MSGIN_2 (IXXAT_USBFD_EP_MSGOUT_2 | USB_DIR_IN)
-#define IXXAT_USBFD_EP_MSGOUT_3 4
-#define IXXAT_USBFD_EP_MSGIN_3 (IXXAT_USBFD_EP_MSGOUT_3 | USB_DIR_IN)
-#define IXXAT_USBFD_EP_MSGOUT_4 5
-#define IXXAT_USBFD_EP_MSGIN_4 (IXXAT_USBFD_EP_MSGOUT_4 | USB_DIR_IN)
-
-/* DELL Edge GW3002 Endpoints */
-#define DELL_EDGE_GW3002_EP_MSGOUT_0 1
-#define DELL_EDGE_GW3002_EP_MSGIN_0 (2 | USB_DIR_IN)
-#define DELL_EDGE_GW3002_EP_MSGOUT_1 3
-#define DELL_EDGE_GW3002_EP_MSGIN_1 (4 | USB_DIR_IN)
-#define DELL_EDGE_GW3002_EP_MSGOUT_2 5
-#define DELL_EDGE_GW3002_EP_MSGIN_2 (6 | USB_DIR_IN)
-#define DELL_EDGE_GW3002_EP_MSGOUT_3 7
-#define DELL_EDGE_GW3002_EP_MSGIN_3 (8 | USB_DIR_IN)
-#define DELL_EDGE_GW3002_EP_MSGOUT_4 9
-#define DELL_EDGE_GW3002_EP_MSGIN_4 (10 | USB_DIR_IN)
-
-/* usb-to-can fd rx/tx buffers size */
-#define IXXAT_USBFD_RX_BUFFER_SIZE 512
-#define IXXAT_USBFD_TX_BUFFER_SIZE 512
-
-#define IXXAT_USBFD_CMD_BUFFER_SIZE 256
-
-/* reception of 11-bit id messages */
-#define IXXAT_USBFD_OPMODE_STANDARD 0x01
-/* reception of 29-bit id messages */
-#define IXXAT_USBFD_OPMODE_EXTENDED 0x02
-/* enable reception of error frames */
-#define IXXAT_USBFD_OPMODE_ERRFRAME 0x04
-/* listen only mode (TX passive) */
-#define IXXAT_USBFD_OPMODE_LISTONLY 0x08
-
-/* no extended operation */
-#define IXXAT_USBFD_EXMODE_DISABLED 0x00
-/* extended data length */
-#define IXXAT_USBFD_EXMODE_EXTDATA 0x01
-/* fast data bit rate */
-#define IXXAT_USBFD_EXMODE_FASTDATA 0x02
-/* ISO conform CAN-FD frame */
-#define IXXAT_USBFD_EXMODE_ISOFD 0x04
-
-/* Stuff error */
-#define IXXAT_USBFD_CAN_ERROR_STUFF 1
-/* Form error */
-#define IXXAT_USBFD_CAN_ERROR_FORM 2
-/* Acknowledgment error */
-#define IXXAT_USBFD_CAN_ERROR_ACK 3
-/* Bit error */
-#define IXXAT_USBFD_CAN_ERROR_BIT 4
-/* Fast data bit rate error */
-#define IXXAT_USBFD_CAN_ERROR_FAST_DATA 5
-/* CRC error */
-#define IXXAT_USBFD_CAN_ERROR_CRC 6
-/* Other (unspecified) error */
-#define IXXAT_USBFD_CAN_ERROR_OTHER 7
-
-/* Data overrun occurred */
-#define IXXAT_USBFD_CAN_STATUS_OVRRUN 0x02
-/* Error warning limit exceeded */
-#define IXXAT_USBFD_CAN_STATUS_ERRLIM 0x04
-/* Bus off status */
-#define IXXAT_USBFD_CAN_STATUS_BUSOFF 0x08
-
-#define IXXAT_USBFD_CAN_DATA 0x00
-#define IXXAT_USBFD_CAN_INFO 0x01
-#define IXXAT_USBFD_CAN_ERROR 0x02
-#define IXXAT_USBFD_CAN_STATUS 0x03
-#define IXXAT_USBFD_CAN_WAKEUP 0x04
-#define IXXAT_USBFD_CAN_TIMEOVR 0x05
-#define IXXAT_USBFD_CAN_TIMERST 0x06
-
-
-#define IXXAT_USBFD_MSG_FLAGS_TYPE 0x000000FF
-#define IXXAT_USBFD_MSG_FLAGS_SSM 0x00000100
-#define IXXAT_USBFD_MSG_FLAGS_HPM 0x00000200
-#define IXXAT_USBFD_MSG_FLAGS_EDL 0x00000400
-#define IXXAT_USBFD_MSG_FLAGS_FDR 0x00000800
-#define IXXAT_USBFD_MSG_FLAGS_ESI 0x00001000
-#define IXXAT_USBFD_MSG_FLAGS_RES 0x0000E000
-#define IXXAT_USBFD_MSG_FLAGS_DLC 0x000F0000
-#define IXXAT_USBFD_MSG_FLAGS_OVR 0x00100000
-#define IXXAT_USBFD_MSG_FLAGS_SRR 0x00200000
-#define IXXAT_USBFD_MSG_FLAGS_RTR 0x00400000
-#define IXXAT_USBFD_MSG_FLAGS_EXT 0x00800000
-#define IXXAT_USBFD_MSG_FLAGS_AFC 0xFF000000
-
-#define IXXAT_USBFD_BAL_CMD_CLASS 3
-#define IXXAT_USBFD_BRD_CMD_CLASS 4
-
-#define IXXAT_USBFD_BRD_CMD_CAT 0
-#define IXXAT_USBFD_CAN_CMD_CAT 1
-
-#define IXXAT_USBFD_VCI_CMD_CODE(Class, Function) \
- ((u32) (((Class) << 8) | (Function)))
-
-#define IXXAT_USBFD_BRD_CMD_CODE(Category, Function) \
- IXXAT_USBFD_VCI_CMD_CODE(IXXAT_USBFD_BRD_CMD_CLASS, \
- ((Category) << 5) | (Function))
-
-#define IXXAT_USBFD_BAL_CMD_CODE(Category, Function) \
- IXXAT_USBFD_VCI_CMD_CODE(IXXAT_USBFD_BAL_CMD_CLASS, \
- ((Category) << 5) | (Function))
-
-#define IXXAT_USBFD_CAN_GET_CAPS_CMD \
- IXXAT_USBFD_BAL_CMD_CODE(IXXAT_USBFD_CAN_CMD_CAT, 0)
-#define IXXAT_USBFD_POWER_CMD \
- IXXAT_USBFD_BRD_CMD_CODE(IXXAT_USBFD_CAN_CMD_CAT, 1)
-#define IXXAT_USBFD_CAN_INIT_CMD \
- IXXAT_USBFD_BAL_CMD_CODE(IXXAT_USBFD_CAN_CMD_CAT, 5)
-#define IXXAT_USBFD_CAN_START_CMD \
- IXXAT_USBFD_BAL_CMD_CODE(IXXAT_USBFD_CAN_CMD_CAT, 6)
-#define IXXAT_USBFD_CAN_STOP_CMD \
- IXXAT_USBFD_BAL_CMD_CODE(IXXAT_USBFD_CAN_CMD_CAT, 7)
-#define IXXAT_USBFD_CAN_RESET_CMD \
- IXXAT_USBFD_BAL_CMD_CODE(IXXAT_USBFD_CAN_CMD_CAT, 8)
-/* Additional commands for USB-to-CAN FD */
-#define IXXAT_USBFD_INIT_V2_CMD \
- IXXAT_USBFD_BAL_CMD_CODE(IXXAT_USBFD_CAN_CMD_CAT, 23)
-
-#define IXXAT_USBFD_BRD_GET_FWINFO_CMD \
- IXXAT_USBFD_BRD_CMD_CODE(IXXAT_USBFD_BRD_CMD_CAT, 0)
-#define IXXAT_USBFD_BRD_GET_DEVCAPS_CMD \
- IXXAT_USBFD_BRD_CMD_CODE(IXXAT_USBFD_BRD_CMD_CAT, 1)
-#define IXXAT_USBFD_BRD_GET_DEVINFO_CMD \
- IXXAT_USBFD_BRD_CMD_CODE(IXXAT_USBFD_BRD_CMD_CAT, 2)
-
-struct ixx_usbfd_dal_req {
- u32 req_size;
- u16 req_port;
- u16 req_socket;
- u32 req_code;
-} __packed;
-
-struct ixx_usbfd_dal_res {
- u32 res_size;
- u32 ret_size;
- u32 ret_code;
-} __packed;
-
-// Additional structures for the for USB-to-CAN FD
-
-struct ixx_usbfd_dev_power_req {
- struct ixx_usbfd_dal_req dal_req;
- u8 mode;
- u8 _padding1;
- u16 _padding2;
-} __packed;
-
-struct ixx_usbfd_dev_power_res {
- struct ixx_usbfd_dal_res dal_res;
-} __packed;
-
-struct ixx_usbfd_ctrl_init_v2_req {
- struct ixx_usbfd_dal_req dal_req;
- u8 opmode;
- u8 exmode;
- struct canbtp sdr;
- struct canbtp fdr;
- u16 _padding;
-} __packed;
-
-struct ixx_usbfd_ctrl_init_v2_res {
- struct ixx_usbfd_dal_res dal_res;
-} __packed;
-
-struct ixx_usbfd_dev_caps_req {
- struct ixx_usbfd_dal_req dal_req;
-} __packed;
-
-struct ixx_usbfd_dev_caps_res {
- struct ixx_usbfd_dal_res dal_res;
- struct ixx_dev_caps dev_caps;
-} __packed;
-
-struct ixx_usbfd_ctrl_caps_req {
- struct ixx_usbfd_dal_req dal_req;
-} __packed;
-
-struct ixx_usbfd_ctrl_caps_res {
- struct ixx_usbfd_dal_res dal_res;
- struct ixx_ctrl_caps ctrl_caps;
-} __packed;
-
-struct ixx_usbfd_ctrl_init_req {
- struct ixx_usbfd_dal_req dal_req;
- u8 mode;
- u8 btr0;
- u8 btr1;
- u8 padding;
-} __packed;
-
-struct ixx_usbfd_ctrl_init_res {
- struct ixx_usbfd_dal_res dal_res;
-} __packed;
-
-struct ixx_usbfd_ctrl_start_req {
- struct ixx_usbfd_dal_req dal_req;
-} __packed;
-
-struct ixx_usbfd_ctrl_start_res {
- struct ixx_usbfd_dal_res dal_res;
- u32 start_time;
-} __packed;
-
-struct ixx_usbfd_ctrl_stop_req {
- struct ixx_usbfd_dal_req dal_req;
- u32 action;
-} __packed;
-
-struct ixx_usbfd_ctrl_stop_res {
- struct ixx_usbfd_dal_res dal_res;
-} __packed;
-
-struct ixx_usbfd_brd_get_fwinfo_req {
- struct ixx_usbfd_dal_req dal_req;
-} __packed;
-
-struct ixx_usbfd_brd_get_fwinfo_res {
- struct ixx_usbfd_dal_res dal_res;
- struct ixx_intf_fw_info fwinfo;
-} __packed;
-
-struct ixx_usbfd_brd_get_intf_info_req {
- struct ixx_usbfd_dal_req dal_req;
-} __packed;
-
-struct ixx_usbfd_brd_get_intf_info_res {
- struct ixx_usbfd_dal_res dal_res;
- struct ixx_intf_info info;
-} __packed;
-
-/*
- * send usb-to-can fd command synchronously
- */
-static int ixx_usbfd_send_cmd(struct usb_device *dev,
- struct ixx_usbfd_dal_req *dal_req)
-{
- int err, i;
- u16 size, value;
- u8 request, requesttype;
- u8 *buf;
-
- request = 0xff;
- requesttype = USB_TYPE_VENDOR | USB_DIR_OUT;
- value = le16_to_cpu(dal_req->req_port);
- size = le32_to_cpu(dal_req->req_size) +
- sizeof(const struct ixx_usbfd_dal_res);
-
- buf = kmalloc(size, GFP_KERNEL);
- if(!buf)
- return -ENOMEM;
- memcpy(buf, (u8 *)dal_req, size);
-
- for (i = 0; i < 10; ++i) {
- err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request,
- requesttype,
- value,
- 0,
- buf,
- size,
- msecs_to_jiffies(50));
-
- if (err < 0)
- msleep(20);
- else
- break;
- }
-
- kfree(buf);
-
- if (err < 0) {
- dev_err(&dev->dev, "sending command failure: %d\n", err);
- return err;
- }
-
- return 0;
-}
-
-/*
- * receive usb-to-can fd command synchronously
- */
-static int ixx_usbfd_rcv_cmd(struct usb_device *dev,
- struct ixx_usbfd_dal_res *dal_res, int value)
-{
- int err, res_size, i, size_to_read;
- u8 request, requesttype;
- u8 *buf;
-
- request = 0xff;
- requesttype = USB_TYPE_VENDOR | USB_DIR_IN;
- res_size = 0;
- size_to_read = le32_to_cpu(dal_res->res_size);
-
- buf = kmalloc(size_to_read, GFP_KERNEL);
- if(!buf)
- return -ENOMEM;
-
- for (i = 0; i < 10; ++i) {
- err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), request,
- requesttype, value,
- 0, buf + (u8) res_size,
- size_to_read - res_size, msecs_to_jiffies(50));
-
- if (err < 0) {
- msleep(20);
- continue;
- }
-
- res_size += err;
- if (res_size < size_to_read)
- msleep(20);
- else
- break;
- }
-
- if (res_size != size_to_read)
- err = -EBADMSG;
-
- if (err < 0) {
- dev_err(&dev->dev, "receiving command failure: %d\n", err);
- kfree(buf);
- return err;
- }
-
- memcpy((u8 *)dal_res, buf, size_to_read);
- kfree(buf);
-
- return err;
-}
-
-static int ixx_usbfd_init_ctrl(struct ixx_usb_device *dev, u8 mode,
- u8 exmode,
- struct can_bittiming *arbitration_phase,
- struct can_bittiming *data_phase)
-{
- int err = -ENODEV;
- u8 data[IXXAT_USBFD_CMD_BUFFER_SIZE] = { 0 };
- struct ixx_usbfd_ctrl_init_v2_req *ctrl_init_req;
- struct ixx_usbfd_ctrl_init_v2_res *ctrl_init_res;
- u32 req_size = sizeof(*ctrl_init_req);
-
- ctrl_init_req = (struct ixx_usbfd_ctrl_init_v2_req *) data;
- ctrl_init_res = (struct ixx_usbfd_ctrl_init_v2_res *)(data + req_size);
-
- ctrl_init_req->dal_req.req_size = cpu_to_le32(req_size);
- ctrl_init_req->dal_req.req_code =
- cpu_to_le32(IXXAT_USBFD_INIT_V2_CMD);
- ctrl_init_req->dal_req.req_port = cpu_to_le16(dev->ctrl_idx);
- ctrl_init_req->dal_req.req_socket = 0xffff;
- ctrl_init_req->opmode = mode;
- ctrl_init_req->exmode = exmode;
-
- ctrl_init_req->sdr.mode = cpu_to_le32(IXX_BTMODE_NAT);
- ctrl_init_req->sdr.bps = cpu_to_le32(arbitration_phase->brp);
- ctrl_init_req->sdr.ts1 =
- cpu_to_le16(arbitration_phase->prop_seg +
- arbitration_phase->phase_seg1);
- ctrl_init_req->sdr.ts2 = cpu_to_le16(arbitration_phase->phase_seg2);
- ctrl_init_req->sdr.sjw = cpu_to_le16(arbitration_phase->sjw);
- ctrl_init_req->sdr.tdo = 0;
-
- if (exmode) {
- ctrl_init_req->fdr.mode = cpu_to_le32(IXX_BTMODE_NAT);
- ctrl_init_req->fdr.bps = cpu_to_le32(data_phase->brp);
- ctrl_init_req->fdr.ts1 =
- cpu_to_le16(data_phase->prop_seg +
- data_phase->phase_seg1);
- ctrl_init_req->fdr.ts2 = cpu_to_le16(data_phase->phase_seg2);
- ctrl_init_req->fdr.sjw = cpu_to_le16(data_phase->sjw);
- ctrl_init_req->fdr.tdo =
- cpu_to_le16((1 + data_phase->phase_seg1 +
- data_phase->prop_seg) *
- data_phase->brp);
- }
-
- ctrl_init_res->dal_res.res_size =
- cpu_to_le32(sizeof(*ctrl_init_res));
- ctrl_init_res->dal_res.ret_size = 0;
- ctrl_init_res->dal_res.ret_code = 0xffffffff;
-
- err = ixx_usbfd_send_cmd(dev->udev, &ctrl_init_req->dal_req);
- if (err < 0)
- return err;
-
- err = ixx_usbfd_rcv_cmd(dev->udev,
- &ctrl_init_res->dal_res,
- dev->ctrl_idx);
- if (err < 0)
- return err;
-
- return le32_to_cpu(ctrl_init_res->dal_res.ret_code);
-}
-
-static int ixx_usbfd_start_ctrl(struct ixx_usb_device *dev, u32 *time_ref)
-{
- int err = -ENODEV;
- u8 data[IXXAT_USBFD_CMD_BUFFER_SIZE] = { 0 };
- struct ixx_usbfd_ctrl_start_req *ctrl_start_req;
- struct ixx_usbfd_ctrl_start_res *ctrl_start_res;
- u32 req_size = sizeof(*ctrl_start_req);
-
- ctrl_start_req = (struct ixx_usbfd_ctrl_start_req *) data;
- ctrl_start_res = (struct ixx_usbfd_ctrl_start_res *)(data + req_size);
-
- ctrl_start_req->dal_req.req_size = cpu_to_le32(req_size);
- ctrl_start_req->dal_req.req_code =
- cpu_to_le32(IXXAT_USBFD_CAN_START_CMD);
- ctrl_start_req->dal_req.req_port = cpu_to_le16(dev->ctrl_idx);
- ctrl_start_req->dal_req.req_socket = 0xffff;
-
- ctrl_start_res->dal_res.res_size =
- cpu_to_le32(sizeof(*ctrl_start_res));
- ctrl_start_res->dal_res.ret_size = 0;
- ctrl_start_res->dal_res.ret_code = 0xffffffff;
- ctrl_start_res->start_time = 0;
-
- err = ixx_usbfd_send_cmd(dev->udev, &ctrl_start_req->dal_req);
- if (err < 0)
- return err;
-
- err = ixx_usbfd_rcv_cmd(dev->udev,
- &ctrl_start_res->dal_res,
- dev->ctrl_idx);
- if (err < 0)
- return err;
-
- if (time_ref)
- *time_ref = le32_to_cpu(ctrl_start_res->start_time);
-
- return le32_to_cpu(ctrl_start_res->dal_res.ret_code);
-}
-
-static int ixx_usbfd_stop_ctrl(struct ixx_usb_device *dev)
-{
- int err = -ENODEV;
- u8 data[IXXAT_USBFD_CMD_BUFFER_SIZE] = { 0 };
- struct ixx_usbfd_ctrl_stop_req *ctrl_stop_req;
- struct ixx_usbfd_ctrl_stop_res *ctrl_stop_res;
- u32 req_size = sizeof(*ctrl_stop_req);
-
- ctrl_stop_req = (struct ixx_usbfd_ctrl_stop_req *) data;
- ctrl_stop_res = (struct ixx_usbfd_ctrl_stop_res *)(data + req_size);
-
- ctrl_stop_req->dal_req.req_size = cpu_to_le32(req_size);
- ctrl_stop_req->dal_req.req_code =
- cpu_to_le32(IXXAT_USBFD_CAN_STOP_CMD);
- ctrl_stop_req->dal_req.req_port = cpu_to_le16(dev->ctrl_idx);
- ctrl_stop_req->dal_req.req_socket = 0xffff;
- ctrl_stop_req->action = cpu_to_le32(0x3);
-
- ctrl_stop_res->dal_res.res_size =
- cpu_to_le32(sizeof(*ctrl_stop_res));
- ctrl_stop_res->dal_res.ret_size = 0;
- ctrl_stop_res->dal_res.ret_code = 0xffffffff;
-
- err = ixx_usbfd_send_cmd(dev->udev, &ctrl_stop_req->dal_req);
- if (err < 0)
- return err;
-
- err = ixx_usbfd_rcv_cmd(dev->udev,
- &ctrl_stop_res->dal_res,
- dev->ctrl_idx);
- if (err < 0)
- return err;
-
- if (!le32_to_cpu(ctrl_stop_res->dal_res.ret_code))
- dev->can.state = CAN_STATE_STOPPED;
-
- return le32_to_cpu(ctrl_stop_res->dal_res.ret_code);
-}
-
-static int ixx_usbfd_reset_ctrl(struct ixx_usb_device *dev)
-{
- int err = -ENODEV;
- u8 data[IXXAT_USBFD_CMD_BUFFER_SIZE] = { 0 };
- struct ixx_usbfd_dal_req *dal_req;
- struct ixx_usbfd_dal_res *dal_res;
- u32 req_size = sizeof(*dal_req);
-
- dal_req = (struct ixx_usbfd_dal_req *) data;
- dal_res = (struct ixx_usbfd_dal_res *)(data + req_size);
-
- dal_req->req_size = cpu_to_le32(req_size);
- dal_req->req_code = cpu_to_le32(IXXAT_USBFD_CAN_RESET_CMD);
- dal_req->req_port = cpu_to_le16(dev->ctrl_idx);
- dal_req->req_socket = 0xffff;
-
- dal_res->res_size = cpu_to_le32(sizeof(*dal_res));
- dal_res->ret_size = 0;
- dal_res->ret_code = 0xffffffff;
-
- err = ixx_usbfd_send_cmd(dev->udev, dal_req);
- if (err < 0)
- return err;
-
- err = ixx_usbfd_rcv_cmd(dev->udev, dal_res,
- dev->ctrl_idx);
- if (err < 0)
- return err;
-
- return le32_to_cpu(dal_res->ret_code);
-}
-
-static int ixx_usbfd_power_ctrl(struct usb_device *dev, u8 mode)
-{
- int err = -ENODEV;
- u8 data[IXXAT_USBFD_CMD_BUFFER_SIZE] = { 0 };
- struct ixx_usbfd_dev_power_req *ctrl_power_req;
- struct ixx_usbfd_dev_power_res *ctrl_power_res;
- u32 req_size = sizeof(*ctrl_power_req);
-
- ctrl_power_req = (struct ixx_usbfd_dev_power_req *) data;
- ctrl_power_res = (struct ixx_usbfd_dev_power_res *)(data + req_size);
-
- ctrl_power_req->dal_req.req_size = cpu_to_le32(req_size);
- ctrl_power_req->dal_req.req_code =
- cpu_to_le32(IXXAT_USBFD_POWER_CMD);
- ctrl_power_req->dal_req.req_port = cpu_to_le16(0xffff);
- ctrl_power_req->dal_req.req_socket = 0xffff;
- ctrl_power_req->mode = mode;
-
- ctrl_power_res->dal_res.res_size =
- cpu_to_le32(sizeof(*ctrl_power_res));
- ctrl_power_res->dal_res.ret_size = 0;
- ctrl_power_res->dal_res.ret_code = 0xffffffff;
-
- err = ixx_usbfd_send_cmd(dev, &ctrl_power_req->dal_req);
- if (err < 0)
- return err;
-
- err = ixx_usbfd_rcv_cmd(dev,
- &ctrl_power_res->dal_res,
- 0xffff);
- if (err < 0)
- return err;
-
- return le32_to_cpu(ctrl_power_res->dal_res.ret_code);
-}
-
-/*
- * handle restart but in asynchronously way
- */
-static int ixx_usbfd_restart_task(void *user_data)
-{
- u32 time_ref;
- struct ixx_usb_device *dev = user_data;
-
- while (!kthread_should_stop()) {
- if (!dev->must_quit) {
- wait_event_interruptible(dev->wait_queue,
- dev->restart_flag);
- if (!dev->must_quit) {
- ixx_usbfd_stop_ctrl(dev);
- ixx_usbfd_start_ctrl(dev, &time_ref);
- dev->restart_flag = 0;
- dev->can.state = CAN_STATE_ERROR_ACTIVE;
- }
- } else
- msleep(20);
- }
- return 0;
-}
-
-static int ixx_usbfd_handle_canmsg(struct ixx_usb_device *dev,
- struct ixx_can_msg_v2 *rx)
-{
- struct net_device *netdev = dev->netdev;
- struct canfd_frame *can_frame;
- struct sk_buff *skb;
- const u32 flags = le32_to_cpu(rx->flags);
-
- if (flags & IXXAT_USBFD_MSG_FLAGS_EDL)
- skb = alloc_canfd_skb(netdev, &can_frame);
- else
- skb = alloc_can_skb(netdev, (struct can_frame **)&can_frame);
-
- if (!skb)
- return -ENOMEM;
-
- if (flags & IXXAT_USBFD_MSG_FLAGS_EDL) {
- if (flags & IXXAT_USBFD_MSG_FLAGS_FDR)
- can_frame->flags |= CANFD_BRS;
-
- if (flags & IXXAT_USBFD_MSG_FLAGS_ESI)
- can_frame->flags |= CANFD_ESI;
-
- can_frame->len =
- can_dlc2len(
- get_canfd_dlc((flags & IXXAT_USBFD_MSG_FLAGS_DLC)
- >> 16));
- } else {
- can_frame->len =
- get_canfd_dlc((flags & IXXAT_USBFD_MSG_FLAGS_DLC)
- >> 16);
- }
-
- if (flags & IXXAT_USBFD_MSG_FLAGS_OVR) {
- netdev->stats.rx_over_errors++;
- netdev->stats.rx_errors++;
- }
-
- can_frame->can_id = le32_to_cpu(rx->msg_id);
-
- if (flags & IXXAT_USBFD_MSG_FLAGS_EXT)
- can_frame->can_id |= CAN_EFF_FLAG;
-
- if (flags & IXXAT_USBFD_MSG_FLAGS_RTR)
- can_frame->can_id |= CAN_RTR_FLAG;
- else
- memcpy(can_frame->data, rx->data, can_frame->len);
-
- ixxat_usb_get_ts_tv(dev, le32_to_cpu(rx->time), &skb->tstamp);
-
- netif_rx(skb);
- netdev->stats.rx_packets++;
- netdev->stats.rx_bytes += can_frame->len;
-
- return 0;
-}
-
-static int ixx_usbfd_handle_error(struct ixx_usb_device *dev,
- struct ixx_can_msg_v2 *rx)
-{
- struct net_device *netdev = dev->netdev;
- struct can_frame *can_frame;
- struct sk_buff *skb;
- u8 raw_status = 0;
-
- /* nothing should be sent while in BUS_OFF state */
- if (dev->can.state == CAN_STATE_BUS_OFF)
- return 0;
-
- raw_status = rx->data[0];
-
- /* allocate an skb to store the error frame */
- skb = alloc_can_err_skb(netdev, &can_frame);
- if (!skb)
- return -ENOMEM;
-
- switch (raw_status) {
- case IXXAT_USBFD_CAN_ERROR_ACK:
- can_frame->can_id |= CAN_ERR_ACK;
- netdev->stats.tx_errors++;
- break;
- case IXXAT_USBFD_CAN_ERROR_BIT:
- can_frame->can_id |= CAN_ERR_PROT;
- can_frame->data[2] |= CAN_ERR_PROT_BIT;
- netdev->stats.rx_errors++;
- break;
- case IXXAT_USBFD_CAN_ERROR_CRC:
- can_frame->can_id |= CAN_ERR_PROT;
- can_frame->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ;
- netdev->stats.rx_errors++;
- break;
- case IXXAT_USBFD_CAN_ERROR_FORM:
- can_frame->can_id |= CAN_ERR_PROT;
- can_frame->data[2] |= CAN_ERR_PROT_FORM;
- netdev->stats.rx_errors++;
- break;
- case IXXAT_USBFD_CAN_ERROR_STUFF:
- can_frame->can_id |= CAN_ERR_PROT;
- can_frame->data[2] |= CAN_ERR_PROT_STUFF;
- netdev->stats.rx_errors++;
- break;
- case IXXAT_USBFD_CAN_ERROR_OTHER:
- can_frame->can_id |= CAN_ERR_PROT;
- can_frame->data[2] |= CAN_ERR_PROT_UNSPEC;
- netdev->stats.rx_errors++;
- break;
- default:
- can_frame->can_id |= CAN_ERR_PROT;
- netdev->stats.rx_errors++;
- }
-
- netif_rx(skb);
- netdev->stats.rx_packets++;
- netdev->stats.rx_bytes += can_frame->can_dlc;
-
- dev->bec.txerr = le16_to_cpu(rx->data[1]);
- dev->bec.rxerr = le16_to_cpu(rx->data[3]);
-
- return 0;
-}
-
-static int ixx_usbfd_handle_status(struct ixx_usb_device *dev,
- struct ixx_can_msg_v2 *rx)
-{
- struct net_device *netdev = dev->netdev;
- struct can_frame *can_frame;
- struct sk_buff *skb;
- u8 raw_status = 0;
- u32 new_state = 0;
-
- raw_status = rx->data[0];
-
- /* nothing should be sent while in BUS_OFF state */
- if (dev->can.state == CAN_STATE_BUS_OFF)
- return 0;
-
- if (!raw_status) {
- /* no error bit (back to active state) */
- dev->can.state = CAN_STATE_ERROR_ACTIVE;
-
- dev->bec.txerr = 0;
- dev->bec.rxerr = 0;
- return 0;
- }
-
- /* allocate an skb to store the error frame */
- skb = alloc_can_err_skb(netdev, &can_frame);
- if (!skb)
- return -ENOMEM;
-
- if (raw_status & IXXAT_USBFD_CAN_STATUS_BUSOFF) {
- can_frame->can_id |= CAN_ERR_BUSOFF;
- new_state = CAN_STATE_BUS_OFF;
- dev->can.can_stats.bus_off++;
- can_bus_off(netdev);
- } else {
- if (raw_status & IXXAT_USBFD_CAN_STATUS_ERRLIM) {
- can_frame->can_id |= CAN_ERR_CRTL;
- can_frame->data[1] |= CAN_ERR_CRTL_TX_WARNING;
- can_frame->data[1] |= CAN_ERR_CRTL_RX_WARNING;
- dev->can.can_stats.error_warning++;
- new_state = CAN_STATE_ERROR_WARNING;
- }
-
- if (raw_status & IXXAT_USBFD_CAN_STATUS_OVRRUN) {
- can_frame->can_id |= CAN_ERR_PROT;
- can_frame->data[2] |= CAN_ERR_PROT_OVERLOAD;
- netdev->stats.rx_over_errors++;
- netdev->stats.rx_errors++;
- }
-
- if (!new_state) {
- new_state = CAN_STATE_ERROR_ACTIVE;
-
- dev->bec.txerr = 0;
- dev->bec.rxerr = 0;
- }
- }
-
- dev->can.state = new_state;
-
- netif_rx(skb);
- netdev->stats.rx_packets++;
- netdev->stats.rx_bytes += can_frame->can_dlc;
-
- return 0;
-}
-
-/*
- * callback for bulk IN urb
- */
-static int ixx_usbfd_decode_buf(struct ixx_usb_device *dev, struct urb *urb)
-{
- struct net_device *netdev = dev->netdev;
- struct ixx_can_msg_v2 *can_msg;
- u32 msg_end;
- int err = 0;
- u32 read_size = 0;
- u8 msg_type;
-
- u8 *data = urb->transfer_buffer;
-
- /* loop reading all the records from the incoming message */
- msg_end = urb->actual_length;
- for (; msg_end > 0;) {
- can_msg = (struct ixx_can_msg_v2 *) &data[read_size];
-
- if (!can_msg || !can_msg->size) {
- netdev_err(netdev, "got unsupported rec in usb msg:\n");
- err = -ENOTSUPP;
- break;
- }
-
- /* check if the record goes out of current packet */
- if ((read_size + can_msg->size + 1) > urb->actual_length) {
- netdev_err(netdev,
- "got frag rec: should inc usb rx buf size\n");
- err = -EBADMSG;
- break;
- }
-
- msg_type = (le32_to_cpu(can_msg->flags) &
- IXXAT_USBFD_MSG_FLAGS_TYPE);
-
- switch (msg_type) {
-
- case IXXAT_USBFD_CAN_DATA:
- err = ixx_usbfd_handle_canmsg(dev, can_msg);
- if (err < 0)
- goto fail;
- break;
-
- case IXXAT_USBFD_CAN_STATUS:
- err = ixx_usbfd_handle_status(dev, can_msg);
- if (err < 0)
- goto fail;
- break;
-
- case IXXAT_USBFD_CAN_ERROR:
- err = ixx_usbfd_handle_error(dev, can_msg);
- if (err < 0)
- goto fail;
- break;
-
- case IXXAT_USBFD_CAN_TIMEOVR:
- ixxat_usb_get_ts_tv(dev, can_msg->time, NULL);
- break;
-
- case IXXAT_USBFD_CAN_INFO:
- case IXXAT_USBFD_CAN_WAKEUP:
- case IXXAT_USBFD_CAN_TIMERST:
- break;
-
- default:
- netdev_err(netdev,
- "unhandled rec type 0x%02x (%d): ignored\n",
- msg_type, msg_type);
- break;
- }
-
- read_size += can_msg->size + 1;
- msg_end -= (can_msg->size + 1);
- }
-
-fail:
- if (err)
- ixxat_dump_mem("received msg", urb->transfer_buffer,
- urb->actual_length);
-
- return err;
-}
-
-static int ixx_usbfd_encode_msg(struct ixx_usb_device *dev, struct sk_buff *skb,
- u8 *obuf, size_t *size)
-{
- struct canfd_frame *cf = (struct canfd_frame *) skb->data;
- struct ixx_can_msg_v2 can_msg = { 0 };
-
- if (cf->can_id & CAN_RTR_FLAG)
- can_msg.flags |= IXXAT_USBFD_MSG_FLAGS_RTR;
-
- if (cf->can_id & CAN_EFF_FLAG) {
- can_msg.flags |= IXXAT_USBFD_MSG_FLAGS_EXT;
- can_msg.msg_id = cf->can_id & CAN_EFF_MASK;
- } else {
- can_msg.msg_id = cf->can_id & CAN_SFF_MASK;
- }
-
- if (dev->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
- can_msg.flags |= IXXAT_USBFD_MSG_FLAGS_SSM;
-
- if (skb->len == CANFD_MTU) {
- can_msg.flags |= IXXAT_USBFD_MSG_FLAGS_EDL;
-
- if (!(cf->can_id & CAN_RTR_FLAG) && (cf->flags & CANFD_BRS))
- can_msg.flags |= IXXAT_USBFD_MSG_FLAGS_FDR;
- }
-
- can_msg.flags |= (can_len2dlc(cf->len) << 16) &
- IXXAT_USBFD_MSG_FLAGS_DLC;
-
- can_msg.flags = cpu_to_le32(can_msg.flags);
- can_msg.msg_id = cpu_to_le32(can_msg.msg_id);
-
- memcpy(can_msg.data, cf->data, cf->len);
- can_msg.size = (u8)(sizeof(can_msg) - 1 - CANFD_MAX_DLEN + cf->len);
-
- memcpy(obuf, &can_msg, can_msg.size + 1);
-
- *size = can_msg.size + 1;
-
- skb->data_len = *size;
-
- return 0;
-}
-
-static int ixx_usbfd_start(struct ixx_usb_device *dev)
-{
- int err;
- u32 time_ref = 0;
- u8 can_opmode = IXXAT_USBFD_OPMODE_EXTENDED
- | IXXAT_USBFD_OPMODE_STANDARD;
- u8 can_exmode = 0;
-
- if (dev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
- can_opmode |= IXXAT_USBFD_OPMODE_ERRFRAME;
- if (dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
- can_opmode |= IXXAT_USBFD_OPMODE_LISTONLY;
-
- if ((CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO) & dev->can.ctrlmode)
- can_exmode |= IXXAT_USBFD_EXMODE_EXTDATA |
- IXXAT_USBFD_EXMODE_FASTDATA;
-
- if (!(CAN_CTRLMODE_FD_NON_ISO & dev->can.ctrlmode) && can_exmode)
- can_exmode |= IXXAT_USBFD_EXMODE_ISOFD;
-
- /* Try to reset the controller, in case it is already initalized
- from a previous unclean shutdown */
- ixx_usbfd_reset_ctrl(dev);
-
- err = ixx_usbfd_init_ctrl(dev, can_opmode,
- can_exmode,
- &dev->can.bittiming,
- &dev->can.data_bittiming);
- if (err)
- return err;
-
- /* opening first device: */
- if (dev->ctrl_opened_count == 0) {
- err = ixx_usbfd_start_ctrl(dev, &time_ref);
- if (err)
- return err;
-
- ixxat_usb_set_ts_now(dev, time_ref);
- }
-
- dev->ctrl_opened_count++;
-
- dev->bec.txerr = 0;
- dev->bec.rxerr = 0;
-
- return err;
-}
-
-/*
- * stop interface
- * (last chance before set bus off)
- */
-static int ixx_usbfd_stop(struct ixx_usb_device *dev)
-{
- int err;
-
- if (dev->ctrl_opened_count == 1) {
- err = ixx_usbfd_stop_ctrl(dev);
- if (err)
- return err;
- }
-
- dev->ctrl_opened_count--;
-
- return 0;
-}
-
-/*
- * called when probing to initialize a device object.
- */
-static int ixx_usbfd_init(struct ixx_usb_device *dev)
-{
- dev->restart_task = kthread_run(&ixx_usbfd_restart_task, dev,
- "restart_thread");
- if (!dev->restart_task)
- return -ENOBUFS;
-
- return 0;
-}
-
-static void ixx_usbfd_exit(struct ixx_usb_device *dev)
-{
- ixx_usbfd_reset_ctrl(dev);
-
- dev->must_quit = 1;
- dev->restart_flag = 1;
- wake_up_interruptible(&dev->wait_queue);
- if (dev->restart_task)
- kthread_stop(dev->restart_task);
-}
-
-/*
- * probe function for new IXXAT USB-to-CAN FD interface
- */
-static int ixx_usbfd_probe(struct usb_interface *intf)
-{
- struct usb_host_interface *if_desc;
- int i;
-
- if_desc = intf->altsetting;
-
- /* check interface endpoint addresses */
- for (i = 0; i < if_desc->desc.bNumEndpoints; i++) {
- struct usb_endpoint_descriptor *ep = &if_desc->endpoint[i].desc;
-
- /*
- * below is the list of valid ep addreses. Any other ep address
- * is considered as not-CAN interface address => no dev created
- */
- switch (ep->bEndpointAddress) {
- case IXXAT_USBFD_EP_MSGOUT_0:
- case IXXAT_USBFD_EP_MSGOUT_1:
- case IXXAT_USBFD_EP_MSGOUT_2:
- case IXXAT_USBFD_EP_MSGOUT_3:
- case IXXAT_USBFD_EP_MSGOUT_4:
- case IXXAT_USBFD_EP_MSGIN_0:
- case IXXAT_USBFD_EP_MSGIN_1:
- case IXXAT_USBFD_EP_MSGIN_2:
- case IXXAT_USBFD_EP_MSGIN_3:
- case IXXAT_USBFD_EP_MSGIN_4:
-
- break;
- default:
- return -ENODEV;
- }
- }
-
- return 0;
-}
-
-static int ixx_usbfd_get_dev_caps(struct usb_device *dev,
- struct ixx_dev_caps *dev_caps)
-{
- int err = -ENODEV, i;
- u8 data[IXXAT_USBFD_CMD_BUFFER_SIZE] = { 0 };
- struct ixx_usbfd_dev_caps_req *dev_caps_req;
- struct ixx_usbfd_dev_caps_res *dev_caps_res;
- u32 req_size = sizeof(*dev_caps_req);
-
- dev_caps_req = (struct ixx_usbfd_dev_caps_req *) data;
- dev_caps_res = (struct ixx_usbfd_dev_caps_res *)(data + req_size);
-
- dev_caps_req->dal_req.req_size = cpu_to_le32(req_size);
- dev_caps_req->dal_req.req_code =
- cpu_to_le32(IXXAT_USBFD_BRD_GET_DEVCAPS_CMD);
- dev_caps_req->dal_req.req_port = 0xffff;
- dev_caps_req->dal_req.req_socket = 0xffff;
-
- dev_caps_res->dal_res.res_size = cpu_to_le32(
- sizeof(*dev_caps_res));
- dev_caps_res->dal_res.ret_size = 0;
- dev_caps_res->dal_res.ret_code = 0xffffffff;
-
- err = ixx_usbfd_send_cmd(dev, &dev_caps_req->dal_req);
- if (err < 0)
- return err;
-
- err = ixx_usbfd_rcv_cmd(dev, &dev_caps_res->dal_res,
- 0xffff);
- if (err < 0)
- return err;
-
- dev_caps->bus_ctrl_count =
- le16_to_cpu(dev_caps_res->dev_caps.bus_ctrl_count);
- for (i = 0; i < dev_caps->bus_ctrl_count; ++i)
- dev_caps->bus_ctrl_types[i] =
- le16_to_cpu(dev_caps_res->dev_caps.bus_ctrl_types[i]);
-
- return 0;
-}
-
-static int ixx_usbfd_get_ctrl_caps(struct usb_device *dev,
- struct ixx_ctrl_caps *ctrl_caps, int index)
-{
- int err = -ENODEV;
- u8 data[IXXAT_USBFD_CMD_BUFFER_SIZE] = { 0 };
- struct ixx_usbfd_ctrl_caps_req *ctrl_caps_req;
- struct ixx_usbfd_ctrl_caps_res *ctrl_caps_res;
- u32 req_size = sizeof(*ctrl_caps_req);
-
- ctrl_caps_req = (struct ixx_usbfd_ctrl_caps_req *) data;
- ctrl_caps_res = (struct ixx_usbfd_ctrl_caps_res *)(data + req_size);
-
- ctrl_caps_req->dal_req.req_size = cpu_to_le32(req_size);
- ctrl_caps_req->dal_req.req_code =
- cpu_to_le32(IXXAT_USBFD_CAN_GET_CAPS_CMD);
- ctrl_caps_req->dal_req.req_port = cpu_to_le16(index);
- ctrl_caps_req->dal_req.req_socket = 0xffff;
-
- ctrl_caps_res->dal_res.res_size =
- cpu_to_le32(sizeof(*ctrl_caps_res));
- ctrl_caps_res->dal_res.ret_size = 0;
- ctrl_caps_res->dal_res.ret_code = 0xffffffff;
-
- err = ixx_usbfd_send_cmd(dev, &ctrl_caps_req->dal_req);
- if (err < 0)
- return err;
-
- err = ixx_usbfd_rcv_cmd(dev,
- &ctrl_caps_res->dal_res,
- index);
- if (err < 0)
- return err;
-
- ctrl_caps->bus_coupling =
- le16_to_cpu(ctrl_caps_res->ctrl_caps.bus_coupling);
- ctrl_caps->clock_freq =
- le32_to_cpu(ctrl_caps_res->ctrl_caps.clock_freq);
- ctrl_caps->cms_divisor =
- le32_to_cpu(ctrl_caps_res->ctrl_caps.cms_divisor);
- ctrl_caps->cms_max_ticks =
- le32_to_cpu(ctrl_caps_res->ctrl_caps.cms_max_ticks);
- ctrl_caps->ctrl_type = le16_to_cpu(ctrl_caps_res->ctrl_caps.ctrl_type);
- ctrl_caps->dtx_divisor =
- le32_to_cpu(ctrl_caps_res->ctrl_caps.dtx_divisor);
- ctrl_caps->dtx_max_ticks =
- le32_to_cpu(ctrl_caps_res->ctrl_caps.dtx_max_ticks);
- ctrl_caps->features = le32_to_cpu(ctrl_caps_res->ctrl_caps.features);
- ctrl_caps->tsc_divisor =
- le32_to_cpu(ctrl_caps_res->ctrl_caps.tsc_divisor);
-
- return 0;
-}
-
-static int ixx_usbfd_get_fwinfo(struct ixx_usb_device *dev,
- struct ixx_intf_fw_info *fwinfo)
-{
- int err = -ENODEV;
- u8 data[IXXAT_USBFD_CMD_BUFFER_SIZE] = { 0 };
- struct ixx_usbfd_brd_get_fwinfo_req *fw_info_req;
- struct ixx_usbfd_brd_get_fwinfo_res *fw_info_res;
- u32 req_size = sizeof(*fw_info_req);
-
- fw_info_req = (struct ixx_usbfd_brd_get_fwinfo_req *) data;
- fw_info_res = (struct ixx_usbfd_brd_get_fwinfo_res *)(data + req_size);
-
- fw_info_req->dal_req.req_size = cpu_to_le32(req_size);
- fw_info_req->dal_req.req_code =
- cpu_to_le32(IXXAT_USBFD_BRD_GET_FWINFO_CMD);
- fw_info_req->dal_req.req_port = 0xffff;
- fw_info_req->dal_req.req_socket = 0xffff;
-
- fw_info_res->dal_res.res_size =
- cpu_to_le32(sizeof(*fw_info_res));
- fw_info_res->dal_res.ret_size = 0;
- fw_info_res->dal_res.ret_code = 0xffffffff;
-
- err = ixx_usbfd_send_cmd(dev->udev, &fw_info_req->dal_req);
- if (err < 0)
- return err;
-
- err = ixx_usbfd_rcv_cmd(dev->udev,
- &fw_info_res->dal_res, 0xffff);
- if (err < 0)
- return err;
-
- if (fwinfo) {
- fwinfo->build_version = le16_to_cpu(
- fw_info_res->fwinfo.build_version);
- fwinfo->firmware_type = le32_to_cpu(
- fw_info_res->fwinfo.firmware_type);
- fwinfo->major_version = le16_to_cpu(
- fw_info_res->fwinfo.major_version);
- fwinfo->minor_version = le16_to_cpu(
- fw_info_res->fwinfo.minor_version);
- fwinfo->reserved = le16_to_cpu(fw_info_res->fwinfo.reserved);
- }
-
- return le32_to_cpu(fw_info_res->dal_res.ret_code);
-}
-
-static int ixx_usbfd_get_dev_info(struct ixx_usb_device *dev,
- struct ixx_intf_info *dev_info)
-{
- int err = -ENODEV;
- u8 data[IXXAT_USBFD_CMD_BUFFER_SIZE] = { 0 };
- struct ixx_usbfd_brd_get_intf_info_req *dev_info_req;
- struct ixx_usbfd_brd_get_intf_info_res *dev_info_res;
- u32 req_size = sizeof(*dev_info_req);
-
- dev_info_req = (struct ixx_usbfd_brd_get_intf_info_req *) data;
- dev_info_res =
- (struct ixx_usbfd_brd_get_intf_info_res *)(data + req_size);
-
- dev_info_req->dal_req.req_size = cpu_to_le32(req_size);
- dev_info_req->dal_req.req_code =
- cpu_to_le32(IXXAT_USBFD_BRD_GET_DEVINFO_CMD);
- dev_info_req->dal_req.req_port = 0xffff;
- dev_info_req->dal_req.req_socket = 0xffff;
-
- dev_info_res->dal_res.res_size =
- cpu_to_le32(sizeof(*dev_info_res));
- dev_info_res->dal_res.ret_size = 0;
- dev_info_res->dal_res.ret_code = 0xffffffff;
-
- err = ixx_usbfd_send_cmd(dev->udev,
- &dev_info_req->dal_req);
- if (err < 0)
- return err;
-
- err = ixx_usbfd_rcv_cmd(dev->udev,
- &dev_info_res->dal_res,
- 0xffff);
- if (err < 0)
- return err;
-
- if (dev_info) {
- memcpy(dev_info->device_id, &dev_info_res->info.device_id,
- sizeof(dev_info_res->info.device_id));
- memcpy(dev_info->device_name, &dev_info_res->info.device_name,
- sizeof(dev_info_res->info.device_name));
- dev_info->device_fpga_version = le16_to_cpu(
- dev_info_res->info.device_fpga_version);
- dev_info->device_version = le32_to_cpu(
- dev_info_res->info.device_version);
- }
-
- return le32_to_cpu(dev_info_res->dal_res.ret_code);
-}
-
-/*
- * describes the USB-to-CAN FD automotive adapter
- */
-struct ixx_usb_adapter usb_to_can_fd_automotive = {
- .name = "USB-to-CAN FD automotive",
- .device_id = USB_TO_CAN_FD_AUTOMOTIVE_PRODUCT_ID,
- .clock = {
- .freq = IFIFD_CRYSTAL_HZ,
- },
-
- .bittiming_const = {
- .name = "ifi_can",
- .tseg1_min = 1,
- .tseg1_max = 256,
- .tseg2_min = 1,
- .tseg2_max = 256,
- .sjw_max = 128,
- .brp_min = 2,
- .brp_max = 513,
- .brp_inc = 1, },
-
- .data_bittiming_const = {
- .name = "ifi_can",
- .tseg1_min = 1,
- .tseg1_max = 256,
- .tseg2_min = 1,
- .tseg2_max = 256,
- .sjw_max = 128,
- .brp_min = 2,
- .brp_max = 513,
- .brp_inc = 1, },
-
- .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
- CAN_CTRLMODE_LISTENONLY |
- CAN_CTRLMODE_LOOPBACK |
- CAN_CTRLMODE_BERR_REPORTING |
- CAN_CTRLMODE_FD |
- CAN_CTRLMODE_FD_NON_ISO,
-
- /* size of device private data */
- .sizeof_dev_private = sizeof(const struct ixx_usb_device),
-
- /* give here messages in/out endpoints */
- .ep_msg_in = { IXXAT_USBFD_EP_MSGIN_0, IXXAT_USBFD_EP_MSGIN_1,
- IXXAT_USBFD_EP_MSGIN_2, IXXAT_USBFD_EP_MSGIN_3,
- IXXAT_USBFD_EP_MSGIN_4 },
- .ep_msg_out = { IXXAT_USBFD_EP_MSGOUT_0, IXXAT_USBFD_EP_MSGOUT_1,
- IXXAT_USBFD_EP_MSGOUT_2, IXXAT_USBFD_EP_MSGOUT_3,
- IXXAT_USBFD_EP_MSGOUT_4 },
-
- /* size of rx/tx usb buffers */
- .rx_buffer_size = IXXAT_USBFD_RX_BUFFER_SIZE,
- .tx_buffer_size = IXXAT_USBFD_TX_BUFFER_SIZE,
-
- /* device callbacks */
- .intf_probe = ixx_usbfd_probe,
- .dev_get_dev_caps = ixx_usbfd_get_dev_caps,
- .dev_get_ctrl_caps = ixx_usbfd_get_ctrl_caps,
- .dev_init = ixx_usbfd_init,
- .dev_exit = ixx_usbfd_exit,
- .intf_get_info = ixx_usbfd_get_dev_info,
- .intf_get_fw_info = ixx_usbfd_get_fwinfo,
- .dev_decode_buf = ixx_usbfd_decode_buf,
- .dev_encode_msg = ixx_usbfd_encode_msg,
- .dev_start = ixx_usbfd_start,
- .dev_stop = ixx_usbfd_stop,
- .dev_power = ixx_usbfd_power_ctrl,
- .has_bgi_ep = 1,
-};
-
-/*
- * describes the USB-to-CAN FD compact adapter
- */
-struct ixx_usb_adapter usb_to_can_fd_compact = {
- .name = "USB-to-CAN FD compact",
- .device_id = USB_TO_CAN_FD_COMPACT_PRODUCT_ID,
- .clock = {
- .freq = IFIFD_CRYSTAL_HZ,
- },
-
- .bittiming_const = {
- .name = "ifi_can",
- .tseg1_min = 1,
- .tseg1_max = 256,
- .tseg2_min = 1,
- .tseg2_max = 256,
- .sjw_max = 128,
- .brp_min = 2,
- .brp_max = 513,
- .brp_inc = 1, },
-
- .data_bittiming_const = {
- .name = "ifi_can",
- .tseg1_min = 1,
- .tseg1_max = 256,
- .tseg2_min = 1,
- .tseg2_max = 256,
- .sjw_max = 128,
- .brp_min = 2,
- .brp_max = 513,
- .brp_inc = 1, },
-
- .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
- CAN_CTRLMODE_LISTENONLY |
- CAN_CTRLMODE_LOOPBACK |
- CAN_CTRLMODE_BERR_REPORTING |
- CAN_CTRLMODE_FD |
- CAN_CTRLMODE_FD_NON_ISO,
-
- /* size of device private data */
- .sizeof_dev_private = sizeof(const struct ixx_usb_device),
-
- /* give here messages in/out endpoints */
- .ep_msg_in = { IXXAT_USBFD_EP_MSGIN_0, IXXAT_USBFD_EP_MSGIN_1,
- IXXAT_USBFD_EP_MSGIN_2, IXXAT_USBFD_EP_MSGIN_3,
- IXXAT_USBFD_EP_MSGIN_4 },
- .ep_msg_out = { IXXAT_USBFD_EP_MSGOUT_0, IXXAT_USBFD_EP_MSGOUT_1,
- IXXAT_USBFD_EP_MSGOUT_2, IXXAT_USBFD_EP_MSGOUT_3,
- IXXAT_USBFD_EP_MSGOUT_4 },
-
- /* size of rx/tx usb buffers */
- .rx_buffer_size = IXXAT_USBFD_RX_BUFFER_SIZE,
- .tx_buffer_size = IXXAT_USBFD_TX_BUFFER_SIZE,
-
- /* device callbacks */
- .intf_probe = ixx_usbfd_probe,
- .dev_get_dev_caps = ixx_usbfd_get_dev_caps,
- .dev_get_ctrl_caps = ixx_usbfd_get_ctrl_caps,
- .dev_init = ixx_usbfd_init,
- .dev_exit = ixx_usbfd_exit,
- .intf_get_info = ixx_usbfd_get_dev_info,
- .intf_get_fw_info = ixx_usbfd_get_fwinfo,
- .dev_decode_buf = ixx_usbfd_decode_buf,
- .dev_encode_msg = ixx_usbfd_encode_msg,
- .dev_start = ixx_usbfd_start,
- .dev_stop = ixx_usbfd_stop,
- .dev_power = ixx_usbfd_power_ctrl,
- .has_bgi_ep = 1,
-};
-
-/*
- * describes the DELL Edge GW3002
- */
-struct ixx_usb_adapter dell_edge_gw3002 = {
- .name = "USB DELL Edge GW3002",
- .device_id = DELL_EDGE_GW3002_PRODUCT_ID,
- .clock = {
- .freq = IFIFD_CRYSTAL_HZ,
- },
-
- .bittiming_const = {
- .name = "mcan",
- .tseg1_min = 1,
- .tseg1_max = 64,
- .tseg2_min = 1,
- .tseg2_max = 16,
- .sjw_max = 16,
- .brp_min = 1,
- .brp_max = 1024,
- .brp_inc = 1, },
-
- .data_bittiming_const = {
- .name = "mcan",
- .tseg1_min = 1,
- .tseg1_max = 16,
- .tseg2_min = 1,
- .tseg2_max = 8,
- .sjw_max = 4,
- .brp_min = 1,
- .brp_max = 32,
- .brp_inc = 1, },
-
- .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
- CAN_CTRLMODE_LISTENONLY |
- CAN_CTRLMODE_LOOPBACK |
- CAN_CTRLMODE_BERR_REPORTING
-
- /* currently not supported
- CAN_CTRLMODE_FD |
- CAN_CTRLMODE_FD_NON_ISO
- */,
-
- /* size of device private data */
- .sizeof_dev_private = sizeof(const struct ixx_usb_device),
-
- /* give here messages in/out endpoints */
- .ep_msg_in = { DELL_EDGE_GW3002_EP_MSGIN_0, DELL_EDGE_GW3002_EP_MSGIN_1,
- DELL_EDGE_GW3002_EP_MSGIN_2, DELL_EDGE_GW3002_EP_MSGIN_3,
- DELL_EDGE_GW3002_EP_MSGIN_4 },
- .ep_msg_out = { DELL_EDGE_GW3002_EP_MSGOUT_0, DELL_EDGE_GW3002_EP_MSGOUT_1,
- DELL_EDGE_GW3002_EP_MSGOUT_2, DELL_EDGE_GW3002_EP_MSGOUT_3,
- DELL_EDGE_GW3002_EP_MSGOUT_4 },
-
- /* size of rx/tx usb buffers */
- .rx_buffer_size = IXXAT_USBFD_RX_BUFFER_SIZE,
- .tx_buffer_size = IXXAT_USBFD_TX_BUFFER_SIZE,
-
- /* device callbacks */
- .intf_probe = ixx_usbfd_probe,
- .dev_get_dev_caps = ixx_usbfd_get_dev_caps,
- .dev_get_ctrl_caps = ixx_usbfd_get_ctrl_caps,
- .dev_init = ixx_usbfd_init,
- .dev_exit = ixx_usbfd_exit,
- .intf_get_info = ixx_usbfd_get_dev_info,
- .intf_get_fw_info = ixx_usbfd_get_fwinfo,
- .dev_decode_buf = ixx_usbfd_decode_buf,
- .dev_encode_msg = ixx_usbfd_encode_msg,
- .dev_start = ixx_usbfd_start,
- .dev_stop = ixx_usbfd_stop,
- .dev_power = ixx_usbfd_power_ctrl,
- .has_bgi_ep = 0,
-};
-
-/*
- * describes the USB-to-CAN FD professional adapter
- */
-struct ixx_usb_adapter usb_to_can_fd_professional = {
- .name = "USB-to-CAN FD professional",
- .device_id = USB_TO_CAN_FD_PROFESSIONAL_PRODUCT_ID,
- .clock = {
- .freq = IFIFD_CRYSTAL_HZ,
- },
-
- .bittiming_const = {
- .name = "ifi_can",
- .tseg1_min = 1,
- .tseg1_max = 256,
- .tseg2_min = 1,
- .tseg2_max = 256,
- .sjw_max = 128,
- .brp_min = 2,
- .brp_max = 513,
- .brp_inc = 1, },
-
- .data_bittiming_const = {
- .name = "ifi_can",
- .tseg1_min = 1,
- .tseg1_max = 256,
- .tseg2_min = 1,
- .tseg2_max = 256,
- .sjw_max = 128,
- .brp_min = 2,
- .brp_max = 513,
- .brp_inc = 1, },
-
- .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
- CAN_CTRLMODE_LISTENONLY |
- CAN_CTRLMODE_LOOPBACK |
- CAN_CTRLMODE_BERR_REPORTING |
- CAN_CTRLMODE_FD |
- CAN_CTRLMODE_FD_NON_ISO,
-
- /* size of device private data */
- .sizeof_dev_private = sizeof(const struct ixx_usb_device),
-
- /* give here messages in/out endpoints */
- .ep_msg_in = { IXXAT_USBFD_EP_MSGIN_0, IXXAT_USBFD_EP_MSGIN_1,
- IXXAT_USBFD_EP_MSGIN_2, IXXAT_USBFD_EP_MSGIN_3,
- IXXAT_USBFD_EP_MSGIN_4 },
- .ep_msg_out = { IXXAT_USBFD_EP_MSGOUT_0, IXXAT_USBFD_EP_MSGOUT_1,
- IXXAT_USBFD_EP_MSGOUT_2, IXXAT_USBFD_EP_MSGOUT_3,
- IXXAT_USBFD_EP_MSGOUT_4 },
-
- /* size of rx/tx usb buffers */
- .rx_buffer_size = IXXAT_USBFD_RX_BUFFER_SIZE,
- .tx_buffer_size = IXXAT_USBFD_TX_BUFFER_SIZE,
-
- /* device callbacks */
- .intf_probe = ixx_usbfd_probe,
- .dev_get_dev_caps = ixx_usbfd_get_dev_caps,
- .dev_get_ctrl_caps = ixx_usbfd_get_ctrl_caps,
- .dev_init = ixx_usbfd_init,
- .dev_exit = ixx_usbfd_exit,
- .intf_get_info = ixx_usbfd_get_dev_info,
- .intf_get_fw_info = ixx_usbfd_get_fwinfo,
- .dev_decode_buf = ixx_usbfd_decode_buf,
- .dev_encode_msg = ixx_usbfd_encode_msg,
- .dev_start = ixx_usbfd_start,
- .dev_stop = ixx_usbfd_stop,
- .dev_power = ixx_usbfd_power_ctrl,
- .has_bgi_ep = 1,
-};
-
-/*
- * describes the USB-to-CAN FD PCIe mini adapter
- */
-struct ixx_usb_adapter usb_to_can_fd_pcie_mini = {
- .name = "USB-to-CAN FD PCIe mini",
- .device_id = USB_TO_CAN_FD_PCIE_MINI_PRODUCT_ID,
- .clock = {
- .freq = IFIFD_CRYSTAL_HZ,
- },
-
- .bittiming_const = {
- .name = "ifi_can",
- .tseg1_min = 1,
- .tseg1_max = 256,
- .tseg2_min = 1,
- .tseg2_max = 256,
- .sjw_max = 128,
- .brp_min = 2,
- .brp_max = 513,
- .brp_inc = 1, },
-
- .data_bittiming_const = {
- .name = "ifi_can",
- .tseg1_min = 1,
- .tseg1_max = 256,
- .tseg2_min = 1,
- .tseg2_max = 256,
- .sjw_max = 128,
- .brp_min = 2,
- .brp_max = 513,
- .brp_inc = 1, },
-
- .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
- CAN_CTRLMODE_LISTENONLY |
- CAN_CTRLMODE_LOOPBACK |
- CAN_CTRLMODE_BERR_REPORTING |
- CAN_CTRLMODE_FD |
- CAN_CTRLMODE_FD_NON_ISO,
-
- /* size of device private data */
- .sizeof_dev_private = sizeof(const struct ixx_usb_device),
-
- /* give here messages in/out endpoints */
- .ep_msg_in = { IXXAT_USBFD_EP_MSGIN_0, IXXAT_USBFD_EP_MSGIN_1,
- IXXAT_USBFD_EP_MSGIN_2, IXXAT_USBFD_EP_MSGIN_3,
- IXXAT_USBFD_EP_MSGIN_4 },
- .ep_msg_out = { IXXAT_USBFD_EP_MSGOUT_0, IXXAT_USBFD_EP_MSGOUT_1,
- IXXAT_USBFD_EP_MSGOUT_2, IXXAT_USBFD_EP_MSGOUT_3,
- IXXAT_USBFD_EP_MSGOUT_4 },
-
- /* size of rx/tx usb buffers */
- .rx_buffer_size = IXXAT_USBFD_RX_BUFFER_SIZE,
- .tx_buffer_size = IXXAT_USBFD_TX_BUFFER_SIZE,
-
- /* device callbacks */
- .intf_probe = ixx_usbfd_probe,
- .dev_get_dev_caps = ixx_usbfd_get_dev_caps,
- .dev_get_ctrl_caps = ixx_usbfd_get_ctrl_caps,
- .dev_init = ixx_usbfd_init,
- .dev_exit = ixx_usbfd_exit,
- .intf_get_info = ixx_usbfd_get_dev_info,
- .intf_get_fw_info = ixx_usbfd_get_fwinfo,
- .dev_decode_buf = ixx_usbfd_decode_buf,
- .dev_encode_msg = ixx_usbfd_encode_msg,
- .dev_start = ixx_usbfd_start,
- .dev_stop = ixx_usbfd_stop,
- .dev_power = ixx_usbfd_power_ctrl,
- .has_bgi_ep = 1,
-};
-
-/*
- * describes the USB-to-CAR adapter
- */
-struct ixx_usb_adapter usb_to_car = {
- .name = "USB-to-CAR",
- .device_id = USB_TO_CAR_ID,
- .clock = {
- .freq = IFIFD_CRYSTAL_HZ,
- },
-
- .bittiming_const = {
- .name = "ifi_can",
- .tseg1_min = 1,
- .tseg1_max = 256,
- .tseg2_min = 1,
- .tseg2_max = 256,
- .sjw_max = 128,
- .brp_min = 2,
- .brp_max = 513,
- .brp_inc = 1, },
-
- .data_bittiming_const = {
- .name = "ifi_can",
- .tseg1_min = 1,
- .tseg1_max = 256,
- .tseg2_min = 1,
- .tseg2_max = 256,
- .sjw_max = 128,
- .brp_min = 2,
- .brp_max = 513,
- .brp_inc = 1, },
-
- .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
- CAN_CTRLMODE_LISTENONLY |
- CAN_CTRLMODE_LOOPBACK |
- CAN_CTRLMODE_BERR_REPORTING |
- CAN_CTRLMODE_FD |
- CAN_CTRLMODE_FD_NON_ISO,
-
- /* size of device private data */
- .sizeof_dev_private = sizeof(const struct ixx_usb_device),
-
- /* give here messages in/out endpoints */
- .ep_msg_in = { IXXAT_USBFD_EP_MSGIN_0, IXXAT_USBFD_EP_MSGIN_1,
- IXXAT_USBFD_EP_MSGIN_2, IXXAT_USBFD_EP_MSGIN_3,
- IXXAT_USBFD_EP_MSGIN_4 },
- .ep_msg_out = { IXXAT_USBFD_EP_MSGOUT_0, IXXAT_USBFD_EP_MSGOUT_1,
- IXXAT_USBFD_EP_MSGOUT_2, IXXAT_USBFD_EP_MSGOUT_3,
- IXXAT_USBFD_EP_MSGOUT_4 },
-
- /* size of rx/tx usb buffers */
- .rx_buffer_size = IXXAT_USBFD_RX_BUFFER_SIZE,
- .tx_buffer_size = IXXAT_USBFD_TX_BUFFER_SIZE,
-
- /* device callbacks */
- .intf_probe = ixx_usbfd_probe,
- .dev_get_dev_caps = ixx_usbfd_get_dev_caps,
- .dev_get_ctrl_caps = ixx_usbfd_get_ctrl_caps,
- .dev_init = ixx_usbfd_init,
- .dev_exit = ixx_usbfd_exit,
- .intf_get_info = ixx_usbfd_get_dev_info,
- .intf_get_fw_info = ixx_usbfd_get_fwinfo,
- .dev_decode_buf = ixx_usbfd_decode_buf,
- .dev_encode_msg = ixx_usbfd_encode_msg,
- .dev_start = ixx_usbfd_start,
- .dev_stop = ixx_usbfd_stop,
- .dev_power = ixx_usbfd_power_ctrl,
- .has_bgi_ep = 1,
-};
-
-
-#endif // CANFD_CAPABLE
diff --git a/ubuntu/ixxat/ixx_usb_v2.c b/ubuntu/ixxat/ixx_usb_v2.c
deleted file mode 100644
index 3fe639c5b817..000000000000
--- a/ubuntu/ixxat/ixx_usb_v2.c
+++ /dev/null
@@ -1,1450 +0,0 @@
-/*
- * CAN driver for IXXAT USB-to-CAN V2
- *
- * Copyright (C) 2014 Michael Hengler <mhengler at ixxat.de>
- *
- * Based on code originally by pcan_usb_core
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#include <linux/netdevice.h>
-#include <linux/usb.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/can.h>
-#include <linux/can/dev.h>
-#include <linux/can/error.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/types.h>
-#include <linux/gfp.h>
-#include <asm-generic/errno.h>
-#include <stdarg.h>
-
-#include "ixx_usb_core.h"
-
-MODULE_SUPPORTED_DEVICE("IXXAT Automation GmbH USB-to-CAN V2");
-
-/* use sja 1000 clock due to internal bittiming calculations */
-#define SJA1000_CRYSTAL_HZ 8000000
-
-/* usb-to-can v2 Endpoints */
-#define IXXAT_USBV2_EP_CMDOUT 0
-#define IXXAT_USBV2_EP_CMDIN (IXXAT_USBV2_EP_CMDOUT | USB_DIR_IN)
-#define IXXAT_USBV2_EP_MSGOUT_0 1
-#define IXXAT_USBV2_EP_MSGIN_0 (IXXAT_USBV2_EP_MSGOUT_0 | USB_DIR_IN)
-#define IXXAT_USBV2_EP_MSGOUT_1 2
-#define IXXAT_USBV2_EP_MSGIN_1 (IXXAT_USBV2_EP_MSGOUT_1 | USB_DIR_IN)
-#define IXXAT_USBV2_EP_MSGOUT_2 3
-#define IXXAT_USBV2_EP_MSGIN_2 (IXXAT_USBV2_EP_MSGOUT_2 | USB_DIR_IN)
-#define IXXAT_USBV2_EP_MSGOUT_3 4
-#define IXXAT_USBV2_EP_MSGIN_3 (IXXAT_USBV2_EP_MSGOUT_3 | USB_DIR_IN)
-#define IXXAT_USBV2_EP_MSGOUT_4 5
-#define IXXAT_USBV2_EP_MSGIN_4 (IXXAT_USBV2_EP_MSGOUT_4 | USB_DIR_IN)
-
-/* usb-to-can v2 rx/tx buffers size */
-#define IXXAT_USBV2_RX_BUFFER_SIZE 512
-#define IXXAT_USBV2_TX_BUFFER_SIZE 256
-
-#define IXXAT_USBV2_CMD_BUFFER_SIZE 256
-
-#define IXXAT_USBV2_OPMODE_STANDARD 0x01 /* reception of 11-bit id messages */
-#define IXXAT_USBV2_OPMODE_EXTENDED 0x02 /* reception of 29-bit id messages */
-#define IXXAT_USBV2_OPMODE_ERRFRAME 0x04 /* enable reception of error frames */
-#define IXXAT_USBV2_OPMODE_LISTONLY 0x08 /* listen only mode (TX passive) */
-
-/* Stuff error */
-#define IXXAT_USBV2_CAN_ERROR_STUFF 1
-/* Form error */
-#define IXXAT_USBV2_CAN_ERROR_FORM 2
-/* Acknowledgment error */
-#define IXXAT_USBV2_CAN_ERROR_ACK 3
-/* Bit error */
-#define IXXAT_USBV2_CAN_ERROR_BIT 4
-/* CRC error */
-#define IXXAT_USBV2_CAN_ERROR_CRC 6
-/* Other (unspecified) error */
-#define IXXAT_USBV2_CAN_ERROR_OTHER 7
-
-/* Data overrun occurred */
-#define IXXAT_USBV2_CAN_STATUS_OVRRUN 0x02
-/* Error warning limit exceeded */
-#define IXXAT_USBV2_CAN_STATUS_ERRLIM 0x04
-/* Bus off status */
-#define IXXAT_USBV2_CAN_STATUS_BUSOFF 0x08
-
-#define IXXAT_USBV2_CAN_DATA 0x00
-#define IXXAT_USBV2_CAN_INFO 0x01
-#define IXXAT_USBV2_CAN_ERROR 0x02
-#define IXXAT_USBV2_CAN_STATUS 0x03
-#define IXXAT_USBV2_CAN_WAKEUP 0x04
-#define IXXAT_USBV2_CAN_TIMEOVR 0x05
-#define IXXAT_USBV2_CAN_TIMERST 0x06
-
-#define IXXAT_USBV2_MSG_FLAGS_TYPE 0x000000FF
-#define IXXAT_USBV2_MSG_FLAGS_SSM 0x00000100
-#define IXXAT_USBV2_MSG_FLAGS_HPM 0x00000600
-#define IXXAT_USBV2_MSG_FLAGS_RES 0x0000F800
-#define IXXAT_USBV2_MSG_FLAGS_DLC 0x000F0000
-#define IXXAT_USBV2_MSG_FLAGS_OVR 0x00100000
-#define IXXAT_USBV2_MSG_FLAGS_SRR 0x00200000
-#define IXXAT_USBV2_MSG_FLAGS_RTR 0x00400000
-#define IXXAT_USBV2_MSG_FLAGS_EXT 0x00800000
-#define IXXAT_USBV2_MSG_FLAGS_AFC 0xFF000000
-
-#define IXXAT_USBV2_BAL_CMD_CLASS 3
-#define IXXAT_USBV2_BRD_CMD_CLASS 4
-#define IXXAT_USBV2_BMG_CMD_CLASS 5
-
-#define IXXAT_USBV2_BRD_CMD_CAT 0
-#define IXXAT_USBV2_CAN_CMD_CAT 1
-
-#define IXXAT_USBV2_VCI_CMD_CODE(Class, Function) \
- ((u32) (((Class) << 8) | (Function)))
-
-#define IXXAT_USBV2_BRD_CMD_CODE(Category, Function) \
- IXXAT_USBV2_VCI_CMD_CODE(IXXAT_USBV2_BRD_CMD_CLASS, \
- ((Category) << 5) | (Function))
-
-#define IXXAT_USBV2_BAL_CMD_CODE(Category, Function) \
- IXXAT_USBV2_VCI_CMD_CODE(IXXAT_USBV2_BAL_CMD_CLASS, \
- ((Category) << 5) | (Function))
-
-#define IXXAT_USBV2_CAN_GET_CAPS_CMD \
- IXXAT_USBV2_BAL_CMD_CODE(IXXAT_USBV2_CAN_CMD_CAT, 0)
-#define IXXAT_USBV2_CAN_INIT_CMD \
- IXXAT_USBV2_BAL_CMD_CODE(IXXAT_USBV2_CAN_CMD_CAT, 5)
-#define IXXAT_USBV2_CAN_START_CMD \
- IXXAT_USBV2_BAL_CMD_CODE(IXXAT_USBV2_CAN_CMD_CAT, 6)
-#define IXXAT_USBV2_CAN_STOP_CMD \
- IXXAT_USBV2_BAL_CMD_CODE(IXXAT_USBV2_CAN_CMD_CAT, 7)
-#define IXXAT_USBV2_CAN_RESET_CMD \
- IXXAT_USBV2_BAL_CMD_CODE(IXXAT_USBV2_CAN_CMD_CAT, 8)
-
-#define IXXAT_USBV2_BRD_GET_FWINFO_CMD \
- IXXAT_USBV2_BRD_CMD_CODE(IXXAT_USBV2_BRD_CMD_CAT, 0)
-#define IXXAT_USBV2_BRD_GET_DEVCAPS_CMD \
- IXXAT_USBV2_BRD_CMD_CODE(IXXAT_USBV2_BRD_CMD_CAT, 1)
-#define IXXAT_USBV2_BRD_GET_DEVINFO_CMD \
- IXXAT_USBV2_BRD_CMD_CODE(IXXAT_USBV2_BRD_CMD_CAT, 2)
-
-struct ixx_usbv2_dal_req {
- u32 req_size;
- u16 req_port;
- u16 req_socket;
- u32 req_code;
-} __packed;
-
-struct ixx_usbv2_dal_res {
- u32 res_size;
- u32 ret_size;
- u32 ret_code;
-} __packed;
-
-struct ixx_usbv2_dev_caps_req {
- struct ixx_usbv2_dal_req dal_req;
-} __packed;
-
-struct ixx_usbv2_dev_caps_res {
- struct ixx_usbv2_dal_res dal_res;
- struct ixx_dev_caps dev_caps;
-} __packed;
-
-struct ixx_usbv2_ctrl_caps_req {
- struct ixx_usbv2_dal_req dal_req;
-} __packed;
-
-struct ixx_usbv2_ctrl_caps_res {
- struct ixx_usbv2_dal_res dal_res;
- struct ixx_ctrl_caps ctrl_caps;
-} __packed;
-
-struct ixx_usbv2_ctrl_init_req {
- struct ixx_usbv2_dal_req dal_req;
- u8 mode;
- u8 btr0;
- u8 btr1;
- u8 padding;
-} __packed;
-
-struct ixx_usbv2_ctrl_init_res {
- struct ixx_usbv2_dal_res dal_res;
-} __packed;
-
-struct ixx_usbv2_ctrl_start_req {
- struct ixx_usbv2_dal_req dal_req;
-} __packed;
-
-struct ixx_usbv2_ctrl_start_res {
- struct ixx_usbv2_dal_res dal_res;
- u32 start_time;
-} __packed;
-
-struct ixx_usbv2_ctrl_stop_req {
- struct ixx_usbv2_dal_req dal_req;
- u32 action;
-} __packed;
-
-struct ixx_usbv2_ctrl_stop_res {
- struct ixx_usbv2_dal_res dal_res;
-} __packed;
-
-struct ixx_usbv2_brd_get_fwinfo_req {
- struct ixx_usbv2_dal_req dal_req;
-} __packed;
-
-struct ixx_usbv2_brd_get_fwinfo_res {
- struct ixx_usbv2_dal_res dal_res;
- struct ixx_intf_fw_info fwinfo;
-} __packed;
-
-struct ixx_usbv2_brd_get_intf_info_req {
- struct ixx_usbv2_dal_req dal_req;
-} __packed;
-
-struct ixx_usbv2_brd_get_intf_info_res {
- struct ixx_usbv2_dal_res dal_res;
- struct ixx_intf_info info;
-} __packed;
-
-/*
- * send usb-to-can v2 command synchronously
- */
-static int ixx_usbv2_send_cmd(struct usb_device *dev,
- struct ixx_usbv2_dal_req *dal_req)
-{
- int err, i;
- u16 size, value;
- u8 request, requesttype;
- u8 *buf;
-
- request = 0xff;
- requesttype = USB_TYPE_VENDOR | USB_DIR_OUT;
- value = le16_to_cpu(dal_req->req_port);
- size = le32_to_cpu(dal_req->req_size) +
- sizeof(const struct ixx_usbv2_dal_res);
-
- buf = kmalloc(size, GFP_KERNEL);
- if(!buf)
- return -ENOMEM;
- memcpy(buf, (u8 *)dal_req, size);
-
-
- for (i = 0; i < 10; ++i) {
- err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request,
- requesttype,
- value,
- 0,
- buf,
- size,
- msecs_to_jiffies(50));
-
- if (err < 0)
- msleep(20);
- else
- break;
- }
-
- kfree(buf);
-
- if (err < 0) {
- dev_err(&dev->dev, "sending command failure: %d\n", err);
- return err;
- }
-
- return 0;
-}
-
-/*
- * receive usb-to-can v2 command synchronously
- */
-static int ixx_usbv2_rcv_cmd(struct usb_device *dev,
- struct ixx_usbv2_dal_res *dal_res, int value)
-{
- int err, res_size, i, size_to_read;
- u8 request, requesttype;
- u8 *buf;
-
- request = 0xff;
- requesttype = USB_TYPE_VENDOR | USB_DIR_IN;
- res_size = 0;
- size_to_read = le32_to_cpu(dal_res->res_size);
-
- buf = kmalloc(size_to_read, GFP_KERNEL);
- if(!buf)
- return -ENOMEM;
-
-
- for (i = 0; i < 10; ++i) {
- err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), request,
- requesttype, value,
- 0, buf + (u8) res_size,
- size_to_read - res_size, msecs_to_jiffies(50));
-
- if (err < 0) {
- msleep(20);
- continue;
- }
-
- res_size += err;
- if (res_size < size_to_read)
- msleep(20);
- else
- break;
- }
-
- if (res_size != size_to_read)
- err = -EBADMSG;
-
- if (err < 0) {
- dev_err(&dev->dev, "receiving command failure: %d\n", err);
- kfree(buf);
- return err;
- }
-
- memcpy((u8 *)dal_res, buf, size_to_read);
- kfree(buf);
-
- return err;
-}
-
-static int ixx_usbv2_init_ctrl(struct ixx_usb_device *dev, u8 mode, u8 btr0,
- u8 btr1)
-{
- int err = -ENODEV;
- u8 data[IXXAT_USBV2_CMD_BUFFER_SIZE] = { 0 };
- struct ixx_usbv2_ctrl_init_req *ctrl_init_req;
- struct ixx_usbv2_ctrl_init_res *ctrl_init_res;
- u32 req_size = sizeof(*ctrl_init_req);
-
- ctrl_init_req = (struct ixx_usbv2_ctrl_init_req *) data;
- ctrl_init_res = (struct ixx_usbv2_ctrl_init_res *)(data + req_size);
-
- ctrl_init_req->dal_req.req_size = cpu_to_le32(req_size);
- ctrl_init_req->dal_req.req_code =
- cpu_to_le32(IXXAT_USBV2_CAN_INIT_CMD);
- ctrl_init_req->dal_req.req_port = cpu_to_le16(dev->ctrl_idx);
- ctrl_init_req->dal_req.req_socket = 0xffff;
- ctrl_init_req->mode = mode;
- ctrl_init_req->btr0 = btr0;
- ctrl_init_req->btr1 = btr1;
-
- ctrl_init_res->dal_res.res_size = cpu_to_le32(
- sizeof(*ctrl_init_res));
- ctrl_init_res->dal_res.ret_size = 0;
- ctrl_init_res->dal_res.ret_code = 0xffffffff;
-
- err = ixx_usbv2_send_cmd(dev->udev, &ctrl_init_req->dal_req);
- if (err < 0)
- return err;
-
- err = ixx_usbv2_rcv_cmd(dev->udev,
- &ctrl_init_res->dal_res,
- dev->ctrl_idx);
- if (err < 0)
- return err;
-
- return le32_to_cpu(ctrl_init_res->dal_res.ret_code);
-}
-
-static int ixx_usbv2_start_ctrl(struct ixx_usb_device *dev, u32 *time_ref)
-{
- int err = -ENODEV;
- u8 data[IXXAT_USBV2_CMD_BUFFER_SIZE] = { 0 };
- struct ixx_usbv2_ctrl_start_req *ctrl_start_req;
- struct ixx_usbv2_ctrl_start_res *ctrl_start_res;
- u32 req_size = sizeof(*ctrl_start_req);
-
- ctrl_start_req = (struct ixx_usbv2_ctrl_start_req *) data;
- ctrl_start_res = (struct ixx_usbv2_ctrl_start_res *)(data + req_size);
-
- ctrl_start_req->dal_req.req_size = cpu_to_le32(req_size);
- ctrl_start_req->dal_req.req_code =
- cpu_to_le32(IXXAT_USBV2_CAN_START_CMD);
- ctrl_start_req->dal_req.req_port = cpu_to_le16(dev->ctrl_idx);
- ctrl_start_req->dal_req.req_socket = 0xffff;
-
- ctrl_start_res->dal_res.res_size = cpu_to_le32(
- sizeof(*ctrl_start_res));
- ctrl_start_res->dal_res.ret_size = 0;
- ctrl_start_res->dal_res.ret_code = 0xffffffff;
- ctrl_start_res->start_time = 0;
-
- err = ixx_usbv2_send_cmd(dev->udev, &ctrl_start_req->dal_req);
- if (err < 0)
- return err;
-
- err = ixx_usbv2_rcv_cmd(dev->udev,
- &ctrl_start_res->dal_res,
- dev->ctrl_idx);
- if (err < 0)
- return err;
-
- if (time_ref)
- *time_ref = le32_to_cpu(ctrl_start_res->start_time);
-
- return le32_to_cpu(ctrl_start_res->dal_res.ret_code);
-}
-
-static int ixx_usbv2_stop_ctrl(struct ixx_usb_device *dev)
-{
- int err = -ENODEV;
- u8 data[IXXAT_USBV2_CMD_BUFFER_SIZE] = { 0 };
- struct ixx_usbv2_ctrl_stop_req *ctrl_stop_req;
- struct ixx_usbv2_ctrl_stop_res *ctrl_stop_res;
- u32 req_size = sizeof(struct ixx_usbv2_ctrl_stop_req);
-
- ctrl_stop_req = (struct ixx_usbv2_ctrl_stop_req *) data;
- ctrl_stop_res = (struct ixx_usbv2_ctrl_stop_res *)(data + req_size);
-
- ctrl_stop_req->dal_req.req_size = cpu_to_le32(req_size);
- ctrl_stop_req->dal_req.req_code =
- cpu_to_le32(IXXAT_USBV2_CAN_STOP_CMD);
- ctrl_stop_req->dal_req.req_port = cpu_to_le16(dev->ctrl_idx);
- ctrl_stop_req->dal_req.req_socket = 0xffff;
- ctrl_stop_req->action = cpu_to_le32(0x3);
-
- ctrl_stop_res->dal_res.res_size =
- cpu_to_le32(sizeof(*ctrl_stop_res));
- ctrl_stop_res->dal_res.ret_size = 0;
- ctrl_stop_res->dal_res.ret_code = 0xffffffff;
-
- err = ixx_usbv2_send_cmd(dev->udev, &ctrl_stop_req->dal_req);
- if (err < 0)
- return err;
-
- err = ixx_usbv2_rcv_cmd(dev->udev,
- &ctrl_stop_res->dal_res,
- dev->ctrl_idx);
- if (err < 0)
- return err;
-
- if (!le32_to_cpu(ctrl_stop_res->dal_res.ret_code))
- dev->can.state = CAN_STATE_STOPPED;
-
- return le32_to_cpu(ctrl_stop_res->dal_res.ret_code);
-}
-
-static int ixx_usbv2_reset_ctrl(struct ixx_usb_device *dev)
-{
- int err = -ENODEV;
- u8 data[IXXAT_USBV2_CMD_BUFFER_SIZE] = { 0 };
- struct ixx_usbv2_dal_req *dal_req;
- struct ixx_usbv2_dal_res *dal_res;
- u32 req_size = sizeof(*dal_req);
-
- dal_req = (struct ixx_usbv2_dal_req *) data;
- dal_res = (struct ixx_usbv2_dal_res *)(data + req_size);
-
- dal_req->req_size = cpu_to_le32(req_size);
- dal_req->req_code = cpu_to_le32(IXXAT_USBV2_CAN_RESET_CMD);
- dal_req->req_port = cpu_to_le16(dev->ctrl_idx);
- dal_req->req_socket = 0xffff;
-
- dal_res->res_size = cpu_to_le32(sizeof(*dal_res));
- dal_res->ret_size = 0;
- dal_res->ret_code = 0xffffffff;
-
- err = ixx_usbv2_send_cmd(dev->udev, dal_req);
- if (err < 0)
- return err;
-
- err = ixx_usbv2_rcv_cmd(dev->udev, dal_res,
- dev->ctrl_idx);
- if (err < 0)
- return err;
-
- return le32_to_cpu(dal_res->ret_code);
-}
-
-static int ixx_usbv2_set_bittiming(struct ixx_usb_device *dev,
- struct can_bittiming *bt)
-{
- u8 btr0 = 0, btr1 = 0, can_opmode = 0;
-
- btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6);
- btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf)
- | (((bt->phase_seg2 - 1) & 0x7) << 4);
- if (dev->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
- btr1 |= 0x80;
-
- can_opmode = IXXAT_USBV2_OPMODE_EXTENDED | IXXAT_USBV2_OPMODE_STANDARD;
-
- if (dev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
- can_opmode |= IXXAT_USBV2_OPMODE_ERRFRAME;
- if (dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
- can_opmode |= IXXAT_USBV2_OPMODE_LISTONLY;
-
- dev->btr0 = btr0;
- dev->btr1 = btr1;
-
- netdev_dbg(dev->netdev, "setting btr0=0x%08x btr1=0x%08x mode=0x%08x\n",
- btr0, btr1, can_opmode);
-
- return ixx_usbv2_init_ctrl(dev, can_opmode, btr0, btr1);
-}
-
-/*
- * handle restart but in asynchronously way
- */
-static int ixx_usbv2_restart_task(void *user_data)
-{
- u32 time_ref;
- struct ixx_usb_device *dev = user_data;
-
- while (!kthread_should_stop()) {
- if (!dev->must_quit) {
- wait_event_interruptible(dev->wait_queue,
- dev->restart_flag);
- if (!dev->must_quit) {
- ixx_usbv2_stop_ctrl(dev);
- ixx_usbv2_start_ctrl(dev, &time_ref);
- dev->restart_flag = 0;
- dev->can.state = CAN_STATE_ERROR_ACTIVE;
- }
- } else
- msleep(20);
- }
- return 0;
-}
-
-static int ixx_usbv2_handle_canmsg(struct ixx_usb_device *dev,
- struct ixx_can_msg *rx)
-{
- struct net_device *netdev = dev->netdev;
- struct can_frame *can_frame;
- struct sk_buff *skb;
-
- skb = alloc_can_skb(netdev, &can_frame);
- if (!skb)
- return -ENOMEM;
-
- if (le32_to_cpu(rx->flags) & IXXAT_USBV2_MSG_FLAGS_OVR) {
- netdev->stats.rx_over_errors++;
- netdev->stats.rx_errors++;
- }
-
- can_frame->can_id = le32_to_cpu(rx->msg_id);
- can_frame->can_dlc =
- (le32_to_cpu(rx->flags) &
- IXXAT_USBV2_MSG_FLAGS_DLC) >> 16;
-
- if (le32_to_cpu(rx->flags) & IXXAT_USBV2_MSG_FLAGS_EXT)
- can_frame->can_id |= CAN_EFF_FLAG;
-
- if (le32_to_cpu(rx->flags) & IXXAT_USBV2_MSG_FLAGS_RTR)
- can_frame->can_id |= CAN_RTR_FLAG;
- else
- memcpy(can_frame->data, rx->data, can_frame->can_dlc);
-
- ixxat_usb_get_ts_tv(dev, le32_to_cpu(rx->time), &skb->tstamp);
-
- netif_rx(skb);
- netdev->stats.rx_packets++;
- netdev->stats.rx_bytes += can_frame->can_dlc;
-
- return 0;
-}
-
-static int ixx_usbv2_handle_error(struct ixx_usb_device *dev,
- struct ixx_can_msg *rx)
-{
- struct net_device *netdev = dev->netdev;
- struct can_frame *can_frame;
- struct sk_buff *skb;
- u8 raw_status = 0;
-
- /* nothing should be sent while in BUS_OFF state */
- if (dev->can.state == CAN_STATE_BUS_OFF)
- return 0;
-
- raw_status = rx->data[0];
-
- /* allocate an skb to store the error frame */
- skb = alloc_can_err_skb(netdev, &can_frame);
- if (!skb)
- return -ENOMEM;
-
- switch (raw_status) {
- case IXXAT_USBV2_CAN_ERROR_ACK:
- can_frame->can_id |= CAN_ERR_ACK;
- netdev->stats.tx_errors++;
- break;
- case IXXAT_USBV2_CAN_ERROR_BIT:
- can_frame->can_id |= CAN_ERR_PROT;
- can_frame->data[2] |= CAN_ERR_PROT_BIT;
- netdev->stats.rx_errors++;
- break;
- case IXXAT_USBV2_CAN_ERROR_CRC:
- can_frame->can_id |= CAN_ERR_PROT;
- can_frame->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ;
- netdev->stats.rx_errors++;
- break;
- case IXXAT_USBV2_CAN_ERROR_FORM:
- can_frame->can_id |= CAN_ERR_PROT;
- can_frame->data[2] |= CAN_ERR_PROT_FORM;
- netdev->stats.rx_errors++;
- break;
- case IXXAT_USBV2_CAN_ERROR_STUFF:
- can_frame->can_id |= CAN_ERR_PROT;
- can_frame->data[2] |= CAN_ERR_PROT_STUFF;
- netdev->stats.rx_errors++;
- break;
- case IXXAT_USBV2_CAN_ERROR_OTHER:
- can_frame->can_id |= CAN_ERR_PROT;
- can_frame->data[2] |= CAN_ERR_PROT_UNSPEC;
- netdev->stats.rx_errors++;
- break;
- default:
- can_frame->can_id |= CAN_ERR_PROT;
- netdev->stats.rx_errors++;
- }
-
- netif_rx(skb);
- netdev->stats.rx_packets++;
- netdev->stats.rx_bytes += can_frame->can_dlc;
-
- dev->bec.txerr = le16_to_cpu(rx->data[1]);
- dev->bec.rxerr = le16_to_cpu(rx->data[3]);
-
- return 0;
-}
-
-static int ixx_usbv2_handle_status(struct ixx_usb_device *dev,
- struct ixx_can_msg *rx)
-{
- struct net_device *netdev = dev->netdev;
- struct can_frame *can_frame;
- struct sk_buff *skb;
- u8 raw_status = 0;
- u32 new_state = 0;
-
- raw_status = rx->data[0];
-
- /* nothing should be sent while in BUS_OFF state */
- if (dev->can.state == CAN_STATE_BUS_OFF)
- return 0;
-
- if (!raw_status) {
- /* no error bit (back to active state) */
- dev->can.state = CAN_STATE_ERROR_ACTIVE;
-
- dev->bec.txerr = 0;
- dev->bec.rxerr = 0;
- return 0;
- }
-
- /* allocate an skb to store the error frame */
- skb = alloc_can_err_skb(netdev, &can_frame);
- if (!skb)
- return -ENOMEM;
-
- if (raw_status & IXXAT_USBV2_CAN_STATUS_BUSOFF) {
- can_frame->can_id |= CAN_ERR_BUSOFF;
- new_state = CAN_STATE_BUS_OFF;
- dev->can.can_stats.bus_off++;
- can_bus_off(netdev);
- } else {
- if (raw_status & IXXAT_USBV2_CAN_STATUS_ERRLIM) {
- can_frame->can_id |= CAN_ERR_CRTL;
- can_frame->data[1] |= CAN_ERR_CRTL_TX_WARNING;
- can_frame->data[1] |= CAN_ERR_CRTL_RX_WARNING;
- dev->can.can_stats.error_warning++;
- new_state = CAN_STATE_ERROR_WARNING;
- }
-
- if (raw_status & IXXAT_USBV2_CAN_STATUS_OVRRUN) {
- can_frame->can_id |= CAN_ERR_PROT;
- can_frame->data[2] |= CAN_ERR_PROT_OVERLOAD;
- netdev->stats.rx_over_errors++;
- netdev->stats.rx_errors++;
- }
-
- if (!new_state) {
- new_state = CAN_STATE_ERROR_ACTIVE;
-
- dev->bec.txerr = 0;
- dev->bec.rxerr = 0;
- }
- }
-
- dev->can.state = new_state;
-
- netif_rx(skb);
- netdev->stats.rx_packets++;
- netdev->stats.rx_bytes += can_frame->can_dlc;
-
- return 0;
-}
-
-/*
- * callback for bulk IN urb
- */
-static int ixx_usbv2_decode_buf(struct ixx_usb_device *dev, struct urb *urb)
-{
- struct net_device *netdev = dev->netdev;
- struct ixx_can_msg *can_msg;
- u32 msg_end;
- int err = 0;
- u32 read_size = 0;
- u8 msg_type;
- u8 *data;
-
- data = urb->transfer_buffer;
-
- /* loop reading all the records from the incoming message */
- msg_end = urb->actual_length;
- for (; msg_end > 0;) {
- can_msg = (struct ixx_can_msg *) &data[read_size];
-
- if (!can_msg || !can_msg->size) {
- netdev_err(netdev, "got unsupported rec in usb msg:\n");
- err = -ENOTSUPP;
- break;
- }
-
- /* check if the record goes out of current packet */
- if ((read_size + can_msg->size + 1) > urb->actual_length) {
- netdev_err(netdev,
- "got frag rec: should inc usb rx buf size\n");
- err = -EBADMSG;
- break;
- }
-
- msg_type =
- (le32_to_cpu(can_msg->flags) &
- IXXAT_USBV2_MSG_FLAGS_TYPE);
-
- switch (msg_type) {
-
- case IXXAT_USBV2_CAN_DATA:
- err = ixx_usbv2_handle_canmsg(dev, can_msg);
- if (err < 0)
- goto fail;
- break;
-
- case IXXAT_USBV2_CAN_STATUS:
- err = ixx_usbv2_handle_status(dev, can_msg);
- if (err < 0)
- goto fail;
- break;
-
- case IXXAT_USBV2_CAN_ERROR:
- err = ixx_usbv2_handle_error(dev, can_msg);
- if (err < 0)
- goto fail;
- break;
-
- case IXXAT_USBV2_CAN_TIMEOVR:
- ixxat_usb_get_ts_tv(dev, can_msg->time, NULL);
- break;
-
- case IXXAT_USBV2_CAN_INFO:
- case IXXAT_USBV2_CAN_WAKEUP:
- case IXXAT_USBV2_CAN_TIMERST:
- break;
-
- default:
- netdev_err(netdev,
- "unhandled rec type 0x%02x (%d): ignored\n",
- msg_type, msg_type);
- break;
- }
-
- read_size += can_msg->size + 1;
- msg_end -= (can_msg->size + 1);
- }
-
-fail:
- if (err)
- ixxat_dump_mem("received msg", urb->transfer_buffer,
- urb->actual_length);
-
- return err;
-}
-
-static int ixx_usbv2_encode_msg(struct ixx_usb_device *dev, struct sk_buff *skb,
- u8 *obuf, size_t *size)
-{
- struct can_frame *cf = (struct can_frame *) skb->data;
- struct ixx_can_msg can_msg = { 0 };
-
- if (cf->can_id & CAN_RTR_FLAG)
- can_msg.flags |= IXXAT_USBV2_MSG_FLAGS_RTR;
-
- if (cf->can_id & CAN_EFF_FLAG) {
- can_msg.flags |= IXXAT_USBV2_MSG_FLAGS_EXT;
- can_msg.msg_id = cf->can_id & CAN_EFF_MASK;
- } else {
- can_msg.msg_id = cf->can_id & CAN_SFF_MASK;
- }
-
- if (dev->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
- can_msg.flags |= IXXAT_USBV2_MSG_FLAGS_SSM;
-
- can_msg.flags |= (cf->can_dlc << 16) & IXXAT_USBV2_MSG_FLAGS_DLC;
-
- can_msg.flags = cpu_to_le32(can_msg.flags);
- can_msg.msg_id = cpu_to_le32(can_msg.msg_id);
-
- memcpy(can_msg.data, cf->data, cf->can_dlc);
- can_msg.size = (u8)(sizeof(can_msg) - 1 - CAN_MAX_DLEN + cf->can_dlc);
-
- memcpy(obuf, &can_msg, can_msg.size + 1);
-
- *size = can_msg.size + 1;
-
- skb->data_len = *size;
-
- return 0;
-}
-
-static int ixx_usbv2_start(struct ixx_usb_device *dev)
-{
- int err;
- u32 time_ref = 0;
- u8 can_opmode = IXXAT_USBV2_OPMODE_EXTENDED
- | IXXAT_USBV2_OPMODE_STANDARD;
-
- if (dev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
- can_opmode |= IXXAT_USBV2_OPMODE_ERRFRAME;
- if (dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
- can_opmode |= IXXAT_USBV2_OPMODE_LISTONLY;
-
- err = ixx_usbv2_init_ctrl(dev, can_opmode, dev->btr0, dev->btr1);
- if (err)
- return err;
-
- /* opening first device: */
- if (dev->ctrl_opened_count == 0) {
- err = ixx_usbv2_start_ctrl(dev, &time_ref);
- if (err)
- return err;
-
- ixxat_usb_set_ts_now(dev, time_ref);
- }
-
- dev->ctrl_opened_count++;
-
- dev->bec.txerr = 0;
- dev->bec.rxerr = 0;
-
- return err;
-}
-
-/*
- * stop interface
- * (last chance before set bus off)
- */
-static int ixx_usbv2_stop(struct ixx_usb_device *dev)
-{
- int err;
-
- if (dev->ctrl_opened_count == 1) {
- err = ixx_usbv2_stop_ctrl(dev);
- if (err)
- return err;
- }
-
- /* turn off ts msgs for that interface if no other dev opened */
-// if (pdev->usb_if->dev_opened_count == 1)
-// ixx_usbv2_set_ts(dev, 0);
- dev->ctrl_opened_count--;
-
- return 0;
-}
-
-/*
- * called when probing to initialize a device object.
- */
-static int ixx_usbv2_init(struct ixx_usb_device *dev)
-{
- dev->restart_task = kthread_run(&ixx_usbv2_restart_task, dev,
- "restart_thread");
- if (!dev->restart_task)
- return -ENOBUFS;
-
- return 0;
-}
-
-static void ixx_usbv2_exit(struct ixx_usb_device *dev)
-{
- ixx_usbv2_reset_ctrl(dev);
-
- dev->must_quit = 1;
- dev->restart_flag = 1;
- wake_up_interruptible(&dev->wait_queue);
- if (dev->restart_task)
- kthread_stop(dev->restart_task);
-}
-
-/*
- * probe function for new IXXAT USB-to-CAN V2 interface
- */
-static int ixx_usbv2_probe(struct usb_interface *intf)
-{
- struct usb_host_interface *if_desc;
- int i;
-
- if_desc = intf->altsetting;
-
- /* check interface endpoint addresses */
- for (i = 0; i < if_desc->desc.bNumEndpoints; i++) {
- struct usb_endpoint_descriptor *ep = &if_desc->endpoint[i].desc;
-
- /*
- * below is the list of valid ep addreses. Any other ep address
- * is considered as not-CAN interface address => no dev created
- */
- switch (ep->bEndpointAddress) {
- case IXXAT_USBV2_EP_MSGOUT_0:
- case IXXAT_USBV2_EP_MSGOUT_1:
- case IXXAT_USBV2_EP_MSGOUT_2:
- case IXXAT_USBV2_EP_MSGOUT_3:
- case IXXAT_USBV2_EP_MSGOUT_4:
- case IXXAT_USBV2_EP_MSGIN_0:
- case IXXAT_USBV2_EP_MSGIN_1:
- case IXXAT_USBV2_EP_MSGIN_2:
- case IXXAT_USBV2_EP_MSGIN_3:
- case IXXAT_USBV2_EP_MSGIN_4:
-
- break;
- default:
- return -ENODEV;
- }
- }
-
- return 0;
-}
-
-static int ixx_usbv2_get_dev_caps(struct usb_device *dev,
- struct ixx_dev_caps *dev_caps)
-{
- int err = -ENODEV, i;
- u8 data[IXXAT_USBV2_CMD_BUFFER_SIZE] = { 0 };
- struct ixx_usbv2_dev_caps_req *dev_caps_req;
- struct ixx_usbv2_dev_caps_res *dev_caps_res;
- u32 req_size = sizeof(*dev_caps_req);
-
- dev_caps_req = (struct ixx_usbv2_dev_caps_req *) data;
- dev_caps_res = (struct ixx_usbv2_dev_caps_res *)(data + req_size);
-
- dev_caps_req->dal_req.req_size = cpu_to_le32(req_size);
- dev_caps_req->dal_req.req_code =
- cpu_to_le32(IXXAT_USBV2_BRD_GET_DEVCAPS_CMD);
- dev_caps_req->dal_req.req_port = 0xffff;
- dev_caps_req->dal_req.req_socket = 0xffff;
-
- dev_caps_res->dal_res.res_size =
- cpu_to_le32(sizeof(*dev_caps_res));
- dev_caps_res->dal_res.ret_size = 0;
- dev_caps_res->dal_res.ret_code = 0xffffffff;
-
- err = ixx_usbv2_send_cmd(dev, &dev_caps_req->dal_req);
- if (err < 0)
- return err;
-
- err = ixx_usbv2_rcv_cmd(dev, &dev_caps_res->dal_res,
- 0xffff);
- if (err < 0)
- return err;
-
- dev_caps->bus_ctrl_count =
- le16_to_cpu(dev_caps_res->dev_caps.bus_ctrl_count);
- for (i = 0; i < dev_caps->bus_ctrl_count; ++i)
- dev_caps->bus_ctrl_types[i] =
- le16_to_cpu(dev_caps_res->dev_caps.bus_ctrl_types[i]);
-
- return 0;
-}
-
-static int ixx_usbv2_get_ctrl_caps(struct usb_device *dev,
- struct ixx_ctrl_caps *ctrl_caps, int index)
-{
- int err = -ENODEV;
- u8 data[IXXAT_USBV2_CMD_BUFFER_SIZE] = { 0 };
- struct ixx_usbv2_ctrl_caps_req *ctrl_caps_req;
- struct ixx_usbv2_ctrl_caps_res *ctrl_caps_res;
- u32 req_size = sizeof(*ctrl_caps_req);
-
- ctrl_caps_req = (struct ixx_usbv2_ctrl_caps_req *) data;
- ctrl_caps_res = (struct ixx_usbv2_ctrl_caps_res *)(data + req_size);
-
- ctrl_caps_req->dal_req.req_size = cpu_to_le32(req_size);
- ctrl_caps_req->dal_req.req_code =
- cpu_to_le32(IXXAT_USBV2_CAN_GET_CAPS_CMD);
- ctrl_caps_req->dal_req.req_port = cpu_to_le16(index);
- ctrl_caps_req->dal_req.req_socket = 0xffff;
-
- ctrl_caps_res->dal_res.res_size =
- cpu_to_le32(sizeof(*ctrl_caps_res));
- ctrl_caps_res->dal_res.ret_size = 0;
- ctrl_caps_res->dal_res.ret_code = 0xffffffff;
-
- err = ixx_usbv2_send_cmd(dev, &ctrl_caps_req->dal_req);
- if (err < 0)
- return err;
-
- err = ixx_usbv2_rcv_cmd(dev, &ctrl_caps_res->dal_res,
- index);
- if (err < 0)
- return err;
-
- ctrl_caps->bus_coupling = le16_to_cpu(
- ctrl_caps_res->ctrl_caps.bus_coupling);
- ctrl_caps->clock_freq =
- le32_to_cpu(ctrl_caps_res->ctrl_caps.clock_freq);
- ctrl_caps->cms_divisor = le32_to_cpu(
- ctrl_caps_res->ctrl_caps.cms_divisor);
- ctrl_caps->cms_max_ticks = le32_to_cpu(
- ctrl_caps_res->ctrl_caps.cms_max_ticks);
- ctrl_caps->ctrl_type = le16_to_cpu(ctrl_caps_res->ctrl_caps.ctrl_type);
- ctrl_caps->dtx_divisor = le32_to_cpu(
- ctrl_caps_res->ctrl_caps.dtx_divisor);
- ctrl_caps->dtx_max_ticks = le32_to_cpu(
- ctrl_caps_res->ctrl_caps.dtx_max_ticks);
- ctrl_caps->features = le32_to_cpu(ctrl_caps_res->ctrl_caps.features);
- ctrl_caps->tsc_divisor = le32_to_cpu(
- ctrl_caps_res->ctrl_caps.tsc_divisor);
-
- return 0;
-}
-
-static int ixx_usbv2_get_fwinfo(struct ixx_usb_device *dev,
- struct ixx_intf_fw_info *fwinfo)
-{
- int err = -ENODEV;
- u8 data[IXXAT_USBV2_CMD_BUFFER_SIZE] = { 0 };
- struct ixx_usbv2_brd_get_fwinfo_req *fw_info_req;
- struct ixx_usbv2_brd_get_fwinfo_res *fw_info_res;
- u32 req_size = sizeof(*fw_info_req);
-
- fw_info_req = (struct ixx_usbv2_brd_get_fwinfo_req *) data;
- fw_info_res = (struct ixx_usbv2_brd_get_fwinfo_res *)(data + req_size);
-
- fw_info_req->dal_req.req_size = cpu_to_le32(req_size);
- fw_info_req->dal_req.req_code =
- cpu_to_le32(IXXAT_USBV2_BRD_GET_FWINFO_CMD);
- fw_info_req->dal_req.req_port = 0xffff;
- fw_info_req->dal_req.req_socket = 0xffff;
-
- fw_info_res->dal_res.res_size =
- cpu_to_le32(sizeof(*fw_info_res));
- fw_info_res->dal_res.ret_size = 0;
- fw_info_res->dal_res.ret_code = 0xffffffff;
-
- err = ixx_usbv2_send_cmd(dev->udev, &fw_info_req->dal_req);
- if (err < 0)
- return err;
-
- err = ixx_usbv2_rcv_cmd(dev->udev,
- &fw_info_res->dal_res, 0xffff);
- if (err < 0)
- return err;
-
- if (fwinfo) {
- fwinfo->build_version =
- le16_to_cpu(fw_info_res->fwinfo.build_version);
- fwinfo->firmware_type =
- le32_to_cpu(fw_info_res->fwinfo.firmware_type);
- fwinfo->major_version =
- le16_to_cpu(fw_info_res->fwinfo.major_version);
- fwinfo->minor_version =
- le16_to_cpu(fw_info_res->fwinfo.minor_version);
- fwinfo->reserved =
- le16_to_cpu(fw_info_res->fwinfo.reserved);
- }
-
- return le32_to_cpu(fw_info_res->dal_res.ret_code);
-}
-
-static int ixx_usbv2_get_dev_info(struct ixx_usb_device *dev,
- struct ixx_intf_info *dev_info)
-{
- int err = -ENODEV;
- u8 data[IXXAT_USBV2_CMD_BUFFER_SIZE] = { 0 };
- struct ixx_usbv2_brd_get_intf_info_req *dev_info_req;
- struct ixx_usbv2_brd_get_intf_info_res *dev_info_res;
- u32 req_size = sizeof(*dev_info_req);
-
- dev_info_req = (struct ixx_usbv2_brd_get_intf_info_req *) data;
- dev_info_res =
- (struct ixx_usbv2_brd_get_intf_info_res *)(data + req_size);
-
- dev_info_req->dal_req.req_size = cpu_to_le32(req_size);
- dev_info_req->dal_req.req_code =
- cpu_to_le32(IXXAT_USBV2_BRD_GET_DEVINFO_CMD);
- dev_info_req->dal_req.req_port = 0xffff;
- dev_info_req->dal_req.req_socket = 0xffff;
-
- dev_info_res->dal_res.res_size =
- cpu_to_le32(sizeof(*dev_info_res));
- dev_info_res->dal_res.ret_size = 0;
- dev_info_res->dal_res.ret_code = 0xffffffff;
-
- err = ixx_usbv2_send_cmd(dev->udev, &dev_info_req->dal_req);
- if (err < 0)
- return err;
-
- err = ixx_usbv2_rcv_cmd(dev->udev,
- &dev_info_res->dal_res, 0xffff);
- if (err < 0)
- return err;
-
- if (dev_info) {
- memcpy(dev_info->device_id, &dev_info_res->info.device_id,
- sizeof(dev_info_res->info.device_id));
- memcpy(dev_info->device_name, &dev_info_res->info.device_name,
- sizeof(dev_info_res->info.device_name));
- dev_info->device_fpga_version =
- le16_to_cpu(dev_info_res->info.device_fpga_version);
- dev_info->device_version =
- le32_to_cpu(dev_info_res->info.device_version);
- }
-
- return le32_to_cpu(dev_info_res->dal_res.ret_code);
-}
-
-/*
- * describe the describes the USB-to-CAN V2 compact adapter
- */
-struct ixx_usb_adapter usb_to_can_v2_compact = {
- .name = "USB-to-CAN V2 compact",
- .device_id = USB_TO_CAN_V2_COMPACT_PRODUCT_ID,
- .clock = {
- .freq = SJA1000_CRYSTAL_HZ,
- },
- .bittiming_const = {
- .name = "ixxat_usb",
- .tseg1_min = 1,
- .tseg1_max = 16,
- .tseg2_min = 1,
- .tseg2_max = 8,
- .sjw_max = 4,
- .brp_min = 1,
- .brp_max = 64,
- .brp_inc = 1,
- },
-
- .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
- CAN_CTRLMODE_BERR_REPORTING |
- CAN_CTRLMODE_LOOPBACK |
- CAN_CTRLMODE_LISTENONLY,
-
- /* size of device private data */
- .sizeof_dev_private = sizeof(struct ixx_usb_device),
-
- /* give here messages in/out endpoints */
- .ep_msg_in = { IXXAT_USBV2_EP_MSGIN_0, IXXAT_USBV2_EP_MSGIN_1,
- IXXAT_USBV2_EP_MSGIN_2, IXXAT_USBV2_EP_MSGIN_3,
- IXXAT_USBV2_EP_MSGIN_4 },
- .ep_msg_out = { IXXAT_USBV2_EP_MSGOUT_0, IXXAT_USBV2_EP_MSGOUT_1,
- IXXAT_USBV2_EP_MSGOUT_2, IXXAT_USBV2_EP_MSGOUT_3,
- IXXAT_USBV2_EP_MSGOUT_4 },
-
- /* size of rx/tx usb buffers */
- .rx_buffer_size = IXXAT_USBV2_RX_BUFFER_SIZE,
- .tx_buffer_size = IXXAT_USBV2_TX_BUFFER_SIZE,
-
- /* device callbacks */
- .intf_probe = ixx_usbv2_probe,
- .dev_get_dev_caps = ixx_usbv2_get_dev_caps,
- .dev_get_ctrl_caps = ixx_usbv2_get_ctrl_caps,
- .dev_init = ixx_usbv2_init,
- .dev_exit = ixx_usbv2_exit,
- .dev_set_bittiming = ixx_usbv2_set_bittiming,
- .intf_get_info = ixx_usbv2_get_dev_info,
- .intf_get_fw_info = ixx_usbv2_get_fwinfo,
- .dev_decode_buf = ixx_usbv2_decode_buf,
- .dev_encode_msg = ixx_usbv2_encode_msg,
- .dev_start = ixx_usbv2_start,
- .dev_stop = ixx_usbv2_stop,
-};
-
-/*
- * describes the USB-to-CAN V2 automotive adapter
- */
-struct ixx_usb_adapter usb_to_can_v2_automotive = {
- .name = "USB-to-CAN V2 automotive",
- .device_id = USB_TO_CAN_V2_AUTOMOTIVE_PRODUCT_ID,
- .clock = {
- .freq = SJA1000_CRYSTAL_HZ,
- },
- .bittiming_const = {
- .name = "ixxat_usb",
- .tseg1_min = 1,
- .tseg1_max = 16,
- .tseg2_min = 1,
- .tseg2_max = 8,
- .sjw_max = 4,
- .brp_min = 1,
- .brp_max = 64,
- .brp_inc = 1,
- },
-
- .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
- CAN_CTRLMODE_BERR_REPORTING |
- CAN_CTRLMODE_LOOPBACK |
- CAN_CTRLMODE_LISTENONLY,
-
- /* size of device private data */
- .sizeof_dev_private = sizeof(struct ixx_usb_device),
-
- /* give here messages in/out endpoints */
- .ep_msg_in = { IXXAT_USBV2_EP_MSGIN_0, IXXAT_USBV2_EP_MSGIN_1,
- IXXAT_USBV2_EP_MSGIN_2, IXXAT_USBV2_EP_MSGIN_3,
- IXXAT_USBV2_EP_MSGIN_4 },
- .ep_msg_out = { IXXAT_USBV2_EP_MSGOUT_0, IXXAT_USBV2_EP_MSGOUT_1,
- IXXAT_USBV2_EP_MSGOUT_2, IXXAT_USBV2_EP_MSGOUT_3,
- IXXAT_USBV2_EP_MSGOUT_4 },
-
- /* size of rx/tx usb buffers */
- .rx_buffer_size = IXXAT_USBV2_RX_BUFFER_SIZE,
- .tx_buffer_size = IXXAT_USBV2_TX_BUFFER_SIZE,
-
- /* device callbacks */
- .intf_probe = ixx_usbv2_probe,
- .dev_get_dev_caps = ixx_usbv2_get_dev_caps,
- .dev_get_ctrl_caps = ixx_usbv2_get_ctrl_caps,
- .dev_init = ixx_usbv2_init,
- .dev_exit = ixx_usbv2_exit,
- .dev_set_bittiming = ixx_usbv2_set_bittiming,
- .intf_get_info = ixx_usbv2_get_dev_info,
- .intf_get_fw_info = ixx_usbv2_get_fwinfo,
- .dev_decode_buf = ixx_usbv2_decode_buf,
- .dev_encode_msg = ixx_usbv2_encode_msg,
- .dev_start = ixx_usbv2_start,
- .dev_stop = ixx_usbv2_stop,
-};
-
-/*
- * describes the USB-to-CAN V2 embedded adapter
- */
-struct ixx_usb_adapter usb_to_can_v2_embedded = {
- .name = "USB-to-CAN V2 embedded",
- .device_id = USB_TO_CAN_V2_EMBEDDED_PRODUCT_ID,
- .clock = {
- .freq = SJA1000_CRYSTAL_HZ,
- },
- .bittiming_const = {
- .name = "ixxat_usb",
- .tseg1_min = 1,
- .tseg1_max = 16,
- .tseg2_min = 1,
- .tseg2_max = 8,
- .sjw_max = 4,
- .brp_min = 1,
- .brp_max = 64,
- .brp_inc = 1,
- },
-
- .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
- CAN_CTRLMODE_BERR_REPORTING |
- CAN_CTRLMODE_LOOPBACK |
- CAN_CTRLMODE_LISTENONLY,
-
- /* size of device private data */
- .sizeof_dev_private = sizeof(struct ixx_usb_device),
-
- /* give here messages in/out endpoints */
- .ep_msg_in = { IXXAT_USBV2_EP_MSGIN_0, IXXAT_USBV2_EP_MSGIN_1,
- IXXAT_USBV2_EP_MSGIN_2, IXXAT_USBV2_EP_MSGIN_3,
- IXXAT_USBV2_EP_MSGIN_4 },
- .ep_msg_out = { IXXAT_USBV2_EP_MSGOUT_0, IXXAT_USBV2_EP_MSGOUT_1,
- IXXAT_USBV2_EP_MSGOUT_2, IXXAT_USBV2_EP_MSGOUT_3,
- IXXAT_USBV2_EP_MSGOUT_4 },
-
- /* size of rx/tx usb buffers */
- .rx_buffer_size = IXXAT_USBV2_RX_BUFFER_SIZE,
- .tx_buffer_size = IXXAT_USBV2_TX_BUFFER_SIZE,
-
- /* device callbacks */
- .intf_probe = ixx_usbv2_probe,
- .dev_get_dev_caps = ixx_usbv2_get_dev_caps,
- .dev_get_ctrl_caps = ixx_usbv2_get_ctrl_caps,
- .dev_init = ixx_usbv2_init,
- .dev_exit = ixx_usbv2_exit,
- .dev_set_bittiming = ixx_usbv2_set_bittiming,
- .intf_get_info = ixx_usbv2_get_dev_info,
- .intf_get_fw_info = ixx_usbv2_get_fwinfo,
- .dev_decode_buf = ixx_usbv2_decode_buf,
- .dev_encode_msg = ixx_usbv2_encode_msg,
- .dev_start = ixx_usbv2_start,
- .dev_stop = ixx_usbv2_stop,
-};
-
-/*
- * describes the USB-to-CAN V2 professional adapter
- */
-struct ixx_usb_adapter usb_to_can_v2_professional = {
- .name = "USB-to-CAN V2 professional",
- .device_id = USB_TO_CAN_V2_PROFESSIONAL_PRODUCT_ID,
- .clock = {
- .freq = SJA1000_CRYSTAL_HZ,
- },
- .bittiming_const = {
- .name = "ixxat_usb",
- .tseg1_min = 1,
- .tseg1_max = 16,
- .tseg2_min = 1,
- .tseg2_max = 8,
- .sjw_max = 4,
- .brp_min = 1,
- .brp_max = 64,
- .brp_inc = 1,
- },
-
- .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
- CAN_CTRLMODE_BERR_REPORTING |
- CAN_CTRLMODE_LOOPBACK |
- CAN_CTRLMODE_LISTENONLY,
-
- /* size of device private data */
- .sizeof_dev_private = sizeof(struct ixx_usb_device),
-
- /* give here messages in/out endpoints */
- .ep_msg_in = { IXXAT_USBV2_EP_MSGIN_0, IXXAT_USBV2_EP_MSGIN_1,
- IXXAT_USBV2_EP_MSGIN_2, IXXAT_USBV2_EP_MSGIN_3,
- IXXAT_USBV2_EP_MSGIN_4 },
- .ep_msg_out = { IXXAT_USBV2_EP_MSGOUT_0, IXXAT_USBV2_EP_MSGOUT_1,
- IXXAT_USBV2_EP_MSGOUT_2, IXXAT_USBV2_EP_MSGOUT_3,
- IXXAT_USBV2_EP_MSGOUT_4 },
-
- /* size of rx/tx usb buffers */
- .rx_buffer_size = IXXAT_USBV2_RX_BUFFER_SIZE,
- .tx_buffer_size = IXXAT_USBV2_TX_BUFFER_SIZE,
-
- /* device callbacks */
- .intf_probe = ixx_usbv2_probe,
- .dev_get_dev_caps = ixx_usbv2_get_dev_caps,
- .dev_get_ctrl_caps = ixx_usbv2_get_ctrl_caps,
- .dev_init = ixx_usbv2_init,
- .dev_exit = ixx_usbv2_exit,
- .dev_set_bittiming = ixx_usbv2_set_bittiming,
- .intf_get_info = ixx_usbv2_get_dev_info,
- .intf_get_fw_info = ixx_usbv2_get_fwinfo,
- .dev_decode_buf = ixx_usbv2_decode_buf,
- .dev_encode_msg = ixx_usbv2_encode_msg,
- .dev_start = ixx_usbv2_start,
- .dev_stop = ixx_usbv2_stop,
-};
-
-/*
- * describes the USB-to-CAN V2 low speed adapter
- */
-struct ixx_usb_adapter usb_to_can_v2_low_speed = {
- .name = "USB-to-CAN V2 low speed",
- .device_id = USB_TO_CAN_V2_LOW_SPEED_PRODUCT_ID,
- .clock = {
- .freq = SJA1000_CRYSTAL_HZ,
- },
- .bittiming_const = {
- .name = "ixxat_usb",
- .tseg1_min = 1,
- .tseg1_max = 16,
- .tseg2_min = 1,
- .tseg2_max = 8,
- .sjw_max = 4,
- .brp_min = 1,
- .brp_max = 64,
- .brp_inc = 1,
- },
-
- .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
- CAN_CTRLMODE_BERR_REPORTING |
- CAN_CTRLMODE_LOOPBACK |
- CAN_CTRLMODE_LISTENONLY,
-
- /* size of device private data */
- .sizeof_dev_private = sizeof(struct ixx_usb_device),
-
- /* give here messages in/out endpoints */
- .ep_msg_in = { IXXAT_USBV2_EP_MSGIN_0, IXXAT_USBV2_EP_MSGIN_1,
- IXXAT_USBV2_EP_MSGIN_2, IXXAT_USBV2_EP_MSGIN_3,
- IXXAT_USBV2_EP_MSGIN_4 },
- .ep_msg_out = { IXXAT_USBV2_EP_MSGOUT_0, IXXAT_USBV2_EP_MSGOUT_1,
- IXXAT_USBV2_EP_MSGOUT_2, IXXAT_USBV2_EP_MSGOUT_3,
- IXXAT_USBV2_EP_MSGOUT_4 },
-
- /* size of rx/tx usb buffers */
- .rx_buffer_size = IXXAT_USBV2_RX_BUFFER_SIZE,
- .tx_buffer_size = IXXAT_USBV2_TX_BUFFER_SIZE,
-
- /* device callbacks */
- .intf_probe = ixx_usbv2_probe,
- .dev_get_dev_caps = ixx_usbv2_get_dev_caps,
- .dev_get_ctrl_caps = ixx_usbv2_get_ctrl_caps,
- .dev_init = ixx_usbv2_init,
- .dev_exit = ixx_usbv2_exit,
- .dev_set_bittiming = ixx_usbv2_set_bittiming,
- .intf_get_info = ixx_usbv2_get_dev_info,
- .intf_get_fw_info = ixx_usbv2_get_fwinfo,
- .dev_decode_buf = ixx_usbv2_decode_buf,
- .dev_encode_msg = ixx_usbv2_encode_msg,
- .dev_start = ixx_usbv2_start,
- .dev_stop = ixx_usbv2_stop,
-};
-
-/*
- * describes the USB-to-CAN V2 extended adapter
- */
-struct ixx_usb_adapter usb_to_can_v2_extended = {
- .name = "USB-to-CAN V2 extended",
- .device_id = USB_TO_CAN_V2_EXTENDED_PRODUCT_ID,
- .clock = {
- .freq = SJA1000_CRYSTAL_HZ,
- },
- .bittiming_const = {
- .name = "ixxat_usb",
- .tseg1_min = 1,
- .tseg1_max = 16,
- .tseg2_min = 1,
- .tseg2_max = 8,
- .sjw_max = 4,
- .brp_min = 1,
- .brp_max = 64,
- .brp_inc = 1,
- },
-
- .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
- CAN_CTRLMODE_BERR_REPORTING |
- CAN_CTRLMODE_LOOPBACK |
- CAN_CTRLMODE_LISTENONLY,
-
- /* size of device private data */
- .sizeof_dev_private = sizeof(struct ixx_usb_device),
-
- /* give here messages in/out endpoints */
- .ep_msg_in = { IXXAT_USBV2_EP_MSGIN_0, IXXAT_USBV2_EP_MSGIN_1,
- IXXAT_USBV2_EP_MSGIN_2, IXXAT_USBV2_EP_MSGIN_3,
- IXXAT_USBV2_EP_MSGIN_4 },
- .ep_msg_out = { IXXAT_USBV2_EP_MSGOUT_0, IXXAT_USBV2_EP_MSGOUT_1,
- IXXAT_USBV2_EP_MSGOUT_2, IXXAT_USBV2_EP_MSGOUT_3,
- IXXAT_USBV2_EP_MSGOUT_4 },
-
- /* size of rx/tx usb buffers */
- .rx_buffer_size = IXXAT_USBV2_RX_BUFFER_SIZE,
- .tx_buffer_size = IXXAT_USBV2_TX_BUFFER_SIZE,
-
- /* device callbacks */
- .intf_probe = ixx_usbv2_probe,
- .dev_get_dev_caps = ixx_usbv2_get_dev_caps,
- .dev_get_ctrl_caps = ixx_usbv2_get_ctrl_caps,
- .dev_init = ixx_usbv2_init,
- .dev_exit = ixx_usbv2_exit,
- .dev_set_bittiming = ixx_usbv2_set_bittiming,
- .intf_get_info = ixx_usbv2_get_dev_info,
- .intf_get_fw_info = ixx_usbv2_get_fwinfo,
- .dev_decode_buf = ixx_usbv2_decode_buf,
- .dev_encode_msg = ixx_usbv2_encode_msg,
- .dev_start = ixx_usbv2_start,
- .dev_stop = ixx_usbv2_stop,
-};
--
2.17.1
More information about the kernel-team
mailing list