linux/drivers/media/video/gspca/kinect.c
<<
>>
Prefs
   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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  28
  29#define MODULE_NAME "kinect"
  30
  31#include "gspca.h"
  32
  33#define CTRL_TIMEOUT 500
  34
  35MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
  36MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver");
  37MODULE_LICENSE("GPL");
  38
  39struct pkt_hdr {
  40        uint8_t magic[2];
  41        uint8_t pad;
  42        uint8_t flag;
  43        uint8_t unk1;
  44        uint8_t seq;
  45        uint8_t unk2;
  46        uint8_t unk3;
  47        uint32_t timestamp;
  48};
  49
  50struct cam_hdr {
  51        uint8_t magic[2];
  52        uint16_t len;
  53        uint16_t cmd;
  54        uint16_t tag;
  55};
  56
  57/* specific webcam descriptor */
  58struct sd {
  59        struct gspca_dev gspca_dev; /* !! must be the first item */
  60        uint16_t cam_tag;           /* a sequence number for packets */
  61        uint8_t stream_flag;        /* to identify different stream types */
  62        uint8_t obuf[0x400];        /* output buffer for control commands */
  63        uint8_t ibuf[0x200];        /* input buffer for control commands */
  64};
  65
  66/* V4L2 controls supported by the driver */
  67/* controls prototypes here */
  68
  69static const struct ctrl sd_ctrls[] = {
  70};
  71
  72#define MODE_640x480   0x0001
  73#define MODE_640x488   0x0002
  74#define MODE_1280x1024 0x0004
  75
  76#define FORMAT_BAYER   0x0010
  77#define FORMAT_UYVY    0x0020
  78#define FORMAT_Y10B    0x0040
  79
  80#define FPS_HIGH       0x0100
  81
  82static const struct v4l2_pix_format video_camera_mode[] = {
  83        {640, 480, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
  84         .bytesperline = 640,
  85         .sizeimage = 640 * 480,
  86         .colorspace = V4L2_COLORSPACE_SRGB,
  87         .priv = MODE_640x480 | FORMAT_BAYER | FPS_HIGH},
  88        {640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE,
  89         .bytesperline = 640 * 2,
  90         .sizeimage = 640 * 480 * 2,
  91         .colorspace = V4L2_COLORSPACE_SRGB,
  92         .priv = MODE_640x480 | FORMAT_UYVY},
  93        {1280, 1024, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
  94         .bytesperline = 1280,
  95         .sizeimage = 1280 * 1024,
  96         .colorspace = V4L2_COLORSPACE_SRGB,
  97         .priv = MODE_1280x1024 | FORMAT_BAYER},
  98        {640, 488, V4L2_PIX_FMT_Y10BPACK, V4L2_FIELD_NONE,
  99         .bytesperline = 640 * 10 / 8,
 100         .sizeimage =  640 * 488 * 10 / 8,
 101         .colorspace = V4L2_COLORSPACE_SRGB,
 102         .priv = MODE_640x488 | FORMAT_Y10B | FPS_HIGH},
 103        {1280, 1024, V4L2_PIX_FMT_Y10BPACK, V4L2_FIELD_NONE,
 104         .bytesperline = 1280 * 10 / 8,
 105         .sizeimage =  1280 * 1024 * 10 / 8,
 106         .colorspace = V4L2_COLORSPACE_SRGB,
 107         .priv = MODE_1280x1024 | FORMAT_Y10B},
 108};
 109
 110static int kinect_write(struct usb_device *udev, uint8_t *data,
 111                        uint16_t wLength)
 112{
 113        return usb_control_msg(udev,
 114                              usb_sndctrlpipe(udev, 0),
 115                              0x00,
 116                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 117                              0, 0, data, wLength, CTRL_TIMEOUT);
 118}
 119
 120static int kinect_read(struct usb_device *udev, uint8_t *data, uint16_t wLength)
 121{
 122        return usb_control_msg(udev,
 123                              usb_rcvctrlpipe(udev, 0),
 124                              0x00,
 125                              USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 126                              0, 0, data, wLength, CTRL_TIMEOUT);
 127}
 128
 129static int send_cmd(struct gspca_dev *gspca_dev, uint16_t cmd, void *cmdbuf,
 130                unsigned int cmd_len, void *replybuf, unsigned int reply_len)
 131{
 132        struct sd *sd = (struct sd *) gspca_dev;
 133        struct usb_device *udev = gspca_dev->dev;
 134        int res, actual_len;
 135        uint8_t *obuf = sd->obuf;
 136        uint8_t *ibuf = sd->ibuf;
 137        struct cam_hdr *chdr = (void *)obuf;
 138        struct cam_hdr *rhdr = (void *)ibuf;
 139
 140        if (cmd_len & 1 || cmd_len > (0x400 - sizeof(*chdr))) {
 141                pr_err("send_cmd: Invalid command length (0x%x)\n", cmd_len);
 142                return -1;
 143        }
 144
 145        chdr->magic[0] = 0x47;
 146        chdr->magic[1] = 0x4d;
 147        chdr->cmd = cpu_to_le16(cmd);
 148        chdr->tag = cpu_to_le16(sd->cam_tag);
 149        chdr->len = cpu_to_le16(cmd_len / 2);
 150
 151        memcpy(obuf+sizeof(*chdr), cmdbuf, cmd_len);
 152
 153        res = kinect_write(udev, obuf, cmd_len + sizeof(*chdr));
 154        PDEBUG(D_USBO, "Control cmd=%04x tag=%04x len=%04x: %d", cmd,
 155                sd->cam_tag, cmd_len, res);
 156        if (res < 0) {
 157                pr_err("send_cmd: Output control transfer failed (%d)\n", res);
 158                return res;
 159        }
 160
 161        do {
 162                actual_len = kinect_read(udev, ibuf, 0x200);
 163        } while (actual_len == 0);
 164        PDEBUG(D_USBO, "Control reply: %d", res);
 165        if (actual_len < sizeof(*rhdr)) {
 166                pr_err("send_cmd: Input control transfer failed (%d)\n", res);
 167                return res;
 168        }
 169        actual_len -= sizeof(*rhdr);
 170
 171        if (rhdr->magic[0] != 0x52 || rhdr->magic[1] != 0x42) {
 172                pr_err("send_cmd: Bad magic %02x %02x\n",
 173                       rhdr->magic[0], rhdr->magic[1]);
 174                return -1;
 175        }
 176        if (rhdr->cmd != chdr->cmd) {
 177                pr_err("send_cmd: Bad cmd %02x != %02x\n",
 178                       rhdr->cmd, chdr->cmd);
 179                return -1;
 180        }
 181        if (rhdr->tag != chdr->tag) {
 182                pr_err("send_cmd: Bad tag %04x != %04x\n",
 183                       rhdr->tag, chdr->tag);
 184                return -1;
 185        }
 186        if (cpu_to_le16(rhdr->len) != (actual_len/2)) {
 187                pr_err("send_cmd: Bad len %04x != %04x\n",
 188                       cpu_to_le16(rhdr->len), (int)(actual_len/2));
 189                return -1;
 190        }
 191
 192        if (actual_len > reply_len) {
 193                pr_warn("send_cmd: Data buffer is %d bytes long, but got %d bytes\n",
 194                        reply_len, actual_len);
 195                memcpy(replybuf, ibuf+sizeof(*rhdr), reply_len);
 196        } else {
 197                memcpy(replybuf, ibuf+sizeof(*rhdr), actual_len);
 198        }
 199
 200        sd->cam_tag++;
 201
 202        return actual_len;
 203}
 204
 205static int write_register(struct gspca_dev *gspca_dev, uint16_t reg,
 206                        uint16_t data)
 207{
 208        uint16_t reply[2];
 209        uint16_t cmd[2];
 210        int res;
 211
 212        cmd[0] = cpu_to_le16(reg);
 213        cmd[1] = cpu_to_le16(data);
 214
 215        PDEBUG(D_USBO, "Write Reg 0x%04x <= 0x%02x", reg, data);
 216        res = send_cmd(gspca_dev, 0x03, cmd, 4, reply, 4);
 217        if (res < 0)
 218                return res;
 219        if (res != 2) {
 220                pr_warn("send_cmd returned %d [%04x %04x], 0000 expected\n",
 221                        res, reply[0], reply[1]);
 222        }
 223        return 0;
 224}
 225
 226/* this function is called at probe time */
 227static int sd_config(struct gspca_dev *gspca_dev,
 228                     const struct usb_device_id *id)
 229{
 230        struct sd *sd = (struct sd *) gspca_dev;
 231        struct cam *cam;
 232
 233        sd->cam_tag = 0;
 234
 235        /* Only video stream is supported for now,
 236         * which has stream flag = 0x80 */
 237        sd->stream_flag = 0x80;
 238
 239        cam = &gspca_dev->cam;
 240
 241        cam->cam_mode = video_camera_mode;
 242        cam->nmodes = ARRAY_SIZE(video_camera_mode);
 243
 244#if 0
 245        /* Setting those values is not needed for video stream */
 246        cam->npkt = 15;
 247        gspca_dev->pkt_size = 960 * 2;
 248#endif
 249
 250        return 0;
 251}
 252
 253/* this function is called at probe and resume time */
 254static int sd_init(struct gspca_dev *gspca_dev)
 255{
 256        PDEBUG(D_PROBE, "Kinect Camera device.");
 257
 258        return 0;
 259}
 260
 261static int sd_start(struct gspca_dev *gspca_dev)
 262{
 263        int mode;
 264        uint8_t fmt_reg, fmt_val;
 265        uint8_t res_reg, res_val;
 266        uint8_t fps_reg, fps_val;
 267        uint8_t mode_val;
 268
 269        mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
 270
 271        if (mode & FORMAT_Y10B) {
 272                fmt_reg = 0x19;
 273                res_reg = 0x1a;
 274                fps_reg = 0x1b;
 275                mode_val = 0x03;
 276        } else {
 277                fmt_reg = 0x0c;
 278                res_reg = 0x0d;
 279                fps_reg = 0x0e;
 280                mode_val = 0x01;
 281        }
 282
 283        /* format */
 284        if (mode & FORMAT_UYVY)
 285                fmt_val = 0x05;
 286        else
 287                fmt_val = 0x00;
 288
 289        if (mode & MODE_1280x1024)
 290                res_val = 0x02;
 291        else
 292                res_val = 0x01;
 293
 294        if (mode & FPS_HIGH)
 295                fps_val = 0x1e;
 296        else
 297                fps_val = 0x0f;
 298
 299
 300        /* turn off IR-reset function */
 301        write_register(gspca_dev, 0x105, 0x00);
 302
 303        /* Reset video stream */
 304        write_register(gspca_dev, 0x05, 0x00);
 305
 306        /* Due to some ridiculous condition in the firmware, we have to start
 307         * and stop the depth stream before the camera will hand us 1280x1024
 308         * IR.  This is a stupid workaround, but we've yet to find a better
 309         * solution.
 310         *
 311         * Thanks to Drew Fisher for figuring this out.
 312         */
 313        if (mode & (FORMAT_Y10B | MODE_1280x1024)) {
 314                write_register(gspca_dev, 0x13, 0x01);
 315                write_register(gspca_dev, 0x14, 0x1e);
 316                write_register(gspca_dev, 0x06, 0x02);
 317                write_register(gspca_dev, 0x06, 0x00);
 318        }
 319
 320        write_register(gspca_dev, fmt_reg, fmt_val);
 321        write_register(gspca_dev, res_reg, res_val);
 322        write_register(gspca_dev, fps_reg, fps_val);
 323
 324        /* Start video stream */
 325        write_register(gspca_dev, 0x05, mode_val);
 326
 327        /* disable Hflip */
 328        write_register(gspca_dev, 0x47, 0x00);
 329
 330        return 0;
 331}
 332
 333static void sd_stopN(struct gspca_dev *gspca_dev)
 334{
 335        /* reset video stream */
 336        write_register(gspca_dev, 0x05, 0x00);
 337}
 338
 339static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *__data, int len)
 340{
 341        struct sd *sd = (struct sd *) gspca_dev;
 342
 343        struct pkt_hdr *hdr = (void *)__data;
 344        uint8_t *data = __data + sizeof(*hdr);
 345        int datalen = len - sizeof(*hdr);
 346
 347        uint8_t sof = sd->stream_flag | 1;
 348        uint8_t mof = sd->stream_flag | 2;
 349        uint8_t eof = sd->stream_flag | 5;
 350
 351        if (len < 12)
 352                return;
 353
 354        if (hdr->magic[0] != 'R' || hdr->magic[1] != 'B') {
 355                pr_warn("[Stream %02x] Invalid magic %02x%02x\n",
 356                        sd->stream_flag, hdr->magic[0], hdr->magic[1]);
 357                return;
 358        }
 359
 360        if (hdr->flag == sof)
 361                gspca_frame_add(gspca_dev, FIRST_PACKET, data, datalen);
 362
 363        else if (hdr->flag == mof)
 364                gspca_frame_add(gspca_dev, INTER_PACKET, data, datalen);
 365
 366        else if (hdr->flag == eof)
 367                gspca_frame_add(gspca_dev, LAST_PACKET, data, datalen);
 368
 369        else
 370                pr_warn("Packet type not recognized...\n");
 371}
 372
 373/* sub-driver description */
 374static const struct sd_desc sd_desc = {
 375        .name      = MODULE_NAME,
 376        .ctrls     = sd_ctrls,
 377        .nctrls    = ARRAY_SIZE(sd_ctrls),
 378        .config    = sd_config,
 379        .init      = sd_init,
 380        .start     = sd_start,
 381        .stopN     = sd_stopN,
 382        .pkt_scan  = sd_pkt_scan,
 383        /*
 384        .querymenu = sd_querymenu,
 385        .get_streamparm = sd_get_streamparm,
 386        .set_streamparm = sd_set_streamparm,
 387        */
 388};
 389
 390/* -- module initialisation -- */
 391static const struct usb_device_id device_table[] = {
 392        {USB_DEVICE(0x045e, 0x02ae)},
 393        {}
 394};
 395
 396MODULE_DEVICE_TABLE(usb, device_table);
 397
 398/* -- device connect -- */
 399static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
 400{
 401        return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
 402                                THIS_MODULE);
 403}
 404
 405static struct usb_driver sd_driver = {
 406        .name       = MODULE_NAME,
 407        .id_table   = device_table,
 408        .probe      = sd_probe,
 409        .disconnect = gspca_disconnect,
 410#ifdef CONFIG_PM
 411        .suspend    = gspca_suspend,
 412        .resume     = gspca_resume,
 413#endif
 414};
 415
 416module_usb_driver(sd_driver);
 417