svn commit: r215802 - in head/sys/dev/usb: . controller

Weongyo Jeong weongyo at FreeBSD.org
Wed Nov 24 19:11:33 UTC 2010


Author: weongyo
Date: Wed Nov 24 19:11:32 2010
New Revision: 215802
URL: http://svn.freebsd.org/changeset/base/215802

Log:
  Removes all duplicated code with BPF that it's greatly simplified and
  take all benefits whenever BPF code is improved.
  
  Pointed by:	jkim
  Reviewed by:	thompsa

Modified:
  head/sys/dev/usb/controller/usb_controller.c
  head/sys/dev/usb/usb_bus.h
  head/sys/dev/usb/usb_pf.c
  head/sys/dev/usb/usb_pf.h

Modified: head/sys/dev/usb/controller/usb_controller.c
==============================================================================
--- head/sys/dev/usb/controller/usb_controller.c	Wed Nov 24 18:35:11 2010	(r215801)
+++ head/sys/dev/usb/controller/usb_controller.c	Wed Nov 24 19:11:32 2010	(r215802)
@@ -548,7 +548,7 @@ usb_bus_mem_alloc_all(struct usb_bus *bu
 
 	TAILQ_INIT(&bus->intr_q.head);
 
-	usbpf_attach(bus, &bus->uif);
+	usbpf_attach(bus);
 
 #if USB_HAVE_BUSDMA
 	usb_dma_tag_setup(bus->dma_parent_tag, bus->dma_tags,

Modified: head/sys/dev/usb/usb_bus.h
==============================================================================
--- head/sys/dev/usb/usb_bus.h	Wed Nov 24 18:35:11 2010	(r215801)
+++ head/sys/dev/usb/usb_bus.h	Wed Nov 24 19:11:32 2010	(r215802)
@@ -86,7 +86,7 @@ struct usb_bus {
 	struct usb_bus_methods *methods;	/* filled by HC driver */
 	struct usb_device **devices;
 
-	struct usbpf_if *uif;	/* USB Packet Filter */
+	struct ifnet *ifp;	/* only for USB Packet Filter */
 
 	usb_power_mask_t hw_power_state;	/* see USB_HW_POWER_XXX */
 	usb_size_t uframe_usage[USB_HS_MICRO_FRAMES_MAX];

Modified: head/sys/dev/usb/usb_pf.c
==============================================================================
--- head/sys/dev/usb/usb_pf.c	Wed Nov 24 18:35:11 2010	(r215801)
+++ head/sys/dev/usb/usb_pf.c	Wed Nov 24 19:11:32 2010	(r215802)
@@ -43,6 +43,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/socket.h>
 #include <sys/sockio.h>
 #include <net/if.h>
+#include <net/if_types.h>
+#include <net/bpf.h>
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
@@ -55,1624 +57,39 @@ __FBSDID("$FreeBSD$");
 #include <dev/usb/usb_pf.h>
 #include <dev/usb/usb_transfer.h>
 
-/*
- * All usbpf implementations are extracted from bpf(9) APIs and it's
- * specialized for USB packet filtering between the driver and the host
- * controller.
- */
-
-MALLOC_DEFINE(M_USBPF, "USBPktFilter", "USB Packet Filter");
-
-/*
- * Rotate the packet buffers in descriptor ud.  Move the store buffer into the
- * hold slot, and the free buffer ino the store slot.  Zero the length of the
- * new store buffer.  Descriptor lock should be held.
- */
-#define	USBPF_ROTATE_BUFFERS(ud)	do {				\
-	(ud)->ud_hbuf = (ud)->ud_sbuf;					\
-	(ud)->ud_hlen = (ud)->ud_slen;					\
-	(ud)->ud_sbuf = (ud)->ud_fbuf;					\
-	(ud)->ud_slen = 0;						\
-	(ud)->ud_fbuf = NULL;						\
-	usbpf_bufheld(ud);						\
-} while (0)
-
-#ifndef __i386__
-#define	USBPF_ALIGN
-#endif
-
-#ifndef USBPF_ALIGN
-#define	USBPF_EXTRACT_SHORT(p)	((u_int16_t)ntohs(*(u_int16_t *)p))
-#define	USBPF_EXTRACT_LONG(p)	(ntohl(*(u_int32_t *)p))
-#else
-#define	USBPF_EXTRACT_SHORT(p)						\
-	((u_int16_t)							\
-	    ((u_int16_t)*((u_char *)p+0)<<8|				\
-		(u_int16_t)*((u_char *)p+1)<<0))
-#define	USBPF_EXTRACT_LONG(p)						\
-	((u_int32_t)*((u_char *)p+0)<<24|				\
-	    (u_int32_t)*((u_char *)p+1)<<16|				\
-	    (u_int32_t)*((u_char *)p+2)<<8|				\
-	    (u_int32_t)*((u_char *)p+3)<<0)
-#endif
-
-/*
- * Number of scratch memory words (for USBPF_LD|USBPF_MEM and USBPF_ST).
- */
-#define	USBPF_MEMWORDS		 16
-
-/* Values for ud_state */
-#define	USBPF_IDLE		0	/* no select in progress */
-#define	USBPF_WAITING		1	/* waiting for read timeout in select */
-#define	USBPF_TIMED_OUT		2	/* read timeout has expired in select */
-
-#define	PRIUSB			26	/* interruptible */
-
-/* Frame directions */
-enum usbpf_direction {
-	USBPF_D_IN,	/* See incoming frames */
-	USBPF_D_INOUT,	/* See incoming and outgoing frames */
-	USBPF_D_OUT	/* See outgoing frames */
-};
-
-static void	usbpf_append_bytes(struct usbpf_d *, caddr_t, u_int, void *,
-		    u_int);
-static void	usbpf_attachd(struct usbpf_d *, struct usbpf_if *);
-static void	usbpf_detachd(struct usbpf_d *);
-static int	usbpf_canfreebuf(struct usbpf_d *);
-static void	usbpf_buf_reclaimed(struct usbpf_d *);
-static int	usbpf_canwritebuf(struct usbpf_d *);
-
-static	d_open_t	usbpf_open;
-static	d_read_t	usbpf_read;
-static	d_write_t	usbpf_write;
-static	d_ioctl_t	usbpf_ioctl;
-static	d_poll_t	usbpf_poll;
-static	d_kqfilter_t	usbpf_kqfilter;
-
-static struct cdevsw usbpf_cdevsw = {
-	.d_version =	D_VERSION,
-	.d_open =	usbpf_open,
-	.d_read =	usbpf_read,
-	.d_write =	usbpf_write,
-	.d_ioctl =	usbpf_ioctl,
-	.d_poll =	usbpf_poll,
-	.d_name =	"usbpf",
-	.d_kqfilter =	usbpf_kqfilter,
-};
-
-static struct cdev *usbpf_cdev;
-static LIST_HEAD(, usbpf_if)	usbpf_iflist;
-static struct mtx	usbpf_mtx;		/* global lock */
-static int usbpf_uifd_cnt;
-
-static int usbpf_bufsize = 4096;
-#define	USBPF_MINBUFSIZE 32
-#define	USBPF_MAXBUFSIZE 0x80000
-static int usbpf_maxbufsize = USBPF_MAXBUFSIZE;
-#define	USBPF_MAXINSNS 512
-static int usbpf_maxinsns = USBPF_MAXINSNS;
-
-static void
-usbpf_buffer_init(struct usbpf_d *ud)
-{
-
-	ud->ud_bufsize = usbpf_bufsize;
-}
-
-/*
- * Free USBPF kernel buffers on device close.
- */
-static void
-usbpf_buffer_free(struct usbpf_d *ud)
-{
-
-	if (ud->ud_sbuf != NULL)
-		free(ud->ud_sbuf, M_USBPF);
-	if (ud->ud_hbuf != NULL)
-		free(ud->ud_hbuf, M_USBPF);
-	if (ud->ud_fbuf != NULL)
-		free(ud->ud_fbuf, M_USBPF);
-
-#ifdef INVARIANTS
-	ud->ud_sbuf = ud->ud_hbuf = ud->ud_fbuf = (caddr_t)~0;
-#endif
-}
-
-static void
-usbpf_buffer_alloc(struct usbpf_d *ud)
-{
-
-	KASSERT(ud->ud_fbuf == NULL, ("%s: ud_fbuf != NULL", __func__));
-	KASSERT(ud->ud_sbuf == NULL, ("%s: ud_sbuf != NULL", __func__));
-	KASSERT(ud->ud_hbuf == NULL, ("%s: ud_hbuf != NULL", __func__));
-
-	ud->ud_fbuf = (caddr_t)malloc(ud->ud_bufsize, M_USBPF, M_WAITOK);
-	ud->ud_sbuf = (caddr_t)malloc(ud->ud_bufsize, M_USBPF, M_WAITOK);
-	ud->ud_hbuf = NULL;
-	ud->ud_slen = 0;
-	ud->ud_hlen = 0;
-}
-
-/*
- * Copy buffer storage to user space in read().
- */
-static int
-usbpf_buffer_uiomove(struct usbpf_d *ud, caddr_t buf, u_int len,
-    struct uio *uio)
-{
-
-	return (uiomove(buf, len, uio));
-}
-
-/*
- * Simple data copy to the current kernel buffer.
- */
-static void
-usbpf_buffer_append_bytes(struct usbpf_d *ud, caddr_t buf, u_int offset,
-    void *src, u_int len)
-{
-	u_char *src_bytes;
-
-	src_bytes = (u_char *)src;
-	bcopy(src_bytes, buf + offset, len);
-}
-
-/*
- * Allocate or resize buffers.
- */
-static int
-usbpf_buffer_ioctl_sblen(struct usbpf_d *ud, u_int *i)
-{
-	u_int size;
-
-	USBPFD_LOCK(ud);
-	if (ud->ud_bif != NULL) {
-		USBPFD_UNLOCK(ud);
-		return (EINVAL);
-	}
-	size = *i;
-	if (size > usbpf_maxbufsize)
-		*i = size = usbpf_maxbufsize;
-	else if (size < USBPF_MINBUFSIZE)
-		*i = size = USBPF_MINBUFSIZE;
-	ud->ud_bufsize = size;
-	USBPFD_UNLOCK(ud);
-	return (0);
-}
-
-static const u_short	usbpf_code_map[] = {
-	0x10ff,	/* 0x00-0x0f: 1111111100001000 */
-	0x3070,	/* 0x10-0x1f: 0000111000001100 */
-	0x3131,	/* 0x20-0x2f: 1000110010001100 */
-	0x3031,	/* 0x30-0x3f: 1000110000001100 */
-	0x3131,	/* 0x40-0x4f: 1000110010001100 */
-	0x1011,	/* 0x50-0x5f: 1000100000001000 */
-	0x1013,	/* 0x60-0x6f: 1100100000001000 */
-	0x1010,	/* 0x70-0x7f: 0000100000001000 */
-	0x0093,	/* 0x80-0x8f: 1100100100000000 */
-	0x0000,	/* 0x90-0x9f: 0000000000000000 */
-	0x0000,	/* 0xa0-0xaf: 0000000000000000 */
-	0x0002,	/* 0xb0-0xbf: 0100000000000000 */
-	0x0000,	/* 0xc0-0xcf: 0000000000000000 */
-	0x0000,	/* 0xd0-0xdf: 0000000000000000 */
-	0x0000,	/* 0xe0-0xef: 0000000000000000 */
-	0x0000	/* 0xf0-0xff: 0000000000000000 */
-};
-
-#define	USBPF_VALIDATE_CODE(c)	\
-    ((c) <= 0xff && (usbpf_code_map[(c) >> 4] & (1 << ((c) & 0xf))) != 0)
-
-/*
- * Return true if the 'fcode' is a valid filter program.
- * The constraints are that each jump be forward and to a valid
- * code.  The code must terminate with either an accept or reject.
- *
- * The kernel needs to be able to verify an application's filter code.
- * Otherwise, a bogus program could easily crash the system.
- */
-static int
-usbpf_validate(const struct usbpf_insn *f, int len)
-{
-	register int i;
-	register const struct usbpf_insn *p;
-
-	/* Do not accept negative length filter. */
-	if (len < 0)
-		return (0);
-
-	/* An empty filter means accept all. */
-	if (len == 0)
-		return (1);
-
-	for (i = 0; i < len; ++i) {
-		p = &f[i];
-		/*
-		 * Check that the code is valid.
-		 */
-		if (!USBPF_VALIDATE_CODE(p->code))
-			return (0);
-		/*
-		 * Check that that jumps are forward, and within
-		 * the code block.
-		 */
-		if (USBPF_CLASS(p->code) == USBPF_JMP) {
-			register u_int offset;
-
-			if (p->code == (USBPF_JMP|USBPF_JA))
-				offset = p->k;
-			else
-				offset = p->jt > p->jf ? p->jt : p->jf;
-			if (offset >= (u_int)(len - i) - 1)
-				return (0);
-			continue;
-		}
-		/*
-		 * Check that memory operations use valid addresses.
-		 */
-		if (p->code == USBPF_ST || p->code == USBPF_STX ||
-		    p->code == (USBPF_LD|USBPF_MEM) ||
-		    p->code == (USBPF_LDX|USBPF_MEM)) {
-			if (p->k >= USBPF_MEMWORDS)
-				return (0);
-			continue;
-		}
-		/*
-		 * Check for constant division by 0.
-		 */
-		if (p->code == (USBPF_ALU|USBPF_DIV|USBPF_K) && p->k == 0)
-			return (0);
-	}
-	return (USBPF_CLASS(f[len - 1].code) == USBPF_RET);
-}
-
-#ifdef _KERNEL
-#define	MINDEX(m, k) \
-{ \
-	register int len = m->m_len; \
- \
-	while (k >= len) { \
-		k -= len; \
-		m = m->m_next; \
-		if (m == 0) \
-			return (0); \
-		len = m->m_len; \
-	} \
-}
-
-static u_int16_t	m_xhalf(struct mbuf *m, usbpf_u_int32 k, int *err);
-static u_int32_t	m_xword(struct mbuf *m, usbpf_u_int32 k, int *err);
-
-static u_int32_t
-m_xword(struct mbuf *m, usbpf_u_int32 k, int *err)
-{
-	size_t len;
-	u_char *cp, *np;
-	struct mbuf *m0;
-
-	len = m->m_len;
-	while (k >= len) {
-		k -= len;
-		m = m->m_next;
-		if (m == 0)
-			goto bad;
-		len = m->m_len;
-	}
-	cp = mtod(m, u_char *) + k;
-	if (len - k >= 4) {
-		*err = 0;
-		return (USBPF_EXTRACT_LONG(cp));
-	}
-	m0 = m->m_next;
-	if (m0 == 0 || m0->m_len + len - k < 4)
-		goto bad;
-	*err = 0;
-	np = mtod(m0, u_char *);
-	switch (len - k) {
-	case 1:
-		return (((u_int32_t)cp[0] << 24) |
-		    ((u_int32_t)np[0] << 16) |
-		    ((u_int32_t)np[1] << 8)  |
-		    (u_int32_t)np[2]);
-
-	case 2:
-		return (((u_int32_t)cp[0] << 24) |
-		    ((u_int32_t)cp[1] << 16) |
-		    ((u_int32_t)np[0] << 8) |
-		    (u_int32_t)np[1]);
-
-	default:
-		return (((u_int32_t)cp[0] << 24) |
-		    ((u_int32_t)cp[1] << 16) |
-		    ((u_int32_t)cp[2] << 8) |
-		    (u_int32_t)np[0]);
-	}
-    bad:
-	*err = 1;
-	return (0);
-}
-
-static u_int16_t
-m_xhalf(struct mbuf *m, usbpf_u_int32 k, int *err)
-{
-	size_t len;
-	u_char *cp;
-	struct mbuf *m0;
-
-	len = m->m_len;
-	while (k >= len) {
-		k -= len;
-		m = m->m_next;
-		if (m == 0)
-			goto bad;
-		len = m->m_len;
-	}
-	cp = mtod(m, u_char *) + k;
-	if (len - k >= 2) {
-		*err = 0;
-		return (USBPF_EXTRACT_SHORT(cp));
-	}
-	m0 = m->m_next;
-	if (m0 == 0)
-		goto bad;
-	*err = 0;
-	return ((cp[0] << 8) | mtod(m0, u_char *)[0]);
- bad:
-	*err = 1;
-	return (0);
-}
-#endif
-
-/*
- * Execute the filter program starting at pc on the packet p
- * wirelen is the length of the original packet
- * buflen is the amount of data present
- */
-static u_int
-usbpf_filter(const struct usbpf_insn *pc, u_char *p, u_int wirelen,
-    u_int buflen)
-{
-	u_int32_t A = 0, X = 0;
-	usbpf_u_int32 k;
-	u_int32_t mem[USBPF_MEMWORDS];
-
-	/*
-	 * XXX temporarily the filter system is disabled because currently it
-	 * could not handle the some machine code properly that leads to
-	 * kernel crash by invalid usage.
-	 */
-	return ((u_int)-1);
-
-	if (pc == NULL)
-		/*
-		 * No filter means accept all.
-		 */
-		return ((u_int)-1);
-
-	--pc;
-	while (1) {
-		++pc;
-		switch (pc->code) {
-		default:
-#ifdef _KERNEL
-			return (0);
-#else
-			abort();
-#endif
-
-		case USBPF_RET|USBPF_K:
-			return ((u_int)pc->k);
-
-		case USBPF_RET|USBPF_A:
-			return ((u_int)A);
-
-		case USBPF_LD|USBPF_W|USBPF_ABS:
-			k = pc->k;
-			if (k > buflen || sizeof(int32_t) > buflen - k) {
-#ifdef _KERNEL
-				int merr;
-
-				if (buflen != 0)
-					return (0);
-				A = m_xword((struct mbuf *)p, k, &merr);
-				if (merr != 0)
-					return (0);
-				continue;
-#else
-				return (0);
-#endif
-			}
-#ifdef USBPF_ALIGN
-			if (((intptr_t)(p + k) & 3) != 0)
-				A = USBPF_EXTRACT_LONG(&p[k]);
-			else
-#endif
-				A = ntohl(*(int32_t *)(p + k));
-			continue;
-
-		case USBPF_LD|USBPF_H|USBPF_ABS:
-			k = pc->k;
-			if (k > buflen || sizeof(int16_t) > buflen - k) {
-#ifdef _KERNEL
-				int merr;
-
-				if (buflen != 0)
-					return (0);
-				A = m_xhalf((struct mbuf *)p, k, &merr);
-				continue;
-#else
-				return (0);
-#endif
-			}
-			A = USBPF_EXTRACT_SHORT(&p[k]);
-			continue;
-
-		case USBPF_LD|USBPF_B|USBPF_ABS:
-			k = pc->k;
-			if (k >= buflen) {
-#ifdef _KERNEL
-				struct mbuf *m;
-
-				if (buflen != 0)
-					return (0);
-				m = (struct mbuf *)p;
-				MINDEX(m, k);
-				A = mtod(m, u_char *)[k];
-				continue;
-#else
-				return (0);
-#endif
-			}
-			A = p[k];
-			continue;
-
-		case USBPF_LD|USBPF_W|USBPF_LEN:
-			A = wirelen;
-			continue;
-
-		case USBPF_LDX|USBPF_W|USBPF_LEN:
-			X = wirelen;
-			continue;
-
-		case USBPF_LD|USBPF_W|USBPF_IND:
-			k = X + pc->k;
-			if (pc->k > buflen || X > buflen - pc->k ||
-			    sizeof(int32_t) > buflen - k) {
-#ifdef _KERNEL
-				int merr;
-
-				if (buflen != 0)
-					return (0);
-				A = m_xword((struct mbuf *)p, k, &merr);
-				if (merr != 0)
-					return (0);
-				continue;
-#else
-				return (0);
-#endif
-			}
-#ifdef USBPF_ALIGN
-			if (((intptr_t)(p + k) & 3) != 0)
-				A = USBPF_EXTRACT_LONG(&p[k]);
-			else
-#endif
-				A = ntohl(*(int32_t *)(p + k));
-			continue;
-
-		case USBPF_LD|USBPF_H|USBPF_IND:
-			k = X + pc->k;
-			if (X > buflen || pc->k > buflen - X ||
-			    sizeof(int16_t) > buflen - k) {
-#ifdef _KERNEL
-				int merr;
-
-				if (buflen != 0)
-					return (0);
-				A = m_xhalf((struct mbuf *)p, k, &merr);
-				if (merr != 0)
-					return (0);
-				continue;
-#else
-				return (0);
-#endif
-			}
-			A = USBPF_EXTRACT_SHORT(&p[k]);
-			continue;
-
-		case USBPF_LD|USBPF_B|USBPF_IND:
-			k = X + pc->k;
-			if (pc->k >= buflen || X >= buflen - pc->k) {
-#ifdef _KERNEL
-				struct mbuf *m;
-
-				if (buflen != 0)
-					return (0);
-				m = (struct mbuf *)p;
-				MINDEX(m, k);
-				A = mtod(m, u_char *)[k];
-				continue;
-#else
-				return (0);
-#endif
-			}
-			A = p[k];
-			continue;
-
-		case USBPF_LDX|USBPF_MSH|USBPF_B:
-			k = pc->k;
-			if (k >= buflen) {
-#ifdef _KERNEL
-				register struct mbuf *m;
-
-				if (buflen != 0)
-					return (0);
-				m = (struct mbuf *)p;
-				MINDEX(m, k);
-				X = (mtod(m, u_char *)[k] & 0xf) << 2;
-				continue;
-#else
-				return (0);
-#endif
-			}
-			X = (p[pc->k] & 0xf) << 2;
-			continue;
-
-		case USBPF_LD|USBPF_IMM:
-			A = pc->k;
-			continue;
-
-		case USBPF_LDX|USBPF_IMM:
-			X = pc->k;
-			continue;
-
-		case USBPF_LD|USBPF_MEM:
-			A = mem[pc->k];
-			continue;
-
-		case USBPF_LDX|USBPF_MEM:
-			X = mem[pc->k];
-			continue;
-
-		case USBPF_ST:
-			mem[pc->k] = A;
-			continue;
-
-		case USBPF_STX:
-			mem[pc->k] = X;
-			continue;
-
-		case USBPF_JMP|USBPF_JA:
-			pc += pc->k;
-			continue;
-
-		case USBPF_JMP|USBPF_JGT|USBPF_K:
-			pc += (A > pc->k) ? pc->jt : pc->jf;
-			continue;
-
-		case USBPF_JMP|USBPF_JGE|USBPF_K:
-			pc += (A >= pc->k) ? pc->jt : pc->jf;
-			continue;
-
-		case USBPF_JMP|USBPF_JEQ|USBPF_K:
-			pc += (A == pc->k) ? pc->jt : pc->jf;
-			continue;
-
-		case USBPF_JMP|USBPF_JSET|USBPF_K:
-			pc += (A & pc->k) ? pc->jt : pc->jf;
-			continue;
-
-		case USBPF_JMP|USBPF_JGT|USBPF_X:
-			pc += (A > X) ? pc->jt : pc->jf;
-			continue;
-
-		case USBPF_JMP|USBPF_JGE|USBPF_X:
-			pc += (A >= X) ? pc->jt : pc->jf;
-			continue;
-
-		case USBPF_JMP|USBPF_JEQ|USBPF_X:
-			pc += (A == X) ? pc->jt : pc->jf;
-			continue;
-
-		case USBPF_JMP|USBPF_JSET|USBPF_X:
-			pc += (A & X) ? pc->jt : pc->jf;
-			continue;
-
-		case USBPF_ALU|USBPF_ADD|USBPF_X:
-			A += X;
-			continue;
-
-		case USBPF_ALU|USBPF_SUB|USBPF_X:
-			A -= X;
-			continue;
-
-		case USBPF_ALU|USBPF_MUL|USBPF_X:
-			A *= X;
-			continue;
-
-		case USBPF_ALU|USBPF_DIV|USBPF_X:
-			if (X == 0)
-				return (0);
-			A /= X;
-			continue;
-
-		case USBPF_ALU|USBPF_AND|USBPF_X:
-			A &= X;
-			continue;
-
-		case USBPF_ALU|USBPF_OR|USBPF_X:
-			A |= X;
-			continue;
-
-		case USBPF_ALU|USBPF_LSH|USBPF_X:
-			A <<= X;
-			continue;
-
-		case USBPF_ALU|USBPF_RSH|USBPF_X:
-			A >>= X;
-			continue;
-
-		case USBPF_ALU|USBPF_ADD|USBPF_K:
-			A += pc->k;
-			continue;
-
-		case USBPF_ALU|USBPF_SUB|USBPF_K:
-			A -= pc->k;
-			continue;
-
-		case USBPF_ALU|USBPF_MUL|USBPF_K:
-			A *= pc->k;
-			continue;
-
-		case USBPF_ALU|USBPF_DIV|USBPF_K:
-			A /= pc->k;
-			continue;
-
-		case USBPF_ALU|USBPF_AND|USBPF_K:
-			A &= pc->k;
-			continue;
-
-		case USBPF_ALU|USBPF_OR|USBPF_K:
-			A |= pc->k;
-			continue;
-
-		case USBPF_ALU|USBPF_LSH|USBPF_K:
-			A <<= pc->k;
-			continue;
-
-		case USBPF_ALU|USBPF_RSH|USBPF_K:
-			A >>= pc->k;
-			continue;
-
-		case USBPF_ALU|USBPF_NEG:
-			A = -A;
-			continue;
-
-		case USBPF_MISC|USBPF_TAX:
-			X = A;
-			continue;
-
-		case USBPF_MISC|USBPF_TXA:
-			A = X;
-			continue;
-		}
-	}
-}
-
-static void
-usbpf_free(struct usbpf_d *ud)
-{
-
-	switch (ud->ud_bufmode) {
-	case USBPF_BUFMODE_BUFFER:
-		return (usbpf_buffer_free(ud));
-	default:
-		panic("usbpf_buf_free");
-	}
-}
-
-/*
- * Notify the buffer model that a buffer has moved into the hold position.
- */
-static void
-usbpf_bufheld(struct usbpf_d *ud)
-{
-
-	USBPFD_LOCK_ASSERT(ud);
-}
-
-/*
- * Free buffers currently in use by a descriptor.
- * Called on close.
- */
-static void
-usbpf_freed(struct usbpf_d *ud)
-{
-
-	/*
-	 * We don't need to lock out interrupts since this descriptor has
-	 * been detached from its interface and it yet hasn't been marked
-	 * free.
-	 */
-	usbpf_free(ud);
-	if (ud->ud_rfilter != NULL)
-		free((caddr_t)ud->ud_rfilter, M_USBPF);
-	if (ud->ud_wfilter != NULL)
-		free((caddr_t)ud->ud_wfilter, M_USBPF);
-	mtx_destroy(&ud->ud_mtx);
-}
-
-/*
- * Close the descriptor by detaching it from its interface,
- * deallocating its buffers, and marking it free.
- */
-static void
-usbpf_dtor(void *data)
-{
-	struct usbpf_d *ud = data;
-
-	USBPFD_LOCK(ud);
-	if (ud->ud_state == USBPF_WAITING)
-		callout_stop(&ud->ud_callout);
-	ud->ud_state = USBPF_IDLE;
-	USBPFD_UNLOCK(ud);
-	funsetown(&ud->ud_sigio);
-	mtx_lock(&usbpf_mtx);
-	if (ud->ud_bif)
-		usbpf_detachd(ud);
-	mtx_unlock(&usbpf_mtx);
-	selwakeuppri(&ud->ud_sel, PRIUSB);
-	knlist_destroy(&ud->ud_sel.si_note);
-	callout_drain(&ud->ud_callout);
-	usbpf_freed(ud);
-	free(ud, M_USBPF);
-}
-
-/*
- * Open device.  Returns ENXIO for illegal minor device number,
- * EBUSY if file is open by another process.
- */
-/* ARGSUSED */
-static	int
-usbpf_open(struct cdev *dev, int flags, int fmt, struct thread *td)
-{
-	struct usbpf_d *ud;
-	int error;
-
-	ud = malloc(sizeof(*ud), M_USBPF, M_WAITOK | M_ZERO);
-	error = devfs_set_cdevpriv(ud, usbpf_dtor);
-	if (error != 0) {
-		free(ud, M_USBPF);
-		return (error);
-	}
-
-	usbpf_buffer_init(ud);
-	ud->ud_bufmode = USBPF_BUFMODE_BUFFER;
-	ud->ud_sig = SIGIO;
-	ud->ud_direction = USBPF_D_INOUT;
-	ud->ud_pid = td->td_proc->p_pid;
-	mtx_init(&ud->ud_mtx, devtoname(dev), "usbpf cdev lock", MTX_DEF);
-	callout_init_mtx(&ud->ud_callout, &ud->ud_mtx, 0);
-	knlist_init_mtx(&ud->ud_sel.si_note, &ud->ud_mtx);
-
-	return (0);
-}
-
-static int
-usbpf_uiomove(struct usbpf_d *ud, caddr_t buf, u_int len, struct uio *uio)
-{
-
-	if (ud->ud_bufmode != USBPF_BUFMODE_BUFFER)
-		return (EOPNOTSUPP);
-	return (usbpf_buffer_uiomove(ud, buf, len, uio));
-}
-
-/*
- *  usbpf_read - read next chunk of packets from buffers
- */
-static	int
-usbpf_read(struct cdev *dev, struct uio *uio, int ioflag)
-{
-	struct usbpf_d *ud;
-	int error;
-	int non_block;
-	int timed_out;
-
-	error = devfs_get_cdevpriv((void **)&ud);
-	if (error != 0)
-		return (error);
-
-	/*
-	 * Restrict application to use a buffer the same size as
-	 * as kernel buffers.
-	 */
-	if (uio->uio_resid != ud->ud_bufsize)
-		return (EINVAL);
-
-	non_block = ((ioflag & O_NONBLOCK) != 0);
-
-	USBPFD_LOCK(ud);
-	ud->ud_pid = curthread->td_proc->p_pid;
-	if (ud->ud_bufmode != USBPF_BUFMODE_BUFFER) {
-		USBPFD_UNLOCK(ud);
-		return (EOPNOTSUPP);
-	}
-	if (ud->ud_state == USBPF_WAITING)
-		callout_stop(&ud->ud_callout);
-	timed_out = (ud->ud_state == USBPF_TIMED_OUT);
-	ud->ud_state = USBPF_IDLE;
-	/*
-	 * If the hold buffer is empty, then do a timed sleep, which
-	 * ends when the timeout expires or when enough packets
-	 * have arrived to fill the store buffer.
-	 */
-	while (ud->ud_hbuf == NULL) {
-		if (ud->ud_slen != 0) {
-			/*
-			 * A packet(s) either arrived since the previous
-			 * read or arrived while we were asleep.
-			 */
-			if (ud->ud_immediate || non_block || timed_out) {
-				/*
-				 * Rotate the buffers and return what's here
-				 * if we are in immediate mode, non-blocking
-				 * flag is set, or this descriptor timed out.
-				 */
-				USBPF_ROTATE_BUFFERS(ud);
-				break;
-			}
-		}
-
-		/*
-		 * No data is available, check to see if the usbpf device
-		 * is still pointed at a real interface.  If not, return
-		 * ENXIO so that the userland process knows to rebind
-		 * it before using it again.
-		 */
-		if (ud->ud_bif == NULL) {
-			USBPFD_UNLOCK(ud);
-			return (ENXIO);
-		}
-
-		if (non_block) {
-			USBPFD_UNLOCK(ud);
-			return (EWOULDBLOCK);
-		}
-		error = msleep(ud, &ud->ud_mtx, PRIUSB|PCATCH,
-		    "uff", ud->ud_rtout);
-		if (error == EINTR || error == ERESTART) {
-			USBPFD_UNLOCK(ud);
-			return (error);
-		}
-		if (error == EWOULDBLOCK) {
-			/*
-			 * On a timeout, return what's in the buffer,
-			 * which may be nothing.  If there is something
-			 * in the store buffer, we can rotate the buffers.
-			 */
-			if (ud->ud_hbuf)
-				/*
-				 * We filled up the buffer in between
-				 * getting the timeout and arriving
-				 * here, so we don't need to rotate.
-				 */
-				break;
-
-			if (ud->ud_slen == 0) {
-				USBPFD_UNLOCK(ud);
-				return (0);
-			}
-			USBPF_ROTATE_BUFFERS(ud);
-			break;
-		}
-	}
-	/*
-	 * At this point, we know we have something in the hold slot.
-	 */
-	USBPFD_UNLOCK(ud);
-
-	/*
-	 * Move data from hold buffer into user space.
-	 * We know the entire buffer is transferred since
-	 * we checked above that the read buffer is usbpf_bufsize bytes.
-	 *
-	 * XXXRW: More synchronization needed here: what if a second thread
-	 * issues a read on the same fd at the same time?  Don't want this
-	 * getting invalidated.
-	 */
-	error = usbpf_uiomove(ud, ud->ud_hbuf, ud->ud_hlen, uio);
-
-	USBPFD_LOCK(ud);
-	ud->ud_fbuf = ud->ud_hbuf;
-	ud->ud_hbuf = NULL;
-	ud->ud_hlen = 0;
-	usbpf_buf_reclaimed(ud);
-	USBPFD_UNLOCK(ud);
-
-	return (error);
-}
-
-static int
-usbpf_write(struct cdev *dev, struct uio *uio, int ioflag)
-{
-
-	/* NOT IMPLEMENTED */
-	return (ENOSYS);
-}
-
-static int
-usbpf_ioctl_sblen(struct usbpf_d *ud, u_int *i)
-{
-
-	if (ud->ud_bufmode != USBPF_BUFMODE_BUFFER)
-		return (EOPNOTSUPP);
-	return (usbpf_buffer_ioctl_sblen(ud, i));
-}
-
-/*
- * Reset a descriptor by flushing its packet buffer and clearing the receive
- * and drop counts.  This is doable for kernel-only buffers, but with
- * zero-copy buffers, we can't write to (or rotate) buffers that are
- * currently owned by userspace.  It would be nice if we could encapsulate
- * this logic in the buffer code rather than here.
- */
-static void
-usbpf_reset_d(struct usbpf_d *ud)
-{

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list