From: Wolfgang Grandegger <wg@grandegger.com>
To: Stephane Grosjean <s.grosjean@peak-system.com>
Cc: Oliver Hartkopp <socketcan@hartkopp.net>,
Linux CAN mailing list <linux-can@vger.kernel.org>
Subject: Re: [PATCH] Add support for PEAK System PCAN-USB Pro adapter
Date: Tue, 10 Jan 2012 12:21:09 +0100 [thread overview]
Message-ID: <4F0C1F25.3000304@grandegger.com> (raw)
In-Reply-To: <604716.570905538-sendEmail@ubuntu-i386>
On 12/22/2011 02:14 PM, Stephane Grosjean wrote:
>>From a1b285074b883edc3dccc6aacafb18407e98e18a Mon Sep 17 00:00:00 2001
> From: Stephane Grosjean <s.grosjean@peak-system.com>
> Date: Thu, 22 Dec 2011 13:59:00 +0100
> Subject: [PATCH] Add support for PEAK System PCAN-USB Pro adapter
>
> ---
> drivers/net/can/usb/peak_usb/pcan_usb_pro.c | 1092 +++++++++++++++++++++++++++
> drivers/net/can/usb/peak_usb/pcan_usb_pro.h | 352 +++++++++
> 2 files changed, 1444 insertions(+), 0 deletions(-)
> create mode 100644 drivers/net/can/usb/peak_usb/pcan_usb_pro.c
> create mode 100644 drivers/net/can/usb/peak_usb/pcan_usb_pro.h
>
> diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
> new file mode 100644
> index 0000000..0747395
> --- /dev/null
> +++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
> @@ -0,0 +1,1092 @@
> +/*
> + * CAN driver for PEAK System PCAN-USB Pro adapter
> + *
> + * Copyright (C) 2011-2012 PEAK-System GmbH
> + *
> + * 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/can.h>
> +#include <linux/can/dev.h>
> +#include <linux/can/error.h>
> +
> +#include "peak_usb.h"
> +#include "pcan_usb_pro.h"
> +
> +MODULE_SUPPORTED_DEVICE("PEAK-System PCAN-USB Pro adapter");
> +
> +/* PCAN-USB Pro Endpoints */
> +#define PCAN_USBPRO_EP_CMDOUT 1
> +#define PCAN_USBPRO_EP_CMDIN (PCAN_USBPRO_EP_CMDOUT | USB_DIR_IN)
> +#define PCAN_USBPRO_EP_MSGOUT_0 2
> +#define PCAN_USBPRO_EP_MSGIN (PCAN_USBPRO_EP_MSGOUT_0 | USB_DIR_IN)
> +#define PCAN_USBPRO_EP_MSGOUT_1 3
> +
> +#define PCAN_USBPRO_CHANNEL_COUNT 2
> +
> +/* PCAN-USB Pro adapter internal clock (MHz) */
> +#define PCAN_USBPRO_CRYSTAL_HZ 56000000
> +
> +/* PCAN-USB Pro command timeout (ms.) */
> +#define PCAN_USBPRO_COMMAND_TIMEOUT 1000
> +
> +/* PCAN-USB Pro rx/tx buffers size */
> +#define PCAN_USBPRO_RX_BUFFER_SIZE 1024
> +#define PCAN_USBPRO_TX_BUFFER_SIZE 64
> +
> +#define PCAN_USBPRO_MSG_HEADER_LEN 4
> +
> +/* Some commands responses need to be re-submitted */
> +#define PCAN_USBPRO_RSP_SUBMIT_MAX 2
> +
> +#define PCAN_USBPRO_RTR 0x01
> +#define PCAN_USBPRO_EXT 0x02
> +
> +#define PCAN_USBPRO_CMD_BUFFER_SIZE 512
> +
> +struct pcan_usb_pro_interface {
> + struct peak_usb_device *dev[PCAN_USBPRO_CHANNEL_COUNT];
> + struct peak_time_ref time_ref;
> + int cm_ignore_count;
> + int dev_opened_count;
> +};
> +
> +struct pcan_usb_pro_device {
> + struct peak_usb_device peak_usb_device; /* must be the first member */
This construction is deprecated. Using container_of() is usually the
better and safer solution. Is it an option?
> + struct pcan_usb_pro_interface *usb_if;
> +};
> +
> +/* Internal structure used to handle messages sent to bulk urb */
> +struct pcan_usb_pro_msg {
> + u8 *rec_ptr;
> + int rec_buffer_size;
> + int rec_buffer_len;
> + union {
> + u16 *rec_cnt_rd;
> + u32 *rec_cnt;
> + u8 *rec_buffer;
> + } u;
> +};
> +
> +static int pcan_usb_pro_sizeof_rec(u8 data_type)
> +{
> + switch (data_type) {
> + case PCAN_USBPRO_RXMSG8:
> + return sizeof(struct pcan_usb_pro_rxmsg);
> + case PCAN_USBPRO_RXMSG4:
> + return sizeof(struct pcan_usb_pro_rxmsg) - 4;
> + case PCAN_USBPRO_RXMSG0:
> + case PCAN_USBPRO_RXRTR:
> + return sizeof(struct pcan_usb_pro_rxmsg) - 8;
> + case PCAN_USBPRO_RXSTATUS:
> + return sizeof(struct pcan_usb_pro_rxstatus);
> + case PCAN_USBPRO_RXTS:
> + return sizeof(struct pcan_usb_pro_rxts);
> + case PCAN_USBPRO_TXMSG8:
> + return sizeof(struct pcan_usb_pro_txmsg);
> + case PCAN_USBPRO_TXMSG4:
> + return sizeof(struct pcan_usb_pro_txmsg) - 4;
> + case PCAN_USBPRO_TXMSG0:
> + return sizeof(struct pcan_usb_pro_txmsg) - 8;
> + case PCAN_USBPRO_GETBTR:
> + case PCAN_USBPRO_SETBTR:
> + return sizeof(struct pcan_usb_pro_btr);
> + case PCAN_USBPRO_SETSILENT:
> + return sizeof(struct pcan_usb_pro_silent);
> + case PCAN_USBPRO_SETDEVID:
> + case PCAN_USBPRO_GETDEVID:
> + return sizeof(struct pcan_usb_pro_devid);
> + case PCAN_USBPRO_GETBUSACT:
> + case PCAN_USBPRO_SETBUSACT:
> + return sizeof(struct pcan_usb_pro_busact);
> + case PCAN_USBPRO_SETWARNLIM:
> + return sizeof(struct pcan_usb_pro_warnlim);
> + case PCAN_USBPRO_SETLKUP:
> + return sizeof(struct pcan_usb_pro_lkup);
> + case PCAN_USBPRO_SETLKUPGRP:
> + return sizeof(struct pcan_usb_pro_lkupgrp);
> + case PCAN_USBPRO_SETFILTR:
> + return sizeof(struct pcan_usb_pro_filter);
> + case PCAN_USBPRO_SETRST:
> + return sizeof(struct pcan_usb_pro_reset);
> + case PCAN_USBPRO_SETERRFRM:
> + return sizeof(struct pcan_usb_pro_errfrm);
> + case PCAN_USBPRO_GETBUSSTAT:
> + return sizeof(struct pcan_usb_pro_busstat);
> + case PCAN_USBPRO_SETREG:
> + return sizeof(struct pcan_usb_pro_setreg);
> + case PCAN_USBPRO_GETREG:
> + return sizeof(struct pcan_usb_pro_getreg);
> + case PCAN_USBPRO_SETTS:
> + return sizeof(struct pcan_usb_pro_setts);
> + case PCAN_USBPRO_SETSTR:
> + return sizeof(struct pcan_usb_pro_setstr);
> + case PCAN_USBPRO_GETSTR:
> + return sizeof(struct pcan_usb_pro_getstr);
> + case PCAN_USBPRO_STRING:
> + return sizeof(struct pcan_usb_pro_str);
> + case PCAN_USBPRO_SAVE:
> + return sizeof(struct pcan_usb_pro_save);
> + case PCAN_USBPRO_PDELAY:
> + return sizeof(struct pcan_usb_pro_pdelay);
> + case PCAN_USBPRO_TSARG:
> + return sizeof(struct pcan_usb_pro_tsarg);
> + case PCAN_USBPRO_ERRID:
> + return sizeof(struct pcan_usb_pro_errid);
> + case PCAN_USBPRO_ERRNOW:
> + return sizeof(struct pcan_usb_pro_errnow);
> + case PCAN_USBPRO_SETSFILER:
> + return sizeof(struct pcan_usb_pro_sfiller);
> + case PCAN_USBPRO_SETLED:
> + return sizeof(struct pcan_usb_pro_setled);
> + default:
> + pr_info("%s: %s(%d): unsupported data type\n",
> + PCAN_USB_DRIVER_NAME, __func__, data_type);
> + break;
> + }
> +
> + return -1;
> +}
Please use a jump table, which you already did, IIRC.
> +/*
> + * initialize PCAN-USB Pro message data structure
> + */
> +static u8 *pcan_usb_pro_msg_init(struct pcan_usb_pro_msg *pm,
> + void *buffer_addr, int buffer_size)
> +{
> + if (buffer_size < PCAN_USBPRO_MSG_HEADER_LEN)
> + return NULL;
> +
> + pm->u.rec_buffer = (u8 *)buffer_addr;
> + pm->rec_buffer_size = pm->rec_buffer_len = buffer_size;
> + pm->rec_ptr = pm->u.rec_buffer + PCAN_USBPRO_MSG_HEADER_LEN;
> +
> + return pm->rec_ptr;
> +}
> +
> +static u8 *pcan_usb_pro_msg_init_empty(struct pcan_usb_pro_msg *pm,
> + void *buffer_addr, int buffer_size)
> +{
> + u8 *pr = pcan_usb_pro_msg_init(pm, buffer_addr, buffer_size);
> + if (pr) {
> + pm->rec_buffer_len = PCAN_USBPRO_MSG_HEADER_LEN;
> + *pm->u.rec_cnt = 0;
> + }
> + return pr;
> +}
> +
> +/*
> + * add one record to a message being built
> + */
> +static int pcan_usb_pro_add_rec(struct pcan_usb_pro_msg *pm, int id, ...)
> +{
> + int l, i;
l or 1? Depending on your font, it will be hard to distinguish.
Therefore, please use "j", "k", or "len" instead.
> + u8 *pc;
> + va_list ap;
> +
> + va_start(ap, id);
> +
> + pc = pm->rec_ptr + 1;
> +
> + i = 0;
> + switch (id) {
> + case PCAN_USBPRO_TXMSG8:
> + i += 4;
> + case PCAN_USBPRO_TXMSG4:
> + i += 4;
> + case PCAN_USBPRO_TXMSG0:
> + *pc++ = (u8)va_arg(ap, int);
> + *pc++ = (u8)va_arg(ap, int);
> + *pc++ = (u8)va_arg(ap, int);
Are the casts (u8) and (u16) here and below really needed?
> + *(u32 *)pc = cpu_to_le32(va_arg(ap, u32));
> + pc += 4;
> + memcpy(pc, va_arg(ap, int *), i);
> + pc += i;
> + break;
> +
> + case PCAN_USBPRO_GETBUSACT:
> + case PCAN_USBPRO_GETBUSSTAT:
> + *pc++ = (u8)va_arg(ap, int);
> + break;
> +
> + case PCAN_USBPRO_SETBTR:
> + case PCAN_USBPRO_GETBTR:
> + case PCAN_USBPRO_SETDEVID:
> + case PCAN_USBPRO_GETDEVID:
> + *pc++ = (u8)va_arg(ap, int);
> + pc += 2;
> + *(u32 *)pc = cpu_to_le32(va_arg(ap, u32));
> + pc += 4;
> + break;
> +
> + case PCAN_USBPRO_SETBUSACT:
> + case PCAN_USBPRO_SETSILENT:
> + case PCAN_USBPRO_SETWARNLIM:
> + case PCAN_USBPRO_SETFILTR:
> + case PCAN_USBPRO_SETRST:
> + case PCAN_USBPRO_SETERRFRM:
> + case PCAN_USBPRO_TSARG:
> + case PCAN_USBPRO_ERRNOW:
> + *pc++ = (u8)va_arg(ap, int);
> + *(u16 *)pc = cpu_to_le16((u16)va_arg(ap, int));
> + pc += 2;
> + break;
> +
> + case PCAN_USBPRO_SETLKUP:
> + case PCAN_USBPRO_SETLED:
> + *pc++ = (u8)va_arg(ap, int);
> + *(u16 *)pc = cpu_to_le16((u16)va_arg(ap, int));
> + pc += 2;
> + *(u32 *)pc = cpu_to_le32(va_arg(ap, u32));
> + pc += 4;
> + break;
> +
> + case PCAN_USBPRO_SETLKUPGRP:
> + *pc++ = (u8)va_arg(ap, int);
> + *(u16 *)pc = cpu_to_le16((u16)va_arg(ap, int));
> + pc += 2;
> + *(u32 *)pc = cpu_to_le32(va_arg(ap, u32));
> + pc += 4;
> + *(u32 *)pc = cpu_to_le32(va_arg(ap, u32));
> + pc += 4;
> + break;
> +
> + case PCAN_USBPRO_SETREG:
> + *pc++ = (u8)va_arg(ap, int);
> + pc += 2;
> + *(u32 *)pc = cpu_to_le32(va_arg(ap, u32));
> + pc += 4;
> + *(u32 *)pc = cpu_to_le32(va_arg(ap, u32));
> + pc += 4;
> + *(u32 *)pc = cpu_to_le32(va_arg(ap, u32));
> + pc += 4;
> + break;
> +
> + case PCAN_USBPRO_GETREG:
> + *pc++ = (u8)va_arg(ap, int);
> + pc += 2;
> + *(u32 *)pc = cpu_to_le32(va_arg(ap, u32));
> + pc += 4;
> + *(u32 *)pc = cpu_to_le32(va_arg(ap, u32));
> + pc += 4;
> + break;
> +
> + case PCAN_USBPRO_SETTS:
> + case PCAN_USBPRO_PDELAY:
> + pc++;
> + *(u16 *)pc = cpu_to_le16((u16)va_arg(ap, int));
> + pc += 2;
> + break;
> +
> + case PCAN_USBPRO_SETBUSLAST:
> + *pc++ = (u8)va_arg(ap, int);
> + pc++;
> + *pc++ = (u8)va_arg(ap, int);
> + pc += 2;
> + *(u16 *)pc = cpu_to_le16(4096);
> + pc += 2;
> + break;
> +
> + case PCAN_USBPRO_SETSTR:
> + *pc++ = (u8)va_arg(ap, int);
> + *pc++ = (u8)va_arg(ap, int);
> + *pc++ = (u8)va_arg(ap, int);
> + memcpy(pc, va_arg(ap, u8 *), 60);
> + pc += 60;
> + break;
> +
> + case PCAN_USBPRO_GETSTR:
> + case PCAN_USBPRO_SAVE:
> + *pc++ = (u8)va_arg(ap, int);
> + pc += 2;
> + break;
> +
> + case PCAN_USBPRO_STRING:
> + *pc++ = (u8)va_arg(ap, int);
> + pc += 2;
> + memcpy(pc, va_arg(ap, u8 *), 250);
> + pc += 250;
> + break;
> +
> + case PCAN_USBPRO_ERRID:
> + *pc++ = (u8)va_arg(ap, int);
> + *(u16 *)pc = cpu_to_le16((u16)va_arg(ap, int));
> + pc += 2;
> + *(u32 *)pc = cpu_to_le32(va_arg(ap, u32));
> + pc += 4;
> + *(u16 *)pc = cpu_to_le16((u16)va_arg(ap, int));
> + pc += 2;
> + *(u16 *)pc = cpu_to_le16((u16)va_arg(ap, int));
> + pc += 2;
> + break;
> +
> + case PCAN_USBPRO_SETSFILER:
> + *pc++ = (u8)va_arg(ap, int);
> + pc += 2;
> + *(u32 *)pc = cpu_to_le32(va_arg(ap, u32));
> + pc += 4;
> + *(u32 *)pc = cpu_to_le32(va_arg(ap, u32));
> + pc += 4;
> + break;
> +
> + default:
> + pr_info("%s: %s(): unknown data type %02Xh (%d)\n",
> + PCAN_USB_DRIVER_NAME, __func__, id, id);
info or error?
> + pc--;
> + break;
> + }
A jump table would make sense here as well combining it with the one
used above.
> + l = pc - pm->rec_ptr;
> + if (l > 0) {
> + *pm->u.rec_cnt = cpu_to_le32(*pm->u.rec_cnt+1);
> + *(pm->rec_ptr) = (u8)id;
> +
> + pm->rec_ptr = pc;
> + pm->rec_buffer_len += l;
> + }
> +
> + va_end(ap);
> +
> + return l;
> +}
> +
> +/*
> + * send PCAN-USB Pro command synchronously
> + */
> +static int pcan_usb_pro_send_cmd(struct peak_usb_device *dev,
> + struct pcan_usb_pro_msg *pum)
> +{
> + int actual_length;
> + int err;
> +
> + /* usb device unregistered? */
> + if (!(dev->state & PCAN_USB_STATE_CONNECTED))
> + return 0;
> +
> + err = usb_bulk_msg(dev->udev,
> + usb_sndbulkpipe(dev->udev, PCAN_USBPRO_EP_CMDOUT),
> + pum->u.rec_buffer, pum->rec_buffer_len,
> + &actual_length, PCAN_USBPRO_COMMAND_TIMEOUT);
> + if (err)
> + netdev_err(dev->netdev, "sending command failure: %d\n", err);
> +
> + return err;
> +}
> +
> +/*
> + * wait for PCAN-USB Pro command response
> + */
> +static int pcan_usb_pro_wait_rsp(struct peak_usb_device *dev,
> + struct pcan_usb_pro_msg *pum)
> +{
> + u8 req_data_type, req_channel;
> + int actual_length;
> + int i, err = 0;
> +
> + /* usb device unregistered? */
> + if (!(dev->state & PCAN_USB_STATE_CONNECTED))
> + return 0;
> +
> + req_data_type = pum->u.rec_buffer[4];
> + req_channel = pum->u.rec_buffer[5];
> +
> + *pum->u.rec_cnt = 0;
> + for (i = 0; !err && i < PCAN_USBPRO_RSP_SUBMIT_MAX; i++) {
> + struct pcan_usb_pro_msg rsp;
> + union pcan_usb_pro_rec *pr;
> + u32 r, rec_cnt;
> + int rec_len;
> + u8 *pc;
> +
> + err = usb_bulk_msg(dev->udev,
> + usb_rcvbulkpipe(dev->udev, PCAN_USBPRO_EP_CMDIN),
> + pum->u.rec_buffer, pum->rec_buffer_len,
> + &actual_length, PCAN_USBPRO_COMMAND_TIMEOUT);
> + if (err) {
> + netdev_err(dev->netdev, "waiting rsp error %d\n", err);
> + break;
> + }
> +
> + if (actual_length == 0)
> + continue;
> +
> + if (actual_length < PCAN_USBPRO_MSG_HEADER_LEN) {
> + netdev_err(dev->netdev,
> + "got abnormal too small rsp (len=%d)\n",
> + actual_length);
> + err = -EBADMSG;
> + break;
> + }
> +
> + pc = pcan_usb_pro_msg_init(&rsp, pum->u.rec_buffer,
> + actual_length);
> +
> + rec_cnt = le32_to_cpu(*rsp.u.rec_cnt);
> +
> + /* loop on records stored into message */
> + for (r = 0; r < rec_cnt; r++) {
> + pr = (union pcan_usb_pro_rec *)pc;
> + rec_len = pcan_usb_pro_sizeof_rec(pr->data_type);
> + if (rec_len <= 0) {
> + netdev_err(dev->netdev,
> + "got unprocessed record in msg\n");
> + dump_mem("rcvd rsp msg", pum->u.rec_buffer,
> + actual_length);
> + err = -EBADMSG;
> + break;
> + }
> +
> + /* check if response corresponds to request */
> + if (pr->data_type != req_data_type)
> + netdev_err(dev->netdev,
> + "got unwanted rsp %xh: ignored\n",
> + pr->data_type);
> +
> + /* check if channel in response corresponds too */
> + else if ((req_channel != 0xff) && \
> + (pr->bus_act.channel != req_channel))
> + netdev_err(dev->netdev,
> + "got rsp %xh but on chan%u: ignored\n",
> + req_data_type, pr->bus_act.channel);
err = ?
> +
> + /* got the response */
> + else
> + return 0;
> +
> + /* otherwise, go on with next record in message */
> + pc += rec_len;
> + }
> +
> + }
> +
> + return (i >= PCAN_USBPRO_RSP_SUBMIT_MAX) ? -ERANGE : err;
> +}
> +
> +static int pcan_usb_pro_send_req(struct peak_usb_device *dev, int req_id,
> + int req_value, void *req_addr, int req_size)
> +{
> + int err;
> + u8 req_type;
> + unsigned int p;
> +
> + /* usb device unregistered? */
> + if (!(dev->state & PCAN_USB_STATE_CONNECTED))
> + return 0;
> +
> + memset(req_addr, '\0', req_size);
> +
> + req_type = USB_TYPE_VENDOR | USB_RECIP_OTHER;
> +
> + switch (req_id) {
> + case PCAN_USBPRO_REQ_FCT:
> + p = usb_sndctrlpipe(dev->udev, 0);
> + break;
> +
> + case PCAN_USBPRO_REQ_INFO:
Not needed if it belongs to the default cases.
> + default:
> + p = usb_rcvctrlpipe(dev->udev, 0);
> + req_type |= USB_DIR_IN;
> + break;
> + }
> +
> + err = usb_control_msg(dev->udev, p, req_id, req_type, req_value, 0,
> + req_addr, req_size, 2*USB_CTRL_GET_TIMEOUT);
Spaces around "*".
> + if (err < 0)
> + netdev_info(dev->netdev,
> + "unable to request usb[type=%d value=%d] err=%d\n",
> + req_id, req_value, err);
> + else
> + err = 0;
> +
> + return err;
if (err < 0) {
...
return err;
}
return 0;
look better.
> +}
> +
> +static int pcan_usb_pro_set_ts(struct peak_usb_device *dev, u16 onoff)
> +{
> + struct pcan_usb_pro_msg um;
> + u8 tmp[32];
> +
> + pcan_usb_pro_msg_init_empty(&um, tmp, sizeof(tmp));
> + pcan_usb_pro_add_rec(&um, PCAN_USBPRO_SETTS, onoff);
> +
> + return pcan_usb_pro_send_cmd(dev, &um);
> +}
> +
> +static int pcan_usb_pro_set_bus(struct peak_usb_device *dev, u8 onoff)
> +{
> + struct pcan_usb_pro_msg um;
> + u8 tmp[32];
> +
> + pcan_usb_pro_msg_init_empty(&um, tmp, sizeof(tmp));
> + pcan_usb_pro_add_rec(&um, PCAN_USBPRO_SETBUSACT, dev->ctrl_idx, onoff);
> +
> + return pcan_usb_pro_send_cmd(dev, &um);
> +}
> +
> +static int pcan_usb_pro_set_silent(struct peak_usb_device *dev, u8 onoff)
> +{
> + struct pcan_usb_pro_msg um;
> + u8 tmp[32];
> +
> + pcan_usb_pro_msg_init_empty(&um, tmp, sizeof(tmp));
> + pcan_usb_pro_add_rec(&um, PCAN_USBPRO_SETSILENT, dev->ctrl_idx, onoff);
> +
> + return pcan_usb_pro_send_cmd(dev, &um);
> +}
> +
> +static int pcan_usb_pro_set_filter(struct peak_usb_device *dev, u16 filter_mode)
> +{
> + struct pcan_usb_pro_msg um;
> + u8 tmp[32];
> +
> + pcan_usb_pro_msg_init_empty(&um, tmp, sizeof(tmp));
> + pcan_usb_pro_add_rec(&um, PCAN_USBPRO_SETFILTR, dev->ctrl_idx,
> + filter_mode);
> +
> + return pcan_usb_pro_send_cmd(dev, &um);
> +}
> +
> +static int pcan_usb_pro_set_led(struct peak_usb_device *dev, u8 mode,
> + u32 timeout)
> +{
> + struct pcan_usb_pro_msg um;
> + u8 tmp[32];
> +
> + pcan_usb_pro_msg_init_empty(&um, tmp, sizeof(tmp));
> + pcan_usb_pro_add_rec(&um, PCAN_USBPRO_SETLED, dev->ctrl_idx, mode,
> + timeout);
> +
> + return pcan_usb_pro_send_cmd(dev, &um);
> +}
> +
> +static int pcan_usb_pro_get_device_id(struct peak_usb_device *dev,
> + u32 *device_id)
> +{
> + struct pcan_usb_pro_msg um;
> + struct pcan_usb_pro_devid *pdn;
> + u8 tmp[32], *pc;
> + int err;
> +
> + pc = pcan_usb_pro_msg_init_empty(&um, tmp, sizeof(tmp));
> + pcan_usb_pro_add_rec(&um, PCAN_USBPRO_GETDEVID, dev->ctrl_idx);
> +
> + err = pcan_usb_pro_send_cmd(dev, &um);
> + if (err)
> + return err;
> +
> + err = pcan_usb_pro_wait_rsp(dev, &um);
> + if (err)
> + return err;
> +
> + pdn = (struct pcan_usb_pro_devid *)pc;
> + if (device_id)
> + *device_id = le32_to_cpu(pdn->serial_num);
> +
> + return err;
> +}
> +
> +static int pcan_usb_pro_set_bittiming(struct peak_usb_device *dev,
> + struct can_bittiming *bt)
> +{
> + struct pcan_usb_pro_msg um;
> + u8 tmp[32];
> + u32 ccbt;
> +
> + ccbt = (dev->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 0x00800000 : 0;
> + ccbt |= (bt->sjw - 1) << 24;
> + ccbt |= (bt->phase_seg2 - 1) << 20;
> + ccbt |= (bt->prop_seg + bt->phase_seg1 - 1) << 16; /* = tseg1 */
> + ccbt |= bt->brp - 1;
> +
> + netdev_dbg(dev->netdev, "ccbt=0x%08x\n", ccbt);
Please netdev_info like all other drivers.
> +
> + pcan_usb_pro_msg_init_empty(&um, tmp, sizeof(tmp));
> + pcan_usb_pro_add_rec(&um, PCAN_USBPRO_SETBTR, dev->ctrl_idx, ccbt);
> +
> + return pcan_usb_pro_send_cmd(dev, &um);
> +}
> +
> +static void pcan_usb_pro_drv_loaded(struct peak_usb_device *dev, int loaded)
> +{
> + u8 buffer[16];
> +
> + buffer[0] = 0;
> + buffer[1] = loaded ? 1 : 0;
> +
> + pcan_usb_pro_send_req(dev, PCAN_USBPRO_REQ_FCT,
> + PCAN_USBPRO_FCT_DRIVER_LOADED, buffer, sizeof(buffer));
> +}
> +
> +static inline
> +struct pcan_usb_pro_interface *pcan_usb_pro_dev_if(struct peak_usb_device *dev)
> +{
> + return ((struct pcan_usb_pro_device *)dev)->usb_if;
> +}
> +
> +static int pcan_usb_pro_handle_canmsg(struct pcan_usb_pro_interface *usb_if,
> + struct pcan_usb_pro_rxmsg *rx)
> +{
> + const unsigned int ctrl_idx = (rx->len >> 4) & 0x0f;
> + struct peak_usb_device *dev = usb_if->dev[ctrl_idx];
> + struct net_device *netdev = dev->netdev;
> + struct can_frame *can_frame;
> + struct sk_buff *skb;
> + struct timeval tv;
> +
> + skb = alloc_can_skb(netdev, &can_frame);
> + if (!skb)
> + return -ENOMEM;
> +
> + can_frame->can_id = le32_to_cpu(rx->id);
> + can_frame->can_dlc = rx->len & 0x0f;
> +
> + if (rx->flags & PCAN_USBPRO_RTR)
> + can_frame->can_id |= CAN_RTR_FLAG;
> + if (rx->flags & PCAN_USBPRO_EXT)
> + can_frame->can_id |= CAN_EFF_FLAG;
> +
> + memcpy(can_frame->data, rx->data, can_frame->can_dlc);
In case of RTR, we should not copy data, IIRC.
> + peak_usb_get_ts_tv(&usb_if->time_ref, le32_to_cpu(rx->ts32), &tv);
> + skb->tstamp = timeval_to_ktime(tv);
> +
> + netif_rx(skb);
> + netdev->stats.rx_packets++;
> + netdev->stats.rx_bytes += can_frame->can_dlc;
> +
> + return 0;
> +}
> +
> +static int pcan_usb_pro_handle_error(struct pcan_usb_pro_interface *usb_if,
> + struct pcan_usb_pro_rxstatus *er)
> +{
> + const u32 raw_status = le32_to_cpu(er->status);
> + const unsigned int ctrl_idx = (er->channel >> 4) & 0x0f;
> + struct peak_usb_device *dev = usb_if->dev[ctrl_idx];
> + struct net_device *netdev = dev->netdev;
> + struct can_frame *can_frame;
> + struct sk_buff *skb;
> + struct timeval tv;
> +
> + skb = alloc_can_err_skb(netdev, &can_frame);
> + if (!skb)
> + return -ENOMEM;
> +
> + memset(can_frame, '\0', sizeof(struct can_frame));
Not necessary because already done by alloc_can_err_skb().
> +
> + if (raw_status & FW_USBPRO_STATUS_BUS_S) {
> + can_frame->can_id |= CAN_ERR_BUSOFF;
> + can_bus_off(netdev);
> +
> + } else if (raw_status & FW_USBPRO_STATUS_ERROR_S) {
> + u32 rx_err_cnt = (le32_to_cpu(er->err_frm) & 0x00ff0000) >> 16;
> + u32 tx_err_cnt = (le32_to_cpu(er->err_frm) & 0xff000000) >> 24;
> +
> + if (rx_err_cnt > 127) {
> + can_frame->can_id |= CAN_ERR_CRTL;
> + can_frame->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
> + dev->can.can_stats.error_passive++;
> +
> + } else if (rx_err_cnt > 96) {
> + can_frame->can_id |= CAN_ERR_CRTL;
> + can_frame->data[1] |= CAN_ERR_CRTL_RX_WARNING;
> + dev->can.can_stats.error_warning++;
> + }
> +
> + if (tx_err_cnt > 127) {
> + can_frame->can_id |= CAN_ERR_CRTL;
> + can_frame->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
> + dev->can.can_stats.error_passive++;
> +
> + } else if (tx_err_cnt > 96) {
> + can_frame->can_id |= CAN_ERR_CRTL;
> + can_frame->data[1] |= CAN_ERR_CRTL_TX_WARNING;
> + dev->can.can_stats.error_warning++;
> + }
> + }
> +
> + if (raw_status & FW_USBPRO_STATUS_OVERRUN_S) {
> + can_frame->can_id |= CAN_ERR_PROT;
> + can_frame->data[2] |= CAN_ERR_PROT_OVERLOAD;
> + }
> +
> + if (raw_status & FW_USBPRO_STATUS_QOVERRUN_S) {
> + can_frame->can_id |= CAN_ERR_CRTL;
> + can_frame->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW;
> + }
> +
> + if (can_frame->can_id != CAN_ERR_FLAG) {
> + peak_usb_get_ts_tv(&usb_if->time_ref, le32_to_cpu(er->ts32),
> + &tv);
> + skb->tstamp = timeval_to_ktime(tv);
> + netif_rx(skb);
> + netdev->stats.rx_packets++;
rx_bytes?
> + } else {
> + kfree_skb(skb);
> + }
> +
> + return 0;
> +}
> +
> +static int pcan_usb_pro_handle_ts(struct pcan_usb_pro_interface *usb_if,
> + struct pcan_usb_pro_rxts *ts)
> +{
> + /* should wait until clock is stabilized */
> + if (usb_if->cm_ignore_count > 0)
> + usb_if->cm_ignore_count--;
> + else
> + peak_usb_set_ts_now(&usb_if->time_ref,
> + le32_to_cpu(ts->ts64[1]));
> +
> + return 0;
> +}
> +
> +/*
> + * callback for bulk IN urb
> + */
> +static int pcan_usb_pro_decode_buf(struct peak_usb_device *dev, struct urb *urb)
> +{
> + struct pcan_usb_pro_interface *usb_if = pcan_usb_pro_dev_if(dev);
> + struct net_device *netdev = dev->netdev;
> + struct pcan_usb_pro_msg usb_msg;
> + u8 *rec_ptr, *msg_end;
> + u16 rec_cnt;
> + int err = 0;
> +
> + rec_ptr = pcan_usb_pro_msg_init(&usb_msg, urb->transfer_buffer,
> + urb->actual_length);
> + if (!rec_ptr) {
> + netdev_err(netdev, "bad msg hdr len %d\n", urb->actual_length);
> + return -EINVAL;
> + }
> +
> + /* loop reading all the records from the incoming message */
> + msg_end = urb->transfer_buffer + urb->actual_length;
> + rec_cnt = le16_to_cpu(*usb_msg.u.rec_cnt_rd);
> + for (; rec_cnt > 0; rec_cnt--) {
> + union pcan_usb_pro_rec *pr = (union pcan_usb_pro_rec *)rec_ptr;
> + int sizeof_rec = pcan_usb_pro_sizeof_rec(pr->data_type);
> +
> + if (sizeof_rec <= 0) {
> + netdev_err(netdev,
> + "got unsupported rec in usb msg:\n");
> + err = -ENOTSUPP;
> + break;
> + }
> +
> + /* check if the record goes out of current packet */
> + if (rec_ptr + sizeof_rec > msg_end) {
> + netdev_err(netdev,
> + "got frag rec: should inc usb rx buf size\n");
> + err = -EBADMSG;
> + break;
> + }
> +
> + switch (pr->data_type) {
> + case PCAN_USBPRO_RXMSG8:
> + case PCAN_USBPRO_RXMSG4:
> + case PCAN_USBPRO_RXMSG0:
> + case PCAN_USBPRO_RXRTR:
> + err = pcan_usb_pro_handle_canmsg(usb_if, &pr->rx_msg);
> + if (err < 0)
> + goto fail;
> + break;
> +
> + case PCAN_USBPRO_RXSTATUS:
> + err = pcan_usb_pro_handle_error(usb_if, &pr->rx_status);
> + if (err < 0)
> + goto fail;
> + break;
> +
> + case PCAN_USBPRO_RXTS:
> + err = pcan_usb_pro_handle_ts(usb_if, &pr->rx_ts);
> + break;
> +
> + default:
> + netdev_err(netdev,
> + "unhandled rec type 0x%02x (%d): ignored\n",
> + pr->data_type, pr->data_type);
> + break;
> + }
> +
> + rec_ptr += sizeof_rec;
> + }
> +
> +fail:
> + if (err)
> + dump_mem("received msg",
> + urb->transfer_buffer, urb->actual_length);
> +
> + return err;
> +}
> +
> +static int pcan_usb_pro_encode_msg(struct peak_usb_device *dev,
> + struct sk_buff *skb, u8 *obuf, size_t *size)
> +{
> + struct can_frame *cf = (struct can_frame *)skb->data;
> + u8 data_type, len, flags;
> + struct pcan_usb_pro_msg usb_msg;
> + int err = 0;
> +
> + pcan_usb_pro_msg_init_empty(&usb_msg, obuf, *size);
> +
> + if ((cf->can_id & CAN_RTR_FLAG) || (cf->can_dlc == 0))
> + data_type = PCAN_USBPRO_TXMSG0;
> +
> + else if (cf->can_dlc <= 4)
> + data_type = PCAN_USBPRO_TXMSG4;
> + else
> + data_type = PCAN_USBPRO_TXMSG8;
> +
> + len = (dev->ctrl_idx << 4) | (cf->can_dlc & 0x0f);
> +
> + flags = 0;
> + if (cf->can_id & CAN_EFF_FLAG)
> + flags |= 0x02;
> + if (cf->can_id & CAN_RTR_FLAG)
> + flags |= 0x01;
> +
> + err = pcan_usb_pro_add_rec(&usb_msg, data_type, 0, flags, len,
> + cf->can_id, cf->data);
> +
> + *size = usb_msg.rec_buffer_len;
> +
> + return 0;
> +}
> +
> +static int pcan_usb_pro_start(struct peak_usb_device *dev)
> +{
> + struct pcan_usb_pro_device *pdev = (struct pcan_usb_pro_device *)dev;
> + int err;
> +
> + err = pcan_usb_pro_set_silent(dev,
> + (dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY));
"()" not needed.
> + if (err)
> + goto start_failed;
> +
> + /* Set filter mode: 0-> All OFF; 1->bypass */
> + err = pcan_usb_pro_set_filter(dev, 1);
> + if (err)
> + goto start_failed;
> +
> + /* opening first device: */
> + if (pdev->usb_if->dev_opened_count == 0) {
> + /* reset time_ref */
> + peak_usb_init_time_ref(&pdev->usb_if->time_ref, &pcan_usb_pro);
> +
> + /* ask device to send ts messages */
> + err = pcan_usb_pro_set_ts(dev, 1);
> + }
> +
> + pdev->usb_if->dev_opened_count++;
> +
> +start_failed:
> + return err;
Useless label!
> +}
> +
> +/*
> + * Stop interface
> + * (last chance before set bus off)
> + */
> +static int pcan_usb_pro_stop(struct peak_usb_device *dev)
> +{
> + struct pcan_usb_pro_device *pdev = (struct pcan_usb_pro_device *)dev;
Hm, this cast worries me. What about using container_of?
> + /* turn off ts msgs for that interface if no other dev opened */
> + if (pdev->usb_if->dev_opened_count == 1)
> + pcan_usb_pro_set_ts(dev, 0);
> +
> + pdev->usb_if->dev_opened_count--;
> +
> + return 0;
> +}
> +
> +/*
> + * called when probing to initialize a device object.
> + */
> +static int pcan_usb_pro_init(struct peak_usb_device *dev)
> +{
> + struct pcan_usb_pro_interface *usb_if;
> + struct pcan_usb_pro_device *pdev = (struct pcan_usb_pro_device *)dev;
> +
> + /* do this for 1st channel only */
> + if (!dev->prev_siblings) {
> + struct pcan_usb_pro_fwinfo fi;
> + struct pcan_usb_pro_blinfo bi;
> +
> + /* tell the device the can driver is running */
> + pcan_usb_pro_drv_loaded(dev, 1);
> +
> + if (pcan_usb_pro_send_req(dev, PCAN_USBPRO_REQ_INFO,
> + PCAN_USBPRO_INFO_FIRMWARE, &fi, sizeof(fi)) >= 0)
> + netdev_info(dev->netdev,
> + "%s fw v%d.%d.%d (%02d/%02d/%02d) fw 0x%08x\n",
> + pcan_usb_pro.name,
> + fi.version[0], fi.version[1], fi.version[2],
> + fi.day, fi.month, fi.year, fi.fw_type);
> +
> + if (pcan_usb_pro_send_req(dev, PCAN_USBPRO_REQ_INFO,
> + PCAN_USBPRO_INFO_BOOTLOADER, &bi, sizeof(bi)) >= 0) {
> + netdev_info(dev->netdev,
> + "bootloader v%d.%d.%d (%02d/%02d/%02d)\n",
> + bi.version[0], bi.version[1], bi.version[2],
> + bi.day, bi.month, bi.year);
> +
> + netdev_info(dev->netdev,
> + "serial %08X.%08X hw 0x%08x rev 0x%08x\n",
> + bi.serial_num_hi, bi.serial_num_lo,
> + bi.hw_type, bi.hw_rev);
> +
> + dev->device_rev = (u8)bi.hw_rev;
> + }
> +
> + usb_if = kzalloc(sizeof(struct pcan_usb_pro_interface),
> + GFP_KERNEL);
> + if (!usb_if)
> + return -ENOMEM;
> +
> + /* number of ts msgs to ignore before taking one into account */
> + usb_if->cm_ignore_count = 5;
> +
> + } else {
> + usb_if = pcan_usb_pro_dev_if(dev->prev_siblings);
> + }
> +
> + pdev->usb_if = usb_if;
> + usb_if->dev[dev->ctrl_idx] = dev;
> +
> + /* set LED in default state (end of init phase) */
> + pcan_usb_pro_set_led(dev, 0, 1);
> +
> + return 0;
> +}
> +
> +static void pcan_usb_pro_exit(struct peak_usb_device *dev)
> +{
> + struct pcan_usb_pro_device *pdev = (struct pcan_usb_pro_device *)dev;
> +
> + /*
> + * when rmmod called before unplug and if down, should reset things
> + * before leaving
> + */
> + if (dev->can.state != CAN_STATE_STOPPED)
> +
remove empty line.
> + /* set bus off on the corresponding channel */
> + pcan_usb_pro_set_bus(dev, 0);
> +
> + /* if channel #0 (only) */
> + if (dev->ctrl_idx == 0) {
> + /* turn off calibration message if any device were opened */
> + if (pdev->usb_if->dev_opened_count > 0)
> + pcan_usb_pro_set_ts(dev, 0);
> +
> + /* tell the PCAN-USB Pro device driver is being unloaded */
> + pcan_usb_pro_drv_loaded(dev, 0);
> + }
> +}
> +
> +/*
> + * called when PCAN-USB Pro adapter is unplugged
> + */
> +static void pcan_usb_pro_free(struct peak_usb_device *dev)
> +{
> + /* last device: can free pcan_usb_pro_interface object now */
> + if (!dev->prev_siblings && !dev->next_siblings)
> + kfree(pcan_usb_pro_dev_if(dev));
> +}
> +
> +/*
> + * probe function for new PCAN-USB Pro usb interface
> + */
> +static int pcan_usb_pro_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. All other ep address
> + * is considered as not-CAN interface address => no dev created
> + */
> + switch (ep->bEndpointAddress) {
> + case PCAN_USBPRO_EP_CMDOUT:
> + case PCAN_USBPRO_EP_CMDIN:
> + case PCAN_USBPRO_EP_MSGOUT_0:
> + case PCAN_USBPRO_EP_MSGOUT_1:
> + case PCAN_USBPRO_EP_MSGIN:
> + /* CAN usb interface unused ep */
> + case 0x83:
> + break;
> + default:
> + return -ENODEV;
> + }
> + }
> +
> + return 0;
> +}
> +
> +/*
> + * describe the PCAN-USB Pro adapter
> + */
> +struct peak_usb_adapter pcan_usb_pro = {
> + .name = "PCAN-USB Pro",
> + .device_id = PCAN_USBPRO_PRODUCT_ID,
> + .ctrl_count = PCAN_USBPRO_CHANNEL_COUNT,
> + .clock = {
> + .freq = PCAN_USBPRO_CRYSTAL_HZ,
> + },
> + .bittiming_const = {
> + .name = "pcan_usb_pro",
> + .tseg1_min = 1,
> + .tseg1_max = 16,
> + .tseg2_min = 1,
> + .tseg2_max = 8,
> + .sjw_max = 4,
> + .brp_min = 1,
> + .brp_max = 1024,
> + .brp_inc = 1,
> + },
> +
> + /* size of device private data */
> + .sizeof_dev_private = sizeof(struct pcan_usb_pro_device),
> +
> + /* timestamps usage */
> + .ts_used_bits = 32,
> + .ts_period = 1000000, /* calibration period in ts. */
> + .us_per_ts_scale = 1, /* us = (ts * scale) >> shift */
> + .us_per_ts_shift = 0,
> +
> + /* give here commands/messages in/out endpoints */
> + .ep_msg_in = PCAN_USBPRO_EP_MSGIN,
> + .ep_msg_out = {PCAN_USBPRO_EP_MSGOUT_0, PCAN_USBPRO_EP_MSGOUT_1},
> + /* size of rx/tx usb buffers */
> + .rx_buffer_size = PCAN_USBPRO_RX_BUFFER_SIZE,
> + .tx_buffer_size = PCAN_USBPRO_TX_BUFFER_SIZE,
> +
> + /* device callbacks */
> + .intf_probe = pcan_usb_pro_probe,
> + .dev_init = pcan_usb_pro_init,
> + .dev_exit = pcan_usb_pro_exit,
> + .dev_free = pcan_usb_pro_free,
> + .dev_set_bus = pcan_usb_pro_set_bus,
> + .dev_set_bittiming = pcan_usb_pro_set_bittiming,
> + .dev_get_device_id = pcan_usb_pro_get_device_id,
> + .dev_decode_buf = pcan_usb_pro_decode_buf,
> + .dev_encode_msg = pcan_usb_pro_encode_msg,
> + .dev_start = pcan_usb_pro_start,
> + .dev_stop = pcan_usb_pro_stop,
> +};
> diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.h b/drivers/net/can/usb/peak_usb/pcan_usb_pro.h
> new file mode 100644
> index 0000000..66952cb
> --- /dev/null
> +++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.h
> @@ -0,0 +1,352 @@
> +/*
> + * CAN driver for PEAK System PCAN-USB Pro adapter
> + *
> + * Copyright (C) 2011-2012 PEAK-System GmbH
> + *
> + * 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.
> + */
> +#ifndef __pcan_usb_pro_h__
> +#define __pcan_usb_pro_h__
> +
> +/*
> + * USB Vendor request data types
> + */
> +
> +#define PCAN_USBPRO_REQ_INFO 0
> +#define PCAN_USBPRO_REQ_FCT 2
> +
> +/* Vendor Request wValue for XXX_INFO */
Please correct message?
> +#define PCAN_USBPRO_INFO_BOOTLOADER 0
> +#define PCAN_USBPRO_INFO_FIRMWARE 1
> +
> +/* Vendor Request wValue for XXX_FCT */
> +#define PCAN_USBPRO_FCT_DRIVER_LOADED 5
Ditto.
> +
> +/* PCAN_USBPRO_INFO_BOOTLOADER vendor request record type */
> +struct __packed pcan_usb_pro_blinfo {
> + u32 ctrl_type;
> + u8 version[4];
> + u8 day;
> + u8 month;
> + u8 year;
> + u8 dummy;
> + u32 serial_num_hi;
> + u32 serial_num_lo;
> + u32 hw_type;
> + u32 hw_rev;
> +};
> +
> +/* PCAN_USBPRO_INFO_FIRMWARE vendor request record type */
> +struct __packed pcan_usb_pro_fwinfo {
> + u32 ctrl_type;
> + u8 version[4];
> + u8 day;
> + u8 month;
> + u8 year;
> + u8 dummy;
> + u32 fw_type;
> +};
> +
> +/*
> + * USB Command record types
> + */
> +#define PCAN_USBPRO_RXMSG8 0x80
> +#define PCAN_USBPRO_RXMSG4 0x81
> +#define PCAN_USBPRO_RXMSG0 0x82
> +#define PCAN_USBPRO_RXRTR 0x83
> +#define PCAN_USBPRO_RXSTATUS 0x84
> +#define PCAN_USBPRO_RXTS 0x85
> +#define PCAN_USBPRO_RXBUSLAST 0x86
> +#define PCAN_USBPRO_TXMSG8 0x41
> +#define PCAN_USBPRO_TXMSG4 0x42
> +#define PCAN_USBPRO_TXMSG0 0x43
> +#define PCAN_USBPRO_GETBTR 0x01
> +#define PCAN_USBPRO_SETBTR 0x02
> +#define PCAN_USBPRO_GETBUSACT 0x03
> +#define PCAN_USBPRO_SETBUSACT 0x04
> +#define PCAN_USBPRO_SETSILENT 0x05
> +#define PCAN_USBPRO_SETDEVID 0x06
> +#define PCAN_USBPRO_SETWARNLIM 0x07
> +#define PCAN_USBPRO_SETLKUP 0x08
> +#define PCAN_USBPRO_SETLKUPGRP 0x09
> +#define PCAN_USBPRO_SETFILTR 0x0a
> +#define PCAN_USBPRO_SETRST 0x0b
> +#define PCAN_USBPRO_SETERRFRM 0x0c
> +#define PCAN_USBPRO_GETBUSSTAT 0x0D
> +#define PCAN_USBPRO_SETREG 0x0e
> +#define PCAN_USBPRO_GETREG 0x0f
> +#define PCAN_USBPRO_SETTS 0x10
> +#define PCAN_USBPRO_SETBUSLAST 0x11
> +#define PCAN_USBPRO_GETDEVID 0x12
> +#define PCAN_USBPRO_SETSTR 0x13
> +#define PCAN_USBPRO_GETSTR 0x14
> +#define PCAN_USBPRO_STRING 0x15
> +#define PCAN_USBPRO_SAVE 0x16
> +#define PCAN_USBPRO_PDELAY 0x17
> +#define PCAN_USBPRO_TSARG 0x18
> +#define PCAN_USBPRO_ERRID 0x19
> +#define PCAN_USBPRO_ERRNOW 0x1A
> +#define PCAN_USBPRO_SETSFILER 0x1B
> +#define PCAN_USBPRO_SETLED 0x1C
> +
> +/* record structures */
> +struct __packed pcan_usb_pro_rxmsg {
> + u8 data_type;
> + u8 client;
> + u8 flags;
> + u8 len;
> + u32 ts32;
> + u32 id;
> +
> + u8 data[8];
> +};
> +
> +#define FW_USBPRO_STATUS_ERROR_S 0x0001
> +#define FW_USBPRO_STATUS_BUS_S 0x0002
Check tabs!
> +#define FW_USBPRO_STATUS_OVERRUN_S 0x0004
> +#define FW_USBPRO_STATUS_QOVERRUN_S 0x0008
> +
> +struct __packed pcan_usb_pro_rxstatus {
> + u8 data_type;
> + u8 channel;
> + u16 status;
> + u32 ts32;
> + u32 err_frm;
> +};
> +
> +struct __packed pcan_usb_pro_rxts {
> + u8 data_type;
> + u8 dummy[3];
> + u32 ts64[2];
> +};
> +
> +struct __packed pcan_usb_pro_buslast {
> + u8 data_type;
> + u8 channel;
> + u16 buslast_val;
> + u32 ts32;
> +};
> +
> +struct __packed pcan_usb_pro_txmsg {
> + u8 data_type;
> + u8 client;
> + u8 flags;
> + u8 len;
> + u32 id;
> + u8 data[8];
> +};
> +
> +struct __packed pcan_usb_pro_btr {
> + u8 data_type;
> + u8 channel;
> + u16 dummy;
> + u32 CCBT;
> +};
> +
> +struct __packed pcan_usb_pro_busact {
> + u8 data_type;
> + u8 channel;
> + u16 onoff;
> +};
> +
> +struct __packed pcan_usb_pro_silent {
> + u8 data_type;
> + u8 channel;
> + u16 onoff;
> +};
> +
> +struct __packed pcan_usb_pro_devid {
> + u8 data_type;
> + u8 channel;
> + u16 dummy;
> + u32 serial_num;
> +};
> +
> +struct __packed pcan_usb_pro_warnlim {
> + u8 data_type;
> + u8 channel;
> + u16 warning_limit;
> +};
> +
> +struct __packed pcan_usb_pro_lkup {
> + u8 data_type;
> + u8 channel;
> + u16 id_type;
> + u32 id;
> +};
> +
> +struct __packed pcan_usb_pro_lkupgrp {
> + u8 data_type;
> + u8 channel;
> + u16 id_type;
> + u32 id_start;
> + u32 id_end;
> +};
> +
> +struct __packed pcan_usb_pro_filter {
> + u8 data_type;
> + u8 dummy;
> + u16 filter_mode;
> +};
> +
> +struct __packed pcan_usb_pro_reset {
> + u8 data_type;
> + u8 channel;
> + u16 reset;
> +};
> +
> +struct __packed pcan_usb_pro_errfrm {
> + u8 data_type;
> + u8 channel;
> + u16 mode;
> +};
> +
> +struct __packed pcan_usb_pro_busstat {
> + u8 data_type;
> + u8 channel;
> + u16 status;
> +};
> +
> +struct __packed pcan_usb_pro_setreg {
> + u8 data_type;
> + u8 irq_off;
> + u16 dummy;
> + u32 address;
> + u32 value;
> + u32 mask;
> +};
> +
> +struct __packed pcan_usb_pro_getreg {
> + u8 data_type;
> + u8 irq_off;
> + u16 dummy;
> + u32 address;
> + u32 value;
> +};
> +
> +struct __packed pcan_usb_pro_setts {
> + u8 data_type;
> + u8 dummy;
> + u16 mode;
> +};
> +
> +struct __packed pcan_usb_pro_setbl {
> + u8 data_type;
> + u8 channel;
> + u8 dummy;
> + u8 mode;
> + u16 prescaler;
> + u16 sampletimequanta;
> +};
> +
> +struct __packed pcan_usb_pro_setstr {
> + u8 data_type;
> + u8 channel;
> + u8 offset;
> + u8 len;
> + u8 data[60];
> +};
> +
> +struct __packed pcan_usb_pro_getstr {
> + u8 data_type;
> + u8 channel;
> + u16 dummy;
> +};
> +
> +struct __packed pcan_usb_pro_str {
> + u8 data_type;
> + u8 channel;
> + u16 dummy;
> + u8 data[250];
> +};
> +
> +struct __packed pcan_usb_pro_save {
> + u8 data_type;
> + u8 channel;
> + u16 dummy;
> +};
> +
> +struct __packed pcan_usb_pro_pdelay {
> + u8 data_type;
> + u8 dummy;
> + u16 delay;
> +};
> +
> +struct __packed pcan_usb_pro_tsarg {
> + u8 data_type;
> + u8 channel;
> + u16 start_or_end;
> +};
> +
> +struct __packed pcan_usb_pro_errid {
> + u8 data_type;
> + u8 channel;
> + u16 bit_pos;
> + u32 id;
> + u16 ok_counter;
> + u16 error_counter;
> +};
> +
> +struct __packed pcan_usb_pro_errnow {
> + u8 data_type;
> + u8 channel;
> + u16 bit_pos;
> +};
> +
> +struct __packed pcan_usb_pro_sfiller {
> + u8 data_type;
> + u8 channel;
> + u16 dummy;
> + u32 accmask;
> + u32 acccode;
> +};
> +
> +struct __packed pcan_usb_pro_setled {
> + u8 data_type;
> + u8 channel;
> + u16 mode;
> + u32 timeout;
> +};
> +
> +union pcan_usb_pro_rec {
> + u8 data_type;
> + struct pcan_usb_pro_rxmsg rx_msg;
> + struct pcan_usb_pro_rxstatus rx_status;
> + struct pcan_usb_pro_rxts rx_ts;
> + struct pcan_usb_pro_buslast rx_buslast;
> + struct pcan_usb_pro_txmsg tx_msg;
> + struct pcan_usb_pro_btr btr;
Tabs?
> + struct pcan_usb_pro_busact bus_act;
> + struct pcan_usb_pro_silent silent_mode;
> + struct pcan_usb_pro_devid dev_id;
> + struct pcan_usb_pro_warnlim warn_lim;
> + struct pcan_usb_pro_lkup lkup_expl;
> + struct pcan_usb_pro_lkupgrp lkup_group;
> + struct pcan_usb_pro_filter filter_mode;
> + struct pcan_usb_pro_reset rst_mode;
> + struct pcan_usb_pro_errfrm err_frame;
> + struct pcan_usb_pro_busstat bus_status;
> + struct pcan_usb_pro_setreg set_reg;
> + struct pcan_usb_pro_getreg get_reg;
> + struct pcan_usb_pro_setts ts;
> + struct pcan_usb_pro_setbl bus_last;
> + struct pcan_usb_pro_setstr set_str;
> + struct pcan_usb_pro_getstr get_str;
> + struct pcan_usb_pro_str str;
Tabs?
> + struct pcan_usb_pro_save save_eeprom;
> + struct pcan_usb_pro_pdelay p_delay;
> + struct pcan_usb_pro_tsarg ts_arg;
> + struct pcan_usb_pro_errid err_id;
> + struct pcan_usb_pro_errnow err_now;
> + struct pcan_usb_pro_sfiller soft_filler;
> + struct pcan_usb_pro_setled set_can_led;
> +};
> +
> +#endif
Wolfgang.
prev parent reply other threads:[~2012-01-10 11:21 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-12-22 13:14 [PATCH] Add support for PEAK System PCAN-USB Pro adapter Stephane Grosjean
2011-12-23 19:57 ` Sebastian Haas
2011-12-26 10:55 ` Grosjean Stephane
2012-01-10 11:21 ` Wolfgang Grandegger [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4F0C1F25.3000304@grandegger.com \
--to=wg@grandegger.com \
--cc=linux-can@vger.kernel.org \
--cc=s.grosjean@peak-system.com \
--cc=socketcan@hartkopp.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.