summaryrefslogtreecommitdiffstats
path: root/drivers/usb/ibmcam.h
blob: 6eb1d99ba6eb990eec0516c6d9b01db6b7a43eb6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
/*
 * Header file for USB IBM C-It Video Camera driver.
 *
 * Supports IBM C-It Video Camera.
 *
 * This driver is based on earlier work of:
 *
 * (C) Copyright 1999 Johannes Erdfelt
 * (C) Copyright 1999 Randy Dunlap
 */

#ifndef __LINUX_IBMCAM_H
#define __LINUX_IBMCAM_H

#include <linux/list.h>

#define USES_IBMCAM_PUTPIXEL    0       /* 0=Fast/oops 1=Slow/secure */

/* Video Size 384 x 288 x 3 bytes for RGB */
/* 384 because xawtv tries to grab 384 even though we tell it 352 is our max */
#define V4L_FRAME_WIDTH         384
#define V4L_FRAME_WIDTH_USED	352
#define V4L_FRAME_HEIGHT        288
#define V4L_BYTES_PER_PIXEL     3
#define MAX_FRAME_SIZE          (V4L_FRAME_WIDTH * V4L_FRAME_HEIGHT * V4L_BYTES_PER_PIXEL)

/* Camera capabilities (maximum) */
#define CAMERA_IMAGE_WIDTH      352
#define CAMERA_IMAGE_HEIGHT     288
#define CAMERA_IMAGE_LINE_SZ    ((CAMERA_IMAGE_WIDTH * 3) / 2) /* Bytes */
#define CAMERA_URB_FRAMES       32
#define CAMERA_MAX_ISO_PACKET   1023 /* 1022 actually sent by camera */

#define IBMCAM_NUMFRAMES	2
#define IBMCAM_NUMSBUF		2

#define FRAMES_PER_DESC		(CAMERA_URB_FRAMES)
#define FRAME_SIZE_PER_DESC	(CAMERA_MAX_ISO_PACKET)

/* This macro restricts an int variable to an inclusive range */
#define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); }

/*
 * This macro performs bounds checking - use it when working with
 * new formats, or else you may get oopses all over the place.
 * If pixel falls out of bounds then it gets shoved back (as close
 * to place of offence as possible) and is painted bright red.
 */
#define IBMCAM_PUTPIXEL(fr, ix, iy, vr, vg, vb) { \
	register unsigned char *pf; \
	int limiter = 0, mx, my; \
	mx = ix; \
	my = iy; \
	if (mx < 0) { \
		mx=0; \
		limiter++; \
	} else if (mx >= 352) { \
		mx=351; \
		limiter++; \
	} \
	if (my < 0) { \
		my = 0; \
		limiter++; \
	} else if (my >= V4L_FRAME_HEIGHT) { \
		my = V4L_FRAME_HEIGHT - 1; \
		limiter++; \
	} \
	pf = (fr)->data + V4L_BYTES_PER_PIXEL*((iy)*352 + (ix)); \
	if (limiter) { \
		*pf++ = 0; \
		*pf++ = 0; \
		*pf++ = 0xFF; \
	} else { \
		*pf++ = (vb); \
		*pf++ = (vg); \
		*pf++ = (vr); \
	} \
}

/*
 * We use macros to do YUV -> RGB conversion because this is
 * very important for speed and totally unimportant for size.
 *
 * YUV -> RGB Conversion
 * ---------------------
 *
 * B = 1.164*(Y-16)		    + 2.018*(V-128)
 * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128)
 * R = 1.164*(Y-16) + 1.596*(U-128)
 *
 * If you fancy integer arithmetics (as you should), hear this:
 *
 * 65536*B = 76284*(Y-16)		  + 132252*(V-128)
 * 65536*G = 76284*(Y-16) -  53281*(U-128) -  25625*(V-128)
 * 65536*R = 76284*(Y-16) + 104595*(U-128)
 *
 * Make sure the output values are within [0..255] range.
 */
#define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x)))
#define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \
    int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \
    mm_y = (my) - 16;  \
    mm_u = (mu) - 128; \
    mm_v = (mv) - 128; \
    mm_yc= mm_y * 76284; \
    mm_b = (mm_yc		+ 132252*mm_v	) >> 16; \
    mm_g = (mm_yc -  53281*mm_u -  25625*mm_v	) >> 16; \
    mm_r = (mm_yc + 104595*mm_u			) >> 16; \
    mb = LIMIT_RGB(mm_b); \
    mg = LIMIT_RGB(mm_g); \
    mr = LIMIT_RGB(mm_r); \
}

/* Debugging aid */
#define IBMCAM_SAY_AND_WAIT(what) { \
	wait_queue_head_t wq; \
	init_waitqueue_head(&wq); \
	printk(KERN_INFO "Say: %s\n", what); \
	interruptible_sleep_on_timeout (&wq, HZ*3); \
}

enum {
	STATE_SCANNING,		/* Scanning for header */
	STATE_LINES,		/* Parsing lines */
};

enum {
	FRAME_UNUSED,		/* Unused (no MCAPTURE) */
	FRAME_READY,		/* Ready to start grabbing */
	FRAME_GRABBING,		/* In the process of being grabbed into */
	FRAME_DONE,		/* Finished grabbing, but not been synced yet */
	FRAME_ERROR,		/* Something bad happened while processing */
};

struct usb_device;

struct ibmcam_sbuf {
	char *data;
	urb_t *urb;
};

struct ibmcam_frame {
	char *data;		/* Frame buffer */
	int order_uv;		/* True=UV False=VU */
	unsigned char hdr_sig;	/* "00 FF 00 ??" where 'hdr_sig' is '??' */

	int width;		/* Width application is expecting */
	int height;		/* Height */

	int frmwidth;		/* Width the frame actually is */
	int frmheight;		/* Height */

	volatile int grabstate;	/* State of grabbing */
	int scanstate;		/* State of scanning */

	int curline;		/* Line of frame we're working on */

	long scanlength;	/* uncompressed, raw data length of frame */
	long bytes_read;	/* amount of scanlength that has been read from *data */

	wait_queue_head_t wq;	/* Processes waiting */
};

struct usb_ibmcam {
	struct video_device vdev;

	/* Device structure */
	struct usb_device *dev;

	unsigned char iface;

	struct semaphore lock;
	int user;		/* user count for exclusive use */

	int initialized;	/* Had we already sent init sequence? */
	int streaming;		/* Are we streaming Isochronous? */
	int grabbing;		/* Are we grabbing? */

	int compress;		/* Should the next frame be compressed? */

	char *fbuf;		/* Videodev buffer area */
	int fbuf_size;		/* Videodev buffer size */

	int curframe;
	struct ibmcam_frame frame[IBMCAM_NUMFRAMES];	/* Double buffering */

	int cursbuf;		/* Current receiving sbuf */
	struct ibmcam_sbuf sbuf[IBMCAM_NUMSBUF];	/* Double buffering */
	volatile int remove_pending;	/* If set then about to exit */
	wait_queue_head_t remove_ok;	/* Wait here until removal is safe */

        /*
	 * Scratch space from the Isochronous pipe.
	 * Scratch buffer should contain at least one pair of lines
	 * (CAMERA_IMAGE_LINE_SZ). We set it to two pairs here.
	 * This will be approximately 2 KB. HOWEVER in reality this
	 * buffer must be as large as hundred of KB because otherwise
	 * you'll get lots of overflows because V4L client may request
	 * frames not as uniformly as USB sources them.
	 */
	unsigned char *scratch;
	int scratchlen;

	struct video_picture vpic, vpic_old;	/* Picture settings */
	struct video_capability vcap;		/* Video capabilities */
	struct video_channel vchan;	/* May be used for tuner support */
	unsigned char video_endp;	/* 0x82 for IBM camera */
        int has_hdr;
        int frame_num;
	int iso_packet_len;		/* Videomode-dependent, saves bus bandwidth */

	/* Statistics that can be overlayed on screen */
        unsigned long urb_count;        /* How many URBs we received so far */
        unsigned long urb_length;       /* Length of last URB */
        unsigned long data_count;       /* How many bytes we received */
        unsigned long header_count;     /* How many frame headers we found */
	unsigned long scratch_ovf_count;/* How many times we overflowed scratch */
	unsigned long iso_skip_count;	/* How many empty ISO packets received */
	unsigned long iso_err_count;	/* How many bad ISO packets received */
};

#endif /* __LINUX_IBMCAM_H */