aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorAntonio Ospite <ospite@studenti.unina.it>2011-04-07 11:45:52 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-05-20 08:27:27 -0400
commit6612155a1dce344fb609c9487a879c693150ebb1 (patch)
tree04edb337ff57789944694c2db93b556a8025a335 /drivers/media
parent8bb36c2139f7bcea32a78472272f1d0de3b00f7b (diff)
[media] gspca - kinect: New subdriver for Microsoft Kinect
The Kinect sensor is a device used by Microsoft for its Kinect project, which is a system for controller-less Human-Computer interaction targeted for Xbox 360. In the Kinect device, RGBD data is captured from two distinct sensors: a regular RGB sensor and a monochrome sensor which, with the aid of a IR structured light, captures what is finally exposed as a depth map; so what we have is basically a Structured-light 3D scanner. The Kinect gspca subdriver just supports the video stream for now, exposing the output from the RGB sensor or the unprocessed output from the monochrome sensor; it does not deal with the processed depth stream yet, but it allows using the sensor as a Webcam or as an IR camera (an external source of IR light might be needed for this use). The low level implementation is based on code from the OpenKinect project (http://openkinect.org). Signed-off-by: Antonio Ospite <ospite@studenti.unina.it> Signed-off-by: Jean-François Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/gspca/Kconfig9
-rw-r--r--drivers/media/video/gspca/Makefile2
-rw-r--r--drivers/media/video/gspca/kinect.c427
3 files changed, 438 insertions, 0 deletions
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig
index eb04e8b59989..34ae2c299799 100644
--- a/drivers/media/video/gspca/Kconfig
+++ b/drivers/media/video/gspca/Kconfig
@@ -77,6 +77,15 @@ config USB_GSPCA_JEILINJ
77 To compile this driver as a module, choose M here: the 77 To compile this driver as a module, choose M here: the
78 module will be called gspca_jeilinj. 78 module will be called gspca_jeilinj.
79 79
80config USB_GSPCA_KINECT
81 tristate "Kinect sensor device USB Camera Driver"
82 depends on VIDEO_V4L2 && USB_GSPCA
83 help
84 Say Y here if you want support for the Microsoft Kinect sensor device.
85
86 To compile this driver as a module, choose M here: the
87 module will be called gspca_kinect.
88
80config USB_GSPCA_KONICA 89config USB_GSPCA_KONICA
81 tristate "Konica USB Camera V4L2 driver" 90 tristate "Konica USB Camera V4L2 driver"
82 depends on VIDEO_V4L2 && USB_GSPCA 91 depends on VIDEO_V4L2 && USB_GSPCA
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile
index 855fbc8c9c47..802fbe1bff4a 100644
--- a/drivers/media/video/gspca/Makefile
+++ b/drivers/media/video/gspca/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_USB_GSPCA_CPIA1) += gspca_cpia1.o
5obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o 5obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o
6obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o 6obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o
7obj-$(CONFIG_USB_GSPCA_JEILINJ) += gspca_jeilinj.o 7obj-$(CONFIG_USB_GSPCA_JEILINJ) += gspca_jeilinj.o
8obj-$(CONFIG_USB_GSPCA_KINECT) += gspca_kinect.o
8obj-$(CONFIG_USB_GSPCA_KONICA) += gspca_konica.o 9obj-$(CONFIG_USB_GSPCA_KONICA) += gspca_konica.o
9obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o 10obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o
10obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o 11obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o
@@ -46,6 +47,7 @@ gspca_cpia1-objs := cpia1.o
46gspca_etoms-objs := etoms.o 47gspca_etoms-objs := etoms.o
47gspca_finepix-objs := finepix.o 48gspca_finepix-objs := finepix.o
48gspca_jeilinj-objs := jeilinj.o 49gspca_jeilinj-objs := jeilinj.o
50gspca_kinect-objs := kinect.o
49gspca_konica-objs := konica.o 51gspca_konica-objs := konica.o
50gspca_mars-objs := mars.o 52gspca_mars-objs := mars.o
51gspca_mr97310a-objs := mr97310a.o 53gspca_mr97310a-objs := mr97310a.o
diff --git a/drivers/media/video/gspca/kinect.c b/drivers/media/video/gspca/kinect.c
new file mode 100644
index 000000000000..f85e746665cc
--- /dev/null
+++ b/drivers/media/video/gspca/kinect.c
@@ -0,0 +1,427 @@
1/*
2 * kinect sensor device camera, gspca driver
3 *
4 * Copyright (C) 2011 Antonio Ospite <ospite@studenti.unina.it>
5 *
6 * Based on the OpenKinect project and libfreenect
7 * http://openkinect.org/wiki/Init_Analysis
8 *
9 * Special thanks to Steven Toth and kernellabs.com for sponsoring a Kinect
10 * sensor device which I tested the driver on.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27#define MODULE_NAME "kinect"
28
29#include "gspca.h"
30
31#define CTRL_TIMEOUT 500
32
33MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
34MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver");
35MODULE_LICENSE("GPL");
36
37#ifdef DEBUG
38int gspca_debug = D_ERR | D_PROBE | D_CONF | D_STREAM | D_FRAM | D_PACK |
39 D_USBI | D_USBO | D_V4L2;
40#endif
41
42struct pkt_hdr {
43 uint8_t magic[2];
44 uint8_t pad;
45 uint8_t flag;
46 uint8_t unk1;
47 uint8_t seq;
48 uint8_t unk2;
49 uint8_t unk3;
50 uint32_t timestamp;
51};
52
53struct cam_hdr {
54 uint8_t magic[2];
55 uint16_t len;
56 uint16_t cmd;
57 uint16_t tag;
58};
59
60/* specific webcam descriptor */
61struct sd {
62 struct gspca_dev gspca_dev; /* !! must be the first item */
63 uint16_t cam_tag; /* a sequence number for packets */
64 uint8_t stream_flag; /* to identify different steram types */
65};
66
67/* V4L2 controls supported by the driver */
68/* controls prototypes here */
69
70static const struct ctrl sd_ctrls[] = {
71};
72
73#define MODE_640x480 0x0001
74#define MODE_640x488 0x0002
75#define MODE_1280x1024 0x0004
76
77#define FORMAT_BAYER 0x0010
78#define FORMAT_UYVY 0x0020
79#define FORMAT_Y10B 0x0040
80
81#define FPS_HIGH 0x0100
82
83static const struct v4l2_pix_format video_camera_mode[] = {
84 {640, 480, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
85 .bytesperline = 640,
86 .sizeimage = 640 * 480,
87 .colorspace = V4L2_COLORSPACE_SRGB,
88 .priv = MODE_640x480 | FORMAT_BAYER | FPS_HIGH},
89 {640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE,
90 .bytesperline = 640 * 2,
91 .sizeimage = 640 * 480 * 2,
92 .colorspace = V4L2_COLORSPACE_SRGB,
93 .priv = MODE_640x480 | FORMAT_UYVY},
94 {1280, 1024, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
95 .bytesperline = 1280,
96 .sizeimage = 1280 * 1024,
97 .colorspace = V4L2_COLORSPACE_SRGB,
98 .priv = MODE_1280x1024 | FORMAT_BAYER},
99 {640, 488, V4L2_PIX_FMT_Y10BPACK, V4L2_FIELD_NONE,
100 .bytesperline = 640 * 10 / 8,
101 .sizeimage = 640 * 488 * 10 / 8,
102 .colorspace = V4L2_COLORSPACE_SRGB,
103 .priv = MODE_640x488 | FORMAT_Y10B | FPS_HIGH},
104 {1280, 1024, V4L2_PIX_FMT_Y10BPACK, V4L2_FIELD_NONE,
105 .bytesperline = 1280 * 10 / 8,
106 .sizeimage = 1280 * 1024 * 10 / 8,
107 .colorspace = V4L2_COLORSPACE_SRGB,
108 .priv = MODE_1280x1024 | FORMAT_Y10B},
109};
110
111static int kinect_write(struct usb_device *udev, uint8_t *data,
112 uint16_t wLength)
113{
114 return usb_control_msg(udev,
115 usb_sndctrlpipe(udev, 0),
116 0x00,
117 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
118 0, 0, data, wLength, CTRL_TIMEOUT);
119}
120
121static int kinect_read(struct usb_device *udev, uint8_t *data, uint16_t wLength)
122{
123 return usb_control_msg(udev,
124 usb_rcvctrlpipe(udev, 0),
125 0x00,
126 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
127 0, 0, data, wLength, CTRL_TIMEOUT);
128}
129
130static int send_cmd(struct gspca_dev *gspca_dev, uint16_t cmd, void *cmdbuf,
131 unsigned int cmd_len, void *replybuf, unsigned int reply_len)
132{
133 struct sd *sd = (struct sd *) gspca_dev;
134 struct usb_device *udev = gspca_dev->dev;
135 int res, actual_len;
136 uint8_t obuf[0x400];
137 uint8_t ibuf[0x200];
138 struct cam_hdr *chdr = (void *)obuf;
139 struct cam_hdr *rhdr = (void *)ibuf;
140
141 if (cmd_len & 1 || cmd_len > (0x400 - sizeof(*chdr))) {
142 err("send_cmd: Invalid command length (0x%x)", cmd_len);
143 return -1;
144 }
145
146 chdr->magic[0] = 0x47;
147 chdr->magic[1] = 0x4d;
148 chdr->cmd = cpu_to_le16(cmd);
149 chdr->tag = cpu_to_le16(sd->cam_tag);
150 chdr->len = cpu_to_le16(cmd_len / 2);
151
152 memcpy(obuf+sizeof(*chdr), cmdbuf, cmd_len);
153
154 res = kinect_write(udev, obuf, cmd_len + sizeof(*chdr));
155 PDEBUG(D_USBO, "Control cmd=%04x tag=%04x len=%04x: %d", cmd,
156 sd->cam_tag, cmd_len, res);
157 if (res < 0) {
158 err("send_cmd: Output control transfer failed (%d)", res);
159 return res;
160 }
161
162 do {
163 actual_len = kinect_read(udev, ibuf, 0x200);
164 } while (actual_len == 0);
165 PDEBUG(D_USBO, "Control reply: %d", res);
166 if (actual_len < sizeof(*rhdr)) {
167 err("send_cmd: Input control transfer failed (%d)", res);
168 return res;
169 }
170 actual_len -= sizeof(*rhdr);
171
172 if (rhdr->magic[0] != 0x52 || rhdr->magic[1] != 0x42) {
173 err("send_cmd: Bad magic %02x %02x", rhdr->magic[0],
174 rhdr->magic[1]);
175 return -1;
176 }
177 if (rhdr->cmd != chdr->cmd) {
178 err("send_cmd: Bad cmd %02x != %02x", rhdr->cmd, chdr->cmd);
179 return -1;
180 }
181 if (rhdr->tag != chdr->tag) {
182 err("send_cmd: Bad tag %04x != %04x", rhdr->tag, chdr->tag);
183 return -1;
184 }
185 if (cpu_to_le16(rhdr->len) != (actual_len/2)) {
186 err("send_cmd: Bad len %04x != %04x",
187 cpu_to_le16(rhdr->len), (int)(actual_len/2));
188 return -1;
189 }
190
191 if (actual_len > reply_len) {
192 warn("send_cmd: Data buffer is %d bytes long, but got %d bytes",
193 reply_len, actual_len);
194 memcpy(replybuf, ibuf+sizeof(*rhdr), reply_len);
195 } else {
196 memcpy(replybuf, ibuf+sizeof(*rhdr), actual_len);
197 }
198
199 sd->cam_tag++;
200
201 return actual_len;
202}
203
204static int write_register(struct gspca_dev *gspca_dev, uint16_t reg,
205 uint16_t data)
206{
207 uint16_t reply[2];
208 uint16_t cmd[2];
209 int res;
210
211 cmd[0] = cpu_to_le16(reg);
212 cmd[1] = cpu_to_le16(data);
213
214 PDEBUG(D_USBO, "Write Reg 0x%04x <= 0x%02x", reg, data);
215 res = send_cmd(gspca_dev, 0x03, cmd, 4, reply, 4);
216 if (res < 0)
217 return res;
218 if (res != 2) {
219 warn("send_cmd returned %d [%04x %04x], 0000 expected",
220 res, reply[0], reply[1]);
221 }
222 return 0;
223}
224
225/* this function is called at probe time */
226static int sd_config(struct gspca_dev *gspca_dev,
227 const struct usb_device_id *id)
228{
229 struct sd *sd = (struct sd *) gspca_dev;
230 struct cam *cam;
231
232 sd->cam_tag = 0;
233
234 /* Only color camera is supported for now,
235 * which has stream flag = 0x80 */
236 sd->stream_flag = 0x80;
237
238 cam = &gspca_dev->cam;
239
240 cam->cam_mode = video_camera_mode;
241 cam->nmodes = ARRAY_SIZE(video_camera_mode);
242
243#if 0
244 /* Setting those values is not needed for color camera */
245 cam->npkt = 15;
246 gspca_dev->pkt_size = 960 * 2;
247#endif
248
249 return 0;
250}
251
252/* this function is called at probe and resume time */
253static int sd_init(struct gspca_dev *gspca_dev)
254{
255 PDEBUG(D_PROBE, "Kinect Camera device.");
256
257 return 0;
258}
259
260static int sd_start(struct gspca_dev *gspca_dev)
261{
262 int mode;
263 uint8_t fmt_reg, fmt_val;
264 uint8_t res_reg, res_val;
265 uint8_t fps_reg, fps_val;
266 uint8_t mode_val;
267
268 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
269
270 if (mode & FORMAT_Y10B) {
271 fmt_reg = 0x19;
272 res_reg = 0x1a;
273 fps_reg = 0x1b;
274 mode_val = 0x03;
275 } else {
276 fmt_reg = 0x0c;
277 res_reg = 0x0d;
278 fps_reg = 0x0e;
279 mode_val = 0x01;
280 }
281
282 /* format */
283 if (mode & FORMAT_UYVY)
284 fmt_val = 0x05;
285 else
286 fmt_val = 0x00;
287
288 if (mode & MODE_1280x1024)
289 res_val = 0x02;
290 else
291 res_val = 0x01;
292
293 if (mode & FPS_HIGH)
294 fps_val = 0x1e;
295 else
296 fps_val = 0x0f;
297
298
299 /* turn off IR-reset function */
300 write_register(gspca_dev, 0x105, 0x00);
301
302 /* Reset video stream */
303 write_register(gspca_dev, 0x05, 0x00);
304
305 /* Due to some ridiculous condition in the firmware, we have to start
306 * and stop the depth stream before the camera will hand us 1280x1024
307 * IR. This is a stupid workaround, but we've yet to find a better
308 * solution.
309 *
310 * Thanks to Drew Fisher for figuring this out.
311 */
312 if (mode & (FORMAT_Y10B | MODE_1280x1024)) {
313 write_register(gspca_dev, 0x13, 0x01);
314 write_register(gspca_dev, 0x14, 0x1e);
315 write_register(gspca_dev, 0x06, 0x02);
316 write_register(gspca_dev, 0x06, 0x00);
317 }
318
319 write_register(gspca_dev, fmt_reg, fmt_val);
320 write_register(gspca_dev, res_reg, res_val);
321 write_register(gspca_dev, fps_reg, fps_val);
322
323 /* Start video stream */
324 write_register(gspca_dev, 0x05, mode_val);
325
326 /* disable Hflip */
327 write_register(gspca_dev, 0x47, 0x00);
328
329 return 0;
330}
331
332static void sd_stopN(struct gspca_dev *gspca_dev)
333{
334 /* reset video stream */
335 write_register(gspca_dev, 0x05, 0x00);
336}
337
338static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *__data, int len)
339{
340 struct sd *sd = (struct sd *) gspca_dev;
341
342 struct pkt_hdr *hdr = (void *)__data;
343 uint8_t *data = __data + sizeof(*hdr);
344 int datalen = len - sizeof(*hdr);
345
346 uint8_t sof = sd->stream_flag | 1;
347 uint8_t mof = sd->stream_flag | 2;
348 uint8_t eof = sd->stream_flag | 5;
349
350 if (len < 12)
351 return;
352
353 if (hdr->magic[0] != 'R' || hdr->magic[1] != 'B') {
354 warn("[Stream %02x] Invalid magic %02x%02x", sd->stream_flag,
355 hdr->magic[0], hdr->magic[1]);
356 return;
357 }
358
359 if (hdr->flag == sof)
360 gspca_frame_add(gspca_dev, FIRST_PACKET, data, datalen);
361
362 else if (hdr->flag == mof)
363 gspca_frame_add(gspca_dev, INTER_PACKET, data, datalen);
364
365 else if (hdr->flag == eof)
366 gspca_frame_add(gspca_dev, LAST_PACKET, data, datalen);
367
368 else
369 warn("Packet type not recognized...");
370}
371
372/* sub-driver description */
373static const struct sd_desc sd_desc = {
374 .name = MODULE_NAME,
375 .ctrls = sd_ctrls,
376 .nctrls = ARRAY_SIZE(sd_ctrls),
377 .config = sd_config,
378 .init = sd_init,
379 .start = sd_start,
380 .stopN = sd_stopN,
381 .pkt_scan = sd_pkt_scan,
382 /*
383 .querymenu = sd_querymenu,
384 .get_streamparm = sd_get_streamparm,
385 .set_streamparm = sd_set_streamparm,
386 */
387};
388
389/* -- module initialisation -- */
390static const __devinitdata struct usb_device_id device_table[] = {
391 {USB_DEVICE(0x045e, 0x02ae)},
392 {}
393};
394
395MODULE_DEVICE_TABLE(usb, device_table);
396
397/* -- device connect -- */
398static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
399{
400 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
401 THIS_MODULE);
402}
403
404static struct usb_driver sd_driver = {
405 .name = MODULE_NAME,
406 .id_table = device_table,
407 .probe = sd_probe,
408 .disconnect = gspca_disconnect,
409#ifdef CONFIG_PM
410 .suspend = gspca_suspend,
411 .resume = gspca_resume,
412#endif
413};
414
415/* -- module insert / remove -- */
416static int __init sd_mod_init(void)
417{
418 return usb_register(&sd_driver);
419}
420
421static void __exit sd_mod_exit(void)
422{
423 usb_deregister(&sd_driver);
424}
425
426module_init(sd_mod_init);
427module_exit(sd_mod_exit);