Commit 23eb45fc authored by David S. Miller's avatar David S. Miller

Merge branch 'fixes-for-3.10' of git://gitorious.org/linux-can/linux-can

Marc Kleine-Budde says:

====================
here are there fixes for the v3.10 release cycle:

The first patch by Jonas Peterson and Olivier Sobrie fixes the reception of CAN
frames on Kvaser's "USBcan Pro" and "USBcan R" type hardware.

The last two patches by Olivier Sobrie (for esd_usb2) and me (for peak_usb)
change the memory handling for the USB messages from stack to kmalloc(), as
memory used for DMA should not be allocated on stack.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c418253f f14e2243
...@@ -612,9 +612,15 @@ static int esd_usb2_start(struct esd_usb2_net_priv *priv) ...@@ -612,9 +612,15 @@ static int esd_usb2_start(struct esd_usb2_net_priv *priv)
{ {
struct esd_usb2 *dev = priv->usb2; struct esd_usb2 *dev = priv->usb2;
struct net_device *netdev = priv->netdev; struct net_device *netdev = priv->netdev;
struct esd_usb2_msg msg; struct esd_usb2_msg *msg;
int err, i; int err, i;
msg = kmalloc(sizeof(*msg), GFP_KERNEL);
if (!msg) {
err = -ENOMEM;
goto out;
}
/* /*
* Enable all IDs * Enable all IDs
* The IDADD message takes up to 64 32 bit bitmasks (2048 bits). * The IDADD message takes up to 64 32 bit bitmasks (2048 bits).
...@@ -628,33 +634,32 @@ static int esd_usb2_start(struct esd_usb2_net_priv *priv) ...@@ -628,33 +634,32 @@ static int esd_usb2_start(struct esd_usb2_net_priv *priv)
* the number of the starting bitmask (0..64) to the filter.option * the number of the starting bitmask (0..64) to the filter.option
* field followed by only some bitmasks. * field followed by only some bitmasks.
*/ */
msg.msg.hdr.cmd = CMD_IDADD; msg->msg.hdr.cmd = CMD_IDADD;
msg.msg.hdr.len = 2 + ESD_MAX_ID_SEGMENT; msg->msg.hdr.len = 2 + ESD_MAX_ID_SEGMENT;
msg.msg.filter.net = priv->index; msg->msg.filter.net = priv->index;
msg.msg.filter.option = ESD_ID_ENABLE; /* start with segment 0 */ msg->msg.filter.option = ESD_ID_ENABLE; /* start with segment 0 */
for (i = 0; i < ESD_MAX_ID_SEGMENT; i++) for (i = 0; i < ESD_MAX_ID_SEGMENT; i++)
msg.msg.filter.mask[i] = cpu_to_le32(0xffffffff); msg->msg.filter.mask[i] = cpu_to_le32(0xffffffff);
/* enable 29bit extended IDs */ /* enable 29bit extended IDs */
msg.msg.filter.mask[ESD_MAX_ID_SEGMENT] = cpu_to_le32(0x00000001); msg->msg.filter.mask[ESD_MAX_ID_SEGMENT] = cpu_to_le32(0x00000001);
err = esd_usb2_send_msg(dev, &msg); err = esd_usb2_send_msg(dev, msg);
if (err) if (err)
goto failed; goto out;
err = esd_usb2_setup_rx_urbs(dev); err = esd_usb2_setup_rx_urbs(dev);
if (err) if (err)
goto failed; goto out;
priv->can.state = CAN_STATE_ERROR_ACTIVE; priv->can.state = CAN_STATE_ERROR_ACTIVE;
return 0; out:
failed:
if (err == -ENODEV) if (err == -ENODEV)
netif_device_detach(netdev); netif_device_detach(netdev);
if (err)
netdev_err(netdev, "couldn't start device: %d\n", err);
netdev_err(netdev, "couldn't start device: %d\n", err); kfree(msg);
return err; return err;
} }
...@@ -833,26 +838,30 @@ static netdev_tx_t esd_usb2_start_xmit(struct sk_buff *skb, ...@@ -833,26 +838,30 @@ static netdev_tx_t esd_usb2_start_xmit(struct sk_buff *skb,
static int esd_usb2_close(struct net_device *netdev) static int esd_usb2_close(struct net_device *netdev)
{ {
struct esd_usb2_net_priv *priv = netdev_priv(netdev); struct esd_usb2_net_priv *priv = netdev_priv(netdev);
struct esd_usb2_msg msg; struct esd_usb2_msg *msg;
int i; int i;
msg = kmalloc(sizeof(*msg), GFP_KERNEL);
if (!msg)
return -ENOMEM;
/* Disable all IDs (see esd_usb2_start()) */ /* Disable all IDs (see esd_usb2_start()) */
msg.msg.hdr.cmd = CMD_IDADD; msg->msg.hdr.cmd = CMD_IDADD;
msg.msg.hdr.len = 2 + ESD_MAX_ID_SEGMENT; msg->msg.hdr.len = 2 + ESD_MAX_ID_SEGMENT;
msg.msg.filter.net = priv->index; msg->msg.filter.net = priv->index;
msg.msg.filter.option = ESD_ID_ENABLE; /* start with segment 0 */ msg->msg.filter.option = ESD_ID_ENABLE; /* start with segment 0 */
for (i = 0; i <= ESD_MAX_ID_SEGMENT; i++) for (i = 0; i <= ESD_MAX_ID_SEGMENT; i++)
msg.msg.filter.mask[i] = 0; msg->msg.filter.mask[i] = 0;
if (esd_usb2_send_msg(priv->usb2, &msg) < 0) if (esd_usb2_send_msg(priv->usb2, msg) < 0)
netdev_err(netdev, "sending idadd message failed\n"); netdev_err(netdev, "sending idadd message failed\n");
/* set CAN controller to reset mode */ /* set CAN controller to reset mode */
msg.msg.hdr.len = 2; msg->msg.hdr.len = 2;
msg.msg.hdr.cmd = CMD_SETBAUD; msg->msg.hdr.cmd = CMD_SETBAUD;
msg.msg.setbaud.net = priv->index; msg->msg.setbaud.net = priv->index;
msg.msg.setbaud.rsvd = 0; msg->msg.setbaud.rsvd = 0;
msg.msg.setbaud.baud = cpu_to_le32(ESD_USB2_NO_BAUDRATE); msg->msg.setbaud.baud = cpu_to_le32(ESD_USB2_NO_BAUDRATE);
if (esd_usb2_send_msg(priv->usb2, &msg) < 0) if (esd_usb2_send_msg(priv->usb2, msg) < 0)
netdev_err(netdev, "sending setbaud message failed\n"); netdev_err(netdev, "sending setbaud message failed\n");
priv->can.state = CAN_STATE_STOPPED; priv->can.state = CAN_STATE_STOPPED;
...@@ -861,6 +870,8 @@ static int esd_usb2_close(struct net_device *netdev) ...@@ -861,6 +870,8 @@ static int esd_usb2_close(struct net_device *netdev)
close_candev(netdev); close_candev(netdev);
kfree(msg);
return 0; return 0;
} }
...@@ -886,7 +897,8 @@ static int esd_usb2_set_bittiming(struct net_device *netdev) ...@@ -886,7 +897,8 @@ static int esd_usb2_set_bittiming(struct net_device *netdev)
{ {
struct esd_usb2_net_priv *priv = netdev_priv(netdev); struct esd_usb2_net_priv *priv = netdev_priv(netdev);
struct can_bittiming *bt = &priv->can.bittiming; struct can_bittiming *bt = &priv->can.bittiming;
struct esd_usb2_msg msg; struct esd_usb2_msg *msg;
int err;
u32 canbtr; u32 canbtr;
int sjw_shift; int sjw_shift;
...@@ -912,15 +924,22 @@ static int esd_usb2_set_bittiming(struct net_device *netdev) ...@@ -912,15 +924,22 @@ static int esd_usb2_set_bittiming(struct net_device *netdev)
if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
canbtr |= ESD_USB2_3_SAMPLES; canbtr |= ESD_USB2_3_SAMPLES;
msg.msg.hdr.len = 2; msg = kmalloc(sizeof(*msg), GFP_KERNEL);
msg.msg.hdr.cmd = CMD_SETBAUD; if (!msg)
msg.msg.setbaud.net = priv->index; return -ENOMEM;
msg.msg.setbaud.rsvd = 0;
msg.msg.setbaud.baud = cpu_to_le32(canbtr); msg->msg.hdr.len = 2;
msg->msg.hdr.cmd = CMD_SETBAUD;
msg->msg.setbaud.net = priv->index;
msg->msg.setbaud.rsvd = 0;
msg->msg.setbaud.baud = cpu_to_le32(canbtr);
netdev_info(netdev, "setting BTR=%#x\n", canbtr); netdev_info(netdev, "setting BTR=%#x\n", canbtr);
return esd_usb2_send_msg(priv->usb2, &msg); err = esd_usb2_send_msg(priv->usb2, msg);
kfree(msg);
return err;
} }
static int esd_usb2_get_berr_counter(const struct net_device *netdev, static int esd_usb2_get_berr_counter(const struct net_device *netdev,
...@@ -1022,7 +1041,7 @@ static int esd_usb2_probe(struct usb_interface *intf, ...@@ -1022,7 +1041,7 @@ static int esd_usb2_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
struct esd_usb2 *dev; struct esd_usb2 *dev;
struct esd_usb2_msg msg; struct esd_usb2_msg *msg;
int i, err; int i, err;
dev = kzalloc(sizeof(*dev), GFP_KERNEL); dev = kzalloc(sizeof(*dev), GFP_KERNEL);
...@@ -1037,27 +1056,33 @@ static int esd_usb2_probe(struct usb_interface *intf, ...@@ -1037,27 +1056,33 @@ static int esd_usb2_probe(struct usb_interface *intf,
usb_set_intfdata(intf, dev); usb_set_intfdata(intf, dev);
msg = kmalloc(sizeof(*msg), GFP_KERNEL);
if (!msg) {
err = -ENOMEM;
goto free_msg;
}
/* query number of CAN interfaces (nets) */ /* query number of CAN interfaces (nets) */
msg.msg.hdr.cmd = CMD_VERSION; msg->msg.hdr.cmd = CMD_VERSION;
msg.msg.hdr.len = 2; msg->msg.hdr.len = 2;
msg.msg.version.rsvd = 0; msg->msg.version.rsvd = 0;
msg.msg.version.flags = 0; msg->msg.version.flags = 0;
msg.msg.version.drv_version = 0; msg->msg.version.drv_version = 0;
err = esd_usb2_send_msg(dev, &msg); err = esd_usb2_send_msg(dev, msg);
if (err < 0) { if (err < 0) {
dev_err(&intf->dev, "sending version message failed\n"); dev_err(&intf->dev, "sending version message failed\n");
goto free_dev; goto free_msg;
} }
err = esd_usb2_wait_msg(dev, &msg); err = esd_usb2_wait_msg(dev, msg);
if (err < 0) { if (err < 0) {
dev_err(&intf->dev, "no version message answer\n"); dev_err(&intf->dev, "no version message answer\n");
goto free_dev; goto free_msg;
} }
dev->net_count = (int)msg.msg.version_reply.nets; dev->net_count = (int)msg->msg.version_reply.nets;
dev->version = le32_to_cpu(msg.msg.version_reply.version); dev->version = le32_to_cpu(msg->msg.version_reply.version);
if (device_create_file(&intf->dev, &dev_attr_firmware)) if (device_create_file(&intf->dev, &dev_attr_firmware))
dev_err(&intf->dev, dev_err(&intf->dev,
...@@ -1075,10 +1100,10 @@ static int esd_usb2_probe(struct usb_interface *intf, ...@@ -1075,10 +1100,10 @@ static int esd_usb2_probe(struct usb_interface *intf,
for (i = 0; i < dev->net_count; i++) for (i = 0; i < dev->net_count; i++)
esd_usb2_probe_one_net(intf, i); esd_usb2_probe_one_net(intf, i);
return 0; free_msg:
kfree(msg);
free_dev: if (err)
kfree(dev); kfree(dev);
done: done:
return err; return err;
} }
......
...@@ -136,6 +136,9 @@ ...@@ -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,8 +820,13 @@ static void kvaser_usb_rx_can_msg(const struct kvaser_usb *dev, ...@@ -817,8 +820,13 @@ 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_FLAG_OVERRUN)) { (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)) {
kvaser_usb_rx_can_err(priv, msg); kvaser_usb_rx_can_err(priv, msg);
return; return;
} else if (msg->u.rx_can.flag & ~MSG_FLAG_REMOTE_FRAME) { } else if (msg->u.rx_can.flag & ~MSG_FLAG_REMOTE_FRAME) {
...@@ -834,22 +842,40 @@ static void kvaser_usb_rx_can_msg(const struct kvaser_usb *dev, ...@@ -834,22 +842,40 @@ static void kvaser_usb_rx_can_msg(const struct kvaser_usb *dev,
return; return;
} }
cf->can_id = ((msg->u.rx_can.msg[0] & 0x1f) << 6) | if (msg->id == CMD_LOG_MESSAGE) {
(msg->u.rx_can.msg[1] & 0x3f); cf->can_id = le32_to_cpu(msg->u.log_message.id);
cf->can_dlc = get_can_dlc(msg->u.rx_can.msg[5]); if (cf->can_id & KVASER_EXTENDED_FRAME)
cf->can_id &= CAN_EFF_MASK | CAN_EFF_FLAG;
else
cf->can_id &= CAN_SFF_MASK;
if (msg->id == CMD_RX_EXT_MESSAGE) { cf->can_dlc = get_can_dlc(msg->u.log_message.dlc);
cf->can_id <<= 18;
cf->can_id |= ((msg->u.rx_can.msg[2] & 0x0f) << 14) |
((msg->u.rx_can.msg[3] & 0xff) << 6) |
(msg->u.rx_can.msg[4] & 0x3f);
cf->can_id |= CAN_EFF_FLAG;
}
if (msg->u.rx_can.flag & MSG_FLAG_REMOTE_FRAME) if (msg->u.log_message.flags & 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.log_message.data,
cf->can_dlc);
} else {
cf->can_id = ((msg->u.rx_can.msg[0] & 0x1f) << 6) |
(msg->u.rx_can.msg[1] & 0x3f);
if (msg->id == CMD_RX_EXT_MESSAGE) {
cf->can_id <<= 18;
cf->can_id |= ((msg->u.rx_can.msg[2] & 0x0f) << 14) |
((msg->u.rx_can.msg[3] & 0xff) << 6) |
(msg->u.rx_can.msg[4] & 0x3f);
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)
cf->can_id |= CAN_RTR_FLAG;
else
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, ...@@ -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, ...@@ -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;
......
...@@ -504,15 +504,24 @@ static int pcan_usb_pro_restart_async(struct peak_usb_device *dev, ...@@ -504,15 +504,24 @@ static int pcan_usb_pro_restart_async(struct peak_usb_device *dev,
return usb_submit_urb(urb, GFP_ATOMIC); return usb_submit_urb(urb, GFP_ATOMIC);
} }
static void pcan_usb_pro_drv_loaded(struct peak_usb_device *dev, int loaded) static int pcan_usb_pro_drv_loaded(struct peak_usb_device *dev, int loaded)
{ {
u8 buffer[16]; u8 *buffer;
int err;
buffer = kmalloc(PCAN_USBPRO_FCT_DRVLD_REQ_LEN, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
buffer[0] = 0; buffer[0] = 0;
buffer[1] = !!loaded; buffer[1] = !!loaded;
pcan_usb_pro_send_req(dev, PCAN_USBPRO_REQ_FCT, err = pcan_usb_pro_send_req(dev, PCAN_USBPRO_REQ_FCT,
PCAN_USBPRO_FCT_DRVLD, buffer, sizeof(buffer)); PCAN_USBPRO_FCT_DRVLD, buffer,
PCAN_USBPRO_FCT_DRVLD_REQ_LEN);
kfree(buffer);
return err;
} }
static inline static inline
...@@ -851,21 +860,24 @@ static int pcan_usb_pro_stop(struct peak_usb_device *dev) ...@@ -851,21 +860,24 @@ static int pcan_usb_pro_stop(struct peak_usb_device *dev)
*/ */
static int pcan_usb_pro_init(struct peak_usb_device *dev) 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 *pdev =
container_of(dev, struct pcan_usb_pro_device, dev); container_of(dev, struct pcan_usb_pro_device, dev);
struct pcan_usb_pro_interface *usb_if = NULL;
struct pcan_usb_pro_fwinfo *fi = NULL;
struct pcan_usb_pro_blinfo *bi = NULL;
int err;
/* do this for 1st channel only */ /* do this for 1st channel only */
if (!dev->prev_siblings) { if (!dev->prev_siblings) {
struct pcan_usb_pro_fwinfo fi;
struct pcan_usb_pro_blinfo bi;
int err;
/* allocate netdevices common structure attached to first one */ /* allocate netdevices common structure attached to first one */
usb_if = kzalloc(sizeof(struct pcan_usb_pro_interface), usb_if = kzalloc(sizeof(struct pcan_usb_pro_interface),
GFP_KERNEL); GFP_KERNEL);
if (!usb_if) fi = kmalloc(sizeof(struct pcan_usb_pro_fwinfo), GFP_KERNEL);
return -ENOMEM; bi = kmalloc(sizeof(struct pcan_usb_pro_blinfo), GFP_KERNEL);
if (!usb_if || !fi || !bi) {
err = -ENOMEM;
goto err_out;
}
/* number of ts msgs to ignore before taking one into account */ /* number of ts msgs to ignore before taking one into account */
usb_if->cm_ignore_count = 5; usb_if->cm_ignore_count = 5;
...@@ -877,34 +889,34 @@ static int pcan_usb_pro_init(struct peak_usb_device *dev) ...@@ -877,34 +889,34 @@ static int pcan_usb_pro_init(struct peak_usb_device *dev)
*/ */
err = pcan_usb_pro_send_req(dev, PCAN_USBPRO_REQ_INFO, err = pcan_usb_pro_send_req(dev, PCAN_USBPRO_REQ_INFO,
PCAN_USBPRO_INFO_FW, PCAN_USBPRO_INFO_FW,
&fi, sizeof(fi)); fi, sizeof(*fi));
if (err) { if (err) {
kfree(usb_if);
dev_err(dev->netdev->dev.parent, dev_err(dev->netdev->dev.parent,
"unable to read %s firmware info (err %d)\n", "unable to read %s firmware info (err %d)\n",
pcan_usb_pro.name, err); pcan_usb_pro.name, err);
return err; goto err_out;
} }
err = pcan_usb_pro_send_req(dev, PCAN_USBPRO_REQ_INFO, err = pcan_usb_pro_send_req(dev, PCAN_USBPRO_REQ_INFO,
PCAN_USBPRO_INFO_BL, PCAN_USBPRO_INFO_BL,
&bi, sizeof(bi)); bi, sizeof(*bi));
if (err) { if (err) {
kfree(usb_if);
dev_err(dev->netdev->dev.parent, dev_err(dev->netdev->dev.parent,
"unable to read %s bootloader info (err %d)\n", "unable to read %s bootloader info (err %d)\n",
pcan_usb_pro.name, err); pcan_usb_pro.name, err);
return err; goto err_out;
} }
/* tell the device the can driver is running */
err = pcan_usb_pro_drv_loaded(dev, 1);
if (err)
goto err_out;
dev_info(dev->netdev->dev.parent, dev_info(dev->netdev->dev.parent,
"PEAK-System %s hwrev %u serial %08X.%08X (%u channels)\n", "PEAK-System %s hwrev %u serial %08X.%08X (%u channels)\n",
pcan_usb_pro.name, pcan_usb_pro.name,
bi.hw_rev, bi.serial_num_hi, bi.serial_num_lo, bi->hw_rev, bi->serial_num_hi, bi->serial_num_lo,
pcan_usb_pro.ctrl_count); pcan_usb_pro.ctrl_count);
/* tell the device the can driver is running */
pcan_usb_pro_drv_loaded(dev, 1);
} else { } else {
usb_if = pcan_usb_pro_dev_if(dev->prev_siblings); usb_if = pcan_usb_pro_dev_if(dev->prev_siblings);
} }
...@@ -916,6 +928,13 @@ static int pcan_usb_pro_init(struct peak_usb_device *dev) ...@@ -916,6 +928,13 @@ static int pcan_usb_pro_init(struct peak_usb_device *dev)
pcan_usb_pro_set_led(dev, 0, 1); pcan_usb_pro_set_led(dev, 0, 1);
return 0; return 0;
err_out:
kfree(bi);
kfree(fi);
kfree(usb_if);
return err;
} }
static void pcan_usb_pro_exit(struct peak_usb_device *dev) static void pcan_usb_pro_exit(struct peak_usb_device *dev)
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
/* Vendor Request value for XXX_FCT */ /* Vendor Request value for XXX_FCT */
#define PCAN_USBPRO_FCT_DRVLD 5 /* tell device driver is loaded */ #define PCAN_USBPRO_FCT_DRVLD 5 /* tell device driver is loaded */
#define PCAN_USBPRO_FCT_DRVLD_REQ_LEN 16
/* PCAN_USBPRO_INFO_BL vendor request record type */ /* PCAN_USBPRO_INFO_BL vendor request record type */
struct __packed pcan_usb_pro_blinfo { struct __packed pcan_usb_pro_blinfo {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment