📄 net-fd.c
字号:
int port = 0; // XXX compound device struct usb_net_private *net_private; struct urb *urb; //dbg_tx(5,"skb: %p", skb); // XXX XXX // return -EINVAL; net_private = &net_private_array[interface]; if (!net_private->device) { dbg_tx (0, "net_private NULL"); return -EUNATCH; }#if 0#ifdef CONFIG_ARCH_SA1100 // compensate for SA-1110 DMA setup problems by sending three dummy urbs before // any real traffic, these will be dropped at the far end if (net_private->first) { int i; dbg_tx (1, "sending three init URBS"); for (i = 0; i < 3; i++) { if ((urb = usbd_alloc_urb (net_private->device, (net_private->device->function_instance_array + port), CONFIG_USBD_NET_IN_ENDPOINT | IN, 200))) { memset (urb->buffer, i, 200); urb->actual_length = 100; usbd_send_urb (urb); } } net_private->first = 0; }#endif#endif if (! (urb = usbd_alloc_urb (net_private->device, (net_private->device->function_instance_array + port), CONFIG_USBD_NET_IN_ENDPOINT | IN, skb->len + 5 + in_pkt_sz))) { dbg_tx (0, "urb alloc failed len: %d", skb->len); return -ENOMEM; } if (net_private->crc) { u32 send_fcs; send_fcs = fcs_memcpy32 (urb->buffer, skb->data, skb->len, CRC32_INITFCS); urb->actual_length = skb->len; // check if we need to pre-pend a NULL byte before CRC if ((urb->actual_length % in_pkt_sz) == (in_pkt_sz - 4)) { send_fcs = fcs_pad32 (urb->buffer + urb->actual_length, 1, send_fcs); urb->actual_length++; dbg_tx (2, "do_fcs32: adding NULL byte before CRC"); } // if transfer is less than packetsize guarantee that is at lest two packets else if (skb->len < (in_pkt_sz - 3)) { dbg_tx (2, "do_fcs32: len: %d padding; %d", skb->len, (in_pkt_sz - skb->len - 3)); send_fcs = fcs_pad32 (urb->buffer + urb->actual_length, (in_pkt_sz - skb->len - 3), send_fcs); urb->actual_length = in_pkt_sz - 3; }#if defined(CONFIG_USBD_NET_PADDED)//#warning LINKUP Padding defined // Linkup - minimum size of last packet dbg_tx (2, "do_fcs32: checking actual: %d pktsize: %d remainder: %d", urb->actual_length, in_pkt_sz, (urb->actual_length + 4) % in_pkt_sz); while (((urb->actual_length + 4) % in_pkt_sz) <= (in_pkt_sz - 2)) { send_fcs = fcs_pad32 (urb->buffer + urb->actual_length, 1, send_fcs); urb->actual_length++; //dbg_tx(3, "do_fcs32: adding NULL byte(s) before CRC"); }#endif send_fcs = ~send_fcs; urb->buffer[urb->actual_length++] = send_fcs & 0xff; urb->buffer[urb->actual_length++] = (send_fcs >> 8) & 0xff; urb->buffer[urb->actual_length++] = (send_fcs >> 16) & 0xff; urb->buffer[urb->actual_length++] = (send_fcs >> 24) & 0xff; } else { urb->buffer = skb->data; urb->actual_length = skb->len; }#ifdef CONFIG_USBD_NO_ZLP_SUPPORT//#warning -//#warning NO ZLP SUPPORT DEFINED // check if we need to append a NULL byte if (!(urb->actual_length % in_pkt_sz)) { dbg_tx (3, "adding NULL byte after CRC"); urb->buffer[urb->actual_length++] = 0; }#endif // save skb for netproto_done urb->privdata = (void *) skb; dbg_tx (4, "skb: %p head: %p data: %p tail: %p len: %d endpoint: %x", skb, skb->head, skb->data, skb->tail, skb->len, CONFIG_USBD_NET_IN_ENDPOINT); dbg_tx (4, "urb: %p buffer: %p acutal_length: %d", urb, urb->buffer, urb->actual_length); dbgPRINTmem (dbgflg_usbdfd_tx, 4, urb->buffer, urb->actual_length); if (usbd_send_urb (urb)) { dbg_tx (1, "usbd_send_urb failed"); urb->privdata = NULL; usbd_dealloc_urb (urb); return -ECOMM; } return 0;}static int net_set_addr (int dev, void *addr, int len){ return 0;}/** * net_tx_timeout - called by netproto if transmit times out * @dev: which device * * Called to cancel an in progress transmit. Note that this routine is advisory, * it just sends a message to the lower layer which may or may not actually do * anything about it. */static int net_tx_timeout (int interface){ struct usb_net_private *net_private; dbg_tx (1, "if=%d", interface); net_private = &net_private_array[interface]; if (!net_private->device) { return -EINVAL; } return usbd_cancel_urb (net_private->device, NULL);}struct usb_function_operations function_ops = { event:net_event, recv_urb:net_recv_urb, recv_setup:net_recv_setup, urb_sent:net_urb_sent,#if 0 alloc_urb_data:net_alloc_urb_data, dealloc_urb_data:net_dealloc_urb_data#endif function_init:net_function_init, function_exit:net_function_exit,};struct usb_function_driver function_driver = { name:"Generic Network", ops:&function_ops, device_description:&net_device_description, configurations:sizeof (net_description) / sizeof (struct usb_configuration_description), configuration_description:net_description, this_module:THIS_MODULE,};/* proc file system ********************************************************************** */int net_device_condition = NET_DEVICE_CONDITION_UNKNOWN;static int net_device_received_command = 0;static int net_device_bus_active = 0;static struct timer_list net_device_fail_check_timer;static void net_device_fail_check(unsigned long data){ if (net_device_condition == NET_DEVICE_CONDITION_RESET) { net_device_condition = NET_DEVICE_CONDITION_FAIL; }}static void net_device_check_condition(usb_device_event_t event){ switch (event) { case DEVICE_RESET: del_timer(&net_device_fail_check_timer); net_device_condition = NET_DEVICE_CONDITION_RESET; net_device_received_command = 0; net_device_bus_active = 1; net_device_fail_check_timer.function = net_device_fail_check; net_device_fail_check_timer.expires = jiffies + 30 * 100; add_timer(&net_device_fail_check_timer); break; case DEVICE_CONFIGURED: net_device_received_command = 1; break; case DEVICE_BUS_INACTIVE: net_device_bus_active = 0; break; case DEVICE_BUS_ACTIVITY: net_device_bus_active = 1; break; default: break; }}/* * * net_device_proc_read - implement proc file system read. * @file: xx * @buf: xx * @count: xx * @pos: xx * * Standard proc file system read function. * * We let upper layers iterate for us, *pos will indicate which device to return * statistics for. */static ssize_tnet_device_proc_read_condition(struct file *file, char *buf, size_t count, loff_t * pos){ int len = 0; char *p; if (*pos > 0) return 0; switch (net_device_condition) { case NET_DEVICE_CONDITION_UNKNOWN: default: p = "Unknown\n"; break; case NET_DEVICE_CONDITION_RESET: p = "Enumeration Start\n"; break; case NET_DEVICE_CONDITION_OK: if ( !net_device_bus_active ) { p = "Unknown -- bus inactive\n"; } else { p = "Enumeration OK\n"; } break; case NET_DEVICE_CONDITION_FAIL: if ( !net_device_bus_active ) { p = "Unknown -- bus inactive\n"; } else if ( !net_device_received_command ) { p = "Unknown -- command wasn't received from host\n"; // USB cable not connected } else { p = "Enumeration Fail\n"; } break; } len = strlen(p); *pos += len; if (len > count) { len = -EINVAL; } else if (len > 0 && copy_to_user(buf, p, len)) { len = -EFAULT; } return len;}/* * * usbd_monitor_proc_write - implement proc file system write. * @file * @buf * @count * @pos * * Proc file system write function, used to signal monitor actions complete. * (Hotplug script (or whatever) writes to the file to signal the completion * of the script.) An ugly hack. */static ssize_tnet_device_proc_write_condition(struct file *file, const char *buf, size_t count, loff_t * pos){ if (net_device_condition != NET_DEVICE_CONDITION_RESET) net_device_condition = NET_DEVICE_CONDITION_UNKNOWN; return count;}static struct file_operations net_device_proc_operations_condition = { read: net_device_proc_read_condition, write:net_device_proc_write_condition,};/* Module init and exit ********************************************************************** */unsigned char hexdigit (char c){ return isxdigit (c) ? (isdigit (c) ? (c - '0') : (c - 'A' + 10)) : 0;}/* * net_modinit - module init * */static int __init net_modinit (void){ char local_mac_address_buffer[13]; int i; debug_option *op = find_debug_option (dbg_table, "net"); printk (KERN_INFO "%s (dbg=\"%s\",alwaysup=%d,OUT=%d,IN=%d)\n", __usbd_module_info, dbg ? dbg : "", alwaysup, out_pkt_sz, in_pkt_sz); printk (KERN_INFO "vendorID: %x productID: %x\n", CONFIG_USBD_VENDORID, CONFIG_USBD_PRODUCTID); if (NULL != op) { op->sub_table = netproto_get_dbg_table (); } if (0 != scan_debug_options ("net_fd", dbg_table, dbg)) { return (-EINVAL); } memset (net_private_array, 0, sizeof (net_private_array)); // verify pkt sizes not too small if (out_pkt_sz < 3 || in_pkt_sz < 3) { dbg_init (0, "Rx pkt size %d or Tx pkt size %d too small", out_pkt_sz, in_pkt_sz); return (-EINVAL); } // Check for non-default packet sizes if (out_pkt_sz != CONFIG_USBD_NET_OUT_PKTSIZE) {#ifdef CONFIG_USBD_NET_SAFE net_default[0].wMaxPacketSize = out_pkt_sz;#endif /* CONFIG_USBD_NET_SAFE */#ifdef CONFIG_USBD_NET_CDC net_alt_1_endpoints[0].wMaxPacketSize = out_pkt_sz;#endif } if (in_pkt_sz != CONFIG_USBD_NET_IN_PKTSIZE) {#ifdef CONFIG_USBD_NET_SAFE net_default[1].wMaxPacketSize = in_pkt_sz;#endif /* CONFIG_USBD_NET_SAFE */#ifdef CONFIG_USBD_NET_CDC net_alt_1_endpoints[1].wMaxPacketSize = in_pkt_sz;#endif } dbg_init (1, "Rx pkt size %d, Tx pkt size %d", out_pkt_sz, in_pkt_sz); if (vendor_id) { net_device_description.idVendor = vendor_id; } if (product_id) { net_device_description.idProduct = product_id; } // initialize the netproto library if (netproto_modinit (if_name, MAX_INTERFACES)) { dbg_init (0, "netproto_modinit failed"); return -EINVAL; } if (local_mac_address && (strlen (local_mac_address) == 12)) { dbg_init (1, "using local_mac_address: %s", local_mac_address); memcpy (local_mac_address_buffer, local_mac_address, 12); } else { dbg_init (1, "using LOCAL_MACADDR: %s", CONFIG_USBD_NET_LOCAL_MACADDR); memcpy (local_mac_address_buffer, CONFIG_USBD_NET_LOCAL_MACADDR, 12); } local_mac_address_buffer[12] = '\0'; dbg_init (1, "local_mac_address_buffer: %s", local_mac_address_buffer); dbg_init (1, "LOCAL_MACADDR: %s", CONFIG_USBD_NET_LOCAL_MACADDR); if (local_mac_address) { dbg_init (1, "localmac_address: %s len: %d", local_mac_address, strlen (local_mac_address)); } // save the mac address for the network device for (i = 0; i < ETH_ALEN; i++) { default_dev_addr[i] = hexdigit (local_mac_address_buffer[i * 2]) << 4 | hexdigit (local_mac_address_buffer[i * 2 + 1]); //dbg_init(0, "local_mac_address[%d]: %02x %02x %d %d %02x", i, // local_mac_address_buffer[i*2], local_mac_address_buffer[i*2+1], // hexdigit(local_mac_address_buffer[i*2]), hexdigit(local_mac_address_buffer[i*2+1]), // default_dev_addr[i]); } // create network interface //net_create(0); // register us with the usb device support layer if (usbd_register_function (&function_driver)) { dbg_init (0, "usbd_register_function failed"); netproto_modexit (); return -EINVAL; } { struct proc_dir_entry *p; if ((p = create_proc_entry("usb-condition", 0, 0)) == NULL) { netproto_modexit(); return -ENOMEM; } p->proc_fops = &net_device_proc_operations_condition; init_timer(&net_device_fail_check_timer); } return 0;}/* * function_exit - module cleanup * */static void __exit net_modexit (void){ dbg_init (1, "exiting"); // de-register us with the usb device support layer usbd_deregister_function (&function_driver); // destroy network interface //net_destroy(0); // tell the netproto library to exit netproto_modexit (); remove_proc_entry("usb-condition", NULL); del_timer(&net_device_fail_check_timer);}module_init (net_modinit);module_exit (net_modexit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -