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

📄 auermain.c

📁 ep9315平台下USB驱动的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		return;	/* Wake up all processes waiting for a buffer */	wake_up(&cp->bufferwait);	/* Cleaning up */	auerisdn_disconnect(cp);	auerswald_int_release(cp);	auerchain_free(&cp->controlchain);	auerbuf_free_buffers(&cp->bufctl);	/* release the memory */	kfree(cp);}/* add a new service to the device   scp->id must be set!   return: 0 if OK, else error code*/int auerswald_addservice(struct auerswald *cp, struct auerscon *scp){	int ret;	/* is the device available? */	if (!cp->usbdev) {		dbg("usbdev == NULL");		return -EIO;	/*no: can not add a service, sorry */	}	/* is the service available? */	if (cp->services[scp->id]) {		dbg("service is busy");		return -EBUSY;	}	/* device is available, service is free */	cp->services[scp->id] = scp;	/* register service in device */	ret = auerchain_control_msg(&cp->controlchain,			/* pointer to control chain */				    cp->usbdev,				/* pointer to device */				    usb_sndctrlpipe(cp->usbdev, 0),	/* pipe to control endpoint */				    AUV_CHANNELCTL,			/* USB message request value */				    AUT_WREQ,				/* USB message request type value */				    0x01,	/* open */		/* USB message value */				    scp->id,				/* USB message index value */				    NULL,				/* pointer to the data to send */				    0,					/* length in bytes of the data to send */				    HZ * 2);				/* time to wait for the message to complete before timing out */	if (ret < 0) {		dbg("auerswald_addservice: auerchain_control_msg returned error code %d", ret);		/* undo above actions */		cp->services[scp->id] = NULL;		return ret;	}	dbg("auerswald_addservice: channel open OK");	return 0;}/* remove a service from the the device   scp->id must be set! */void auerswald_removeservice(struct auerswald *cp, struct auerscon *scp){	dbg("auerswald_removeservice called");	/* check if we have a service allocated */	if (scp->id == AUH_UNASSIGNED)		return;	/* If there is a device: close the channel */	if (cp->usbdev && !cp->disconnecting) {		/* Close the service channel inside the device */		int ret = auerchain_control_msg(&cp->controlchain,		/* pointer to control chain */						cp->usbdev,			/* pointer to device */						usb_sndctrlpipe(cp->usbdev, 0),	/* pipe to control endpoint */						AUV_CHANNELCTL,			/* USB message request value */						AUT_WREQ,			/* USB message request type value */						0x00,	/* close */		/* USB message value */						scp->id,			/* USB message index value */						NULL,				/* pointer to the data to send */						0,				/* length in bytes of the data to send */						HZ * 2);			/* time to wait for the message to complete before timing out */		if (ret < 0) {			dbg("auerswald_removeservice: auerchain_control_msg returned error code %d", ret);		} else {			dbg("auerswald_removeservice: channel close OK");		}	}	/* remove the service from the device */	cp->services[scp->id] = NULL;	scp->id = AUH_UNASSIGNED;}/*----------------------------------------------------------------------*//* File operation structure                                             */static struct file_operations auerswald_fops = {	owner:THIS_MODULE,	llseek:auerchar_llseek,	read:auerchar_read,	write:auerchar_write,	ioctl:auerchar_ioctl,	open:auerchar_open,	release:auerchar_release,};/* --------------------------------------------------------------------- *//* Special USB driver functions                                          *//* Probe if this driver wants to serve an USB device   This entry point is called whenever a new device is attached to the bus.   Then the device driver has to create a new instance of its internal data   structures for the new device.   The  dev argument specifies the device context, which contains pointers   to all USB descriptors. The  interface argument specifies the interface   number. If a USB driver wants to bind itself to a particular device and   interface it has to return a pointer. This pointer normally references   the device driver's context structure.   Probing normally is done by checking the vendor and product identifications   or the class and subclass definitions. If they match the interface number   is compared with the ones supported by the driver. When probing is done   class based it might be necessary to parse some more USB descriptors because   the device properties can differ in a wide range.*/static void *auerswald_probe(struct usb_device *usbdev, unsigned int ifnum,			     const struct usb_device_id *id){	struct auerswald *cp = NULL;	DECLARE_WAIT_QUEUE_HEAD(wqh);	unsigned int dtindex;	unsigned int u = 0;	char *pbuf;	int ret;	dbg("probe: vendor id 0x%x, device id 0x%x ifnum:%d",	    usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,	    ifnum);	/* See if the device offered us matches that we can accept */	if (usbdev->descriptor.idVendor != ID_AUERSWALD)		return NULL;	/* we use only the first -and only- interface */	if (ifnum != 0)		return NULL;	/* prevent module unloading while sleeping */	MOD_INC_USE_COUNT;	/* allocate memory for our device and intialize it */	cp = kmalloc(sizeof(struct auerswald), GFP_KERNEL);	if (cp == NULL) {		err("out of memory");		goto pfail;	}	/* Initialize device descriptor */	memset(cp, 0, sizeof(struct auerswald));	init_MUTEX(&cp->mutex);	cp->usbdev = usbdev;	auerchain_init(&cp->controlchain);	auerbuf_init(&cp->bufctl);	init_waitqueue_head(&cp->bufferwait);	auerisdn_init_dev(cp);	/* find a free slot in the device table */	down(&auerdev_table_mutex);	for (dtindex = 0; dtindex < AUER_MAX_DEVICES; ++dtindex) {		if (auerdev_table[dtindex] == NULL)			break;	}	if (dtindex >= AUER_MAX_DEVICES) {		err("more than %d devices plugged in, can not handle this device", AUER_MAX_DEVICES);		up(&auerdev_table_mutex);		goto pfail;	}	/* Give the device a name */	sprintf(cp->name, AU_PREFIX "%d", dtindex);	/* Store the index */	cp->dtindex = dtindex;	auerdev_table[dtindex] = cp;	up(&auerdev_table_mutex);	/* initialize the devfs node for this device and register it */	cp->devfs = devfs_register(usb_devfs_handle, cp->name,				   DEVFS_FL_DEFAULT, USB_MAJOR,				   AUER_MINOR_BASE + dtindex,				   S_IFCHR | S_IRUGO | S_IWUGO,				   &auerswald_fops, NULL);	/* Get the usb version of the device */	cp->version = cp->usbdev->descriptor.bcdDevice;	dbg("Version is %X", cp->version);	/* allow some time to settle the device */	sleep_on_timeout(&wqh, HZ / 3);	/* Try to get a suitable textual description of the device */	/* Device name: */	ret =	    usb_string(cp->usbdev, AUSI_DEVICE, cp->dev_desc,		       AUSI_DLEN - 1);	if (ret >= 0) {		u += ret;		/* Append Serial Number */		memcpy(&cp->dev_desc[u], ",Ser# ", 6);		u += 6;		ret =		    usb_string(cp->usbdev, AUSI_SERIALNR, &cp->dev_desc[u],			       AUSI_DLEN - u - 1);		if (ret >= 0) {			u += ret;			/* Append subscriber number */			memcpy(&cp->dev_desc[u], ", ", 2);			u += 2;			ret =			    usb_string(cp->usbdev, AUSI_MSN,				       &cp->dev_desc[u],				       AUSI_DLEN - u - 1);			if (ret >= 0) {				u += ret;			}		}	}	cp->dev_desc[u] = '\0';	info("device is a %s", cp->dev_desc);	/* get the maximum allowed control transfer length */	pbuf = (char *) kmalloc(2, GFP_KERNEL);	/* use an allocated buffer because of urb target */	if (!pbuf) {		err("out of memory");		goto pfail;	}	ret = usb_control_msg(cp->usbdev,			/* pointer to device */			      usb_rcvctrlpipe(cp->usbdev, 0),	/* pipe to control endpoint */			      AUV_GETINFO,			/* USB message request value */			      AUT_RREQ,				/* USB message request type value */			      0,				/* USB message value */			      AUDI_MBCTRANS,			/* USB message index value */			      pbuf,				/* pointer to the receive buffer */			      2,				/* length of the buffer */			      HZ * 2);				/* time to wait for the message to complete before timing out */	if (ret == 2) {		cp->maxControlLength = le16_to_cpup(pbuf);		kfree(pbuf);		dbg("setup: max. allowed control transfersize is %d bytes",		    cp->maxControlLength);	} else {		kfree(pbuf);		err("setup: getting max. allowed control transfer length failed with error %d", ret);		goto pfail;	}	/* allocate a chain for the control messages */	if (auerchain_setup(&cp->controlchain, AUCH_ELEMENTS)) {		err("out of memory");		goto pfail;	}	/* allocate buffers for control messages */	if (auerbuf_setup	    (&cp->bufctl, AU_RBUFFERS * 2,	     cp->maxControlLength + AUH_SIZE)) {		err("out of memory");		goto pfail;	}	/* start the interrupt endpoint */	if (auerswald_int_open(cp)) {		err("int endpoint failed");		goto pfail;	}	/* Try to connect to hisax interface */	if (auerisdn_probe(cp)) {		err("hisax connect failed");		goto pfail;	}	/* all OK */	return cp;	/* Error exit: clean up the memory */      pfail:auerswald_delete(cp);	MOD_DEC_USE_COUNT;	return NULL;}/* Disconnect driver from a served device   This function is called whenever a device which was served by this driver   is disconnected.   The argument  dev specifies the device context and the  driver_context   returns a pointer to the previously registered  driver_context of the   probe function. After returning from the disconnect function the USB   framework completly deallocates all data structures associated with   this device. So especially the usb_device structure must not be used   any longer by the usb driver.*/static void auerswald_disconnect(struct usb_device *usbdev,				 void *driver_context){	struct auerswald *cp = (struct auerswald *) driver_context;	unsigned int u;	/* all parallel tasks can react on disconnect ASAP */	cp->disconnecting = 1;	down(&cp->mutex);	info("device /dev/usb/%s now disconnecting", cp->name);	/* remove from device table */	/* Nobody can open() this device any more */	down(&auerdev_table_mutex);	auerdev_table[cp->dtindex] = NULL;	up(&auerdev_table_mutex);	/* remove our devfs node */	/* Nobody can see this device any more */	devfs_unregister(cp->devfs);	/* stop the ISDN connection */	auerisdn_disconnect(cp);	/* Stop the interrupt endpoint 0 */	auerswald_int_release(cp);	/* remove the control chain allocated in auerswald_probe	   This has the benefit of	   a) all pending (a)synchronous urbs are unlinked	   b) all buffers dealing with urbs are reclaimed	 */	auerchain_free(&cp->controlchain);	if (cp->open_count == 0) {		struct auerscon *scp;		/* nobody is using this device. So we can clean up now */		up(&cp->mutex);	/* up() is possible here because no other task				   can open the device (see above). I don't want				   to kfree() a locked mutex. */		/* disconnect the D channel */		scp = cp->services[AUH_DCHANNEL];		if (scp)			scp->disconnect(scp);		auerswald_delete(cp);	} else {		/* device is used. Remove the pointer to the		   usb device (it's not valid any more). The last		   release() will do the clean up */		cp->usbdev = NULL;		up(&cp->mutex);		/* Terminate waiting writers */		wake_up(&cp->bufferwait);		/* Inform all waiting readers */		for (u = 0; u < AUH_TYPESIZE; u++) {			struct auerscon *scp = cp->services[u];			if (scp)				scp->disconnect(scp);		}	}	/* The device releases this module */	MOD_DEC_USE_COUNT;}/* Descriptor for the devices which are served by this driver.   NOTE: this struct is parsed by the usbmanager install scripts.         Don't change without caution!*/static struct usb_device_id auerswald_ids[] = {	{USB_DEVICE(ID_AUERSWALD, 0x00C0)},	/* COMpact 2104 USB/DSL */	{USB_DEVICE(ID_AUERSWALD, 0x00DB)},	/* COMpact 4410/2206 USB */	{USB_DEVICE(ID_AUERSWALD, 0x00DC)},	/* comming soon... */	{USB_DEVICE(ID_AUERSWALD, 0x00F1)},	/* Comfort 2000 System Telephone */	{USB_DEVICE(ID_AUERSWALD, 0x00F2)},	/* Comfort 1200 System Telephone */	{}					/* Terminating entry */};/* Standard module device table */MODULE_DEVICE_TABLE(usb, auerswald_ids);/* Standard usb driver struct */static struct usb_driver auerswald_driver = {	name:"auerswald",	probe:auerswald_probe,	disconnect:auerswald_disconnect,	fops:&auerswald_fops,	minor:AUER_MINOR_BASE,	id_table:auerswald_ids,};/* --------------------------------------------------------------------- *//* Module loading/unloading                                              *//* Driver initialisation. Called after module loading.   NOTE: there is no concurrency at _init*/static int __init auerswald_init(void){	int result;	dbg("init");	/* initialize the device table */	memset(&auerdev_table, 0, sizeof(auerdev_table));	init_MUTEX(&auerdev_table_mutex);	auerisdn_init();	/* register driver at the USB subsystem */	/* NOTE: usb_register() may call probe()! */	result = usb_register(&auerswald_driver);	if (result < 0) {		err("driver could not be registered");		return -1;	}	return 0;}/* Driver deinit. Called before module removal.   NOTE: there is no concurrency at _cleanup*/static void __exit auerswald_cleanup(void){	dbg("cleanup");	auerisdn_cleanup();	usb_deregister(&auerswald_driver);}/* --------------------------------------------------------------------- *//* Linux device driver module description                                */MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");module_init(auerswald_init);module_exit(auerswald_cleanup);/* --------------------------------------------------------------------- */

⌨️ 快捷键说明

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