📄 usbnet.c
字号:
{ int status = urb->status; switch (status) { case 0: /* success */ break; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ dbg("%s - urb shutting down with status: %d", __FUNCTION__, status); return; default: dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); } // NOTE: 2.4 still has automagic resubmit, so this would be // wrong ... but this code has never worked, is always disabled. status = usb_submit_urb (urb, GFP_ATOMIC); if (status) err ("%s - usb_submit_urb failed with result %d", __FUNCTION__, status);}static 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 = SUBMIT_URB (priv->irq_urb, GFP_KERNEL)) != 0) dbg ("gl_interrupt_read: submit fail - %X...", retval); else dbg ("gl_interrupt_read: submit success..."); } return 0;}// check whether another side is connectedstatic int genelink_check_connect (struct usbnet *dev){ int retval; dbg ("genelink_check_connect..."); // detect whether another side is connected if ((retval = gl_control_write (dev, GENELINK_CONNECT_WRITE, 0)) != 0) { dbg ("%s: genelink_check_connect write fail - %X", dev->net.name, retval); return retval; } // usb interrupt read to ack another side if ((retval = gl_interrupt_read (dev)) != 0) { dbg ("%s: genelink_check_connect read fail - %X", dev->net.name, retval); return retval; } dbg ("%s: genelink_check_connect read success", dev->net.name); return 0;}// allocate and initialize the private data for genelinkstatic int genelink_init (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 = ALLOC_URB (0, GFP_KERNEL)) == 0) { dbg ("%s: cannot allocate private irq urb per device", dev->net.name); kfree (priv); return -ENOMEM; } // fill irq urb usb_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 datastatic int genelink_free (struct usbnet *dev){ struct gl_priv *priv = dev->priv_data; if (!priv) return 0;// FIXME: can't cancel here; it's synchronous, and// should have happened earlier in any case (interrupt// handling needs to be generic) // 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;}#endifstatic int genelink_rx_fixup (struct usbnet *dev, struct sk_buff *skb){ struct gl_header *header; struct gl_packet *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); if ((header->packet_count > GL_MAX_TRANSMIT_PACKETS) || (header->packet_count < 0)) { dbg ("genelink: illegal received packet count %d", header->packet_count); return 0; } // set the current packet pointer to the first packet 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 = packet->packet_length; // this may be a broken packet if (size > GL_MAX_PACKET_LEN) { dbg ("genelink: illegal rx length %d", size); return 0; } // allocate the skb for the individual packet gl_skb = alloc_skb (size, GFP_ATOMIC); if (gl_skb) { // copy the packet data to the new skb memcpy (gl_skb->data, packet->packet_data, size); // set skb data size gl_skb->len = size; 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); } // advance to the next packet packet = (struct gl_packet *) &packet->packet_data [size]; header->packet_count--; // shift the data pointer to the next gl_packet skb_pull (skb, size + 4); } // skip the packet length field 4 bytes skb_pull (skb, 4); if (skb->len > GL_MAX_PACKET_LEN) { dbg ("genelink: illegal rx length %d", skb->len); return 0; } return 1;}static struct sk_buff *genelink_tx_fixup (struct usbnet *dev, struct sk_buff *skb, int flags){ int padlen; int length = skb->len; int headroom = skb_headroom (skb); int tailroom = skb_tailroom (skb); u32 *packet_count; u32 *packet_len; // FIXME: magic numbers, bleech 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; } } else { struct sk_buff *skb2; skb2 = skb_copy_expand (skb, (4 + 4*1) , padlen, flags); dev_kfree_skb_any (skb); skb = skb2; } // attach the packet count to the header packet_count = (u32 *) skb_push (skb, (4 + 4*1)); packet_len = packet_count + 1; // FIXME little endian? *packet_count = 1; *packet_len = length; // add padding byte if ((skb->len % EP_SIZE (dev)) == 0) skb_put (skb, 1); return skb;}static const struct driver_info genelink_info = { .description = "Genesys GeneLink", .flags = FLAG_FRAMING_GL | FLAG_NO_SETINT, .rx_fixup = genelink_rx_fixup, .tx_fixup = genelink_tx_fixup, .in = 1, .out = 2, .epsize =64,#ifdef GENELINK_ACK .check_connect =genelink_check_connect,#endif};#endif /* CONFIG_USB_GENESYS */#ifdef CONFIG_USB_NET1080/*------------------------------------------------------------------------- * * Netchip 1080 driver ... http://www.netchip.com * Used in LapLink cables * *-------------------------------------------------------------------------*//* * NetChip framing of ethernet packets, supporting additional error * checks for links that may drop bulk packets from inside messages. * Odd USB length == always short read for last usb packet. * - nc_header * - Ethernet header (14 bytes) * - payload * - (optional padding byte, if needed so length becomes odd) * - nc_trailer * * This framing is to be avoided for non-NetChip devices. */struct nc_header { // packed: u16 hdr_len; // sizeof nc_header (LE, all) u16 packet_len; // payload size (including ethhdr) u16 packet_id; // detects dropped packets#define MIN_HEADER 6 // all else is optional, and must start with: // u16 vendorId; // from usb-if // u16 productId;} __attribute__((__packed__));#define PAD_BYTE ((unsigned char)0xAC)struct nc_trailer { u16 packet_id;} __attribute__((__packed__));// packets may use FLAG_FRAMING_NC and optional pad#define FRAMED_SIZE(mtu) (sizeof (struct nc_header) \ + sizeof (struct ethhdr) \ + (mtu) \ + 1 \ + sizeof (struct nc_trailer))#define MIN_FRAMED FRAMED_SIZE(0)/* * Zero means no timeout; else, how long a 64 byte bulk packet may be queued * before the hardware drops it. If that's done, the driver will need to * frame network packets to guard against the dropped USB packets. The win32 * driver sets this for both sides of the link. */#define NC_READ_TTL_MS ((u8)255) // ms/* * We ignore most registers and EEPROM contents. */#define REG_USBCTL ((u8)0x04)#define REG_TTL ((u8)0x10)#define REG_STATUS ((u8)0x11)/* * Vendor specific requests to read/write data */#define REQUEST_REGISTER ((u8)0x10)#define REQUEST_EEPROM ((u8)0x11)static intnc_vendor_read (struct usbnet *dev, u8 req, u8 regnum, u16 *retval_ptr){ int status = usb_control_msg (dev->udev, usb_rcvctrlpipe (dev->udev, 0), req, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, regnum, retval_ptr, sizeof *retval_ptr, CONTROL_TIMEOUT_JIFFIES); if (status > 0) status = 0; if (!status) le16_to_cpus (retval_ptr); return status;}static inline intnc_register_read (struct usbnet *dev, u8 regnum, u16 *retval_ptr){ return nc_vendor_read (dev, REQUEST_REGISTER, regnum, retval_ptr);}// no retval ... can become async, usable in_interrupt()static voidnc_vendor_write (struct usbnet *dev, u8 req, u8 regnum, u16 value){ usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0), req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, regnum, 0, 0, // data is in setup packet CONTROL_TIMEOUT_JIFFIES);}static inline voidnc_register_write (struct usbnet *dev, u8 regnum, u16 value){ nc_vendor_write (dev, REQUEST_REGISTER, regnum, value);}#if 0static void nc_dump_registers (struct usbnet *dev){ u8 reg; u16 *vp = kmalloc (sizeof (u16)); if (!vp) { dbg ("no memory?"); return; } dbg ("%s registers:", dev->net.name); for (reg = 0; reg < 0x20; reg++) { int retval; // reading some registers is trouble if (reg >= 0x08 && reg <= 0xf) continue; if (reg >= 0x12 && reg <= 0x1e) continue; retval = nc_register_read (dev, reg, vp); if (retval < 0) dbg ("%s reg [0x%x] ==> error %d", dev->net.name, reg, retval); else dbg ("%s reg [0x%x] = 0x%x", dev->net.name, reg, *vp); } kfree (vp);}#endif/*-------------------------------------------------------------------------*//* * Control register */#define USBCTL_WRITABLE_MASK 0x1f0f// bits 15-13 reserved, r/o#define USBCTL_ENABLE_LANG (1 << 12)#define USBCTL_ENABLE_MFGR (1 << 11)#define USBCTL_ENABLE_PROD (1 << 10)#define USBCTL_ENABLE_SERIAL (1 << 9)#define USBCTL_ENABLE_DEFAULTS (1 << 8)// bits 7-4 reserved, r/o#define USBCTL_FLUSH_OTHER (1 << 3)#define USBCTL_FLUSH_THIS (1 << 2)#define USBCTL_DISCONN_OTHER (1 << 1)#define USBCTL_DISCONN_THIS (1 << 0)static inline void nc_dump_usbctl (struct usbnet *dev, u16 usbctl){#ifdef DEBUG devdbg (dev, "net1080 %s-%s usbctl 0x%x:%s%s%s%s%s;" " this%s%s;" " other%s%s; r/o 0x%x", dev->udev->bus->bus_name, dev->udev->devpath, usbctl, (usbctl & USBCTL_ENABLE_LANG) ? " lang" : "", (usbctl & USBCTL_ENABLE_MFGR) ? " mfgr" : "", (usbctl & USBCTL_ENABLE_PROD) ? " prod" : "", (usbctl & USBCTL_ENABLE_SERIAL) ? " serial" : "", (usbctl & USBCTL_ENABLE_DEFAULTS) ? " defaults" : "", (usbctl & USBCTL_FLUSH_OTHER) ? " FLUSH" : "", (usbctl & USBCTL_DISCONN_OTHER) ? " DIS" : "", (usbctl & USBCTL_FLUSH_THIS) ? " FLUSH" : "", (usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "", usbctl & ~USBCTL_WRITABLE_MASK );#endif}/*-------------------------------------------------------------------------*//* * Status register */#define STATUS_PORT_A (1 << 15)#define STATUS_CONN_OTHER (1 << 14)#define STATUS_SUSPEND_OTHER (1 << 13)#define STATUS_MAILBOX_OTHER (1 << 12)#define STATUS_PACKETS_OTHER(n) (((n) >> 8) && 0x03)#define STATUS_CONN_THIS (1 << 6)#define STATUS_SUSPEND_THIS (1 << 5)#define STATUS_MAILBOX_THIS (1 << 4)#define STATUS_PACKETS_THIS(n) (((n) >> 0) && 0x03)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -