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