/*------------------------------------------------------------------------------
 * This is called when the USB service is started or resumed for a PD.
 * Context: softirq
 */
int oz_usb_start(struct oz_pd *pd, int resume)
{
	int rc = 0;
	struct oz_usb_ctx *usb_ctx;
	struct oz_usb_ctx *old_ctx = 0;
	oz_event_log(OZ_EVT_SERVICE, 3, OZ_APPID_USB, 0, resume);
	if (resume) {
		oz_trace("USB service resumed.\n");
		return 0;
	}
	oz_trace("USB service started.\n");
	/* Create a USB context in case we need one. If we find the PD already
	 * has a USB context then we will destroy it.
	 */
	usb_ctx = kzalloc(sizeof(struct oz_usb_ctx), GFP_ATOMIC);
	if (usb_ctx == 0)
		return -ENOMEM;
	atomic_set(&usb_ctx->ref_count, 1);
	usb_ctx->pd = pd;
	usb_ctx->stopped = 0;
	/* Install the USB context if the PD doesn't already have one.
	 * If it does already have one then destroy the one we have just
	 * created.
	 */
	spin_lock_bh(&pd->app_lock[OZ_APPID_USB-1]);
	old_ctx = pd->app_ctx[OZ_APPID_USB-1];
	if (old_ctx == 0)
		pd->app_ctx[OZ_APPID_USB-1] = usb_ctx;
	oz_usb_get(pd->app_ctx[OZ_APPID_USB-1]);
	spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]);
	if (old_ctx) {
		oz_trace("Already have USB context.\n");
		kfree(usb_ctx);
		usb_ctx = old_ctx;
	} else if (usb_ctx) {
		/* Take a reference to the PD. This will be released when
		 * the USB context is destroyed.
		 */
		oz_pd_get(pd);
	}
	/* If we already had a USB context and had obtained a port from
	 * the USB HCD then just reset the port. If we didn't have a port
	 * then report the arrival to the USB HCD so we get one.
	 */
	if (usb_ctx->hport) {
		oz_hcd_pd_reset(usb_ctx, usb_ctx->hport);
	} else {
		usb_ctx->hport = oz_hcd_pd_arrived(usb_ctx);
		if (usb_ctx->hport == 0) {
			oz_trace("USB hub returned null port.\n");
			spin_lock_bh(&pd->app_lock[OZ_APPID_USB-1]);
			pd->app_ctx[OZ_APPID_USB-1] = 0;
			spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]);
			oz_usb_put(usb_ctx);
			rc = -1;
		}
	}
	oz_usb_put(usb_ctx);
	return rc;
}
示例#2
0
/*------------------------------------------------------------------------------
 * Context: softirq or process
 */
void oz_cdev_stop(struct oz_pd *pd, int pause)
{
	struct oz_serial_ctx *ctx;
	oz_event_log(OZ_EVT_SERVICE, 4, OZ_APPID_SERIAL, 0, pause);
	if (pause) {
		oz_trace("Serial service paused.\n");
		return;
	}
	spin_lock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]);
	ctx = (struct oz_serial_ctx *)pd->app_ctx[OZ_APPID_SERIAL-1];
	pd->app_ctx[OZ_APPID_SERIAL-1] = 0;
	spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]);
	if (ctx)
		oz_cdev_release_ctx(ctx);
	spin_lock(&g_cdev.lock);
	if (pd == g_cdev.active_pd)
		g_cdev.active_pd = 0;
	else
		pd = 0;
	spin_unlock(&g_cdev.lock);
	if (pd) {
		oz_pd_put(pd);
		oz_trace("Active PD departed.\n");
	}
	oz_trace("Serial service stopped.\n");
}
示例#3
0
/*------------------------------------------------------------------------------
 * This is called when the USB service is stopped or paused for a PD.
 * Context: softirq or process
 */
