usb_8dev: Add support for USB2CAN interface from 8 devices
PATCH v2 1/1 usb_8dev: Add support for USB2CAN interface from 8 devices
Add device driver for USB2CAN interface from "8 devices" (http://www.8devices.com).
--- drivers/net/can/usb/Kconfig | 6 + drivers/net/can/usb/Makefile | 1 + drivers/net/can/usb/usb_8dev.c | 1098 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1105 insertions(+) create mode 100644 drivers/net/can/usb/usb_8dev.c
drivers/net/can/usb/Kconfig +6 -0
@@ -48,4 +48,10 @@ config CAN_PEAK_USB This driver supports the PCAN-USB and PCAN-USB Pro adapters from PEAK-System Technik (http://www.peak-system.com). +config CAN_8DEV_USB + tristate "8 devices USB2CAN interface" + ---help--- + This driver supports the USB2CAN interface + from 8 devices (http://www.8devices.com). + endmenu
drivers/net/can/usb/Makefile +1 -0
@@ -6,5 +6,6 @@ obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o obj-$(CONFIG_CAN_ESD_USB2) += esd_usb2.o obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb.o obj-$(CONFIG_CAN_PEAK_USB) += peak_usb/ +obj-$(CONFIG_CAN_8DEV_USB) += usb_8dev.o ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
drivers/net/can/usb/usb_8dev.c new file +1098 -0
1,098 lines not on this page · raw message
Signature · 1 line
1.7.10.4
Hi, at a closer look I see a few more issues:
Please use s/dev_warn(netdev->dev.parent,/netdev_warn(/ for dev_warn and friends.
You can drop the do_set_bittiming callback if it's not needed. There is no need for a dummy function, IIRC.
And please also drop the remaining sysfs files for firmware and hardware. I thinks it's enough that the versions are printed when the device is probed.
Quoted 45 lines · On 12/03/2012 01:50 AM, [email protected] wrote:
Add device driver for USB2CAN interface from "8 devices"
(http://www.8devices.com).Signed-off-by Bernd Krumboeck <[email protected]>--- drivers/net/can/usb/Kconfig | 6 + drivers/net/can/usb/Makefile | 1 + drivers/net/can/usb/usb_8dev.c | 1098 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1105 insertions(+) create mode 100644 drivers/net/can/usb/usb_8dev.cdrivers/net/can/usb/Kconfig +6
-0@@ -48,4 +48,10 @@ config CAN_PEAK_USB This driver supports the PCAN-USB and PCAN-USB Pro adapters from PEAK-System Technik (http://www.peak-system.com). +config CAN_8DEV_USB + tristate "8 devices USB2CAN interface" + ---help--- + This driver supports the USB2CAN interface + from 8 devices (http://www.8devices.com). + endmenudrivers/net/can/usb/Makefile +1
-0@@ -6,5 +6,6 @@ obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o obj-$(CONFIG_CAN_ESD_USB2) += esd_usb2.o obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb.o obj-$(CONFIG_CAN_PEAK_USB) += peak_usb/ +obj-$(CONFIG_CAN_8DEV_USB) += usb_8dev.o ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUGdrivers/net/can/usb/usb_8dev.c new file +0
-0
drivers/net/can/usb/usb_8dev.c line 2
Quoted 2 lines
drivers/net/can/usb/usb_8dev.c new file +2
-0@@ -0,0 +1,1098 @@ +/* +* CAN driver for UAB "8 devices" USB2CAN converter
UAB means?
drivers/net/can/usb/usb_8dev.c line 325
Quoted 7 lines
drivers/net/can/usb/usb_8dev.c new file +2
-0+/* Get firmware version */ +static ssize_t show_firmware(struct device *d, struct device_attribute*attr,
drivers/net/can/usb/usb_8dev.c new file +4
-0+ char *buf) +{ +struct usb_8dev_cmd_msg outmsg; +struct usb_8dev_cmd_msg inmsg;
Just one space.
Quoted 20 lines
drivers/net/can/usb/usb_8dev.c new file +19
-0+int err =0 ; +u16 result; +struct usb_interface *intf =to_usb_interface (d); +struct usb_8dev *dev =usb_get_intfdata (intf); + +memset (&outmsg,0 ,sizeof (struct usb_8dev_cmd_msg )); + outmsg.command =USB_8DEV_GET_SOFTW_VER ; + + err =usb_8dev_send_cmd (dev, &outmsg, &inmsg); +if (err) +return -EIO ; + + result =be16_to_cpu (*(u16 *)inmsg.data); + +return sprintf (buf,"%d.%d\n" , (u8)(result>>8 ), (u8 )result); +} + +/* Get hardware version */ +static ssize_t show_hardware(struct device *d, struct device_attribute*attr,
drivers/net/can/usb/usb_8dev.c line 325
Quoted 4 lines
drivers/net/can/usb/usb_8dev.c new file +4
-0+ char *buf) +{ +struct usb_8dev_cmd_msg outmsg; +struct usb_8dev_cmd_msg inmsg;
Ditto.
Quoted 79 lines
drivers/net/can/usb/usb_8dev.c new file +10
-0+static DEVICE_ATTR(firmware, S_IRUGO, show_firmware, NULL); +static DEVICE_ATTR(hardware, S_IRUGO, show_hardware, NULL); + +/* +* Set network device mode +* +* Maybe we should leave this function empty, because the device +* set mode variable with open command. +*/ +static int usb_8dev_set_mode(struct net_device *netdev, enum can_modemode)
drivers/net/can/usb/usb_8dev.c new file +68
-0+{ +struct usb_8dev *dev =netdev_priv (netdev); +int err =0 ; + +switch (mode) { +case CAN_MODE_START : + err =usb_8dev_cmd_open (dev); +if (err) +dev_warn (netdev->dev.parent,"couldn't start device" ); + +if (netif_queue_stopped (netdev)) +netif_wake_queue (netdev); +break ; + +default : +return -EOPNOTSUPP ; + } + +return 0 ; +} + +/* +* Empty function: We set bittiming when we start the interface. +* This is a firmware limitation. +*/ +static int usb_8dev_set_bittiming (struct net_device *netdev) +{ +return 0 ; +} + +/* Read data and status frames */ +static void usb_8dev_rx_can_msg (struct usb_8dev *dev, +struct usb_8dev_rx_msg *msg) +{ +struct can_frame *cf; +struct sk_buff *skb; +int i; +struct net_device_stats *stats = &dev->netdev->stats; + +if (msg->type ==USB_8DEV_TYPE_CAN_FRAME ) { + skb =alloc_can_skb (dev->netdev, &cf); +if (!skb) +return ; + + cf->can_id =be32_to_cpu (msg->id); + cf->can_dlc =get_can_dlc (msg->dlc &0xF ); + +if (msg->flags &USB_8DEV_EXTID ) + cf->can_id |=CAN_EFF_FLAG ; + +if (msg->flags &USB_8DEV_RTR ) + cf->can_id |=CAN_RTR_FLAG ; +else +for (i =0 ; i < cf->can_dlc; i++) + cf->data[i] = msg->data[i]; + }else if (msg->type ==USB_8DEV_TYPE_ERROR_FRAME && + msg->flags ==USB_8DEV_ERR_FLAG ) { + +/* +* Error message: +* byte 0: Status +* byte 1: bit 7: Receive Passive +* byte 1: bit 0-6: Receive Error Counter +* byte 2: Transmit Error Counter +* byte 3: Always 0 (maybe reserved for future use) +*/ + +u8 state = msg->data[0 ];
drivers/net/can/usb/usb_8dev.c line 453
Quoted 10 lines
drivers/net/can/usb/usb_8dev.c new file +10
-0+u8 rxerr = msg->data[1 ] &USB_8DEV_RP_MASK ; +u8 txerr = msg->data[2 ]; +int rx_errors =0 ; +int tx_errors =0 ; + + skb =alloc_can_err_skb (dev->netdev, &cf); +if (!skb) +return ; + + dev->can.can_stats.bus_error++;
As we have seen, please check first if a bus error has been reported. And the same for setting "CAN_ERR_PROT | CAN_ERR_BUSERROR" below. Obviously, the device reports either a bus-error or a state-change.
Quoted 67 lines
drivers/net/can/usb/usb_8dev.c new file +66
-0+ +switch (state) { +case USB_8DEV_STATUSMSG_OK : + dev->can.state =CAN_STATE_ERROR_ACTIVE ; + cf->can_id |=CAN_ERR_PROT ; + cf->data[2 ] =CAN_ERR_PROT_ACTIVE ; +break ; +case USB_8DEV_STATUSMSG_BUSOFF : + dev->can.state =CAN_STATE_BUS_OFF ; + cf->can_id |=CAN_ERR_BUSOFF ; +can_bus_off (dev->netdev); +break ; +default : + dev->can.state =CAN_STATE_ERROR_WARNING ; + cf->can_id |=CAN_ERR_PROT |CAN_ERR_BUSERROR ; +break ; + } +switch (state) { +case USB_8DEV_STATUSMSG_ACK : + cf->can_id |=CAN_ERR_ACK ; + tx_errors =1 ; +break ; +case USB_8DEV_STATUSMSG_CRC : + cf->data[2 ] |=CAN_ERR_PROT_BIT ; + rx_errors =1 ; +break ; +case USB_8DEV_STATUSMSG_BIT0 : + cf->data[2 ] |=CAN_ERR_PROT_BIT0 ; + tx_errors =1 ; +break ; +case USB_8DEV_STATUSMSG_BIT1 : + cf->data[2 ] |=CAN_ERR_PROT_BIT1 ; + tx_errors =1 ; +break ; +case USB_8DEV_STATUSMSG_FORM : + cf->data[2 ] |=CAN_ERR_PROT_FORM ; + rx_errors =1 ; +break ; +case USB_8DEV_STATUSMSG_STUFF : + cf->data[2 ] |=CAN_ERR_PROT_STUFF ; + rx_errors =1 ; +break ; +case USB_8DEV_STATUSMSG_OVERRUN : + cf->can_id |=CAN_ERR_CRTL ; + cf->data[1 ] = (txerr > rxerr) ? +CAN_ERR_CRTL_TX_OVERFLOW : +CAN_ERR_CRTL_RX_OVERFLOW ; + cf->data[2 ] |=CAN_ERR_PROT_OVERLOAD ; + stats->rx_over_errors++; +break ; +case USB_8DEV_STATUSMSG_BUSLIGHT : + cf->can_id |=CAN_ERR_CRTL ; + cf->data[1 ] = (txerr > rxerr) ? +CAN_ERR_CRTL_TX_WARNING : +CAN_ERR_CRTL_RX_WARNING ; + dev->can.can_stats.error_warning++; +break ; +case USB_8DEV_STATUSMSG_BUSHEAVY : + cf->can_id |=CAN_ERR_CRTL ; + cf->data[1 ] = (txerr > rxerr) ? +CAN_ERR_CRTL_TX_PASSIVE : +CAN_ERR_CRTL_RX_PASSIVE ; + dev->can.can_stats.error_passive++; +break ; +default : + cf->data[2 ] |=CAN_ERR_PROT_UNSPEC ;
drivers/net/can/usb/usb_8dev.c line 530
Quoted 10 lines
drivers/net/can/usb/usb_8dev.c new file +10
-0+break ; + } + +if (tx_errors) { + cf->data[2 ] |=CAN_ERR_PROT_TX ; + stats->tx_errors++; + } + +if (rx_errors) + stats->rx_errors++;
If tx_errors or rx_errors is set, it's a bus-error. Then also set CAN_ERR_PROT | CAN_ERR_BUSERROR and increment bus_error.
Quoted 7 lines
drivers/net/can/usb/usb_8dev.c new file +7
-0+ cf->data[6 ] = txerr; + cf->data[7 ] = rxerr; + + dev->bec.txerr = txerr; + dev->bec.rxerr = rxerr; + + }else {
drivers/net/can/usb/usb_8dev.c line 548
Quoted 10 lines
drivers/net/can/usb/usb_8dev.c new file +10
-0+dev_warn (dev->udev->dev.parent,"frame type %d unknown" , + msg->type); +return ; + } + +netif_rx (skb); + + stats->rx_packets++; + stats->rx_bytes += cf->can_dlc; +}
Wolfgang.
Hi Wolfgang!
Quoted 4 lines
And please also drop the remaining sysfs files for firmware and hardware. I thinks it's enough that the versions are printed when the device is probed.
Systemadministrators often use versions for configuration scripts. If you insist I will remove.
Quoted 5 lines
Quoted 2 lines
+/*
+ * CAN driver for UAB "8 devices" USB2CAN converterUAB means?
I don't know. I've taken from the homepage. Maybe it is a type of company.
I will remove...
Thanks for your comments and suggestions.
regards,
Bernd
Quoted 9 lines · On 12/03/2012 09:32 PM, [email protected] wrote:
Hi Wolfgang!
Quoted 4 lines
And please also drop the remaining sysfs files for firmware and hardware. I thinks it's enough that the versions are printed when the device is probed.
Systemadministrators often use versions for configuration scripts. If you insist I will remove.
Marc?
Wolfgang.
Marc Kleine-Budde
maintainerQuoted 4 lines · Wolfgang Grandegger
Quoted 3 lines · On 12/03/2012 09:32 PM, [email protected] wrote:
Hi Wolfgang!
Quoted 1 line
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
And please also drop the remaining sysfs files for firmware and hardware. I thinks it's enough that the versions are printed when the device is probed.
Systemadministrators often use versions for configuration scripts. If you insist I will remove.
Marc?
Are these values exported via lsusb -v (e.g. iSerial)?
Marc
Signature · 4 lines
Pengutronix e.K. | Marc Kleine-Budde | Industrial Linux Solutions | Phone: +49-231-2826-924 | Vertretung West/Dortmund | Fax: +49-5121-206917-5555 | Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
A message that is not in the archive (sent off-list or not yet received): c003ee227fe9e5a754a78fd8575ce977.squirrel@webmail.universalnet.at
Marc Kleine-Budde
maintainerQuoted 31 lines · Bernd Krumböck
Quoted 9 lines · Wolfgang Grandegger
Quoted 8 lines · On 12/03/2012 09:32 PM, [email protected] wrote:
Quoted 7 lines
Hi Wolfgang!
Quoted 4 lines
And please also drop the remaining sysfs files for firmware and hardware. I thinks it's enough that the versions are printed when the device is probed.
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Systemadministrators often use versions for configuration scripts. If you insist I will remove.
Marc?
Are these values exported via lsusb -v (e.g. iSerial)?
No, I have not seen yet.
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 255 Vendor Specific Class
bDeviceSubClass 255 Vendor Specific Subclass
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor0x0483SGS Thomson Microelectronics
idProduct0x1234
bcdDevice 1.00
Quoted 3 lines
iManufacturer 1 iProduct 2 iSerial 3
^^^^^^^^^^^^^^^^^^^^^^^^^
[...]
Quoted 8 lines
dmesg:
[11708.644014] usb 6-2: new full-speed USB device number 2 using uhci_hcd [11708.820030] usb 6-2: New USB device found, idVendor=0483, idProduct=1234 [11708.820034] usb 6-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [11708.820036] usb 6-2: Product: USB2CAN converter [11708.820038] usb 6-2: Manufacturer: edevices [11708.820041] usb 6-2: SerialNumber: ED000202
^^^^^^^^
Does these numbers correspond to the hardware and firmware revision?
Marc
Signature · 4 lines
Pengutronix e.K. | Marc Kleine-Budde | Industrial Linux Solutions | Phone: +49-231-2826-924 | Vertretung West/Dortmund | Fax: +49-5121-206917-5555 | Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
Am 2012-12-04 21:22, schrieb Marc Kleine-Budde:
Quoted 47 lines · Bernd Krumböck
Quoted 31 lines
Quoted 9 lines · Wolfgang Grandegger
Quoted 8 lines · On 12/03/2012 09:32 PM, [email protected] wrote:
Quoted 7 lines
Hi Wolfgang!
Quoted 4 lines
And please also drop the remaining sysfs files for firmware and hardware. I thinks it's enough that the versions are printed when the device is probed.
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Systemadministrators often use versions for configuration scripts. If you insist I will remove.
Marc?
Are these values exported via lsusb -v (e.g. iSerial)?
No, I have not seen yet.
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 255 Vendor Specific Class
bDeviceSubClass 255 Vendor Specific Subclass
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor0x0483SGS Thomson Microelectronics
idProduct0x1234
bcdDevice 1.00Quoted 3 lines
iManufacturer 1 iProduct 2 iSerial 3^^^^^^^^^^^^^^^^^^^^^^^^^[...]
Quoted 8 lines
dmesg:
[11708.644014] usb 6-2: new full-speed USB device number 2 using uhci_hcd [11708.820030] usb 6-2: New USB device found, idVendor=0483, idProduct=1234 [11708.820034] usb 6-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [11708.820036] usb 6-2: Product: USB2CAN converter [11708.820038] usb 6-2: Manufacturer: edevices [11708.820041] usb 6-2: SerialNumber: ED000202
Quoted 1 line
^^^^^^^^
This serial number is printed on the device.
Quoted 2 lines
Does these numbers correspond to the hardware and firmware revision?
No.
firmware: 1.4
hardware: 1.0
best regards,
Bernd
Marc Kleine-Budde
maintainerQuoted 4 lines · On 12/03/2012 01:50 AM, [email protected] wrote:
Add device driver for USB2CAN interface from "8 devices"
(http://www.8devices.com).Signed-off-by Bernd Krumboeck <[email protected]>
Please send your patch with git send-email, as with this one all tabs are converted to spaces.
Quoted 150 lines
--- drivers/net/can/usb/Kconfig | 6 + drivers/net/can/usb/Makefile | 1 + drivers/net/can/usb/usb_8dev.c | 1098 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1105 insertions(+) create mode 100644 drivers/net/can/usb/usb_8dev.cdrivers/net/can/usb/Kconfig +6
-0@@ -48,4 +48,10 @@ config CAN_PEAK_USB This driver supports the PCAN-USB and PCAN-USB Pro adapters from PEAK-System Technik (http://www.peak-system.com). +config CAN_8DEV_USB + tristate "8 devices USB2CAN interface" + ---help--- + This driver supports the USB2CAN interface + from 8 devices (http://www.8devices.com). + endmenudrivers/net/can/usb/Makefile +1
-0@@ -6,5 +6,6 @@ obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o obj-$(CONFIG_CAN_ESD_USB2) += esd_usb2.o obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb.o obj-$(CONFIG_CAN_PEAK_USB) += peak_usb/ +obj-$(CONFIG_CAN_8DEV_USB) += usb_8dev.o ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUGdrivers/net/can/usb/usb_8dev.c new file +19
-0@@ -0,0 +1,1098 @@ +/* +* CAN driver for UAB "8 devices" USB2CAN converter +* +* Copyright (C) 2012 Bernd Krumboeck ([email protected]) +* +* 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. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +* +* This driver is inspired by the 3.2.0 version of
drivers/net/can/usb/ems_usb.c
+ * anddrivers/net/can/usb/esd_usb2.c
+ *
+ * Many thanks to Gerhard Bertelsmann ([email protected])
+ * for testing and fixing this driver. Also many thanks to "8 devices",
+ * who were very cooperative and answered my questions.
+ */drivers/net/can/usb/usb_8dev.c new file +75
-0+ +#include <linux/init.h> +#include <linux/signal.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/usb.h> + +#include <linux/can.h> +#include <linux/can/dev.h> +#include <linux/can/error.h> + +/* driver constants */ +#define MAX_RX_URBS 10 +#define MAX_TX_URBS 10 +#define RX_BUFFER_SIZE 64 + +/* vendor and product id */ +#define USB_8DEV_VENDOR_ID 0x0483 +#define USB_8DEV_PRODUCT_ID 0x1234 + +/* bittiming constants */ +#define USB_8DEV_ABP_CLOCK 32000000 +#define USB_8DEV_BAUD_MANUAL 0x09 +#define USB_8DEV_TSEG1_MIN 1 +#define USB_8DEV_TSEG1_MAX 16 +#define USB_8DEV_TSEG2_MIN 1 +#define USB_8DEV_TSEG2_MAX 8 +#define USB_8DEV_SJW_MAX 4 +#define USB_8DEV_BRP_MIN 1 +#define USB_8DEV_BRP_MAX 1024 +#define USB_8DEV_BRP_INC 1 + +/* setup flags */ +#define USB_8DEV_SILENT 0x01 +#define USB_8DEV_LOOPBACK 0x02 +#define USB_8DEV_DISABLE_AUTO_RESTRANS 0x04 +#define USB_8DEV_STATUS_FRAME 0x08 + +/* commands */ +enum usb_8dev_cmd { +USB_8DEV_RESET =1 , +USB_8DEV_OPEN , +USB_8DEV_CLOSE , +USB_8DEV_SET_SPEED , +USB_8DEV_SET_MASK_FILTER , +USB_8DEV_GET_STATUS , +USB_8DEV_GET_STATISTICS , +USB_8DEV_GET_SERIAL , +USB_8DEV_GET_SOFTW_VER , +USB_8DEV_GET_HARDW_VER , +USB_8DEV_RESET_TIMESTAMP , +USB_8DEV_GET_SOFTW_HARDW_VER +}; + +#define USB_8DEV_CMD_START 0x11 +#define USB_8DEV_CMD_END 0x22 + +#define USB_8DEV_CMD_SUCCESS 0 +#define USB_8DEV_CMD_ERROR 255 + +/* frames */ +#define USB_8DEV_DATA_START 0x55 +#define USB_8DEV_DATA_END 0xAA + +#define USB_8DEV_TYPE_CAN_FRAME 0 +#define USB_8DEV_TYPE_ERROR_FRAME 3 + +#define USB_8DEV_EXTID 0x01 +#define USB_8DEV_RTR 0x02 +#define USB_8DEV_ERR_FLAG 0x04 + +/* status */ +#define USB_8DEV_STATUSMSG_OK 0x00/* Normal condition. */ +#define USB_8DEV_STATUSMSG_OVERRUN 0x01/* Overrun occured when sending */
+#defineUSB_8DEV_STATUSMSG_BUSLIGHT0x02/* Error counter has
reached 96 */
+#defineUSB_8DEV_STATUSMSG_BUSHEAVY0x03/* Error count. has
reached 128 */drivers/net/can/usb/usb_8dev.c new file +3
-0+#define USB_8DEV_STATUSMSG_BUSOFF 0x04/* Device is in BUSOFF */ +#define USB_8DEV_STATUSMSG_STUFF 0x20/* Stuff Error */ +#define USB_8DEV_STATUSMSG_FORM 0x21/* Form Error */
drivers/net/can/usb/usb_8dev.c line 115
Quoted 10 lines
drivers/net/can/usb/usb_8dev.c new file +10
-0+#define USB_8DEV_STATUSMSG_ACK 0x23/* Ack Error */ +#define USB_8DEV_STATUSMSG_BIT0 0x24/* Bit1 Error */ +#define USB_8DEV_STATUSMSG_BIT1 0x25/* Bit0 Error */ +#define USB_8DEV_STATUSMSG_CRC 0x26/* CRC Error */ +e +#define USB_8DEV_RP_MASK 0x7F/* Mask for Receive Error Bit */ + + +/* table of devices that work with this driver */ +static struct usb_device_id usb_8dev_table[] = {
const
Quoted 69 lines
drivers/net/can/usb/usb_8dev.c new file +69
-0+ { USB_DEVICE(USB_8DEV_VENDOR_ID, USB_8DEV_PRODUCT_ID) }, + { }/* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, usb_8dev_table); + +struct usb_8dev_tx_urb_context { +struct usb_8dev *dev; + +u32 echo_index; +u8 dlc; +}; + +/* Structure to hold all of our device specific stuff */ +struct usb_8dev { +struct can_priv can;/* must be the first member */ + +struct sk_buff *echo_skb[MAX_TX_URBS ]; + +struct usb_device *udev; +struct net_device *netdev; + +atomic_t active_tx_urbs; +struct usb_anchor tx_submitted; +struct usb_8dev_tx_urb_context tx_contexts[MAX_TX_URBS ]; + +struct usb_anchor rx_submitted; + +struct can_berr_counter bec; + +u8 *cmd_msg_buffer; + +unsigned int free_slots;/* remember number of available slots */ + +struct mutex usb_8dev_cmd_lock; + +}; + +/* tx frame */ +struct __packed usb_8dev_tx_msg { +u8 begin; +u8 flags;/* RTR and EXT_ID flag */ +__be32 id;/* upper 3 bits not used */ +u8 dlc;/* data length code 0-8 bytes */ +u8 data[8 ];/* 64-bit data */ +u8 end; +}; + +/* rx frame */ +struct __packed usb_8dev_rx_msg { +u8 begin; +u8 type;/* frame type */ +u8 flags;/* RTR and EXT_ID flag */ +__be32 id;/* upper 3 bits not used */ +u8 dlc;/* data length code 0-8 bytes */ +u8 data[8 ];/* 64-bit data */ +__be32 timestamp;/* 32-bit timestamp */ +u8 end; +}; + +/* command frame */ +struct __packed usb_8dev_cmd_msg { +u8 begin; +u8 channel;/* unkown - always 0 */ +u8 command;/* command to execute */ +u8 opt1;/* optional parameter / return value */ +u8 opt2;/* optional parameter 2 */ +u8 data[10 ];/* optional parameter and data */ +u8 end;
drivers/net/can/usb/usb_8dev.c line 194
Quoted 10 lines
drivers/net/can/usb/usb_8dev.c new file +10
-0+}; + +static struct usb_driver usb_8dev_driver; + +static int usb_8dev_send_cmd_msg (struct usb_8dev *dev,u8 *msg,int size) +{ +int actual_length; + +return usb_bulk_msg (dev->udev,usb_sndbulkpipe (dev->udev,4 ), + msg, size, &actual_length,1000 );
Please make this 1000 a #define.
Quoted 17 lines
drivers/net/can/usb/usb_8dev.c new file +14
-0+} + +static int usb_8dev_wait_cmd_msg (struct usb_8dev *dev,u8 *msg,int size, +int *actual_length) +{ +return usb_bulk_msg (dev->udev,usb_rcvbulkpipe (dev->udev,3 ), + msg, size, actual_length,1000 ); +} + +/* +* Send command to device and receive result. +* Command was successful when opt1 = 0. +*/ +static int usb_8dev_send_cmd(struct usb_8dev *dev, struct
usb_8dev_cmd_msg*out,drivers/net/can/usb/usb_8dev.c new file +2
-0+ struct usb_8dev_cmd_msg *in) +{
drivers/net/can/usb/usb_8dev.c line 220
Quoted 10 lines
drivers/net/can/usb/usb_8dev.c new file +10
-0+int err; +int num_bytes_read; +struct net_device *netdev; + + netdev = dev->netdev; + + out->begin =USB_8DEV_CMD_START ; + out->end =USB_8DEV_CMD_END ; + + memcpy(&dev->cmd_msg_buffer[0], out,
just dev->cmd_msg_buffer (there are several of this)
drivers/net/can/usb/usb_8dev.c line 223
Quoted 3 lines
drivers/net/can/usb/usb_8dev.c new file +3
-0+ sizeof(struct usb_8dev_cmd_msg)); + +mutex_lock (&dev->usb_8dev_cmd_lock);
Is cmd_msg_buffer a shared resource, too? Then it should probably accessed unter the mutex only.
drivers/net/can/usb/usb_8dev.c line 229
Quoted 6 lines
drivers/net/can/usb/usb_8dev.c new file +6
-0+ + err =usb_8dev_send_cmd_msg (dev, &dev->cmd_msg_buffer[0 ], +sizeof (struct usb_8dev_cmd_msg )); +if (err <0 ) { +dev_err (netdev->dev.parent,"sending command message failed\n" ); +return err;
mutex?
drivers/net/can/usb/usb_8dev.c line 237
Quoted 8 lines
drivers/net/can/usb/usb_8dev.c new file +8
-0+ } + + err =usb_8dev_wait_cmd_msg (dev, &dev->cmd_msg_buffer[0 ], +sizeof (struct usb_8dev_cmd_msg ), + &num_bytes_read); +if (err <0 ) { +dev_err (netdev->dev.parent,"no command message answer\n" ); +return err;
mutex?
drivers/net/can/usb/usb_8dev.c line 242
Quoted 5 lines
drivers/net/can/usb/usb_8dev.c new file +5
-0+ } + +mutex_unlock (&dev->usb_8dev_cmd_lock); + +memcpy (in, &dev->cmd_msg_buffer[0 ],sizeof (struct usb_8dev_cmd_msg ));
cmd_msg_buffer is accessed wihtout lock.
Quoted 24 lines
drivers/net/can/usb/usb_8dev.c new file +24
-0+ +if (in->begin !=USB_8DEV_CMD_START || in->end !=USB_8DEV_CMD_END || + num_bytes_read !=16 || in->opt1 !=0 ) +return -EPROTO ; + +return 0 ; +} + +/* Send open command to device */ +static int usb_8dev_cmd_open (struct usb_8dev *dev) +{ +struct can_bittiming *bt = &dev->can.bittiming; +struct usb_8dev_cmd_msg outmsg; +struct usb_8dev_cmd_msg inmsg; +u32 flags =0 ; +u32 beflags; +u16 bebrp; +u32 ctrlmode = dev->can.ctrlmode; + +if (ctrlmode &CAN_CTRLMODE_LOOPBACK ) + flags |=USB_8DEV_LOOPBACK ; +if (ctrlmode &CAN_CTRLMODE_LISTENONLY ) + flags |=USB_8DEV_SILENT ; +if (ctrlmode &CAN_CTRLMODE_ONE_SHOT )
drivers/net/can/usb/usb_8dev.c line 276
Quoted 10 lines
drivers/net/can/usb/usb_8dev.c new file +10
-0+ flags |=USB_8DEV_DISABLE_AUTO_RESTRANS ; + + flags |=USB_8DEV_STATUS_FRAME ; + +memset (&outmsg,0 ,sizeof (struct usb_8dev_cmd_msg )); + outmsg.command =USB_8DEV_OPEN ; + outmsg.opt1 =USB_8DEV_BAUD_MANUAL ; + outmsg.data[0 ] = (bt->prop_seg + bt->phase_seg1); + outmsg.data[1 ] = bt->phase_seg2; + outmsg.data[2 ] = bt->sjw;
But you should not use usb_bulk_msg() to send data which is on the stack, please use you already allocated memory in priv or kmalloc something here.
drivers/net/can/usb/usb_8dev.c line 280
Quoted 4 lines
drivers/net/can/usb/usb_8dev.c new file +4
-0+ +/* BRP */ + bebrp =cpu_to_be16 ((u16 ) bt->brp); +memcpy (&outmsg.data[3 ], &bebrp,sizeof (bebrp));
Are you sure about the endianess? Some data types are BE some are LE?
Quoted 6 lines
drivers/net/can/usb/usb_8dev.c new file +6
-0+ +/* flags */ + beflags =cpu_to_be32 (flags); +memcpy (&outmsg.data[5 ], &beflags,sizeof (beflags)); + +return usb_8dev_send_cmd (dev, &outmsg, &inmsg);
drivers/net/can/usb/usb_8dev.c line 296
Quoted 10 lines
drivers/net/can/usb/usb_8dev.c new file +10
-0+} + +/* Send close command to device */ +static int usb_8dev_cmd_close (struct usb_8dev *dev) +{ +struct usb_8dev_cmd_msg outmsg; +struct usb_8dev_cmd_msg inmsg; + +memset (&outmsg,0 ,sizeof (struct usb_8dev_cmd_msg )); + outmsg.command =USB_8DEV_CLOSE ;
Same here, don't use stack allocated mem for usb_bulk_msg
drivers/net/can/usb/usb_8dev.c line 309
Quoted 13 lines
drivers/net/can/usb/usb_8dev.c new file +13
-0+ +return usb_8dev_send_cmd (dev, &outmsg, &inmsg); +} + +/* Get firmware and hardware version */ +static int usb_8dev_cmd_version (struct usb_8dev *dev,u32 *res) +{ +struct usb_8dev_cmd_msg outmsg; +struct usb_8dev_cmd_msg inmsg; +int err =0 ; + +memset (&outmsg,0 ,sizeof (struct usb_8dev_cmd_msg )); + outmsg.command =USB_8DEV_GET_SOFTW_HARDW_VER ;
dito
Quoted 14 lines
drivers/net/can/usb/usb_8dev.c new file +12
-0+ + err =usb_8dev_send_cmd (dev, &outmsg, &inmsg); +if (err) +return err; + + *res =be32_to_cpu (*(u32 *)inmsg.data); + +return err; +} + +/* Get firmware version */ +static ssize_t show_firmware(struct device *d, struct device_attribute*attr,
drivers/net/can/usb/usb_8dev.c new file +1
-0+ char *buf)
drivers/net/can/usb/usb_8dev.c line 332
Quoted 10 lines
drivers/net/can/usb/usb_8dev.c new file +10
-0+{ +struct usb_8dev_cmd_msg outmsg; +struct usb_8dev_cmd_msg inmsg; +int err =0 ; +u16 result; +struct usb_interface *intf =to_usb_interface (d); +struct usb_8dev *dev =usb_get_intfdata (intf); + +memset (&outmsg,0 ,sizeof (struct usb_8dev_cmd_msg )); + outmsg.command =USB_8DEV_GET_SOFTW_VER ;
dito
drivers/net/can/usb/usb_8dev.c line 338
Quoted 6 lines
drivers/net/can/usb/usb_8dev.c new file +6
-0+ + err =usb_8dev_send_cmd (dev, &outmsg, &inmsg); +if (err) +return -EIO ; + + result =be16_to_cpu (*(u16 *)inmsg.data);
IIRC there is a "p" variant, that can be directly used on pointers.
Quoted 8 lines
drivers/net/can/usb/usb_8dev.c new file +6
-0+ +return sprintf (buf,"%d.%d\n" , (u8)(result>>8 ), (u8 )result); +} + +/* Get hardware version */ +static ssize_t show_hardware(struct device *d, struct device_attribute*attr,
drivers/net/can/usb/usb_8dev.c new file +1
-0+ char *buf)
drivers/net/can/usb/usb_8dev.c line 355
Quoted 10 lines
drivers/net/can/usb/usb_8dev.c new file +10
-0+{ +struct usb_8dev_cmd_msg outmsg; +struct usb_8dev_cmd_msg inmsg; +int err =0 ; +u16 result; +struct usb_interface *intf =to_usb_interface (d); +struct usb_8dev *dev =usb_get_intfdata (intf); + +memset (&outmsg,0 ,sizeof (struct usb_8dev_cmd_msg )); + outmsg.command =USB_8DEV_GET_HARDW_VER ;
Stack-usb_bulk_msg-Problem
Quoted 20 lines
drivers/net/can/usb/usb_8dev.c new file +19
-0+ err =usb_8dev_send_cmd (dev, &outmsg, &inmsg); +if (err) +return -EIO ; + + result =be16_to_cpu (*(u16 *)inmsg.data); + +return sprintf (buf,"%d.%d\n" , (u8)(result>>8 ), (u8 )result); +} + +static DEVICE_ATTR(firmware, S_IRUGO, show_firmware, NULL); +static DEVICE_ATTR(hardware, S_IRUGO, show_hardware, NULL); + +/* +* Set network device mode +* +* Maybe we should leave this function empty, because the device +* set mode variable with open command. +*/ +static int usb_8dev_set_mode(struct net_device *netdev, enum can_modemode)
drivers/net/can/usb/usb_8dev.c line 384
Quoted 9 lines
drivers/net/can/usb/usb_8dev.c new file +9
-0+{ +struct usb_8dev *dev =netdev_priv (netdev); +int err =0 ; + +switch (mode) { +case CAN_MODE_START : + err =usb_8dev_cmd_open (dev); +if (err) +dev_warn (netdev->dev.parent,"couldn't start device" );
Are you sure?....Do you really want to wake the queue?
drivers/net/can/usb/usb_8dev.c line 387
Quoted 3 lines
drivers/net/can/usb/usb_8dev.c new file +3
-0+ +if (netif_queue_stopped (netdev)) +netif_wake_queue (netdev);
No need for the if (netif_queue_stopped(netdev))
Quoted 33 lines
drivers/net/can/usb/usb_8dev.c new file +33
-0+break ; + +default : +return -EOPNOTSUPP ; + } + +return 0 ; +} + +/* +* Empty function: We set bittiming when we start the interface. +* This is a firmware limitation. +*/ +static int usb_8dev_set_bittiming (struct net_device *netdev) +{ +return 0 ; +} + +/* Read data and status frames */ +static void usb_8dev_rx_can_msg (struct usb_8dev *dev, +struct usb_8dev_rx_msg *msg) +{ +struct can_frame *cf; +struct sk_buff *skb; +int i; +struct net_device_stats *stats = &dev->netdev->stats; + +if (msg->type ==USB_8DEV_TYPE_CAN_FRAME ) { + skb =alloc_can_skb (dev->netdev, &cf); +if (!skb) +return ; + + cf->can_id =be32_to_cpu (msg->id);
drivers/net/can/usb/usb_8dev.c line 430
Quoted 10 lines
drivers/net/can/usb/usb_8dev.c new file +10
-0+ cf->can_dlc =get_can_dlc (msg->dlc &0xF ); + +if (msg->flags &USB_8DEV_EXTID ) + cf->can_id |=CAN_EFF_FLAG ; + +if (msg->flags &USB_8DEV_RTR ) + cf->can_id |=CAN_RTR_FLAG ; +else +for (i =0 ; i < cf->can_dlc; i++) + cf->data[i] = msg->data[i];
Use memcpy
Quoted 141 lines
drivers/net/can/usb/usb_8dev.c new file +141
-0+ }else if (msg->type ==USB_8DEV_TYPE_ERROR_FRAME && + msg->flags ==USB_8DEV_ERR_FLAG ) { + +/* +* Error message: +* byte 0: Status +* byte 1: bit 7: Receive Passive +* byte 1: bit 0-6: Receive Error Counter +* byte 2: Transmit Error Counter +* byte 3: Always 0 (maybe reserved for future use) +*/ + +u8 state = msg->data[0 ]; +u8 rxerr = msg->data[1 ] &USB_8DEV_RP_MASK ; +u8 txerr = msg->data[2 ]; +int rx_errors =0 ; +int tx_errors =0 ; + + skb =alloc_can_err_skb (dev->netdev, &cf); +if (!skb) +return ; + + dev->can.can_stats.bus_error++; + +switch (state) { +case USB_8DEV_STATUSMSG_OK : + dev->can.state =CAN_STATE_ERROR_ACTIVE ; + cf->can_id |=CAN_ERR_PROT ; + cf->data[2 ] =CAN_ERR_PROT_ACTIVE ; +break ; +case USB_8DEV_STATUSMSG_BUSOFF : + dev->can.state =CAN_STATE_BUS_OFF ; + cf->can_id |=CAN_ERR_BUSOFF ; +can_bus_off (dev->netdev); +break ; +default : + dev->can.state =CAN_STATE_ERROR_WARNING ; + cf->can_id |=CAN_ERR_PROT |CAN_ERR_BUSERROR ; +break ; + } + +switch (state) { +case USB_8DEV_STATUSMSG_ACK : + cf->can_id |=CAN_ERR_ACK ; + tx_errors =1 ; +break ; +case USB_8DEV_STATUSMSG_CRC : + cf->data[2 ] |=CAN_ERR_PROT_BIT ; + rx_errors =1 ; +break ; +case USB_8DEV_STATUSMSG_BIT0 : + cf->data[2 ] |=CAN_ERR_PROT_BIT0 ; + tx_errors =1 ; +break ; +case USB_8DEV_STATUSMSG_BIT1 : + cf->data[2 ] |=CAN_ERR_PROT_BIT1 ; + tx_errors =1 ; +break ; +case USB_8DEV_STATUSMSG_FORM : + cf->data[2 ] |=CAN_ERR_PROT_FORM ; + rx_errors =1 ; +break ; +case USB_8DEV_STATUSMSG_STUFF : + cf->data[2 ] |=CAN_ERR_PROT_STUFF ; + rx_errors =1 ; +break ; +case USB_8DEV_STATUSMSG_OVERRUN : + cf->can_id |=CAN_ERR_CRTL ; + cf->data[1 ] = (txerr > rxerr) ? +CAN_ERR_CRTL_TX_OVERFLOW : +CAN_ERR_CRTL_RX_OVERFLOW ; + cf->data[2 ] |=CAN_ERR_PROT_OVERLOAD ; + stats->rx_over_errors++; +break ; +case USB_8DEV_STATUSMSG_BUSLIGHT : + cf->can_id |=CAN_ERR_CRTL ; + cf->data[1 ] = (txerr > rxerr) ? +CAN_ERR_CRTL_TX_WARNING : +CAN_ERR_CRTL_RX_WARNING ; + dev->can.can_stats.error_warning++; +break ; +case USB_8DEV_STATUSMSG_BUSHEAVY : + cf->can_id |=CAN_ERR_CRTL ; + cf->data[1 ] = (txerr > rxerr) ? +CAN_ERR_CRTL_TX_PASSIVE : +CAN_ERR_CRTL_RX_PASSIVE ; + dev->can.can_stats.error_passive++; +break ; +default : + cf->data[2 ] |=CAN_ERR_PROT_UNSPEC ; +break ; + } + +if (tx_errors) { + cf->data[2 ] |=CAN_ERR_PROT_TX ; + stats->tx_errors++; + } + +if (rx_errors) + stats->rx_errors++; + + cf->data[6 ] = txerr; + cf->data[7 ] = rxerr; + + dev->bec.txerr = txerr; + dev->bec.rxerr = rxerr; + + }else { +dev_warn (dev->udev->dev.parent,"frame type %d unknown" , + msg->type); +return ; + } + +netif_rx (skb); + + stats->rx_packets++; + stats->rx_bytes += cf->can_dlc; +} + +/* +* Callback for reading data from device +* +* Check urb status, call read function and resubmit urb read operation. +*/ +static void usb_8dev_read_bulk_callback (struct urb *urb) +{ +struct usb_8dev *dev = urb->context; +struct net_device *netdev; +int retval; +int pos =0 ; + + netdev = dev->netdev; + +if (!netif_device_present (netdev)) +return ; + +switch (urb->status) { +case 0 :/* success */ +break ; + +case -ENOENT :
drivers/net/can/usb/usb_8dev.c line 581
Quoted 10 lines
drivers/net/can/usb/usb_8dev.c new file +10
-0+case -ESHUTDOWN : +return ; + +default : +dev_info (netdev->dev.parent,"Rx URB aborted (%d)\n" , + urb->status); + goto resubmit_urb; + } + +while (pos < urb->actual_length) {
please check if the whole msg fits into the received data.
Quoted 49 lines
drivers/net/can/usb/usb_8dev.c new file +49
-0+struct usb_8dev_rx_msg *msg; + + msg = (struct usb_8dev_rx_msg *)(urb->transfer_buffer + pos); + +usb_8dev_rx_can_msg (dev, msg); + + pos +=sizeof (struct usb_8dev_rx_msg ); + +if (pos > urb->actual_length) { +dev_err (dev->udev->dev.parent,"format error\n" ); +break ; + } + } + +resubmit_urb: +usb_fill_bulk_urb (urb, dev->udev,usb_rcvbulkpipe (dev->udev,1 ), + urb->transfer_buffer,RX_BUFFER_SIZE , + usb_8dev_read_bulk_callback, dev); + + retval =usb_submit_urb (urb,GFP_ATOMIC ); + +if (retval == -ENODEV ) +netif_device_detach (netdev); +else if (retval) +dev_err (netdev->dev.parent, +"failed resubmitting read bulk urb: %d\n" , retval); +} + +/* +* Callback handler for write operations +* +* Free allocated buffers, check transmit status and +* calculate statistic. +*/ +static void usb_8dev_write_bulk_callback (struct urb *urb) +{ +struct usb_8dev_tx_urb_context *context = urb->context; +struct usb_8dev *dev; +struct net_device *netdev; + +BUG_ON (!context); + + dev = context->dev; + netdev = dev->netdev; + +/* free up our allocated buffer */ +usb_free_coherent (urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); +
drivers/net/can/usb/usb_8dev.c line 640
Quoted 10 lines
drivers/net/can/usb/usb_8dev.c new file +10
-0+atomic_dec (&dev->active_tx_urbs); + +if (!netif_device_present (netdev)) +return ; + +if (urb->status) +dev_info (netdev->dev.parent,"Tx URB aborted (%d)\n" , + urb->status); + + netdev->trans_start = jiffies;
I think trans_start is't needed anymore.
drivers/net/can/usb/usb_8dev.c line 651
Quoted 11 lines
drivers/net/can/usb/usb_8dev.c new file +11
-0+ + netdev->stats.tx_packets++; + netdev->stats.tx_bytes += context->dlc; + +can_get_echo_skb (netdev, context->echo_index); + +/* Release context */ + context->echo_index =MAX_TX_URBS ; + +if (netif_queue_stopped (netdev)) +netif_wake_queue (netdev);
just call wake_queue
Quoted 42 lines
drivers/net/can/usb/usb_8dev.c new file +42
-0+} + +/* Send data to device */ +static netdev_tx_t usb_8dev_start_xmit (struct sk_buff *skb, +struct net_device *netdev) +{ +struct usb_8dev *dev =netdev_priv (netdev); +struct net_device_stats *stats = &netdev->stats; +struct can_frame *cf = (struct can_frame *) skb->data; +struct usb_8dev_tx_msg *msg; +struct urb *urb; +struct usb_8dev_tx_urb_context *context =NULL ; +u8 *buf; +int i, err; +size_t size =sizeof (struct usb_8dev_tx_msg ); + +if (can_dropped_invalid_skb (netdev, skb)) +return NETDEV_TX_OK ; + +/* create a URB, and a buffer for it, and copy the data to the URB */ + urb =usb_alloc_urb (0 ,GFP_ATOMIC ); +if (!urb) { +dev_err (netdev->dev.parent,"No memory left for URBs\n" ); + goto nomem; + } + + buf =usb_alloc_coherent (dev->udev, size,GFP_ATOMIC , + &urb->transfer_dma); +if (!buf) { +dev_err (netdev->dev.parent,"No memory left for USB buffer\n" ); +usb_free_urb (urb); + goto nomem; + } + +memset (buf,0 , size); + + msg = (struct usb_8dev_tx_msg *)buf; + msg->begin =USB_8DEV_DATA_START ; + msg->flags =0x00 ; + +if (cf->can_id &CAN_RTR_FLAG ) + msg->flags |=USB_8DEV_RTR ;
drivers/net/can/usb/usb_8dev.c line 703
Quoted 10 lines
drivers/net/can/usb/usb_8dev.c new file +10
-0+ +if (cf->can_id &CAN_EFF_FLAG ) + msg->flags |=USB_8DEV_EXTID ; + + msg->id =cpu_to_be32 (cf->can_id &CAN_ERR_MASK ); + + msg->dlc = cf->can_dlc; + +for (i =0 ; i < cf->can_dlc; i++) + msg->data[i] = cf->data[i];
memcpy
Quoted 46 lines
drivers/net/can/usb/usb_8dev.c new file +46
-0+ + msg->end =USB_8DEV_DATA_END ; + + +for (i =0 ; i <MAX_TX_URBS ; i++) { +if (dev->tx_contexts[i].echo_index ==MAX_TX_URBS ) { + context = &dev->tx_contexts[i]; +break ; + } + } + +/* +* May never happen! When this happens we'd more URBs in flight as +* allowed (MAX_TX_URBS). +*/ +if (!context) { +usb_unanchor_urb (urb); +usb_free_coherent (dev->udev, size, buf, urb->transfer_dma); + +dev_warn (netdev->dev.parent,"couldn't find free context" ); + +return NETDEV_TX_BUSY ; + } + + context->dev = dev; + context->echo_index = i; + context->dlc = cf->can_dlc; + +usb_fill_bulk_urb (urb, dev->udev,usb_sndbulkpipe (dev->udev,2 ), buf, + size, usb_8dev_write_bulk_callback, context); + urb->transfer_flags |=URB_NO_TRANSFER_DMA_MAP ; +usb_anchor_urb (urb, &dev->tx_submitted); + +can_put_echo_skb (skb, netdev, context->echo_index); + +atomic_inc (&dev->active_tx_urbs); + + err =usb_submit_urb (urb,GFP_ATOMIC ); +if (unlikely (err)) { +can_free_echo_skb (netdev, context->echo_index); + +usb_unanchor_urb (urb); +usb_free_coherent (dev->udev, size, buf, urb->transfer_dma); +dev_kfree_skb (skb); + +atomic_dec (&dev->active_tx_urbs);
drivers/net/can/usb/usb_8dev.c line 759
Quoted 10 lines
drivers/net/can/usb/usb_8dev.c new file +10
-0+ +if (err == -ENODEV ) { +netif_device_detach (netdev); + }else { +dev_warn (netdev->dev.parent,"failed tx_urb %d\n" , err); + + stats->tx_dropped++; + } + }else { + netdev->trans_start = jiffies;
needed?
Quoted 175 lines
drivers/net/can/usb/usb_8dev.c new file +10
-0+ +/* Slow down tx path */ +if (atomic_read (&dev->active_tx_urbs) >=MAX_TX_URBS || + dev->free_slots <5 ) { +netif_stop_queue (netdev); + } + } + +/* +* Release our reference to this URB, the USB core will eventually free
drivers/net/can/usb/usb_8dev.c new file +164
-0+* it entirely. +*/ +usb_free_urb (urb); + +return NETDEV_TX_OK ; + +nomem: +dev_kfree_skb (skb); + stats->tx_dropped++; + +return NETDEV_TX_OK ; +} + +static int usb_8dev_get_berr_counter (const struct net_device *netdev, +struct can_berr_counter *bec) +{ +struct usb_8dev *dev =netdev_priv (netdev); + + bec->txerr = dev->bec.txerr; + bec->rxerr = dev->bec.rxerr; + +return 0 ; +} + +/* Start USB device */ +static int usb_8dev_start (struct usb_8dev *dev) +{ +struct net_device *netdev = dev->netdev; +int err, i; + + dev->free_slots =15 ;/* initial size */ + +for (i =0 ; i <MAX_RX_URBS ; i++) { +struct urb *urb =NULL ; +u8 *buf =NULL ; + +/* create a URB, and a buffer for it */ + urb =usb_alloc_urb (0 ,GFP_KERNEL ); +if (!urb) { +dev_err (netdev->dev.parent, +"No memory left for URBs\n" ); +return -ENOMEM ; + } + + buf =usb_alloc_coherent (dev->udev,RX_BUFFER_SIZE ,GFP_KERNEL , + &urb->transfer_dma); +if (!buf) { +dev_err (netdev->dev.parent, +"No memory left for USB buffer\n" ); +usb_free_urb (urb); +return -ENOMEM ; + } + +usb_fill_bulk_urb (urb, dev->udev,usb_rcvbulkpipe (dev->udev,1 ), + buf,RX_BUFFER_SIZE , + usb_8dev_read_bulk_callback, dev); + urb->transfer_flags |=URB_NO_TRANSFER_DMA_MAP ; +usb_anchor_urb (urb, &dev->rx_submitted); + + err =usb_submit_urb (urb,GFP_KERNEL ); +if (err) { +if (err == -ENODEV ) +netif_device_detach (dev->netdev); + +usb_unanchor_urb (urb); +usb_free_coherent (dev->udev,RX_BUFFER_SIZE , buf, + urb->transfer_dma); +break ; + } + +/* Drop reference, USB core will take care of freeing it */ +usb_free_urb (urb); + } + +/* Did we submit any URBs */ +if (i ==0 ) { +dev_warn (netdev->dev.parent,"couldn't setup read URBs\n" ); +return err; + } + +/* Warn if we've couldn't transmit all the URBs */ +if (i <MAX_RX_URBS ) +dev_warn (netdev->dev.parent,"rx performance may be slow\n" ); + + err =usb_8dev_cmd_open (dev); +if (err) + goto failed; + + dev->can.state =CAN_STATE_ERROR_ACTIVE ; + +return 0 ; + +failed: +if (err == -ENODEV ) +netif_device_detach (dev->netdev); + +dev_warn (netdev->dev.parent,"couldn't submit control: %d\n" , err); + +return err; +} + +/* Open USB device */ +static int usb_8dev_open (struct net_device *netdev) +{ +struct usb_8dev *dev =netdev_priv (netdev); +int err; + +/* common open */ + err =open_candev (netdev); +if (err) +return err; + +/* finally start device */ + err =usb_8dev_start (dev); +if (err) { +if (err == -ENODEV ) +netif_device_detach (dev->netdev); + +dev_warn (netdev->dev.parent,"couldn't start device: %d\n" , + err); + +close_candev (netdev); + +return err; + } + +netif_start_queue (netdev); + +return 0 ; +} + +static void unlink_all_urbs (struct usb_8dev *dev) +{ +int i; + +usb_kill_anchored_urbs (&dev->rx_submitted); + +usb_kill_anchored_urbs (&dev->tx_submitted); +atomic_set (&dev->active_tx_urbs,0 ); + +for (i =0 ; i <MAX_TX_URBS ; i++) + dev->tx_contexts[i].echo_index =MAX_TX_URBS ; +} + +/* Close USB device */ +static int usb_8dev_close (struct net_device *netdev) +{ +struct usb_8dev *dev =netdev_priv (netdev); +int err =0 ; + +/* Send CLOSE command to CAN controller */ + err =usb_8dev_cmd_close (dev); +if (err) +dev_warn (netdev->dev.parent,"couldn't stop device" ); + + dev->can.state =CAN_STATE_STOPPED ; + +/* Stop polling */ +unlink_all_urbs (dev); + +netif_stop_queue (netdev); + +close_candev (netdev); +
drivers/net/can/usb/usb_8dev.c line 943
Quoted 10 lines
drivers/net/can/usb/usb_8dev.c new file +10
-0+return err; +} + +static const struct net_device_ops usb_8dev_netdev_ops = { + .ndo_open = usb_8dev_open, + .ndo_stop = usb_8dev_close, + .ndo_start_xmit = usb_8dev_start_xmit, +}; + +static struct can_bittiming_const usb_8dev_bittiming_const = {
const
Quoted 146 lines
drivers/net/can/usb/usb_8dev.c new file +109
-0+ .name = "usb_8dev", + .tseg1_min = USB_8DEV_TSEG1_MIN, + .tseg1_max = USB_8DEV_TSEG1_MAX, + .tseg2_min = USB_8DEV_TSEG2_MIN, + .tseg2_max = USB_8DEV_TSEG2_MAX, + .sjw_max = USB_8DEV_SJW_MAX, + .brp_min = USB_8DEV_BRP_MIN, + .brp_max = USB_8DEV_BRP_MAX, + .brp_inc = USB_8DEV_BRP_INC, +}; + +/* +* Probe USB device +* +* Check device and firmware. +* Set supported modes and bittiming constants. +* Allocate some memory. +*/ +static int usb_8dev_probe (struct usb_interface *intf, +const struct usb_device_id *id) +{ +struct net_device *netdev; +struct usb_8dev *dev; +int i, err = -ENOMEM ; +u32 version; +char buf[18 ]; +struct usb_device *usbdev =interface_to_usbdev (intf); + +/* product id looks strange, better we also check iProdukt string */ +if (usb_string (usbdev, usbdev->descriptor.iProduct, buf, +sizeof (buf)) >0 &&strcmp (buf,"USB2CAN converter" )) { +dev_info (&usbdev->dev,"ignoring: not an USB2CAN converter\n" ); +return -ENODEV ; + } + + netdev =alloc_candev (sizeof (struct usb_8dev ),MAX_TX_URBS ); +if (!netdev) { +dev_err (&intf->dev,"Couldn't alloc candev\n" ); +return -ENOMEM ; + } + + dev =netdev_priv (netdev); + + dev->udev = usbdev; + dev->netdev = netdev; + + dev->can.state =CAN_STATE_STOPPED ; + dev->can.clock.freq =USB_8DEV_ABP_CLOCK ; + dev->can.bittiming_const = &usb_8dev_bittiming_const; + dev->can.do_set_bittiming = usb_8dev_set_bittiming; + dev->can.do_set_mode = usb_8dev_set_mode; + dev->can.do_get_berr_counter = usb_8dev_get_berr_counter; + dev->can.ctrlmode_supported =CAN_CTRLMODE_LOOPBACK | +CAN_CTRLMODE_LISTENONLY | +CAN_CTRLMODE_ONE_SHOT ; + + netdev->netdev_ops = &usb_8dev_netdev_ops; + + netdev->flags |=IFF_ECHO ;/* we support local echo */ + +init_usb_anchor (&dev->rx_submitted); + +init_usb_anchor (&dev->tx_submitted); +atomic_set (&dev->active_tx_urbs,0 ); + +for (i =0 ; i <MAX_TX_URBS ; i++) + dev->tx_contexts[i].echo_index =MAX_TX_URBS ; + + dev->cmd_msg_buffer =kzalloc (sizeof (struct usb_8dev_cmd_msg ), +GFP_KERNEL ); +if (!dev->cmd_msg_buffer) { +dev_err (&intf->dev,"Couldn't alloc Tx buffer\n" ); + goto cleanup_candev; + } + +usb_set_intfdata (intf, dev); + +SET_NETDEV_DEV (netdev, &intf->dev); + +mutex_init (&dev->usb_8dev_cmd_lock); + + err =usb_8dev_cmd_version (dev, &version); +if (err) { +dev_err (netdev->dev.parent,"can't get firmware version\n" ); + goto cleanup_cmd_msg_buffer; + }else { +dev_info (netdev->dev.parent, +"firmware: %d.%d, hardware: %d.%d\n" , + (version>>24 ) &0xff , (version>>16 ) &0xff , + (version>>8 ) &0xff , version &0xff ); + } + + err =register_candev (netdev); +if (err) { +dev_err (netdev->dev.parent, +"couldn't register CAN device: %d\n" , err); + goto cleanup_cmd_msg_buffer; + } + +if (device_create_file (&intf->dev, &dev_attr_firmware)) +dev_err (&intf->dev, +"Couldn't create device file for firmware\n" ); + +if (device_create_file (&intf->dev, &dev_attr_hardware)) +dev_err (&intf->dev, +"Couldn't create device file for hardware\n" ); + +/* let the user know what node this device is now attached to */ + dev_info(netdev->dev.parent, "device registered as %s\n",
netdev->name);drivers/net/can/usb/usb_8dev.c new file +36
-0+return 0 ; + +cleanup_cmd_msg_buffer: +kfree (dev->cmd_msg_buffer); + +cleanup_candev: +free_candev (netdev); + +return err; + +} + +/* Called by the usb core when driver is unloaded or device is removed */ +static void usb_8dev_disconnect (struct usb_interface *intf) +{ +struct usb_8dev *dev =usb_get_intfdata (intf); + +device_remove_file (&intf->dev, &dev_attr_firmware); +device_remove_file (&intf->dev, &dev_attr_hardware); + +usb_set_intfdata (intf,NULL ); + +if (dev) { +dev_info (&intf->dev,"disconnect %s\n" , dev->netdev->name); + +unregister_netdev (dev->netdev); +free_candev (dev->netdev); + +unlink_all_urbs (dev); + } + +} + +static struct usb_driver usb_8dev_driver = { + .name ="usb_8dev" , + .probe = usb_8dev_probe,
drivers/net/can/usb/usb_8dev.c line 1098
Quoted 10 lines
drivers/net/can/usb/usb_8dev.c new file +10
-0+ .disconnect = usb_8dev_disconnect, + .id_table = usb_8dev_table, +}; + +module_usb_driver (usb_8dev_driver); + +MODULE_AUTHOR ("Bernd Krumboeck <[email protected]>" ); +MODULE_DESCRIPTION ("CAN driver for UAB 8 devices USB2CAN interfaces" ); +MODULE_LICENSE ("GPL v2" ); +
Please remove trailing empty line
Marc
Signature · 4 lines
Pengutronix e.K. | Marc Kleine-Budde | Industrial Linux Solutions | Phone: +49-231-2826-924 | Vertretung West/Dortmund | Fax: +49-5121-206917-5555 | Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
Hi Marc!
Quoted 22 lines
Quoted 22 lines
drivers/net/can/usb/usb_8dev.c new file +22
-0+/* Send open command to device */ +static int usb_8dev_cmd_open (struct usb_8dev *dev) +{ +struct can_bittiming *bt = &dev->can.bittiming; +struct usb_8dev_cmd_msg outmsg; +struct usb_8dev_cmd_msg inmsg; +u32 flags =0 ; +u32 beflags; +u16 bebrp; +u32 ctrlmode = dev->can.ctrlmode; + +if (ctrlmode &CAN_CTRLMODE_LOOPBACK ) + flags |=USB_8DEV_LOOPBACK ; +if (ctrlmode &CAN_CTRLMODE_LISTENONLY ) + flags |=USB_8DEV_SILENT ; +if (ctrlmode &CAN_CTRLMODE_ONE_SHOT ) + flags |=USB_8DEV_DISABLE_AUTO_RESTRANS ; + + flags |=USB_8DEV_STATUS_FRAME ; + +memset (&outmsg,0 ,sizeof (struct usb_8dev_cmd_msg )); + outmsg.command =USB_8DEV_OPEN ;
Quoted 8 lines
drivers/net/can/usb/usb_8dev.c line 276
Quoted 4 lines
drivers/net/can/usb/usb_8dev.c new file +4
-0+ outmsg.opt1 =USB_8DEV_BAUD_MANUAL ; + outmsg.data[0 ] = (bt->prop_seg + bt->phase_seg1); + outmsg.data[1 ] = bt->phase_seg2; + outmsg.data[2 ] = bt->sjw;But you should not use
usb_bulk_msg()to send data which is on the stack, please use you already allocated memory in priv or kmalloc something here.
The function usb_8dev_send_cmd copies the data to dev->cmd_msg_buffer (allocated with kzalloc, GFP_KERNEL).
Quoted 7 lines
drivers/net/can/usb/usb_8dev.c line 280
Quoted 5 lines
drivers/net/can/usb/usb_8dev.c new file +4
-0+ +/* BRP */ + bebrp =cpu_to_be16 ((u16 ) bt->brp); +memcpy (&outmsg.data[3 ], &bebrp,sizeof (bebrp));Are you sure about the endianess? Some data types are BE some are LE?
Where is LE used?
Quoted 11 lines
Quoted 11 lines
drivers/net/can/usb/usb_8dev.c new file +10
-0+ +/* flags */ + beflags =cpu_to_be32 (flags); +memcpy (&outmsg.data[5 ], &beflags,sizeof (beflags)); + +return usb_8dev_send_cmd (dev, &outmsg, &inmsg); +} + +/* Send close command to device */ +static int usb_8dev_cmd_close (struct usb_8dev *dev)
Quoted 8 lines
drivers/net/can/usb/usb_8dev.c line 296
Quoted 6 lines
drivers/net/can/usb/usb_8dev.c new file +6
-0+{ +struct usb_8dev_cmd_msg outmsg; +struct usb_8dev_cmd_msg inmsg; + +memset (&outmsg,0 ,sizeof (struct usb_8dev_cmd_msg )); + outmsg.command =USB_8DEV_CLOSE ;Same here, don't use stack allocated mem for
usb_bulk_msg
All command functions use usb_8dev_send_cmd.
Quoted 3 lines
Are you sure?....Do you really want to wake the queue?
No, I've removed.
Quoted 3 lines
needed?
I don't know. -> removed.
Thanks for your comments.
best regards,
Bernd
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 34 lines · On 12/03/2012 09:42 PM, [email protected] wrote:
Hi Marc!
Quoted 22 lines
Quoted 22 lines
drivers/net/can/usb/usb_8dev.c new file +22
-0+/* Send open command to device */ +static int usb_8dev_cmd_open (struct usb_8dev *dev) +{ +struct can_bittiming *bt = &dev->can.bittiming; +struct usb_8dev_cmd_msg outmsg; +struct usb_8dev_cmd_msg inmsg; +u32 flags =0 ; +u32 beflags; +u16 bebrp; +u32 ctrlmode = dev->can.ctrlmode; + +if (ctrlmode &CAN_CTRLMODE_LOOPBACK ) + flags |=USB_8DEV_LOOPBACK ; +if (ctrlmode &CAN_CTRLMODE_LISTENONLY ) + flags |=USB_8DEV_SILENT ; +if (ctrlmode &CAN_CTRLMODE_ONE_SHOT ) + flags |=USB_8DEV_DISABLE_AUTO_RESTRANS ; + + flags |=USB_8DEV_STATUS_FRAME ; + +memset (&outmsg,0 ,sizeof (struct usb_8dev_cmd_msg )); + outmsg.command =USB_8DEV_OPEN ;Quoted 8 lines
drivers/net/can/usb/usb_8dev.c line 276
Quoted 4 lines
drivers/net/can/usb/usb_8dev.c new file +4
-0+ outmsg.opt1 =USB_8DEV_BAUD_MANUAL ; + outmsg.data[0 ] = (bt->prop_seg + bt->phase_seg1); + outmsg.data[1 ] = bt->phase_seg2; + outmsg.data[2 ] = bt->sjw;But you should not use
usb_bulk_msg()to send data which is on the stack, please use you already allocated memory in priv or kmalloc something here.
Quoted 2 lines
The function
usb_8dev_send_cmdcopies the data todev->cmd_msg_buffer(allocated with kzalloc,GFP_KERNEL).
Okay, then you might want to set outmsg via C99 initializers.
Quoted 8 lines
Quoted 6 lines
drivers/net/can/usb/usb_8dev.c line 280
Quoted 4 lines
drivers/net/can/usb/usb_8dev.c new file +4
-0+ +/* BRP */ + bebrp =cpu_to_be16 ((u16 ) bt->brp); +memcpy (&outmsg.data[3 ], &bebrp,sizeof (bebrp));Are you sure about the endianess? Some data types are BE some are LE?
Where is LE used?
Opps, yeah right. only BE.
Marc
Signature · 4 lines
Pengutronix e.K. | Marc Kleine-Budde | Industrial Linux Solutions | Phone: +49-231-2826-924 | Vertretung West/Dortmund | Fax: +49-5121-206917-5555 | Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
Marc Kleine-Budde
maintainerHello,
please leave the mailinglist on Cc
Quoted 9 lines · On 12/03/2012 09:47 PM, [email protected] wrote:
Quoted 7 lines
Quoted 4 lines
Gives following error:
usb_8dev.c:979:27: warning: assignment discards ‘const’ qualifier from pointer target type [enabled by default]which kernel are you using?
Linux debian 3.2.0-4-amd64 #1 SMP Debian 3.2.32-1
x86_64GNU/Linux
The struct definition has been changed with commit:
194b9a4 can: mark bittiming_const pointer in struct can_priv as const
which was first released with v3.6-rc1.
Please develop and send patches against David Miller's net-next/master, or even better, linux-can-next/master.
Marc
Signature · 4 lines
Pengutronix e.K. | Marc Kleine-Budde | Industrial Linux Solutions | Phone: +49-231-2826-924 | Vertretung West/Dortmund | Fax: +49-5121-206917-5555 | Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
A message that is not in the archive (sent off-list or not yet received): afcf5a63bd9cbc8324d8d6ebdda93b07.squirrel@webmail.universalnet.at
Marc Kleine-Budde
maintainerHello,
please leave the mailinglist on Cc!
Quoted 4 lines · Bernd Krumböck
I use David Miller's net-next/master for my patches, but for tests I also compile it against my debian kernel.
Sorry for the noise...
No problem.
Marc
Signature · 4 lines
Pengutronix e.K. | Marc Kleine-Budde | Industrial Linux Solutions | Phone: +49-231-2826-924 | Vertretung West/Dortmund | Fax: +49-5121-206917-5555 | Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
Quoted 4 lines
Hello,
please leave the mailinglist on Cc!
Sorry, this was not my intention.
I simple pressed the wrong button. ;-)
Bernd