Hallo,

I am sending for 3rd time patch with GL620USB-A driver for usbnet.c.

I have done updates and merge for Linux 2.4.13 (use FLAG_NO_SETINT).

I have done cosmetical changes suggested by David Brownell.

Can anybody add this driver to next version?

-- 
Stanislav Brabec


--- linux/drivers/usb/usbnet.c.orig     Sun Oct 21 05:13:11 2001
+++ linux/drivers/usb/usbnet.c  Thu Oct 25 20:59:13 2001
@@ -19,6 +19,8 @@
  *     - "Linux Devices" (like iPaq and similar SA-1100 based PDAs)
  *     - NetChip 1080 (interoperates with NetChip Win32 drivers)
  *     - Prolific PL-2301/2302 (replaces "plusb" driver)
+ *     - GeneSys GL620USB-A
+
  *
  * USB devices can implement their side of this protocol at the cost
  * of two bulk endpoints; it's not restricted to "cable" applications.
@@ -76,6 +78,9 @@
  * 17-oct-2001 Handle "Advance USBNET" product, like Belkin/eTEK devices,
  *             from Ioannis Mavroukakis <[EMAIL PROTECTED]>;
  *             rx unlinks somehow weren't async; minor cleanup.
+ * 25-oct-2001 Merged GeneSys driver, using code from
+ *             Jiun-Jie Huang <[EMAIL PROTECTED]>
+ *             by Stanislav Brabec <[EMAIL PROTECTED]>
  *
  *-------------------------------------------------------------------------*/
 
@@ -104,6 +109,7 @@
 #define        CONFIG_USB_LINUXDEV
 #define        CONFIG_USB_NET1080
 #define        CONFIG_USB_PL2301
+#define        CONFIG_USB_GENELINK
 
 
 /*-------------------------------------------------------------------------*/
@@ -165,6 +171,9 @@
        struct sk_buff_head     done;
        struct tasklet_struct   bh;
        struct tq_struct        ctrl_task;
+
+       // various data structure may be needed
+       void                    *priv_data;
 };
 
 // device-specific info used by the driver
@@ -173,6 +182,7 @@
 
        int             flags;
 #define FLAG_FRAMING_NC        0x0001          /* guard against device dropouts */ 
+#define FLAG_GENELINK  0x0002          /* genelink flag */
 #define FLAG_NO_SETINT 0x0010          /* device can't set_interface() */
 
        /* reset device ... can sleep */
@@ -181,6 +191,12 @@
        /* see if peer is connected ... can sleep */
        int     (*check_connect)(struct usbnet *);
 
+       /* allocate and initialize the private resources per device */
+       int     (*initialize_private)(struct usbnet *);
+
+       /* free the private resources per device */
+       int     (*release_private)(struct usbnet *);
+
        // FIXME -- also an interrupt mechanism
 
        /* framework currently "knows" bulk EPs talk packets */
@@ -725,6 +741,199 @@
 
 
 