void oz_usb_stop(struct oz_pd *pd, int pause)
{
	struct oz_usb_ctx *usb_ctx;
	if (pause) {
		oz_trace("USB service paused.\n");
		return;
	}
	spin_lock_bh(&pd->app_lock[OZ_APPID_USB-1]);
	usb_ctx = (struct oz_usb_ctx *)pd->app_ctx[OZ_APPID_USB-1];
	pd->app_ctx[OZ_APPID_USB-1] = NULL;
	spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]);
	if (usb_ctx) {
		unsigned long tout = jiffies + HZ;
		oz_trace("USB service stopping...\n");
		usb_ctx->stopped = 1;
		/* At this point the reference count on the usb context should
		 * be 2 - one from when we created it and one from the hcd
		 * which claims a reference. Since stopped = 1 no one else
		 * should get in but someone may already be in. So wait
		 * until they leave but timeout after 1 second.
		 */
		while ((atomic_read(&usb_ctx->ref_count) > 2) &&
			time_before(jiffies, tout))
			;
		oz_trace("USB service stopped.\n");
		oz_hcd_pd_departed(usb_ctx->hport);
		/* Release the reference taken in oz_usb_start.
		 */
		oz_usb_put(usb_ctx);
	}
}
示例#4
0
/*------------------------------------------------------------------------------
 * Context: softirq-serialized
 */
int oz_cdev_start(struct oz_pd *pd, int resume)
{
	struct oz_serial_ctx *ctx;
	struct oz_serial_ctx *old_ctx = 0;
	oz_event_log(OZ_EVT_SERVICE, 3, OZ_APPID_SERIAL, 0, resume);
	if (resume) {
		oz_trace("Serial service resumed.\n");
		return 0;
	}
	ctx = kzalloc(sizeof(struct oz_serial_ctx), GFP_ATOMIC);
	if (ctx == 0)
		return -ENOMEM;
	atomic_set(&ctx->ref_count, 1);
	ctx->tx_seq_num = 1;
	spin_lock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]);
	old_ctx = pd->app_ctx[OZ_APPID_SERIAL-1];
	if (old_ctx) {
		spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]);
		kfree(ctx);
	} else {
		pd->app_ctx[OZ_APPID_SERIAL-1] = ctx;
		spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]);
	}
	spin_lock(&g_cdev.lock);
	if ((g_cdev.active_pd == 0) &&
		(memcmp(pd->mac_addr, g_cdev.active_addr, ETH_ALEN) == 0)) {
		oz_pd_get(pd);
		g_cdev.active_pd = pd;
		oz_trace("Active PD arrived.\n");
	}
	spin_unlock(&g_cdev.lock);
	oz_trace("Serial service started.\n");
	return 0;
}
示例#5
0
/*------------------------------------------------------------------------------
 * Context: softirq-serialized
 */
void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt)
{
	struct oz_serial_ctx *ctx;
	struct oz_app_hdr *app_hdr;
	u8 *data;
	int len;
	int space;
	int copy_sz;
	int ix;

	ctx = oz_cdev_claim_ctx(pd);
	if (ctx == 0) {
		oz_trace("Cannot claim serial context.\n");
		return;
	}

	app_hdr = (struct oz_app_hdr *)(elt+1);
	/* If sequence number is non-zero then check it is not a duplicate.
	 */
	if (app_hdr->elt_seq_num != 0) {
		if (((ctx->rx_seq_num - app_hdr->elt_seq_num) & 0x80) == 0) {
			/* Reject duplicate element. */
			oz_trace("Duplicate element:%02x %02x\n",
				app_hdr->elt_seq_num, ctx->rx_seq_num);
			goto out;
		}
	}
	ctx->rx_seq_num = app_hdr->elt_seq_num;
	len = elt->length - sizeof(struct oz_app_hdr);
	data = ((u8 *)(elt+1)) + sizeof(struct oz_app_hdr);
	if (len <= 0)
		goto out;
	space = ctx->rd_out - ctx->rd_in - 1;
	if (space < 0)
		space += OZ_RD_BUF_SZ;
	if (len > space) {
		oz_trace("Not enough space:%d %d\n", len, space);
		len = space;
	}
	ix = ctx->rd_in;
	copy_sz = OZ_RD_BUF_SZ - ix;
	if (copy_sz > len)
		copy_sz = len;
	memcpy(&ctx->rd_buf[ix], data, copy_sz);
	len -= copy_sz;
	ix += copy_sz;
	if (ix == OZ_RD_BUF_SZ)
		ix = 0;
	if (len) {
		memcpy(ctx->rd_buf, data+copy_sz, len);
		ix = len;
	}
	ctx->rd_in = ix;
	wake_up(&g_cdev.rdq);
out:
	oz_cdev_release_ctx(ctx);
}
示例#6
0
/*------------------------------------------------------------------------------
 * Context: process
 */
