Hi,

it took longer than expected, but here is a patch to add support for
binary mode to slcan with error recovery!
Regards,

Maximilian


Patch against SVN Rev 1054:

Index: kernel/2.6/drivers/net/can/slcan.c
===================================================================
--- kernel/2.6/drivers/net/can/slcan.c  (Revision 1054)
+++ kernel/2.6/drivers/net/can/slcan.c  (Arbeitskopie)
@@ -11,6 +11,7 @@
  * slip.c Authors  : Laurence Culhane <[email protected]>
  *                   Fred N. van Kempen <[email protected]>
  * slcan.c Author  : Oliver Hartkopp <[email protected]>
+ *                   Maximilian Falkenstein <[email protected]>
  *
  * Copyright (c) 2007-2009 Volkswagen Group Electronic Research
  *
@@ -75,13 +76,15 @@

 #include <socketcan/can.h>

+#if 0
 #include <socketcan/can/version.h> /* for RCSID. Removed by mkpatch script */
 RCSID("$Id$");
+#endif

-static __initdata const char banner[] =
-       KERN_INFO "slcan: serial line CAN interface driver\n";
+static __initdata const char banner[] = KERN_INFO
+"slcan: serial line CAN interface driver\n";

-MODULE_ALIAS_LDISC(N_SLCAN);
+MODULE_ALIAS_LDISC( N_SLCAN);
 MODULE_DESCRIPTION("serial line CAN interface");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Oliver Hartkopp <[email protected]>");
@@ -126,47 +129,73 @@
 #define SLC_CHECK_TRANSMIT
 #define SLCAN_MAGIC 0x53CA

-static int maxdev = 10;                /* MAX number of SLCAN channels;
-                                  This can be overridden with
-                                  insmod slcan.ko maxdev=nnn   */
+static int maxdev = 10; /* MAX number of SLCAN channels;
+ This can be overridden with
+ insmod slcan.ko maxdev=nnn    */
 module_param(maxdev, int, 0);
 MODULE_PARM_DESC(maxdev, "Maximum number of slcan interfaces");
+/* MAX number of packets to put *
+ * into the device buffer, can  *
+ * also be overridden                  */
+static int maxack = 2;
+module_param(maxack, int, 0);
+MODULE_PARM_DESC(maxack, "Maximum number of packets to put into the
device buffer, be _VERY_ careful with this!");

-/* maximum rx buffer len: extended CAN frame with timestamp */
+/* maximum rx buffer len: extended CAN frame with timestamp in ASCII format */
 #define SLC_MTU (sizeof("T1111222281122334455667788EA5F\r")+1)

 struct slcan {
-       int                     magic;
+       int magic;

+
+       /* We need some extra vars for binary mode! */
+       int dnum; /* How many data bytes do we except to receive */
+       int to_ack; /* How many packets have we put into the device buffer? */
+       int rec_rcount; /* special rcount for recovery purposes */
+
+
        /* Various fields. */
-       struct tty_struct       *tty;           /* ptr to TTY structure      */
-       struct net_device       *dev;           /* easy for intr handling    */
-       spinlock_t              lock;
+       struct tty_struct *tty; /* ptr to TTY structure      */
+       struct net_device *dev; /* easy for intr handling    */
+       spinlock_t lock;

+
        /* These are pointers to the malloc()ed frame buffers. */
-       unsigned char           rbuff[SLC_MTU]; /* receiver buffer           */
-       int                     rcount;         /* received chars counter    */
-       unsigned char           xbuff[SLC_MTU]; /* transmitter buffer        */
-       unsigned char           *xhead;         /* pointer to next XMIT byte */
-       int                     xleft;          /* bytes left in XMIT queue  */
+       unsigned char rbuff[SLC_MTU]; /* receiver buffer             */
+       int rcount; /* received chars counter    */
+       unsigned char xbuff[SLC_MTU]; /* transmitter buffer          */
+       unsigned char *xhead; /* pointer to next XMIT byte */
+       int xleft; /* bytes left in XMIT queue  */

+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
        /* SLCAN interface statistics. */
        struct net_device_stats stats;
 #endif

-       unsigned long           flags;          /* Flag values/ mode etc     */
+       unsigned long flags; /* Flag values/ mode etc     */
 #define SLF_INUSE              0               /* Channel in use            */
-#define SLF_ERROR              1               /* Parity, etc. error        */
+#define SLF_ERROR              1       /* Parity, etc. error        */
+#define SLF_BINENC             2               /* Do we use binary 
encapsulation? */
+#define SLF_EFRAME             3               /* Is the frame we are 
currently receiving extended */
+#define SLF_RESP               4               /* Is the next byte a response 
to a command */

-       unsigned char           leased;
-       dev_t                   line;
-       pid_t                   pid;
+
+       /* true, if we've paused the transmission of packets because the 
hardware       *
+        * hasn't answered (yet).                                               
                                                        */
+#define SLF_PAUSED             5
+
+
+#define SLF_LOST_SYNC  6               /* true, if we don't know what's going 
on... */
+#define SLF_FRAME_CANDIDAT 7   /* What we're receiving looks like a frame... */
+
+       unsigned char leased;
+       dev_t line;
+       pid_t pid;
 };

 static struct net_device **slcan_devs;

-
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
 /* Netdevice get statistics request */
 static struct net_device_stats *slc_get_stats(struct net_device *dev)
@@ -177,9 +206,9 @@
 }
 #endif

- /************************************************************************
-  *                    SLCAN ENCAPSULATION FORMAT                       *
-  ************************************************************************/
+/************************************************************************
+ *                     SLCAN ENCAPSULATION FORMAT                       *
+ ************************************************************************/

 /*
  * A CAN frame has a can_id (11 bit standard frame format OR 29 bit extended
@@ -210,11 +239,19 @@
  * T12ABCDEF2AA55 : extended can_id 0x12ABCDEF, can_dlc 2, data 0xAA 0x55
  * r1230 : can_id 0x123, can_dlc 0, no data, remote transmission request
  *
+ * NEW: We also have a binary encapsulation. It's very similar to the ASCII
+ * one, except that we don't user \r \n and don't convert to ASCII. The return
+ * value is also different! As the lib on controller doesn't differ between
+ * RTR and normal frame with 0 databytes, we don't differ between 'R'
and 'T', too.
+ *
+ * Examples(Binary):
+ * t 0x01 0x23 0x00 : like t1230, can_id 0x123, can_dlc 0, no data
+ * T 0x12 0xAB 0xCD 0xEF 0x03 0xAA 0x55 : extended can_id 0x12ABCDEF,
can_dlc 2, data 0xAA 0x55
  */

