Wolfgang Grandegger wrote:
> Some general comments. Please respect the Linux coding style. There are
> many issue: lines too long, // comments, comment style. Please use
> checkpatch.pl to spot coding style problems.
Ok, changed accordingly.
> Furthermore, don't mix
> coding style corrections and code beautifications with functional
> changes. Please provide separate patches.
Well, as I've changed the code to respect the Linux coding style, these changes 
should be gone now...
> And this patch is line wrapped.
Finally using another mail client for patches, should work now...



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,8 +76,10 @@
 
 #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";
@@ -132,12 +135,25 @@
 module_param(maxdev, int, 0);
 MODULE_PARM_DESC(maxdev, "Maximum number of slcan interfaces");
 
-/* maximum rx buffer len: extended CAN frame with timestamp */
+/* 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 in ASCII format */
 #define SLC_MTU (sizeof("T1111222281122334455667788EA5F\r")+1)
 
 struct slcan {
        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    */
@@ -158,7 +174,17 @@
        unsigned long           flags;          /* Flag values/ mode etc     */
 #define SLF_INUSE              0               /* Channel in use            */
 #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 */
 
+/* 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;
@@ -166,7 +192,6 @@
 
 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)
@@ -210,6 +235,16 @@
  * 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
  */
 
  /************************************************************************
@@ -245,50 +280,84 @@
        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 */
+               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;
@@ -314,24 +383,205 @@
 #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 {
+                               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;
 }
 
  /************************************************************************
@@ -349,41 +599,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]);
+               /* 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);
 
-       DBG("ASCII frame = '%s'\n", sl->xbuff);
+               /* 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, (cf->can_id 
&
+                 CAN_EFF_FLAG ? 6 : 4)+cf->can_dlc);
+#else
+               actual = sl->tty->ops->write(sl->tty, sl->xbuff, (cf->can_id
+                               & CAN_EFF_FLAG ? 6 : 4) + cf->can_dlc);
+#endif
 
-       strcat(sl->xbuff, "\r"); /* add terminating character */
+       } 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 */
 
-       /* 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 (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));
+               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));
+               actual = sl->tty->ops->write(sl->tty, sl->xbuff, 
strlen(sl->xbuff));
 #endif
+       }
 #ifdef SLC_CHECK_TRANSMIT
        sl->dev->trans_start = jiffies;
 #endif
@@ -415,7 +719,12 @@
                 * 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;
        }
 
@@ -462,7 +771,6 @@
        spin_unlock(&sl->lock);
 }
 
-
 /******************************************
  *   Routines looking at netdevice side.
  ******************************************/
@@ -496,7 +804,6 @@
        return 0;
 }
 
-
 /* Netdevice UP -> DOWN routine */
 static int slc_close(struct net_device *dev)
 {
@@ -523,7 +830,7 @@
        if (sl->tty == NULL)
                return -ENODEV;
 
-       sl->flags &= (1 << SLF_INUSE);
+       sl->flags &= (1 << SLF_INUSE) | (1 << SLF_BINENC);
        netif_start_queue(dev);
        return 0;
 }
@@ -591,7 +898,6 @@
  * 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)
 {
@@ -643,7 +949,6 @@
        }
 }
 
-
 /* Find a free SLCAN channel, and link in this `tty' line. */
 static struct slcan *slc_alloc(dev_t line)
 {
@@ -737,6 +1042,7 @@
        /* Initialize channel control data */
        sl->magic       = SLCAN_MAGIC;
        sl->dev         = dev;
+       sl->to_ack      = 0;
        spin_lock_init(&sl->lock);
        slcan_devs[i] = dev;
 
@@ -752,7 +1058,6 @@
  *
  * Called in process context serialized from other ldisc calls.
  */
-
 static int slcan_open(struct tty_struct *tty)
 {
        struct slcan *sl;
@@ -885,6 +1190,21 @@
                return -EINVAL;
 
        switch (cmd) {
+       case SIOCGIFENCAP:
+               /* Do we use binary encapsulation? */
+               return test_bit(SLF_BINENC, &sl->flags);
+       case SIOCSIFENCAP:
+               /* Let's modify our encapsulation! */
+               if (arg > 0) {
+                       set_bit(SLF_BINENC, &sl->flags);
+                       printk(KERN_INFO "slcan: Now using binary encapsulation 
on device \
+                                       %s!", sl->dev->name);
+               } else {
+                       clear_bit(SLF_BINENC, &sl->flags);
+                       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))
@@ -938,6 +1258,9 @@
        if (maxdev < 4)
                maxdev = 4; /* Sanity */
 
+       if (maxack < 1)
+               maxack = 1; /* Dito */
+
        printk(banner);
        printk(KERN_INFO "slcan: %d dynamic interface channels.\n", maxdev);
 
@@ -1019,3 +1342,4 @@
 
 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