146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* 246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * CAN driver for PEAK System PCAN-USB adapter 346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * Derived from the PCAN project file driver/src/pcan_usb.c 446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * 546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * Copyright (C) 2003-2010 PEAK System-Technik GmbH 646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * Copyright (C) 2011-2012 Stephane Grosjean <s.grosjean@peak-system.com> 746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * 846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * Many thanks to Klaus Hitschler <klaus.hitschler@gmx.de> 946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * 1046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * This program is free software; you can redistribute it and/or modify it 1146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * under the terms of the GNU General Public License as published 1246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * by the Free Software Foundation; version 2 of the License. 1346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * 1446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * This program is distributed in the hope that it will be useful, but 1546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * WITHOUT ANY WARRANTY; without even the implied warranty of 1646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * General Public License for more details. 1846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 1946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#include <linux/netdevice.h> 2046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#include <linux/usb.h> 2146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#include <linux/module.h> 2246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 2346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#include <linux/can.h> 2446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#include <linux/can/dev.h> 2546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#include <linux/can/error.h> 2646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 2746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#include "pcan_usb_core.h" 2846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 2946be265d3388339d8168c863791f0c7bbf3f2fedStephane GrosjeanMODULE_SUPPORTED_DEVICE("PEAK-System PCAN-USB adapter"); 3046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 3146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* PCAN-USB Endpoints */ 3246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_EP_CMDOUT 1 3346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_EP_CMDIN (PCAN_USB_EP_CMDOUT | USB_DIR_IN) 3446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_EP_MSGOUT 2 3546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_EP_MSGIN (PCAN_USB_EP_MSGOUT | USB_DIR_IN) 3646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 3746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* PCAN-USB command struct */ 3846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_CMD_FUNC 0 3946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_CMD_NUM 1 4046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_CMD_ARGS 2 4146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_CMD_ARGS_LEN 14 4246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_CMD_LEN (PCAN_USB_CMD_ARGS + \ 4346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean PCAN_USB_CMD_ARGS_LEN) 4446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 4546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* PCAN-USB command timeout (ms.) */ 4646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_COMMAND_TIMEOUT 1000 4746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 4846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* PCAN-USB startup timeout (ms.) */ 4946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_STARTUP_TIMEOUT 10 5046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 5146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* PCAN-USB rx/tx buffers size */ 5246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_RX_BUFFER_SIZE 64 5346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_TX_BUFFER_SIZE 64 5446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 5546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_MSG_HEADER_LEN 2 5646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 5746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* PCAN-USB adapter internal clock (MHz) */ 5846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_CRYSTAL_HZ 16000000 5946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 6046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* PCAN-USB USB message record status/len field */ 6146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_STATUSLEN_TIMESTAMP (1 << 7) 6246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_STATUSLEN_INTERNAL (1 << 6) 6346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_STATUSLEN_EXT_ID (1 << 5) 6446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_STATUSLEN_RTR (1 << 4) 6546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_STATUSLEN_DLC (0xf) 6646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 6746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* PCAN-USB error flags */ 6846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_ERROR_TXFULL 0x01 6946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_ERROR_RXQOVR 0x02 7046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_ERROR_BUS_LIGHT 0x04 7146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_ERROR_BUS_HEAVY 0x08 7246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_ERROR_BUS_OFF 0x10 7346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_ERROR_RXQEMPTY 0x20 7446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_ERROR_QOVR 0x40 7546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_ERROR_TXQFULL 0x80 7646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 7746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* SJA1000 modes */ 7846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define SJA1000_MODE_NORMAL 0x00 7946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define SJA1000_MODE_INIT 0x01 8046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 8146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* 8246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * tick duration = 42.666 us => 8346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * (tick_number * 44739243) >> 20 ~ (tick_number * 42666) / 1000 8446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * accuracy = 10^-7 8546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 8646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_TS_DIV_SHIFTER 20 8746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_TS_US_PER_TICK 44739243 8846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 8946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* PCAN-USB messages record types */ 9046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_REC_ERROR 1 9146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_REC_ANALOG 2 9246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_REC_BUSLOAD 3 9346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_REC_TS 4 9446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean#define PCAN_USB_REC_BUSEVT 5 9546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 9646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* private to PCAN-USB adapter */ 9746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstruct pcan_usb { 9846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct peak_usb_device dev; 9946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct peak_time_ref time_ref; 10046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct timer_list restart_timer; 10146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean}; 10246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 10346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* incoming message context for decoding */ 10446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstruct pcan_usb_msg_context { 10546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u16 ts16; 10646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 prev_ts8; 10746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 *ptr; 10846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 *end; 10946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 rec_cnt; 11046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 rec_idx; 11146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 rec_data_idx; 11246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct net_device *netdev; 11346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct pcan_usb *pdev; 11446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean}; 11546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 11646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* 11746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * send a command 11846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 11946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_send_cmd(struct peak_usb_device *dev, u8 f, u8 n, u8 *p) 12046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 12146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean int err; 12246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean int actual_length; 12346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 12446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* usb device unregistered? */ 12546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (!(dev->state & PCAN_USB_STATE_CONNECTED)) 12646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return 0; 12746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 12846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean dev->cmd_buf[PCAN_USB_CMD_FUNC] = f; 12946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean dev->cmd_buf[PCAN_USB_CMD_NUM] = n; 13046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 13146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (p) 13246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean memcpy(dev->cmd_buf + PCAN_USB_CMD_ARGS, 13346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean p, PCAN_USB_CMD_ARGS_LEN); 13446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 13546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean err = usb_bulk_msg(dev->udev, 13646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean usb_sndbulkpipe(dev->udev, PCAN_USB_EP_CMDOUT), 13746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean dev->cmd_buf, PCAN_USB_CMD_LEN, &actual_length, 13846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean PCAN_USB_COMMAND_TIMEOUT); 13946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (err) 14046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean netdev_err(dev->netdev, 14146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean "sending cmd f=0x%x n=0x%x failure: %d\n", 14246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean f, n, err); 14346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return err; 14446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 14546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 14646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* 14746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * send a command then wait for its response 14846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 14946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_wait_rsp(struct peak_usb_device *dev, u8 f, u8 n, u8 *p) 15046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 15146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean int err; 15246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean int actual_length; 15346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 15446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* usb device unregistered? */ 15546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (!(dev->state & PCAN_USB_STATE_CONNECTED)) 15646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return 0; 15746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 15846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* first, send command */ 15946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean err = pcan_usb_send_cmd(dev, f, n, NULL); 16046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (err) 16146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return err; 16246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 16346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean err = usb_bulk_msg(dev->udev, 16446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean usb_rcvbulkpipe(dev->udev, PCAN_USB_EP_CMDIN), 16546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean dev->cmd_buf, PCAN_USB_CMD_LEN, &actual_length, 16646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean PCAN_USB_COMMAND_TIMEOUT); 16746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (err) 16846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean netdev_err(dev->netdev, 16946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean "waiting rsp f=0x%x n=0x%x failure: %d\n", f, n, err); 17046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean else if (p) 17146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean memcpy(p, dev->cmd_buf + PCAN_USB_CMD_ARGS, 17246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean PCAN_USB_CMD_ARGS_LEN); 17346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 17446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return err; 17546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 17646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 17746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_set_sja1000(struct peak_usb_device *dev, u8 mode) 17846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 17946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 args[PCAN_USB_CMD_ARGS_LEN] = { 18046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean [1] = mode, 18146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean }; 18246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 18346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return pcan_usb_send_cmd(dev, 9, 2, args); 18446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 18546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 18646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_set_bus(struct peak_usb_device *dev, u8 onoff) 18746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 18846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 args[PCAN_USB_CMD_ARGS_LEN] = { 18946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean [0] = !!onoff, 19046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean }; 19146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 19246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return pcan_usb_send_cmd(dev, 3, 2, args); 19346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 19446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 19546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_set_silent(struct peak_usb_device *dev, u8 onoff) 19646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 19746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 args[PCAN_USB_CMD_ARGS_LEN] = { 19846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean [0] = !!onoff, 19946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean }; 20046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 20146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return pcan_usb_send_cmd(dev, 3, 3, args); 20246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 20346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 20446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_set_ext_vcc(struct peak_usb_device *dev, u8 onoff) 20546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 20646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 args[PCAN_USB_CMD_ARGS_LEN] = { 20746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean [0] = !!onoff, 20846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean }; 20946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 21046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return pcan_usb_send_cmd(dev, 10, 2, args); 21146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 21246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 21346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* 21446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * set bittiming value to can 21546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 21646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_set_bittiming(struct peak_usb_device *dev, 21746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct can_bittiming *bt) 21846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 21946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 args[PCAN_USB_CMD_ARGS_LEN]; 22046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 btr0, btr1; 22146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 22246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6); 22346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) | 22446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean (((bt->phase_seg2 - 1) & 0x7) << 4); 22546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (dev->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) 22646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean btr1 |= 0x80; 22746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 22846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean netdev_info(dev->netdev, "setting BTR0=0x%02x BTR1=0x%02x\n", 22946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean btr0, btr1); 23046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 23146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean args[0] = btr1; 23246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean args[1] = btr0; 23346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 23446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return pcan_usb_send_cmd(dev, 1, 2, args); 23546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 23646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 23746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* 23846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * init/reset can 23946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 24046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_write_mode(struct peak_usb_device *dev, u8 onoff) 24146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 24246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean int err; 24346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 24446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean err = pcan_usb_set_bus(dev, onoff); 24546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (err) 24646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return err; 24746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 24846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (!onoff) { 24946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean err = pcan_usb_set_sja1000(dev, SJA1000_MODE_INIT); 25046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } else { 25146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* the PCAN-USB needs time to init */ 25246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean set_current_state(TASK_INTERRUPTIBLE); 25346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean schedule_timeout(msecs_to_jiffies(PCAN_USB_STARTUP_TIMEOUT)); 25446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 25546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 25646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return err; 25746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 25846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 25946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* 26046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * handle end of waiting for the device to reset 26146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 26246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic void pcan_usb_restart(unsigned long arg) 26346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 26446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* notify candev and netdev */ 26546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean peak_usb_restart_complete((struct peak_usb_device *)arg); 26646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 26746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 26846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* 26946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * handle the submission of the restart urb 27046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 27146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic void pcan_usb_restart_pending(struct urb *urb) 27246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 27346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct pcan_usb *pdev = urb->context; 27446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 27546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* the PCAN-USB needs time to restart */ 27646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mod_timer(&pdev->restart_timer, 27746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean jiffies + msecs_to_jiffies(PCAN_USB_STARTUP_TIMEOUT)); 27846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 27946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* can delete usb resources */ 28046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean peak_usb_async_complete(urb); 28146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 28246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 28346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* 28446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * handle asynchronous restart 28546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 28646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_restart_async(struct peak_usb_device *dev, struct urb *urb, 28746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 *buf) 28846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 28946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct pcan_usb *pdev = container_of(dev, struct pcan_usb, dev); 29046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 29146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (timer_pending(&pdev->restart_timer)) 29246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return -EBUSY; 29346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 29446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* set bus on */ 29546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean buf[PCAN_USB_CMD_FUNC] = 3; 29646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean buf[PCAN_USB_CMD_NUM] = 2; 29746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean buf[PCAN_USB_CMD_ARGS] = 1; 29846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 29946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean usb_fill_bulk_urb(urb, dev->udev, 30046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean usb_sndbulkpipe(dev->udev, PCAN_USB_EP_CMDOUT), 30146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean buf, PCAN_USB_CMD_LEN, 30246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean pcan_usb_restart_pending, pdev); 30346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 30446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return usb_submit_urb(urb, GFP_ATOMIC); 30546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 30646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 30746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* 30846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * read serial number from device 30946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 31046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_get_serial(struct peak_usb_device *dev, u32 *serial_number) 31146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 31246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 args[PCAN_USB_CMD_ARGS_LEN]; 31346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean int err; 31446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 31546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean err = pcan_usb_wait_rsp(dev, 6, 1, args); 31646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (err) { 31746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean netdev_err(dev->netdev, "getting serial failure: %d\n", err); 31846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } else if (serial_number) { 31946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u32 tmp32; 32046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 32146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean memcpy(&tmp32, args, 4); 32246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean *serial_number = le32_to_cpu(tmp32); 32346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 32446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 32546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return err; 32646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 32746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 32846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* 32946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * read device id from device 33046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 33146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_get_device_id(struct peak_usb_device *dev, u32 *device_id) 33246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 33346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 args[PCAN_USB_CMD_ARGS_LEN]; 33446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean int err; 33546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 33646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean err = pcan_usb_wait_rsp(dev, 4, 1, args); 33746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (err) 33846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean netdev_err(dev->netdev, "getting device id failure: %d\n", err); 33946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean else if (device_id) 34046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean *device_id = args[0]; 34146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 34246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return err; 34346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 34446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 34546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* 34646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * update current time ref with received timestamp 34746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 34846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_update_ts(struct pcan_usb_msg_context *mc) 34946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 35046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u16 tmp16; 35146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 35246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if ((mc->ptr+2) > mc->end) 35346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return -EINVAL; 35446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 35546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean memcpy(&tmp16, mc->ptr, 2); 35646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 35746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->ts16 = le16_to_cpu(tmp16); 35846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 35946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (mc->rec_idx > 0) 36046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean peak_usb_update_ts_now(&mc->pdev->time_ref, mc->ts16); 36146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean else 36246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean peak_usb_set_ts_now(&mc->pdev->time_ref, mc->ts16); 36346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 36446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return 0; 36546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 36646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 36746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* 36846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * decode received timestamp 36946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 37046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_decode_ts(struct pcan_usb_msg_context *mc, u8 first_packet) 37146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 37246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* only 1st packet supplies a word timestamp */ 37346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (first_packet) { 37446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u16 tmp16; 37546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 37646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if ((mc->ptr + 2) > mc->end) 37746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return -EINVAL; 37846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 37946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean memcpy(&tmp16, mc->ptr, 2); 38046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->ptr += 2; 38146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 38246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->ts16 = le16_to_cpu(tmp16); 38346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->prev_ts8 = mc->ts16 & 0x00ff; 38446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } else { 38546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 ts8; 38646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 38746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if ((mc->ptr + 1) > mc->end) 38846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return -EINVAL; 38946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 39046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean ts8 = *mc->ptr++; 39146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 39246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (ts8 < mc->prev_ts8) 39346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->ts16 += 0x100; 39446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 39546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->ts16 &= 0xff00; 39646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->ts16 |= ts8; 39746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->prev_ts8 = ts8; 39846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 39946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 40046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return 0; 40146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 40246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 40346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n, 40446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 status_len) 40546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 40646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct sk_buff *skb; 40746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct can_frame *cf; 40846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct timeval tv; 40946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean enum can_state new_state; 41046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 41146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* ignore this error until 1st ts received */ 41246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (n == PCAN_USB_ERROR_QOVR) 41346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (!mc->pdev->time_ref.tick_count) 41446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return 0; 41546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 41646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean new_state = mc->pdev->dev.can.state; 41746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 41846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean switch (mc->pdev->dev.can.state) { 41946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean case CAN_STATE_ERROR_ACTIVE: 42046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (n & PCAN_USB_ERROR_BUS_LIGHT) { 42146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean new_state = CAN_STATE_ERROR_WARNING; 42246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean break; 42346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 42446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 42546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean case CAN_STATE_ERROR_WARNING: 42646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (n & PCAN_USB_ERROR_BUS_HEAVY) { 42746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean new_state = CAN_STATE_ERROR_PASSIVE; 42846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean break; 42946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 43046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (n & PCAN_USB_ERROR_BUS_OFF) { 43146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean new_state = CAN_STATE_BUS_OFF; 43246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean break; 43346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 43446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (n & (PCAN_USB_ERROR_RXQOVR | PCAN_USB_ERROR_QOVR)) { 43546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* 43646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * trick to bypass next comparison and process other 43746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * errors 43846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 43946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean new_state = CAN_STATE_MAX; 44046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean break; 44146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 44246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if ((n & PCAN_USB_ERROR_BUS_LIGHT) == 0) { 44346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* no error (back to active state) */ 44446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->pdev->dev.can.state = CAN_STATE_ERROR_ACTIVE; 44546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return 0; 44646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 44746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean break; 44846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 44946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean case CAN_STATE_ERROR_PASSIVE: 45046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (n & PCAN_USB_ERROR_BUS_OFF) { 45146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean new_state = CAN_STATE_BUS_OFF; 45246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean break; 45346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 45446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (n & PCAN_USB_ERROR_BUS_LIGHT) { 45546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean new_state = CAN_STATE_ERROR_WARNING; 45646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean break; 45746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 45846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (n & (PCAN_USB_ERROR_RXQOVR | PCAN_USB_ERROR_QOVR)) { 45946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* 46046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * trick to bypass next comparison and process other 46146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * errors 46246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 46346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean new_state = CAN_STATE_MAX; 46446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean break; 46546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 46646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 46746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if ((n & PCAN_USB_ERROR_BUS_HEAVY) == 0) { 46846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* no error (back to active state) */ 46946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->pdev->dev.can.state = CAN_STATE_ERROR_ACTIVE; 47046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return 0; 47146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 47246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean break; 47346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 47446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean default: 47546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* do nothing waiting for restart */ 47646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return 0; 47746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 47846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 47946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* donot post any error if current state didn't change */ 48046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (mc->pdev->dev.can.state == new_state) 48146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return 0; 48246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 48346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* allocate an skb to store the error frame */ 48446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean skb = alloc_can_err_skb(mc->netdev, &cf); 48546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (!skb) 48646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return -ENOMEM; 48746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 48846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean switch (new_state) { 48946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean case CAN_STATE_BUS_OFF: 49046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean cf->can_id |= CAN_ERR_BUSOFF; 49146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean can_bus_off(mc->netdev); 49246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean break; 49346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 49446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean case CAN_STATE_ERROR_PASSIVE: 49546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean cf->can_id |= CAN_ERR_CRTL; 49646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE | 49746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean CAN_ERR_CRTL_RX_PASSIVE; 49846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->pdev->dev.can.can_stats.error_passive++; 49946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean break; 50046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 50146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean case CAN_STATE_ERROR_WARNING: 50246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean cf->can_id |= CAN_ERR_CRTL; 50346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean cf->data[1] |= CAN_ERR_CRTL_TX_WARNING | 50446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean CAN_ERR_CRTL_RX_WARNING; 50546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->pdev->dev.can.can_stats.error_warning++; 50646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean break; 50746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 50846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean default: 50946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* CAN_STATE_MAX (trick to handle other errors) */ 51046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean cf->can_id |= CAN_ERR_CRTL; 51146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW; 51246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->netdev->stats.rx_over_errors++; 51346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->netdev->stats.rx_errors++; 51446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 51546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean new_state = mc->pdev->dev.can.state; 51646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean break; 51746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 51846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 51946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->pdev->dev.can.state = new_state; 52046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 52146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (status_len & PCAN_USB_STATUSLEN_TIMESTAMP) { 522c9faaa09e2a1335678f09c70a0d0eda095564babOliver Hartkopp struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb); 523c9faaa09e2a1335678f09c70a0d0eda095564babOliver Hartkopp 52446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean peak_usb_get_ts_tv(&mc->pdev->time_ref, mc->ts16, &tv); 525c9faaa09e2a1335678f09c70a0d0eda095564babOliver Hartkopp hwts->hwtstamp = timeval_to_ktime(tv); 52646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 52746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 52846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean netif_rx(skb); 52946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->netdev->stats.rx_packets++; 53046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->netdev->stats.rx_bytes += cf->can_dlc; 53146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 53246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return 0; 53346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 53446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 53546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* 53646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * decode non-data usb message 53746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 53846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_decode_status(struct pcan_usb_msg_context *mc, 53946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 status_len) 54046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 54146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 rec_len = status_len & PCAN_USB_STATUSLEN_DLC; 54246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 f, n; 54346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean int err; 54446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 54546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* check whether function and number can be read */ 54646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if ((mc->ptr + 2) > mc->end) 54746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return -EINVAL; 54846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 54946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean f = mc->ptr[PCAN_USB_CMD_FUNC]; 55046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean n = mc->ptr[PCAN_USB_CMD_NUM]; 55146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->ptr += PCAN_USB_CMD_ARGS; 55246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 55346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (status_len & PCAN_USB_STATUSLEN_TIMESTAMP) { 55446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean int err = pcan_usb_decode_ts(mc, !mc->rec_idx); 55546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 55646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (err) 55746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return err; 55846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 55946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 56046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean switch (f) { 56146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean case PCAN_USB_REC_ERROR: 56246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean err = pcan_usb_decode_error(mc, n, status_len); 56346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (err) 56446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return err; 56546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean break; 56646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 56746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean case PCAN_USB_REC_ANALOG: 56846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* analog values (ignored) */ 56946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean rec_len = 2; 57046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean break; 57146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 57246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean case PCAN_USB_REC_BUSLOAD: 57346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* bus load (ignored) */ 57446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean rec_len = 1; 57546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean break; 57646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 57746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean case PCAN_USB_REC_TS: 57846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* only timestamp */ 57946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (pcan_usb_update_ts(mc)) 58046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return -EINVAL; 58146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean break; 58246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 58346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean case PCAN_USB_REC_BUSEVT: 58446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* error frame/bus event */ 58546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (n & PCAN_USB_ERROR_TXQFULL) 58646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean netdev_dbg(mc->netdev, "device Tx queue full)\n"); 58746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean break; 58846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean default: 58946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean netdev_err(mc->netdev, "unexpected function %u\n", f); 59046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean break; 59146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 59246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 59346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if ((mc->ptr + rec_len) > mc->end) 59446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return -EINVAL; 59546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 59646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->ptr += rec_len; 59746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 59846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return 0; 59946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 60046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 60146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* 60246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * decode data usb message 60346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 60446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len) 60546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 60646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 rec_len = status_len & PCAN_USB_STATUSLEN_DLC; 60746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct sk_buff *skb; 60846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct can_frame *cf; 60946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct timeval tv; 610c9faaa09e2a1335678f09c70a0d0eda095564babOliver Hartkopp struct skb_shared_hwtstamps *hwts; 61146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 61246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean skb = alloc_can_skb(mc->netdev, &cf); 61346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (!skb) 61446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return -ENOMEM; 61546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 61646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (status_len & PCAN_USB_STATUSLEN_EXT_ID) { 61746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u32 tmp32; 61846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 61946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if ((mc->ptr + 4) > mc->end) 62046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean goto decode_failed; 62146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 62246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean memcpy(&tmp32, mc->ptr, 4); 62346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->ptr += 4; 62446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 62546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean cf->can_id = le32_to_cpu(tmp32 >> 3) | CAN_EFF_FLAG; 62646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } else { 62746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u16 tmp16; 62846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 62946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if ((mc->ptr + 2) > mc->end) 63046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean goto decode_failed; 63146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 63246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean memcpy(&tmp16, mc->ptr, 2); 63346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->ptr += 2; 63446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 63546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean cf->can_id = le16_to_cpu(tmp16 >> 5); 63646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 63746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 63846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean cf->can_dlc = get_can_dlc(rec_len); 63946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 64046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* first data packet timestamp is a word */ 64146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (pcan_usb_decode_ts(mc, !mc->rec_data_idx)) 64246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean goto decode_failed; 64346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 64446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* read data */ 64546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean memset(cf->data, 0x0, sizeof(cf->data)); 64646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (status_len & PCAN_USB_STATUSLEN_RTR) { 64746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean cf->can_id |= CAN_RTR_FLAG; 64846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } else { 64946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if ((mc->ptr + rec_len) > mc->end) 65046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean goto decode_failed; 65146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 6523c322a56b01695df15c70bfdc2d02e0ccd80654eStephane Grosjean memcpy(cf->data, mc->ptr, cf->can_dlc); 65346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->ptr += rec_len; 65446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 65546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 65646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* convert timestamp into kernel time */ 65746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean peak_usb_get_ts_tv(&mc->pdev->time_ref, mc->ts16, &tv); 658c9faaa09e2a1335678f09c70a0d0eda095564babOliver Hartkopp hwts = skb_hwtstamps(skb); 659c9faaa09e2a1335678f09c70a0d0eda095564babOliver Hartkopp hwts->hwtstamp = timeval_to_ktime(tv); 66046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 66146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* push the skb */ 66246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean netif_rx(skb); 66346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 66446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* update statistics */ 66546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->netdev->stats.rx_packets++; 66646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc->netdev->stats.rx_bytes += cf->can_dlc; 66746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 66846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return 0; 66946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 67046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeandecode_failed: 67146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean dev_kfree_skb(skb); 67246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return -EINVAL; 67346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 67446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 67546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* 67646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * process incoming message 67746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 67846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_decode_msg(struct peak_usb_device *dev, u8 *ibuf, u32 lbuf) 67946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 68046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct pcan_usb_msg_context mc = { 68146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .rec_cnt = ibuf[1], 68246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .ptr = ibuf + PCAN_USB_MSG_HEADER_LEN, 68346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .end = ibuf + lbuf, 68446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .netdev = dev->netdev, 68546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .pdev = container_of(dev, struct pcan_usb, dev), 68646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean }; 68746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean int err; 68846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 68946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean for (err = 0; mc.rec_idx < mc.rec_cnt && !err; mc.rec_idx++) { 69046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 sl = *mc.ptr++; 69146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 69246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* handle status and error frames here */ 69346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (sl & PCAN_USB_STATUSLEN_INTERNAL) { 69446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean err = pcan_usb_decode_status(&mc, sl); 69546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* handle normal can frames here */ 69646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } else { 69746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean err = pcan_usb_decode_data(&mc, sl); 69846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean mc.rec_data_idx++; 69946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 70046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 70146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 70246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return err; 70346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 70446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 70546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* 70646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * process any incoming buffer 70746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 70846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_decode_buf(struct peak_usb_device *dev, struct urb *urb) 70946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 71046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean int err = 0; 71146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 71246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (urb->actual_length > PCAN_USB_MSG_HEADER_LEN) { 71346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean err = pcan_usb_decode_msg(dev, urb->transfer_buffer, 71446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean urb->actual_length); 71546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 71646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } else if (urb->actual_length > 0) { 71746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean netdev_err(dev->netdev, "usb message length error (%u)\n", 71846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean urb->actual_length); 71946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean err = -EINVAL; 72046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 72146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 72246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return err; 72346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 72446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 72546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* 72646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * process outgoing packet 72746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 72846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_encode_msg(struct peak_usb_device *dev, struct sk_buff *skb, 72946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 *obuf, size_t *size) 73046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 73146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct net_device *netdev = dev->netdev; 73246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct net_device_stats *stats = &netdev->stats; 73346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct can_frame *cf = (struct can_frame *)skb->data; 73446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u8 *pc; 73546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 73646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean obuf[0] = 2; 73746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean obuf[1] = 1; 73846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 73946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean pc = obuf + PCAN_USB_MSG_HEADER_LEN; 74046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 74146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* status/len byte */ 74246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean *pc = cf->can_dlc; 74346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (cf->can_id & CAN_RTR_FLAG) 74446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean *pc |= PCAN_USB_STATUSLEN_RTR; 74546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 74646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* can id */ 74746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (cf->can_id & CAN_EFF_FLAG) { 7481ccba2103a8b3a1041f261301b08b9e16f76df8aStephane Grosjean __le32 tmp32 = cpu_to_le32((cf->can_id & CAN_ERR_MASK) << 3); 74946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 75046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean *pc |= PCAN_USB_STATUSLEN_EXT_ID; 75146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean memcpy(++pc, &tmp32, 4); 75246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean pc += 4; 75346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } else { 7541ccba2103a8b3a1041f261301b08b9e16f76df8aStephane Grosjean __le16 tmp16 = cpu_to_le16((cf->can_id & CAN_ERR_MASK) << 5); 75546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 75646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean memcpy(++pc, &tmp16, 2); 75746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean pc += 2; 75846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 75946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 76046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* can data */ 76146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (!(cf->can_id & CAN_RTR_FLAG)) { 76246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean memcpy(pc, cf->data, cf->can_dlc); 76346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean pc += cf->can_dlc; 76446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 76546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 76646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean obuf[(*size)-1] = (u8)(stats->tx_packets & 0xff); 76746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 76846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return 0; 76946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 77046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 77146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* 77246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * start interface 77346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 77446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_start(struct peak_usb_device *dev) 77546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 77646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct pcan_usb *pdev = container_of(dev, struct pcan_usb, dev); 77746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 77846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* number of bits used in timestamps read from adapter struct */ 77946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean peak_usb_init_time_ref(&pdev->time_ref, &pcan_usb); 78046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 78146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* if revision greater than 3, can put silent mode on/off */ 78246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (dev->device_rev > 3) { 78346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean int err; 78446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 78546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean err = pcan_usb_set_silent(dev, 78646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY); 78746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (err) 78846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return err; 78946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 79046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 79146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return pcan_usb_set_ext_vcc(dev, 0); 79246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 79346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 79446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_init(struct peak_usb_device *dev) 79546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 79646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct pcan_usb *pdev = container_of(dev, struct pcan_usb, dev); 79746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean u32 serial_number; 79846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean int err; 79946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 80046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* initialize a timer needed to wait for hardware restart */ 80146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean init_timer(&pdev->restart_timer); 80246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean pdev->restart_timer.function = pcan_usb_restart; 80346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean pdev->restart_timer.data = (unsigned long)dev; 80446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 80546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* 80646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * explicit use of dev_xxx() instead of netdev_xxx() here: 80746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * information displayed are related to the device itself, not 80846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * to the canx netdevice. 80946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 81046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean err = pcan_usb_get_serial(dev, &serial_number); 81146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if (err) { 81246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean dev_err(dev->netdev->dev.parent, 81346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean "unable to read %s serial number (err %d)\n", 81446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean pcan_usb.name, err); 81546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return err; 81646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 81746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 81846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean dev_info(dev->netdev->dev.parent, 81946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean "PEAK-System %s adapter hwrev %u serial %08X (%u channel)\n", 82046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean pcan_usb.name, dev->device_rev, serial_number, 82146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean pcan_usb.ctrl_count); 82246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 82346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return 0; 82446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 82546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 82646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* 82746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * probe function for new PCAN-USB usb interface 82846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 82946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstatic int pcan_usb_probe(struct usb_interface *intf) 83046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean{ 83146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct usb_host_interface *if_desc; 83246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean int i; 83346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 83446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean if_desc = intf->altsetting; 83546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 83646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* check interface endpoint addresses */ 83746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean for (i = 0; i < if_desc->desc.bNumEndpoints; i++) { 83846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean struct usb_endpoint_descriptor *ep = &if_desc->endpoint[i].desc; 83946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 84046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean switch (ep->bEndpointAddress) { 84146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean case PCAN_USB_EP_CMDOUT: 84246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean case PCAN_USB_EP_CMDIN: 84346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean case PCAN_USB_EP_MSGOUT: 84446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean case PCAN_USB_EP_MSGIN: 84546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean break; 84646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean default: 84746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return -ENODEV; 84846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 84946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean } 85046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 85146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean return 0; 85246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean} 85346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 85446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean/* 85546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean * describe the PCAN-USB adapter 85646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean */ 85746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjeanstruct peak_usb_adapter pcan_usb = { 85846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .name = "PCAN-USB", 85946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .device_id = PCAN_USB_PRODUCT_ID, 86046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .ctrl_count = 1, 86146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .clock = { 86246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .freq = PCAN_USB_CRYSTAL_HZ / 2 , 86346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean }, 86446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .bittiming_const = { 86546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .name = "pcan_usb", 86646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .tseg1_min = 1, 86746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .tseg1_max = 16, 86846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .tseg2_min = 1, 86946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .tseg2_max = 8, 87046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .sjw_max = 4, 87146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .brp_min = 1, 87246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .brp_max = 64, 87346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .brp_inc = 1, 87446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean }, 87546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 87646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* size of device private data */ 87746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .sizeof_dev_private = sizeof(struct pcan_usb), 87846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 87946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* timestamps usage */ 88046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .ts_used_bits = 16, 88146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .ts_period = 24575, /* calibration period in ts. */ 88246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .us_per_ts_scale = PCAN_USB_TS_US_PER_TICK, /* us=(ts*scale) */ 88346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .us_per_ts_shift = PCAN_USB_TS_DIV_SHIFTER, /* >> shift */ 88446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 88546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* give here messages in/out endpoints */ 88646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .ep_msg_in = PCAN_USB_EP_MSGIN, 88746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .ep_msg_out = {PCAN_USB_EP_MSGOUT}, 88846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 88946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* size of rx/tx usb buffers */ 89046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .rx_buffer_size = PCAN_USB_RX_BUFFER_SIZE, 89146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .tx_buffer_size = PCAN_USB_TX_BUFFER_SIZE, 89246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean 89346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean /* device callbacks */ 89446be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .intf_probe = pcan_usb_probe, 89546be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .dev_init = pcan_usb_init, 89646be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .dev_set_bus = pcan_usb_write_mode, 89746be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .dev_set_bittiming = pcan_usb_set_bittiming, 89846be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .dev_get_device_id = pcan_usb_get_device_id, 89946be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .dev_decode_buf = pcan_usb_decode_buf, 90046be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .dev_encode_msg = pcan_usb_encode_msg, 90146be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .dev_start = pcan_usb_start, 90246be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean .dev_restart_async = pcan_usb_restart_async, 90346be265d3388339d8168c863791f0c7bbf3f2fedStephane Grosjean}; 904