+#ifdef CONFIG_USB_GENELINK
+
+/*-------------------------------------------------------------------------
+ *
+ * GeneSys GL620USB-A (www.genesyslogic.com.tw)
+ *
+ *-------------------------------------------------------------------------*/
+
+// control msg write command
+#define GENELINK_CONNECT_WRITE                 0xF0
+// interrupt pipe index
+#define GENELINK_INTERRUPT_PIPE                        0x03
+// interrupt read buffer size
+#define INTERRUPT_BUFSIZE                              0x08
+// interrupt pipe interval value
+#define GENELINK_INTERRUPT_INTERVAL            0x10
+// max transmit packet number per transmit
+#define GL_MAX_TRANSMIT_PACKETS                        32
+// max packet length
+#define GL_MAX_PACKET_LEN                              1514
+// max receive buffer size 
+#define GL_RCV_BUF_SIZE                                        (((GL_MAX_PACKET_LEN + 
+4) * GL_MAX_TRANSMIT_PACKETS) + 4)
+
+struct gl_priv
+{ 
+       struct urb *irq_urb;
+       char irq_buf[INTERRUPT_BUFSIZE];
+};
+
+struct gl_packet 
+{
+       u32 packet_length;
+       char packet_data[1];
+};
+
+struct gl_header 
+{
+       u32 packet_count;
+
+       struct gl_packet packets;
+};
+
+static inline int gl_control_write(struct usbnet *dev, u8 request, u16 value)
+{
+       int retval;
+
+       retval = usb_control_msg (dev->udev,
+                                                         usb_sndctrlpipe (dev->udev, 
+0),
+                                                         request,
+                                                         USB_DIR_OUT | USB_TYPE_CLASS 
+| USB_RECIP_INTERFACE,
+                                                         value, 
+                                                         0,                    // 
+index
+                                                         0,                    // 
+data buffer
+                                                         0,                    // size
+                                                         CONTROL_TIMEOUT_JIFFIES);
+
+       return retval;
+}
+
+static void gl_interrupt_complete (struct urb *urb)
+{
+       int status = urb->status;
+       
+       if (status)
+               dbg("gl_interrupt_complete fail - %X\n", status);
+       else
+               dbg("gl_interrupt_complete success...\n");
+}
+
+static inline int gl_interrupt_read(struct usbnet *dev)
+{
+       struct gl_priv *priv = dev->priv_data;
+       int     retval;
+
+       // issue usb interrupt read
+       if (priv && priv->irq_urb) {
+               // submit urb
+               if ((retval = usb_submit_urb (priv->irq_urb)) != 0)
+                       dbg("gl_interrupt_read: submit interrupt read urb fail - 
+%X...\n", retval);
+               else
+                       dbg("gl_interrupt_read: submit interrupt read urb 
+success...\n");
+       }
+
+       return 0;
+}
+
+// check whether another side is connected
+static int genelink_check_connect (struct usbnet *dev)
+{
+       dbg ("%s: assuming peer is connected", dev->net.name);
+       return 0;
+
+       /*
+       // FIXME Uncomment this code after genelink_check_connect
+       // control hanshaking will be implemented
+
+       int                     retval;
+
+       dbg("genelink_check_connect...\n");
+
+       // issue a usb control write command to detect whether another side is 
+connected
+       if ((retval = gl_control_write(dev, GENELINK_CONNECT_WRITE, 0)) != 0) {
+               dbg ("%s: genelink_check_connect control write fail - %X\n", 
+dev->net.name, retval);
+               return retval;
+       } else {
+               dbg("%s: genelink_check_conntect control write 
+success\n",dev->net.name);
+
+               // issue a usb interrupt read command to ack another side 
+
+               if ((retval = gl_interrupt_read(dev)) != 0) {
+                       dbg("%s: genelink_check_connect interrupt read fail - %X\n", 
+dev->net.name, retval);
+                       return retval;
+               } else {
+                       dbg("%s: genelink_check_connect interrupt read success\n", 
+dev->net.name);
+               }
+
+       }
+       */
+
+       return 0;
+}
+
+// allocate and initialize the private data for genelink
+static int genelink_init_priv(struct usbnet *dev)
+{
+       struct gl_priv *priv;
+
+       // allocate the private data structure
+       if ((priv = kmalloc (sizeof *priv, GFP_KERNEL)) == 0) {
+               dbg("%s: cannot allocate private data per device", dev->net.name);
+               return -ENOMEM;
+       }
+
+       // allocate irq urb
+       if ((priv->irq_urb = usb_alloc_urb(0)) == 0) {
+               dbg("%s: cannot allocate private irq urb per device", dev->net.name);
+               kfree(priv);
+               return -ENOMEM;
+       }
+
+       // fill irq urb
+       FILL_INT_URB(priv->irq_urb, dev->udev, usb_rcvintpipe(dev->udev, 
+GENELINK_INTERRUPT_PIPE),
+                                priv->irq_buf, INTERRUPT_BUFSIZE, 
+gl_interrupt_complete, 0, GENELINK_INTERRUPT_INTERVAL);
+
+       // set private data pointer
+       dev->priv_data = priv;
+
+       return 0;
+}
+
+// release the private data
+static int genelink_release_priv(struct usbnet *dev)
+{
+       struct gl_priv *priv = dev->priv_data;
+
+       if (!priv) 
+               return 0;
+       
+       // cancel irq urb first
+       usb_unlink_urb(priv->irq_urb);
+
+       // free irq urb
+       usb_free_urb(priv->irq_urb);
+
+       // free the private data structure
+       kfree(priv);
+
+       return 0;
+}
+
+// reset the device status
+static int genelink_reset (struct usbnet *dev)
+{
+       // we don't need to reset, just return 0
+       return 0;
+}
+
+static const struct driver_info        genelink_info = {
+       description:    "Genesys GeneLink",
+       flags:          FLAG_GENELINK | FLAG_NO_SETINT,
+       reset:          genelink_reset,
+       check_connect:  genelink_check_connect,
+       initialize_private: genelink_init_priv,
+       release_private: genelink_release_priv,
+
+       in: 1, out: 2,          // direction distinguishes these
+       epsize: 64,
+};
+
+#endif /* CONFIG_USB_GENELINK */
+
+
+
 /*-------------------------------------------------------------------------
  *
  * Network Device Driver (peer link to "Host Device", from USB host)
@@ -785,6 +994,11 @@
        unsigned long           lockflags;
        size_t                  size;
 
+#ifdef CONFIG_USB_GENELINK
+       if (dev->driver_info->flags & FLAG_GENELINK)
+               size = GL_RCV_BUF_SIZE;
+       else
+#endif
        if (dev->driver_info->flags & FLAG_FRAMING_NC)
                size = FRAMED_SIZE (dev->net.mtu);
        else
@@ -908,9 +1122,114 @@
                // the extra byte we may have appended
        }
 
+#ifdef CONFIG_USB_GENELINK
+       if (dev->driver_info->flags & FLAG_GENELINK) {
+               struct gl_header *header;
+               struct gl_packet *current_packet;
+               struct sk_buff *gl_skb;
+               int status;
+               u32 size;
+
+               header = (struct gl_header *)skb->data;
+
+               // get the packet count of the received skb
+               le32_to_cpus(&header->packet_count);
+
+//             dbg("receive packet count = %d", header->packet_count);
+
+               if ((header->packet_count > GL_MAX_TRANSMIT_PACKETS) || 
+                   (header->packet_count < 0)) {
+                       dbg("genelink: illegal received packet count %d", 
+header->packet_count);
+                       goto error;
+               }
+
+               // set the current packet pointer to the first packet
+               current_packet = &(header->packets);
+
+               // decrement the length for the packet count size 4 bytes
+               skb_pull(skb, 4);
+
+               while (header->packet_count > 1) {
+                       // get the packet length
+                       size = current_packet->packet_length;
+
+                       // this may be a broken packet
+                       if (size > GL_MAX_PACKET_LEN) {
+                               dbg("genelink: illegal received packet length %d, 
+maybe a broken packet", size);
+                               goto error;
+                       }
+
+                       // allocate the skb for the individual packet
+                       gl_skb = alloc_skb (size, in_interrupt () ? GFP_ATOMIC : 
+GFP_KERNEL);
+
+                       if (gl_skb == 0)
+                               goto error;
+
+                       // copy the packet data to the new skb
+                       memcpy(gl_skb->data,current_packet->packet_data,size);
+
+                       // set skb data size
+                       gl_skb->len = size;
+/*
+                       dbg("rx_process one gl_packet, size = %d...", size);
+
+                       dbg("%02X %02X %02X %02X %02X %02X",
+                               
+(u8)gl_skb->data[0],(u8)gl_skb->data[1],(u8)gl_skb->data[2],
+                               
+(u8)gl_skb->data[3],(u8)gl_skb->data[4],(u8)gl_skb->data[5]);
+                       dbg("%02X %02X %02X %02X %02X %02X\n",
+                               
+(u8)gl_skb->data[6],(u8)gl_skb->data[7],(u8)gl_skb->data[8],
+                               
+(u8)gl_skb->data[9],(u8)gl_skb->data[10],(u8)gl_skb->data[11]);
+*/
+                       gl_skb->dev = &dev->net;
+
+                       // determine the packet's protocol ID
+                       gl_skb->protocol = eth_type_trans(gl_skb, &dev->net);
+
+                       // update the status
+                       dev->stats.rx_packets++;
+                       dev->stats.rx_bytes += size;
+
+                       // notify os of the received packet
+                       status = netif_rx (gl_skb);
+
+//                     dev_kfree_skb (gl_skb); // just for debug purpose, delete this 
+line for normal operation
+
+                       // advance to the next packet
+                       current_packet = (struct gl_packet 
+*)(current_packet->packet_data + size);
+
+                       header->packet_count --;
+
+                       // shift the data pointer to the next gl_packet
+                       skb_pull(skb, size + 4);
+               }       // while (header->packet_count > 1)
+
+               // skip the packet length field 4 bytes
+               skb_pull(skb, 4);
+       }
+#endif
+
        if (skb->len) {
                int     status;
 
+#ifdef CONFIG_USB_GENELINK
+/*
+               dbg("rx_process one packet, size = %d", skb->len);
+
+               dbg("%02X %02X %02X %02X %02X %02X",
+                       (u8)skb->data[0],(u8)skb->data[1],(u8)skb->data[2],
+                       (u8)skb->data[3],(u8)skb->data[4],(u8)skb->data[5]);
+               dbg("%02X %02X %02X %02X %02X %02X\n",
+                       (u8)skb->data[6],(u8)skb->data[7],(u8)skb->data[8],
+                       (u8)skb->data[9],(u8)skb->data[10],(u8)skb->data[11]);
+*/
+
+               if ((dev->driver_info->flags & FLAG_GENELINK) &&
+                   (skb->len > GL_MAX_PACKET_LEN)) {
+                       dbg("genelink: illegal received packet length %d, maybe a 
+broken packet", skb->len);
+                       goto error;
+               }
+#endif
+
 // FIXME: eth_copy_and_csum "small" packets to new SKB (small < ~200 bytes) ?
 
                skb->dev = &dev->net;
@@ -1063,6 +1382,9 @@
        dev->wait = 0;
        remove_wait_queue (&unlink_wakeup, &wait); 
 
+       if (dev->driver_info->release_private)
+               dev->driver_info->release_private(dev);
+
        mutex_unlock (&dev->mutex);
        return 0;
 }
@@ -1090,6 +1412,14 @@
                goto done;
        }
 
+       // initialize the private resources
+       if (info->initialize_private) {
+               if ((retval = info->initialize_private(dev)) < 0) {
+                       dbg("%s: open initialize private fail", dev->net.name);
+                       goto done;
+               }
+       }
+
        // insist peer be connected
        if (info->check_connect && (retval = info->check_connect (dev)) < 0) {
                devdbg (dev, "can't open; %d", retval);
@@ -1196,6 +1526,44 @@
 
 /*-------------------------------------------------------------------------*/
 
+#ifdef CONFIG_USB_GENELINK
+static struct sk_buff *gl_build_skb (struct sk_buff *skb)
+{
+       struct sk_buff *skb2;
+       int padlen;
+
+       int     headroom = skb_headroom (skb);
+       int     tailroom = skb_tailroom (skb);
+
+//     dbg("headroom = %d, tailroom = %d", headroom, tailroom);
+
+       padlen = ((skb->len + (4 + 4*1)) % 64) ? 0 : 1;
+
+       if ((!skb_cloned (skb)) && ((headroom + tailroom) >= (padlen + (4 + 4*1)))) {
+               if ((headroom < (4 + 4*1)) || (tailroom < padlen)) {
+                       skb->data = memmove (skb->head + (4 + 4*1),
+                                            skb->data, skb->len);
+                       skb->tail = skb->data + skb->len;
+               }
+               skb2 = skb;
+       } else {
+               skb2 = skb_copy_expand (skb, (4 + 4*1) , padlen, in_interrupt () ? 
+GFP_ATOMIC : GFP_KERNEL);
+
+               if (!skb2) {
+                       dbg("genelink: skb_copy_expand fail");
+                       return 0;
+               }
+
+               // free the original skb
+               dev_kfree_skb_any (skb);
+       }
+
+       return skb2;
+}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
 static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
 {
        struct usbnet           *dev = (struct usbnet *) net->priv;
@@ -1220,6 +1588,13 @@
                skb = skb2;
        }
 
+#ifdef CONFIG_USB_GENELINK
+       if ((info->flags & FLAG_GENELINK) && (skb = gl_build_skb(skb)) == 0) {
+               dbg("can't build skb for genelink transmit");
+               goto drop;
+       }
+#endif
+
        if (!(urb = usb_alloc_urb (0))) {
                dbg ("no urb");
                goto drop;
@@ -1238,7 +1613,27 @@
                if (!((skb->len + sizeof *trailer) & 0x01))
                        *skb_put (skb, 1) = PAD_BYTE;
                trailer = (struct nc_trailer *) skb_put (skb, sizeof *trailer);
-       } else if ((length % EP_SIZE (dev)) == 0) {
+       }
+#ifdef CONFIG_USB_GENELINK
+         else if (info->flags & FLAG_GENELINK) {
+               u32 *packet_count, *packet_len;
+
+               // attach the packet count to the header
+               packet_count = (u32 *)skb_push(skb, (4 + 4*1));
+               packet_len = packet_count + 1;
+
+               // set packet to 1
+               *packet_count = 1;
+
+               // set packet length
+               *packet_len = length;
+
+               // add padding byte
+               if ((skb->len % EP_SIZE(dev)) == 0)
+                       skb_put(skb, 1);
+       }
+#endif
+         else if ((length % EP_SIZE (dev)) == 0) {
                // not all hardware behaves with USB_ZERO_PACKET,
                // so we add an extra one-byte packet
                if (skb_shared (skb)) {
@@ -1516,10 +1911,6 @@
 },
 #endif
 
-// GeneSys GL620USB (www.genesyslogic.com.tw)
-// (patch exists against an older driver version)
-
-
 #ifdef CONFIG_USB_LINUXDEV
 /*
  * for example, this can be a host side talk-to-PDA driver.
@@ -1549,6 +1940,13 @@
 },
 #endif
 
+#ifdef CONFIG_USB_GENELINK
+{
+       USB_DEVICE (0x05e3, 0x0502),    // GL620USB-A
+       driver_info:    (unsigned long) &genelink_info,
+},
+#endif
+
        { },            // END
 };
 MODULE_DEVICE_TABLE (usb, products);
--- linux/Documentation/Configure.help.orig     Sun Oct 21 05:17:19 2001
+++ linux/Documentation/Configure.help  Thu Oct 25 20:38:52 2001
@@ -11885,9 +11885,11 @@
 CONFIG_USB_USBNET
   This driver supports network links over USB with USB "Network"
   or "data transfer" cables, often used to network laptops to PCs.
-  Such cables have chips from suppliers such as NetChip and Prolific.
-  Intelligent USB devices could also use this approach to provide
-  Internet access, using standard USB cabling.
+  Such cables have chips from suppliers such as Belkin/eTEK, GeneSys
+  (GeneLink), NetChip and Prolific. Intelligent USB devices could also
+  use this approach to provide Internet access, using standard USB
+  cabling. You can find these chips also on some motherboards with
+  USB PC2PC support.
 
   These links will have names like "usb0", "usb1", etc.  They act
   like two-node Ethernets, so you can use 802.1d Ethernet Bridging

_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to