diff options
author | Bernd Krumboeck <b.krumboeck@gmail.com> | 2013-01-19 01:30:45 -0500 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2013-01-26 10:58:58 -0500 |
commit | 0024d8ad1639e32d717445c69ca813fd19c2a91c (patch) | |
tree | 4761a3b7409cdb7be0f03d17b4868ee1d3446db1 /drivers/net/can | |
parent | af5fd6da40412002bd2ba3293fd11fe862e15d80 (diff) |
can: usb_8dev: Add support for USB2CAN interface from 8 devices
Add device driver for USB2CAN interface from "8 devices" (http://www.8devices.com).
changes since v10:
* small cleanups
changes since v9:
* fixed syslog messages
* fixed crc error number
* increased MAX_RX_URBS and MAX_TX_URBS
changes since v8:
* remove all sysfs files
changes since v7:
* add sysfs documentation
* fix minor styling issue
* fixed can state for passive mode
* changed handling for crc errors
changes since v6:
* changed some variable types to big endian equivalent
* small cleanups
changes since v5:
* unlock mutex on error
changes since v4:
* removed FSF address
* renamed struct usb_8dev
* removed unused variable free_slots
* replaced some _to_cpu functions with pointer equivalent
* fix return value for usb_8dev_set_mode
* handle can errors with separate function
* fix overrun error handling
* rewrite error handling for usb_8dev_start_xmit
* fix urb submit in usb_8dev_start
* various small fixes
Acked-by: Wolfgang Grandegger <wg@grandegger.com>
Tested-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Bernd Krumboeck <krumboeck@universalnet.at>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'drivers/net/can')
-rw-r--r-- | drivers/net/can/usb/Kconfig | 6 | ||||
-rw-r--r-- | drivers/net/can/usb/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/can/usb/usb_8dev.c | 1022 |
3 files changed, 1029 insertions, 0 deletions
diff --git a/drivers/net/can/usb/Kconfig b/drivers/net/can/usb/Kconfig index acba33d1e2b0..fc96a3d83ebe 100644 --- a/drivers/net/can/usb/Kconfig +++ b/drivers/net/can/usb/Kconfig | |||
@@ -48,4 +48,10 @@ config CAN_PEAK_USB | |||
48 | This driver supports the PCAN-USB and PCAN-USB Pro adapters | 48 | This driver supports the PCAN-USB and PCAN-USB Pro adapters |
49 | from PEAK-System Technik (http://www.peak-system.com). | 49 | from PEAK-System Technik (http://www.peak-system.com). |
50 | 50 | ||
51 | config CAN_8DEV_USB | ||
52 | tristate "8 devices USB2CAN interface" | ||
53 | ---help--- | ||
54 | This driver supports the USB2CAN interface | ||
55 | from 8 devices (http://www.8devices.com). | ||
56 | |||
51 | endmenu | 57 | endmenu |
diff --git a/drivers/net/can/usb/Makefile b/drivers/net/can/usb/Makefile index 80a2ee41fd61..becef460a91a 100644 --- a/drivers/net/can/usb/Makefile +++ b/drivers/net/can/usb/Makefile | |||
@@ -6,5 +6,6 @@ obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o | |||
6 | obj-$(CONFIG_CAN_ESD_USB2) += esd_usb2.o | 6 | obj-$(CONFIG_CAN_ESD_USB2) += esd_usb2.o |
7 | obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb.o | 7 | obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb.o |
8 | obj-$(CONFIG_CAN_PEAK_USB) += peak_usb/ | 8 | obj-$(CONFIG_CAN_PEAK_USB) += peak_usb/ |
9 | obj-$(CONFIG_CAN_8DEV_USB) += usb_8dev.o | ||
9 | 10 | ||
10 | ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG | 11 | ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG |
diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c new file mode 100644 index 000000000000..a9e73fa4ad0f --- /dev/null +++ b/drivers/net/can/usb/usb_8dev.c | |||
@@ -0,0 +1,1022 @@ | |||
1 | /* | ||
2 | * CAN driver for "8 devices" USB2CAN converter | ||
3 | * | ||
4 | * Copyright (C) 2012 Bernd Krumboeck (krumboeck@universalnet.at) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published | ||
8 | * by the Free Software Foundation; version 2 of the License. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along | ||
16 | * with this program. | ||
17 | * | ||
18 | * This driver is inspired by the 3.2.0 version of drivers/net/can/usb/ems_usb.c | ||
19 | * and drivers/net/can/usb/esd_usb2.c | ||
20 | * | ||
21 | * Many thanks to Gerhard Bertelsmann (info@gerhard-bertelsmann.de) | ||
22 | * for testing and fixing this driver. Also many thanks to "8 devices", | ||
23 | * who were very cooperative and answered my questions. | ||
24 | */ | ||
25 | |||
26 | #include <linux/init.h> | ||
27 | #include <linux/signal.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/netdevice.h> | ||
31 | #include <linux/usb.h> | ||
32 | |||
33 | #include <linux/can.h> | ||
34 | #include <linux/can/dev.h> | ||
35 | #include <linux/can/error.h> | ||
36 | |||
37 | /* driver constants */ | ||
38 | #define MAX_RX_URBS 20 | ||
39 | #define MAX_TX_URBS 20 | ||
40 | #define RX_BUFFER_SIZE 64 | ||
41 | |||
42 | /* vendor and product id */ | ||
43 | #define USB_8DEV_VENDOR_ID 0x0483 | ||
44 | #define USB_8DEV_PRODUCT_ID 0x1234 | ||
45 | |||
46 | /* endpoints */ | ||
47 | enum usb_8dev_endpoint { | ||
48 | USB_8DEV_ENDP_DATA_RX = 1, | ||
49 | USB_8DEV_ENDP_DATA_TX, | ||
50 | USB_8DEV_ENDP_CMD_RX, | ||
51 | USB_8DEV_ENDP_CMD_TX | ||
52 | }; | ||
53 | |||
54 | /* device CAN clock */ | ||
55 | #define USB_8DEV_ABP_CLOCK 32000000 | ||
56 | |||
57 | /* setup flags */ | ||
58 | #define USB_8DEV_SILENT 0x01 | ||
59 | #define USB_8DEV_LOOPBACK 0x02 | ||
60 | #define USB_8DEV_DISABLE_AUTO_RESTRANS 0x04 | ||
61 | #define USB_8DEV_STATUS_FRAME 0x08 | ||
62 | |||
63 | /* commands */ | ||
64 | enum usb_8dev_cmd { | ||
65 | USB_8DEV_RESET = 1, | ||
66 | USB_8DEV_OPEN, | ||
67 | USB_8DEV_CLOSE, | ||
68 | USB_8DEV_SET_SPEED, | ||
69 | USB_8DEV_SET_MASK_FILTER, | ||
70 | USB_8DEV_GET_STATUS, | ||
71 | USB_8DEV_GET_STATISTICS, | ||
72 | USB_8DEV_GET_SERIAL, | ||
73 | USB_8DEV_GET_SOFTW_VER, | ||
74 | USB_8DEV_GET_HARDW_VER, | ||
75 | USB_8DEV_RESET_TIMESTAMP, | ||
76 | USB_8DEV_GET_SOFTW_HARDW_VER | ||
77 | }; | ||
78 | |||
79 | /* command options */ | ||
80 | #define USB_8DEV_BAUD_MANUAL 0x09 | ||
81 | #define USB_8DEV_CMD_START 0x11 | ||
82 | #define USB_8DEV_CMD_END 0x22 | ||
83 | |||
84 | #define USB_8DEV_CMD_SUCCESS 0 | ||
85 | #define USB_8DEV_CMD_ERROR 255 | ||
86 | |||
87 | #define USB_8DEV_CMD_TIMEOUT 1000 | ||
88 | |||
89 | /* frames */ | ||
90 | #define USB_8DEV_DATA_START 0x55 | ||
91 | #define USB_8DEV_DATA_END 0xAA | ||
92 | |||
93 | #define USB_8DEV_TYPE_CAN_FRAME 0 | ||
94 | #define USB_8DEV_TYPE_ERROR_FRAME 3 | ||
95 | |||
96 | #define USB_8DEV_EXTID 0x01 | ||
97 | #define USB_8DEV_RTR 0x02 | ||
98 | #define USB_8DEV_ERR_FLAG 0x04 | ||
99 | |||
100 | /* status */ | ||
101 | #define USB_8DEV_STATUSMSG_OK 0x00 /* Normal condition. */ | ||
102 | #define USB_8DEV_STATUSMSG_OVERRUN 0x01 /* Overrun occured when sending */ | ||
103 | #define USB_8DEV_STATUSMSG_BUSLIGHT 0x02 /* Error counter has reached 96 */ | ||
104 | #define USB_8DEV_STATUSMSG_BUSHEAVY 0x03 /* Error count. has reached 128 */ | ||
105 | #define USB_8DEV_STATUSMSG_BUSOFF 0x04 /* Device is in BUSOFF */ | ||
106 | #define USB_8DEV_STATUSMSG_STUFF 0x20 /* Stuff Error */ | ||
107 | #define USB_8DEV_STATUSMSG_FORM 0x21 /* Form Error */ | ||
108 | #define USB_8DEV_STATUSMSG_ACK 0x23 /* Ack Error */ | ||
109 | #define USB_8DEV_STATUSMSG_BIT0 0x24 /* Bit1 Error */ | ||
110 | #define USB_8DEV_STATUSMSG_BIT1 0x25 /* Bit0 Error */ | ||
111 | #define USB_8DEV_STATUSMSG_CRC 0x27 /* CRC Error */ | ||
112 | |||
113 | #define USB_8DEV_RP_MASK 0x7F /* Mask for Receive Error Bit */ | ||
114 | |||
115 | |||
116 | /* table of devices that work with this driver */ | ||
117 | static const struct usb_device_id usb_8dev_table[] = { | ||
118 | { USB_DEVICE(USB_8DEV_VENDOR_ID, USB_8DEV_PRODUCT_ID) }, | ||
119 | { } /* Terminating entry */ | ||
120 | }; | ||
121 | |||
122 | MODULE_DEVICE_TABLE(usb, usb_8dev_table); | ||
123 | |||
124 | struct usb_8dev_tx_urb_context { | ||
125 | struct usb_8dev_priv *priv; | ||
126 | |||
127 | u32 echo_index; | ||
128 | u8 dlc; | ||
129 | }; | ||
130 | |||
131 | /* Structure to hold all of our device specific stuff */ | ||
132 | struct usb_8dev_priv { | ||
133 | struct can_priv can; /* must be the first member */ | ||
134 | |||
135 | struct sk_buff *echo_skb[MAX_TX_URBS]; | ||
136 | |||
137 | struct usb_device *udev; | ||
138 | struct net_device *netdev; | ||
139 | |||
140 | atomic_t active_tx_urbs; | ||
141 | struct usb_anchor tx_submitted; | ||
142 | struct usb_8dev_tx_urb_context tx_contexts[MAX_TX_URBS]; | ||
143 | |||
144 | struct usb_anchor rx_submitted; | ||
145 | |||
146 | struct can_berr_counter bec; | ||
147 | |||
148 | u8 *cmd_msg_buffer; | ||
149 | |||
150 | struct mutex usb_8dev_cmd_lock; | ||
151 | |||
152 | }; | ||
153 | |||
154 | /* tx frame */ | ||
155 | struct __packed usb_8dev_tx_msg { | ||
156 | u8 begin; | ||
157 | u8 flags; /* RTR and EXT_ID flag */ | ||
158 | __be32 id; /* upper 3 bits not used */ | ||
159 | u8 dlc; /* data length code 0-8 bytes */ | ||
160 | u8 data[8]; /* 64-bit data */ | ||
161 | u8 end; | ||
162 | }; | ||
163 | |||
164 | /* rx frame */ | ||
165 | struct __packed usb_8dev_rx_msg { | ||
166 | u8 begin; | ||
167 | u8 type; /* frame type */ | ||
168 | u8 flags; /* RTR and EXT_ID flag */ | ||
169 | __be32 id; /* upper 3 bits not used */ | ||
170 | u8 dlc; /* data length code 0-8 bytes */ | ||
171 | u8 data[8]; /* 64-bit data */ | ||
172 | __be32 timestamp; /* 32-bit timestamp */ | ||
173 | u8 end; | ||
174 | }; | ||
175 | |||
176 | /* command frame */ | ||
177 | struct __packed usb_8dev_cmd_msg { | ||
178 | u8 begin; | ||
179 | u8 channel; /* unkown - always 0 */ | ||
180 | u8 command; /* command to execute */ | ||
181 | u8 opt1; /* optional parameter / return value */ | ||
182 | u8 opt2; /* optional parameter 2 */ | ||
183 | u8 data[10]; /* optional parameter and data */ | ||
184 | u8 end; | ||
185 | }; | ||
186 | |||
187 | static int usb_8dev_send_cmd_msg(struct usb_8dev_priv *priv, u8 *msg, int size) | ||
188 | { | ||
189 | int actual_length; | ||
190 | |||
191 | return usb_bulk_msg(priv->udev, | ||
192 | usb_sndbulkpipe(priv->udev, USB_8DEV_ENDP_CMD_TX), | ||
193 | msg, size, &actual_length, USB_8DEV_CMD_TIMEOUT); | ||
194 | } | ||
195 | |||
196 | static int usb_8dev_wait_cmd_msg(struct usb_8dev_priv *priv, u8 *msg, int size, | ||
197 | int *actual_length) | ||
198 | { | ||
199 | return usb_bulk_msg(priv->udev, | ||
200 | usb_rcvbulkpipe(priv->udev, USB_8DEV_ENDP_CMD_RX), | ||
201 | msg, size, actual_length, USB_8DEV_CMD_TIMEOUT); | ||
202 | } | ||
203 | |||
204 | /* Send command to device and receive result. | ||
205 | * Command was successful when opt1 = 0. | ||
206 | */ | ||
207 | static int usb_8dev_send_cmd(struct usb_8dev_priv *priv, | ||
208 | struct usb_8dev_cmd_msg *out, | ||
209 | struct usb_8dev_cmd_msg *in) | ||
210 | { | ||
211 | int err; | ||
212 | int num_bytes_read; | ||
213 | struct net_device *netdev; | ||
214 | |||
215 | netdev = priv->netdev; | ||
216 | |||
217 | out->begin = USB_8DEV_CMD_START; | ||
218 | out->end = USB_8DEV_CMD_END; | ||
219 | |||
220 | mutex_lock(&priv->usb_8dev_cmd_lock); | ||
221 | |||
222 | memcpy(priv->cmd_msg_buffer, out, | ||
223 | sizeof(struct usb_8dev_cmd_msg)); | ||
224 | |||
225 | err = usb_8dev_send_cmd_msg(priv, priv->cmd_msg_buffer, | ||
226 | sizeof(struct usb_8dev_cmd_msg)); | ||
227 | if (err < 0) { | ||
228 | netdev_err(netdev, "sending command message failed\n"); | ||
229 | goto failed; | ||
230 | } | ||
231 | |||
232 | err = usb_8dev_wait_cmd_msg(priv, priv->cmd_msg_buffer, | ||
233 | sizeof(struct usb_8dev_cmd_msg), | ||
234 | &num_bytes_read); | ||
235 | if (err < 0) { | ||
236 | netdev_err(netdev, "no command message answer\n"); | ||
237 | goto failed; | ||
238 | } | ||
239 | |||
240 | memcpy(in, priv->cmd_msg_buffer, sizeof(struct usb_8dev_cmd_msg)); | ||
241 | |||
242 | if (in->begin != USB_8DEV_CMD_START || in->end != USB_8DEV_CMD_END || | ||
243 | num_bytes_read != 16 || in->opt1 != 0) | ||
244 | err = -EPROTO; | ||
245 | |||
246 | failed: | ||
247 | mutex_unlock(&priv->usb_8dev_cmd_lock); | ||
248 | return err; | ||
249 | } | ||
250 | |||
251 | /* Send open command to device */ | ||
252 | static int usb_8dev_cmd_open(struct usb_8dev_priv *priv) | ||
253 | { | ||
254 | struct can_bittiming *bt = &priv->can.bittiming; | ||
255 | struct usb_8dev_cmd_msg outmsg; | ||
256 | struct usb_8dev_cmd_msg inmsg; | ||
257 | u32 ctrlmode = priv->can.ctrlmode; | ||
258 | u32 flags = USB_8DEV_STATUS_FRAME; | ||
259 | __be32 beflags; | ||
260 | __be16 bebrp; | ||
261 | |||
262 | memset(&outmsg, 0, sizeof(outmsg)); | ||
263 | outmsg.command = USB_8DEV_OPEN; | ||
264 | outmsg.opt1 = USB_8DEV_BAUD_MANUAL; | ||
265 | outmsg.data[0] = bt->prop_seg + bt->phase_seg1; | ||
266 | outmsg.data[1] = bt->phase_seg2; | ||
267 | outmsg.data[2] = bt->sjw; | ||
268 | |||
269 | /* BRP */ | ||
270 | bebrp = cpu_to_be16((u16)bt->brp); | ||
271 | memcpy(&outmsg.data[3], &bebrp, sizeof(bebrp)); | ||
272 | |||
273 | /* flags */ | ||
274 | if (ctrlmode & CAN_CTRLMODE_LOOPBACK) | ||
275 | flags |= USB_8DEV_LOOPBACK; | ||
276 | if (ctrlmode & CAN_CTRLMODE_LISTENONLY) | ||
277 | flags |= USB_8DEV_SILENT; | ||
278 | if (ctrlmode & CAN_CTRLMODE_ONE_SHOT) | ||
279 | flags |= USB_8DEV_DISABLE_AUTO_RESTRANS; | ||
280 | |||
281 | beflags = cpu_to_be32(flags); | ||
282 | memcpy(&outmsg.data[5], &beflags, sizeof(beflags)); | ||
283 | |||
284 | return usb_8dev_send_cmd(priv, &outmsg, &inmsg); | ||
285 | } | ||
286 | |||
287 | /* Send close command to device */ | ||
288 | static int usb_8dev_cmd_close(struct usb_8dev_priv *priv) | ||
289 | { | ||
290 | struct usb_8dev_cmd_msg inmsg; | ||
291 | struct usb_8dev_cmd_msg outmsg = { | ||
292 | .channel = 0, | ||
293 | .command = USB_8DEV_CLOSE, | ||
294 | .opt1 = 0, | ||
295 | .opt2 = 0 | ||
296 | }; | ||
297 | |||
298 | return usb_8dev_send_cmd(priv, &outmsg, &inmsg); | ||
299 | } | ||
300 | |||
301 | /* Get firmware and hardware version */ | ||
302 | static int usb_8dev_cmd_version(struct usb_8dev_priv *priv, u32 *res) | ||
303 | { | ||
304 | struct usb_8dev_cmd_msg inmsg; | ||
305 | struct usb_8dev_cmd_msg outmsg = { | ||
306 | .channel = 0, | ||
307 | .command = USB_8DEV_GET_SOFTW_HARDW_VER, | ||
308 | .opt1 = 0, | ||
309 | .opt2 = 0 | ||
310 | }; | ||
311 | |||
312 | int err = usb_8dev_send_cmd(priv, &outmsg, &inmsg); | ||
313 | if (err) | ||
314 | return err; | ||
315 | |||
316 | *res = be32_to_cpup((__be32 *)inmsg.data); | ||
317 | |||
318 | return err; | ||
319 | } | ||
320 | |||
321 | /* Set network device mode | ||
322 | * | ||
323 | * Maybe we should leave this function empty, because the device | ||
324 | * set mode variable with open command. | ||
325 | */ | ||
326 | static int usb_8dev_set_mode(struct net_device *netdev, enum can_mode mode) | ||
327 | { | ||
328 | struct usb_8dev_priv *priv = netdev_priv(netdev); | ||
329 | int err = 0; | ||
330 | |||
331 | switch (mode) { | ||
332 | case CAN_MODE_START: | ||
333 | err = usb_8dev_cmd_open(priv); | ||
334 | if (err) | ||
335 | netdev_warn(netdev, "couldn't start device"); | ||
336 | break; | ||
337 | |||
338 | default: | ||
339 | return -EOPNOTSUPP; | ||
340 | } | ||
341 | |||
342 | return err; | ||
343 | } | ||
344 | |||
345 | /* Read error/status frames */ | ||
346 | static void usb_8dev_rx_err_msg(struct usb_8dev_priv *priv, | ||
347 | struct usb_8dev_rx_msg *msg) | ||
348 | { | ||
349 | struct can_frame *cf; | ||
350 | struct sk_buff *skb; | ||
351 | struct net_device_stats *stats = &priv->netdev->stats; | ||
352 | |||
353 | /* Error message: | ||
354 | * byte 0: Status | ||
355 | * byte 1: bit 7: Receive Passive | ||
356 | * byte 1: bit 0-6: Receive Error Counter | ||
357 | * byte 2: Transmit Error Counter | ||
358 | * byte 3: Always 0 (maybe reserved for future use) | ||
359 | */ | ||
360 | |||
361 | u8 state = msg->data[0]; | ||
362 | u8 rxerr = msg->data[1] & USB_8DEV_RP_MASK; | ||
363 | u8 txerr = msg->data[2]; | ||
364 | int rx_errors = 0; | ||
365 | int tx_errors = 0; | ||
366 | |||
367 | skb = alloc_can_err_skb(priv->netdev, &cf); | ||
368 | if (!skb) | ||
369 | return; | ||
370 | |||
371 | switch (state) { | ||
372 | case USB_8DEV_STATUSMSG_OK: | ||
373 | priv->can.state = CAN_STATE_ERROR_ACTIVE; | ||
374 | cf->can_id |= CAN_ERR_PROT; | ||
375 | cf->data[2] = CAN_ERR_PROT_ACTIVE; | ||
376 | break; | ||
377 | case USB_8DEV_STATUSMSG_BUSOFF: | ||
378 | priv->can.state = CAN_STATE_BUS_OFF; | ||
379 | cf->can_id |= CAN_ERR_BUSOFF; | ||
380 | can_bus_off(priv->netdev); | ||
381 | break; | ||
382 | case USB_8DEV_STATUSMSG_OVERRUN: | ||
383 | case USB_8DEV_STATUSMSG_BUSLIGHT: | ||
384 | case USB_8DEV_STATUSMSG_BUSHEAVY: | ||
385 | cf->can_id |= CAN_ERR_CRTL; | ||
386 | break; | ||
387 | default: | ||
388 | priv->can.state = CAN_STATE_ERROR_WARNING; | ||
389 | cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; | ||
390 | priv->can.can_stats.bus_error++; | ||
391 | break; | ||
392 | } | ||
393 | |||
394 | switch (state) { | ||
395 | case USB_8DEV_STATUSMSG_OK: | ||
396 | case USB_8DEV_STATUSMSG_BUSOFF: | ||
397 | break; | ||
398 | case USB_8DEV_STATUSMSG_ACK: | ||
399 | cf->can_id |= CAN_ERR_ACK; | ||
400 | tx_errors = 1; | ||
401 | break; | ||
402 | case USB_8DEV_STATUSMSG_CRC: | ||
403 | cf->data[2] |= CAN_ERR_PROT_UNSPEC; | ||
404 | cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ | | ||
405 | CAN_ERR_PROT_LOC_CRC_DEL; | ||
406 | rx_errors = 1; | ||
407 | break; | ||
408 | case USB_8DEV_STATUSMSG_BIT0: | ||
409 | cf->data[2] |= CAN_ERR_PROT_BIT0; | ||
410 | tx_errors = 1; | ||
411 | break; | ||
412 | case USB_8DEV_STATUSMSG_BIT1: | ||
413 | cf->data[2] |= CAN_ERR_PROT_BIT1; | ||
414 | tx_errors = 1; | ||
415 | break; | ||
416 | case USB_8DEV_STATUSMSG_FORM: | ||
417 | cf->data[2] |= CAN_ERR_PROT_FORM; | ||
418 | rx_errors = 1; | ||
419 | break; | ||
420 | case USB_8DEV_STATUSMSG_STUFF: | ||
421 | cf->data[2] |= CAN_ERR_PROT_STUFF; | ||
422 | rx_errors = 1; | ||
423 | break; | ||
424 | case USB_8DEV_STATUSMSG_OVERRUN: | ||
425 | cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; | ||
426 | stats->rx_over_errors++; | ||
427 | rx_errors = 1; | ||
428 | break; | ||
429 | case USB_8DEV_STATUSMSG_BUSLIGHT: | ||
430 | priv->can.state = CAN_STATE_ERROR_WARNING; | ||
431 | cf->data[1] = (txerr > rxerr) ? | ||
432 | CAN_ERR_CRTL_TX_WARNING : | ||
433 | CAN_ERR_CRTL_RX_WARNING; | ||
434 | priv->can.can_stats.error_warning++; | ||
435 | break; | ||
436 | case USB_8DEV_STATUSMSG_BUSHEAVY: | ||
437 | priv->can.state = CAN_STATE_ERROR_PASSIVE; | ||
438 | cf->data[1] = (txerr > rxerr) ? | ||
439 | CAN_ERR_CRTL_TX_PASSIVE : | ||
440 | CAN_ERR_CRTL_RX_PASSIVE; | ||
441 | priv->can.can_stats.error_passive++; | ||
442 | break; | ||
443 | default: | ||
444 | netdev_warn(priv->netdev, | ||
445 | "Unknown status/error message (%d)\n", state); | ||
446 | break; | ||
447 | } | ||
448 | |||
449 | if (tx_errors) { | ||
450 | cf->data[2] |= CAN_ERR_PROT_TX; | ||
451 | stats->tx_errors++; | ||
452 | } | ||
453 | |||
454 | if (rx_errors) | ||
455 | stats->rx_errors++; | ||
456 | |||
457 | cf->data[6] = txerr; | ||
458 | cf->data[7] = rxerr; | ||
459 | |||
460 | priv->bec.txerr = txerr; | ||
461 | priv->bec.rxerr = rxerr; | ||
462 | |||
463 | netif_rx(skb); | ||
464 | |||
465 | stats->rx_packets++; | ||
466 | stats->rx_bytes += cf->can_dlc; | ||
467 | } | ||
468 | |||
469 | /* Read data and status frames */ | ||
470 | static void usb_8dev_rx_can_msg(struct usb_8dev_priv *priv, | ||
471 | struct usb_8dev_rx_msg *msg) | ||
472 | { | ||
473 | struct can_frame *cf; | ||
474 | struct sk_buff *skb; | ||
475 | struct net_device_stats *stats = &priv->netdev->stats; | ||
476 | |||
477 | if (msg->type == USB_8DEV_TYPE_ERROR_FRAME && | ||
478 | msg->flags == USB_8DEV_ERR_FLAG) { | ||
479 | usb_8dev_rx_err_msg(priv, msg); | ||
480 | } else if (msg->type == USB_8DEV_TYPE_CAN_FRAME) { | ||
481 | skb = alloc_can_skb(priv->netdev, &cf); | ||
482 | if (!skb) | ||
483 | return; | ||
484 | |||
485 | cf->can_id = be32_to_cpu(msg->id); | ||
486 | cf->can_dlc = get_can_dlc(msg->dlc & 0xF); | ||
487 | |||
488 | if (msg->flags & USB_8DEV_EXTID) | ||
489 | cf->can_id |= CAN_EFF_FLAG; | ||
490 | |||
491 | if (msg->flags & USB_8DEV_RTR) | ||
492 | cf->can_id |= CAN_RTR_FLAG; | ||
493 | else | ||
494 | memcpy(cf->data, msg->data, cf->can_dlc); | ||
495 | |||
496 | netif_rx(skb); | ||
497 | |||
498 | stats->rx_packets++; | ||
499 | stats->rx_bytes += cf->can_dlc; | ||
500 | } else { | ||
501 | netdev_warn(priv->netdev, "frame type %d unknown", | ||
502 | msg->type); | ||
503 | } | ||
504 | |||
505 | } | ||
506 | |||
507 | /* Callback for reading data from device | ||
508 | * | ||
509 | * Check urb status, call read function and resubmit urb read operation. | ||
510 | */ | ||
511 | static void usb_8dev_read_bulk_callback(struct urb *urb) | ||
512 | { | ||
513 | struct usb_8dev_priv *priv = urb->context; | ||
514 | struct net_device *netdev; | ||
515 | int retval; | ||
516 | int pos = 0; | ||
517 | |||
518 | netdev = priv->netdev; | ||
519 | |||
520 | if (!netif_device_present(netdev)) | ||
521 | return; | ||
522 | |||
523 | switch (urb->status) { | ||
524 | case 0: /* success */ | ||
525 | break; | ||
526 | |||
527 | case -ENOENT: | ||
528 | case -ESHUTDOWN: | ||
529 | return; | ||
530 | |||
531 | default: | ||
532 | netdev_info(netdev, "Rx URB aborted (%d)\n", | ||
533 | urb->status); | ||
534 | goto resubmit_urb; | ||
535 | } | ||
536 | |||
537 | while (pos < urb->actual_length) { | ||
538 | struct usb_8dev_rx_msg *msg; | ||
539 | |||
540 | if (pos + sizeof(struct usb_8dev_rx_msg) > urb->actual_length) { | ||
541 | netdev_err(priv->netdev, "format error\n"); | ||
542 | break; | ||
543 | } | ||
544 | |||
545 | msg = (struct usb_8dev_rx_msg *)(urb->transfer_buffer + pos); | ||
546 | usb_8dev_rx_can_msg(priv, msg); | ||
547 | |||
548 | pos += sizeof(struct usb_8dev_rx_msg); | ||
549 | } | ||
550 | |||
551 | resubmit_urb: | ||
552 | usb_fill_bulk_urb(urb, priv->udev, | ||
553 | usb_rcvbulkpipe(priv->udev, USB_8DEV_ENDP_DATA_RX), | ||
554 | urb->transfer_buffer, RX_BUFFER_SIZE, | ||
555 | usb_8dev_read_bulk_callback, priv); | ||
556 | |||
557 | retval = usb_submit_urb(urb, GFP_ATOMIC); | ||
558 | |||
559 | if (retval == -ENODEV) | ||
560 | netif_device_detach(netdev); | ||
561 | else if (retval) | ||
562 | netdev_err(netdev, | ||
563 | "failed resubmitting read bulk urb: %d\n", retval); | ||
564 | } | ||
565 | |||
566 | /* Callback handler for write operations | ||
567 | * | ||
568 | * Free allocated buffers, check transmit status and | ||
569 | * calculate statistic. | ||
570 | */ | ||
571 | static void usb_8dev_write_bulk_callback(struct urb *urb) | ||
572 | { | ||
573 | struct usb_8dev_tx_urb_context *context = urb->context; | ||
574 | struct usb_8dev_priv *priv; | ||
575 | struct net_device *netdev; | ||
576 | |||
577 | BUG_ON(!context); | ||
578 | |||
579 | priv = context->priv; | ||
580 | netdev = priv->netdev; | ||
581 | |||
582 | /* free up our allocated buffer */ | ||
583 | usb_free_coherent(urb->dev, urb->transfer_buffer_length, | ||
584 | urb->transfer_buffer, urb->transfer_dma); | ||
585 | |||
586 | atomic_dec(&priv->active_tx_urbs); | ||
587 | |||
588 | if (!netif_device_present(netdev)) | ||
589 | return; | ||
590 | |||
591 | if (urb->status) | ||
592 | netdev_info(netdev, "Tx URB aborted (%d)\n", | ||
593 | urb->status); | ||
594 | |||
595 | netdev->stats.tx_packets++; | ||
596 | netdev->stats.tx_bytes += context->dlc; | ||
597 | |||
598 | can_get_echo_skb(netdev, context->echo_index); | ||
599 | |||
600 | /* Release context */ | ||
601 | context->echo_index = MAX_TX_URBS; | ||
602 | |||
603 | netif_wake_queue(netdev); | ||
604 | } | ||
605 | |||
606 | /* Send data to device */ | ||
607 | static netdev_tx_t usb_8dev_start_xmit(struct sk_buff *skb, | ||
608 | struct net_device *netdev) | ||
609 | { | ||
610 | struct usb_8dev_priv *priv = netdev_priv(netdev); | ||
611 | struct net_device_stats *stats = &netdev->stats; | ||
612 | struct can_frame *cf = (struct can_frame *) skb->data; | ||
613 | struct usb_8dev_tx_msg *msg; | ||
614 | struct urb *urb; | ||
615 | struct usb_8dev_tx_urb_context *context = NULL; | ||
616 | u8 *buf; | ||
617 | int i, err; | ||
618 | size_t size = sizeof(struct usb_8dev_tx_msg); | ||
619 | |||
620 | if (can_dropped_invalid_skb(netdev, skb)) | ||
621 | return NETDEV_TX_OK; | ||
622 | |||
623 | /* create a URB, and a buffer for it, and copy the data to the URB */ | ||
624 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
625 | if (!urb) { | ||
626 | netdev_err(netdev, "No memory left for URBs\n"); | ||
627 | goto nomem; | ||
628 | } | ||
629 | |||
630 | buf = usb_alloc_coherent(priv->udev, size, GFP_ATOMIC, | ||
631 | &urb->transfer_dma); | ||
632 | if (!buf) { | ||
633 | netdev_err(netdev, "No memory left for USB buffer\n"); | ||
634 | goto nomembuf; | ||
635 | } | ||
636 | |||
637 | memset(buf, 0, size); | ||
638 | |||
639 | msg = (struct usb_8dev_tx_msg *)buf; | ||
640 | msg->begin = USB_8DEV_DATA_START; | ||
641 | msg->flags = 0x00; | ||
642 | |||
643 | if (cf->can_id & CAN_RTR_FLAG) | ||
644 | msg->flags |= USB_8DEV_RTR; | ||
645 | |||
646 | if (cf->can_id & CAN_EFF_FLAG) | ||
647 | msg->flags |= USB_8DEV_EXTID; | ||
648 | |||
649 | msg->id = cpu_to_be32(cf->can_id & CAN_ERR_MASK); | ||
650 | msg->dlc = cf->can_dlc; | ||
651 | memcpy(msg->data, cf->data, cf->can_dlc); | ||
652 | msg->end = USB_8DEV_DATA_END; | ||
653 | |||
654 | for (i = 0; i < MAX_TX_URBS; i++) { | ||
655 | if (priv->tx_contexts[i].echo_index == MAX_TX_URBS) { | ||
656 | context = &priv->tx_contexts[i]; | ||
657 | break; | ||
658 | } | ||
659 | } | ||
660 | |||
661 | /* May never happen! When this happens we'd more URBs in flight as | ||
662 | * allowed (MAX_TX_URBS). | ||
663 | */ | ||
664 | if (!context) | ||
665 | goto nofreecontext; | ||
666 | |||
667 | context->priv = priv; | ||
668 | context->echo_index = i; | ||
669 | context->dlc = cf->can_dlc; | ||
670 | |||
671 | usb_fill_bulk_urb(urb, priv->udev, | ||
672 | usb_sndbulkpipe(priv->udev, USB_8DEV_ENDP_DATA_TX), | ||
673 | buf, size, usb_8dev_write_bulk_callback, context); | ||
674 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
675 | usb_anchor_urb(urb, &priv->tx_submitted); | ||
676 | |||
677 | can_put_echo_skb(skb, netdev, context->echo_index); | ||
678 | |||
679 | atomic_inc(&priv->active_tx_urbs); | ||
680 | |||
681 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
682 | if (unlikely(err)) | ||
683 | goto failed; | ||
684 | else if (atomic_read(&priv->active_tx_urbs) >= MAX_TX_URBS) | ||
685 | /* Slow down tx path */ | ||
686 | netif_stop_queue(netdev); | ||
687 | |||
688 | /* Release our reference to this URB, the USB core will eventually free | ||
689 | * it entirely. | ||
690 | */ | ||
691 | usb_free_urb(urb); | ||
692 | |||
693 | return NETDEV_TX_OK; | ||
694 | |||
695 | nofreecontext: | ||
696 | usb_unanchor_urb(urb); | ||
697 | usb_free_coherent(priv->udev, size, buf, urb->transfer_dma); | ||
698 | |||
699 | netdev_warn(netdev, "couldn't find free context"); | ||
700 | |||
701 | return NETDEV_TX_BUSY; | ||
702 | |||
703 | failed: | ||
704 | can_free_echo_skb(netdev, context->echo_index); | ||
705 | |||
706 | usb_unanchor_urb(urb); | ||
707 | usb_free_coherent(priv->udev, size, buf, urb->transfer_dma); | ||
708 | |||
709 | atomic_dec(&priv->active_tx_urbs); | ||
710 | |||
711 | if (err == -ENODEV) | ||
712 | netif_device_detach(netdev); | ||
713 | else | ||
714 | netdev_warn(netdev, "failed tx_urb %d\n", err); | ||
715 | |||
716 | nomembuf: | ||
717 | usb_free_urb(urb); | ||
718 | |||
719 | nomem: | ||
720 | dev_kfree_skb(skb); | ||
721 | stats->tx_dropped++; | ||
722 | |||
723 | return NETDEV_TX_OK; | ||
724 | } | ||
725 | |||
726 | static int usb_8dev_get_berr_counter(const struct net_device *netdev, | ||
727 | struct can_berr_counter *bec) | ||
728 | { | ||
729 | struct usb_8dev_priv *priv = netdev_priv(netdev); | ||
730 | |||
731 | bec->txerr = priv->bec.txerr; | ||
732 | bec->rxerr = priv->bec.rxerr; | ||
733 | |||
734 | return 0; | ||
735 | } | ||
736 | |||
737 | /* Start USB device */ | ||
738 | static int usb_8dev_start(struct usb_8dev_priv *priv) | ||
739 | { | ||
740 | struct net_device *netdev = priv->netdev; | ||
741 | int err, i; | ||
742 | |||
743 | for (i = 0; i < MAX_RX_URBS; i++) { | ||
744 | struct urb *urb = NULL; | ||
745 | u8 *buf; | ||
746 | |||
747 | /* create a URB, and a buffer for it */ | ||
748 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
749 | if (!urb) { | ||
750 | netdev_err(netdev, "No memory left for URBs\n"); | ||
751 | err = -ENOMEM; | ||
752 | break; | ||
753 | } | ||
754 | |||
755 | buf = usb_alloc_coherent(priv->udev, RX_BUFFER_SIZE, GFP_KERNEL, | ||
756 | &urb->transfer_dma); | ||
757 | if (!buf) { | ||
758 | netdev_err(netdev, "No memory left for USB buffer\n"); | ||
759 | usb_free_urb(urb); | ||
760 | err = -ENOMEM; | ||
761 | break; | ||
762 | } | ||
763 | |||
764 | usb_fill_bulk_urb(urb, priv->udev, | ||
765 | usb_rcvbulkpipe(priv->udev, | ||
766 | USB_8DEV_ENDP_DATA_RX), | ||
767 | buf, RX_BUFFER_SIZE, | ||
768 | usb_8dev_read_bulk_callback, priv); | ||
769 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
770 | usb_anchor_urb(urb, &priv->rx_submitted); | ||
771 | |||
772 | err = usb_submit_urb(urb, GFP_KERNEL); | ||
773 | if (err) { | ||
774 | usb_unanchor_urb(urb); | ||
775 | usb_free_coherent(priv->udev, RX_BUFFER_SIZE, buf, | ||
776 | urb->transfer_dma); | ||
777 | break; | ||
778 | } | ||
779 | |||
780 | /* Drop reference, USB core will take care of freeing it */ | ||
781 | usb_free_urb(urb); | ||
782 | } | ||
783 | |||
784 | /* Did we submit any URBs */ | ||
785 | if (i == 0) { | ||
786 | netdev_warn(netdev, "couldn't setup read URBs\n"); | ||
787 | return err; | ||
788 | } | ||
789 | |||
790 | /* Warn if we've couldn't transmit all the URBs */ | ||
791 | if (i < MAX_RX_URBS) | ||
792 | netdev_warn(netdev, "rx performance may be slow\n"); | ||
793 | |||
794 | err = usb_8dev_cmd_open(priv); | ||
795 | if (err) | ||
796 | goto failed; | ||
797 | |||
798 | priv->can.state = CAN_STATE_ERROR_ACTIVE; | ||
799 | |||
800 | return 0; | ||
801 | |||
802 | failed: | ||
803 | if (err == -ENODEV) | ||
804 | netif_device_detach(priv->netdev); | ||
805 | |||
806 | netdev_warn(netdev, "couldn't submit control: %d\n", err); | ||
807 | |||
808 | return err; | ||
809 | } | ||
810 | |||
811 | /* Open USB device */ | ||
812 | static int usb_8dev_open(struct net_device *netdev) | ||
813 | { | ||
814 | struct usb_8dev_priv *priv = netdev_priv(netdev); | ||
815 | int err; | ||
816 | |||
817 | /* common open */ | ||
818 | err = open_candev(netdev); | ||
819 | if (err) | ||
820 | return err; | ||
821 | |||
822 | /* finally start device */ | ||
823 | err = usb_8dev_start(priv); | ||
824 | if (err) { | ||
825 | if (err == -ENODEV) | ||
826 | netif_device_detach(priv->netdev); | ||
827 | |||
828 | netdev_warn(netdev, "couldn't start device: %d\n", | ||
829 | err); | ||
830 | |||
831 | close_candev(netdev); | ||
832 | |||
833 | return err; | ||
834 | } | ||
835 | |||
836 | netif_start_queue(netdev); | ||
837 | |||
838 | return 0; | ||
839 | } | ||
840 | |||
841 | static void unlink_all_urbs(struct usb_8dev_priv *priv) | ||
842 | { | ||
843 | int i; | ||
844 | |||
845 | usb_kill_anchored_urbs(&priv->rx_submitted); | ||
846 | |||
847 | usb_kill_anchored_urbs(&priv->tx_submitted); | ||
848 | atomic_set(&priv->active_tx_urbs, 0); | ||
849 | |||
850 | for (i = 0; i < MAX_TX_URBS; i++) | ||
851 | priv->tx_contexts[i].echo_index = MAX_TX_URBS; | ||
852 | } | ||
853 | |||
854 | /* Close USB device */ | ||
855 | static int usb_8dev_close(struct net_device *netdev) | ||
856 | { | ||
857 | struct usb_8dev_priv *priv = netdev_priv(netdev); | ||
858 | int err = 0; | ||
859 | |||
860 | /* Send CLOSE command to CAN controller */ | ||
861 | err = usb_8dev_cmd_close(priv); | ||
862 | if (err) | ||
863 | netdev_warn(netdev, "couldn't stop device"); | ||
864 | |||
865 | priv->can.state = CAN_STATE_STOPPED; | ||
866 | |||
867 | netif_stop_queue(netdev); | ||
868 | |||
869 | /* Stop polling */ | ||
870 | unlink_all_urbs(priv); | ||
871 | |||
872 | close_candev(netdev); | ||
873 | |||
874 | return err; | ||
875 | } | ||
876 | |||
877 | static const struct net_device_ops usb_8dev_netdev_ops = { | ||
878 | .ndo_open = usb_8dev_open, | ||
879 | .ndo_stop = usb_8dev_close, | ||
880 | .ndo_start_xmit = usb_8dev_start_xmit, | ||
881 | }; | ||
882 | |||
883 | static const struct can_bittiming_const usb_8dev_bittiming_const = { | ||
884 | .name = "usb_8dev", | ||
885 | .tseg1_min = 1, | ||
886 | .tseg1_max = 16, | ||
887 | .tseg2_min = 1, | ||
888 | .tseg2_max = 8, | ||
889 | .sjw_max = 4, | ||
890 | .brp_min = 1, | ||
891 | .brp_max = 1024, | ||
892 | .brp_inc = 1, | ||
893 | }; | ||
894 | |||
895 | /* Probe USB device | ||
896 | * | ||
897 | * Check device and firmware. | ||
898 | * Set supported modes and bittiming constants. | ||
899 | * Allocate some memory. | ||
900 | */ | ||
901 | static int usb_8dev_probe(struct usb_interface *intf, | ||
902 | const struct usb_device_id *id) | ||
903 | { | ||
904 | struct net_device *netdev; | ||
905 | struct usb_8dev_priv *priv; | ||
906 | int i, err = -ENOMEM; | ||
907 | u32 version; | ||
908 | char buf[18]; | ||
909 | struct usb_device *usbdev = interface_to_usbdev(intf); | ||
910 | |||
911 | /* product id looks strange, better we also check iProduct string */ | ||
912 | if (usb_string(usbdev, usbdev->descriptor.iProduct, buf, | ||
913 | sizeof(buf)) > 0 && strcmp(buf, "USB2CAN converter")) { | ||
914 | dev_info(&usbdev->dev, "ignoring: not an USB2CAN converter\n"); | ||
915 | return -ENODEV; | ||
916 | } | ||
917 | |||
918 | netdev = alloc_candev(sizeof(struct usb_8dev_priv), MAX_TX_URBS); | ||
919 | if (!netdev) { | ||
920 | dev_err(&intf->dev, "Couldn't alloc candev\n"); | ||
921 | return -ENOMEM; | ||
922 | } | ||
923 | |||
924 | priv = netdev_priv(netdev); | ||
925 | |||
926 | priv->udev = usbdev; | ||
927 | priv->netdev = netdev; | ||
928 | |||
929 | priv->can.state = CAN_STATE_STOPPED; | ||
930 | priv->can.clock.freq = USB_8DEV_ABP_CLOCK; | ||
931 | priv->can.bittiming_const = &usb_8dev_bittiming_const; | ||
932 | priv->can.do_set_mode = usb_8dev_set_mode; | ||
933 | priv->can.do_get_berr_counter = usb_8dev_get_berr_counter; | ||
934 | priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | | ||
935 | CAN_CTRLMODE_LISTENONLY | | ||
936 | CAN_CTRLMODE_ONE_SHOT; | ||
937 | |||
938 | netdev->netdev_ops = &usb_8dev_netdev_ops; | ||
939 | |||
940 | netdev->flags |= IFF_ECHO; /* we support local echo */ | ||
941 | |||
942 | init_usb_anchor(&priv->rx_submitted); | ||
943 | |||
944 | init_usb_anchor(&priv->tx_submitted); | ||
945 | atomic_set(&priv->active_tx_urbs, 0); | ||
946 | |||
947 | for (i = 0; i < MAX_TX_URBS; i++) | ||
948 | priv->tx_contexts[i].echo_index = MAX_TX_URBS; | ||
949 | |||
950 | priv->cmd_msg_buffer = kzalloc(sizeof(struct usb_8dev_cmd_msg), | ||
951 | GFP_KERNEL); | ||
952 | if (!priv->cmd_msg_buffer) { | ||
953 | netdev_err(netdev, "Couldn't alloc Tx buffer\n"); | ||
954 | goto cleanup_candev; | ||
955 | } | ||
956 | |||
957 | usb_set_intfdata(intf, priv); | ||
958 | |||
959 | SET_NETDEV_DEV(netdev, &intf->dev); | ||
960 | |||
961 | mutex_init(&priv->usb_8dev_cmd_lock); | ||
962 | |||
963 | err = register_candev(netdev); | ||
964 | if (err) { | ||
965 | netdev_err(netdev, | ||
966 | "couldn't register CAN device: %d\n", err); | ||
967 | goto cleanup_cmd_msg_buffer; | ||
968 | } | ||
969 | |||
970 | err = usb_8dev_cmd_version(priv, &version); | ||
971 | if (err) { | ||
972 | netdev_err(netdev, "can't get firmware version\n"); | ||
973 | goto cleanup_cmd_msg_buffer; | ||
974 | } else { | ||
975 | netdev_info(netdev, | ||
976 | "firmware: %d.%d, hardware: %d.%d\n", | ||
977 | (version>>24) & 0xff, (version>>16) & 0xff, | ||
978 | (version>>8) & 0xff, version & 0xff); | ||
979 | } | ||
980 | |||
981 | return 0; | ||
982 | |||
983 | cleanup_cmd_msg_buffer: | ||
984 | kfree(priv->cmd_msg_buffer); | ||
985 | |||
986 | cleanup_candev: | ||
987 | free_candev(netdev); | ||
988 | |||
989 | return err; | ||
990 | |||
991 | } | ||
992 | |||
993 | /* Called by the usb core when driver is unloaded or device is removed */ | ||
994 | static void usb_8dev_disconnect(struct usb_interface *intf) | ||
995 | { | ||
996 | struct usb_8dev_priv *priv = usb_get_intfdata(intf); | ||
997 | |||
998 | usb_set_intfdata(intf, NULL); | ||
999 | |||
1000 | if (priv) { | ||
1001 | netdev_info(priv->netdev, "device disconnected\n"); | ||
1002 | |||
1003 | unregister_netdev(priv->netdev); | ||
1004 | free_candev(priv->netdev); | ||
1005 | |||
1006 | unlink_all_urbs(priv); | ||
1007 | } | ||
1008 | |||
1009 | } | ||
1010 | |||
1011 | static struct usb_driver usb_8dev_driver = { | ||
1012 | .name = "usb_8dev", | ||
1013 | .probe = usb_8dev_probe, | ||
1014 | .disconnect = usb_8dev_disconnect, | ||
1015 | .id_table = usb_8dev_table, | ||
1016 | }; | ||
1017 | |||
1018 | module_usb_driver(usb_8dev_driver); | ||
1019 | |||
1020 | MODULE_AUTHOR("Bernd Krumboeck <krumboeck@universalnet.at>"); | ||
1021 | MODULE_DESCRIPTION("CAN driver for 8 devices USB2CAN interfaces"); | ||
1022 | MODULE_LICENSE("GPL v2"); | ||