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

📄 auerswald.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
        newbp->len = bp->len;        /* insert new buffer in read list */        spin_lock_irqsave (&ccp->bufctl.lock, flags);	list_add_tail (&newbp->buff_list, &ccp->bufctl.rec_buff_list);        spin_unlock_irqrestore (&ccp->bufctl.lock, flags);        dbg ("read buffer appended to rec_list");        /* wake up pending synchronous reads */	wake_up (&ccp->readwait);}/* Delete an auerswald driver context */static void auerswald_delete( pauerswald_t cp){	dbg( "auerswald_delete");	if (cp == NULL)		return;	/* Wake up all processes waiting for a buffer */	wake_up (&cp->bufferwait);	/* Cleaning up */	auerswald_int_release (cp);	auerchain_free (&cp->controlchain);	auerbuf_free_buffers (&cp->bufctl);	/* release the memory */	kfree( cp);}/* Delete an auerswald character context */static void auerchar_delete( pauerchar_t ccp){	dbg ("auerchar_delete");	if (ccp == NULL)		return;        /* wake up pending synchronous reads */	ccp->removed = 1;	wake_up (&ccp->readwait);	/* remove the read buffer */	if (ccp->readbuf) {		auerbuf_releasebuf (ccp->readbuf);		ccp->readbuf = NULL;	}	/* remove the character buffers */	auerbuf_free_buffers (&ccp->bufctl);	/* release the memory */	kfree( ccp);}/* add a new service to the device   scp->id must be set!   return: 0 if OK, else error code*/static int auerswald_addservice (pauerswald_t cp, pauerscon_t 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! */static void auerswald_removeservice (pauerswald_t cp, pauerscon_t 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) {		/* 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;}/* --------------------------------------------------------------------- *//* Char device functions                                                 *//* Open a new character device */static int auerchar_open (struct inode *inode, struct file *file){	int dtindex = iminor(inode);	pauerswald_t cp = NULL;	pauerchar_t ccp = NULL;	struct usb_interface *intf;        int ret;        /* minor number in range? */	if (dtindex < 0) {		return -ENODEV;        }	intf = usb_find_interface(&auerswald_driver, dtindex);	if (!intf) {		return -ENODEV;	}	/* usb device available? */	cp = usb_get_intfdata (intf);	if (cp == NULL) {		return -ENODEV;	}	if (down_interruptible (&cp->mutex)) {		return -ERESTARTSYS;	}	/* we have access to the device. Now lets allocate memory */	ccp = (pauerchar_t) kmalloc(sizeof(auerchar_t), GFP_KERNEL);	if (ccp == NULL) {		err ("out of memory");		ret = -ENOMEM;		goto ofail;	}	/* Initialize device descriptor */	memset( ccp, 0, sizeof(auerchar_t));	init_MUTEX( &ccp->mutex);	init_MUTEX( &ccp->readmutex);        auerbuf_init (&ccp->bufctl);        ccp->scontext.id = AUH_UNASSIGNED;        ccp->scontext.dispatch = auerchar_ctrlread_dispatch;	ccp->scontext.disconnect = auerchar_disconnect;	init_waitqueue_head (&ccp->readwait);	ret = auerbuf_setup (&ccp->bufctl, AU_RBUFFERS, cp->maxControlLength+AUH_SIZE);       	if (ret) {		goto ofail;	}	cp->open_count++;	ccp->auerdev = cp;	dbg("open %s as /dev/%s", cp->dev_desc, cp->name);	up (&cp->mutex);	/* file IO stuff */	file->f_pos = 0;	file->private_data = ccp;	return nonseekable_open(inode, file);	/* Error exit */ofail:	up (&cp->mutex);	auerchar_delete (ccp);	return ret;}/* IOCTL functions */static int auerchar_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	pauerchar_t ccp = (pauerchar_t) file->private_data;	int ret = 0;        audevinfo_t devinfo;        pauerswald_t cp = NULL;	unsigned int u;	unsigned int __user *user_arg = (unsigned int __user *)arg;        dbg ("ioctl");	/* get the mutexes */	if (down_interruptible (&ccp->mutex)) {		return -ERESTARTSYS;	}	cp = ccp->auerdev;	if (!cp) {		up (&ccp->mutex);                return -ENODEV;	}	if (down_interruptible (&cp->mutex)) {		up(&ccp->mutex);		return -ERESTARTSYS;	}	/* Check for removal */	if (!cp->usbdev) {		up(&cp->mutex);		up(&ccp->mutex);                return -ENODEV;	}	switch (cmd) {	/* return != 0 if Transmitt channel ready to send */	case IOCTL_AU_TXREADY:		dbg ("IOCTL_AU_TXREADY");		u   = ccp->auerdev		   && (ccp->scontext.id != AUH_UNASSIGNED)		   && !list_empty (&cp->bufctl.free_buff_list);	        ret = put_user (u, user_arg);		break;	/* return != 0 if connected to a service channel */	case IOCTL_AU_CONNECT:		dbg ("IOCTL_AU_CONNECT");		u = (ccp->scontext.id != AUH_UNASSIGNED);	        ret = put_user (u, user_arg);		break;	/* return != 0 if Receive Data available */	case IOCTL_AU_RXAVAIL:		dbg ("IOCTL_AU_RXAVAIL");		if (ccp->scontext.id == AUH_UNASSIGNED) {                        ret = -EIO;                        break;                }		u = 0;	/* no data */		if (ccp->readbuf) {			int restlen = ccp->readbuf->len - ccp->readoffset;			if (restlen > 0)				u = 1;		}		if (!u) {        		if (!list_empty (&ccp->bufctl.rec_buff_list)) {				u = 1;			}		}	        ret = put_user (u, user_arg);		break;	/* return the max. buffer length for the device */	case IOCTL_AU_BUFLEN:		dbg ("IOCTL_AU_BUFLEN");		u = cp->maxControlLength;	        ret = put_user (u, user_arg);		break;	/* requesting a service channel */        case IOCTL_AU_SERVREQ:		dbg ("IOCTL_AU_SERVREQ");                /* requesting a service means: release the previous one first */		auerswald_removeservice (cp, &ccp->scontext);		/* get the channel number */		ret = get_user (u, user_arg);		if (ret) {			break;		}		if ((u < AUH_FIRSTUSERCH) || (u >= AUH_TYPESIZE)) {                        ret = -EIO;                        break;                }                dbg ("auerchar service request parameters are ok");		ccp->scontext.id = u;		/* request the service now */		ret = auerswald_addservice (cp, &ccp->scontext);		if (ret) {			/* no: revert service entry */                	ccp->scontext.id = AUH_UNASSIGNED;		}		break;	/* get a string descriptor for the device */	case IOCTL_AU_DEVINFO:		dbg ("IOCTL_AU_DEVINFO");                if (copy_from_user (&devinfo, (void __user *) arg, sizeof (audevinfo_t))) {        		ret = -EFAULT;	        	break;                }		u = strlen(cp->dev_desc)+1;		if (u > devinfo.bsize) {			u = devinfo.bsize;		}		ret = copy_to_user(devinfo.buf, cp->dev_desc, u) ? -EFAULT : 0;		break;	/* get the max. string descriptor length */        case IOCTL_AU_SLEN:		dbg ("IOCTL_AU_SLEN");		u = AUSI_DLEN;	        ret = put_user (u, user_arg);		break;	default:		dbg ("IOCTL_AU_UNKNOWN");		ret = -ENOIOCTLCMD;		break;        }	/* release the mutexes */	up(&cp->mutex);	up(&ccp->mutex);	return ret;}/* Read data from the device */static ssize_t auerchar_read (struct file *file, char __user *buf, size_t count, loff_t * ppos){        unsigned long flags;	pauerchar_t ccp = (pauerchar_t) file->private_data;        pauerbuf_t   bp = NULL;	wait_queue_t wait;        dbg ("auerchar_read");	/* Error checking */	if (!ccp)		return -EIO;	if (*ppos) 		return -ESPIPE;        if (count == 0)		return 0;	/* get the mutex */	if (down_interruptible (&ccp->mutex))		return -ERESTARTSYS;	/* Can we expect to read something? */	if (ccp->scontext.id == AUH_UNASSIGNED) {		up (&ccp->mutex);                return -EIO;	}	/* only one reader per device allowed */	if (down_interruptible (&ccp->readmutex)) {		up (&ccp->mutex);		return -ERESTARTSYS;	}	/* read data from readbuf, if available */doreadbuf:	bp = ccp->readbuf;	if (bp) {		/* read the maximum bytes */		int restlen = bp->len - ccp->readoffset;		if (restlen < 0)			restlen = 0;		if (count > restlen)			count = restlen;		if (count) {			if (copy_to_user (buf, bp->bufp+ccp->readoffset, count)) {				dbg ("auerswald_read: copy_to_user failed");				up (&ccp->readmutex);				up (&ccp->mutex);				return -EFAULT;			}		}		/* advance the read offset */		ccp->readoffset += count;

⌨️ 快捷键说明

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