int oz_cdev_open(struct inode *inode, struct file *filp)
{
	struct oz_cdev *dev;
	oz_trace("oz_cdev_open()\n");
	oz_trace("major = %d minor = %d\n", imajor(inode), iminor(inode));
	dev = container_of(inode->i_cdev, struct oz_cdev, cdev);
	filp->private_data = dev;
	return 0;
}
/*-----------------------------------------------------------------------------
 */
void oz_remember_urb(struct urb *urb)
{
	unsigned long irq_state;
	spin_lock_irqsave(&g_urb_mem_lock, irq_state);
	if (g_nb_urbs < OZ_MAX_URBS) {
		g_urb_memory[g_nb_urbs++] = urb;
		oz_trace("%lu: urb up = %d %p\n", jiffies, g_nb_urbs, urb);
	} else {
		oz_trace("ERROR urb buffer full\n");
	}
	spin_unlock_irqrestore(&g_urb_mem_lock, irq_state);
}
示例#8
0
/*------------------------------------------------------------------------------
 * Context: softirq
 */
int oz_pd_sleep(struct oz_pd *pd)
{
	int do_stop = 0;
	u16 stop_apps = 0;
	oz_polling_lock_bh();
	if (pd->state & (OZ_PD_S_SLEEP | OZ_PD_S_STOPPED)) {
		oz_polling_unlock_bh();
		return 0;
	}
	if (pd->keep_alive_j && pd->session_id) {
		oz_pd_set_state(pd, OZ_PD_S_SLEEP);
		pd->pulse_time_j = jiffies + pd->keep_alive_j;
		oz_trace("Sleep Now %lu until %lu\n",
			jiffies, pd->pulse_time_j);
	} else {
		do_stop = 1;
	}
	stop_apps = pd->total_apps;
	oz_polling_unlock_bh();
	if (do_stop) {
		oz_pd_stop(pd);
	} else {
		oz_services_stop(pd, stop_apps, 1);
		oz_timer_add(pd, OZ_TIMER_STOP, jiffies + pd->keep_alive_j, 1);
	}
	return do_stop;
}
示例#9
0
/*------------------------------------------------------------------------------
 * Context: softirq or process
 */
static void oz_cdev_release_ctx(struct oz_serial_ctx *ctx)
{
	if (atomic_dec_and_test(&ctx->ref_count)) {
		oz_trace("Dealloc serial context.\n");
		kfree(ctx);
	}
}
示例#10
0
/*------------------------------------------------------------------------------
 * This decrements the reference count of the context area for a specific PD
 * and destroys the context area if the reference count becomes zero.
 * Context: softirq or process
 */
void oz_usb_put(void *hpd)
{
	struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
	if (atomic_dec_and_test(&usb_ctx->ref_count)) {
		oz_trace("Dealloc USB context.\n");
		oz_pd_put(usb_ctx->pd);
		kfree(usb_ctx);
	}
}
示例#11
0
/*------------------------------------------------------------------------------
 * Context: softirq or process
 */
void oz_pd_stop(struct oz_pd *pd)
{
	u16 stop_apps = 0;
	oz_trace("oz_pd_stop() State = 0x%x\n", pd->state);
	oz_pd_indicate_farewells(pd);
	oz_polling_lock_bh();
	stop_apps = pd->total_apps;
	pd->total_apps = 0;
	pd->paused_apps = 0;
	oz_polling_unlock_bh();
	oz_services_stop(pd, stop_apps, 0);
	oz_polling_lock_bh();
	oz_pd_set_state(pd, OZ_PD_S_STOPPED);
	/* Remove from PD list.*/
	list_del(&pd->link);
	oz_polling_unlock_bh();
	oz_trace("pd ref count = %d\n", atomic_read(&pd->ref_count));
	oz_timer_delete(pd, 0);
	oz_pd_put(pd);
}
示例#12
0
/*------------------------------------------------------------------------------
 * Context: softirq or process
 */
void oz_pd_set_state(struct oz_pd *pd, unsigned state)
{
	pd->state = state;
	oz_event_log(OZ_EVT_PD_STATE, 0, 0, 0, state);
#ifdef WANT_TRACE
	switch (state) {
	case OZ_PD_S_IDLE:
		oz_trace("PD State: OZ_PD_S_IDLE\n");
		break;
	case OZ_PD_S_CONNECTED:
		oz_trace("PD State: OZ_PD_S_CONNECTED\n");
		break;
	case OZ_PD_S_STOPPED:
		oz_trace("PD State: OZ_PD_S_STOPPED\n");
		break;
	case OZ_PD_S_SLEEP:
		oz_trace("PD State: OZ_PD_S_SLEEP\n");
		break;
	}
#endif /* WANT_TRACE */
}
示例#13
0
/*------------------------------------------------------------------------------
 * Context: softirq
 */
