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

📄 adb.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		flags |= ADBREQ_SYNC;	}	req->nbytes = nbytes+1;	req->done = done;	req->reply_expected = flags & ADBREQ_REPLY;	req->data[0] = ADB_PACKET;	va_start(list, nbytes);	for (i = 0; i < nbytes; ++i)		req->data[i+1] = va_arg(list, int);	va_end(list);	if (flags & ADBREQ_NOSEND)		return 0;	return adb_controller->send_request(req, flags & ADBREQ_SYNC);} /* Ultimately this should return the number of devices with    the given default id.    And it does it now ! Note: changed behaviour: This function    will now register if default_id _and_ handler_id both match    but handler_id can be left to 0 to match with default_id only.    When handler_id is set, this function will try to adjust    the handler_id id it doesn't match. */intadb_register(int default_id, int handler_id, struct adb_ids *ids,	     void (*handler)(unsigned char *, int, struct pt_regs *, int)){	int i;	ids->nids = 0;	for (i = 1; i < 16; i++) {		if ((adb_handler[i].original_address == default_id) &&		    (!handler_id || (handler_id == adb_handler[i].handler_id) || 		    adb_try_handler_change(i, handler_id))) {			if (adb_handler[i].handler != 0) {				printk(KERN_ERR				       "Two handlers for ADB device %d\n",				       default_id);				continue;			}			adb_handler[i].handler = handler;			ids->id[ids->nids++] = i;		}	}	return ids->nids;}intadb_unregister(int index){	if (!adb_handler[index].handler)		return -ENODEV;	adb_handler[index].handler = 0;	return 0;}voidadb_input(unsigned char *buf, int nb, struct pt_regs *regs, int autopoll){	int i, id;	static int dump_adb_input = 0;	/* We skip keystrokes and mouse moves when the sleep process	 * has been started. We stop autopoll, but this is another security	 */	if (adb_got_sleep)		return;			id = buf[0] >> 4;	if (dump_adb_input) {		printk(KERN_INFO "adb packet: ");		for (i = 0; i < nb; ++i)			printk(" %x", buf[i]);		printk(", id = %d\n", id);	}	if (adb_handler[id].handler != 0) {		(*adb_handler[id].handler)(buf, nb, regs, autopoll);	}}/* Try to change handler to new_id. Will return 1 if successful */intadb_try_handler_change(int address, int new_id){	struct adb_request req;	if (adb_handler[address].handler_id == new_id)	    return 1;	adb_request(&req, NULL, ADBREQ_SYNC, 3,	    ADB_WRITEREG(address, 3), address | 0x20, new_id);	adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,	    ADB_READREG(address, 3));	if (req.reply_len < 2)	    return 0;	if (req.reply[2] != new_id)	    return 0;	adb_handler[address].handler_id = req.reply[2];	return 1;}intadb_get_infos(int address, int *original_address, int *handler_id){	*original_address = adb_handler[address].original_address;	*handler_id = adb_handler[address].handler_id;		return (*original_address != 0);}/* * /dev/adb device driver. */#define ADB_MAJOR	56	/* major number for /dev/adb */extern void adbdev_init(void);struct adbdev_state {	spinlock_t	lock;	atomic_t	n_pending;	struct adb_request *completed;  	wait_queue_head_t wait_queue;	int		inuse;};static void adb_write_done(struct adb_request *req){	struct adbdev_state *state = (struct adbdev_state *) req->arg;	unsigned long flags;	if (!req->complete) {		req->reply_len = 0;		req->complete = 1;	}	spin_lock_irqsave(&state->lock, flags);	atomic_dec(&state->n_pending);	if (!state->inuse) {		kfree(req);		if (atomic_read(&state->n_pending) == 0) {			spin_unlock_irqrestore(&state->lock, flags);			kfree(state);			return;		}	} else {		struct adb_request **ap = &state->completed;		while (*ap != NULL)			ap = &(*ap)->next;		req->next = NULL;		*ap = req;		wake_up_interruptible(&state->wait_queue);	}	spin_unlock_irqrestore(&state->lock, flags);}static int adb_open(struct inode *inode, struct file *file){	struct adbdev_state *state;	if (MINOR(inode->i_rdev) > 0 || adb_controller == NULL)		return -ENXIO;	state = kmalloc(sizeof(struct adbdev_state), GFP_KERNEL);	if (state == 0)		return -ENOMEM;	file->private_data = state;	spin_lock_init(&state->lock);	atomic_set(&state->n_pending, 0);	state->completed = NULL;	init_waitqueue_head(&state->wait_queue);	state->inuse = 1;	return 0;}static int adb_release(struct inode *inode, struct file *file){	struct adbdev_state *state = file->private_data;	unsigned long flags;	lock_kernel();	if (state) {		file->private_data = NULL;		spin_lock_irqsave(&state->lock, flags);		if (atomic_read(&state->n_pending) == 0		    && state->completed == NULL) {			spin_unlock_irqrestore(&state->lock, flags);			kfree(state);		} else {			state->inuse = 0;			spin_unlock_irqrestore(&state->lock, flags);		}	}	unlock_kernel();	return 0;}static long long adb_lseek(struct file *file, loff_t offset, int origin){	return -ESPIPE;}static ssize_t adb_read(struct file *file, char *buf,			size_t count, loff_t *ppos){	int ret;	struct adbdev_state *state = file->private_data;	struct adb_request *req;	wait_queue_t wait = __WAITQUEUE_INITIALIZER(wait,current);	unsigned long flags;	if (count < 2)		return -EINVAL;	if (count > sizeof(req->reply))		count = sizeof(req->reply);	ret = verify_area(VERIFY_WRITE, buf, count);	if (ret)		return ret;	req = NULL;	add_wait_queue(&state->wait_queue, &wait);	current->state = TASK_INTERRUPTIBLE;	for (;;) {		spin_lock_irqsave(&state->lock, flags);		req = state->completed;		if (req != NULL)			state->completed = req->next;		else if (atomic_read(&state->n_pending) == 0)			ret = -EIO;		spin_unlock_irqrestore(&state->lock, flags);		if (req != NULL || ret != 0)			break;				if (file->f_flags & O_NONBLOCK) {			ret = -EAGAIN;			break;		}		if (signal_pending(current)) {			ret = -ERESTARTSYS;			break;		}		schedule();	}	current->state = TASK_RUNNING;	remove_wait_queue(&state->wait_queue, &wait);	if (ret)		return ret;	ret = req->reply_len;	if (ret > count)		ret = count;	if (ret > 0 && copy_to_user(buf, req->reply, ret))		ret = -EFAULT;	kfree(req);	return ret;}static ssize_t adb_write(struct file *file, const char *buf,			 size_t count, loff_t *ppos){	int ret/*, i*/;	struct adbdev_state *state = file->private_data;	struct adb_request *req;	if (count < 2 || count > sizeof(req->data))		return -EINVAL;	ret = verify_area(VERIFY_READ, buf, count);	if (ret)		return ret;	req = (struct adb_request *) kmalloc(sizeof(struct adb_request),					     GFP_KERNEL);	if (req == NULL)		return -ENOMEM;	req->nbytes = count;	req->done = adb_write_done;	req->arg = (void *) state;	req->complete = 0;		ret = -EFAULT;	if (copy_from_user(req->data, buf, count))		goto out;	atomic_inc(&state->n_pending);	if (adb_controller == NULL) return -ENXIO;	/* Special case for ADB_BUSRESET request, all others are sent to	   the controller */	if ((req->data[0] == ADB_PACKET)&&(count > 1)		&&(req->data[1] == ADB_BUSRESET)) {		ret = adb_reset_bus();		atomic_dec(&state->n_pending);		goto out;	} else {			req->reply_expected = ((req->data[1] & 0xc) == 0xc);		if (adb_controller && adb_controller->send_request)			ret = adb_controller->send_request(req, 0);		else			ret = -ENXIO;	}	if (ret != 0) {		atomic_dec(&state->n_pending);		goto out;	}	return count;out:	kfree(req);	return ret;}static struct file_operations adb_fops = {	llseek:		adb_lseek,	read:		adb_read,	write:		adb_write,	open:		adb_open,	release:	adb_release,};void adbdev_init(){#ifdef CONFIG_PPC	if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) )		return;#endif#ifdef CONFIG_MAC	if (!MACH_IS_MAC)		return;#endif	if (devfs_register_chrdev(ADB_MAJOR, "adb", &adb_fops))		printk(KERN_ERR "adb: unable to get major %d\n", ADB_MAJOR);	else		devfs_register (NULL, "adb", DEVFS_FL_DEFAULT,				ADB_MAJOR, 0,				S_IFCHR | S_IRUSR | S_IWUSR,				&adb_fops, NULL);}

⌨️ 快捷键说明

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