net: can: kvaser_usb: fix reception on "USBcan Pro" and "USBcan R" type hardware.

Unlike Kvaser Leaf light devices, some other Kvaser devices (like USBcan
Pro, USBcan R) receive CAN messages in CMD_LOG_MESSAGE frames. This
patch adds support for it.

Cc: linux-stable <stable@vger.kernel.org> # >= v3.8
Signed-off-by: Jonas Peterson <jonas.peterson@gmail.com>
Signed-off-by: Olivier Sobrie <olivier@sobrie.be>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
This commit is contained in:
Jonas Peterson 2013-05-07 22:05:23 +02:00 коммит произвёл Marc Kleine-Budde
Родитель 01cb71d2d4
Коммит a90f13b24f
1 изменённых файлов: 43 добавлений и 21 удалений

Просмотреть файл

@ -136,6 +136,9 @@
#define KVASER_CTRL_MODE_SELFRECEPTION 3 #define KVASER_CTRL_MODE_SELFRECEPTION 3
#define KVASER_CTRL_MODE_OFF 4 #define KVASER_CTRL_MODE_OFF 4
/* log message */
#define KVASER_EXTENDED_FRAME BIT(31)
struct kvaser_msg_simple { struct kvaser_msg_simple {
u8 tid; u8 tid;
u8 channel; u8 channel;
@ -817,7 +820,12 @@ static void kvaser_usb_rx_can_msg(const struct kvaser_usb *dev,
priv = dev->nets[channel]; priv = dev->nets[channel];
stats = &priv->netdev->stats; stats = &priv->netdev->stats;
if (msg->u.rx_can.flag & (MSG_FLAG_ERROR_FRAME | MSG_FLAG_NERR | if ((msg->u.rx_can.flag & MSG_FLAG_ERROR_FRAME) &&
(msg->id == CMD_LOG_MESSAGE)) {
kvaser_usb_rx_error(dev, msg);
return;
} else if (msg->u.rx_can.flag & (MSG_FLAG_ERROR_FRAME |
MSG_FLAG_NERR |
MSG_FLAG_OVERRUN)) { MSG_FLAG_OVERRUN)) {
kvaser_usb_rx_can_err(priv, msg); kvaser_usb_rx_can_err(priv, msg);
return; return;
@ -834,9 +842,23 @@ static void kvaser_usb_rx_can_msg(const struct kvaser_usb *dev,
return; return;
} }
if (msg->id == CMD_LOG_MESSAGE) {
cf->can_id = le32_to_cpu(msg->u.log_message.id);
if (cf->can_id & KVASER_EXTENDED_FRAME)
cf->can_id &= CAN_EFF_MASK | CAN_EFF_FLAG;
else
cf->can_id &= CAN_SFF_MASK;
cf->can_dlc = get_can_dlc(msg->u.log_message.dlc);
if (msg->u.log_message.flags & MSG_FLAG_REMOTE_FRAME)
cf->can_id |= CAN_RTR_FLAG;
else
memcpy(cf->data, &msg->u.log_message.data,
cf->can_dlc);
} else {
cf->can_id = ((msg->u.rx_can.msg[0] & 0x1f) << 6) | cf->can_id = ((msg->u.rx_can.msg[0] & 0x1f) << 6) |
(msg->u.rx_can.msg[1] & 0x3f); (msg->u.rx_can.msg[1] & 0x3f);
cf->can_dlc = get_can_dlc(msg->u.rx_can.msg[5]);
if (msg->id == CMD_RX_EXT_MESSAGE) { if (msg->id == CMD_RX_EXT_MESSAGE) {
cf->can_id <<= 18; cf->can_id <<= 18;
@ -846,10 +868,14 @@ static void kvaser_usb_rx_can_msg(const struct kvaser_usb *dev,
cf->can_id |= CAN_EFF_FLAG; cf->can_id |= CAN_EFF_FLAG;
} }
cf->can_dlc = get_can_dlc(msg->u.rx_can.msg[5]);
if (msg->u.rx_can.flag & MSG_FLAG_REMOTE_FRAME) if (msg->u.rx_can.flag & MSG_FLAG_REMOTE_FRAME)
cf->can_id |= CAN_RTR_FLAG; cf->can_id |= CAN_RTR_FLAG;
else else
memcpy(cf->data, &msg->u.rx_can.msg[6], cf->can_dlc); memcpy(cf->data, &msg->u.rx_can.msg[6],
cf->can_dlc);
}
netif_rx(skb); netif_rx(skb);
@ -911,6 +937,7 @@ static void kvaser_usb_handle_message(const struct kvaser_usb *dev,
case CMD_RX_STD_MESSAGE: case CMD_RX_STD_MESSAGE:
case CMD_RX_EXT_MESSAGE: case CMD_RX_EXT_MESSAGE:
case CMD_LOG_MESSAGE:
kvaser_usb_rx_can_msg(dev, msg); kvaser_usb_rx_can_msg(dev, msg);
break; break;
@ -919,11 +946,6 @@ static void kvaser_usb_handle_message(const struct kvaser_usb *dev,
kvaser_usb_rx_error(dev, msg); kvaser_usb_rx_error(dev, msg);
break; break;
case CMD_LOG_MESSAGE:
if (msg->u.log_message.flags & MSG_FLAG_ERROR_FRAME)
kvaser_usb_rx_error(dev, msg);
break;
case CMD_TX_ACKNOWLEDGE: case CMD_TX_ACKNOWLEDGE:
kvaser_usb_tx_acknowledge(dev, msg); kvaser_usb_tx_acknowledge(dev, msg);
break; break;