This source file includes following definitions.
- recv_control_msg
- send_video_command
- send_control_msg
- set_video_mode_Nala
- set_video_mode_Timon
- set_video_mode_Kiara
- pwc_set_video_mode
- pwc_get_fps_Nala
- pwc_get_fps_Kiara
- pwc_get_fps_Timon
- pwc_get_fps
- pwc_get_u8_ctrl
- pwc_set_u8_ctrl
- pwc_get_s8_ctrl
- pwc_get_u16_ctrl
- pwc_set_u16_ctrl
- pwc_button_ctrl
- pwc_camera_power
- pwc_set_leds
- pwc_get_cmos_sensor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #ifdef __KERNEL__
30 #include <linux/uaccess.h>
31 #endif
32 #include <asm/errno.h>
33
34 #include "pwc.h"
35 #include "pwc-kiara.h"
36 #include "pwc-timon.h"
37 #include "pwc-dec1.h"
38 #include "pwc-dec23.h"
39
40
41 #define GET_STATUS_B00 0x0B00
42 #define SENSOR_TYPE_FORMATTER1 0x0C00
43 #define GET_STATUS_3000 0x3000
44 #define READ_RAW_Y_MEAN_FORMATTER 0x3100
45 #define SET_POWER_SAVE_MODE_FORMATTER 0x3200
46 #define MIRROR_IMAGE_FORMATTER 0x3300
47 #define LED_FORMATTER 0x3400
48 #define LOWLIGHT 0x3500
49 #define GET_STATUS_3600 0x3600
50 #define SENSOR_TYPE_FORMATTER2 0x3700
51 #define GET_STATUS_3800 0x3800
52 #define GET_STATUS_4000 0x4000
53 #define GET_STATUS_4100 0x4100
54 #define CTL_STATUS_4200 0x4200
55
56
57 #define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100
58
59 static const char *size2name[PSZ_MAX] =
60 {
61 "subQCIF",
62 "QSIF",
63 "QCIF",
64 "SIF",
65 "CIF",
66 "VGA",
67 };
68
69
70
71
72
73
74
75
76
77 #define PWC_FPS_MAX_NALA 8
78
79 struct Nala_table_entry {
80 char alternate;
81 int compressed;
82
83 unsigned char mode[3];
84 };
85
86 static unsigned int Nala_fps_vector[PWC_FPS_MAX_NALA] = { 4, 5, 7, 10, 12, 15, 20, 24 };
87
88 static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] =
89 {
90 #include "pwc-nala.h"
91 };
92
93
94
95 static int recv_control_msg(struct pwc_device *pdev,
96 u8 request, u16 value, int recv_count)
97 {
98 int rc;
99
100 rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
101 request,
102 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
103 value, pdev->vcinterface,
104 pdev->ctrl_buf, recv_count, USB_CTRL_GET_TIMEOUT);
105 if (rc < 0)
106 PWC_ERROR("recv_control_msg error %d req %02x val %04x\n",
107 rc, request, value);
108 return rc;
109 }
110
111 static inline int send_video_command(struct pwc_device *pdev,
112 int index, const unsigned char *buf, int buflen)
113 {
114 int rc;
115
116 memcpy(pdev->ctrl_buf, buf, buflen);
117
118 rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
119 SET_EP_STREAM_CTL,
120 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
121 VIDEO_OUTPUT_CONTROL_FORMATTER, index,
122 pdev->ctrl_buf, buflen, USB_CTRL_SET_TIMEOUT);
123 if (rc >= 0)
124 memcpy(pdev->cmd_buf, buf, buflen);
125 else
126 PWC_ERROR("send_video_command error %d\n", rc);
127
128 return rc;
129 }
130
131 int send_control_msg(struct pwc_device *pdev,
132 u8 request, u16 value, void *buf, int buflen)
133 {
134 return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
135 request,
136 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
137 value, pdev->vcinterface,
138 buf, buflen, USB_CTRL_SET_TIMEOUT);
139 }
140
141 static int set_video_mode_Nala(struct pwc_device *pdev, int size, int pixfmt,
142 int frames, int *compression, int send_to_cam)
143 {
144 int fps, ret = 0;
145 struct Nala_table_entry *pEntry;
146 int frames2frames[31] =
147 {
148 0, 0, 0, 0, 4,
149 5, 5, 7, 7, 10,
150 10, 10, 12, 12, 15,
151 15, 15, 15, 20, 20,
152 20, 20, 20, 24, 24,
153 24, 24, 24, 24, 24,
154 24
155 };
156 int frames2table[31] =
157 { 0, 0, 0, 0, 0,
158 1, 1, 1, 2, 2,
159 3, 3, 4, 4, 4,
160 5, 5, 5, 5, 5,
161 6, 6, 6, 6, 7,
162 7, 7, 7, 7, 7,
163 7
164 };
165
166 if (size < 0 || size > PSZ_CIF)
167 return -EINVAL;
168 if (frames < 4)
169 frames = 4;
170 else if (size > PSZ_QCIF && frames > 15)
171 frames = 15;
172 else if (frames > 25)
173 frames = 25;
174 frames = frames2frames[frames];
175 fps = frames2table[frames];
176 pEntry = &Nala_table[size][fps];
177 if (pEntry->alternate == 0)
178 return -EINVAL;
179
180 if (send_to_cam)
181 ret = send_video_command(pdev, pdev->vendpoint,
182 pEntry->mode, 3);
183 if (ret < 0)
184 return ret;
185
186 if (pEntry->compressed && pixfmt == V4L2_PIX_FMT_YUV420)
187 pwc_dec1_init(pdev, pEntry->mode);
188
189
190 pdev->pixfmt = pixfmt;
191 pdev->vframes = frames;
192 pdev->valternate = pEntry->alternate;
193 pdev->width = pwc_image_sizes[size][0];
194 pdev->height = pwc_image_sizes[size][1];
195 pdev->frame_size = (pdev->width * pdev->height * 3) / 2;
196 if (pEntry->compressed) {
197 if (pdev->release < 5) {
198 pdev->vbandlength = 528;
199 pdev->frame_size /= 4;
200 }
201 else {
202 pdev->vbandlength = 704;
203 pdev->frame_size /= 3;
204 }
205 }
206 else
207 pdev->vbandlength = 0;
208
209
210 *compression = 3;
211
212 return 0;
213 }
214
215
216 static int set_video_mode_Timon(struct pwc_device *pdev, int size, int pixfmt,
217 int frames, int *compression, int send_to_cam)
218 {
219 const struct Timon_table_entry *pChoose;
220 int fps, ret = 0;
221
222 if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
223 return -EINVAL;
224 if (frames < 5)
225 frames = 5;
226 else if (size == PSZ_VGA && frames > 15)
227 frames = 15;
228 else if (frames > 30)
229 frames = 30;
230 fps = (frames / 5) - 1;
231
232
233 do {
234 pChoose = &Timon_table[size][fps][*compression];
235 if (pChoose->alternate != 0)
236 break;
237 (*compression)++;
238 } while (*compression <= 3);
239
240 if (pChoose->alternate == 0)
241 return -ENOENT;
242
243 if (send_to_cam)
244 ret = send_video_command(pdev, pdev->vendpoint,
245 pChoose->mode, 13);
246 if (ret < 0)
247 return ret;
248
249 if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
250 pwc_dec23_init(pdev, pChoose->mode);
251
252
253 pdev->pixfmt = pixfmt;
254 pdev->vframes = (fps + 1) * 5;
255 pdev->valternate = pChoose->alternate;
256 pdev->width = pwc_image_sizes[size][0];
257 pdev->height = pwc_image_sizes[size][1];
258 pdev->vbandlength = pChoose->bandlength;
259 if (pChoose->bandlength > 0)
260 pdev->frame_size = (pChoose->bandlength * pdev->height) / 4;
261 else
262 pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
263 return 0;
264 }
265
266
267 static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int pixfmt,
268 int frames, int *compression, int send_to_cam)
269 {
270 const struct Kiara_table_entry *pChoose;
271 int fps, ret = 0;
272
273 if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
274 return -EINVAL;
275 if (frames < 5)
276 frames = 5;
277 else if (size == PSZ_VGA && frames > 15)
278 frames = 15;
279 else if (frames > 30)
280 frames = 30;
281 fps = (frames / 5) - 1;
282
283
284 do {
285 pChoose = &Kiara_table[size][fps][*compression];
286 if (pChoose->alternate != 0)
287 break;
288 (*compression)++;
289 } while (*compression <= 3);
290
291 if (pChoose->alternate == 0)
292 return -ENOENT;
293
294
295 if (send_to_cam)
296 ret = send_video_command(pdev, 4, pChoose->mode, 12);
297 if (ret < 0)
298 return ret;
299
300 if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
301 pwc_dec23_init(pdev, pChoose->mode);
302
303
304 pdev->pixfmt = pixfmt;
305 pdev->vframes = (fps + 1) * 5;
306 pdev->valternate = pChoose->alternate;
307 pdev->width = pwc_image_sizes[size][0];
308 pdev->height = pwc_image_sizes[size][1];
309 pdev->vbandlength = pChoose->bandlength;
310 if (pdev->vbandlength > 0)
311 pdev->frame_size = (pdev->vbandlength * pdev->height) / 4;
312 else
313 pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
314 PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vbandlength=%d\n",
315 pdev->frame_size, pdev->vframes, size, pdev->vbandlength);
316 return 0;
317 }
318
319 int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
320 int pixfmt, int frames, int *compression, int send_to_cam)
321 {
322 int ret, size;
323
324 PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n",
325 width, height, frames, pixfmt);
326 size = pwc_get_size(pdev, width, height);
327 PWC_TRACE("decode_size = %d.\n", size);
328
329 if (DEVICE_USE_CODEC1(pdev->type)) {
330 ret = set_video_mode_Nala(pdev, size, pixfmt, frames,
331 compression, send_to_cam);
332 } else if (DEVICE_USE_CODEC3(pdev->type)) {
333 ret = set_video_mode_Kiara(pdev, size, pixfmt, frames,
334 compression, send_to_cam);
335 } else {
336 ret = set_video_mode_Timon(pdev, size, pixfmt, frames,
337 compression, send_to_cam);
338 }
339 if (ret < 0) {
340 PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
341 return ret;
342 }
343 pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
344 PWC_DEBUG_SIZE("Set resolution to %dx%d\n", pdev->width, pdev->height);
345 return 0;
346 }
347
348 static unsigned int pwc_get_fps_Nala(struct pwc_device *pdev, unsigned int index, unsigned int size)
349 {
350 unsigned int i;
351
352 for (i = 0; i < PWC_FPS_MAX_NALA; i++) {
353 if (Nala_table[size][i].alternate) {
354 if (index--==0) return Nala_fps_vector[i];
355 }
356 }
357 return 0;
358 }
359
360 static unsigned int pwc_get_fps_Kiara(struct pwc_device *pdev, unsigned int index, unsigned int size)
361 {
362 unsigned int i;
363
364 for (i = 0; i < PWC_FPS_MAX_KIARA; i++) {
365 if (Kiara_table[size][i][3].alternate) {
366 if (index--==0) return Kiara_fps_vector[i];
367 }
368 }
369 return 0;
370 }
371
372 static unsigned int pwc_get_fps_Timon(struct pwc_device *pdev, unsigned int index, unsigned int size)
373 {
374 unsigned int i;
375
376 for (i=0; i < PWC_FPS_MAX_TIMON; i++) {
377 if (Timon_table[size][i][3].alternate) {
378 if (index--==0) return Timon_fps_vector[i];
379 }
380 }
381 return 0;
382 }
383
384 unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size)
385 {
386 unsigned int ret;
387
388 if (DEVICE_USE_CODEC1(pdev->type)) {
389 ret = pwc_get_fps_Nala(pdev, index, size);
390
391 } else if (DEVICE_USE_CODEC3(pdev->type)) {
392 ret = pwc_get_fps_Kiara(pdev, index, size);
393
394 } else {
395 ret = pwc_get_fps_Timon(pdev, index, size);
396 }
397
398 return ret;
399 }
400
401 int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
402 {
403 int ret;
404
405 ret = recv_control_msg(pdev, request, value, 1);
406 if (ret < 0)
407 return ret;
408
409 *data = pdev->ctrl_buf[0];
410 return 0;
411 }
412
413 int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data)
414 {
415 int ret;
416
417 pdev->ctrl_buf[0] = data;
418 ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 1);
419 if (ret < 0)
420 return ret;
421
422 return 0;
423 }
424
425 int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
426 {
427 int ret;
428
429 ret = recv_control_msg(pdev, request, value, 1);
430 if (ret < 0)
431 return ret;
432
433 *data = ((s8 *)pdev->ctrl_buf)[0];
434 return 0;
435 }
436
437 int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
438 {
439 int ret;
440
441 ret = recv_control_msg(pdev, request, value, 2);
442 if (ret < 0)
443 return ret;
444
445 *data = (pdev->ctrl_buf[1] << 8) | pdev->ctrl_buf[0];
446 return 0;
447 }
448
449 int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data)
450 {
451 int ret;
452
453 pdev->ctrl_buf[0] = data & 0xff;
454 pdev->ctrl_buf[1] = data >> 8;
455 ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 2);
456 if (ret < 0)
457 return ret;
458
459 return 0;
460 }
461
462 int pwc_button_ctrl(struct pwc_device *pdev, u16 value)
463 {
464 int ret;
465
466 ret = send_control_msg(pdev, SET_STATUS_CTL, value, NULL, 0);
467 if (ret < 0)
468 return ret;
469
470 return 0;
471 }
472
473
474 void pwc_camera_power(struct pwc_device *pdev, int power)
475 {
476 int r;
477
478 if (!pdev->power_save)
479 return;
480
481 if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6))
482 return;
483
484 if (power)
485 pdev->ctrl_buf[0] = 0x00;
486 else
487 pdev->ctrl_buf[0] = 0xFF;
488 r = send_control_msg(pdev, SET_STATUS_CTL,
489 SET_POWER_SAVE_MODE_FORMATTER, pdev->ctrl_buf, 1);
490 if (r < 0)
491 PWC_ERROR("Failed to power %s camera (%d)\n",
492 power ? "on" : "off", r);
493 }
494
495 int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
496 {
497 int r;
498
499 if (pdev->type < 730)
500 return 0;
501 on_value /= 100;
502 off_value /= 100;
503 if (on_value < 0)
504 on_value = 0;
505 if (on_value > 0xff)
506 on_value = 0xff;
507 if (off_value < 0)
508 off_value = 0;
509 if (off_value > 0xff)
510 off_value = 0xff;
511
512 pdev->ctrl_buf[0] = on_value;
513 pdev->ctrl_buf[1] = off_value;
514
515 r = send_control_msg(pdev,
516 SET_STATUS_CTL, LED_FORMATTER, pdev->ctrl_buf, 2);
517 if (r < 0)
518 PWC_ERROR("Failed to set LED on/off time (%d)\n", r);
519
520 return r;
521 }
522
523 #ifdef CONFIG_USB_PWC_DEBUG
524 int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
525 {
526 int ret = -1, request;
527
528 if (pdev->type < 675)
529 request = SENSOR_TYPE_FORMATTER1;
530 else if (pdev->type < 730)
531 return -1;
532 else
533 request = SENSOR_TYPE_FORMATTER2;
534
535 ret = recv_control_msg(pdev, GET_STATUS_CTL, request, 1);
536 if (ret < 0)
537 return ret;
538 if (pdev->type < 675)
539 *sensor = pdev->ctrl_buf[0] | 0x100;
540 else
541 *sensor = pdev->ctrl_buf[0];
542 return 0;
543 }
544 #endif