can: peak_usb: fix a potential out-of-sync while decoding packets
When decoding a buffer received from PCAN-USB, the first timestamp read in a packet is a 16-bit coded time base, and the next ones are an 8-bit offset to this base, regardless of the type of packet read. This patch corrects a potential loss of synchronization by using a timestamp index read from the buffer, rather than an index of received data packets, to determine on the sizeof the timestamp to be read from the packet being decoded. Signed-off-by: Stephane Grosjean <s.grosjean@peak-system.com> Fixes: 46be265d3388 ("can: usb: PEAK-System Technik PCAN-USB specific part") Cc: linux-stable <stable@vger.kernel.org> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
This commit is contained in:
committed by
Marc Kleine-Budde
parent
5e269324db
commit
de280f403f
@ -100,7 +100,7 @@ struct pcan_usb_msg_context {
|
|||||||
u8 *end;
|
u8 *end;
|
||||||
u8 rec_cnt;
|
u8 rec_cnt;
|
||||||
u8 rec_idx;
|
u8 rec_idx;
|
||||||
u8 rec_data_idx;
|
u8 rec_ts_idx;
|
||||||
struct net_device *netdev;
|
struct net_device *netdev;
|
||||||
struct pcan_usb *pdev;
|
struct pcan_usb *pdev;
|
||||||
};
|
};
|
||||||
@ -547,10 +547,15 @@ static int pcan_usb_decode_status(struct pcan_usb_msg_context *mc,
|
|||||||
mc->ptr += PCAN_USB_CMD_ARGS;
|
mc->ptr += PCAN_USB_CMD_ARGS;
|
||||||
|
|
||||||
if (status_len & PCAN_USB_STATUSLEN_TIMESTAMP) {
|
if (status_len & PCAN_USB_STATUSLEN_TIMESTAMP) {
|
||||||
int err = pcan_usb_decode_ts(mc, !mc->rec_idx);
|
int err = pcan_usb_decode_ts(mc, !mc->rec_ts_idx);
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
/* Next packet in the buffer will have a timestamp on a single
|
||||||
|
* byte
|
||||||
|
*/
|
||||||
|
mc->rec_ts_idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (f) {
|
switch (f) {
|
||||||
@ -632,10 +637,13 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len)
|
|||||||
|
|
||||||
cf->can_dlc = get_can_dlc(rec_len);
|
cf->can_dlc = get_can_dlc(rec_len);
|
||||||
|
|
||||||
/* first data packet timestamp is a word */
|
/* Only first packet timestamp is a word */
|
||||||
if (pcan_usb_decode_ts(mc, !mc->rec_data_idx))
|
if (pcan_usb_decode_ts(mc, !mc->rec_ts_idx))
|
||||||
goto decode_failed;
|
goto decode_failed;
|
||||||
|
|
||||||
|
/* Next packet in the buffer will have a timestamp on a single byte */
|
||||||
|
mc->rec_ts_idx++;
|
||||||
|
|
||||||
/* read data */
|
/* read data */
|
||||||
memset(cf->data, 0x0, sizeof(cf->data));
|
memset(cf->data, 0x0, sizeof(cf->data));
|
||||||
if (status_len & PCAN_USB_STATUSLEN_RTR) {
|
if (status_len & PCAN_USB_STATUSLEN_RTR) {
|
||||||
@ -688,7 +696,6 @@ static int pcan_usb_decode_msg(struct peak_usb_device *dev, u8 *ibuf, u32 lbuf)
|
|||||||
/* handle normal can frames here */
|
/* handle normal can frames here */
|
||||||
} else {
|
} else {
|
||||||
err = pcan_usb_decode_data(&mc, sl);
|
err = pcan_usb_decode_data(&mc, sl);
|
||||||
mc.rec_data_idx++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user