]> rtime.felk.cvut.cz Git - lincan.git/commitdiff
Unoptimized usb extension, adds proc and devfs entry removing function, changed proc...
authorJan Kriz <krizj1@fel.cvut.cz>
Tue, 15 Jul 2008 12:24:20 +0000 (14:24 +0200)
committerppisa <pisa@cmp.felk.cvut.cz>
Tue, 15 Jul 2008 12:24:00 +0000 (14:24 +0200)
lincan/include/proc.h
lincan/include/setup.h
lincan/include/usbcan.h
lincan/src/main.c
lincan/src/proc.c
lincan/src/setup.c
lincan/src/usbcan.c

index c2a3c96ab81d2856ca74f6ebeee0a929283267e0..504b58a1775e38902bd2fc80f5335eab8ad86d5f 100644 (file)
@@ -11,7 +11,9 @@
 #include "./constants.h"
 
 int can_init_procdir(void);
 #include "./constants.h"
 
 int can_init_procdir(void);
+int can_init_procentry(int board);
 int can_delete_procdir(void);
 int can_delete_procdir(void);
+int can_delete_procentry(struct candevice_t *candev);
 
 struct canproc_t {
        struct proc_dir_entry *can_proc_entry;
 
 struct canproc_t {
        struct proc_dir_entry *can_proc_entry;
@@ -31,4 +33,4 @@ struct objectproc_t {
        char lnk_name[20];
        char lnk_dev[20];
        struct proc_dir_entry *lnk;
        char lnk_name[20];
        char lnk_dev[20];
        struct proc_dir_entry *lnk;
-}; 
+};
index d35a8b1e51192a7d0fd270749478a7479a79cfb8..d07e3fda26637b14fd6f43c5390b688e7a389559 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 int init_hw_struct(void);
  */
 
 int init_hw_struct(void);
+int init_new_hw_struct(int devnr);
 int list_hw(void);
 void *can_checked_malloc(size_t size);
 int can_checked_free(void *address_p);
 int list_hw(void);
 void *can_checked_malloc(size_t size);
 int can_checked_free(void *address_p);
index 35ee4f1055218b5deaa54b9885c64eb7291a00ee..94fa0fc42c58e9cb5ee59a70aa408819a6337eea 100644 (file)
@@ -5,6 +5,16 @@
  * Version lincan-0.3  17 Jul 2008
  */
 
  * Version lincan-0.3  17 Jul 2008
  */
 
+#ifndef USBCAN_H
+#define USBCAN_H
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/kref.h>
+#include <asm/uaccess.h>
+#include <linux/usb.h>
+
 int usbcan_request_io(struct candevice_t *candev);
 int usbcan_release_io(struct candevice_t *candev);
 int usbcan_reset(struct candevice_t *candev);
 int usbcan_request_io(struct candevice_t *candev);
 int usbcan_release_io(struct candevice_t *candev);
 int usbcan_reset(struct candevice_t *candev);
@@ -27,4 +37,7 @@ int usbcan_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
 int usbcan_fill_chipspecops(struct canchip_t *chip);
 int usbcan_irq_handler(int irq, struct canchip_t *chip);
 
 int usbcan_fill_chipspecops(struct canchip_t *chip);
 int usbcan_irq_handler(int irq, struct canchip_t *chip);
 
+int usbcan_init(void);
+void usbcan_exit(void);
 
 
+#endif /*USBCAN_H*/
\ No newline at end of file
index 319a09ea2a567cc38e4aaf99024fe611d4372fd9..115354edfc8a14813f4a48045f4d84191d250223 100644 (file)
 #include "../include/can_iortl.h"
 #endif /*CAN_WITH_RTL*/
 
 #include "../include/can_iortl.h"
 #endif /*CAN_WITH_RTL*/
 
+#if defined(CONFIG_OC_LINCAN_CARD_ul_usb1)
+       #include "../include/usbcan.h"
+#endif
+
 can_spinlock_t canuser_manipulation_lock;
 
 int major=CAN_MAJOR;
 can_spinlock_t canuser_manipulation_lock;
 
 int major=CAN_MAJOR;
@@ -351,6 +355,15 @@ int init_module(void)
                }
         }
 #endif
                }
         }
 #endif
+
+#if defined(CONFIG_OC_LINCAN_CARD_ul_usb1)
+       res = usbcan_init();
+       if (res){
+               CANMSG("usb_register for usbcan failed. Error number %d.\n", res);
+               return -ENODEV;
+       }
+#endif
+
        return 0;
 
 #ifdef CONFIG_PROC_FS
        return 0;
 
 #ifdef CONFIG_PROC_FS
@@ -396,10 +409,219 @@ int init_module(void)
                return -ENODEV;
 }
 
                return -ENODEV;
 }
 
