⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 net-fd.c

📁 Linux2.4.20针对三星公司的s3c2440内核基础上的一些设备驱动代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	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 + -