]> rtime.felk.cvut.cz Git - socketcan-devel.git/blobdiff - kernel/2.6/drivers/net/can/usb/ctu_usbcan.c
Added local echo support
[socketcan-devel.git] / kernel / 2.6 / drivers / net / can / usb / ctu_usbcan.c
index 036252c2061d8112e03f0f9ccb7570c4bcfce348..000018fa6c0961aabcc25d6ba5c9bcd7b4a92b6c 100644 (file)
 #include <linux/can/dev.h>
 #include <linux/can/error.h>
 
+// lpc17xx debug
+#define USBCAN_VENDOR_SET_CANBTR       (9)
+#define CTU_USBCAN_CAN_CLOCK   18000000
+// lpc17xx debug - end
+
 #define CTU_USBCAN_VENDOR_ID   0x1669
 #define CTU_USBCAN_PRODUCT_ID  0x1011
 
@@ -53,6 +58,7 @@ struct usbcan_message {
        struct urb      *u;
        struct ctu_usbcan_usb *dev;
        u8      msg[USBCAN_TRANSFER_SIZE];
+       u32 echo_index;
        u8      dlc;
        struct list_head list_node;
 };
@@ -91,6 +97,7 @@ struct ctu_usbcan_usb {
        wait_queue_head_t queue;
 
        volatile long flags;
+
 };
 
 
