pwc-ctrl.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:36k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* Driver for Philips webcam
  2.    Functions that send various control messages to the webcam, including
  3.    video modes.
  4.    (C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl)
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 2 of the License, or
  8.    (at your option) any later version.
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.    You should have received a copy of the GNU General Public License
  14.    along with this program; if not, write to the Free Software
  15.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  16. */
  17. /*
  18.    Changes
  19.    2001/08/03  Alvarado   Added methods for changing white balance and 
  20.                           red/green gains
  21.  */
  22. /* Control functions for the cam; brightness, contrast, video mode, etc. */
  23. #ifdef __KERNEL__
  24. #include <asm/uaccess.h> 
  25. #endif
  26. #include <asm/errno.h>
  27.  
  28. #include "pwc.h"
  29. #include "pwc-ioctl.h"
  30. #include "pwc-uncompress.h"
  31. /* Request types: video */
  32. #define SET_LUM_CTL 0x01
  33. #define GET_LUM_CTL 0x02
  34. #define SET_CHROM_CTL 0x03
  35. #define GET_CHROM_CTL 0x04
  36. #define SET_STATUS_CTL 0x05
  37. #define GET_STATUS_CTL 0x06
  38. #define SET_EP_STREAM_CTL 0x07
  39. #define GET_EP_STREAM_CTL 0x08
  40. /* Selectors for the Luminance controls [GS]ET_LUM_CTL */
  41. #define AGC_MODE_FORMATTER 0x2000
  42. #define PRESET_AGC_FORMATTER 0x2100
  43. #define SHUTTER_MODE_FORMATTER 0x2200
  44. #define PRESET_SHUTTER_FORMATTER 0x2300
  45. #define PRESET_CONTOUR_FORMATTER 0x2400
  46. #define AUTO_CONTOUR_FORMATTER 0x2500
  47. #define BACK_LIGHT_COMPENSATION_FORMATTER 0x2600
  48. #define CONTRAST_FORMATTER 0x2700
  49. #define DYNAMIC_NOISE_CONTROL_FORMATTER 0x2800
  50. #define FLICKERLESS_MODE_FORMATTER 0x2900
  51. #define AE_CONTROL_SPEED 0x2A00
  52. #define BRIGHTNESS_FORMATTER 0x2B00
  53. #define GAMMA_FORMATTER 0x2C00
  54. /* Selectors for the Chrominance controls [GS]ET_CHROM_CTL */
  55. #define WB_MODE_FORMATTER 0x1000
  56. #define AWB_CONTROL_SPEED_FORMATTER 0x1100
  57. #define AWB_CONTROL_DELAY_FORMATTER 0x1200
  58. #define PRESET_MANUAL_RED_GAIN_FORMATTER 0x1300
  59. #define PRESET_MANUAL_BLUE_GAIN_FORMATTER 0x1400
  60. #define COLOUR_MODE_FORMATTER 0x1500
  61. #define SATURATION_MODE_FORMATTER1 0x1600
  62. #define SATURATION_MODE_FORMATTER2 0x1700
  63. /* Selectors for the Status controls [GS]ET_STATUS_CTL */
  64. #define SAVE_USER_DEFAULTS_FORMATTER 0x0200
  65. #define RESTORE_USER_DEFAULTS_FORMATTER 0x0300
  66. #define RESTORE_FACTORY_DEFAULTS_FORMATTER 0x0400
  67. #define READ_AGC_FORMATTER 0x0500
  68. #define READ_SHUTTER_FORMATTER 0x0600
  69. #define READ_RED_GAIN_FORMATTER 0x0700
  70. #define READ_BLUE_GAIN_FORMATTER 0x0800
  71. #define SENSOR_TYPE_FORMATTER1 0x0C00
  72. #define READ_RAW_Y_MEAN_FORMATTER 0x3100
  73. #define SET_POWER_SAVE_MODE_FORMATTER 0x3200
  74. #define MIRROR_IMAGE_FORMATTER 0x3300
  75. #define LED_FORMATTER 0x3400
  76. #define SENSOR_TYPE_FORMATTER2 0x3700
  77. /* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
  78. #define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100
  79. static char *size2name[PSZ_MAX] =
  80. {
  81. "subQCIF",
  82. "QSIF",
  83. "QCIF",
  84. "SIF",
  85. "CIF",
  86. "VGA",
  87. };  
  88. /********/
  89. /* Entries for the Nala (645/646) camera; the Nala doesn't have compression 
  90.    preferences, so you either get compressed or non-compressed streams.
  91.    
  92.    An alternate value of 0 means this mode is not available at all.
  93.  */
  94. struct Nala_table_entry {
  95. char alternate; /* USB alternate setting */
  96. int compressed; /* Compressed yes/no */
  97. unsigned char mode[3]; /* precomputed mode table */
  98. };
  99. static struct Nala_table_entry Nala_table[PSZ_MAX][8] =
  100. {
  101. #include "pwc_nala.h"
  102. };
  103. /* This tables contains entries for the 675/680/690 (Timon) camera, with
  104.    4 different qualities (no compression, low, medium, high).
  105.    It lists the bandwidth requirements for said mode by its alternate interface 
  106.    number. An alternate of 0 means that the mode is unavailable.
  107.    
  108.    There are 6 * 4 * 4 entries: 
  109.      6 different resolutions subqcif, qsif, qcif, sif, cif, vga
  110.      6 framerates: 5, 10, 15, 20, 25, 30
  111.      4 compression modi: none, low, medium, high
  112.      
  113.    When an uncompressed mode is not available, the next available compressed mode 
  114.    will be choosen (unless the decompressor is absent). Sometimes there are only
  115.    1 or 2 compressed modes available; in that case entries are duplicated.
  116. */
  117. struct Timon_table_entry 
  118. {
  119. char alternate; /* USB alternate interface */
  120. unsigned short packetsize; /* Normal packet size */
  121. unsigned short bandlength; /* Bandlength when decompressing */
  122. unsigned char mode[13]; /* precomputed mode settings for cam */
  123. };
  124. static struct Timon_table_entry Timon_table[PSZ_MAX][6][4] = 
  125. {
  126. #include "pwc_timon.h"
  127. };
  128. /* Entries for the Kiara (730/740/750) camera */
  129. struct Kiara_table_entry
  130. {
  131. char alternate; /* USB alternate interface */
  132. unsigned short packetsize; /* Normal packet size */
  133. unsigned short bandlength; /* Bandlength when decompressing */
  134. unsigned char mode[12]; /* precomputed mode settings for cam */
  135. };
  136. static struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
  137. {
  138. #include "pwc_kiara.h"
  139. };
  140. /****************************************************************************/
  141. #define SendControlMsg(request, value, buflen) 
  142. usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 
  143. request, 
  144. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 
  145. value, 
  146. pdev->vcinterface, 
  147. &buf, buflen, HZ / 2)
  148. #define RecvControlMsg(request, value, buflen) 
  149. usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 
  150. request, 
  151. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 
  152. value, 
  153. pdev->vcinterface, 
  154. &buf, buflen, HZ / 2)
  155. #if PWC_DEBUG
  156. void pwc_hexdump(void *p, int len)
  157. {
  158. int i;
  159. unsigned char *s;
  160. char buf[100], *d;
  161. s = (unsigned char *)p;
  162. d = buf;
  163. *d = '';
  164. Debug("Doing hexdump @ %p, %d bytes.n", p, len);
  165. for (i = 0; i < len; i++) {
  166. d += sprintf(d, "%02X ", *s++);
  167. if ((i & 0xF) == 0xF) {
  168. Debug("%sn", buf);
  169. d = buf;
  170. *d = '';
  171. }
  172. }
  173. if ((i & 0xF) != 0)
  174. Debug("%sn", buf);
  175. }
  176. #endif
  177. static inline int send_video_command(struct usb_device *udev, int index, void *buf, int buflen)
  178. {
  179. return usb_control_msg(udev,
  180. usb_sndctrlpipe(udev, 0),
  181. SET_EP_STREAM_CTL,
  182. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  183. VIDEO_OUTPUT_CONTROL_FORMATTER,
  184. index,
  185. buf, buflen, HZ);
  186. }
  187. static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
  188. {
  189. unsigned char buf[3];
  190. int ret, fps;
  191. struct Nala_table_entry *pEntry;
  192. int frames2frames[31] = 
  193. { /* closest match of framerate */
  194.    0,  0,  0,  0,  4,  /*  0-4  */
  195.    5,  5,  7,  7, 10,  /*  5-9  */
  196.           10, 10, 12, 12, 15,  /* 10-14 */
  197.           15, 15, 15, 20, 20,  /* 15-19 */
  198.           20, 20, 20, 24, 24,  /* 20-24 */
  199.           24, 24, 24, 24, 24,  /* 25-29 */
  200.           24                   /* 30    */
  201. };
  202. int frames2table[31] = 
  203. { 0, 0, 0, 0, 0, /*  0-4  */
  204.   1, 1, 1, 2, 2, /*  5-9  */
  205.   3, 3, 4, 4, 4, /* 10-14 */
  206.   5, 5, 5, 5, 5, /* 15-19 */
  207.   6, 6, 6, 6, 7, /* 20-24 */
  208.   7, 7, 7, 7, 7, /* 25-29 */
  209.   7              /* 30    */
  210. };
  211. if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25)
  212. return -EINVAL;
  213. frames = frames2frames[frames];
  214. fps = frames2table[frames];
  215. pEntry = &Nala_table[size][fps];
  216. if (pEntry->alternate == 0)
  217. return -EINVAL;
  218. if (pEntry->compressed && pdev->decompressor == NULL)
  219. return -ENOENT; /* Not supported. */
  220. memcpy(buf, pEntry->mode, 3);
  221. ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
  222. if (ret < 0)
  223. return ret;
  224. if (pEntry->compressed && pdev->decompressor != NULL)
  225. pdev->decompressor->init(pdev->release, buf, pdev->decompress_data);
  226. /* Set various parameters */
  227. pdev->vframes = frames;
  228. pdev->vsize = size;
  229. pdev->valternate = pEntry->alternate;
  230. pdev->image = pwc_image_sizes[size];
  231. pdev->frame_size = (pdev->image.x * pdev->image.y * 3) / 2;
  232. if (pEntry->compressed) {
  233. if (pdev->release < 5) { /* 4 fold compression */
  234. pdev->vbandlength = 528;
  235. pdev->frame_size /= 4;
  236. }
  237. else {
  238. pdev->vbandlength = 704;
  239. pdev->frame_size /= 3;
  240. }
  241. }
  242. else
  243. pdev->vbandlength = 0;
  244. return 0;
  245. }
  246. static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
  247. {
  248. unsigned char buf[13];
  249. struct Timon_table_entry *pChoose;
  250. int ret, fps;
  251. if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
  252. return -EINVAL;
  253. if (size == PSZ_VGA && frames > 15)
  254. return -EINVAL;
  255. fps = (frames / 5) - 1;
  256. /* Find a supported framerate with progressively higher compression ratios
  257.    if the preferred ratio is not available.
  258. */
  259. pChoose = NULL;
  260. if (pdev->decompressor == NULL) {
  261. #if PWC_DEBUG
  262. Debug("Trying to find uncompressed mode.n");
  263. #endif
  264. pChoose = &Timon_table[size][fps][0];
  265. }
  266. else {
  267. while (compression <= 3) {
  268. pChoose = &Timon_table[size][fps][compression];
  269. if (pChoose->alternate != 0)
  270. break;
  271. compression++;
  272. }
  273. }
  274. if (pChoose == NULL || pChoose->alternate == 0)
  275. return -ENOENT; /* Not supported. */
  276. memcpy(buf, pChoose->mode, 13);
  277. if (snapshot)
  278. buf[0] |= 0x80;
  279. ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 13);
  280. if (ret < 0)
  281. return ret;
  282. if (pChoose->bandlength > 0)
  283. pdev->decompressor->init(pdev->release, buf, pdev->decompress_data);
  284. /* Set various parameters */
  285. pdev->vframes = frames;
  286. pdev->vsize = size;
  287. pdev->vsnapshot = snapshot;
  288. pdev->valternate = pChoose->alternate;
  289. pdev->image = pwc_image_sizes[size];
  290. pdev->vbandlength = pChoose->bandlength;
  291. if (pChoose->bandlength > 0) 
  292. pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4;
  293. else
  294. pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
  295. return 0;
  296. }
  297. static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
  298. {
  299. struct Kiara_table_entry *pChoose;
  300. int fps, ret;
  301. unsigned char buf[12];
  302. if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
  303. return -EINVAL;
  304. if (size == PSZ_VGA && frames > 15)
  305. return -EINVAL;
  306. fps = (frames / 5) - 1;
  307. /* Find a supported framerate with progressively higher compression ratios
  308.    if the preferred ratio is not available.
  309. */
  310. pChoose = NULL;
  311. if (pdev->decompressor == NULL) {
  312. #if PWC_DEBUG
  313. Debug("Trying to find uncompressed mode.n");
  314. #endif
  315. pChoose = &Kiara_table[size][fps][0];
  316. }
  317. else {
  318. while (compression <= 3) {
  319. pChoose = &Kiara_table[size][fps][compression];
  320. if (pChoose->alternate != 0)
  321. break;
  322. compression++;
  323. }
  324. }
  325. if (pChoose == NULL || pChoose->alternate == 0)
  326. return -ENOENT; /* Not supported. */
  327. /* usb_control_msg won't take staticly allocated arrays as argument?? */
  328. memcpy(buf, pChoose->mode, 12);
  329. if (snapshot)
  330. buf[0] |= 0x80;
  331. /* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */
  332. ret = send_video_command(pdev->udev, 4 /* pdev->vendpoint */, buf, 12);
  333. if (ret < 0)
  334. return ret;
  335. if (pChoose->bandlength > 0)
  336. pdev->decompressor->init(pdev->release, buf, pdev->decompress_data);
  337. /* All set and go */
  338. pdev->vframes = frames;
  339. pdev->vsize = size;
  340. pdev->vsnapshot = snapshot;
  341. pdev->valternate = pChoose->alternate;
  342. pdev->image = pwc_image_sizes[size];
  343. pdev->vbandlength = pChoose->bandlength;
  344. if (pChoose->bandlength > 0)
  345. pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4;
  346. else 
  347. pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
  348. pdev->frame_size += (pdev->frame_header_size + pdev->frame_trailer_size);
  349. return 0;
  350. }
  351. /**
  352.    @pdev: device structure
  353.    @width: viewport width
  354.    @height: viewport height
  355.    @frame: framerate, in fps
  356.    @compression: preferred compression ratio
  357.    @snapshot: snapshot mode or streaming
  358.  */
  359. int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot)
  360. {
  361. int ret, size;
  362. size = pwc_decode_size(pdev, width, height);
  363. if (size < 0) {
  364. Debug("Could not find suitable size.n");
  365. return -ERANGE;
  366. }
  367. ret = -EINVAL;
  368. switch(pdev->type) {
  369. case 645:
  370. case 646:
  371. ret = set_video_mode_Nala(pdev, size, frames);
  372. break;
  373. case 675:
  374. case 680:
  375. case 690:
  376. ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
  377. break;
  378. case 730:
  379. case 740:
  380. case 750:
  381. ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot);
  382. break;
  383. }
  384. if (ret < 0) {
  385. if (ret == -ENOENT)
  386. Info("Video mode %s@%d fps is only supported with the decompressor module (pwcx).n", size2name[size], frames);
  387. else {
  388. Err("Failed to set video mode %s@%d fps; return code = %dn", size2name[size], frames, ret);
  389. return ret;
  390. }
  391. }
  392. pdev->view.x = width;
  393. pdev->view.y = height;
  394. pwc_set_image_buffer_size(pdev);
  395. Trace(TRACE_SIZE, "Set viewport to %dx%d, image size is %dx%d, palette = %d.n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y, pdev->vpalette);
  396. return 0;
  397. }
  398. void pwc_set_image_buffer_size(struct pwc_device *pdev)
  399. {
  400. int factor, i, filler = 0;
  401. switch(pdev->vpalette) {
  402. case VIDEO_PALETTE_RGB32 | 0x80:
  403. case VIDEO_PALETTE_RGB32:
  404. factor = 16;
  405. filler = 0;
  406. break;
  407. case VIDEO_PALETTE_RGB24 | 0x80:
  408. case VIDEO_PALETTE_RGB24:
  409. factor = 12;
  410. filler = 0;
  411. break;
  412. case VIDEO_PALETTE_YUYV:
  413. case VIDEO_PALETTE_YUV422:
  414. factor = 8;
  415. filler = 128;
  416. break;
  417. case VIDEO_PALETTE_YUV420:
  418. case VIDEO_PALETTE_YUV420P:
  419. factor = 6;
  420. filler = 128;
  421. break;
  422. #if PWC_DEBUG
  423. case VIDEO_PALETTE_RAW:
  424. pdev->image.size = pdev->frame_size;
  425. pdev->view.size = pdev->frame_size;
  426. return;
  427. break;
  428. #endif
  429. default:
  430. factor = 0;
  431. break;
  432. }
  433. /* Set sizes in bytes */
  434. pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
  435. pdev->view.size  = pdev->view.x  * pdev->view.y  * factor / 4;
  436. /* Align offset, or you'll get some very weird results in
  437.    YUV420 mode... x must be multiple of 4 (to get the Y's in 
  438.    place), and y even (or you'll mixup U & V). This is less of a
  439.    problem for YUV420P.
  440.  */
  441. pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC;
  442. pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
  443. /* Fill buffers with gray or black */
  444. for (i = 0; i < MAX_IMAGES; i++) {
  445. if (pdev->image_ptr[i] != NULL)
  446. memset(pdev->image_ptr[i], filler, pdev->view.size);
  447. }
  448. }
  449. /* BRIGHTNESS */
  450. int pwc_get_brightness(struct pwc_device *pdev)
  451. {
  452. char buf;
  453. int ret;
  454. ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
  455. GET_LUM_CTL,
  456. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  457. BRIGHTNESS_FORMATTER,
  458. pdev->vcinterface,
  459. &buf, 1, HZ / 2);
  460. if (ret < 0)
  461. return ret;
  462. return buf << 9;
  463. }
  464. int pwc_set_brightness(struct pwc_device *pdev, int value)
  465. {
  466. char buf;
  467. if (value < 0)
  468. value = 0;
  469. if (value > 0xffff)
  470. value = 0xffff;
  471. buf = (value >> 9) & 0x7f;
  472. return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
  473. SET_LUM_CTL,
  474. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  475. BRIGHTNESS_FORMATTER,
  476. pdev->vcinterface,
  477. &buf, 1, HZ / 2);
  478. }
  479. /* CONTRAST */
  480. int pwc_get_contrast(struct pwc_device *pdev)
  481. {
  482. char buf;
  483. int ret;
  484. ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
  485. GET_LUM_CTL,
  486. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  487. CONTRAST_FORMATTER,
  488. pdev->vcinterface,
  489. &buf, 1, HZ / 2);
  490. if (ret < 0)
  491. return ret;
  492. return buf << 10;
  493. }
  494. int pwc_set_contrast(struct pwc_device *pdev, int value)
  495. {
  496. char buf;
  497. if (value < 0)
  498. value = 0;
  499. if (value > 0xffff)
  500. value = 0xffff;
  501. buf = (value >> 10) & 0x3f;
  502. return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
  503. SET_LUM_CTL,
  504. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  505. CONTRAST_FORMATTER,
  506. pdev->vcinterface,
  507. &buf, 1, HZ / 2);
  508. }
  509. /* GAMMA */
  510. int pwc_get_gamma(struct pwc_device *pdev)
  511. {
  512. char buf;
  513. int ret;
  514. ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
  515. GET_LUM_CTL,
  516. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  517. GAMMA_FORMATTER,
  518. pdev->vcinterface,
  519. &buf, 1, HZ / 2);
  520. if (ret < 0)
  521. return ret;
  522. return buf << 11;
  523. }
  524. int pwc_set_gamma(struct pwc_device *pdev, int value)
  525. {
  526. char buf;
  527. if (value < 0)
  528. value = 0;
  529. if (value > 0xffff)
  530. value = 0xffff;
  531. buf = (value >> 11) & 0x1f;
  532. return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
  533. SET_LUM_CTL,
  534. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  535. GAMMA_FORMATTER,
  536. pdev->vcinterface,
  537. &buf, 1, HZ / 2);
  538. }
  539. /* SATURATION */
  540. int pwc_get_saturation(struct pwc_device *pdev)
  541. {
  542. char buf;
  543. int ret;
  544. if (pdev->type < 675)
  545. return -1;
  546. ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
  547. GET_CHROM_CTL,
  548. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  549. pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1,
  550. pdev->vcinterface,
  551. &buf, 1, HZ / 2);
  552. if (ret < 0)
  553. return ret;
  554. return 32768 + buf * 327;
  555. }
  556. int pwc_set_saturation(struct pwc_device *pdev, int value)
  557. {
  558. char buf;
  559. if (pdev->type < 675)
  560. return -EINVAL;
  561. if (value < 0)
  562. value = 0;
  563. if (value > 0xffff)
  564. value = 0xffff;
  565. /* saturation ranges from -100 to +100 */
  566. buf = (value - 32768) / 327;
  567. return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
  568. SET_CHROM_CTL,
  569. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  570. pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1,
  571. pdev->vcinterface,
  572. &buf, 1, HZ / 2);
  573. }
  574. /* AGC */
  575. static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
  576. {
  577. char buf;
  578. int ret;
  579. if (mode)
  580. buf = 0x0; /* auto */
  581. else
  582. buf = 0xff; /* fixed */
  583. ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
  584. SET_LUM_CTL,
  585. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  586. AGC_MODE_FORMATTER,
  587. pdev->vcinterface,
  588. &buf, 1, HZ / 2);
  589. if (!mode && ret >= 0) {
  590. if (value < 0)
  591. value = 0;
  592. if (value > 0xffff)
  593. value = 0xffff;
  594. buf = (value >> 10) & 0x3F;
  595. ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
  596. SET_LUM_CTL,
  597. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  598. PRESET_AGC_FORMATTER,
  599. pdev->vcinterface,
  600. &buf, 1, HZ / 2);
  601. }
  602. if (ret < 0)
  603. return ret;
  604. return 0;
  605. }
  606. static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
  607. {
  608. unsigned char buf;
  609. int ret;
  610. ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
  611. GET_LUM_CTL,
  612. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  613. AGC_MODE_FORMATTER,
  614. pdev->vcinterface,
  615. &buf, 1, HZ / 2);
  616. if (ret < 0)
  617. return ret;
  618. if (buf != 0) { /* fixed */
  619. ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
  620. GET_LUM_CTL,
  621. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  622. PRESET_AGC_FORMATTER,
  623. pdev->vcinterface,
  624. &buf, 1, HZ / 2);
  625. if (ret < 0)
  626. return ret;
  627. if (buf > 0x3F)
  628. buf = 0x3F;
  629. *value = (buf << 10);
  630. }
  631. else { /* auto */
  632. ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
  633. GET_STATUS_CTL,
  634. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  635. READ_AGC_FORMATTER,
  636. pdev->vcinterface,
  637. &buf, 1, HZ / 2);
  638. if (ret < 0)
  639. return ret;
  640. /* Gah... this value ranges from 0x00 ... 0x9F */
  641. if (buf > 0x9F)
  642. buf = 0x9F;
  643. *value = -(48 + buf * 409);
  644. }
  645. return 0;
  646. }
  647. static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value)
  648. {
  649. char buf[2];
  650. int speed, ret;
  651. if (mode)
  652. buf[0] = 0x0; /* auto */
  653. else
  654. buf[0] = 0xff; /* fixed */
  655. ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
  656. SET_LUM_CTL,
  657. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  658. SHUTTER_MODE_FORMATTER,
  659. pdev->vcinterface,
  660. buf, 1, HZ / 2);
  661. if (!mode && ret >= 0) {
  662. if (value < 0)
  663. value = 0;
  664. if (value > 0xffff)
  665. value = 0xffff;
  666. switch(pdev->type) {
  667. case 675:
  668. case 680:
  669. case 690:
  670. /* speed ranges from 0x0 to 0x290 (656) */
  671. speed = (value / 100);
  672. buf[1] = speed >> 8;
  673. buf[0] = speed & 0xff;
  674. break;
  675. case 730:
  676. case 740:
  677. case 750:
  678. /* speed seems to range from 0x0 to 0xff */
  679. buf[1] = 0;
  680. buf[0] = value >> 8;
  681. break;
  682. }
  683. ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
  684. SET_LUM_CTL,
  685. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  686. PRESET_SHUTTER_FORMATTER,
  687. pdev->vcinterface,
  688. &buf, 2, HZ / 2);
  689. }
  690. return ret;
  691. }
  692. /* POWER */
  693. int pwc_camera_power(struct pwc_device *pdev, int power)
  694. {
  695. char buf;
  696. if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6))
  697. return 0; /* Not supported by Nala or Timon < release 6 */
  698. if (power)
  699. buf = 0x00; /* active */
  700. else
  701. buf = 0xFF; /* power save */
  702. return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
  703. SET_STATUS_CTL,
  704. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  705. SET_POWER_SAVE_MODE_FORMATTER,
  706. pdev->vcinterface,
  707. &buf, 1, HZ / 2);
  708. }
  709. /* private calls */
  710. static inline int pwc_restore_user(struct pwc_device *pdev)
  711. {
  712. return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
  713. SET_STATUS_CTL,
  714. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  715. RESTORE_USER_DEFAULTS_FORMATTER,
  716. pdev->vcinterface,
  717. NULL, 0, HZ / 2);
  718. }
  719. static inline int pwc_save_user(struct pwc_device *pdev)
  720. {
  721. return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
  722. SET_STATUS_CTL,
  723. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  724. SAVE_USER_DEFAULTS_FORMATTER,
  725. pdev->vcinterface,
  726. NULL, 0, HZ / 2);
  727. }
  728. static inline int pwc_restore_factory(struct pwc_device *pdev)
  729. {
  730. return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
  731. SET_STATUS_CTL,
  732. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  733. RESTORE_FACTORY_DEFAULTS_FORMATTER,
  734. pdev->vcinterface,
  735. NULL, 0, HZ / 2);
  736. }
  737.  /* ************************************************* */
  738.  /* Patch by Alvarado: (not in the original version   */
  739.  /*
  740.   * the camera recognizes modes from 0 to 4:
  741.   *
  742.   * 00: indoor (incandescant lighting)
  743.   * 01: outdoor (sunlight)
  744.   * 02: fluorescent lighting
  745.   * 03: manual
  746.   * 04: auto
  747.   */ 
  748. static inline int pwc_set_awb(struct pwc_device *pdev, int mode)
  749. {
  750. char buf;
  751. int ret;
  752. if (mode < 0)
  753.     mode = 0;
  754. if (mode > 4)
  755.     mode = 4;
  756. buf = mode & 0x07; /* just the lowest three bits */
  757. ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
  758. SET_CHROM_CTL,
  759. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  760. WB_MODE_FORMATTER,
  761. pdev->vcinterface,
  762. &buf, 1, HZ / 2);
  763. if (ret < 0)
  764. return ret;
  765. return 0;
  766. }
  767. static inline int pwc_get_awb(struct pwc_device *pdev)
  768. {
  769. unsigned char buf;
  770. int ret;
  771. ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
  772. GET_CHROM_CTL,
  773. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  774. WB_MODE_FORMATTER,
  775. pdev->vcinterface,
  776. &buf, 1, HZ / 2);
  777. if (ret < 0) 
  778. return ret;
  779. return buf;
  780. }
  781. static inline int pwc_set_red_gain(struct pwc_device *pdev, int value)
  782. {
  783.         unsigned char buf;
  784. if (value < 0)
  785. value = 0;
  786. if (value > 0xffff)
  787. value = 0xffff;
  788. /* only the msb are considered */
  789. buf = value >> 8;
  790. return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
  791. SET_CHROM_CTL,
  792. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  793. PRESET_MANUAL_RED_GAIN_FORMATTER,
  794. pdev->vcinterface,
  795. &buf, 1, HZ / 2);
  796. }
  797. static inline int pwc_get_red_gain(struct pwc_device *pdev)
  798. {
  799. unsigned char buf;
  800. int ret;
  801. ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
  802.           GET_CHROM_CTL, 
  803. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  804.         PRESET_MANUAL_RED_GAIN_FORMATTER,
  805. pdev->vcinterface,
  806. &buf, 1, HZ / 2);
  807. if (ret < 0)
  808.     return ret;
  809. return (buf << 8);
  810. }
  811. static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value)
  812. {
  813. unsigned char buf;
  814. if (value < 0)
  815. value = 0;
  816. if (value > 0xffff)
  817. value = 0xffff;
  818. /* linear mapping of 0..0xffff to -0x80..0x7f */
  819. buf = (value >> 8);
  820. return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
  821. SET_CHROM_CTL,
  822. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  823. PRESET_MANUAL_BLUE_GAIN_FORMATTER,
  824. pdev->vcinterface,
  825. &buf, 1, HZ / 2);
  826. }
  827. static inline int pwc_get_blue_gain(struct pwc_device *pdev)
  828. {
  829. unsigned char buf;
  830. int ret;
  831. ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
  832.             GET_CHROM_CTL,
  833. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  834. PRESET_MANUAL_BLUE_GAIN_FORMATTER,
  835. pdev->vcinterface,
  836. &buf, 1, HZ / 2);
  837. if (ret < 0)
  838.     return ret;
  839. return (buf << 8);
  840. }
  841. /* The following two functions are different, since they only read the
  842.    internal red/blue gains, which may be different from the manual 
  843.    gains set or read above.
  844.  */   
  845. static inline int pwc_read_red_gain(struct pwc_device *pdev)
  846. {
  847. unsigned char buf;
  848. int ret;
  849. ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
  850.           GET_STATUS_CTL, 
  851. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  852.         READ_RED_GAIN_FORMATTER,
  853. pdev->vcinterface,
  854. &buf, 1, HZ / 2);
  855. if (ret < 0)
  856.     return ret;
  857. return (buf << 8);
  858. }
  859. static inline int pwc_read_blue_gain(struct pwc_device *pdev)
  860. {
  861. unsigned char buf;
  862. int ret;
  863. ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
  864.             GET_STATUS_CTL,
  865. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  866. READ_BLUE_GAIN_FORMATTER,
  867. pdev->vcinterface,
  868. &buf, 1, HZ / 2);
  869. if (ret < 0)
  870. return ret;
  871. return (buf << 8);
  872. }
  873. static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
  874. {
  875. unsigned char buf;
  876. /* useful range is 0x01..0x20 */
  877. buf = speed / 0x7f0;
  878. return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
  879. SET_CHROM_CTL,
  880. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  881. AWB_CONTROL_SPEED_FORMATTER,
  882. pdev->vcinterface,
  883. &buf, 1, HZ / 2);
  884. }
  885. static inline int pwc_get_wb_speed(struct pwc_device *pdev)
  886. {
  887. unsigned char buf;
  888. int ret;
  889. ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
  890. GET_CHROM_CTL,
  891. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  892. AWB_CONTROL_SPEED_FORMATTER,
  893. pdev->vcinterface,
  894. &buf, 1, HZ / 2);
  895. if (ret < 0)
  896. return ret;
  897. return (buf * 0x7f0);
  898. }
  899. static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
  900. {
  901. unsigned char buf;
  902. /* useful range is 0x01..0x3F */
  903. buf = (delay >> 10);
  904. return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
  905. SET_CHROM_CTL,
  906. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  907. AWB_CONTROL_DELAY_FORMATTER,
  908. pdev->vcinterface,
  909. &buf, 1, HZ / 2);
  910. }
  911. static inline int pwc_get_wb_delay(struct pwc_device *pdev)
  912. {
  913. unsigned char buf;
  914. int ret;
  915. ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
  916. GET_CHROM_CTL,
  917. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  918. AWB_CONTROL_DELAY_FORMATTER,
  919. pdev->vcinterface,
  920. &buf, 1, HZ / 2);
  921. if (ret < 0)
  922. return ret;
  923. return (buf << 10);
  924. }
  925. int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
  926. {
  927. unsigned char buf[2];
  928. if (pdev->type < 730)
  929. return 0;
  930. on_value /= 100;
  931. off_value /= 100;
  932. if (on_value < 0)
  933. on_value = 0;
  934. if (on_value > 0xff)
  935. on_value = 0xff;
  936. if (off_value < 0)
  937. off_value = 0;
  938. if (off_value > 0xff)
  939. off_value = 0xff;
  940. buf[0] = on_value;
  941. buf[1] = off_value;
  942. return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
  943. SET_STATUS_CTL,
  944. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  945. LED_FORMATTER,
  946. pdev->vcinterface,
  947. &buf, 2, HZ / 2);
  948. }
  949. int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
  950. {
  951. unsigned char buf[2];
  952. int ret;
  953. if (pdev->type < 730) {
  954. *on_value = -1;
  955. *off_value = -1;
  956. return 0;
  957. }
  958. ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
  959.             GET_STATUS_CTL,
  960. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  961. LED_FORMATTER,
  962. pdev->vcinterface,
  963. &buf, 2, HZ / 2);
  964. if (ret < 0)
  965. return ret;
  966. *on_value = buf[0] * 100;
  967. *off_value = buf[1] * 100;
  968. return 0;
  969. }
  970. static inline int pwc_set_contour(struct pwc_device *pdev, int contour)
  971. {
  972. unsigned char buf;
  973. int ret;
  974. if (contour < 0)
  975. buf = 0xff; /* auto contour on */
  976. else
  977. buf = 0x0; /* auto contour off */
  978. ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
  979. SET_LUM_CTL,
  980. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  981. AUTO_CONTOUR_FORMATTER,
  982. pdev->vcinterface,
  983. &buf, 1, HZ / 2);
  984. if (ret < 0)
  985. return ret;
  986. if (contour < 0)
  987. return 0;
  988. if (contour > 0xffff)
  989. contour = 0xffff;
  990. buf = (contour >> 10); /* contour preset is [0..3f] */
  991. ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
  992. SET_LUM_CTL,
  993. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  994. PRESET_CONTOUR_FORMATTER,
  995. pdev->vcinterface,
  996. &buf, 1, HZ / 2);
  997. if (ret < 0)
  998. return ret;
  999. return 0;
  1000. }
  1001. static inline int pwc_get_contour(struct pwc_device *pdev, int *contour)
  1002. {
  1003. unsigned char buf;
  1004. int ret;
  1005. ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
  1006. GET_LUM_CTL,
  1007. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  1008. AUTO_CONTOUR_FORMATTER,
  1009. pdev->vcinterface,
  1010. &buf, 1, HZ / 2);
  1011. if (ret < 0)
  1012. return ret;
  1013. if (buf == 0) {
  1014. /* auto mode off, query current preset value */
  1015. ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
  1016. GET_LUM_CTL,
  1017. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  1018. PRESET_CONTOUR_FORMATTER,
  1019. pdev->vcinterface,
  1020. &buf, 1, HZ / 2);
  1021. if (ret < 0)
  1022. return ret;
  1023. *contour =  (buf << 10);
  1024. }
  1025. else
  1026. *contour = -1;
  1027. return 0;
  1028. }
  1029. static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight)
  1030. {
  1031. unsigned char buf;
  1032. if (backlight)
  1033. buf = 0xff;
  1034. else
  1035. buf = 0x0;
  1036. return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
  1037. SET_LUM_CTL,
  1038. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  1039. BACK_LIGHT_COMPENSATION_FORMATTER,
  1040. pdev->vcinterface,
  1041. &buf, 1, HZ / 2);
  1042. }
  1043. static inline int pwc_get_backlight(struct pwc_device *pdev)
  1044. {
  1045. int ret;
  1046. unsigned char buf;
  1047. ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
  1048. GET_LUM_CTL,
  1049. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  1050. BACK_LIGHT_COMPENSATION_FORMATTER,
  1051. pdev->vcinterface,
  1052. &buf, 1, HZ / 2);
  1053. if (ret < 0)
  1054. return ret;
  1055. return buf;
  1056. }
  1057. static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker)
  1058. {
  1059. unsigned char buf;
  1060. if (flicker)
  1061. buf = 0xff;
  1062. else
  1063. buf = 0x0;
  1064. return SendControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
  1065. }
  1066. static inline int pwc_get_flicker(struct pwc_device *pdev)
  1067. {
  1068. int ret;
  1069. unsigned char buf;
  1070. ret = RecvControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
  1071. if (ret < 0)
  1072. return ret;
  1073. return buf;
  1074. }
  1075. static inline int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
  1076. {
  1077. unsigned char buf;
  1078. if (noise < 0)
  1079. noise = 0;
  1080. if (noise > 3)
  1081. noise = 3;
  1082. buf = noise;
  1083. return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
  1084. }
  1085. static inline int pwc_get_dynamic_noise(struct pwc_device *pdev)
  1086. {
  1087. int ret;
  1088. unsigned char buf;
  1089. ret = RecvControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
  1090. if (ret < 0)
  1091. return ret;
  1092. Debug("pwc_get_dynamic_noise = %dn", buf);
  1093. return buf;
  1094. }
  1095. int pwc_get_cmos_sensor(struct pwc_device *pdev)
  1096. {
  1097. unsigned char buf;
  1098. int ret = -1, request;
  1099. if (pdev->type < 675)
  1100. request = SENSOR_TYPE_FORMATTER1;
  1101. else if (pdev->type < 730)
  1102. return -1; /* The Vesta series doesn't have this call */
  1103. else
  1104. request = SENSOR_TYPE_FORMATTER2;
  1105. ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
  1106. GET_STATUS_CTL,
  1107. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  1108. request,
  1109. pdev->vcinterface,
  1110. &buf, 1, HZ / 2);
  1111. if (ret < 0)
  1112. return ret;
  1113. if (pdev->type < 675)
  1114. return buf | 0x100;
  1115. else
  1116. return buf;
  1117. }
  1118.  /* End of Add-Ons                                    */
  1119.  /* ************************************************* */
  1120. int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
  1121. {
  1122. int ret = 0;
  1123. switch(cmd) {
  1124. case VIDIOCPWCRUSER:
  1125. {
  1126. if (pwc_restore_user(pdev))
  1127. ret = -EINVAL;
  1128. break;
  1129. }
  1130. case VIDIOCPWCSUSER:
  1131. {
  1132. if (pwc_save_user(pdev))
  1133. ret = -EINVAL;
  1134. break;
  1135. }
  1136. case VIDIOCPWCFACTORY:
  1137. {
  1138. if (pwc_restore_factory(pdev))
  1139. ret = -EINVAL;
  1140. break;
  1141. }
  1142. case VIDIOCPWCSCQUAL:
  1143. {
  1144. int qual;
  1145. if (copy_from_user(&qual, arg, sizeof(int)))
  1146. ret = -EFAULT;
  1147. else {
  1148. if (qual < 0 || qual > 3)
  1149. ret = -EINVAL;
  1150. else
  1151. ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, qual, pdev->vsnapshot);
  1152. if (ret >= 0)
  1153. pdev->vcompression = qual;
  1154. }
  1155. break;
  1156. }
  1157. case VIDIOCPWCGCQUAL:
  1158. {
  1159. if (copy_to_user(arg, &pdev->vcompression, sizeof(int)))
  1160. ret = -EFAULT;
  1161. break;
  1162. }
  1163. case VIDIOCPWCPROBE:
  1164. {
  1165. struct pwc_probe probe;
  1166. strcpy(probe.name, pdev->vdev->name);
  1167. probe.type = pdev->type;
  1168. if (copy_to_user(arg, &probe, sizeof(probe)))
  1169. ret = -EFAULT;
  1170. break;
  1171. }
  1172. case VIDIOCPWCSAGC:
  1173. {
  1174. int agc;
  1175. if (copy_from_user(&agc, arg, sizeof(agc)))
  1176. ret = -EFAULT;
  1177. else {
  1178. if (pwc_set_agc(pdev, agc < 0 ? 1 : 0, agc))
  1179. ret = -EINVAL;
  1180. }
  1181. break;
  1182. }
  1183. case VIDIOCPWCGAGC:
  1184. {
  1185. int agc;
  1186. if (pwc_get_agc(pdev, &agc))
  1187. ret = -EINVAL;
  1188. else
  1189. if (copy_to_user(arg, &agc, sizeof(agc)))
  1190. ret = -EFAULT;
  1191. break;
  1192. }
  1193. case VIDIOCPWCSSHUTTER:
  1194. {
  1195. int shutter_speed;
  1196. if (copy_from_user(&shutter_speed, arg, sizeof(shutter_speed)))
  1197. ret = -EFAULT;
  1198. else
  1199. ret = pwc_set_shutter_speed(pdev, shutter_speed < 0 ? 1 : 0, shutter_speed);
  1200. break;
  1201. }
  1202.         case VIDIOCPWCSAWB:
  1203. {
  1204. struct pwc_whitebalance wb;
  1205. if (copy_from_user(&wb, arg, sizeof(wb)))
  1206. ret = -EFAULT;
  1207. else {
  1208. ret = pwc_set_awb(pdev, wb.mode);
  1209. if (ret >= 0 && wb.mode == PWC_WB_MANUAL) {
  1210. pwc_set_red_gain(pdev, wb.manual_red);
  1211. pwc_set_blue_gain(pdev, wb.manual_blue);
  1212. }
  1213. }
  1214. break;
  1215. }
  1216. case VIDIOCPWCGAWB:
  1217. {
  1218. struct pwc_whitebalance wb;
  1219. memset(&wb, 0, sizeof(wb));
  1220. wb.mode = pwc_get_awb(pdev);
  1221. if (wb.mode < 0)
  1222. ret = -EINVAL;
  1223. else {
  1224. if (wb.mode == PWC_WB_MANUAL) {
  1225. wb.manual_red = pwc_get_red_gain(pdev);
  1226. wb.manual_blue = pwc_get_blue_gain(pdev);
  1227. }
  1228. if (wb.mode == PWC_WB_AUTO) {
  1229. wb.read_red = pwc_read_red_gain(pdev);
  1230. wb.read_blue = pwc_read_blue_gain(pdev);
  1231. }
  1232. if (copy_to_user(arg, &wb, sizeof(wb)))
  1233. ret= -EFAULT;
  1234. }
  1235. break;
  1236. }
  1237. case VIDIOCPWCSAWBSPEED:
  1238. {
  1239. struct pwc_wb_speed wbs;
  1240. if (copy_from_user(&wbs, arg, sizeof(wbs)))
  1241. ret = -EFAULT;
  1242. else {
  1243. if (wbs.control_speed > 0) {
  1244. ret = pwc_set_wb_speed(pdev, wbs.control_speed);
  1245. }
  1246. if (wbs.control_delay > 0) {
  1247. ret = pwc_set_wb_delay(pdev, wbs.control_delay);
  1248. }
  1249. }
  1250. break;
  1251. }
  1252. case VIDIOCPWCGAWBSPEED:
  1253. {
  1254. struct pwc_wb_speed wbs;
  1255. ret = pwc_get_wb_speed(pdev);
  1256. if (ret < 0)
  1257. break;
  1258. wbs.control_speed = ret;
  1259. ret = pwc_get_wb_delay(pdev);
  1260. if (ret < 0)
  1261. break;
  1262. wbs.control_delay = ret;
  1263. if (copy_to_user(arg, &wbs, sizeof(wbs)))
  1264. ret = -EFAULT;
  1265. break;
  1266. }
  1267.         case VIDIOCPWCSLED:
  1268. {
  1269. struct pwc_leds leds;
  1270. if (copy_from_user(&leds, arg, sizeof(leds)))
  1271. ret = -EFAULT;
  1272. else
  1273. ret = pwc_set_leds(pdev, leds.led_on, leds.led_off);
  1274.      break;
  1275. }
  1276. case VIDIOCPWCGLED:
  1277. {
  1278. struct pwc_leds leds;
  1279. ret = pwc_get_leds(pdev, &leds.led_on, &leds.led_off); 
  1280. if (ret < 0)
  1281. break;
  1282. if (copy_to_user(arg, &leds, sizeof(leds)))
  1283. ret = -EFAULT;
  1284. break;
  1285. }
  1286. case VIDIOCPWCSCONTOUR:
  1287. {
  1288. int contour;
  1289. if (copy_from_user(&contour, arg, sizeof(contour)))
  1290. ret = -EFAULT;
  1291. else
  1292. ret = pwc_set_contour(pdev, contour);
  1293. break;
  1294. }
  1295. case VIDIOCPWCGCONTOUR:
  1296. {
  1297. int contour;
  1298. ret = pwc_get_contour(pdev, &contour);
  1299. if (ret < 0)
  1300. break;
  1301. if (copy_to_user(arg, &contour, sizeof(contour)))
  1302. ret = -EFAULT;
  1303. break;
  1304. }
  1305. case VIDIOCPWCSBACKLIGHT:
  1306. {
  1307. int backlight;
  1308. if (copy_from_user(&backlight, arg, sizeof(backlight)))
  1309. ret = -EFAULT;
  1310. else
  1311. ret = pwc_set_backlight(pdev, backlight);
  1312. break;
  1313. }
  1314. case VIDIOCPWCGBACKLIGHT:
  1315. {
  1316. ret = pwc_get_backlight(pdev);
  1317. if (ret < 0)
  1318. break;
  1319. if (copy_to_user(arg, &ret, sizeof(ret)))
  1320. ret = -EFAULT;
  1321. break;
  1322. }
  1323. case VIDIOCPWCSFLICKER:
  1324. {
  1325. int flicker;
  1326. if (copy_from_user(&flicker, arg, sizeof(flicker)))
  1327. ret = -EFAULT;
  1328. else
  1329. ret = pwc_set_flicker(pdev, flicker);
  1330. break;
  1331. }
  1332. case VIDIOCPWCGFLICKER:
  1333. {
  1334. ret = pwc_get_flicker(pdev);
  1335. if (ret < 0)
  1336. break;
  1337. if (copy_to_user(arg, &ret, sizeof(ret)))
  1338. ret = -EFAULT;
  1339. break;
  1340. }
  1341. case VIDIOCPWCSDYNNOISE:
  1342. {
  1343. int dynnoise;
  1344. if (copy_from_user(&dynnoise, arg, sizeof(dynnoise)))
  1345. ret = -EFAULT;
  1346. else
  1347. ret = pwc_set_dynamic_noise(pdev, dynnoise);
  1348. break;
  1349. }
  1350. case VIDIOCPWCGDYNNOISE:
  1351. {
  1352. ret = pwc_get_dynamic_noise(pdev);
  1353. if (ret < 0)
  1354. break;
  1355. if (copy_to_user(arg, &ret, sizeof(ret)))
  1356. ret = -EFAULT;
  1357. break;
  1358. }
  1359. default:
  1360. ret = -ENOIOCTLCMD;
  1361. break;
  1362. }
  1363. if (ret > 0)
  1364. return 0;
  1365. return ret;
  1366. }