1
2
3
4
5
6
7
8
9
10
11
12
13
14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
15
16#define MODULE_NAME "jeilinj"
17
18#include <linux/slab.h>
19#include "gspca.h"
20#include "jpeg.h"
21
22MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");
23MODULE_DESCRIPTION("GSPCA/JEILINJ USB Camera Driver");
24MODULE_LICENSE("GPL");
25
26
27#define JEILINJ_CMD_TIMEOUT 500
28#define JEILINJ_CMD_DELAY 160
29#define JEILINJ_DATA_TIMEOUT 1000
30
31
32#define JEILINJ_MAX_TRANSFER 0x200
33#define FRAME_HEADER_LEN 0x10
34#define FRAME_START 0xFFFFFFFF
35
36enum {
37 SAKAR_57379,
38 SPORTSCAM_DV15,
39};
40
41#define CAMQUALITY_MIN 0
42#define CAMQUALITY_MAX 97
43
44
45struct sd {
46 struct gspca_dev gspca_dev;
47 int blocks_left;
48 const struct v4l2_pix_format *cap_mode;
49 struct v4l2_ctrl *freq;
50 struct v4l2_ctrl *jpegqual;
51
52 u8 type;
53 u8 quality;
54#define QUALITY_MIN 35
55#define QUALITY_MAX 85
56#define QUALITY_DEF 85
57 u8 jpeg_hdr[JPEG_HDR_SZ];
58};
59
60struct jlj_command {
61 unsigned char instruction[2];
62 unsigned char ack_wanted;
63 unsigned char delay;
64};
65
66
67static struct v4l2_pix_format jlj_mode[] = {
68 { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
69 .bytesperline = 320,
70 .sizeimage = 320 * 240,
71 .colorspace = V4L2_COLORSPACE_JPEG,
72 .priv = 0},
73 { 640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
74 .bytesperline = 640,
75 .sizeimage = 640 * 480,
76 .colorspace = V4L2_COLORSPACE_JPEG,
77 .priv = 0}
78};
79
80
81
82
83
84
85
86static void jlj_write2(struct gspca_dev *gspca_dev, unsigned char *command)
87{
88 int retval;
89
90 if (gspca_dev->usb_err < 0)
91 return;
92 memcpy(gspca_dev->usb_buf, command, 2);
93 retval = usb_bulk_msg(gspca_dev->dev,
94 usb_sndbulkpipe(gspca_dev->dev, 3),
95 gspca_dev->usb_buf, 2, NULL, 500);
96 if (retval < 0) {
97 pr_err("command write [%02x] error %d\n",
98 gspca_dev->usb_buf[0], retval);
99 gspca_dev->usb_err = retval;
100 }
101}
102
103
104static void jlj_read1(struct gspca_dev *gspca_dev, unsigned char *response)
105{
106 int retval;
107
108 if (gspca_dev->usb_err < 0)
109 return;
110 retval = usb_bulk_msg(gspca_dev->dev,
111 usb_rcvbulkpipe(gspca_dev->dev, 0x84),
112 gspca_dev->usb_buf, 1, NULL, 500);
113 *response = gspca_dev->usb_buf[0];
114 if (retval < 0) {
115 pr_err("read command [%02x] error %d\n",
116 gspca_dev->usb_buf[0], retval);
117 gspca_dev->usb_err = retval;
118 }
119}
120
121static void setfreq(struct gspca_dev *gspca_dev, s32 val)
122{
123 u8 freq_commands[][2] = {
124 {0x71, 0x80},
125 {0x70, 0x07}
126 };
127
128 freq_commands[0][1] |= val >> 1;
129
130 jlj_write2(gspca_dev, freq_commands[0]);
131 jlj_write2(gspca_dev, freq_commands[1]);
132}
133
134static void setcamquality(struct gspca_dev *gspca_dev, s32 val)
135{
136 u8 quality_commands[][2] = {
137 {0x71, 0x1E},
138 {0x70, 0x06}
139 };
140 u8 camquality;
141
142
143 camquality = ((QUALITY_MAX - val) * CAMQUALITY_MAX)
144 / (QUALITY_MAX - QUALITY_MIN);
145 quality_commands[0][1] += camquality;
146
147 jlj_write2(gspca_dev, quality_commands[0]);
148 jlj_write2(gspca_dev, quality_commands[1]);
149}
150
151static void setautogain(struct gspca_dev *gspca_dev, s32 val)
152{
153 u8 autogain_commands[][2] = {
154 {0x94, 0x02},
155 {0xcf, 0x00}
156 };
157
158 autogain_commands[1][1] = val << 4;
159
160 jlj_write2(gspca_dev, autogain_commands[0]);
161 jlj_write2(gspca_dev, autogain_commands[1]);
162}
163
164static void setred(struct gspca_dev *gspca_dev, s32 val)
165{
166 u8 setred_commands[][2] = {
167 {0x94, 0x02},
168 {0xe6, 0x00}
169 };
170
171 setred_commands[1][1] = val;
172
173 jlj_write2(gspca_dev, setred_commands[0]);
174 jlj_write2(gspca_dev, setred_commands[1]);
175}
176
177static void setgreen(struct gspca_dev *gspca_dev, s32 val)
178{
179 u8 setgreen_commands[][2] = {
180 {0x94, 0x02},
181 {0xe7, 0x00}
182 };
183
184 setgreen_commands[1][1] = val;
185
186 jlj_write2(gspca_dev, setgreen_commands[0]);
187 jlj_write2(gspca_dev, setgreen_commands[1]);
188}
189
190static void setblue(struct gspca_dev *gspca_dev, s32 val)
191{
192 u8 setblue_commands[][2] = {
193 {0x94, 0x02},
194 {0xe9, 0x00}
195 };
196
197 setblue_commands[1][1] = val;
198
199 jlj_write2(gspca_dev, setblue_commands[0]);
200 jlj_write2(gspca_dev, setblue_commands[1]);
201}
202
203static int jlj_start(struct gspca_dev *gspca_dev)
204{
205 int i;
206 int start_commands_size;
207 u8 response = 0xff;
208 struct sd *sd = (struct sd *) gspca_dev;
209 struct jlj_command start_commands[] = {
210 {{0x71, 0x81}, 0, 0},
211 {{0x70, 0x05}, 0, JEILINJ_CMD_DELAY},
212 {{0x95, 0x70}, 1, 0},
213 {{0x71, 0x81 - gspca_dev->curr_mode}, 0, 0},
214 {{0x70, 0x04}, 0, JEILINJ_CMD_DELAY},
215 {{0x95, 0x70}, 1, 0},
216 {{0x71, 0x00}, 0, 0},
217 {{0x70, 0x08}, 0, JEILINJ_CMD_DELAY},
218 {{0x95, 0x70}, 1, 0},
219#define SPORTSCAM_DV15_CMD_SIZE 9
220 {{0x94, 0x02}, 0, 0},
221 {{0xde, 0x24}, 0, 0},
222 {{0x94, 0x02}, 0, 0},
223 {{0xdd, 0xf0}, 0, 0},
224 {{0x94, 0x02}, 0, 0},
225 {{0xe3, 0x2c}, 0, 0},
226 {{0x94, 0x02}, 0, 0},
227 {{0xe4, 0x00}, 0, 0},
228 {{0x94, 0x02}, 0, 0},
229 {{0xe5, 0x00}, 0, 0},
230 {{0x94, 0x02}, 0, 0},
231 {{0xe6, 0x2c}, 0, 0},
232 {{0x94, 0x03}, 0, 0},
233 {{0xaa, 0x00}, 0, 0}
234 };
235
236 sd->blocks_left = 0;
237
238
239
240 if (sd->type == SPORTSCAM_DV15)
241 start_commands_size = SPORTSCAM_DV15_CMD_SIZE;
242 else
243 start_commands_size = ARRAY_SIZE(start_commands);
244
245 for (i = 0; i < start_commands_size; i++) {
246 jlj_write2(gspca_dev, start_commands[i].instruction);
247 if (start_commands[i].delay)
248 msleep(start_commands[i].delay);
249 if (start_commands[i].ack_wanted)
250 jlj_read1(gspca_dev, &response);
251 }
252 setcamquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual));
253 msleep(2);
254 setfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->freq));
255 if (gspca_dev->usb_err < 0)
256 gspca_err(gspca_dev, "Start streaming command failed\n");
257 return gspca_dev->usb_err;
258}
259
260static void sd_pkt_scan(struct gspca_dev *gspca_dev,
261 u8 *data, int len)
262{
263 struct sd *sd = (struct sd *) gspca_dev;
264 int packet_type;
265 u32 header_marker;
266
267 gspca_dbg(gspca_dev, D_STREAM, "Got %d bytes out of %d for Block 0\n",
268 len, JEILINJ_MAX_TRANSFER);
269 if (len != JEILINJ_MAX_TRANSFER) {
270 gspca_dbg(gspca_dev, D_PACK, "bad length\n");
271 goto discard;
272 }
273
274 header_marker = ((u32 *)data)[0];
275 if (header_marker == FRAME_START) {
276 sd->blocks_left = data[0x0a] - 1;
277 gspca_dbg(gspca_dev, D_STREAM, "blocks_left = 0x%x\n",
278 sd->blocks_left);
279
280 gspca_frame_add(gspca_dev, FIRST_PACKET,
281 sd->jpeg_hdr, JPEG_HDR_SZ);
282
283 gspca_frame_add(gspca_dev, INTER_PACKET,
284 data + FRAME_HEADER_LEN,
285 JEILINJ_MAX_TRANSFER - FRAME_HEADER_LEN);
286 } else if (sd->blocks_left > 0) {
287 gspca_dbg(gspca_dev, D_STREAM, "%d blocks remaining for frame\n",
288 sd->blocks_left);
289 sd->blocks_left -= 1;
290 if (sd->blocks_left == 0)
291 packet_type = LAST_PACKET;
292 else
293 packet_type = INTER_PACKET;
294 gspca_frame_add(gspca_dev, packet_type,
295 data, JEILINJ_MAX_TRANSFER);
296 } else
297 goto discard;
298 return;
299discard:
300
301 gspca_dev->last_packet_type = DISCARD_PACKET;
302}
303
304
305static int sd_config(struct gspca_dev *gspca_dev,
306 const struct usb_device_id *id)
307{
308 struct cam *cam = &gspca_dev->cam;
309 struct sd *dev = (struct sd *) gspca_dev;
310
311 dev->type = id->driver_info;
312 dev->quality = QUALITY_DEF;
313
314 cam->cam_mode = jlj_mode;
315 cam->nmodes = ARRAY_SIZE(jlj_mode);
316 cam->bulk = 1;
317 cam->bulk_nurbs = 1;
318 cam->bulk_size = JEILINJ_MAX_TRANSFER;
319 return 0;
320}
321
322static void sd_stopN(struct gspca_dev *gspca_dev)
323{
324 int i;
325 u8 *buf;
326 static u8 stop_commands[][2] = {
327 {0x71, 0x00},
328 {0x70, 0x09},
329 {0x71, 0x80},
330 {0x70, 0x05}
331 };
332
333 for (;;) {
334
335 usb_bulk_msg(gspca_dev->dev,
336 gspca_dev->urb[0]->pipe,
337 gspca_dev->urb[0]->transfer_buffer,
338 JEILINJ_MAX_TRANSFER, NULL,
339 JEILINJ_DATA_TIMEOUT);
340
341
342 i = 0;
343 buf = gspca_dev->urb[0]->transfer_buffer;
344 while ((i < (JEILINJ_MAX_TRANSFER - 1)) &&
345 ((buf[i] != 0xff) || (buf[i+1] != 0xd9)))
346 i++;
347
348 if (i != (JEILINJ_MAX_TRANSFER - 1))
349
350 break;
351 }
352
353 for (i = 0; i < ARRAY_SIZE(stop_commands); i++)
354 jlj_write2(gspca_dev, stop_commands[i]);
355}
356
357
358static int sd_init(struct gspca_dev *gspca_dev)
359{
360 return gspca_dev->usb_err;
361}
362
363
364static int sd_start(struct gspca_dev *gspca_dev)
365{
366 struct sd *dev = (struct sd *) gspca_dev;
367
368
369 jpeg_define(dev->jpeg_hdr, gspca_dev->pixfmt.height,
370 gspca_dev->pixfmt.width,
371 0x21);
372 jpeg_set_qual(dev->jpeg_hdr, dev->quality);
373 gspca_dbg(gspca_dev, D_STREAM, "Start streaming at %dx%d\n",
374 gspca_dev->pixfmt.height, gspca_dev->pixfmt.width);
375 jlj_start(gspca_dev);
376 return gspca_dev->usb_err;
377}
378
379
380static const struct usb_device_id device_table[] = {
381 {USB_DEVICE(0x0979, 0x0280), .driver_info = SAKAR_57379},
382 {USB_DEVICE(0x0979, 0x0270), .driver_info = SPORTSCAM_DV15},
383 {}
384};
385
386MODULE_DEVICE_TABLE(usb, device_table);
387
388static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
389{
390 struct gspca_dev *gspca_dev =
391 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
392 struct sd *sd = (struct sd *)gspca_dev;
393
394 gspca_dev->usb_err = 0;
395
396 if (!gspca_dev->streaming)
397 return 0;
398
399 switch (ctrl->id) {
400 case V4L2_CID_POWER_LINE_FREQUENCY:
401 setfreq(gspca_dev, ctrl->val);
402 break;
403 case V4L2_CID_RED_BALANCE:
404 setred(gspca_dev, ctrl->val);
405 break;
406 case V4L2_CID_GAIN:
407 setgreen(gspca_dev, ctrl->val);
408 break;
409 case V4L2_CID_BLUE_BALANCE:
410 setblue(gspca_dev, ctrl->val);
411 break;
412 case V4L2_CID_AUTOGAIN:
413 setautogain(gspca_dev, ctrl->val);
414 break;
415 case V4L2_CID_JPEG_COMPRESSION_QUALITY:
416 jpeg_set_qual(sd->jpeg_hdr, ctrl->val);
417 setcamquality(gspca_dev, ctrl->val);
418 break;
419 }
420 return gspca_dev->usb_err;
421}
422
423static const struct v4l2_ctrl_ops sd_ctrl_ops = {
424 .s_ctrl = sd_s_ctrl,
425};
426
427static int sd_init_controls(struct gspca_dev *gspca_dev)
428{
429 struct sd *sd = (struct sd *)gspca_dev;
430 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
431 static const struct v4l2_ctrl_config custom_autogain = {
432 .ops = &sd_ctrl_ops,
433 .id = V4L2_CID_AUTOGAIN,
434 .type = V4L2_CTRL_TYPE_INTEGER,
435 .name = "Automatic Gain (and Exposure)",
436 .max = 3,
437 .step = 1,
438 .def = 0,
439 };
440
441 gspca_dev->vdev.ctrl_handler = hdl;
442 v4l2_ctrl_handler_init(hdl, 6);
443 sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
444 V4L2_CID_POWER_LINE_FREQUENCY,
445 V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1,
446 V4L2_CID_POWER_LINE_FREQUENCY_60HZ);
447 v4l2_ctrl_new_custom(hdl, &custom_autogain, NULL);
448 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
449 V4L2_CID_RED_BALANCE, 0, 3, 1, 2);
450 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
451 V4L2_CID_GAIN, 0, 3, 1, 2);
452 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
453 V4L2_CID_BLUE_BALANCE, 0, 3, 1, 2);
454 sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
455 V4L2_CID_JPEG_COMPRESSION_QUALITY,
456 QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF);
457
458 if (hdl->error) {
459 pr_err("Could not initialize controls\n");
460 return hdl->error;
461 }
462 return 0;
463}
464
465static int sd_set_jcomp(struct gspca_dev *gspca_dev,
466 const struct v4l2_jpegcompression *jcomp)
467{
468 struct sd *sd = (struct sd *) gspca_dev;
469
470 v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
471 return 0;
472}
473
474static int sd_get_jcomp(struct gspca_dev *gspca_dev,
475 struct v4l2_jpegcompression *jcomp)
476{
477 struct sd *sd = (struct sd *) gspca_dev;
478
479 memset(jcomp, 0, sizeof *jcomp);
480 jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
481 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
482 | V4L2_JPEG_MARKER_DQT;
483 return 0;
484}
485
486
487
488static const struct sd_desc sd_desc_sakar_57379 = {
489 .name = MODULE_NAME,
490 .config = sd_config,
491 .init = sd_init,
492 .start = sd_start,
493 .stopN = sd_stopN,
494 .pkt_scan = sd_pkt_scan,
495};
496
497
498static const struct sd_desc sd_desc_sportscam_dv15 = {
499 .name = MODULE_NAME,
500 .config = sd_config,
501 .init = sd_init,
502 .init_controls = sd_init_controls,
503 .start = sd_start,
504 .stopN = sd_stopN,
505 .pkt_scan = sd_pkt_scan,
506 .get_jcomp = sd_get_jcomp,
507 .set_jcomp = sd_set_jcomp,
508};
509
510static const struct sd_desc *sd_desc[2] = {
511 &sd_desc_sakar_57379,
512 &sd_desc_sportscam_dv15
513};
514
515
516static int sd_probe(struct usb_interface *intf,
517 const struct usb_device_id *id)
518{
519 return gspca_dev_probe(intf, id,
520 sd_desc[id->driver_info],
521 sizeof(struct sd),
522 THIS_MODULE);
523}
524
525static struct usb_driver sd_driver = {
526 .name = MODULE_NAME,
527 .id_table = device_table,
528 .probe = sd_probe,
529 .disconnect = gspca_disconnect,
530#ifdef CONFIG_PM
531 .suspend = gspca_suspend,
532 .resume = gspca_resume,
533 .reset_resume = gspca_resume,
534#endif
535};
536
537module_usb_driver(sd_driver);
538