]> rtime.felk.cvut.cz Git - socketcan-devel.git/blobdiff - kernel/2.6/drivers/net/can/usb/ctu_usbcan.c
Getting a bit timing constants from device has been done.
[socketcan-devel.git] / kernel / 2.6 / drivers / net / can / usb / ctu_usbcan.c
index f386579cb6e57cf1d91396672434479fc41dce85..0543bc6440510b99da27e0bbc50a840c82e3213b 100644 (file)
 
 // lpc17xx debug
 #define USBCAN_VENDOR_SET_CANBTR       (9)
-#define CTU_USBCAN_CAN_CLOCK   18000000
+#define USBCAN_VENDOR_GET_BITTIMING_CONST      (10)
 // lpc17xx debug - end
 
 #define CTU_USBCAN_VENDOR_ID   0x1669
 #define CTU_USBCAN_PRODUCT_ID  0x1011
 
-#define USBCAN_TOT_RX_URBS 8
-#define USBCAN_TOT_TX_URBS 8
+#define USBCAN_TOT_RX_URBS     8
+#define USBCAN_TOT_TX_URBS     8
 
-#define USBCAN_TRANSFER_SIZE 16
+#define USBCAN_TRANSFER_SIZE   16
+#define USBCAN_BITTIMING_SIZE  16
+#define USBCAN_BITTIMING_CONST_SIZE    36
 
-#define CAN_MSG_LENGTH 8
+#define CAN_MSG_LENGTH 8
 
-#define MSG_RTR   (1<<0)
+#define MSG_RTR          (1<<0)
 #define MSG_OVR   (1<<1)
 #define MSG_EXT   (1<<2)
 #define MSG_LOCAL (1<<3)
 
-
 #define USBCAN_DATA_OK (1)
 #define USBCAN_TX_PENDING      (2)
+#define USBCAN_BITTIMING_CONST_SET     (3)
+
 
 MODULE_LICENSE("GPL");
 
@@ -58,6 +61,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;
 };
@@ -71,12 +75,14 @@ Structure of byte array msg in struct usbcan_message that represents CAN message
 
 */
 
-
 /* Structure to hold all of our device specific stuff */
 struct ctu_usbcan_usb {
 
        struct can_priv can; /* must be the first member */
 
+       struct can_bittiming_const cbc;
+       u32 can_clock;
+
        struct usb_device *udev;                        /* the usb device for this device */
        struct net_device *netdev;
 
@@ -111,6 +117,115 @@ static void usbcan_usb_message_move_list(struct ctu_usbcan_usb *dev,
 }
 
 
+static int get_bittiming_constants(struct ctu_usbcan_usb *dev)
+{
+
+       int retval;
+       u8 *usbbuf;
+       u32 * ptr;
+
+       usbbuf = kzalloc(sizeof(u8)*USBCAN_BITTIMING_CONST_SIZE, GFP_KERNEL);
+
+       if(!usbbuf){
+               err("Error allocating receive buffer for bittiming constants\n");
+               return 1;
+       }
+       
+       retval = usb_control_msg(dev->udev,
+               usb_rcvctrlpipe(dev->udev, 0),
+               USBCAN_VENDOR_GET_BITTIMING_CONST,
+               USB_TYPE_VENDOR,
+               cpu_to_le16(0), cpu_to_le16(0),
+               usbbuf, USBCAN_BITTIMING_CONST_SIZE,
+               1000);
+
+       if(retval<0)
+               goto exit;
+
+       ptr = (u32*) usbbuf;
+
+       dev->can_clock = le32_to_cpu(*(ptr++));
+       dev->cbc.tseg1_min = le32_to_cpu(*(ptr++));
+       dev->cbc.tseg1_max = le32_to_cpu(*(ptr++));
+       dev->cbc.tseg2_min = le32_to_cpu(*(ptr++));
+       dev->cbc.tseg2_max = le32_to_cpu(*(ptr++));
+       dev->cbc.sjw_max = le32_to_cpu(*(ptr++));
+       dev->cbc.brp_min = le32_to_cpu(*(ptr++));
+       dev->cbc.brp_max = le32_to_cpu(*(ptr++));
+       dev->cbc.brp_inc = le32_to_cpu(*(ptr));
+
+       set_bit(USBCAN_BITTIMING_CONST_SET,&dev->flags);
+
+
+exit:
+
+       kfree(usbbuf);
+       if(retval<0)
+               return retval;
+
+       return 0;
+
+}
+
+static int ctu_usbcan_set_mode(struct net_device *netdev, enum can_mode mode)
+{
+       
+       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;
+       u8 *usbbuf;     
+       u32 * ptr;
+       int retval;
+       
+
+       if (!dev)
+               return -ENODEV;
+
+
+       usbbuf = kzalloc(sizeof(u8)*USBCAN_BITTIMING_SIZE, GFP_KERNEL);
+
+       if(!usbbuf){
+               err("Error allocating transmit buffer for set bittiming\n");
+               return 1;
+       }       
+       
+       ptr = (u32*) usbbuf;
+
+       *(ptr++)=cpu_to_le32(bt->brp);          // baudrate prescaler
+       *(ptr++)=cpu_to_le32(bt->sjw);  // sjw
+       *(ptr++)=cpu_to_le32(bt->prop_seg + bt->phase_seg1);    // TSEG1
+       *(ptr)=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_BITTIMING_SIZE,
+                               1000);
+
+       kfree(usbbuf);
+
+       if(retval){
+               printk("BITRATE %d, BRP: %d, SJW: %d, TSEG1: %d, TSEG2: %d \n", bt->bitrate, bt->brp, bt->sjw,\
+                               (bt->prop_seg + bt->phase_seg1), bt->phase_seg2);       
+               return 0;
+       }
+       else{
+               err("Could not set bittiming\n");
+               return retval;
+       }
+
+}
+
+
 static void ctu_usbcan_tx_callback(struct urb *urb){
 
        struct usbcan_message *m = urb->context;
@@ -131,6 +246,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);
@@ -202,10 +319,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){
@@ -423,6 +540,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,7 +605,7 @@ int usbcan_kthread(void *data)
 
 exit:
        usbcan_kthread_free_urbs(dev);
-       printk("CTU USBCAN: usbcan thread finished!");
+       printk("CTU USBCAN: usbcan thread finished\n");
        
        return 0;
 
@@ -526,65 +645,6 @@ 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)
@@ -621,11 +681,6 @@ 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;
@@ -657,6 +712,16 @@ static int ctu_usbcan_probe(struct usb_interface *intf,
        usb_set_intfdata(intf, dev);
        SET_NETDEV_DEV(netdev, &intf->dev);
 
+       if (get_bittiming_constants(dev)){
+               err("Could not get bittiming constants\n");
+               goto exit;
+       }
+
+       dev->can.clock.freq = dev->can_clock;
+       dev->can.bittiming_const = &dev->cbc;
+       dev->can.do_set_bittiming = ctu_usbcan_set_bittiming;
+       dev->can.do_set_mode = ctu_usbcan_set_mode;
+
 
        err = register_candev(netdev);
        if (err) {
@@ -680,8 +745,11 @@ static void ctu_usbcan_disconnect(struct usb_interface *intf)
        usb_set_intfdata(intf, NULL);
 
        if (dev) {
-               unregister_netdev(dev->netdev);
+               if(test_bit(USBCAN_BITTIMING_CONST_SET,&dev->flags))            
+                       unregister_netdev(dev->netdev);
+
                free_candev(dev->netdev);
+               clear_bit(USBCAN_BITTIMING_CONST_SET,&dev->flags);
        }
 
 }