0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0013
0014 #define MODULE_NAME "se401"
0015
0016 #define BULK_SIZE 4096
0017 #define PACKET_SIZE 1024
0018 #define READ_REQ_SIZE 64
0019 #define MAX_MODES ((READ_REQ_SIZE - 6) / 4)
0020
0021
0022
0023 #define SE401_QUANT_FACT 8
0024
0025 #include <linux/input.h>
0026 #include <linux/slab.h>
0027 #include "gspca.h"
0028 #include "se401.h"
0029
0030 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
0031 MODULE_DESCRIPTION("Endpoints se401");
0032 MODULE_LICENSE("GPL");
0033
0034
0035 enum {
0036 EXPO_CHANGED,
0037 EXPO_DROP_FRAME,
0038 EXPO_NO_CHANGE,
0039 };
0040
0041
0042 struct sd {
0043 struct gspca_dev gspca_dev;
0044 struct {
0045 struct v4l2_ctrl *exposure;
0046 struct v4l2_ctrl *freq;
0047 };
0048 bool has_brightness;
0049 struct v4l2_pix_format fmts[MAX_MODES];
0050 int pixels_read;
0051 int packet_read;
0052 u8 packet[PACKET_SIZE];
0053 u8 restart_stream;
0054 u8 button_state;
0055 u8 resetlevel;
0056 u8 resetlevel_frame_count;
0057 int resetlevel_adjust_dir;
0058 int expo_change_state;
0059 };
0060
0061
0062 static void se401_write_req(struct gspca_dev *gspca_dev, u16 req, u16 value,
0063 int silent)
0064 {
0065 int err;
0066
0067 if (gspca_dev->usb_err < 0)
0068 return;
0069
0070 err = usb_control_msg(gspca_dev->dev,
0071 usb_sndctrlpipe(gspca_dev->dev, 0), req,
0072 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0073 value, 0, NULL, 0, 1000);
0074 if (err < 0) {
0075 if (!silent)
0076 pr_err("write req failed req %#04x val %#04x error %d\n",
0077 req, value, err);
0078 gspca_dev->usb_err = err;
0079 }
0080 }
0081
0082 static void se401_read_req(struct gspca_dev *gspca_dev, u16 req, int silent)
0083 {
0084 int err;
0085
0086 if (gspca_dev->usb_err < 0)
0087 return;
0088
0089 if (USB_BUF_SZ < READ_REQ_SIZE) {
0090 pr_err("USB_BUF_SZ too small!!\n");
0091 gspca_dev->usb_err = -ENOBUFS;
0092 return;
0093 }
0094
0095 err = usb_control_msg(gspca_dev->dev,
0096 usb_rcvctrlpipe(gspca_dev->dev, 0), req,
0097 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0098 0, 0, gspca_dev->usb_buf, READ_REQ_SIZE, 1000);
0099 if (err < 0) {
0100 if (!silent)
0101 pr_err("read req failed req %#04x error %d\n",
0102 req, err);
0103 gspca_dev->usb_err = err;
0104
0105
0106
0107
0108 memset(gspca_dev->usb_buf, 0, READ_REQ_SIZE);
0109 }
0110 }
0111
0112 static void se401_set_feature(struct gspca_dev *gspca_dev,
0113 u16 selector, u16 param)
0114 {
0115 int err;
0116
0117 if (gspca_dev->usb_err < 0)
0118 return;
0119
0120 err = usb_control_msg(gspca_dev->dev,
0121 usb_sndctrlpipe(gspca_dev->dev, 0),
0122 SE401_REQ_SET_EXT_FEATURE,
0123 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0124 param, selector, NULL, 0, 1000);
0125 if (err < 0) {
0126 pr_err("set feature failed sel %#04x param %#04x error %d\n",
0127 selector, param, err);
0128 gspca_dev->usb_err = err;
0129 }
0130 }
0131
0132 static int se401_get_feature(struct gspca_dev *gspca_dev, u16 selector)
0133 {
0134 int err;
0135
0136 if (gspca_dev->usb_err < 0)
0137 return gspca_dev->usb_err;
0138
0139 if (USB_BUF_SZ < 2) {
0140 pr_err("USB_BUF_SZ too small!!\n");
0141 gspca_dev->usb_err = -ENOBUFS;
0142 return gspca_dev->usb_err;
0143 }
0144
0145 err = usb_control_msg(gspca_dev->dev,
0146 usb_rcvctrlpipe(gspca_dev->dev, 0),
0147 SE401_REQ_GET_EXT_FEATURE,
0148 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0149 0, selector, gspca_dev->usb_buf, 2, 1000);
0150 if (err < 0) {
0151 pr_err("get feature failed sel %#04x error %d\n",
0152 selector, err);
0153 gspca_dev->usb_err = err;
0154 return err;
0155 }
0156 return gspca_dev->usb_buf[0] | (gspca_dev->usb_buf[1] << 8);
0157 }
0158
0159 static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
0160 {
0161
0162 se401_write_req(gspca_dev, SE401_REQ_SET_BRT, val, 0);
0163 }
0164
0165 static void setgain(struct gspca_dev *gspca_dev, s32 val)
0166 {
0167 u16 gain = 63 - val;
0168
0169
0170 se401_set_feature(gspca_dev, HV7131_REG_ARCG, gain);
0171
0172 se401_set_feature(gspca_dev, HV7131_REG_AGCG, gain);
0173
0174 se401_set_feature(gspca_dev, HV7131_REG_ABCG, gain);
0175 }
0176
0177 static void setexposure(struct gspca_dev *gspca_dev, s32 val, s32 freq)
0178 {
0179 struct sd *sd = (struct sd *) gspca_dev;
0180 int integration = val << 6;
0181 u8 expose_h, expose_m, expose_l;
0182
0183
0184
0185
0186
0187
0188 sd->expo_change_state = EXPO_CHANGED;
0189
0190 if (freq == V4L2_CID_POWER_LINE_FREQUENCY_50HZ)
0191 integration = integration - integration % 106667;
0192 if (freq == V4L2_CID_POWER_LINE_FREQUENCY_60HZ)
0193 integration = integration - integration % 88889;
0194
0195 expose_h = (integration >> 16);
0196 expose_m = (integration >> 8);
0197 expose_l = integration;
0198
0199
0200 se401_set_feature(gspca_dev, HV7131_REG_TITL, expose_l);
0201
0202 se401_set_feature(gspca_dev, HV7131_REG_TITM, expose_m);
0203
0204 se401_set_feature(gspca_dev, HV7131_REG_TITU, expose_h);
0205 }
0206
0207 static int sd_config(struct gspca_dev *gspca_dev,
0208 const struct usb_device_id *id)
0209 {
0210 struct sd *sd = (struct sd *)gspca_dev;
0211 struct cam *cam = &gspca_dev->cam;
0212 u8 *cd = gspca_dev->usb_buf;
0213 int i, j, n;
0214 int widths[MAX_MODES], heights[MAX_MODES];
0215
0216
0217 se401_read_req(gspca_dev, SE401_REQ_GET_CAMERA_DESCRIPTOR, 1);
0218 if (gspca_dev->usb_err) {
0219
0220
0221 usb_reset_device(gspca_dev->dev);
0222 gspca_dev->usb_err = 0;
0223 se401_read_req(gspca_dev, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0);
0224 }
0225
0226
0227 se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, 0, 0);
0228 if (gspca_dev->usb_err)
0229 return gspca_dev->usb_err;
0230
0231 if (cd[1] != 0x41) {
0232 pr_err("Wrong descriptor type\n");
0233 return -ENODEV;
0234 }
0235
0236 if (!(cd[2] & SE401_FORMAT_BAYER)) {
0237 pr_err("Bayer format not supported!\n");
0238 return -ENODEV;
0239 }
0240
0241 if (cd[3])
0242 pr_info("ExtraFeatures: %d\n", cd[3]);
0243
0244 n = cd[4] | (cd[5] << 8);
0245 if (n > MAX_MODES) {
0246 pr_err("Too many frame sizes\n");
0247 return -ENODEV;
0248 }
0249
0250 for (i = 0; i < n ; i++) {
0251 widths[i] = cd[6 + i * 4 + 0] | (cd[6 + i * 4 + 1] << 8);
0252 heights[i] = cd[6 + i * 4 + 2] | (cd[6 + i * 4 + 3] << 8);
0253 }
0254
0255 for (i = 0; i < n ; i++) {
0256 sd->fmts[i].width = widths[i];
0257 sd->fmts[i].height = heights[i];
0258 sd->fmts[i].field = V4L2_FIELD_NONE;
0259 sd->fmts[i].colorspace = V4L2_COLORSPACE_SRGB;
0260 sd->fmts[i].priv = 1;
0261
0262
0263 for (j = 0; j < n; j++) {
0264 if (widths[j] / 2 == widths[i] &&
0265 heights[j] / 2 == heights[i]) {
0266 sd->fmts[i].priv = 2;
0267 break;
0268 }
0269 }
0270
0271
0272 for (j = 0; j < n; j++) {
0273 if (widths[j] / 4 == widths[i] &&
0274 heights[j] / 4 == heights[i]) {
0275 sd->fmts[i].priv = 4;
0276 break;
0277 }
0278 }
0279
0280 if (sd->fmts[i].priv == 1) {
0281
0282 sd->fmts[i].pixelformat = V4L2_PIX_FMT_SBGGR8;
0283 sd->fmts[i].bytesperline = widths[i];
0284 sd->fmts[i].sizeimage = widths[i] * heights[i];
0285 pr_info("Frame size: %dx%d bayer\n",
0286 widths[i], heights[i]);
0287 } else {
0288
0289 sd->fmts[i].pixelformat = V4L2_PIX_FMT_SE401;
0290 sd->fmts[i].bytesperline = 0;
0291 sd->fmts[i].sizeimage = widths[i] * heights[i] * 3;
0292 pr_info("Frame size: %dx%d 1/%dth janggu\n",
0293 widths[i], heights[i],
0294 sd->fmts[i].priv * sd->fmts[i].priv);
0295 }
0296 }
0297
0298 cam->cam_mode = sd->fmts;
0299 cam->nmodes = n;
0300 cam->bulk = 1;
0301 cam->bulk_size = BULK_SIZE;
0302 cam->bulk_nurbs = 4;
0303 sd->resetlevel = 0x2d;
0304
0305
0306 se401_read_req(gspca_dev, SE401_REQ_GET_BRT, 1);
0307 sd->has_brightness = !!gspca_dev->usb_err;
0308 gspca_dev->usb_err = 0;
0309
0310 return 0;
0311 }
0312
0313
0314 static int sd_init(struct gspca_dev *gspca_dev)
0315 {
0316 return 0;
0317 }
0318
0319
0320 static int sd_isoc_init(struct gspca_dev *gspca_dev)
0321 {
0322 gspca_dev->alt = 1;
0323
0324 return gspca_dev->usb_err;
0325 }
0326
0327
0328 static int sd_start(struct gspca_dev *gspca_dev)
0329 {
0330 struct sd *sd = (struct sd *)gspca_dev;
0331 int mult = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
0332 int mode = 0;
0333
0334 se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, 1, 1);
0335 if (gspca_dev->usb_err) {
0336
0337
0338 usb_reset_device(gspca_dev->dev);
0339 gspca_dev->usb_err = 0;
0340 se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, 1, 0);
0341 }
0342 se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, 1, 0);
0343
0344 se401_set_feature(gspca_dev, HV7131_REG_MODE_B, 0x05);
0345
0346
0347 se401_write_req(gspca_dev, SE401_REQ_SET_WIDTH,
0348 gspca_dev->pixfmt.width * mult, 0);
0349 se401_write_req(gspca_dev, SE401_REQ_SET_HEIGHT,
0350 gspca_dev->pixfmt.height * mult, 0);
0351
0352
0353
0354
0355
0356
0357 switch (mult) {
0358 case 1:
0359 mode = 0x03; break;
0360 case 2:
0361 mode = SE401_QUANT_FACT << 4; break;
0362 case 4:
0363 mode = (SE401_QUANT_FACT << 4) | 0x02; break;
0364 }
0365 se401_set_feature(gspca_dev, SE401_OPERATINGMODE, mode);
0366
0367 se401_set_feature(gspca_dev, HV7131_REG_ARLV, sd->resetlevel);
0368
0369 sd->packet_read = 0;
0370 sd->pixels_read = 0;
0371 sd->restart_stream = 0;
0372 sd->resetlevel_frame_count = 0;
0373 sd->resetlevel_adjust_dir = 0;
0374 sd->expo_change_state = EXPO_NO_CHANGE;
0375
0376 se401_write_req(gspca_dev, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, 0);
0377
0378 return gspca_dev->usb_err;
0379 }
0380
0381 static void sd_stopN(struct gspca_dev *gspca_dev)
0382 {
0383 se401_write_req(gspca_dev, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, 0);
0384 se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, 0, 0);
0385 se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, 0, 0);
0386 }
0387
0388 static void sd_dq_callback(struct gspca_dev *gspca_dev)
0389 {
0390 struct sd *sd = (struct sd *)gspca_dev;
0391 unsigned int ahrc, alrc;
0392 int oldreset, adjust_dir;
0393
0394
0395 if (sd->restart_stream) {
0396 sd_stopN(gspca_dev);
0397 sd_start(gspca_dev);
0398 sd->restart_stream = 0;
0399 }
0400
0401
0402
0403
0404 sd->resetlevel_frame_count++;
0405 if (sd->resetlevel_frame_count < 20)
0406 return;
0407
0408
0409
0410 se401_get_feature(gspca_dev, HV7131_REG_HIREFNOH);
0411 se401_get_feature(gspca_dev, HV7131_REG_HIREFNOL);
0412 se401_get_feature(gspca_dev, HV7131_REG_LOREFNOH);
0413 se401_get_feature(gspca_dev, HV7131_REG_LOREFNOL);
0414 ahrc = 256*se401_get_feature(gspca_dev, HV7131_REG_HIREFNOH) +
0415 se401_get_feature(gspca_dev, HV7131_REG_HIREFNOL);
0416 alrc = 256*se401_get_feature(gspca_dev, HV7131_REG_LOREFNOH) +
0417 se401_get_feature(gspca_dev, HV7131_REG_LOREFNOL);
0418
0419
0420 oldreset = sd->resetlevel;
0421 if (alrc > 10) {
0422 while (alrc >= 10 && sd->resetlevel < 63) {
0423 sd->resetlevel++;
0424 alrc /= 2;
0425 }
0426 } else if (ahrc > 20) {
0427 while (ahrc >= 20 && sd->resetlevel > 0) {
0428 sd->resetlevel--;
0429 ahrc /= 2;
0430 }
0431 }
0432
0433 if (sd->resetlevel > oldreset)
0434 adjust_dir = 1;
0435 else
0436 adjust_dir = -1;
0437 if (sd->resetlevel_adjust_dir &&
0438 sd->resetlevel_adjust_dir != adjust_dir)
0439 sd->resetlevel = oldreset + (sd->resetlevel - oldreset) / 2;
0440
0441 if (sd->resetlevel != oldreset) {
0442 sd->resetlevel_adjust_dir = adjust_dir;
0443 se401_set_feature(gspca_dev, HV7131_REG_ARLV, sd->resetlevel);
0444 }
0445
0446 sd->resetlevel_frame_count = 0;
0447 }
0448
0449 static void sd_complete_frame(struct gspca_dev *gspca_dev, u8 *data, int len)
0450 {
0451 struct sd *sd = (struct sd *)gspca_dev;
0452
0453 switch (sd->expo_change_state) {
0454 case EXPO_CHANGED:
0455
0456
0457 sd->expo_change_state = EXPO_DROP_FRAME;
0458 break;
0459 case EXPO_DROP_FRAME:
0460
0461
0462 gspca_dev->last_packet_type = DISCARD_PACKET;
0463 sd->expo_change_state = EXPO_NO_CHANGE;
0464 break;
0465 case EXPO_NO_CHANGE:
0466 break;
0467 }
0468 gspca_frame_add(gspca_dev, LAST_PACKET, data, len);
0469 }
0470
0471 static void sd_pkt_scan_janggu(struct gspca_dev *gspca_dev, u8 *data, int len)
0472 {
0473 struct sd *sd = (struct sd *)gspca_dev;
0474 int imagesize = gspca_dev->pixfmt.width * gspca_dev->pixfmt.height;
0475 int i, plen, bits, pixels, info, count;
0476
0477 if (sd->restart_stream)
0478 return;
0479
0480
0481 if (gspca_dev->last_packet_type == LAST_PACKET && len == 1024) {
0482 gspca_dev->last_packet_type = DISCARD_PACKET;
0483 return;
0484 }
0485
0486 i = 0;
0487 while (i < len) {
0488
0489 if (sd->packet_read < 4) {
0490 count = 4 - sd->packet_read;
0491 if (count > len - i)
0492 count = len - i;
0493 memcpy(&sd->packet[sd->packet_read], &data[i], count);
0494 sd->packet_read += count;
0495 i += count;
0496 if (sd->packet_read < 4)
0497 break;
0498 }
0499 bits = sd->packet[3] + (sd->packet[2] << 8);
0500 pixels = sd->packet[1] + ((sd->packet[0] & 0x3f) << 8);
0501 info = (sd->packet[0] & 0xc0) >> 6;
0502 plen = ((bits + 47) >> 4) << 1;
0503
0504 if (plen > 1024) {
0505 pr_err("invalid packet len %d restarting stream\n",
0506 plen);
0507 goto error;
0508 }
0509 if (info == 3) {
0510 pr_err("unknown frame info value restarting stream\n");
0511 goto error;
0512 }
0513
0514
0515 count = plen - sd->packet_read;
0516 if (count > len - i)
0517 count = len - i;
0518 memcpy(&sd->packet[sd->packet_read], &data[i], count);
0519 sd->packet_read += count;
0520 i += count;
0521 if (sd->packet_read < plen)
0522 break;
0523
0524 sd->pixels_read += pixels;
0525 sd->packet_read = 0;
0526
0527 switch (info) {
0528 case 0:
0529 gspca_frame_add(gspca_dev, INTER_PACKET, sd->packet,
0530 plen);
0531 break;
0532 case 1:
0533 if (sd->pixels_read != imagesize) {
0534 pr_err("frame size %d expected %d\n",
0535 sd->pixels_read, imagesize);
0536 goto error;
0537 }
0538 sd_complete_frame(gspca_dev, sd->packet, plen);
0539 return;
0540 case 2:
0541 gspca_frame_add(gspca_dev, FIRST_PACKET, sd->packet,
0542 plen);
0543 sd->pixels_read = pixels;
0544 break;
0545 }
0546 }
0547 return;
0548
0549 error:
0550 sd->restart_stream = 1;
0551
0552
0553 gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
0554 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
0555 }
0556
0557 static void sd_pkt_scan_bayer(struct gspca_dev *gspca_dev, u8 *data, int len)
0558 {
0559 struct cam *cam = &gspca_dev->cam;
0560 int imagesize = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
0561
0562 if (gspca_dev->image_len == 0) {
0563 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
0564 return;
0565 }
0566
0567 if (gspca_dev->image_len + len >= imagesize) {
0568 sd_complete_frame(gspca_dev, data, len);
0569 return;
0570 }
0571
0572 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
0573 }
0574
0575 static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, int len)
0576 {
0577 int mult = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
0578
0579 if (len == 0)
0580 return;
0581
0582 if (mult == 1)
0583 sd_pkt_scan_bayer(gspca_dev, data, len);
0584 else
0585 sd_pkt_scan_janggu(gspca_dev, data, len);
0586 }
0587
0588 #if IS_ENABLED(CONFIG_INPUT)
0589 static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, int len)
0590 {
0591 struct sd *sd = (struct sd *)gspca_dev;
0592 u8 state;
0593
0594 if (len != 2)
0595 return -EINVAL;
0596
0597 switch (data[0]) {
0598 case 0:
0599 case 1:
0600 state = data[0];
0601 break;
0602 default:
0603 return -EINVAL;
0604 }
0605 if (sd->button_state != state) {
0606 input_report_key(gspca_dev->input_dev, KEY_CAMERA, state);
0607 input_sync(gspca_dev->input_dev);
0608 sd->button_state = state;
0609 }
0610
0611 return 0;
0612 }
0613 #endif
0614
0615 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
0616 {
0617 struct gspca_dev *gspca_dev =
0618 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
0619 struct sd *sd = (struct sd *)gspca_dev;
0620
0621 gspca_dev->usb_err = 0;
0622
0623 if (!gspca_dev->streaming)
0624 return 0;
0625
0626 switch (ctrl->id) {
0627 case V4L2_CID_BRIGHTNESS:
0628 setbrightness(gspca_dev, ctrl->val);
0629 break;
0630 case V4L2_CID_GAIN:
0631 setgain(gspca_dev, ctrl->val);
0632 break;
0633 case V4L2_CID_EXPOSURE:
0634 setexposure(gspca_dev, ctrl->val, sd->freq->val);
0635 break;
0636 }
0637 return gspca_dev->usb_err;
0638 }
0639
0640 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
0641 .s_ctrl = sd_s_ctrl,
0642 };
0643
0644 static int sd_init_controls(struct gspca_dev *gspca_dev)
0645 {
0646 struct sd *sd = (struct sd *)gspca_dev;
0647 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
0648
0649 gspca_dev->vdev.ctrl_handler = hdl;
0650 v4l2_ctrl_handler_init(hdl, 4);
0651 if (sd->has_brightness)
0652 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0653 V4L2_CID_BRIGHTNESS, 0, 255, 1, 15);
0654
0655 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0656 V4L2_CID_GAIN, 0, 50, 1, 25);
0657 sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0658 V4L2_CID_EXPOSURE, 0, 32767, 1, 15000);
0659 sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
0660 V4L2_CID_POWER_LINE_FREQUENCY,
0661 V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0);
0662
0663 if (hdl->error) {
0664 pr_err("Could not initialize controls\n");
0665 return hdl->error;
0666 }
0667 v4l2_ctrl_cluster(2, &sd->exposure);
0668 return 0;
0669 }
0670
0671
0672 static const struct sd_desc sd_desc = {
0673 .name = MODULE_NAME,
0674 .config = sd_config,
0675 .init = sd_init,
0676 .init_controls = sd_init_controls,
0677 .isoc_init = sd_isoc_init,
0678 .start = sd_start,
0679 .stopN = sd_stopN,
0680 .dq_callback = sd_dq_callback,
0681 .pkt_scan = sd_pkt_scan,
0682 #if IS_ENABLED(CONFIG_INPUT)
0683 .int_pkt_scan = sd_int_pkt_scan,
0684 #endif
0685 };
0686
0687
0688 static const struct usb_device_id device_table[] = {
0689 {USB_DEVICE(0x03e8, 0x0004)},
0690 {USB_DEVICE(0x0471, 0x030b)},
0691 {USB_DEVICE(0x047d, 0x5001)},
0692 {USB_DEVICE(0x047d, 0x5002)},
0693 {USB_DEVICE(0x047d, 0x5003)},
0694 {}
0695 };
0696 MODULE_DEVICE_TABLE(usb, device_table);
0697
0698
0699 static int sd_probe(struct usb_interface *intf,
0700 const struct usb_device_id *id)
0701 {
0702 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
0703 THIS_MODULE);
0704 }
0705
0706 static int sd_pre_reset(struct usb_interface *intf)
0707 {
0708 return 0;
0709 }
0710
0711 static int sd_post_reset(struct usb_interface *intf)
0712 {
0713 return 0;
0714 }
0715
0716 static struct usb_driver sd_driver = {
0717 .name = MODULE_NAME,
0718 .id_table = device_table,
0719 .probe = sd_probe,
0720 .disconnect = gspca_disconnect,
0721 #ifdef CONFIG_PM
0722 .suspend = gspca_suspend,
0723 .resume = gspca_resume,
0724 .reset_resume = gspca_resume,
0725 #endif
0726 .pre_reset = sd_pre_reset,
0727 .post_reset = sd_post_reset,
0728 };
0729
0730 module_usb_driver(sd_driver);