📄 net-fd.c
字号:
if (!(function = device->function_instance_array + port)) { return; } dbg_init (1, "destroying"); if (!(net_private = function->privdata)) { dbg_init (1, "%s net_private null", device->name); return; } if (net_private->flags & NET_ATTACHED) { if (netproto_destroy (net_private->interface)) { dbg_init (1, "error destroying %d", net_private->index); } } { // get module lock and delete from device array unsigned int flags; write_lock_irqsave (&net_rwlock, flags); net_private->device = NULL; net_private->flags = 0; function->privdata = NULL; write_unlock_irqrestore (&net_rwlock, flags); } netproto_off (net_private->interface); MOD_DEC_USE_COUNT; return;}/* Called when a USB Device is created or destroyed ***************************************** */// XXX this should get passed a device structure, not busstatic void net_function_init (struct usb_bus_instance *bus, struct usb_device_instance *device, struct usb_function_driver *function_driver){#if defined(CONFIG_USBD_NET_MDLM) || defined(CONFIG_USBD_NET_CDC) int i;#endif struct usb_function_instance *function; __u32 serial; // trim for use in MAC addr int port = 0; // XXX compound device //dbg_init(1, "-------------------------------------------------------------------------------"); if (!(function = device->function_instance_array + port)) { return; } serial = bus->serial_number & 0x00ffffff;#if defined(CONFIG_USBD_NET_CDC) || defined(CONFIG_USBD_NET_MDLM) if (remote_mac_address && (strlen (remote_mac_address) == 12)) { memcpy (remote_mac_address_buffer, remote_mac_address, 12); } else if (serial) { sprintf (remote_mac_address_buffer, "%06X%06X", CONFIG_USBD_NET_REMOTE_OUI, serial); } else { if (strlen (CONFIG_USBD_NET_REMOTE_MACADDR)) { memcpy (remote_mac_address_buffer, CONFIG_USBD_NET_REMOTE_MACADDR, 12); } else { memcpy (remote_mac_address_buffer, "400002000001", 12); } } remote_mac_address_buffer[12] = '\0'; // sanity check if (strlen (remote_mac_address_buffer) != 12) { dbg_init (0, "mac_address has wrong length: %s %d", remote_mac_address_buffer, strlen (remote_mac_address_buffer)); //return -EINVAL; return; } dbg_init (1, "remote mac_address: %s", remote_mac_address_buffer);#if defined(CONFIG_USBD_NET_CDC) // set the mac address in the descriptor for (i = 0; i < sizeof (cdc_comm_class_descriptions) / sizeof (struct usb_class_description); i++) { struct usb_class_description *class_description = cdc_comm_class_descriptions + i; if (class_description->bDescriptorSubtype == USB_ST_ENF) { class_description->description.ethernet_networking.iMACAddress = remote_mac_address_buffer; break; } }#endif#if defined(CONFIG_USBD_NET_MDLM) // set the mac address in the descriptor for (i = 0; i < sizeof (mdlm_comm_class_descriptions) / sizeof (struct usb_class_description); i++) { struct usb_class_description *class_description = mdlm_comm_class_descriptions + i; if (class_description->bDescriptorSubtype == USB_ST_ENF) { class_description->description.ethernet_networking.iMACAddress = remote_mac_address_buffer; break; } }#endif#endif /* defined(CONFIG_USBD_NET_CDC) || defined(CONFIG_USBD_NET_MDLM) */#if defined(CONFIG_USBD_MAC_AS_SERIAL_NUMBER) if (bus->serial_number_str) { kfree (bus->serial_number_str); bus->serial_number_str = NULL; } bus->serial_number_str = strdup (remote_mac_address_buffer); //net_device_description.iSerialNumber = remote_mac_address_buffer; dbg_init (1, "setting iSerialNumber to remote mac_address: %s", remote_mac_address_buffer);#endif default_dev_addr[ETH_ALEN - 1] = 1;}static void net_function_exit (struct usb_device_instance *device){ dbg_init (1, "CLOSING **************************"); net_destroy (device);}/* Called to handle USB Events ************************************************************** *//** * net_event - process a device event * @device: usb device * @event: the event that happened * * Called by the usb device core layer to respond to various USB events. * * This routine IS called at interrupt time. Please use the usual precautions. * */void net_event (struct usb_device_instance *device, usb_device_event_t event, int data){ int port = 0; struct usb_function_instance *function; struct usb_net_private *net_private; if (!(function = device->function_instance_array + port)) { dbg_usbe (1, "function NULL"); return; } dbg_usbe (1,"%s data: %d privdata: %p", USBD_DEVICE_EVENTS(event), data, function->privdata); dbg_usbe (7, "%p %s %d previous_state: %d device_state: %d", device, device->name, event, device->device_previous_state, device->device_state); switch (event) { case DEVICE_CREATE: // a bus interface driver has created a usb device if (alwaysup) { net_create (device, function); } break; case DEVICE_RESET: net_device_check_condition(DEVICE_RESET); if (!alwaysup) { net_destroy (device); } break; case DEVICE_CONFIGURED: // the host has found a driver that matches net_device_check_condition(DEVICE_CONFIGURED);#if defined(CONFIG_USBD_NET_CDC) break;#else device->interface = 0; device->alternate = 0;#endif case DEVICE_SET_INTERFACE: // the host driver has selected an interface if (!alwaysup) { net_create (device, function); } break; case DEVICE_BUS_INACTIVE: // suspend net_device_check_condition(DEVICE_BUS_INACTIVE); // XXX if ((net_private = function->privdata)) { //netproto_off (net_private->interface); } break; case DEVICE_BUS_ACTIVITY: // resume net_device_check_condition(DEVICE_BUS_ACTIVITY); // XXX if ((net_private = function->privdata)) { //netproto_on (net_private->interface); } break; case DEVICE_DESTROY: // the bus interface driver is unloading net_destroy (device); break; case DEVICE_FUNCTION_PRIVATE: switch (data) { case NET_SET_CRC: break; } break; default: break; }}/** * net_recv_setup - called with a control URB * @urb - pointer to struct urb * * Check if this is a setup packet, process the device request, put results * back into the urb and return zero or non-zero to indicate success (DATA) * or failure (STALL). * * This routine IS called at interrupt time. Please use the usual precautions. * */int net_recv_setup (struct urb *urb){ struct usb_device_request *request; struct usb_device_instance *device = urb->device; int port = 0; struct usb_net_private *net_private = (device->function_instance_array + port)->privdata; request = &urb->device_request; // handle USB Standard Request (c.f. USB Spec table 9-2) if ((request->bmRequestType & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_VENDOR) { dbg_ep0 (1, "not vendor request: %x %x", request->bmRequestType, request->bmRequestType & USB_REQ_TYPE_MASK); return 0; // XXX } // handle all requests that return data (direction bit set on bm RequestType) if ((request->bmRequestType & USB_REQ_DIRECTION_MASK)) { dbg_ep0 (1, "Device-to-Host"); } else { dbg_ep0 (1, "Host-to-Device"); switch (request->bRequest) { case MCCI_ENABLE_CRC: dbg_ep0 (1, "Enabling CRC"); net_private->crc = 1; usbd_device_event_irq (device, DEVICE_FUNCTION_PRIVATE, NET_SET_CRC); break; } } return 0;}/** * net_recv_urb - called with a received URB * @urb - pointer to struct urb * * Return non-zero if we failed and urb is still valid (not disposed) * * This routine IS called at interrupt time. Please use the usual precautions. * */int net_recv_urb (struct urb *urb){ int port = 0; // XXX compound device struct usb_device_instance *device; struct usb_function_instance *function; struct usb_net_private *net_private; unsigned int length; struct sk_buff *skb = NULL; int mtu; if (!urb || !(device = urb->device) || !(function = device->function_instance_array + port) || !(net_private = function->privdata)) { return -EINVAL; } if (!(net_private->flags & NET_INUSE)) { netproto_rx_missed_error (net_private->interface); return -EINVAL; } dbg_rx (5, "urb: %p len: %d maxtransfer: %d\n", urb, urb->actual_length, net_private->maxtransfer); if (urb->status != RECV_OK) { dbg_rx (0, "!RECV_OK urb->actual_length: %d maxtransfer: %d", urb->actual_length, net_private->maxtransfer); netproto_rx_fifo_error (net_private->interface); return -EINVAL; } length = urb->actual_length; if (length > net_private->maxtransfer) { dbg_rx (0, "TOO LARGE urb->actual_length: %d maxtransfer: %d", urb->actual_length, net_private->maxtransfer); netproto_rx_over_error (net_private->interface); return -EINVAL; } if (!(skb = net_dev_alloc_skb (length))) { dbg_rx (0, "cannot malloc skb"); netproto_rx_missed_error (net_private->interface); return -EINVAL; } dbgPRINTmem (dbgflg_usbdfd_rx, 4, urb->buffer, length); if (net_private->crc) { __u32 fcs; // do we need to check for extra null byte if ((length % out_pkt_sz) == 1) { // fcs and copy length minus one byte first, if CRC32 is ok, then assume that we have an extra byte if (((fcs = fcs_memcpy32 (skb_put (skb, length - 1), urb->buffer, length - 1, CRC32_INITFCS)) != CRC32_GOODFCS)) { // CRC32 check failed, fcs and copy last byte, if ok then continue otherwise fail if ((fcs_memcpy32 (skb_put (skb, 1), urb->buffer + length - 1, 1, fcs) != CRC32_GOODFCS)) { dbg_rx (1, "CRC32 failed on extra byte len: %d fcs: %08x", length, fcs); dbgPRINTmem (dbgflg_usbdfd_rx, 1, urb->buffer, length); dev_kfree_skb_any (skb); netproto_rx_crc_error (net_private->interface); return -EINVAL; } } } else { if (((fcs = fcs_memcpy32 (skb_put (skb, length), urb->buffer, length, CRC32_INITFCS)) != CRC32_GOODFCS)) { dbg_rx (1, "CRC32 failed len: %d fcs: %08x", length, fcs); dbgPRINTmem (dbgflg_usbdfd_rx, 4, urb->buffer, length); dev_kfree_skb_any (skb); netproto_rx_crc_error (net_private->interface); return -EINVAL; } } skb_trim (skb, skb->len - 4); } else { memcpy (skb_put (skb, length), urb->buffer, length); } if ((skb->len > net_private->maxtransfer) || (skb->tail > skb->end)) { dbg_rx (0, "ERROR skb: %p head: %p data: %p tail: %p end: %p len: %d", skb, skb->head, skb->data, skb->tail, skb->end, skb->len); dev_kfree_skb_any (skb); netproto_rx_length_error (net_private->interface); return -EINVAL; } // XXX should not be needed mtu = netproto_mtu (net_private->interface); if (skb->len > (mtu + 14)) { skb_trim (skb, (netproto_mtu (net_private->interface) + 14)); } usbd_recycle_urb (urb);#ifdef RXECHO dbg_rx (3, "skb: %p head: %p data: %p tail: %p end: %p len: %d", skb, skb->head, skb->data, skb->tail, skb->end, skb->len); dbgPRINTmem (dbgflg_usbdfd_rx, 3, skb->data, skb->len);#endif // pass it up, free skb if non zero if (netproto_recv (net_private->interface, skb)) { dev_kfree_skb_any (skb); //netproto_rx_dropped(net_private->interface); } return 0;}/** * net_urb_sent - called to indicate URB transmit finished * @urb: pointer to struct urb * @rc: result * * The usb device core layer will use this to let us know when an URB has * been finished with. * * This routine IS called at interrupt time. Please use the usual precautions. * */int net_urb_sent (struct urb *urb, int rc){ int port = 0; // XXX compound device struct usb_device_instance *device; struct usb_function_instance *function; struct usb_net_private *net_private; int interface; struct sk_buff *skb; if (!urb || !(device = urb->device) || !(function = device->function_instance_array + port) || !(net_private = function->privdata)) { return -EINVAL; } if (!(net_private->flags & NET_INUSE)) { // The interface is being/has been shutdown. // XXX Check this logic for mem leaks, but the // shutdown should have taken care of it, so // a leak is not likely. return 0; } interface = net_private->interface; // retrieve skb pointer and unlink from urb pointers skb = (struct sk_buff *) urb->privdata; // if no CRC then we are pointing at skb->buffer, so don't attempt to free urb->buffer if (!net_private->crc) { urb->buffer = NULL; urb->actual_length = 0; } urb->privdata = NULL; usbd_dealloc_urb (urb); // tell netproto we are done with the skb, it will test for NULL netproto_done (interface, skb, rc != SEND_FINISHED_OK); return 0;}/* * * net_xmit_skb - called to transmit an skb * @interface: which interface * @skb: skb to send * */static int net_xmit_skb (int interface, struct sk_buff *skb){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -