On Thu, Sep 27, 2001 at 06:29:10AM -0700, David Brownell wrote:
> Hi,
> 
> > > -  I'd rather not see any fields like "priv_data", be config-specific.
> > >    Could you make support for that be generic (always there?)
> 
> That's mostly removing the #ifdefs relating to that feature.  Thanks!
> 
OK, I have done it. See the patch lower. I hope it is now prepared to be
merged to linux-2.4.11.



> > Opposite ends of cable calls hotplug with different product value. For
> > one side with PRODUCT=5e3/502/181 usbnet module autoloading works, but
> > for other side of cable with PRODUCT=5e3/502/180 the device is
> > recognized only after manual loading of usbnet module. Probably needs
> > aditional info to usb_device_id, but I'm not oriented in it. Can you
> > help me?
> 
> I don't understand the problem.  The patch adds:
> 
> +#ifdef CONFIG_USB_GENELINK
> +{
> + USB_DEVICE (0x05e3, 0x0502), // GL620USB/GL620USB-A
> + driver_info: (unsigned long) &genelink_info,
> +},
> +#endif
> +
> That completely ignores the version number (180 or 181), and
> nothing in that code seems to care about it.   Are you sure you
> have hotplugging set up on both ends?  Is the problem really in

Maybe it is a problem of hotplug script (hotplug gets third number,
while it is called).

I got these messages:

Sep 27 16:59:57 utx kernel: hub.c: USB new device connect on bus2/2, assigned device 
number 2
Sep 27 16:59:58 utx /etc/hotplug/usb.agent: ... no drivers for USB product 5e3/502/180
Sep 27 16:59:58 utx kernel: usb.c: USB device 2 (vend/prod 0x5e3/0x502) is not claimed 
by any active driver.
now the module was manually added:
Sep 27 17:00:12 utx kernel: usb.c: registered new driver usbnet
Sep 27 17:00:12 utx kernel: usb0: register usbnet 002/002, Genesys GeneLink

And modules.usbmap:
# usb module         idVendor idProduct bcdDevice_lo bcdDevice_hi bDeviceClass 
bDeviceSubClass bDeviceProtocol bInterfaceClass bInterfaceSubClass bInterfaceProtocol 
driver_info
usbnet               0x0003   0x05e3    0x0502       0x0000       0x00         0x00    
        0x00            0x00            0x00     0x00               0x00002c60



> driver initialization?  There was some commented-out code
> that related to a handshake for resetting both ends, which might
> conceivably affect such problems.
> 
The code is commented out delibrately. Please keep it there. Author
wrote one half of initial handshaking - initiating connection (opposite
machine was probably Windows machine). If opposite machine is Linux,
currently nobody answers this request, so connection was rejected as
timed out. I do not want to delete the code completely, because I
beleive once the rest of code will be done.


--- linux/drivers/usb/usbnet.c.orig     Sat Sep 15 00:04:07 2001
+++ linux/drivers/usb/usbnet.c  Sun Sep 30 23:00:40 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.
@@ -73,6 +75,9 @@
  *             Win32 Belkin driver; other cleanups (db).
  * 16-jul-2001 Bugfixes for uhci oops-on-unplug, Belkin support, various
  *             cleanups for problems not yet seen in the field. (db)
+ *  3-aug-2001 Merged GeneSys driver, using code from
+ *             Jiun-Jie Huang <[EMAIL PROTECTED]>
+ *             by Stanislav Brabec <[EMAIL PROTECTED]>
  *
  *-------------------------------------------------------------------------*/
 
@@ -101,6 +106,7 @@
 #define        CONFIG_USB_LINUXDEV
 #define        CONFIG_USB_NET1080
 #define        CONFIG_USB_PL2301
+#define        CONFIG_USB_GENELINK
 
 
 /*-------------------------------------------------------------------------*/
@@ -162,6 +168,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
@@ -170,6 +179,7 @@
 
        int             flags;
 #define FLAG_FRAMING   0x0001          /* guard against device dropouts */ 
+#define FLAG_GENELINK  0x0002          /* genelink flag */
 
        /* reset device ... can sleep */
        int     (*reset)(struct usbnet *);
@@ -177,6 +187,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 */
@@ -719,6 +735,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,
+       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)
@@ -782,6 +991,12 @@
        size = (dev->driver_info->flags & FLAG_FRAMING)
                        ? FRAMED_SIZE (dev->net.mtu)
                        : (sizeof (struct ethhdr) + dev->net.mtu);
+
+#ifdef CONFIG_USB_GENELINK
+       if (dev->driver_info->flags & FLAG_GENELINK)
+               size = GL_RCV_BUF_SIZE;
+#endif
+
        if ((skb = alloc_skb (size, flags)) == 0) {
                dbg ("no rx skb");
                tasklet_schedule (&dev->bh);
@@ -894,9 +1109,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;
@@ -1049,6 +1369,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;
 }
@@ -1076,6 +1399,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);
@@ -1180,6 +1511,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;
@@ -1204,6 +1573,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;
@@ -1222,7 +1598,29 @@
                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) {
                        if (skb_shared (skb)) {
                                struct sk_buff *skb2;
                                skb2 = skb_unshare (skb, flags);
@@ -1408,10 +1806,18 @@
                return 0;
        }
 
-       if (usb_set_interface (udev, ifnum, altnum) < 0) {
-               err ("set_interface failed");
-               return 0;
+#ifdef CONFIG_USB_GENELINK
+       // genelink device didn't support set interface command
+       // it need to issue set interface command for genelink device
+       if (!(info->flags & FLAG_GENELINK)) {
+#endif
+               if (usb_set_interface (udev, ifnum, altnum) < 0) {
+                       err ("set_interface failed");
+                       return 0;
+               }
+#ifdef CONFIG_USB_GENELINK
        }
+#endif
 
        // set up our own records
        if (!(dev = kmalloc (sizeof *dev, GFP_KERNEL))) {
@@ -1484,11 +1890,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.
@@ -1528,6 +1929,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);
@@ -1564,5 +1972,5 @@
 module_exit (usbnet_exit);
 
 MODULE_AUTHOR ("David Brownell <[EMAIL PROTECTED]>");
-MODULE_DESCRIPTION ("USB Host-to-Host Link Drivers (Belkin, Linux, NetChip, Prolific, 
...)");
+MODULE_DESCRIPTION ("USB Host-to-Host Link Drivers (Belkin, Linux, NetChip, Prolific, 
+Genesys Logic, ...)");
 MODULE_LICENSE("GPL");
--- linux/Documentation/Configure.help.orig     Tue Sep 25 00:08:44 2001
+++ linux/Documentation/Configure.help  Tue Sep 25 00:14:01 2001
@@ -11738,9 +11738,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 NetChip, Prolific
+  and GeneSys (GeneLink). 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


-- 
Stanislav Brabec

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

Reply via email to