- /************************************************************************
-  *                    STANDARD SLCAN DECAPSULATION                     *
-  ************************************************************************/
+/************************************************************************
+ *                     STANDARD SLCAN DECAPSULATION                     *
+ ************************************************************************/

 static int asc2nibble(char c)
 {
@@ -245,50 +282,82 @@
        unsigned long ultmp;
        char cmd = sl->rbuff[0];

-       if ((cmd != 't') && (cmd != 'T') && (cmd != 'r') && (cmd != 'R'))
-               return;
+       if (!test_bit(SLF_BINENC, &sl->flags)) {
+               if ((cmd != 't') && (cmd != 'T') && (cmd != 'r') && (cmd != 
'R'))
+                       return;

-       if (cmd & 0x20) /* tiny chars 'r' 't' => standard frame format */
-               dlc_pos = 4; /* dlc position tiiid */
-       else
-               dlc_pos = 9; /* dlc position Tiiiiiiiid */
+               if (cmd & 0x20) /* tiny chars 'r' 't' => standard frame format 
*/
+                       dlc_pos = 4; /* dlc position tiiid */
+               else
+                       dlc_pos = 9; /* dlc position Tiiiiiiiid */

-       if (!((sl->rbuff[dlc_pos] >= '0') && (sl->rbuff[dlc_pos] < '9')))
-               return;
+               if (!((sl->rbuff[dlc_pos] >= '0') && (sl->rbuff[dlc_pos] < 
'9')))
+                       return;

-       cf.can_dlc = sl->rbuff[dlc_pos] - '0'; /* get can_dlc from ASCII val */
+               cf.can_dlc = sl->rbuff[dlc_pos] - '0'; /* get can_dlc from 
ASCII val */

-       sl->rbuff[dlc_pos] = 0; /* terminate can_id string */
+               sl->rbuff[dlc_pos] = 0; /* terminate can_id string */

+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
-       ultmp = simple_strtoul(sl->rbuff+1, NULL, 16);
+               ultmp = simple_strtoul(sl->rbuff+1, NULL, 16);
 #else
-       if (strict_strtoul(sl->rbuff+1, 16, &ultmp))
-               return;
+               if (strict_strtoul(sl->rbuff + 1, 16, &ultmp))
+                       return;
 #endif
-       cf.can_id = ultmp;
+               cf.can_id = ultmp;

-       if (!(cmd & 0x20)) /* NO tiny chars => extended frame format */
-               cf.can_id |= CAN_EFF_FLAG;
+               if (!(cmd & 0x20)) /* NO tiny chars => extended frame format */
+                       cf.can_id |= CAN_EFF_FLAG;

-       if ((cmd | 0x20) == 'r') /* RTR frame */
-               cf.can_id |= CAN_RTR_FLAG;
+               if ((cmd | 0x20) == 'r') /* RTR frame */
+                       cf.can_id |= CAN_RTR_FLAG;

-       *(u64 *) (&cf.data) = 0; /* clear payload */
+               *(u64 *) (&cf.data) = 0; /* clear payload */

-       for (i = 0, dlc_pos++; i < cf.can_dlc; i++) {
-
-               tmp = asc2nibble(sl->rbuff[dlc_pos++]);
-               if (tmp > 0x0F)
+               for (i = 0, dlc_pos++; i < cf.can_dlc; i++) {
+                       tmp = asc2nibble(sl->rbuff[dlc_pos++]);
+                       if (tmp > 0x0F)
+                               return;
+                       cf.data[i] = (tmp << 4);
+                       tmp = asc2nibble(sl->rbuff[dlc_pos++]);
+                       if (tmp > 0x0F)
+                               return;
+                       cf.data[i] |= tmp;
+               }
+       } else {
+               //Binary is so much easier ;-)
+               if (cmd == 't') {
+                       //Normal can frame
+                       cf.can_id = (sl->rbuff[1] << 8) | sl->rbuff[2];
+                       cf.can_dlc = sl->rbuff[3];
+                       if (cf.can_dlc > 8) {
+                               printk(KERN_WARNING "slcan: Frame with lenght 
above 8, dropping!");
+                               stats->rx_dropped++;
+                               stats->rx_errors++;
+                               return;
+                       }
+                       for (i = 0; i < cf.can_dlc; i++)
+                               cf.data[i] = sl->rbuff[4 + i];
+               } else if (cmd == 'T') {
+                       //Extended can frame
+                       cf.can_id = (sl->rbuff[1] << 24) | (sl->rbuff[2] << 16) 
|
(sl->rbuff[3] << 8) | sl->rbuff[4];
+                       cf.can_dlc = sl->rbuff[5];
+                       if (cf.can_dlc > 8) {
+                               printk(KERN_WARNING "slcan: Frame with lenght 
above 8, dropping!");
+                               stats->rx_dropped++;
+                               stats->rx_errors++;
+                               return;
+                       }
+                       for (i = 0; i < cf.can_dlc; i++)
+                               cf.data[i] = sl->rbuff[6 + i];
+               } else {
+                       printk(KERN_WARNING "slcan: Got unknown can frame from 
device!");
+                       stats->rx_errors++;
                        return;
-               cf.data[i] = (tmp << 4);
-               tmp = asc2nibble(sl->rbuff[dlc_pos++]);
-               if (tmp > 0x0F)
-                       return;
-               cf.data[i] |= tmp;
+               }
        }

-
        skb = dev_alloc_skb(sizeof(struct can_frame));
        if (!skb)
                return;
@@ -297,8 +366,7 @@
        skb->protocol = htons(ETH_P_CAN);
        skb->pkt_type = PACKET_BROADCAST;
        skb->ip_summed = CHECKSUM_UNNECESSARY;
-       memcpy(skb_put(skb, sizeof(struct can_frame)),
-              &cf, sizeof(struct can_frame));
+       memcpy(skb_put(skb, sizeof(struct can_frame)), &cf, sizeof(struct 
can_frame));
        netif_rx(skb);

        sl->dev->last_rx = jiffies;
@@ -314,29 +382,197 @@
 #else
        struct net_device_stats *stats = &sl->dev->stats;
 #endif
+       int i;
+       unsigned char nrbuff[SLC_MTU];

-       if ((s == '\r') || (s == '\a')) { /* CR or BEL ends the pdu */
-               if (!test_and_clear_bit(SLF_ERROR, &sl->flags) &&
-                   (sl->rcount > 4))  {
+       if (!test_bit(SLF_BINENC, &sl->flags)) {
+               //ASCII
+               if ((s == '\r') || (s == '\a')) { /* CR or BEL ends the pdu */
+                       if (!test_and_clear_bit(SLF_ERROR, &sl->flags) && 
(sl->rcount > 4)) {
+                               slc_bump(sl);
+                       }
+                       sl->rcount = 0;
+               } else {
+                       if (!test_bit(SLF_ERROR, &sl->flags)) {
+                               if (sl->rcount < SLC_MTU) {
+                                       sl->rbuff[sl->rcount++] = s;
+                                       return;
+                               } else {
+                                       stats->rx_over_errors++;
+                                       set_bit(SLF_ERROR, &sl->flags);
+                               }
+                       }
+               }
+       } else {
+               //BINARY
+               if (test_bit(SLF_LOST_SYNC, &sl->flags)) {
+                       //OK, complicated things first(error recovery)...
+                       sl->rbuff[sl->rec_rcount] = s;
+                       sl->rec_rcount++;
+
+                       if (test_bit(SLF_FRAME_CANDIDAT, &sl->flags)) {
+                               if (!test_bit(SLF_RESP, &sl->flags)) {
+                                       int offset = sl->rec_rcount - 
sl->rcount;
+                                       sl->rcount++;
+                                       if ((sl->rcount == 2 && 
!test_bit(SLF_EFRAME, &sl->flags)) |
(sl->rcount == 4 && test_bit(
+                                                       SLF_EFRAME, 
&sl->flags))) {
+                                               //We've recived the last bit of 
the CAN id
+                                               if (test_bit(SLF_EFRAME, 
&sl->flags) && (((sl->rbuff[offset + 1] << 24)
+                                                               | 
(sl->rbuff[offset + 2] << 16) | (sl->rbuff[offset + 3] <<
8) | sl->rbuff[offset + 4])
+                                                               > 0x1FFFFFFF) | 
!test_bit(SLF_EFRAME, &sl->flags) &&
((sl->rbuff[offset + 1] << 8)
+                                                               | 
sl->rbuff[offset + 2]) > 0x7FF) {
+                                                       //Invalid ID
+                                                       goto invalid;
+                                               }
+                                       } else if ((sl->rcount == 5 && 
test_bit(SLF_EFRAME, &sl->flags))
| ((sl->rcount == 3) && !test_bit(
+                                                       SLF_EFRAME, 
&sl->flags))) {
+                                               if (s > 8) //Invalid dlc
+                                                       goto invalid;
+                                               else if (s == 0) {
+                                                       goto rec_out_decaps;
+                                               } else {
+                                                       sl->dnum = s;
+                                                       return;
+                                               }
+                                       } else if (sl->dnum > 0) {
+                                               sl->dnum--;
+                                               if (sl->dnum == 0) {
+                                                       //Decaps
+                                                       goto rec_out_decaps;
+                                               }
+                                       }
+                               } else {
+                                       if (s & 0xf0) {
+                                               if (s != 0xf9) {
+                                                       /* 0xf9 means OK, 
everything different means error */
+                                                       printk(KERN_WARNING 
"%s: Command failed, retval: %X\n",
sl->dev->name, s);
+                                                       stats->tx_errors++;
+                                                       stats->tx_dropped++;
+                                               }
+                                               sl->to_ack--;
+                                               if (test_bit(SLF_PAUSED, 
&sl->flags) && (sl->to_ack < maxack)) {
+                                                       /* The device buffer is 
large enough for at least one
+                                                        * more packet, so 
let's wake the quere */
+                                                       clear_bit(SLF_PAUSED, 
&sl->flags);
+                                                       
netif_wake_queue(sl->dev);
+                                               }
+                                               clear_bit(SLF_RESP, &sl->flags);
+                                               sl->rcount = 0;
+                                               sl->rec_rcount = 0;
+                                               clear_bit(SLF_FRAME_CANDIDAT, 
&sl->flags);
+                                               clear_bit(SLF_LOST_SYNC, 
&sl->flags);
+                                               return;
+                                       } else
+                                               goto invalid;
+                               }
+                       }
+                       if (sl->rec_rcount == SLC_MTU) {
+                               printk( KERN_WARNING
+                               "%s: Buffer full, but still havn't received a 
valid packet!\n",
sl->dev->name);
+                               sl->rcount = 0;
+                               clear_bit(SLF_FRAME_CANDIDAT, &sl->flags);
+                       }
+                       if ((s == 't') | (s == 'T') | (s == 0xe0)) {
+                               set_bit(SLF_FRAME_CANDIDAT, &sl->flags);
+                               if (s == 't')
+                                       clear_bit(SLF_EFRAME, &sl->flags);
+                               if (s == 'T')
+                                       set_bit(SLF_EFRAME, &sl->flags);
+                               if (s == 0xe0)
+                                       set_bit(SLF_RESP, &sl->flags);
+                               sl->rcount = 0;
+                       }
+                       return;
+
+                       invalid: clear_bit(SLF_FRAME_CANDIDAT, &sl->flags);
+                       return;
+
+                       rec_out_decaps:
+                       //Modify buffer so that we can call slc_bump
+                       for (i = 0; i <= sl->rcount; i++)
+                               nrbuff[i] = sl->rbuff[sl->rec_rcount - 
sl->rcount - 1 + i];
+                       memcpy(sl->rbuff, nrbuff, sl->rcount + 1);
                        slc_bump(sl);
+                       sl->rcount = 0;
+                       sl->rec_rcount = 0;
+                       clear_bit(SLF_FRAME_CANDIDAT, &sl->flags);
+                       clear_bit(SLF_LOST_SYNC, &sl->flags);
+                       return;
                }
-               sl->rcount = 0;
-       } else {
-               if (!test_bit(SLF_ERROR, &sl->flags))  {
-                       if (sl->rcount < SLC_MTU)  {
-                               sl->rbuff[sl->rcount++] = s;
+
+               if (test_bit(SLF_RESP, &sl->flags)) {
+                       if (s != 0xf9) {
+                               /* 0xf9 means OK, everything different means 
error */
+                               printk(KERN_WARNING "%s: Command failed, 
retval: %X\n", sl->dev->name, s);
+                               stats->tx_errors++;
+                               stats->tx_dropped++;
+                       }
+                       sl->to_ack--;
+                       if (test_bit(SLF_PAUSED, &sl->flags) && (sl->to_ack < 
maxack)) {
+                               /* The device buffer is large enough for at 
least one
+                                * more packet, so let's wake the quere */
+                               clear_bit(SLF_PAUSED, &sl->flags);
+                               netif_wake_queue(sl->dev);
+                       }
+                       clear_bit(SLF_RESP, &sl->flags);
+                       sl->rcount = 0;
+                       return;
+               }
+
+               if (sl->rcount == 0) {
+                       //What's coming next: a can frame, an extended can 
frame, or an ack/nack?
+                       if (s == 't') {
+                               clear_bit(SLF_EFRAME, &sl->flags);
+                               goto out_write;
+                       } else if (s == 'T') {
+                               set_bit(SLF_EFRAME, &sl->flags);
+                               goto out_write;
+                       } else if (s == 0xe0) {
+                               //ACK/NACK
+                               set_bit(SLF_RESP, &sl->flags);
+                       } else {
+                               //Unknown packet, *may* happen during hot 
plugging!
+                               printk(KERN_WARNING "slcan (dev: %s): Unknown 
packet(head: 0x%X),
entering lost sync mode!\n", sl->dev->name, s);
+                               stats->rx_errors++;
+                               sl->rec_rcount = 0;
+                               sl->rcount = 0;
+                               sl->rec_rcount = 0;
+                               set_bit(SLF_LOST_SYNC, &sl->flags);
                                return;
-                       } else {
-                               stats->rx_over_errors++;
-                               set_bit(SLF_ERROR, &sl->flags);
                        }
+               } else if ((test_bit(SLF_EFRAME, &sl->flags) && sl->rcount == 
5) |
((!test_bit(SLF_EFRAME, &sl->flags))
+                               && sl->rcount == 3)) {
+                       //Now we're receiving the payload lenght
+                       if (s == 0) {
+                               //Oh, cool, a RTR; we can decapsulate it 
immediately
+                               sl->rbuff[sl->rcount] = s;
+                               goto out_decaps;
+                       }
+                       sl->dnum = s;
+                       goto out_write;
+               } else {
+                       //More data
+                       sl->rbuff[sl->rcount] = s;
+                       sl->rcount++;
+                       sl->dnum--;
+                       if (sl->dnum == 0)
+                               goto out_decaps;
                }
        }
+       return;
+
+       out_write: sl->rbuff[sl->rcount] = s;
+       sl->rcount++;
+       return;
+
+       out_decaps: slc_bump(sl);
+       sl->rcount = 0;
+       return;
 }

- /************************************************************************
-  *                    STANDARD SLCAN ENCAPSULATION                     *
-  ************************************************************************/
+/************************************************************************
+ *                     STANDARD SLCAN ENCAPSULATION                     *
+ ************************************************************************/

 /* Encapsulate one can_frame and stuff into a TTY queue. */
 static void slc_encaps(struct slcan *sl, struct can_frame *cf)
@@ -349,41 +585,95 @@
        int actual, idx, i;
        char cmd;

-       if (cf->can_id & CAN_RTR_FLAG)
-               cmd = 'R'; /* becomes 'r' in standard frame format */
-       else
-               cmd = 'T'; /* becomes 't' in standard frame format */
+       if (test_bit(SLF_BINENC, &sl->flags)) {
+               uint32_t id = cf->can_id & CAN_EFF_MASK;
+               uint8_t lof = 0;
+               if (cf->can_id & CAN_EFF_FLAG) {
+                       sl->xbuff[0] = 'T'; //Send
+                       sl->xbuff[1] = (uint8_t)(id >> 24);
+                       sl->xbuff[2] = (uint8_t)(id >> 16);
+                       sl->xbuff[3] = (uint8_t)(id >> 8);
+                       sl->xbuff[4] = (uint8_t) id;
+                       lof = 4;
+               } else {
+                       sl->xbuff[0] = 't'; //Send
+                       sl->xbuff[1] = (uint8_t)(id >> 8);
+                       sl->xbuff[2] = (uint8_t) id;
+                       lof = 2;
+               }
+               sl->xbuff[lof + 1] = cf->can_dlc;
+               /* Stringterm (Reordered for C90 compatibility) */
+               sl->xbuff[lof + 2 + cf->can_dlc] = 0x00;

-       if (cf->can_id & CAN_EFF_FLAG)
-               sprintf(sl->xbuff, "%c%08X%d", cmd,
-                       cf->can_id & CAN_EFF_MASK, cf->can_dlc);
-       else
-               sprintf(sl->xbuff, "%c%03X%d", cmd | 0x20,
-                       cf->can_id & CAN_SFF_MASK, cf->can_dlc);
+               for (i = 0; i < cf->can_dlc; i++) {
+                       sl->xbuff[lof + 2 + i] = cf->data[i];
+               }

-       idx = strlen(sl->xbuff);
+               /* We're going to send another packet into the device's buffer,
+                * let's tell the receiving side that we're sending something
+                * that's going to get a CMD_RESP. */
+               sl->to_ack++;

-       for (i = 0; i < cf->can_dlc; i++)
-               sprintf(&sl->xbuff[idx + 2*i], "%02X", cf->data[i]);

-       DBG("ASCII frame = '%s'\n", sl->xbuff);
+               /* Flow control: The device may be busy, but able to receive
+                * data (interrupt driven, at least in my firmware), but it
+                * can't handle an infinite amount of data, so we have to
+                * stop and wait for response after some packets... */
+               if (sl->to_ack >= maxack)
+                       set_bit(SLF_PAUSED, &sl->flags);

-       strcat(sl->xbuff, "\r"); /* add terminating character */

-       /* Order of next two lines is *very* important.
-        * When we are sending a little amount of data,
-        * the transfer may be completed inside driver.write()
-        * routine, because it's running with interrupts enabled.
-        * In this case we *never* got WRITE_WAKEUP event,
-        * if we did not request it before write operation.
-        *       14 Oct 1994  Dmitry Gorodchanin.
-        */
-       sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
+               /* Order of next two lines is *very* important.
+                * When we are sending a little amount of data,
+                * the transfer may be completed inside driver.write()
+                * routine, because it's running with interrupts enabled.
+                * In this case we *never* got WRITE_WAKEUP event,
+                * if we did not request it before write operation.
+                *       14 Oct 1994  Dmitry Gorodchanin.
+                */
+               sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
-       actual = sl->tty->driver->write(sl->tty, sl->xbuff, strlen(sl->xbuff));
+               actual = sl->tty->driver->write(sl->tty, sl->xbuff, (cf->can_id 
&
CAN_EFF_FLAG ? 6 : 4)+cf->can_dlc);
 #else
-       actual = sl->tty->ops->write(sl->tty, sl->xbuff, strlen(sl->xbuff));
+               actual = sl->tty->ops->write(sl->tty, sl->xbuff, (cf->can_id &
CAN_EFF_FLAG ? 6 : 4) + cf->can_dlc);
 #endif
+
+       } else {
+               if (cf->can_id & CAN_RTR_FLAG)
+                       cmd = 'R'; /* becomes 'r' in standard frame format */
+               else
+                       cmd = 'T'; /* becomes 't' in standard frame format */
+
+               if (cf->can_id & CAN_EFF_FLAG)
+                       sprintf(sl->xbuff, "%c%08X%d", cmd, cf->can_id & 
CAN_EFF_MASK, cf->can_dlc);
+               else
+                       sprintf(sl->xbuff, "%c%03X%d", cmd | 0x20, cf->can_id &
CAN_SFF_MASK, cf->can_dlc);
+
+               idx = strlen(sl->xbuff);
+
+               for (i = 0; i < cf->can_dlc; i++)
+                       sprintf(&sl->xbuff[idx + 2 * i], "%02X", cf->data[i]);
+
+               DBG("ASCII frame = '%s'\n", sl->xbuff);
+
+               strcat(sl->xbuff, "\r"); /* add terminating character */
+
+
+               /* Order of next two lines is *very* important.
+                * When we are sending a little amount of data,
+                * the transfer may be completed inside driver.write()
+                * routine, because it's running with interrupts enabled.
+                * In this case we *never* got WRITE_WAKEUP event,
+                * if we did not request it before write operation.
+                *       14 Oct 1994  Dmitry Gorodchanin.
+                */
+               sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+               actual = sl->tty->driver->write(sl->tty, sl->xbuff, 
strlen(sl->xbuff));
+#else
+               actual = sl->tty->ops->write(sl->tty, sl->xbuff, 
strlen(sl->xbuff));
+#endif
+       }
 #ifdef SLC_CHECK_TRANSMIT
        sl->dev->trans_start = jiffies;
 #endif
@@ -406,16 +696,22 @@
        struct net_device_stats *stats = &sl->dev->stats;
 #endif

+
        /* First make sure we're connected. */
        if (!sl || sl->magic != SLCAN_MAGIC || !netif_running(sl->dev))
                return;

-       if (sl->xleft <= 0)  {
+       if (sl->xleft <= 0) {
                /* Now serial buffer is almost free & we can start
                 * transmission of another packet */
                stats->tx_packets++;
                tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
-               netif_wake_queue(sl->dev);
+
+
+               /* Maybe the device isn't ready, lets check before
+                * we try to send the next packet */
+               if (!(test_bit(SLF_BINENC, &sl->flags) && test_bit(SLF_PAUSED, 
&sl->flags)))
+                       netif_wake_queue(sl->dev);
                return;
        }

@@ -442,27 +738,25 @@
                 *      14 Oct 1994 Dmitry Gorodchanin.
                 */
 #ifdef SLC_CHECK_TRANSMIT
-               if (time_before(jiffies, dev->trans_start + 20 * HZ))  {
+               if (time_before(jiffies, dev->trans_start + 20 * HZ)) {
                        /* 20 sec timeout not reached */
                        goto out;
-               }
-               printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
+               }printk
+               (KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
-                      (sl->tty->driver->chars_in_buffer(sl->tty) || sl->xleft)
+                               (sl->tty->driver->chars_in_buffer(sl->tty) || 
sl->xleft)
 #else
-                      (tty_chars_in_buffer(sl->tty) || sl->xleft)
+                               (tty_chars_in_buffer(sl->tty) || sl->xleft)
 #endif
-                      ? "bad line quality" : "driver error");
+                                               ? "bad line quality" : "driver 
error");
                sl->xleft = 0;
                sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
                netif_wake_queue(sl->dev);
 #endif
        }
-out:
-       spin_unlock(&sl->lock);
+       out: spin_unlock(&sl->lock);
 }

-
 /******************************************
  *   Routines looking at netdevice side.
  ******************************************/
@@ -476,9 +770,10 @@
                goto out;

        spin_lock(&sl->lock);
-       if (!netif_running(dev))  {
+       if (!netif_running(dev)) {
                spin_unlock(&sl->lock);
-               printk(KERN_WARNING "%s: xmit: iface is down\n", dev->name);
+               printk
+               (KERN_WARNING "%s: xmit: iface is down\n", dev->name);
                goto out;
        }

@@ -491,12 +786,10 @@
        slc_encaps(sl, (struct can_frame *) skb->data); /* encaps & send */
        spin_unlock(&sl->lock);

-out:
-       kfree_skb(skb);
+       out: kfree_skb(skb);
        return 0;
 }

-
 /* Netdevice UP -> DOWN routine */
 static int slc_close(struct net_device *dev)
 {
@@ -508,8 +801,8 @@
                sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
        }
        netif_stop_queue(dev);
-       sl->rcount   = 0;
-       sl->xleft    = 0;
+       sl->rcount = 0;
+       sl->xleft = 0;
        spin_unlock_bh(&sl->lock);

        return 0;
@@ -523,18 +816,20 @@
        if (sl->tty == NULL)
                return -ENODEV;

-       sl->flags &= (1 << SLF_INUSE);
+       /* ARGH! Bitmasks are not always clever... */
+       //sl->flags &= (1 << SLF_INUSE);
+       sl->flags &= (1 << SLF_INUSE) | (1 << SLF_BINENC);
        netif_start_queue(dev);
        return 0;
 }

 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)
 static const struct net_device_ops slc_netdev_ops = {
-       .ndo_open               = slc_open,
-       .ndo_stop               = slc_close,
-       .ndo_start_xmit         = slc_xmit,
+       .ndo_open = slc_open,
+       .ndo_stop = slc_close,
+       .ndo_start_xmit = slc_xmit,
 #ifdef SLC_CHECK_TRANSMIT
-       .ndo_tx_timeout         = slc_tx_timeout,
+       .ndo_tx_timeout = slc_tx_timeout,
 #endif
 };
 #endif
@@ -545,31 +840,32 @@
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)
        dev->netdev_ops = &slc_netdev_ops;
 #else
-       dev->open               = slc_open;
-       dev->stop               = slc_close;
-       dev->hard_start_xmit    = slc_xmit;
+       dev->open = slc_open;
+       dev->stop = slc_close;
+       dev->hard_start_xmit = slc_xmit;
 #endif
-       dev->destructor         = free_netdev;
+       dev->destructor = free_netdev;
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
-       dev->get_stats          = slc_get_stats;
+       dev->get_stats = slc_get_stats;
 #endif

-       dev->hard_header_len    = 0;
-       dev->addr_len           = 0;
-       dev->tx_queue_len       = 10;
+       dev->hard_header_len = 0;
+       dev->addr_len = 0;
+       dev->tx_queue_len = 10;

-       dev->mtu                = sizeof(struct can_frame);
-       dev->type               = ARPHRD_CAN;
+       dev->mtu = sizeof(struct can_frame);
+       dev->type = ARPHRD_CAN;
 #ifdef SLC_CHECK_TRANSMIT
 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,28)
-       dev->tx_timeout         = slc_tx_timeout;
+       dev->tx_timeout = slc_tx_timeout;
 #endif
-       dev->watchdog_timeo     = 20*HZ;
+       dev->watchdog_timeo = 20 * HZ;
 #endif

+
        /* New-style flags. */
-       dev->flags              = IFF_NOARP;
-       dev->features           = NETIF_F_NO_CSUM;
+       dev->flags = IFF_NOARP;
+       dev->features = NETIF_F_NO_CSUM;
 }

 /******************************************
@@ -579,7 +875,7 @@
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
 static int slcan_receive_room(struct tty_struct *tty)
 {
-       return 65536;  /* We can handle an infinite amount of data. :-) */
+       return 65536; /* We can handle an infinite amount of data. :-) */
 }
 #endif

@@ -591,9 +887,7 @@
  * be re-entered while running but other ldisc functions may be called
  * in parallel
  */
-
-static void slcan_receive_buf(struct tty_struct *tty,
-                             const unsigned char *cp, char *fp, int count)
+static void slcan_receive_buf(struct tty_struct *tty, const unsigned
char *cp, char *fp, int count)
 {
        struct slcan *sl = (struct slcan *) tty->disc_data;
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
@@ -602,10 +896,10 @@
        struct net_device_stats *stats = &sl->dev->stats;
 #endif

-       if (!sl || sl->magic != SLCAN_MAGIC ||
-           !netif_running(sl->dev))
+       if (!sl || sl->magic != SLCAN_MAGIC || !netif_running(sl->dev))
                return;

+
        /* Read the characters out of the buffer */
        while (count--) {
                if (fp && *fp++) {
@@ -628,7 +922,7 @@
 {
        int i;
        struct net_device *dev;
-       struct slcan      *sl;
+       struct slcan *sl;

        for (i = 0; i < maxdev; i++) {
                dev = slcan_devs[i];
@@ -638,12 +932,11 @@
                sl = netdev_priv(dev);
                if (sl->tty || sl->leased)
                        continue;
-               if (dev->flags&IFF_UP)
+               if (dev->flags & IFF_UP)
                        dev_close(dev);
        }
 }

-
 /* Find a free SLCAN channel, and link in this `tty' line. */
 static struct slcan *slc_alloc(dev_t line)
 {
@@ -651,10 +944,10 @@
        int sel = -1;
        int score = -1;
        struct net_device *dev = NULL;
-       struct slcan       *sl;
+       struct slcan *sl;

        if (slcan_devs == NULL)
-               return NULL;    /* Master array missing ! */
+               return NULL; /* Master array missing ! */

        for (i = 0; i < maxdev; i++) {
                dev = slcan_devs[i];
@@ -729,14 +1022,16 @@
                dev = alloc_netdev(sizeof(*sl), name, slc_setup);
                if (!dev)
                        return NULL;
-               dev->base_addr  = i;
+               dev->base_addr = i;
        }

        sl = netdev_priv(dev);

+
        /* Initialize channel control data */
-       sl->magic       = SLCAN_MAGIC;
-       sl->dev         = dev;
+       sl->magic = SLCAN_MAGIC;
+       sl->dev = dev;
+       sl->to_ack = 0;
        spin_lock_init(&sl->lock);
        slcan_devs[i] = dev;

@@ -752,7 +1047,6 @@
  *
  * Called in process context serialized from other ldisc calls.
  */
-
 static int slcan_open(struct tty_struct *tty)
 {
        struct slcan *sl;
@@ -766,12 +1060,14 @@
                return -EOPNOTSUPP;
 #endif

+
        /* RTnetlink lock is misused here to serialize concurrent
-          opens of slcan channels. There are better ways, but it is
-          the simplest one.
+        opens of slcan channels. There are better ways, but it is
+        the simplest one.
         */
        rtnl_lock();

+
        /* Collect hanged up channels. */
        slc_sync();

@@ -793,16 +1089,17 @@
        sl->line = tty_devnum(tty);
        sl->pid = current->pid;

+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
        /* FIXME: already done before we were called - seems this can go */
        if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       tty->driver->flush_buffer(tty);
 #endif

        if (!test_bit(SLF_INUSE, &sl->flags)) {
                /* Perform the low-level SLCAN initialization. */
-               sl->rcount   = 0;
-               sl->xleft    = 0;
+               sl->rcount = 0;
+               sl->xleft = 0;

                set_bit(SLF_INUSE, &sl->flags);

@@ -814,42 +1111,42 @@
        /* Done.  We have linked the TTY line to a channel. */
        rtnl_unlock();

+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
-       tty->receive_room = 65536;      /* We don't flow control */
+       tty->receive_room = 65536; /* We don't flow control */
 #endif

        return sl->dev->base_addr;

-err_free_chan:
-       sl->tty = NULL;
+       err_free_chan: sl->tty = NULL;
        tty->disc_data = NULL;
        clear_bit(SLF_INUSE, &sl->flags);

-err_exit:
-       rtnl_unlock();
+       err_exit: rtnl_unlock();

+
        /* Count references from TTY module */
        return err;
 }

 /*

-  FIXME: 1,2 are fixed 3 was never true anyway.
+ FIXME: 1,2 are fixed 3 was never true anyway.

-   Let me to blame a bit.
-   1. TTY module calls this funstion on soft interrupt.
-   2. TTY module calls this function WITH MASKED INTERRUPTS!
-   3. TTY module does not notify us about line discipline
-      shutdown,
+ Let me to blame a bit.
+ 1. TTY module calls this function on soft interrupt.
+ 2. TTY module calls this function WITH MASKED INTERRUPTS!
+ 3. TTY module does not notify us about line discipline
+ shutdown,

-   Seems, now it is clean. The solution is to consider netdevice and
-   line discipline sides as two independent threads.
+ Seems, now it is clean. The solution is to consider netdevice and
+ line discipline sides as two independent threads.

-   By-product (not desired): slc? does not feel hangups and remains open.
-   It is supposed, that user level program (dip, diald, slattach...)
-   will catch SIGHUP and make the rest of work.
+ By-product (not desired): slc? does not feel hangups and remains open.
+ It is supposed, that user level program (dip, diald, slattach...)
+ will catch SIGHUP and make the rest of work.

-   I see no way to make more with current tty code. --ANK
+ I see no way to make more with current tty code. --ANK
  */

 /*
@@ -861,6 +1158,7 @@
 {
        struct slcan *sl = (struct slcan *) tty->disc_data;

+
        /* First make sure we're connected. */
        if (!sl || sl->magic != SLCAN_MAGIC || sl->tty != tty)
                return;
@@ -870,62 +1168,71 @@
        if (!sl->leased)
                sl->line = 0;

+
        /* Count references from TTY module */
 }

 /* Perform I/O control on an active SLCAN channel. */
-static int slcan_ioctl(struct tty_struct *tty, struct file *file,
-                      unsigned int cmd, unsigned long arg)
+static int slcan_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
 {
        struct slcan *sl = (struct slcan *) tty->disc_data;
        unsigned int tmp;

+
        /* First make sure we're connected. */
        if (!sl || sl->magic != SLCAN_MAGIC)
                return -EINVAL;

        switch (cmd) {
-       case SIOCGIFNAME:
-               tmp = strlen(sl->dev->name) + 1;
-               if (copy_to_user((void __user *)arg, sl->dev->name, tmp))
-                       return -EFAULT;
-               return 0;
+               case SIOCGIFENCAP:
+                       //Do we use binary encapsulation?
+                       return sl->flags & (1 << SLF_BINENC);
+               case SIOCSIFENCAP:
+                       //Let's modify our encapsulation!
+                       if (arg > 0) {
+                               sl->flags |= (1 << SLF_BINENC);
+                               printk(KERN_INFO "slcan: Now using binary 
encapsulation on device
%s!", sl->dev->name);
+                       } else {
+                               sl->flags &= ~(1 << SLF_BINENC);
+                               printk(KERN_INFO "slcan: Now using ASCII 
encapsulation on device
%s!", sl->dev->name);
+                       }
+                       return 0;
+               case SIOCGIFNAME:
+                       tmp = strlen(sl->dev->name) + 1;
+                       if (copy_to_user((void __user *)arg, sl->dev->name, 
tmp))
+                               return -EFAULT;
+                       return 0;

-       case SIOCSIFHWADDR:
-               return -EINVAL;
+               case SIOCSIFHWADDR:
+                       return -EINVAL;

+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
-       /* Allow stty to read, but not set, the serial port */
-       case TCGETS:
-       case TCGETA:
-               return n_tty_ioctl(tty, file, cmd, arg);
+                       /* Allow stty to read, but not set, the serial port */
+                       case TCGETS:
+                       case TCGETA:
+                       return n_tty_ioctl(tty, file, cmd, arg);

-       default:
-               return -ENOIOCTLCMD;
+                       default:
+                       return -ENOIOCTLCMD;
 #else
-       default:
-               return tty_mode_ioctl(tty, file, cmd, arg);
+               default:
+                       return tty_mode_ioctl(tty, file, cmd, arg);
 #endif
        }
 }

 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
-static struct tty_ldisc        slc_ldisc = {
+static struct tty_ldisc slc_ldisc = {
 #else
 static struct tty_ldisc_ops slc_ldisc = {
 #endif
-       .owner          = THIS_MODULE,
-       .magic          = TTY_LDISC_MAGIC,
-       .name           = "slcan",
-       .open           = slcan_open,
-       .close          = slcan_close,
-       .ioctl          = slcan_ioctl,
-       .receive_buf    = slcan_receive_buf,
+               .owner = THIS_MODULE, .magic = TTY_LDISC_MAGIC, .name = "slcan",
.open = slcan_open, .close = slcan_close,
+               .ioctl = slcan_ioctl, .receive_buf = slcan_receive_buf,
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
-       .receive_room   = slcan_receive_room,
+               .receive_room = slcan_receive_room,
 #endif
-       .write_wakeup   = slcan_write_wakeup,
-};
+               .write_wakeup = slcan_write_wakeup, };

 /************************************
  * general slcan module init/exit
@@ -936,8 +1243,11 @@
        int status;

        if (maxdev < 4)
-               maxdev = 4; /* Sanity */
+       maxdev = 4; /* Sanity */

+       if (maxack < 1)
+       maxack = 1; /* Dito */
+
        printk(banner);
        printk(KERN_INFO "slcan: %d dynamic interface channels.\n", maxdev);

@@ -952,7 +1262,7 @@

        /* Fill in our line protocol discipline, and register it */
        status = tty_register_ldisc(N_SLCAN, &slc_ldisc);
-       if (status != 0)  {
+       if (status != 0) {
                printk(KERN_ERR "slcan: can't register line discipline\n");
                kfree(slcan_devs);
        }
@@ -968,19 +1278,19 @@
        int busy = 0;

        if (slcan_devs == NULL)
-               return;
+       return;

        /* First of all: check for active disciplines and hangup them.
         */
        do {
                if (busy)
-                       msleep_interruptible(100);
+               msleep_interruptible(100);

                busy = 0;
                for (i = 0; i < maxdev; i++) {
                        dev = slcan_devs[i];
                        if (!dev)
-                               continue;
+                       continue;
                        sl = netdev_priv(dev);
                        spin_lock_bh(&sl->lock);
                        if (sl->tty) {
@@ -989,19 +1299,18 @@
                        }
                        spin_unlock_bh(&sl->lock);
                }
-       } while (busy && time_before(jiffies, timeout));
+       }while (busy && time_before(jiffies, timeout));

-
        for (i = 0; i < maxdev; i++) {
                dev = slcan_devs[i];
                if (!dev)
-                       continue;
+               continue;
                slcan_devs[i] = NULL;

                sl = netdev_priv(dev);
                if (sl->tty) {
                        printk(KERN_ERR "%s: tty discipline still running\n",
-                              dev->name);
+                                       dev->name);
                        /* Intentionally leak the control block. */
                        dev->destructor = NULL;
                }
@@ -1014,8 +1323,8 @@

        i = tty_unregister_ldisc(N_SLCAN);
        if (i)
-               printk(KERN_ERR "slcan: can't unregister ldisc (err %d)\n", i);
+       printk(KERN_ERR "slcan: can't unregister ldisc (err %d)\n", i);
 }

-module_init(slcan_init);
-module_exit(slcan_exit);
+module_init( slcan_init);
+module_exit( slcan_exit);
Index: can-utils/slcan_attach.c
===================================================================
--- can-utils/slcan_attach.c    (Revision 1054)
+++ can-utils/slcan_attach.c    (Arbeitskopie)
@@ -45,18 +45,22 @@
  *
  */

-#include <stdio.h>
+#include <termios.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
+#include <stdio.h>
 #include <getopt.h>
 #include <sys/ioctl.h>
+#include <sys/select.h>
+#include <sys/file.h>

+#define BUFFERSIZE 20
 #define LDISC_N_SLCAN 17 /* default slcan line discipline since
Kernel 2.6.25 */

-void print_usage(char *prg)
-{
+void print_usage(char *prg) {
        fprintf(stderr, "\nUsage: %s [options] tty\n\n", prg);
        fprintf(stderr, "Options: -o         (send open command 'O\\r')\n");
        fprintf(stderr, "         -c         (send close command 'C\\r')\n");
@@ -64,6 +68,7 @@
        fprintf(stderr, "         -b <btr>   (set bit time register value)\n");
        fprintf(stderr, "         -d         (only detach line discipline)\n");
        fprintf(stderr, "         -w         (attach - wait for keypess - 
detach)\n");
+       fprintf(stderr, "         -B         (use binary mode)\n");
        fprintf(stderr, "\nExamples:\n");
        fprintf(stderr, "slcan_attach -w -o -s6 -c /dev/ttyS1\n");
        fprintf(stderr, "slcan_attach /dev/ttyS1\n");
@@ -72,26 +77,30 @@
        exit(1);
 }

-int main(int argc, char **argv)
-{
+int main(int argc, char **argv) {
        int fd;
        int ldisc = LDISC_N_SLCAN;
        int detach = 0;
        int waitkey = 0;
        int send_open = 0;
        int send_close = 0;
+       int binary = 0;
        char *speed = NULL;
        char *btr = NULL;
        char buf[10];
        char *tty;
        int opt;

-       while ((opt = getopt(argc, argv, "l:dwocs:b:?")) != -1) {
+       while ((opt = getopt(argc, argv, "l:dwBocs:b:?")) != -1) {
                switch (opt) {
                case 'l':
                        fprintf(stderr, "Ignored option '-l'\n");
                        break;

+               case 'B':
+                       binary = 1;
+                       break;
+
                case 'd':
                        detach = 1;
                        break;
@@ -132,7 +141,7 @@

        tty = argv[optind];

-       if ((fd = open (tty, O_WRONLY | O_NOCTTY)) < 0) {
+       if ((fd = open(tty, O_WRONLY | O_NOCTTY)) < 0) {
                perror(tty);
                exit(1);
        }
@@ -154,9 +163,13 @@
                        write(fd, buf, strlen(buf));
                }

-               if (ioctl (fd, TIOCSETD, &ldisc) < 0) {
+               if (ioctl(fd, TIOCSETD, &ldisc) < 0) {
                        perror("ioctl");
                        exit(1);
+               } else {
+                       if (binary)
+                               if(ioctl(fd, SIOCSIFENCAP, 1)!=0)
+                                       perror("ioctl2");
                }
        }

@@ -167,7 +180,7 @@

        if (waitkey || detach) {
                ldisc = N_TTY;
-               if (ioctl (fd, TIOCSETD, &ldisc) < 0) {
+               if (ioctl(fd, TIOCSETD, &ldisc) < 0) {
                        perror("ioctl");
                        exit(1);
                }
_______________________________________________
Socketcan-core mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/socketcan-core

Reply via email to