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

📄 serial.c

📁 S3C2440ARM9开发板的USB驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Configuration description(s) */struct __devinitdata usb_configuration_description serial_description[] = {#ifdef CONFIG_USBD_SERIAL_CDC      {iConfiguration:"CDC 1.1 ACM Configuration",	      bmAttributes:BMATTRIBUTE,	      bMaxPower:BMAXPOWER,	      interfaces:sizeof (cdc_interfaces) /	 sizeof (struct usb_interface_description),      interface_list:cdc_interfaces,},#endif      {iConfiguration:"USB Simple Serial Configuration",	      bmAttributes:BMATTRIBUTE,	      bMaxPower:BMAXPOWER,	      interfaces:sizeof (serial_interfaces) /	 sizeof (struct usb_interface_description),      interface_list:serial_interfaces,},};/* Device Description */struct __devinitdata usb_device_description serial_device_description = {	bDeviceClass:COMMUNICATIONS_DEVICE_CLASS,	bDeviceSubClass:0,	// XXX	bDeviceProtocol:0,	// XXX	idVendor:CONFIG_USBD_VENDORID,	idProduct:CONFIG_USBD_PRODUCTID,	iManufacturer:CONFIG_USBD_MANUFACTURER,	iProduct:CONFIG_USBD_PRODUCT_NAME,	iSerialNumber:CONFIG_USBD_SERIAL_NUMBER_STR,};/* Transmit Function - called by serproto ****************************************************** */static int serial_xmit_data (int interface, unsigned char *data, int data_length){	int port = 0;		// XXX compound device	struct usb_serial_private *serial_private;	struct usb_device_instance *device;	struct urb *urb;	int packet_length = data_length;	dbg_tx (2, "data: %p data_length: %d", data, data_length);	if ((serial_private = get_serial_private (interface)) == NULL) {		dbg_tx (0, "cannot recover serial private");		return -EINVAL;	}	if ((device = serial_private->device) == NULL) {		dbg_tx (0, "cannot recover serial private device");		return -EINVAL;	}	// XXX Check if we are busy	if ((urb = usbd_alloc_urb (serial_private->device,				   (serial_private->device->function_instance_array + port),				   CONFIG_USBD_SERIAL_IN_ENDPOINT | IN, 0)) == NULL) {		dbg_tx (0, "failed to alloc urb");		return -EINVAL;	}#ifdef CONFIG_USBD_SERIAL_SAFE	if (safe) {		__u16 fcs;		dbg_tx (1, "safe mode: padded: %d data_length: %d packet_length: %d", padded,			data_length, packet_length);		// extend length to pad if required		if (padded) {			//packet_length = MAX(packet_length, CONFIG_USBD_SERIAL_IN_PKTSIZE - 2);			//packet_length = MIN(MAX(packet_length, packet_length), CONFIG_USBD_SERIAL_IN_PKTSIZE - 2);			packet_length = CONFIG_USBD_SERIAL_IN_PKTSIZE - 2;			//packet_length = 2;			//packet_length++;		}		// set length and a null byte 		data[packet_length] = data_length << 2;		data[packet_length + 1] = 0;		// compute CRC across data, padding, data_length and null byte		fcs = fcs_compute10 (data, packet_length + 2, CRC10_INITFCS);		// OR CRC into last two bytes		data[packet_length] |= fcs >> 8;		data[packet_length + 1] = fcs & 0xff;		packet_length += 2;		dbg_tx (1, "safe mode: data_length: %d packet_length: %d", data_length,			packet_length);	}#endif	urb->buffer = data;	urb->actual_length = packet_length;	//dbgPRINTmem(dbgflg_usbdfd_tx,3,urb->buffer,urb->actual_length);	dbgPRINTmem (dbgflg_usbdfd_tx, 3, urb->buffer, CONFIG_USBD_SERIAL_IN_PKTSIZE + 4);	// push it down into the usb-device layer	return usbd_send_urb (urb);}/* serial_urb_sent - called to indicate URB transmit finished * @urb: pointer to struct urb * @rc: result */int serial_urb_sent (struct urb *urb){	int port = 0;		// XXX compound device	struct usb_device_instance *device = urb->device;	struct usb_serial_private *serial_private =	    (device->function_instance_array + port)->privdata;	dbg_tx (2, "%s safe: %d length: %d", urb->device->name, safe, urb->actual_length);	serproto_done (serial_private->interface,		       urb->buffer,		       safe ? (urb->buffer[urb->actual_length - 2] >> 2) : urb->actual_length, 0);	usbd_dealloc_urb (urb);	return 0;}/* USB Device Functions ************************************************************************ *//* serial_event - process a device event * */void serial_event (struct usb_device_instance *device, usb_device_event_t event, int data){	int port = 0;		// XXX compound device	struct usb_function_instance *function;	unsigned int flags;	if ((function = device->function_instance_array + port) == NULL) {		dbg_usbe (1, "no function");		return;	}	dbg_usbe (3, "");        switch (event) {        case DEVICE_UNKNOWN:        case DEVICE_INIT:         case DEVICE_CREATE:             case DEVICE_HUB_CONFIGURED:        case DEVICE_RESET:        case DEVICE_ADDRESS_ASSIGNED:        case DEVICE_CONFIGURED:        case DEVICE_DE_CONFIGURED:        case DEVICE_SET_INTERFACE:        case DEVICE_SET_FEATURE:        case DEVICE_CLEAR_FEATURE:        case DEVICE_BUS_INACTIVE:        case DEVICE_BUS_ACTIVITY:        case DEVICE_POWER_INTERRUPTION:        case DEVICE_HUB_RESET:        case DEVICE_DESTROY:        case DEVICE_FUNCTION_PRIVATE:                dbg_usbe (1,"%s data: %d", usbd_device_events[event], data);                break;        default:                dbg_usbe (1,"%s", usbd_device_events[DEVICE_UNKNOWN]);                break;        }	switch (event) {	case DEVICE_UNKNOWN:	case DEVICE_INIT:		break;	case DEVICE_CREATE:		{			int i;			int interface;			struct usb_serial_private *serial_private;			// There is no way to indicate error, so make this unconditional			// and undo it in the DESTROY event unconditionally as well.			// It the responsibility of the USBD core and the bus interface			// to see that there is a matching DESTROY for every CREATE.			// XXX XXX MOD_INC_USE_COUNT;  // Before any sleepable fns such as kmalloc			// XXX XXX dbg_init(0,"CREATE sc=%d uc=%d",serial_created,GET_USE_COUNT(THIS_MODULE));			// sanity checks			if (serial_created >= MAX_INTERFACES) {				dbg_usbe (1,					  "---> CREATE %s serial_created >= MAX_INTERFACES %d %d",					  device->name, serial_created, MAX_INTERFACES);				dbg_init (0, "CREATE Z1 sc=%d uc=%d", serial_created,					  GET_USE_COUNT (THIS_MODULE));				return;			}			write_lock_irqsave (&serial_rwlock, flags);			for (i = 0; i < MAX_INTERFACES; i++) {				if (serial_private_array[i] == NULL) {					break;				}			}			if (i >= MAX_INTERFACES) {				write_unlock_irqrestore (&serial_rwlock, flags);				dbg_usbe (1, "---> CREATE %s no free interfaces %d %d",					  device->name, i, MAX_INTERFACES);				dbg_init (0, "CREATE Z2 sc=%d uc=%d", serial_created,					  GET_USE_COUNT (THIS_MODULE));				return;			}			serial_created++;			// allocate private data			if ((serial_private =			     kmalloc (sizeof (struct usb_serial_private), GFP_ATOMIC)) == NULL) {				serial_created--;				//MOD_DEC_USE_COUNT;				//dbg_init(0,"CREATE X1 sc=%d uc=%d",serial_created,GET_USE_COUNT(THIS_MODULE));				write_unlock_irqrestore (&serial_rwlock, flags);				dbg_usbe (1, "---> CREATE malloc failed %s", device->name);				return;			}			serial_private->rwlock = RW_LOCK_UNLOCKED;			serial_private_array[i] = serial_private;			write_unlock_irqrestore (&serial_rwlock, flags);			dbg_usbe (1, "---> calling serproto_create(%s,-,%u,%u,%u,%u,%u)", "ttyUSBx",				  CONFIG_USBD_SERIAL_IN_PKTSIZE, txqueue_urbs, txqueue_bytes, safe,				  safe ? 2 : 0);			if ((interface = serproto_create ("ttyUSBx", serial_xmit_data,							  (safe							   ? (CONFIG_USBD_SERIAL_IN_PKTSIZE -							      2) : CONFIG_USBD_SERIAL_IN_PKTSIZE),							  txqueue_urbs, txqueue_bytes, safe,							  safe ? 2 : 0)) < 0) {				// lock and modify device array				write_lock_irqsave (&serial_rwlock, flags);				kfree (serial_private);				serial_created--;				//MOD_DEC_USE_COUNT;				//dbg_init(0,"CREATE X2 sc=%d uc=%d",serial_created,GET_USE_COUNT(THIS_MODULE));				write_unlock_irqrestore (&serial_rwlock, flags);				dbg_usbe (1, "---> serproto_create FAILED");				return;			}			// lock and modify device array			write_lock_irqsave (&serial_rwlock, flags);			serial_private->interface = interface;			serial_private->device = device;			write_unlock_irqrestore (&serial_rwlock, flags);			function->privdata = serial_private;			dbg_usbe (1, "---> START %s privdata assigned: %p interface: %d",				  device->name, serial_private, interface);			return;		}		break;	case DEVICE_HUB_CONFIGURED:		break;	case DEVICE_RESET:		break;	case DEVICE_ADDRESS_ASSIGNED:		break;	case DEVICE_CONFIGURED:		{			struct usb_serial_private *serial_private;			int interface;			if ((serial_private =			     (device->function_instance_array + port)->privdata) == NULL) {				return;			}			interface = serial_private->interface;			if (interface < 0 || interface >= MAX_INTERFACES) {				return;			}			serproto_control (interface, SERPROTO_CONNECT);		}		break;	case DEVICE_SET_INTERFACE:#ifdef CONFIG_USBD_SERIAL_CDC#endif		break;	case DEVICE_SET_FEATURE:		break;	case DEVICE_CLEAR_FEATURE:		break;	case DEVICE_DE_CONFIGURED:		{			struct usb_serial_private *serial_private;			int interface;			if ((serial_private =			     (device->function_instance_array + port)->privdata) == NULL) {				return;			}			interface = serial_private->interface;			if (interface < 0 || interface >= MAX_INTERFACES) {				return;			}			serproto_control (interface, SERPROTO_DISCONNECT);		}		break;	case DEVICE_BUS_INACTIVE:		break;	case DEVICE_BUS_ACTIVITY:		break;	case DEVICE_POWER_INTERRUPTION:		break;	case DEVICE_HUB_RESET:		break;	case DEVICE_DESTROY:		{			struct usb_serial_private *serial_private;			int interface;			if ((serial_private =			     (device->function_instance_array + port)->privdata) == NULL) {				dbg_usbe (1, "---> DESTROY %s serial_private null", device->name);				// XXX XXX MOD_DEC_USE_COUNT;				// XXX XXX dbg_init(0,"DESTROY Z1 sc=%d uc=%d",serial_created,GET_USE_COUNT(THIS_MODULE));				return;			}			dbg_usbe (1, "---> DESTROY %s serial_private %p", device->name,				  serial_private);			interface = serial_private->interface;			if (interface < 0 || interface >= MAX_INTERFACES) {				// XXX XXX MOD_DEC_USE_COUNT;				// XXX XXX dbg_init(0,"DESTROY Z2 sc=%d uc=%d",serial_created,GET_USE_COUNT(THIS_MODULE));				return;			}			if (serial_private_array[interface] != serial_private) {				// XXX XXX MOD_DEC_USE_COUNT;				// XXX XXX dbg_init(0,"DESTROY Z3 sc=%d uc=%d",serial_created,GET_USE_COUNT(THIS_MODULE));				return;			}			write_lock_irqsave (&serial_rwlock, flags);			serial_private_array[interface] = NULL;			kfree (serial_private);			serial_created--;			write_unlock_irqrestore (&serial_rwlock, flags);			serproto_destroy (interface);			// XXX XXX MOD_DEC_USE_COUNT;			// XXX XXX dbg_init(0,"DESTROY sc=%d uc=%d",serial_created,GET_USE_COUNT(THIS_MODULE));			dbg_usbe (1, "---> STOP %s", device->name);			return;		}		break;	case DEVICE_FUNCTION_PRIVATE:		break;	}}/* serial_recv_urb - called to indicate URB has been received * @urb - pointer to struct urb * * Return non-zero if we failed and urb is still valid (not disposed) */int serial_recv_urb (struct urb *urb){	int port = 0;		// XXX compound device	struct usb_device_instance *device = urb->device;	struct usb_serial_private *serial_private =	    (device->function_instance_array + port)->privdata;	int interface = serial_private->interface;	dbg_rx (2, "length=%d", urb->actual_length);	dbgPRINTmem (dbgflg_usbdfd_rx, 3, urb->buffer, urb->actual_length);#ifdef CONFIG_USBD_SERIAL_SAFE	if (safe) {		__u16 fcs;		if ((fcs = fcs_compute10 (urb->buffer, urb->actual_length, CRC10_INITFCS))) {			dbg_rx (0, "CRC check failed");			//return -EINVAL;		} else {			// recover the length from the trailer			urb->actual_length = (urb->buffer[urb->actual_length - 2] >> 2);		}	}	dbg_rx (2, "revised length=%d", urb->actual_length);#endif#if 0	if (0 != dbgflg_usbdfd_loopback) {		if (usbd_send_urb (urb)) {			//XXX verify not freed in usbd_send_urb()			//urb->buffer = NULL;			//urb->actual_length = 0;			//usbd_dealloc_urb(urb);		}		return 0;	}#endif	// push the data up	if (serproto_recv (interface, urb->buffer, urb->actual_length)) {		return (1);	}	// free urb	usbd_recycle_urb (urb);	return (0);}struct usb_function_operations function_ops = {	event:serial_event,	recv_urb:serial_recv_urb,	urb_sent:serial_urb_sent};struct usb_function_driver function_driver = {	name:"function prototype",	ops:&function_ops,	device_description:&serial_device_description,	configurations:sizeof (serial_description) / sizeof (struct usb_configuration_description),	configuration_description:serial_description,	this_module:THIS_MODULE,};/* * serial_modinit - module init * */static int __init serial_modinit (void){	debug_option *op = find_debug_option (dbg_table, "ser");	printk (KERN_INFO "%s (%s)\n", __usbd_module_info, dbg);#ifdef CONFIG_USBD_SERIAL_SAFE	printk (KERN_INFO "vendor_id: %04x product_id: %04x safe: %d padded: %d\n", vendor_id,		product_id, safe, padded);#else	printk (KERN_INFO "vendor_id: %04x product_id: %04x\n", vendor_id, product_id);	if (safe || padded) {		printk (KERN_ERR "serial_fd: not compiled for safe mode\n");		return -EINVAL;	}#endif	printk (KERN_INFO "dbg: %s\n", dbg);	if (NULL != op) {		op->sub_table = serproto_get_dbg_table ();	}	if (0 != scan_debug_options ("serial_fd", dbg_table, dbg)) {		return (-EINVAL);	}	if (vendor_id) {		serial_device_description.idVendor = vendor_id;	}	if (product_id) {		serial_device_description.idProduct = product_id;	}	// Initialize the function registration code.	//	//if (usbd_strings_init()) {	//    return -EINVAL;	//}	// initialize the serproto library	//	if (serproto_modinit ("ttyUSBn", MAX_INTERFACES)) {		return -EINVAL;	}	// register us with the usb device support layer	//	if (usbd_register_function (&function_driver)) {		serproto_modexit ();		return -EINVAL;	}	dbg_loop (1, "LOOPBACK mode");	// return	return 0;}/* serial_modexit - module cleanup */static void __exit serial_modexit (void){	// de-register us with the usb device support layer	// 	usbd_deregister_function (&function_driver);	// tell the serproto library to exit	//	serproto_modexit ();}module_init (serial_modinit);module_exit (serial_modexit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -