Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/video/gspca/spca1528.c
17613 views
1
/*
2
* spca1528 subdriver
3
*
4
* Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr)
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
*/
20
21
#define MODULE_NAME "spca1528"
22
23
#include "gspca.h"
24
#include "jpeg.h"
25
26
MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
27
MODULE_DESCRIPTION("SPCA1528 USB Camera Driver");
28
MODULE_LICENSE("GPL");
29
30
/* specific webcam descriptor */
31
struct sd {
32
struct gspca_dev gspca_dev; /* !! must be the first item */
33
34
u8 brightness;
35
u8 contrast;
36
u8 hue;
37
u8 color;
38
u8 sharpness;
39
40
u8 pkt_seq;
41
42
u8 jpeg_hdr[JPEG_HDR_SZ];
43
};
44
45
/* V4L2 controls supported by the driver */
46
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
47
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
48
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
49
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
50
static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val);
51
static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val);
52
static int sd_setcolor(struct gspca_dev *gspca_dev, __s32 val);
53
static int sd_getcolor(struct gspca_dev *gspca_dev, __s32 *val);
54
static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
55
static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
56
57
static const struct ctrl sd_ctrls[] = {
58
{
59
{
60
.id = V4L2_CID_BRIGHTNESS,
61
.type = V4L2_CTRL_TYPE_INTEGER,
62
.name = "Brightness",
63
.minimum = 0,
64
.maximum = 255,
65
.step = 1,
66
#define BRIGHTNESS_DEF 128
67
.default_value = BRIGHTNESS_DEF,
68
},
69
.set = sd_setbrightness,
70
.get = sd_getbrightness,
71
},
72
{
73
{
74
.id = V4L2_CID_CONTRAST,
75
.type = V4L2_CTRL_TYPE_INTEGER,
76
.name = "Contrast",
77
.minimum = 0,
78
.maximum = 8,
79
.step = 1,
80
#define CONTRAST_DEF 1
81
.default_value = CONTRAST_DEF,
82
},
83
.set = sd_setcontrast,
84
.get = sd_getcontrast,
85
},
86
{
87
{
88
.id = V4L2_CID_HUE,
89
.type = V4L2_CTRL_TYPE_INTEGER,
90
.name = "Hue",
91
.minimum = 0,
92
.maximum = 255,
93
.step = 1,
94
#define HUE_DEF 0
95
.default_value = HUE_DEF,
96
},
97
.set = sd_sethue,
98
.get = sd_gethue,
99
},
100
{
101
{
102
.id = V4L2_CID_SATURATION,
103
.type = V4L2_CTRL_TYPE_INTEGER,
104
.name = "Saturation",
105
.minimum = 0,
106
.maximum = 8,
107
.step = 1,
108
#define COLOR_DEF 1
109
.default_value = COLOR_DEF,
110
},
111
.set = sd_setcolor,
112
.get = sd_getcolor,
113
},
114
{
115
{
116
.id = V4L2_CID_SHARPNESS,
117
.type = V4L2_CTRL_TYPE_INTEGER,
118
.name = "Sharpness",
119
.minimum = 0,
120
.maximum = 255,
121
.step = 1,
122
#define SHARPNESS_DEF 0
123
.default_value = SHARPNESS_DEF,
124
},
125
.set = sd_setsharpness,
126
.get = sd_getsharpness,
127
},
128
};
129
130
static const struct v4l2_pix_format vga_mode[] = {
131
/* (does not work correctly)
132
{176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
133
.bytesperline = 176,
134
.sizeimage = 176 * 144 * 5 / 8 + 590,
135
.colorspace = V4L2_COLORSPACE_JPEG,
136
.priv = 3},
137
*/
138
{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
139
.bytesperline = 320,
140
.sizeimage = 320 * 240 * 4 / 8 + 590,
141
.colorspace = V4L2_COLORSPACE_JPEG,
142
.priv = 2},
143
{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
144
.bytesperline = 640,
145
.sizeimage = 640 * 480 * 3 / 8 + 590,
146
.colorspace = V4L2_COLORSPACE_JPEG,
147
.priv = 1},
148
};
149
150
/* read <len> bytes to gspca usb_buf */
151
static void reg_r(struct gspca_dev *gspca_dev,
152
u8 req,
153
u16 index,
154
int len)
155
{
156
#if USB_BUF_SZ < 64
157
#error "USB buffer too small"
158
#endif
159
struct usb_device *dev = gspca_dev->dev;
160
int ret;
161
162
if (gspca_dev->usb_err < 0)
163
return;
164
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
165
req,
166
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
167
0x0000, /* value */
168
index,
169
gspca_dev->usb_buf, len,
170
500);
171
PDEBUG(D_USBI, "GET %02x 0000 %04x %02x", req, index,
172
gspca_dev->usb_buf[0]);
173
if (ret < 0) {
174
err("reg_r err %d", ret);
175
gspca_dev->usb_err = ret;
176
}
177
}
178
179
static void reg_w(struct gspca_dev *gspca_dev,
180
u8 req,
181
u16 value,
182
u16 index)
183
{
184
struct usb_device *dev = gspca_dev->dev;
185
int ret;
186
187
if (gspca_dev->usb_err < 0)
188
return;
189
PDEBUG(D_USBO, "SET %02x %04x %04x", req, value, index);
190
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
191
req,
192
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
193
value, index,
194
NULL, 0, 500);
195
if (ret < 0) {
196
err("reg_w err %d", ret);
197
gspca_dev->usb_err = ret;
198
}
199
}
200
201
static void reg_wb(struct gspca_dev *gspca_dev,
202
u8 req,
203
u16 value,
204
u16 index,
205
u8 byte)
206
{
207
struct usb_device *dev = gspca_dev->dev;
208
int ret;
209
210
if (gspca_dev->usb_err < 0)
211
return;
212
PDEBUG(D_USBO, "SET %02x %04x %04x %02x", req, value, index, byte);
213
gspca_dev->usb_buf[0] = byte;
214
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
215
req,
216
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
217
value, index,
218
gspca_dev->usb_buf, 1, 500);
219
if (ret < 0) {
220
err("reg_w err %d", ret);
221
gspca_dev->usb_err = ret;
222
}
223
}
224
225
static void wait_status_0(struct gspca_dev *gspca_dev)
226
{
227
int i;
228
229
i = 20;
230
do {
231
reg_r(gspca_dev, 0x21, 0x0000, 1);
232
if (gspca_dev->usb_buf[0] == 0)
233
return;
234
msleep(30);
235
} while (--i > 0);
236
PDEBUG(D_ERR, "wait_status_0 timeout");
237
gspca_dev->usb_err = -ETIME;
238
}
239
240
static void wait_status_1(struct gspca_dev *gspca_dev)
241
{
242
int i;
243
244
i = 10;
245
do {
246
reg_r(gspca_dev, 0x21, 0x0001, 1);
247
msleep(10);
248
if (gspca_dev->usb_buf[0] == 1) {
249
reg_wb(gspca_dev, 0x21, 0x0000, 0x0001, 0x00);
250
reg_r(gspca_dev, 0x21, 0x0001, 1);
251
return;
252
}
253
} while (--i > 0);
254
PDEBUG(D_ERR, "wait_status_1 timeout");
255
gspca_dev->usb_err = -ETIME;
256
}
257
258
static void setbrightness(struct gspca_dev *gspca_dev)
259
{
260
struct sd *sd = (struct sd *) gspca_dev;
261
262
reg_wb(gspca_dev, 0xc0, 0x0000, 0x00c0, sd->brightness);
263
}
264
265
static void setcontrast(struct gspca_dev *gspca_dev)
266
{
267
struct sd *sd = (struct sd *) gspca_dev;
268
269
reg_wb(gspca_dev, 0xc1, 0x0000, 0x00c1, sd->contrast);
270
}
271
272
static void sethue(struct gspca_dev *gspca_dev)
273
{
274
struct sd *sd = (struct sd *) gspca_dev;
275
276
reg_wb(gspca_dev, 0xc2, 0x0000, 0x0000, sd->hue);
277
}
278
279
static void setcolor(struct gspca_dev *gspca_dev)
280
{
281
struct sd *sd = (struct sd *) gspca_dev;
282
283
reg_wb(gspca_dev, 0xc3, 0x0000, 0x00c3, sd->color);
284
}
285
286
static void setsharpness(struct gspca_dev *gspca_dev)
287
{
288
struct sd *sd = (struct sd *) gspca_dev;
289
290
reg_wb(gspca_dev, 0xc4, 0x0000, 0x00c4, sd->sharpness);
291
}
292
293
/* this function is called at probe time */
294
static int sd_config(struct gspca_dev *gspca_dev,
295
const struct usb_device_id *id)
296
{
297
struct sd *sd = (struct sd *) gspca_dev;
298
299
gspca_dev->cam.cam_mode = vga_mode;
300
gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
301
gspca_dev->cam.npkt = 128; /* number of packets per ISOC message */
302
/*fixme: 256 in ms-win traces*/
303
304
sd->brightness = BRIGHTNESS_DEF;
305
sd->contrast = CONTRAST_DEF;
306
sd->hue = HUE_DEF;
307
sd->color = COLOR_DEF;
308
sd->sharpness = SHARPNESS_DEF;
309
310
gspca_dev->nbalt = 4; /* use alternate setting 3 */
311
312
return 0;
313
}
314
315
/* this function is called at probe and resume time */
316
static int sd_init(struct gspca_dev *gspca_dev)
317
{
318
reg_w(gspca_dev, 0x00, 0x0001, 0x2067);
319
reg_w(gspca_dev, 0x00, 0x00d0, 0x206b);
320
reg_w(gspca_dev, 0x00, 0x0000, 0x206c);
321
reg_w(gspca_dev, 0x00, 0x0001, 0x2069);
322
msleep(8);
323
reg_w(gspca_dev, 0x00, 0x00c0, 0x206b);
324
reg_w(gspca_dev, 0x00, 0x0000, 0x206c);
325
reg_w(gspca_dev, 0x00, 0x0001, 0x2069);
326
327
reg_r(gspca_dev, 0x20, 0x0000, 1);
328
reg_r(gspca_dev, 0x20, 0x0000, 5);
329
reg_r(gspca_dev, 0x23, 0x0000, 64);
330
PDEBUG(D_PROBE, "%s%s", &gspca_dev->usb_buf[0x1c],
331
&gspca_dev->usb_buf[0x30]);
332
reg_r(gspca_dev, 0x23, 0x0001, 64);
333
return gspca_dev->usb_err;
334
}
335
336
/* function called at start time before URB creation */
337
static int sd_isoc_init(struct gspca_dev *gspca_dev)
338
{
339
u8 mode;
340
341
reg_r(gspca_dev, 0x00, 0x2520, 1);
342
wait_status_0(gspca_dev);
343
reg_w(gspca_dev, 0xc5, 0x0003, 0x0000);
344
wait_status_1(gspca_dev);
345
346
wait_status_0(gspca_dev);
347
mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
348
reg_wb(gspca_dev, 0x25, 0x0000, 0x0004, mode);
349
reg_r(gspca_dev, 0x25, 0x0004, 1);
350
reg_wb(gspca_dev, 0x27, 0x0000, 0x0000, 0x06);
351
reg_r(gspca_dev, 0x27, 0x0000, 1);
352
return gspca_dev->usb_err;
353
}
354
355
/* -- start the camera -- */
356
static int sd_start(struct gspca_dev *gspca_dev)
357
{
358
struct sd *sd = (struct sd *) gspca_dev;
359
360
/* initialize the JPEG header */
361
jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
362
0x22); /* JPEG 411 */
363
364
/* the JPEG quality seems to be 82% */
365
jpeg_set_qual(sd->jpeg_hdr, 82);
366
367
/* set the controls */
368
setbrightness(gspca_dev);
369
setcontrast(gspca_dev);
370
sethue(gspca_dev);
371
setcolor(gspca_dev);
372
setsharpness(gspca_dev);
373
374
msleep(5);
375
reg_r(gspca_dev, 0x00, 0x2520, 1);
376
msleep(8);
377
378
/* start the capture */
379
wait_status_0(gspca_dev);
380
reg_w(gspca_dev, 0x31, 0x0000, 0x0004);
381
wait_status_1(gspca_dev);
382
wait_status_0(gspca_dev);
383
msleep(200);
384
385
sd->pkt_seq = 0;
386
return gspca_dev->usb_err;
387
}
388
389
static void sd_stopN(struct gspca_dev *gspca_dev)
390
{
391
/* stop the capture */
392
wait_status_0(gspca_dev);
393
reg_w(gspca_dev, 0x31, 0x0000, 0x0000);
394
wait_status_1(gspca_dev);
395
wait_status_0(gspca_dev);
396
}
397
398
/* move a packet adding 0x00 after 0xff */
399
static void add_packet(struct gspca_dev *gspca_dev,
400
u8 *data,
401
int len)
402
{
403
int i;
404
405
i = 0;
406
do {
407
if (data[i] == 0xff) {
408
gspca_frame_add(gspca_dev, INTER_PACKET,
409
data, i + 1);
410
len -= i;
411
data += i;
412
*data = 0x00;
413
i = 0;
414
}
415
} while (++i < len);
416
gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
417
}
418
419
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
420
u8 *data, /* isoc packet */
421
int len) /* iso packet length */
422
{
423
struct sd *sd = (struct sd *) gspca_dev;
424
static const u8 ffd9[] = {0xff, 0xd9};
425
426
/* image packets start with:
427
* 02 8n
428
* with <n> bit:
429
* 0x01: even (0) / odd (1) image
430
* 0x02: end of image when set
431
*/
432
if (len < 3)
433
return; /* empty packet */
434
if (*data == 0x02) {
435
if (data[1] & 0x02) {
436
sd->pkt_seq = !(data[1] & 1);
437
add_packet(gspca_dev, data + 2, len - 2);
438
gspca_frame_add(gspca_dev, LAST_PACKET,
439
ffd9, 2);
440
return;
441
}
442
if ((data[1] & 1) != sd->pkt_seq)
443
goto err;
444
if (gspca_dev->last_packet_type == LAST_PACKET)
445
gspca_frame_add(gspca_dev, FIRST_PACKET,
446
sd->jpeg_hdr, JPEG_HDR_SZ);
447
add_packet(gspca_dev, data + 2, len - 2);
448
return;
449
}
450
err:
451
gspca_dev->last_packet_type = DISCARD_PACKET;
452
}
453
454
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
455
{
456
struct sd *sd = (struct sd *) gspca_dev;
457
458
sd->brightness = val;
459
if (gspca_dev->streaming)
460
setbrightness(gspca_dev);
461
return gspca_dev->usb_err;
462
}
463
464
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
465
{
466
struct sd *sd = (struct sd *) gspca_dev;
467
468
*val = sd->brightness;
469
return 0;
470
}
471
472
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
473
{
474
struct sd *sd = (struct sd *) gspca_dev;
475
476
sd->contrast = val;
477
if (gspca_dev->streaming)
478
setcontrast(gspca_dev);
479
return gspca_dev->usb_err;
480
}
481
482
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
483
{
484
struct sd *sd = (struct sd *) gspca_dev;
485
486
*val = sd->contrast;
487
return 0;
488
}
489
490
static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val)
491
{
492
struct sd *sd = (struct sd *) gspca_dev;
493
494
sd->hue = val;
495
if (gspca_dev->streaming)
496
sethue(gspca_dev);
497
return gspca_dev->usb_err;
498
}
499
500
static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val)
501
{
502
struct sd *sd = (struct sd *) gspca_dev;
503
504
*val = sd->hue;
505
return 0;
506
}
507
508
static int sd_setcolor(struct gspca_dev *gspca_dev, __s32 val)
509
{
510
struct sd *sd = (struct sd *) gspca_dev;
511
512
sd->color = val;
513
if (gspca_dev->streaming)
514
setcolor(gspca_dev);
515
return gspca_dev->usb_err;
516
}
517
518
static int sd_getcolor(struct gspca_dev *gspca_dev, __s32 *val)
519
{
520
struct sd *sd = (struct sd *) gspca_dev;
521
522
*val = sd->color;
523
return 0;
524
}
525
526
static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
527
{
528
struct sd *sd = (struct sd *) gspca_dev;
529
530
sd->sharpness = val;
531
if (gspca_dev->streaming)
532
setsharpness(gspca_dev);
533
return gspca_dev->usb_err;
534
}
535
536
static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
537
{
538
struct sd *sd = (struct sd *) gspca_dev;
539
540
*val = sd->sharpness;
541
return 0;
542
}
543
544
/* sub-driver description */
545
static const struct sd_desc sd_desc = {
546
.name = MODULE_NAME,
547
.ctrls = sd_ctrls,
548
.nctrls = ARRAY_SIZE(sd_ctrls),
549
.config = sd_config,
550
.init = sd_init,
551
.isoc_init = sd_isoc_init,
552
.start = sd_start,
553
.stopN = sd_stopN,
554
.pkt_scan = sd_pkt_scan,
555
};
556
557
/* -- module initialisation -- */
558
static const struct usb_device_id device_table[] = {
559
{USB_DEVICE(0x04fc, 0x1528)},
560
{}
561
};
562
MODULE_DEVICE_TABLE(usb, device_table);
563
564
/* -- device connect -- */
565
static int sd_probe(struct usb_interface *intf,
566
const struct usb_device_id *id)
567
{
568
/* the video interface for isochronous transfer is 1 */
569
if (intf->cur_altsetting->desc.bInterfaceNumber != 1)
570
return -ENODEV;
571
572
return gspca_dev_probe2(intf, id, &sd_desc, sizeof(struct sd),
573
THIS_MODULE);
574
}
575
576
static struct usb_driver sd_driver = {
577
.name = MODULE_NAME,
578
.id_table = device_table,
579
.probe = sd_probe,
580
.disconnect = gspca_disconnect,
581
#ifdef CONFIG_PM
582
.suspend = gspca_suspend,
583
.resume = gspca_resume,
584
#endif
585
};
586
587
/* -- module insert / remove -- */
588
static int __init sd_mod_init(void)
589
{
590
return usb_register(&sd_driver);
591
}
592
static void __exit sd_mod_exit(void)
593
{
594
usb_deregister(&sd_driver);
595
}
596
597
module_init(sd_mod_init);
598
module_exit(sd_mod_exit);
599
600