int oz_usb_get_desc_req(void *hpd, u8 req_id, u8 req_type, u8 desc_type,
	u8 index, u16 windex, int offset, int len)
{
	struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
	struct oz_pd *pd = usb_ctx->pd;
	struct oz_elt *elt;
	struct oz_get_desc_req *body;
	struct oz_elt_buf *eb = &pd->elt_buff;
	struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff);
	oz_trace("    req_type = 0x%x\n", req_type);
	oz_trace("    desc_type = 0x%x\n", desc_type);
	oz_trace("    index = 0x%x\n", index);
	oz_trace("    windex = 0x%x\n", windex);
	oz_trace("    offset = 0x%x\n", offset);
	oz_trace("    len = 0x%x\n", len);
	if (len > 200)
		len = 200;
	if (ei == 0)
		return -1;
	elt = (struct oz_elt *)ei->data;
	elt->length = sizeof(struct oz_get_desc_req);
	body = (struct oz_get_desc_req *)(elt+1);
	body->type = OZ_GET_DESC_REQ;
	body->req_id = req_id;
	put_unaligned(cpu_to_le16(offset), &body->offset);
	put_unaligned(cpu_to_le16(len), &body->size);
	body->req_type = req_type;
	body->desc_type = desc_type;
	body->w_index = windex;
	body->index = index;
	return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0);
}
示例#14
0
/*------------------------------------------------------------------------------
 * Context: softirq-serialized
 */
int oz_services_start(struct oz_pd *pd, u16 apps, int resume)
{
	struct oz_app_if *ai;
	int rc = 0;
	oz_trace("oz_services_start(0x%x) resume(%d)\n", apps, resume);
	for (ai = g_app_if; ai < &g_app_if[OZ_APPID_MAX]; ai++) {
		if (apps & (1<<ai->app_id)) {
			if (ai->start(pd, resume)) {
				rc = -1;
				oz_trace("Unabled to start service %d\n",
					ai->app_id);
				break;
			}
			oz_polling_lock_bh();
			pd->total_apps |= (1<<ai->app_id);
			if (resume)
				pd->paused_apps &= ~(1<<ai->app_id);
			oz_polling_unlock_bh();
		}
	}
	return rc;
}
示例#15
0
/*------------------------------------------------------------------------------
 * Context: softirq or process
 */