+
+
+
+
+struct candevice_t* register_usbdev(const char *hwname,void *anydev){
+       int i=0, j, board;
+       struct candevice_t *candev;
+       struct canchip_t *chip;
+       struct boardtype_t *brp;
+
+       while ( (hw[board] != NULL) && (board < MAX_HW_CARDS) )
+               board++;
+       brp = boardtype_find(hwname);
+       if(!brp) {
+               CANMSG("Sorry, hardware \"%s\" is currently not supported.\n",hw[board]);
+               return NULL;
+       }
+       if (board==MAX_HW_CARDS){
+                       CANMSG("Device \"%s\" could not be registered due to internal limits.\n",hw[board]);
+                       return NULL;
+       }
+       hw[board]=brp->boardtype;
+
+       if (init_new_hw_struct(board))
+               return NULL;
+
+       #ifdef CAN_DEBUG
+               list_hw();
+       #endif
+
+       candev=hardware_p->candevice[board];
+
+       candev->sysdevptr.anydev=anydev;
+
+       if (candev->hwspecops->request_io(candev))
+               goto request_io_error;
+       candev->flags|=CANDEV_IO_RESERVED;
+
+       if (candev->hwspecops->reset(candev))
+               goto reset_error;
+
+       for(j=0; j<candev->nr_all_chips; j++) {
+               if((chip=candev->chip[j])==NULL)
+                       continue;
+
+               if(chip->chipspecops->attach_to_chip(chip)<0) {
+                       CANMSG("Initial attach to the chip HW failed\n");
+                       goto interrupt_error;
+               }
+
+               chip->flags |= CHIP_ATTACHED;
+
+               if(can_chip_setup_irq(chip)<0) {
+                       CANMSG("Error to setup chip IRQ\n");
+                       goto interrupt_error;
+               }
+       }
+
+       if (candev->flags & CANDEV_PROGRAMMABLE_IRQ)
+               if (candev->hwspecops->program_irq(candev)){
+                       CANMSG("Error to program board interrupt\n");
+                       goto interrupt_error;
+               }
+
+#ifdef CONFIG_PROC_FS
+       if (can_init_procentry(board))
+               goto proc_error;
+#endif
+
+#if defined(CONFIG_DEVFS_FS) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+       {
+               #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0))
+               char dev_name[32];
+               #else
+               struct class_device *this_dev;
+               #endif
+               int dev_minor;
+               for(i=0;i<MAX_TOT_MSGOBJS;i++) {
+                       if(!objects_p[i]) continue;
+                       if(objects_p[i]->hostchip->hostdevice != candev) continue;
+
+                       dev_minor=objects_p[i]->minor;
+                       #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0))
+                       sprintf (dev_name, "can%d", dev_minor);
+                       devfs_handles[i]=devfs_register(NULL, dev_name,
+                       DEVFS_FL_DEFAULT, major, dev_minor,
+                       S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
+                       &can_fops, (void*)objects_p[i]);
+                       #else
+                       #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,14))
+                       this_dev=class_device_create(can_class, MKDEV(major, dev_minor), NULL,  "can%d", dev_minor);
+                       #else /* >= 2.6.15 */
+                       this_dev=class_device_create(can_class, NULL, MKDEV(major, dev_minor), NULL,  "can%d", dev_minor);
+                       #endif /* >= 2.6.15 */
+                       if(IS_ERR(this_dev)){
+                               CANMSG("problem to create device \"can%d\" in the class \"can\"\n", dev_minor);
+                       }else{
+                               /*this_dev->class_data=objects_p[i];*/
+                               class_set_devdata(this_dev,objects_p[i]);
+                       }
+                       #ifdef CONFIG_DEVFS_FS
+                       devfs_mk_cdev(MKDEV(major, dev_minor), S_IFCHR | S_IRUGO | S_IWUGO, "can%d", dev_minor);
+                       #endif
+                       #endif
+               }
+       }
+#endif
+       return candev;
+
+#ifdef CONFIG_PROC_FS
+       proc_error: ;
+               CANMSG("Error registering /proc entry.\n");
+               goto memory_error;
+#endif
+
+       interrupt_error: ;
+               goto memory_error;
+
+       reset_error: ;
+               CANMSG("Error resetting device.\n");
+               goto memory_error;
+
+       request_io_error: ;
+               CANMSG("Error to request IO resources for device.\n");
+               goto memory_error;
+
+       memory_error: ;
+
+               #ifdef CAN_WITH_RTL
+       rtldev_error:
+               #endif /*CAN_WITH_RTL*/
+
+//     register_error:
+               if ( can_del_mem_list() )
+                       CANMSG("Error deallocating memory\n");
+
+               return NULL;
+}
+
+
+
+
+
+
+
+void cleanup_usbdev(struct candevice_t *dev)
+{
+       int i=0;
+       int dev_minor;
+
+#ifdef CONFIG_PROC_FS
+       if (can_delete_procentry(dev))
+               CANMSG("Error unregistering /proc/can entry.\n");
+#endif
+
+#if defined(CONFIG_DEVFS_FS) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+       for(i=0;i<MAX_TOT_MSGOBJS;i++) {
+               if(!objects_p[i]) continue;
+               if(objects_p[i]->hostchip->hostdevice != dev) continue;
+               #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0))
+               if(devfs_handles[i])
+                       devfs_unregister(devfs_handles[i]);
+               #else
+               dev_minor=objects_p[i]->minor;
+               if(dev_minor>=0){
+                       #ifdef CONFIG_DEVFS_FS
+                       devfs_remove("can%d", dev_minor);
+                       #endif
+                       class_device_destroy(can_class, MKDEV(major, dev_minor));
+               }
+               #endif
+       }
+#endif
+
+       for(i=0;i<MAX_TOT_MSGOBJS;i++) {
+               if(!objects_p[i]) continue;
+               if(objects_p[i]->hostchip->hostdevice != dev) continue;
+               canqueue_ends_done_chip(objects_p[i]->qends);
+               can_checked_free(objects_p[i]->qends);
+               can_checked_free(objects_p[i]);
+               objects_p[i]=NULL;
+       }
+
+       for(i=0;i<MAX_TOT_CHIPS;i++){
+               if(!chips_p[i]) continue;
+               if(chips_p[i]->hostdevice != dev) continue;
+               can_checked_free(chips_p[i]->chipspecops);
+               can_checked_free(chips_p[i]);
+               chips_p[i]=NULL;
+       }
+
+       hardware_p->candevice[dev->candev_idx]=NULL;
+       hardware_p->nr_boards--;
+       //kfree(hw[dev->candev_idx]);
+       hw[dev->candev_idx]=NULL;
+       can_checked_free(dev->hwspecops);
+       can_checked_free(dev);
+//     if ( can_del_mem_list() )
+//             CANMSG("Error deallocating memory\n");
+
+}
+
+
+
+
 void cleanup_module(void)
 {
        int res=0,i=0;
 
 void cleanup_module(void)
 {
        int res=0,i=0;
 
+#if defined(CONFIG_OC_LINCAN_CARD_ul_usb1)
+       ul_usb1_exit();
+#endif
+
 #ifdef CONFIG_PROC_FS
        if (can_delete_procdir())
                CANMSG("Error unregistering /proc/can entry.\n");
 #ifdef CONFIG_PROC_FS
        if (can_delete_procdir())
                CANMSG("Error unregistering /proc/can entry.\n");
index 3957e5f99e80bce64505a81729c1797a4f0c1384..a73f71e425ada6d1bc1cf3e4e1344499ea581f5b 100644 (file)
@@ -5,7 +5,7 @@
  * email:pisa@cmp.felk.cvut.cz
  * This software is released under the GPL-License.
  * Version lincan-0.3  17 Jun 2004
  * email:pisa@cmp.felk.cvut.cz
  * This software is released under the GPL-License.
  * Version lincan-0.3  17 Jun 2004
- */ 
+ */
 
 #include "../include/can.h"
 #include "../include/can_sysdep.h"
 
 #include "../include/can.h"
 #include "../include/can_sysdep.h"
 
 #define __NO_VERSION__
 #include <linux/module.h>
 
 #define __NO_VERSION__
 #include <linux/module.h>
+#include <linux/mutex.h>
 
 int add_channel_to_procdir(struct candevice_t *candev);
 
 int add_channel_to_procdir(struct candevice_t *candev);
-int remove_channel_from_procdir(void);
+int remove_channels_from_procdir(void);
+int remove_channel_from_procdir(struct candevice_t *candev);
 int add_object_to_procdir(int chip_nr);
 int remove_object_from_procdir(int chip_nr);
 
 int add_object_to_procdir(int chip_nr);
 int remove_object_from_procdir(int chip_nr);
 
@@ -29,6 +31,7 @@ static int cc=0; /* static counter for each CAN chip */
 
 static struct canproc_t can_proc_base;
 static struct canproc_t *base=&can_proc_base;
 
 static struct canproc_t can_proc_base;
 static struct canproc_t *base=&can_proc_base;
+DEFINE_MUTEX(proc_mutex);              /* synchronize access to canproc_t array */
 
 /* The following functions are needed only for kernel version 2.2. Kernel
  * version 2.4 already defines them for us.
 
 /* The following functions are needed only for kernel version 2.2. Kernel
  * version 2.4 already defines them for us.
@@ -48,14 +51,14 @@ static struct proc_dir_entry * can_create_proc_entry(const char *name, mode_t mo
        struct proc_dir_entry *new_entry = NULL;
        char *namestore;
        int namelen;
        struct proc_dir_entry *new_entry = NULL;
        char *namestore;
        int namelen;
-       
+
        if(!name || !parent)
                return NULL;
        namelen=strlen(name);
        if(!namelen)
                return NULL;
 
        if(!name || !parent)
                return NULL;
        namelen=strlen(name);
        if(!namelen)
                return NULL;
 
-       new_entry = (struct proc_dir_entry *) 
+       new_entry = (struct proc_dir_entry *)
                        can_checked_malloc(sizeof(struct proc_dir_entry)+namelen+1);
 
        if (new_entry == NULL)
                        can_checked_malloc(sizeof(struct proc_dir_entry)+namelen+1);
 
        if (new_entry == NULL)
@@ -94,7 +97,7 @@ static int can_remove_proc_entry(struct proc_dir_entry *del, struct proc_dir_ent
 static int can_proc_readlink(struct proc_dir_entry *ent, char *page)
 {
        char *link_dest = (char*)ent->data;
 static int can_proc_readlink(struct proc_dir_entry *ent, char *page)
 {
        char *link_dest = (char*)ent->data;
-       
+
        strcpy(page, link_dest);
        return strlen(link_dest);
 }
        strcpy(page, link_dest);
        return strlen(link_dest);
 }
@@ -106,8 +109,8 @@ static inline struct proc_dir_entry *can_proc_symlink(const char *name,
                 struct proc_dir_entry *parent, const char *dest)
 {
        struct proc_dir_entry *entry;
                 struct proc_dir_entry *parent, const char *dest)
 {
        struct proc_dir_entry *entry;
-       
-       
+
+
        entry = can_create_proc_entry(name, S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, parent);
        if (entry == NULL)
                return NULL;
        entry = can_create_proc_entry(name, S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, parent);
        if (entry == NULL)
                return NULL;
@@ -149,7 +152,10 @@ int can_init_procdir(void)
 {
        int board;
        struct candevice_t *candev;
 {
        int board;
        struct candevice_t *candev;
-       base->can_proc_entry = can_create_proc_entry("can", S_IFDIR | S_IRUGO | 
+
+       mutex_init(&proc_mutex);
+
+       base->can_proc_entry = can_create_proc_entry("can", S_IFDIR | S_IRUGO |
                                        S_IXUGO, &proc_root);
        if (base->can_proc_entry == NULL)
                return -ENODEV;
                                        S_IXUGO, &proc_root);
        if (base->can_proc_entry == NULL)
                return -ENODEV;
@@ -157,24 +163,45 @@ int can_init_procdir(void)
        for (board=0; board<hardware_p->nr_boards; board++) {
                candev=hardware_p->candevice[board];
                if(candev) add_channel_to_procdir(candev);
        for (board=0; board<hardware_p->nr_boards; board++) {
                candev=hardware_p->candevice[board];
                if(candev) add_channel_to_procdir(candev);
-       } 
+       }
 
        return 0;
 }
 
 
        return 0;
 }
 
+/* can_init_procentry registers entry of a new board in CAN directory tree at
+ * the proc system.
+ */
+int can_init_procentry(int board)
+{
+       struct candevice_t *candev;
+       candev=hardware_p->candevice[board];
+       if(candev)
+               return add_channel_to_procdir(candev);
+       return -ENODEV;
+}
+
 /* can_delete_procdir removes the entire CAN tree from the proc system */
 int can_delete_procdir(void)
 {
 /* can_delete_procdir removes the entire CAN tree from the proc system */
 int can_delete_procdir(void)
 {
-       if (remove_channel_from_procdir()) 
+       if (remove_channels_from_procdir())
                return -ENODEV;
        /* name: "can" */
                return -ENODEV;
        /* name: "can" */
-       if (can_remove_proc_entry(base->can_proc_entry, &proc_root)) 
+       if (can_remove_proc_entry(base->can_proc_entry, &proc_root))
+               return -ENODEV;
+
+       return 0;
+}
+
+/* can_delete_procentry removes device entries from CAN tree in the proc system */
+int can_delete_procentry(struct candevice_t *candev)
+{
+       if (remove_channel_from_procdir(candev))
                return -ENODEV;
 
        return 0;
 }
 
                return -ENODEV;
 
        return 0;
 }
 
-static int can_chip_procinfo(char *buf, char **start, off_t offset, 
+static int can_chip_procinfo(char *buf, char **start, off_t offset,
                 int count, int *eof, void *data)
 {
        struct canchip_t *chip=data;
                 int count, int *eof, void *data)
 {
        struct canchip_t *chip=data;
@@ -207,58 +234,108 @@ int add_channel_to_procdir(struct candevice_t *candev)
 {
        int i=0;
 
 {
        int i=0;
 
-       for (i=0; i < candev->nr_all_chips; i++) {
+       mutex_lock(&proc_mutex);
+       for (i=0; i < MAX_TOT_CHIPS; i++){
+               if (!chips_p[i]) continue;
+               if (chips_p[i]->hostdevice != candev) continue;
 
 
-               base->channel[cc] = (struct channelproc_t *)
+               base->channel[i] = (struct channelproc_t *)
                        can_checked_malloc(sizeof(struct channelproc_t));
                        can_checked_malloc(sizeof(struct channelproc_t));
-               if (base->channel[cc] == NULL)
+               if (base->channel[i] == NULL){
+                       mutex_unlock(&proc_mutex);
                        return -ENOMEM;
                        return -ENOMEM;
+               }
 
 
-               sprintf(base->channel[cc]->ch_name, "channel%d",cc);
-                                               
-               base->channel[cc]->ch_entry = can_create_proc_entry(
-                                               base->channel[cc]->ch_name,
+               sprintf(base->channel[i]->ch_name, "channel%d",i);
+
+               base->channel[i]->ch_entry = can_create_proc_entry(
+                                               base->channel[i]->ch_name,
                                                S_IFDIR | S_IRUGO |S_IXUGO,
                                                base->can_proc_entry);
 
                                                S_IFDIR | S_IRUGO |S_IXUGO,
                                                base->can_proc_entry);
 
-               if (base->channel[cc]->ch_entry == NULL)
+               if (base->channel[i]->ch_entry == NULL){
+                       mutex_unlock(&proc_mutex);
                        return -ENODEV;
                        return -ENODEV;
+               }
 
 
-               add_object_to_procdir(cc);
+               add_object_to_procdir(i);
 
                create_proc_read_entry("chip_info",        /* proc entry name */
                                       0,                  /* protection mask, 0->default */
 
                create_proc_read_entry("chip_info",        /* proc entry name */
                                       0,                  /* protection mask, 0->default */
-                                      base->channel[cc]->ch_entry,  /* parent dir, NULL->/proc */
+                                      base->channel[i]->ch_entry,  /* parent dir, NULL->/proc */
                                       can_chip_procinfo,
                                       can_chip_procinfo,
-                                      candev->chip[i]);
-
+                                      chips_p[i]);
                cc++;
                cc++;
-       } 
+       }
+       mutex_unlock(&proc_mutex);
 
        return 0;
 }
 
 
        return 0;
 }
 
-int remove_channel_from_procdir(void)
+int remove_channels_from_procdir(void)
 {
 {
-       
-       while (cc != 0) {
+       int i=0;
+
+       mutex_lock(&proc_mutex);
+       for (i=0; i < MAX_TOT_CHIPS; i++){
+               if (!chips_p[i]) continue;
+
                cc--;
                cc--;
-               
-               if(!base->channel[cc]) continue;
-
-               remove_proc_entry("chip_info", base->channel[cc]->ch_entry);
-               
-               if (remove_object_from_procdir(cc))
-                       return -ENODEV; 
-                       
+
+               if(!base->channel[i]) continue;
+
+               remove_proc_entry("chip_info", base->channel[i]->ch_entry);
+
+               if (remove_object_from_procdir(i)){
+                       mutex_unlock(&proc_mutex);
+                       return -ENODEV;
+               }
+
                /* name: base->channel[cc]->ch_name */
                /* name: base->channel[cc]->ch_name */
-               if (can_remove_proc_entry(base->channel[cc]->ch_entry,
-                                                       base->can_proc_entry))
+               if (can_remove_proc_entry(base->channel[i]->ch_entry,
+                                                       base->can_proc_entry)){
+                       mutex_unlock(&proc_mutex);
                        return -ENODEV;
                        return -ENODEV;
-                       
-               can_checked_free(base->channel[cc]);
-               base->channel[cc] = NULL;
+               }
+
+               can_checked_free(base->channel[i]);
+               base->channel[i] = NULL;
        }
        }
+       mutex_unlock(&proc_mutex);
+
+       return 0;
+}
+
+int remove_channel_from_procdir(struct candevice_t *candev)
+{
+       int i=0,j=0;
+
+       mutex_lock(&proc_mutex);
+       for (i=0; i < MAX_TOT_CHIPS; i++){
+               if (!chips_p[i]) continue;
+               if (chips_p[i]->hostdevice != candev) continue;
+               if (!base->channel[i]) continue;
+
+               remove_proc_entry("chip_info", base->channel[i]->ch_entry);
+
+               if (remove_object_from_procdir(i)){
+                       mutex_unlock(&proc_mutex);
+                       return -ENODEV;
+               }
+
+               /* name: base->channel[cc]->ch_name */
+               if (can_remove_proc_entry(base->channel[i]->ch_entry,
+                                                       base->can_proc_entry)){
+                       mutex_unlock(&proc_mutex);
+                       return -ENODEV;
+               }
+
+               can_checked_free(base->channel[i]);
+               base->channel[i] = NULL;
+
+               cc--;
+       }
+       mutex_unlock(&proc_mutex);
 
        return 0;
 }
 
        return 0;
 }
@@ -279,7 +356,7 @@ int add_object_to_procdir(int chip_nr)
 
                sprintf(base->channel[chip_nr]->object[i]->obj_name,"object%d",i);
                sprintf(base->channel[chip_nr]->object[i]->lnk_name,"dev");
 
                sprintf(base->channel[chip_nr]->object[i]->obj_name,"object%d",i);
                sprintf(base->channel[chip_nr]->object[i]->lnk_name,"dev");
-                                                               
+
                base->channel[chip_nr]->object[i]->obj_entry = can_create_proc_entry(
                                base->channel[chip_nr]->object[i]->obj_name,
                                S_IFDIR | S_IRUGO | S_IXUGO,
                base->channel[chip_nr]->object[i]->obj_entry = can_create_proc_entry(
                                base->channel[chip_nr]->object[i]->obj_name,
                                S_IFDIR | S_IRUGO | S_IXUGO,
@@ -299,7 +376,7 @@ int add_object_to_procdir(int chip_nr)
 
        }
        return 0;
 
        }
        return 0;
-} 
+}
 
 int remove_object_from_procdir(int chip_nr)
 {
 
 int remove_object_from_procdir(int chip_nr)
 {
@@ -309,10 +386,10 @@ int remove_object_from_procdir(int chip_nr)
 
        for (i=0; i<obj; i++) {
                if(!base->channel[chip_nr]->object[i]) continue;
 
        for (i=0; i<obj; i++) {
                if(!base->channel[chip_nr]->object[i]) continue;
-               
+
                /* name: base->channel[chip_nr]->object[i]->lnk_name */
                if (can_remove_proc_entry( base->channel[chip_nr]->object[i]->lnk,
                /* name: base->channel[chip_nr]->object[i]->lnk_name */
                if (can_remove_proc_entry( base->channel[chip_nr]->object[i]->lnk,
-                               base->channel[chip_nr]->object[i]->obj_entry))  
+                               base->channel[chip_nr]->object[i]->obj_entry))
                        return -ENODEV;
                /* name: base->channel[chip_nr]->object[i]->obj_name */
                if (can_remove_proc_entry(
                        return -ENODEV;
                /* name: base->channel[chip_nr]->object[i]->obj_name */
                if (can_remove_proc_entry(
index ac8378922880c0b9af287be4693ef4fa04accc1c..c96658482fe9f9aa2acd557627b232e8aaccc4c1 100644 (file)
@@ -5,7 +5,7 @@
  * email:pisa@cmp.felk.cvut.cz
  * This software is released under the GPL-License.
  * Version lincan-0.3  17 Jun 2004
  * email:pisa@cmp.felk.cvut.cz
  * This software is released under the GPL-License.
  * Version lincan-0.3  17 Jun 2004
- */ 
+ */
 
 #include "../include/can.h"
 #include "../include/can_sysdep.h"
 
 #include "../include/can.h"
 #include "../include/can_sysdep.h"
@@ -34,7 +34,7 @@ int can_base_addr_fixup(struct candevice_t *candev, unsigned long new_base)
 {
        unsigned long offs;
        int i, j;
 {
        unsigned long offs;
        int i, j;
-       
+
        offs=new_base-candev->dev_base_addr;
        candev->dev_base_addr=new_base;
        for(i=0;i<candev->nr_all_chips;i++){
        offs=new_base-candev->dev_base_addr;
        candev->dev_base_addr=new_base;
        for(i=0;i<candev->nr_all_chips;i++){
@@ -47,7 +47,7 @@ int can_base_addr_fixup(struct candevice_t *candev, unsigned long new_base)
 
 /**
  * can_check_dev_taken - checks if bus device description is already taken by driver
 
 /**
  * can_check_dev_taken - checks if bus device description is already taken by driver
- * @anydev:    pointer to bus specific Linux device description 
+ * @anydev:    pointer to bus specific Linux device description
  *
  * Returns: Returns 1 if device is already used by LinCAN driver, 0 otherwise.
  */
  *
  * Returns: Returns 1 if device is already used by LinCAN driver, 0 otherwise.
  */
@@ -64,7 +64,7 @@ int can_check_dev_taken(void *anydev)
                if(boarddev == anydev)
                        return 1;
        }
                if(boarddev == anydev)
                        return 1;
        }
-       
+
        return 0;
 }
 
        return 0;
 }
 
@@ -80,7 +80,7 @@ int register_obj_struct(struct msgobj_t *obj, int minorbase)
 {
        static int next_minor=0;
        int i;
 {
        static int next_minor=0;
        int i;
-       
+
        if(minorbase>=0)
                next_minor=minorbase;
        if(next_minor>=MAX_TOT_MSGOBJS)
        if(minorbase>=0)
                next_minor=minorbase;
        if(next_minor>=MAX_TOT_MSGOBJS)
@@ -111,7 +111,7 @@ int register_chip_struct(struct canchip_t *chip, int minorbase)
 {
        static int next_chip_slot=0;
        int i;
 {
        static int next_chip_slot=0;
        int i;
-       
+
        if(next_chip_slot>=MAX_TOT_CHIPS)
                next_chip_slot=0;
        i=next_chip_slot;
        if(next_chip_slot>=MAX_TOT_CHIPS)
                next_chip_slot=0;
        i=next_chip_slot;
@@ -156,6 +156,30 @@ int init_hw_struct(void)
        return 0;
 }
 
        return 0;
 }
 
+/**
+ * init_new_hw_struct - initializes driver description structures for new hardware
+ *
+ * The function init_new_hw_struct() is used to initialize the hardware structure.
+ *
+ * Return Value: returns negative number in the case of fail
+ */
+int init_new_hw_struct(int devnr)
+{
+       int irq_param_idx=0;
+       int chan_param_idx=0;
+
+       if ( (hw[devnr] != NULL) & (devnr < MAX_HW_CARDS) ) {
+               hardware_p->nr_boards++;
+
+               if (init_device_struct(devnr, &chan_param_idx, &irq_param_idx)) {
+                       CANMSG("Error initializing candevice_t structures.\n");
+                       return -ENODEV;
+               }
+       }
+
+       return 0;
+}
+
 /**
  * init_device_struct - initializes single CAN device/board
  * @card: index into @hardware_p HW description
 /**
  * init_device_struct - initializes single CAN device/board
  * @card: index into @hardware_p HW description
@@ -163,7 +187,7 @@ int init_hw_struct(void)
  * @irq_param_idx_p: pointer to the index into arrays of the per CAN channel IRQ parameters
  *
  * The function builds representation of the one board from parameters provided
  * @irq_param_idx_p: pointer to the index into arrays of the per CAN channel IRQ parameters
  *
  * The function builds representation of the one board from parameters provided
- * in the module parameters arrays: 
+ * in the module parameters arrays:
  *     @hw[card] .. hardware type,
  *     @io[card] .. base IO address,
  *     @baudrate[chan_param_idx] .. per channel baudrate,
  *     @hw[card] .. hardware type,
  *     @io[card] .. base IO address,
  *     @baudrate[chan_param_idx] .. per channel baudrate,
@@ -172,10 +196,10 @@ int init_hw_struct(void)
  * The indexes are advanced after consumed parameters if the registration is successful.
  *
  * The hardware specific operations of the device/board are initialized by call to
  * The indexes are advanced after consumed parameters if the registration is successful.
  *
  * The hardware specific operations of the device/board are initialized by call to
- * init_hwspecops() function. Then board data are initialized by board specific 
+ * init_hwspecops() function. Then board data are initialized by board specific
  * init_hw_data() function. Then chips and objects representation is build by
  * init_chip_struct() function. If all above steps are successful, chips and
  * init_hw_data() function. Then chips and objects representation is build by
  * init_chip_struct() function. If all above steps are successful, chips and
- * message objects are registered into global arrays. 
+ * message objects are registered into global arrays.
  *
  * Return Value: returns negative number in the case of fail
  */
  *
  * Return Value: returns negative number in the case of fail
  */
@@ -187,7 +211,7 @@ int init_device_struct(int card, int *chan_param_idx_p, int *irq_param_idx_p)
        int chipnr;
        long bd;
        int irqsig=-1;
        int chipnr;
        long bd;
        int irqsig=-1;
-       
+
        candev=(struct candevice_t *)can_checked_malloc(sizeof(struct candevice_t));
        if (candev==NULL)
                return -ENOMEM;
        candev=(struct candevice_t *)can_checked_malloc(sizeof(struct candevice_t));
        if (candev==NULL)
                return -ENOMEM;
@@ -220,14 +244,14 @@ int init_device_struct(int card, int *chan_param_idx_p, int *irq_param_idx_p)
 
                if(chipnr<irqnum)
                        irqsig=irq[*irq_param_idx_p+chipnr];
 
                if(chipnr<irqnum)
                        irqsig=irq[*irq_param_idx_p+chipnr];
-               
+
                bd=baudrate[*chan_param_idx_p+chipnr];
                if(!bd) bd=baudrate[0];
                bd=baudrate[*chan_param_idx_p+chipnr];
                if(!bd) bd=baudrate[0];
-       
+
                if ((ret=init_chip_struct(candev, chipnr, irqsig, bd*1000)))
                        goto error_chip;
        }
                if ((ret=init_chip_struct(candev, chipnr, irqsig, bd*1000)))
                        goto error_chip;
        }
-       
+
 
 
        for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
 
 
        for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
@@ -236,7 +260,7 @@ int init_device_struct(int card, int *chan_param_idx_p, int *irq_param_idx_p)
                int objnr;
 
                register_chip_struct(chip, m);
                int objnr;
 
                register_chip_struct(chip, m);
-               
+
                for (objnr=0; objnr<chip->max_objects; objnr++) {
                        register_obj_struct(chip->msgobj[objnr], m);
                        if(m>=0) m++;
                for (objnr=0; objnr<chip->max_objects; objnr++) {
                        register_obj_struct(chip->msgobj[objnr], m);
                        if(m>=0) m++;
@@ -261,7 +285,7 @@ int init_device_struct(int card, int *chan_param_idx_p, int *irq_param_idx_p)
        hardware_p->candevice[card]=NULL;
        can_checked_free(candev);
        return ret;
        hardware_p->candevice[card]=NULL;
        can_checked_free(candev);
        return ret;
-       
+
 }
 
 /**
 }
 
 /**
@@ -271,9 +295,9 @@ int init_device_struct(int card, int *chan_param_idx_p, int *irq_param_idx_p)
  * @irq: chip IRQ number or (-1) if not appropriate
  * @baudrate: baudrate in the units of 1Bd
  *
  * @irq: chip IRQ number or (-1) if not appropriate
  * @baudrate: baudrate in the units of 1Bd
  *
- * Chip structure is allocated and chip specific operations are filled by 
+ * Chip structure is allocated and chip specific operations are filled by
  * call to board specific init_chip_data() which calls chip specific
  * call to board specific init_chip_data() which calls chip specific
- * fill_chipspecops(). The message objects are generated by 
+ * fill_chipspecops(). The message objects are generated by
  * calls to init_obj_struct() function.
  *
  * Return Value: returns negative number in the case of fail
  * calls to init_obj_struct() function.
  *
  * Return Value: returns negative number in the case of fail
@@ -335,7 +359,7 @@ int init_obj_struct(struct candevice_t *candev, struct canchip_t *hostchip, int
 
        obj=(struct msgobj_t *)can_checked_malloc(sizeof(struct msgobj_t));
        hostchip->msgobj[objnr]=obj;
 
        obj=(struct msgobj_t *)can_checked_malloc(sizeof(struct msgobj_t));
        hostchip->msgobj[objnr]=obj;
-       if (obj == NULL) 
+       if (obj == NULL)
                return -ENOMEM;
 
         memset(obj, 0, sizeof(struct msgobj_t));
                return -ENOMEM;
 
         memset(obj, 0, sizeof(struct msgobj_t));
@@ -360,7 +384,7 @@ int init_obj_struct(struct candevice_t *candev, struct canchip_t *hostchip, int
 
        ret=candev->hwspecops->init_obj_data(hostchip,objnr);
        if(ret<0) return ret;
 
        ret=candev->hwspecops->init_obj_data(hostchip,objnr);
        if(ret<0) return ret;
-       
+
        return 0;
 }
 
        return 0;
 }
 
@@ -379,14 +403,14 @@ int init_obj_struct(struct candevice_t *candev, struct canchip_t *hostchip, int
 int init_hwspecops(struct candevice_t *candev, int *irqnum_p)
 {
        const struct boardtype_t *brp;
 int init_hwspecops(struct candevice_t *candev, int *irqnum_p)
 {
        const struct boardtype_t *brp;
-       
+
        brp = boardtype_find(candev->hwname);
        brp = boardtype_find(candev->hwname);
-       
+
        if(!brp) {
                CANMSG("Sorry, hardware \"%s\" is currently not supported.\n",candev->hwname);
                return -EINVAL;
        }
        if(!brp) {
                CANMSG("Sorry, hardware \"%s\" is currently not supported.\n",candev->hwname);
                return -EINVAL;
        }
-       
+
        if(irqnum_p)
                *irqnum_p=brp->irqnum;
        brp->board_register(candev->hwspecops);
        if(irqnum_p)
                *irqnum_p=brp->irqnum;
        brp->board_register(candev->hwspecops);
index aff02d3095df5414ce537d9fe46d3083505b46f5..ad79d58510d5b7b021b6c1fa3f6c785ff9375e8a 100644 (file)
@@ -1133,3 +1133,228 @@ int usbcan_fill_chipspecops(struct canchip_t *chip)
 {
        return 0;
 }
 {
        return 0;
 }
+
+
+
+/* --------------------------------------------------------------------------------------------------- */
+
+
+static void ul_usb1_irq(struct urb *urb)
+{
+       struct usb_ul_usb1 *dev = urb->context;
+       struct ul_usb1_combo devc;
+       int retval;
+
+       CANMSG("Interrupt poll\n");
+
+       switch (urb->status) {
+       case 0:
+               /* success */
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* this urb is terminated, clean up */
+               CANMSG("%s - urb shutting down with status: %d\n", __FUNCTION__, urb->status);
+               return;
+       default:
+               CANMSG("%s - nonzero urb status received: %d\n", __FUNCTION__, urb->status);
+               goto exit;
+       }
+
+       devc.dev = dev;
+       devc.urb = urb;
+
+       dev->candev->chip[0]->chipspecops->irq_handler(0,dev->candev->chip[0]);
+       CANMSG("Interrupt caught\n");
+
+ exit:
+       retval = usb_submit_urb (urb, GFP_ATOMIC);
+       if (retval)
+               CANMSG("%s - usb_submit_urb failed with result %d\n",
+                    __FUNCTION__, retval);
+}
+
+static void ul_usb1_delete(struct usb_ul_usb1 *dev)
+{
+       usb_put_dev(dev->udev);
+       usb_kill_urb(dev->irq);
+       usb_free_urb(dev->irq);
+       kfree(dev->bulk_in_buffer);
+       kfree(dev->int_in_buffer);
+       if (dev->candev){
+               dev->candev->sysdevptr.anydev=NULL;
+               cleanup_usbdev(dev->candev);
+       }
+       kfree(dev);
+}
+
+static int ul_usb1_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+       struct usb_ul_usb1 *dev;
+       struct usb_host_interface *iface_desc;
+       struct usb_endpoint_descriptor *endpoint;
+       struct candevice_t *candev;
+       size_t buffer_size;
+       int i;
+       int retval = -ENOMEM;
+
+       /* allocate memory for our device state and initialize it */
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev) {
+               err("Out of memory");
+               goto error;
+       }
+       sema_init(&dev->limit_sem, WRITES_IN_FLIGHT);
+       mutex_init(&dev->io_mutex);
+       spin_lock_init(&dev->err_lock);
+       init_usb_anchor(&dev->submitted);
+
+//     dev->udev = usb_get_dev(interface_to_usbdev(interface));
+       dev->udev = interface_to_usbdev(interface);
+       dev->interface = interface;
+
+       /* set up the endpoint information */
+       /* use only the first bulk-in and bulk-out endpoints */
+       iface_desc = interface->cur_altsetting;
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+               endpoint = &iface_desc->endpoint[i].desc;
+
+               if (!dev->bulk_in_endpointAddr &&
+                   usb_endpoint_is_bulk_in(endpoint)) {
+                       /* we found a bulk in endpoint */
+                       buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+                       dev->bulk_in_size = buffer_size;
+                       dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
+                       dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+                       if (!dev->bulk_in_buffer) {
+                               err("Could not allocate bulk_in_buffer");
+                               goto error;
+                       }
+               }
+
+               if (!dev->bulk_out_endpointAddr &&
+                   usb_endpoint_is_bulk_out(endpoint)) {
+                       /* we found a bulk out endpoint */
+                               dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
+               }
+
+               if (!dev->int_in_endpointAddr &&
+                   usb_endpoint_is_int_in(endpoint)) {
+                       /* we found an interrupt in endpoint */
+                       buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+                       dev->int_in_size = buffer_size;
+                       dev->int_in_endpointAddr = endpoint->bEndpointAddress;
+                       dev->int_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+                       dev->int_in_interval = endpoint->bInterval;
+                       if (!dev->int_in_buffer) {
+                               err("Could not allocate int_in_buffer");
+                               goto error;
+                       }
+               }
+       }
+       if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr && dev->int_in_endpointAddr)) {
+               err("Could not find all bulk-in, bulk-out and interrupt endpoints");
+               goto error;
+       }
+
+       /* save our data pointer in this interface device */
+       usb_set_intfdata(interface, dev);
+
+       if (main_init_done==1)
+               register_usbdev("ul_usb1",(void *) dev);
+       else {
+               mutex_lock(&usbdev_reg_mutex);
+               if (main_init_done==1)
+                       register_usbdev("ul_usb1",(void *) dev);
+               else {
+                       for (i=0;i<MAX_HW_CARDS;i++){
+                               if (usbregq[i]==NULL){
+                                       usbregq[i]=(struct usbdev_reg_query *)can_checked_malloc(sizeof(struct usbdev_reg_query));
+                                       if (!usbregq[i]){
+                                               CANMSG("Error allocating usbdev_reg_query");
+                                               mutex_unlock(&usbdev_reg_mutex);
+                                               goto error;
+                                       }
+                                       sprintf (usbregq[i]->hwname,"ul_usb1");
+                                       usbregq[i]->anydev=(void *) dev;
+                                       break;
+                               }
+                       }
+                       if (i==MAX_HW_CARDS){
+                               CANMSG("No free space to register new card");
+                               mutex_unlock(&usbdev_reg_mutex);
+                               goto error;
+                       }
+               }
+               mutex_unlock(&usbdev_reg_mutex);
+       }
+
+       dev->irq = usb_alloc_urb(0, GFP_KERNEL);
+       if (!dev->irq){
+               CANMSG("Error allocating usb urb\n");
+               goto error;
+       }
+       dev->irq->dev = dev->udev;
+       usb_fill_int_urb(dev->irq, dev->udev,
+                        usb_rcvintpipe(dev->udev, dev->int_in_endpointAddr),
+                        dev->int_in_buffer, dev->int_in_size,
+                        ul_usb1_irq, dev, dev->int_in_interval);
+/*     usb_fill_bulk_urb(dev->irq, dev->udev,
+                        usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
+                        dev->int_in_buffer, dev->int_in_size,
+                        ul_usb1_irq, dev);*/
+
+/*     dev->irq->transfer_dma = wacom->data_dma;
+       dev->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;*/
+       retval=usb_submit_urb(dev->irq, GFP_KERNEL);
+       if (retval){
+               CANMSG("INT URB %d\n",retval);
+               return -EIO;
+       }else
+               CANMSG("INT URB SUCCCESS\n");
+
+       /* let the user know what node this device is now attached to */
+       info("USB Skeleton device now attached");
+       return 0;
+
+error:
+               ul_usb1_delete(dev);
+       return retval;
+}
+
+static void ul_usb1_disconnect(struct usb_interface *interface)
+{
+       struct usb_ul_usb1 *dev;
+       int minor = interface->minor;
+
+       dev = usb_get_intfdata(interface);
+       usb_set_intfdata(interface, NULL);
+
+       /* prevent more I/O from starting */
+       mutex_lock(&dev->io_mutex);
+       dev->interface = NULL;
+       mutex_unlock(&dev->io_mutex);
+
+       //usb_kill_anchored_urbs(&dev->submitted);
+
+       ul_usb1_delete(dev);
+
+       info("USB Skeleton now disconnected");
+}
+
+static struct usb_driver ul_usb1_driver = {
+       .name =         "ul_usb1-can",
+       .id_table = ul_usb1_table,
+       .probe =        ul_usb1_probe,
+       .disconnect =   ul_usb1_disconnect,
+       .id_table =     ul_usb1_table,
+};
+
+int ul_usb1_init(void){
+       return usb_register(&ul_usb1_driver);
+}
+
+void ul_usb1_exit(void){
+       usb_deregister(&ul_usb1_driver);
+}