linux-can.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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.

      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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).