struct oz_elt_info *oz_elt_info_alloc(struct oz_elt_buf *buf)
{
	struct oz_elt_info *ei = 0;
	spin_lock_bh(&buf->lock);
	if (buf->free_elts && buf->elt_pool) {
		ei = container_of(buf->elt_pool, struct oz_elt_info, link);
		buf->elt_pool = ei->link.next;
		buf->free_elts--;
		spin_unlock_bh(&buf->lock);
		if (ei->magic != OZ_ELT_INFO_MAGIC_FREE) {
			oz_trace("oz_elt_info_alloc: ei with bad magic: 0x%x\n",
				ei->magic);
		}
	} else {
示例#16
0
/*------------------------------------------------------------------------------
 * Context: process
 */
int oz_cdev_register(void)
{
	int err;
	memset(&g_cdev, 0, sizeof(g_cdev));
	err = alloc_chrdev_region(&g_cdev.devnum, 0, 1, "ozwpan");
	if (err < 0)
		return err;
	oz_trace("Alloc dev number %d:%d\n", MAJOR(g_cdev.devnum),
			MINOR(g_cdev.devnum));
	cdev_init(&g_cdev.cdev, &oz_fops);
	g_cdev.cdev.owner = THIS_MODULE;
	g_cdev.cdev.ops = &oz_fops;
	spin_lock_init(&g_cdev.lock);
	init_waitqueue_head(&g_cdev.rdq);
	err = cdev_add(&g_cdev.cdev, g_cdev.devnum, 1);
	return 0;
}
示例#17
0
/*------------------------------------------------------------------------------
 * Context: softirq
 */
int oz_usb_stream_create(void *hpd, u8 ep_num)
{
	struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
	struct oz_pd *pd = usb_ctx->pd;
	oz_trace("oz_usb_stream_create(0x%x)\n", ep_num);
	if (pd->mode & OZ_F_ISOC_NO_ELTS) {
		oz_isoc_stream_create(pd, ep_num);
	} else {
		oz_pd_get(pd);
		if (oz_elt_stream_create(&pd->elt_buff, ep_num,
			4*pd->max_tx_size)) {
			oz_pd_put(pd);
			return -1;
		}
	}
	return 0;
}
示例#18
0
/*------------------------------------------------------------------------------
 * Context: softirq or process
 */
void oz_pd_destroy(struct oz_pd *pd)
{
    struct list_head *e;
    struct oz_tx_frame *f;
    struct oz_isoc_stream *st;
    struct oz_farewell *fwell;
    oz_trace("Destroying PD\n");
    /* Delete any streams.
     */
    e = pd->stream_list.next;
    while (e != &pd->stream_list) {
        st = container_of(e, struct oz_isoc_stream, link);
        e = e->next;
        oz_isoc_stream_free(st);
    }
    /* Free any queued tx frames.
     */
    e = pd->tx_queue.next;
    while (e != &pd->tx_queue) {
        f = container_of(e, struct oz_tx_frame, link);
        e = e->next;
        if (f->skb != NULL)
            kfree_skb(f->skb);
        oz_retire_frame(pd, f);
    }
    oz_elt_buf_term(&pd->elt_buff);
    /* Free any farewells.
     */
    e = pd->farewell_list.next;
    while (e != &pd->farewell_list) {
        fwell = container_of(e, struct oz_farewell, link);
        e = e->next;
        kfree(fwell);
    }
    /* Deallocate all frames in tx pool.
     */
    while (pd->tx_pool) {
        e = pd->tx_pool;
        pd->tx_pool = e->next;
        kfree(container_of(e, struct oz_tx_frame, link));
    }
    if (pd->net_dev)
        dev_put(pd->net_dev);
    kfree(pd);
}
示例#19
0
/*------------------------------------------------------------------------------
 * Context: softirq or process
 */
void oz_services_stop(struct oz_pd *pd, u16 apps, int pause)
{
	struct oz_app_if *ai;
	oz_trace("oz_stop_services(0x%x) pause(%d)\n", apps, pause);
	for (ai = g_app_if; ai < &g_app_if[OZ_APPID_MAX]; ai++) {
		if (apps & (1<<ai->app_id)) {
			oz_polling_lock_bh();
			if (pause) {
				pd->paused_apps |= (1<<ai->app_id);
			} else {
				pd->total_apps &= ~(1<<ai->app_id);
				pd->paused_apps &= ~(1<<ai->app_id);
			}
			oz_polling_unlock_bh();
			ai->stop(pd, pause);
		}
	}
}
示例#20
0
/*------------------------------------------------------------------------------
 * Context: softirq
 */
int oz_usb_stream_delete(void *hpd, u8 ep_num)
{
	struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
	if (usb_ctx) {
		struct oz_pd *pd = usb_ctx->pd;
		if (pd) {
			oz_trace("oz_usb_stream_delete(0x%x)\n", ep_num);
			if (pd->mode & OZ_F_ISOC_NO_ELTS) {
				oz_isoc_stream_delete(pd, ep_num);
			} else {
				if (oz_elt_stream_delete(&pd->elt_buff, ep_num))
					return -1;
				oz_pd_put(pd);
			}
		}
	}
	return 0;
}
/*------------------------------------------------------------------------------
 */
int oz_forget_urb(struct urb *urb)
{
	unsigned long irq_state;
	int i;
	int rc = -1;
	spin_lock_irqsave(&g_urb_mem_lock, irq_state);
	for (i = 0; i < g_nb_urbs; i++) {
		if (g_urb_memory[i] == urb) {
			rc = 0;
			if (--g_nb_urbs > i)
				memcpy(&g_urb_memory[i], &g_urb_memory[i+1],
					(g_nb_urbs - i) * sizeof(struct urb *));
			oz_trace("%lu: urb down = %d %p\n",
				jiffies, g_nb_urbs, urb);
		}
	}
	spin_unlock_irqrestore(&g_urb_mem_lock, irq_state);
	return rc;
}
示例#22
0
/*------------------------------------------------------------------------------
 * Context: process
 */
unsigned int oz_cdev_poll(struct file *filp, poll_table *wait)
{
	unsigned int ret = 0;
	struct oz_cdev *dev = filp->private_data;
	oz_trace("Poll called wait = %p\n", wait);
	spin_lock_bh(&dev->lock);
	if (dev->active_pd) {
		struct oz_serial_ctx *ctx = oz_cdev_claim_ctx(dev->active_pd);
		if (ctx) {
			if (ctx->rd_in != ctx->rd_out)
				ret |= POLLIN | POLLRDNORM;
			oz_cdev_release_ctx(ctx);
		}
	}
	spin_unlock_bh(&dev->lock);
	if (wait)
		poll_wait(filp, &dev->rdq, wait);
	return ret;
}
void oz_event_init(void)
{
	oz_trace("Event tracing initialized\n");
	g_evt_in = g_evt_out = 0;
	g_missed_events = 0;
}
示例#24
0
/*------------------------------------------------------------------------------
 * Context: process
 */
long oz_cdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	int rc = 0;
	if (_IOC_TYPE(cmd) != OZ_IOCTL_MAGIC)
		return -ENOTTY;
	if (_IOC_NR(cmd) > OZ_IOCTL_MAX)
		return -ENOTTY;
	if (_IOC_DIR(cmd) & _IOC_READ)
		rc = !access_ok(VERIFY_WRITE, (void __user *)arg,
			_IOC_SIZE(cmd));
	else if (_IOC_DIR(cmd) & _IOC_WRITE)
		rc = !access_ok(VERIFY_READ, (void __user *)arg,
			_IOC_SIZE(cmd));
	if (rc)
		return -EFAULT;
	switch (cmd) {
	case OZ_IOCTL_GET_PD_LIST: {
			struct oz_pd_list list;
			oz_trace("OZ_IOCTL_GET_PD_LIST\n");
			list.count = oz_get_pd_list(list.addr, OZ_MAX_PDS);
			if (copy_to_user((void __user *)arg, &list,
				sizeof(list)))
				return -EFAULT;
		}
		break;
	case OZ_IOCTL_SET_ACTIVE_PD: {
			u8 addr[ETH_ALEN];
			oz_trace("OZ_IOCTL_SET_ACTIVE_PD\n");
			if (copy_from_user(addr, (void __user *)arg, ETH_ALEN))
				return -EFAULT;
			rc = oz_set_active_pd(addr);
		}
		break;
	case OZ_IOCTL_GET_ACTIVE_PD: {
			u8 addr[ETH_ALEN];
			oz_trace("OZ_IOCTL_GET_ACTIVE_PD\n");
			spin_lock_bh(&g_cdev.lock);
			memcpy(addr, g_cdev.active_addr, ETH_ALEN);
			spin_unlock_bh(&g_cdev.lock);
			if (copy_to_user((void __user *)arg, addr, ETH_ALEN))
				return -EFAULT;
		}
		break;
#ifdef WANT_EVENT_TRACE
	case OZ_IOCTL_CLEAR_EVENTS:
		oz_events_clear();
		break;
	case OZ_IOCTL_GET_EVENTS:
		rc = oz_events_copy((void __user *)arg);
		break;
	case OZ_IOCTL_SET_EVENT_MASK:
		if (copy_from_user(&g_evt_mask, (void __user *)arg,
			sizeof(unsigned long))) {
			return -EFAULT;
		}
		break;
#endif /* WANT_EVENT_TRACE */
	case OZ_IOCTL_ADD_BINDING:
	case OZ_IOCTL_REMOVE_BINDING: {
			struct oz_binding_info b;
			if (copy_from_user(&b, (void __user *)arg,
				sizeof(struct oz_binding_info))) {
				return -EFAULT;
			}
			/* Make sure name is null terminated. */
			b.name[OZ_MAX_BINDING_LEN-1] = 0;
			if (cmd == OZ_IOCTL_ADD_BINDING)
				oz_binding_add(b.name);
			else
				oz_binding_remove(b.name);
		}
		break;
	}
	return rc;
}
示例#25
0
/*------------------------------------------------------------------------------
 * Context: process
 */
int oz_cdev_release(struct inode *inode, struct file *filp)
{
	oz_trace("oz_cdev_release()\n");
	return 0;
}
void oz_event_term(void)
{
	oz_trace("Event tracing terminated\n");
}