@@ -125,6 +132,8 @@ static void ctu_usbcan_tx_callback(struct urb *urb){
        stats->tx_packets++;
        stats->tx_bytes += m->dlc;
 
+       
+       can_get_echo_skb(m->dev->netdev, m->echo_index);
 
        set_bit(USBCAN_DATA_OK,&m->dev->flags);
        usbcan_usb_message_move_list(m->dev, m, &m->dev->tx_ready_list);
@@ -196,10 +205,10 @@ static netdev_tx_t ctu_usbcan_start_xmit(struct sk_buff *skb, struct net_device
 
        m->dlc = (u8) len;
 
-
-
        usbcan_usb_message_move_list(dev, m, &dev->tx_pend_list);
 
+       can_put_echo_skb(skb, netdev, m->echo_index);
+
        /* odeslani     */ 
        retval = usb_submit_urb(m->u, GFP_ATOMIC);
        if (retval){
@@ -274,7 +283,7 @@ void usbcan_kthread_read_handler(struct ctu_usbcan_usb *dev, struct usbcan_messa
        u16 flags = 0;
        struct net_device_stats *stats = &m->dev->netdev->stats;
 
-
+/*
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32)
        skb = alloc_can_skb(m->dev->netdev, &cf);
 #else
@@ -282,6 +291,8 @@ void usbcan_kthread_read_handler(struct ctu_usbcan_usb *dev, struct usbcan_messa
        skb->protocol = htons(ETH_P_CAN);
        cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
 #endif
+*/
+       skb = alloc_can_skb(m->dev->netdev, &cf);
 
        if (skb == NULL){
                err("RX: error alloc skb\n");
@@ -415,6 +426,8 @@ int usbcan_kthread(void *data)
                u->dev = dev->udev;
                m->dev = dev;
 
+               m->echo_index = i;
+
                usb_fill_bulk_urb(u, dev->udev,
                        usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
                        m->msg, USBCAN_TRANSFER_SIZE, ctu_usbcan_tx_callback, m);
@@ -486,9 +499,15 @@ exit:
 
 static int ctu_usbcan_open(struct net_device *netdev)
 {
+       int err;
 
        struct ctu_usbcan_usb *dev = netdev_priv(netdev);
 
+       /* common open */       
+       err = open_candev(netdev);
+       if (err)
+               return err;     
+
        /* start kernel thread */
        dev->comthread = kthread_run(usbcan_kthread, (void *)dev, "usbcan_1");
 
@@ -500,6 +519,8 @@ static int ctu_usbcan_close(struct net_device *netdev)
 
        struct ctu_usbcan_usb *dev = netdev_priv(netdev);
        kthread_stop(dev->comthread);
+
+       close_candev(netdev);
        
        return 0;
 }
@@ -510,6 +531,66 @@ static const struct net_device_ops ctu_usbcan_netdev_ops = {
        .ndo_start_xmit = ctu_usbcan_start_xmit,
 };
 
+static struct can_bittiming_const ctu_usbcan_bittiming_const = {
+       .name = "lpc17xx_can",
+       .tseg1_min = 1,
+       .tseg1_max = 16,
+       .tseg2_min = 1,
+       .tseg2_max = 8,
+       .sjw_max = 4,
+       .brp_min = 1,
+       .brp_max = 1024,
+       .brp_inc = 1,
+};
+
+static int ctu_usbcan_set_mode(struct net_device *netdev, enum can_mode mode)
+{
+       struct ems_usb *dev = netdev_priv(netdev);
+
+       printk("SET MODE\n");
+
+       return 0;
+}
+
+static int ctu_usbcan_set_bittiming(struct net_device *netdev)
+{
+       struct ctu_usbcan_usb *dev = netdev_priv(netdev);
+       struct can_bittiming *bt = &dev->can.bittiming;
+       int retval;
+       
+       u8 usbbuf[USBCAN_TRANSFER_SIZE];
+
+       printk("BRP: %d, SJW: %d, TSEG1: %d, TSEG2: %d - ", bt->brp, bt->sjw, ( bt->prop_seg + bt->phase_seg1), bt->phase_seg2);        
+
+
+       if (!dev)
+               return -ENODEV;
+
+       *(uint32_t *)(usbbuf)=cpu_to_le32(bt->brp);             // baudrate prescaler
+       *(uint32_t *)(usbbuf+4)=cpu_to_le32(bt->sjw);   // sjw
+       *(uint32_t *)(usbbuf+8)=cpu_to_le32(bt->prop_seg + bt->phase_seg1);     // TSEG1
+       *(uint32_t *)(usbbuf+12)=cpu_to_le32(bt->phase_seg2);   // TSEG2
+
+       retval = usb_control_msg(dev->udev,
+                               usb_sndctrlpipe(dev->udev, 0),
+                               USBCAN_VENDOR_SET_CANBTR,
+                               USB_TYPE_VENDOR,
+                               cpu_to_le16(0), cpu_to_le16(0),
+                               &usbbuf, USBCAN_TRANSFER_SIZE,
+                               1000);
+
+       if(retval){
+               printk("OK\n");
+               return 0;
+       }
+       else{
+               printk("KO\n");
+               return retval;
+       }
+
+}
+
+
 static int ctu_usbcan_probe(struct usb_interface *intf,
                                                        const struct usb_device_id *id)
 {
@@ -522,11 +603,14 @@ static int ctu_usbcan_probe(struct usb_interface *intf,
 
        printk(KERN_INFO "CTU USBCAN device now attached\n");
 
+/*
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32)
        netdev = alloc_candev(sizeof(struct ctu_usbcan_usb), USBCAN_TOT_TX_URBS);
 #else
        netdev = alloc_candev(sizeof(struct ctu_usbcan_usb));
 #endif
+*/
+       netdev = alloc_candev(sizeof(struct ctu_usbcan_usb), USBCAN_TOT_TX_URBS);
 
        if (!netdev) {
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,33)
@@ -542,6 +626,12 @@ static int ctu_usbcan_probe(struct usb_interface *intf,
        dev->udev = interface_to_usbdev(intf);
        dev->netdev = netdev;
 
+       dev->can.clock.freq = CTU_USBCAN_CAN_CLOCK;
+       dev->can.bittiming_const = &ctu_usbcan_bittiming_const;
+       dev->can.do_set_bittiming = ctu_usbcan_set_bittiming;
+       dev->can.do_set_mode = ctu_usbcan_set_mode;
+
+
        netdev->netdev_ops = &ctu_usbcan_netdev_ops;
        netdev->flags |= IFF_ECHO;