v4l1-compat.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038
  1. /*
  2. * $Id: v4l1-compat.c,v 1.9 2005/06/12 04:19:19 mchehab Exp $
  3. *
  4. * Video for Linux Two
  5. * Backward Compatibility Layer
  6. *
  7. * Support subroutines for providing V4L2 drivers with backward
  8. * compatibility with applications using the old API.
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License
  12. * as published by the Free Software Foundation; either version
  13. * 2 of the License, or (at your option) any later version.
  14. *
  15. * Author: Bill Dirks <bdirks@pacbell.net>
  16. * et al.
  17. *
  18. */
  19. #include <linux/config.h>
  20. #include <linux/init.h>
  21. #include <linux/module.h>
  22. #include <linux/moduleparam.h>
  23. #include <linux/types.h>
  24. #include <linux/kernel.h>
  25. #include <linux/sched.h>
  26. #include <linux/smp_lock.h>
  27. #include <linux/mm.h>
  28. #include <linux/fs.h>
  29. #include <linux/file.h>
  30. #include <linux/string.h>
  31. #include <linux/errno.h>
  32. #include <linux/slab.h>
  33. #include <linux/videodev.h>
  34. #include <asm/uaccess.h>
  35. #include <asm/system.h>
  36. #include <asm/pgtable.h>
  37. #ifdef CONFIG_KMOD
  38. #include <linux/kmod.h>
  39. #endif
  40. static unsigned int debug = 0;
  41. module_param(debug, int, 0644);
  42. MODULE_PARM_DESC(debug,"enable debug messages");
  43. MODULE_AUTHOR("Bill Dirks");
  44. MODULE_DESCRIPTION("v4l(1) compatibility layer for v4l2 drivers.");
  45. MODULE_LICENSE("GPL");
  46. #define dprintk(fmt, arg...) if (debug) \
  47. printk(KERN_DEBUG "v4l1-compat: " fmt , ## arg)
  48. /*
  49. * I O C T L T R A N S L A T I O N
  50. *
  51. * From here on down is the code for translating the numerous
  52. * ioctl commands from the old API to the new API.
  53. */
  54. static int
  55. get_v4l_control(struct inode *inode,
  56. struct file *file,
  57. int cid,
  58. v4l2_kioctl drv)
  59. {
  60. struct v4l2_queryctrl qctrl2;
  61. struct v4l2_control ctrl2;
  62. int err;
  63. qctrl2.id = cid;
  64. err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);
  65. if (err < 0)
  66. dprintk("VIDIOC_QUERYCTRL: %d\n",err);
  67. if (err == 0 &&
  68. !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
  69. {
  70. ctrl2.id = qctrl2.id;
  71. err = drv(inode, file, VIDIOC_G_CTRL, &ctrl2);
  72. if (err < 0) {
  73. dprintk("VIDIOC_G_CTRL: %d\n",err);
  74. return 0;
  75. }
  76. return ((ctrl2.value - qctrl2.minimum) * 65535
  77. + (qctrl2.maximum - qctrl2.minimum) / 2)
  78. / (qctrl2.maximum - qctrl2.minimum);
  79. }
  80. return 0;
  81. }
  82. static int
  83. set_v4l_control(struct inode *inode,
  84. struct file *file,
  85. int cid,
  86. int value,
  87. v4l2_kioctl drv)
  88. {
  89. struct v4l2_queryctrl qctrl2;
  90. struct v4l2_control ctrl2;
  91. int err;
  92. qctrl2.id = cid;
  93. err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);
  94. if (err < 0)
  95. dprintk("VIDIOC_QUERYCTRL: %d\n",err);
  96. if (err == 0 &&
  97. !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED) &&
  98. !(qctrl2.flags & V4L2_CTRL_FLAG_GRABBED))
  99. {
  100. if (value < 0)
  101. value = 0;
  102. if (value > 65535)
  103. value = 65535;
  104. if (value && qctrl2.type == V4L2_CTRL_TYPE_BOOLEAN)
  105. value = 65535;
  106. ctrl2.id = qctrl2.id;
  107. ctrl2.value =
  108. (value * (qctrl2.maximum - qctrl2.minimum)
  109. + 32767)
  110. / 65535;
  111. ctrl2.value += qctrl2.minimum;
  112. err = drv(inode, file, VIDIOC_S_CTRL, &ctrl2);
  113. if (err < 0)
  114. dprintk("VIDIOC_S_CTRL: %d\n",err);
  115. }
  116. return 0;
  117. }
  118. /* ----------------------------------------------------------------- */
  119. static int palette2pixelformat[] = {
  120. [VIDEO_PALETTE_GREY] = V4L2_PIX_FMT_GREY,
  121. [VIDEO_PALETTE_RGB555] = V4L2_PIX_FMT_RGB555,
  122. [VIDEO_PALETTE_RGB565] = V4L2_PIX_FMT_RGB565,
  123. [VIDEO_PALETTE_RGB24] = V4L2_PIX_FMT_BGR24,
  124. [VIDEO_PALETTE_RGB32] = V4L2_PIX_FMT_BGR32,
  125. /* yuv packed pixel */
  126. [VIDEO_PALETTE_YUYV] = V4L2_PIX_FMT_YUYV,
  127. [VIDEO_PALETTE_YUV422] = V4L2_PIX_FMT_YUYV,
  128. [VIDEO_PALETTE_UYVY] = V4L2_PIX_FMT_UYVY,
  129. /* yuv planar */
  130. [VIDEO_PALETTE_YUV410P] = V4L2_PIX_FMT_YUV410,
  131. [VIDEO_PALETTE_YUV420] = V4L2_PIX_FMT_YUV420,
  132. [VIDEO_PALETTE_YUV420P] = V4L2_PIX_FMT_YUV420,
  133. [VIDEO_PALETTE_YUV411P] = V4L2_PIX_FMT_YUV411P,
  134. [VIDEO_PALETTE_YUV422P] = V4L2_PIX_FMT_YUV422P,
  135. };
  136. static unsigned int
  137. palette_to_pixelformat(unsigned int palette)
  138. {
  139. if (palette < ARRAY_SIZE(palette2pixelformat))
  140. return palette2pixelformat[palette];
  141. else
  142. return 0;
  143. }
  144. static unsigned int
  145. pixelformat_to_palette(int pixelformat)
  146. {
  147. int palette = 0;
  148. switch (pixelformat)
  149. {
  150. case V4L2_PIX_FMT_GREY:
  151. palette = VIDEO_PALETTE_GREY;
  152. break;
  153. case V4L2_PIX_FMT_RGB555:
  154. palette = VIDEO_PALETTE_RGB555;
  155. break;
  156. case V4L2_PIX_FMT_RGB565:
  157. palette = VIDEO_PALETTE_RGB565;
  158. break;
  159. case V4L2_PIX_FMT_BGR24:
  160. palette = VIDEO_PALETTE_RGB24;
  161. break;
  162. case V4L2_PIX_FMT_BGR32:
  163. palette = VIDEO_PALETTE_RGB32;
  164. break;
  165. /* yuv packed pixel */
  166. case V4L2_PIX_FMT_YUYV:
  167. palette = VIDEO_PALETTE_YUYV;
  168. break;
  169. case V4L2_PIX_FMT_UYVY:
  170. palette = VIDEO_PALETTE_UYVY;
  171. break;
  172. /* yuv planar */
  173. case V4L2_PIX_FMT_YUV410:
  174. palette = VIDEO_PALETTE_YUV420;
  175. break;
  176. case V4L2_PIX_FMT_YUV420:
  177. palette = VIDEO_PALETTE_YUV420;
  178. break;
  179. case V4L2_PIX_FMT_YUV411P:
  180. palette = VIDEO_PALETTE_YUV411P;
  181. break;
  182. case V4L2_PIX_FMT_YUV422P:
  183. palette = VIDEO_PALETTE_YUV422P;
  184. break;
  185. }
  186. return palette;
  187. }
  188. /* ----------------------------------------------------------------- */
  189. static int poll_one(struct file *file)
  190. {
  191. int retval = 1;
  192. poll_table *table;
  193. struct poll_wqueues pwq;
  194. poll_initwait(&pwq);
  195. table = &pwq.pt;
  196. for (;;) {
  197. int mask;
  198. set_current_state(TASK_INTERRUPTIBLE);
  199. mask = file->f_op->poll(file, table);
  200. if (mask & POLLIN)
  201. break;
  202. table = NULL;
  203. if (signal_pending(current)) {
  204. retval = -ERESTARTSYS;
  205. break;
  206. }
  207. schedule();
  208. }
  209. set_current_state(TASK_RUNNING);
  210. poll_freewait(&pwq);
  211. return retval;
  212. }
  213. static int count_inputs(struct inode *inode,
  214. struct file *file,
  215. v4l2_kioctl drv)
  216. {
  217. struct v4l2_input input2;
  218. int i;
  219. for (i = 0;; i++) {
  220. memset(&input2,0,sizeof(input2));
  221. input2.index = i;
  222. if (0 != drv(inode,file,VIDIOC_ENUMINPUT, &input2))
  223. break;
  224. }
  225. return i;
  226. }
  227. static int check_size(struct inode *inode,
  228. struct file *file,
  229. v4l2_kioctl drv,
  230. int *maxw, int *maxh)
  231. {
  232. struct v4l2_fmtdesc desc2;
  233. struct v4l2_format fmt2;
  234. memset(&desc2,0,sizeof(desc2));
  235. memset(&fmt2,0,sizeof(fmt2));
  236. desc2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  237. if (0 != drv(inode,file,VIDIOC_ENUM_FMT, &desc2))
  238. goto done;
  239. fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  240. fmt2.fmt.pix.width = 10000;
  241. fmt2.fmt.pix.height = 10000;
  242. fmt2.fmt.pix.pixelformat = desc2.pixelformat;
  243. if (0 != drv(inode,file,VIDIOC_TRY_FMT, &fmt2))
  244. goto done;
  245. *maxw = fmt2.fmt.pix.width;
  246. *maxh = fmt2.fmt.pix.height;
  247. done:
  248. return 0;
  249. }
  250. /* ----------------------------------------------------------------- */
  251. /*
  252. * This function is exported.
  253. */
  254. int
  255. v4l_compat_translate_ioctl(struct inode *inode,
  256. struct file *file,
  257. int cmd,
  258. void *arg,
  259. v4l2_kioctl drv)
  260. {
  261. struct v4l2_capability *cap2 = NULL;
  262. struct v4l2_format *fmt2 = NULL;
  263. enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  264. struct v4l2_framebuffer fbuf2;
  265. struct v4l2_input input2;
  266. struct v4l2_tuner tun2;
  267. struct v4l2_standard std2;
  268. struct v4l2_frequency freq2;
  269. struct v4l2_audio aud2;
  270. struct v4l2_queryctrl qctrl2;
  271. struct v4l2_buffer buf2;
  272. v4l2_std_id sid;
  273. int i, err = 0;
  274. switch (cmd) {
  275. case VIDIOCGCAP: /* capability */
  276. {
  277. struct video_capability *cap = arg;
  278. cap2 = kmalloc(sizeof(*cap2),GFP_KERNEL);
  279. memset(cap, 0, sizeof(*cap));
  280. memset(cap2, 0, sizeof(*cap2));
  281. memset(&fbuf2, 0, sizeof(fbuf2));
  282. err = drv(inode, file, VIDIOC_QUERYCAP, cap2);
  283. if (err < 0) {
  284. dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n",err);
  285. break;
  286. }
  287. if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) {
  288. err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
  289. if (err < 0) {
  290. dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n",err);
  291. memset(&fbuf2, 0, sizeof(fbuf2));
  292. }
  293. err = 0;
  294. }
  295. memcpy(cap->name, cap2->card,
  296. min(sizeof(cap->name), sizeof(cap2->card)));
  297. cap->name[sizeof(cap->name) - 1] = 0;
  298. if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE)
  299. cap->type |= VID_TYPE_CAPTURE;
  300. if (cap2->capabilities & V4L2_CAP_TUNER)
  301. cap->type |= VID_TYPE_TUNER;
  302. if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE)
  303. cap->type |= VID_TYPE_TELETEXT;
  304. if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY)
  305. cap->type |= VID_TYPE_OVERLAY;
  306. if (fbuf2.capability & V4L2_FBUF_CAP_LIST_CLIPPING)
  307. cap->type |= VID_TYPE_CLIPPING;
  308. cap->channels = count_inputs(inode,file,drv);
  309. check_size(inode,file,drv,
  310. &cap->maxwidth,&cap->maxheight);
  311. cap->audios = 0; /* FIXME */
  312. cap->minwidth = 48; /* FIXME */
  313. cap->minheight = 32; /* FIXME */
  314. break;
  315. }
  316. case VIDIOCGFBUF: /* get frame buffer */
  317. {
  318. struct video_buffer *buffer = arg;
  319. err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
  320. if (err < 0) {
  321. dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n",err);
  322. break;
  323. }
  324. buffer->base = fbuf2.base;
  325. buffer->height = fbuf2.fmt.height;
  326. buffer->width = fbuf2.fmt.width;
  327. switch (fbuf2.fmt.pixelformat) {
  328. case V4L2_PIX_FMT_RGB332:
  329. buffer->depth = 8;
  330. break;
  331. case V4L2_PIX_FMT_RGB555:
  332. buffer->depth = 15;
  333. break;
  334. case V4L2_PIX_FMT_RGB565:
  335. buffer->depth = 16;
  336. break;
  337. case V4L2_PIX_FMT_BGR24:
  338. buffer->depth = 24;
  339. break;
  340. case V4L2_PIX_FMT_BGR32:
  341. buffer->depth = 32;
  342. break;
  343. default:
  344. buffer->depth = 0;
  345. }
  346. if (0 != fbuf2.fmt.bytesperline)
  347. buffer->bytesperline = fbuf2.fmt.bytesperline;
  348. else {
  349. buffer->bytesperline =
  350. (buffer->width * buffer->depth + 7) & 7;
  351. buffer->bytesperline >>= 3;
  352. }
  353. break;
  354. }
  355. case VIDIOCSFBUF: /* set frame buffer */
  356. {
  357. struct video_buffer *buffer = arg;
  358. memset(&fbuf2, 0, sizeof(fbuf2));
  359. fbuf2.base = buffer->base;
  360. fbuf2.fmt.height = buffer->height;
  361. fbuf2.fmt.width = buffer->width;
  362. switch (buffer->depth) {
  363. case 8:
  364. fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB332;
  365. break;
  366. case 15:
  367. fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB555;
  368. break;
  369. case 16:
  370. fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
  371. break;
  372. case 24:
  373. fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR24;
  374. break;
  375. case 32:
  376. fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR32;
  377. break;
  378. }
  379. fbuf2.fmt.bytesperline = buffer->bytesperline;
  380. err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
  381. if (err < 0)
  382. dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n",err);
  383. break;
  384. }
  385. case VIDIOCGWIN: /* get window or capture dimensions */
  386. {
  387. struct video_window *win = arg;
  388. fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
  389. memset(win,0,sizeof(*win));
  390. memset(fmt2,0,sizeof(*fmt2));
  391. fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
  392. err = drv(inode, file, VIDIOC_G_FMT, fmt2);
  393. if (err < 0)
  394. dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n",err);
  395. if (err == 0) {
  396. win->x = fmt2->fmt.win.w.left;
  397. win->y = fmt2->fmt.win.w.top;
  398. win->width = fmt2->fmt.win.w.width;
  399. win->height = fmt2->fmt.win.w.height;
  400. win->chromakey = fmt2->fmt.win.chromakey;
  401. win->clips = NULL;
  402. win->clipcount = 0;
  403. break;
  404. }
  405. fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  406. err = drv(inode, file, VIDIOC_G_FMT, fmt2);
  407. if (err < 0) {
  408. dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n",err);
  409. break;
  410. }
  411. win->x = 0;
  412. win->y = 0;
  413. win->width = fmt2->fmt.pix.width;
  414. win->height = fmt2->fmt.pix.height;
  415. win->chromakey = 0;
  416. win->clips = NULL;
  417. win->clipcount = 0;
  418. break;
  419. }
  420. case VIDIOCSWIN: /* set window and/or capture dimensions */
  421. {
  422. struct video_window *win = arg;
  423. int err1,err2;
  424. fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
  425. memset(fmt2,0,sizeof(*fmt2));
  426. fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  427. drv(inode, file, VIDIOC_STREAMOFF, &fmt2->type);
  428. err1 = drv(inode, file, VIDIOC_G_FMT, fmt2);
  429. if (err1 < 0)
  430. dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n",err);
  431. if (err1 == 0) {
  432. fmt2->fmt.pix.width = win->width;
  433. fmt2->fmt.pix.height = win->height;
  434. fmt2->fmt.pix.field = V4L2_FIELD_ANY;
  435. fmt2->fmt.pix.bytesperline = 0;
  436. err = drv(inode, file, VIDIOC_S_FMT, fmt2);
  437. if (err < 0)
  438. dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n",
  439. err);
  440. win->width = fmt2->fmt.pix.width;
  441. win->height = fmt2->fmt.pix.height;
  442. }
  443. memset(fmt2,0,sizeof(*fmt2));
  444. fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
  445. fmt2->fmt.win.w.left = win->x;
  446. fmt2->fmt.win.w.top = win->y;
  447. fmt2->fmt.win.w.width = win->width;
  448. fmt2->fmt.win.w.height = win->height;
  449. fmt2->fmt.win.chromakey = win->chromakey;
  450. fmt2->fmt.win.clips = (void __user *)win->clips;
  451. fmt2->fmt.win.clipcount = win->clipcount;
  452. err2 = drv(inode, file, VIDIOC_S_FMT, fmt2);
  453. if (err2 < 0)
  454. dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n",err);
  455. if (err1 != 0 && err2 != 0)
  456. err = err1;
  457. break;
  458. }
  459. case VIDIOCCAPTURE: /* turn on/off preview */
  460. {
  461. int *on = arg;
  462. if (0 == *on) {
  463. /* dirty hack time. But v4l1 has no STREAMOFF
  464. * equivalent in the API, and this one at
  465. * least comes close ... */
  466. drv(inode, file, VIDIOC_STREAMOFF, &captype);
  467. }
  468. err = drv(inode, file, VIDIOC_OVERLAY, arg);
  469. if (err < 0)
  470. dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n",err);
  471. break;
  472. }
  473. case VIDIOCGCHAN: /* get input information */
  474. {
  475. struct video_channel *chan = arg;
  476. memset(&input2,0,sizeof(input2));
  477. input2.index = chan->channel;
  478. err = drv(inode, file, VIDIOC_ENUMINPUT, &input2);
  479. if (err < 0) {
  480. dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: "
  481. "channel=%d err=%d\n",chan->channel,err);
  482. break;
  483. }
  484. chan->channel = input2.index;
  485. memcpy(chan->name, input2.name,
  486. min(sizeof(chan->name), sizeof(input2.name)));
  487. chan->name[sizeof(chan->name) - 1] = 0;
  488. chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0;
  489. chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0;
  490. switch (input2.type) {
  491. case V4L2_INPUT_TYPE_TUNER:
  492. chan->type = VIDEO_TYPE_TV;
  493. break;
  494. default:
  495. case V4L2_INPUT_TYPE_CAMERA:
  496. chan->type = VIDEO_TYPE_CAMERA;
  497. break;
  498. }
  499. chan->norm = 0;
  500. err = drv(inode, file, VIDIOC_G_STD, &sid);
  501. if (err < 0)
  502. dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n",err);
  503. if (err == 0) {
  504. if (sid & V4L2_STD_PAL)
  505. chan->norm = VIDEO_MODE_PAL;
  506. if (sid & V4L2_STD_NTSC)
  507. chan->norm = VIDEO_MODE_NTSC;
  508. if (sid & V4L2_STD_SECAM)
  509. chan->norm = VIDEO_MODE_SECAM;
  510. }
  511. break;
  512. }
  513. case VIDIOCSCHAN: /* set input */
  514. {
  515. struct video_channel *chan = arg;
  516. sid = 0;
  517. err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel);
  518. if (err < 0)
  519. dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n",err);
  520. switch (chan->norm) {
  521. case VIDEO_MODE_PAL:
  522. sid = V4L2_STD_PAL;
  523. break;
  524. case VIDEO_MODE_NTSC:
  525. sid = V4L2_STD_NTSC;
  526. break;
  527. case VIDEO_MODE_SECAM:
  528. sid = V4L2_STD_SECAM;
  529. break;
  530. }
  531. if (0 != sid) {
  532. err = drv(inode, file, VIDIOC_S_STD, &sid);
  533. if (err < 0)
  534. dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n",err);
  535. }
  536. break;
  537. }
  538. case VIDIOCGPICT: /* get tone controls & partial capture format */
  539. {
  540. struct video_picture *pict = arg;
  541. pict->brightness = get_v4l_control(inode, file,
  542. V4L2_CID_BRIGHTNESS,drv);
  543. pict->hue = get_v4l_control(inode, file,
  544. V4L2_CID_HUE, drv);
  545. pict->contrast = get_v4l_control(inode, file,
  546. V4L2_CID_CONTRAST, drv);
  547. pict->colour = get_v4l_control(inode, file,
  548. V4L2_CID_SATURATION, drv);
  549. pict->whiteness = get_v4l_control(inode, file,
  550. V4L2_CID_WHITENESS, drv);
  551. fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
  552. memset(fmt2,0,sizeof(*fmt2));
  553. fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  554. err = drv(inode, file, VIDIOC_G_FMT, fmt2);
  555. if (err < 0) {
  556. dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n",err);
  557. break;
  558. }
  559. #if 0 /* FIXME */
  560. pict->depth = fmt2->fmt.pix.depth;
  561. #endif
  562. pict->palette = pixelformat_to_palette(
  563. fmt2->fmt.pix.pixelformat);
  564. break;
  565. }
  566. case VIDIOCSPICT: /* set tone controls & partial capture format */
  567. {
  568. struct video_picture *pict = arg;
  569. set_v4l_control(inode, file,
  570. V4L2_CID_BRIGHTNESS, pict->brightness, drv);
  571. set_v4l_control(inode, file,
  572. V4L2_CID_HUE, pict->hue, drv);
  573. set_v4l_control(inode, file,
  574. V4L2_CID_CONTRAST, pict->contrast, drv);
  575. set_v4l_control(inode, file,
  576. V4L2_CID_SATURATION, pict->colour, drv);
  577. set_v4l_control(inode, file,
  578. V4L2_CID_WHITENESS, pict->whiteness, drv);
  579. fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
  580. memset(fmt2,0,sizeof(*fmt2));
  581. fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  582. err = drv(inode, file, VIDIOC_G_FMT, fmt2);
  583. if (err < 0)
  584. dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n",err);
  585. if (fmt2->fmt.pix.pixelformat !=
  586. palette_to_pixelformat(pict->palette)) {
  587. fmt2->fmt.pix.pixelformat = palette_to_pixelformat(
  588. pict->palette);
  589. err = drv(inode, file, VIDIOC_S_FMT, fmt2);
  590. if (err < 0)
  591. dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",err);
  592. }
  593. err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
  594. if (err < 0)
  595. dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n",err);
  596. if (fbuf2.fmt.pixelformat !=
  597. palette_to_pixelformat(pict->palette)) {
  598. fbuf2.fmt.pixelformat = palette_to_pixelformat(
  599. pict->palette);
  600. err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
  601. if (err < 0)
  602. dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",err);
  603. err = 0; /* likely fails for non-root */
  604. }
  605. break;
  606. }
  607. case VIDIOCGTUNER: /* get tuner information */
  608. {
  609. struct video_tuner *tun = arg;
  610. memset(&tun2,0,sizeof(tun2));
  611. err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
  612. if (err < 0) {
  613. dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n",err);
  614. break;
  615. }
  616. memcpy(tun->name, tun2.name,
  617. min(sizeof(tun->name), sizeof(tun2.name)));
  618. tun->name[sizeof(tun->name) - 1] = 0;
  619. tun->rangelow = tun2.rangelow;
  620. tun->rangehigh = tun2.rangehigh;
  621. tun->flags = 0;
  622. tun->mode = VIDEO_MODE_AUTO;
  623. for (i = 0; i < 64; i++) {
  624. memset(&std2,0,sizeof(std2));
  625. std2.index = i;
  626. if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2))
  627. break;
  628. if (std2.id & V4L2_STD_PAL)
  629. tun->flags |= VIDEO_TUNER_PAL;
  630. if (std2.id & V4L2_STD_NTSC)
  631. tun->flags |= VIDEO_TUNER_NTSC;
  632. if (std2.id & V4L2_STD_SECAM)
  633. tun->flags |= VIDEO_TUNER_SECAM;
  634. }
  635. err = drv(inode, file, VIDIOC_G_STD, &sid);
  636. if (err < 0)
  637. dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n",err);
  638. if (err == 0) {
  639. if (sid & V4L2_STD_PAL)
  640. tun->mode = VIDEO_MODE_PAL;
  641. if (sid & V4L2_STD_NTSC)
  642. tun->mode = VIDEO_MODE_NTSC;
  643. if (sid & V4L2_STD_SECAM)
  644. tun->mode = VIDEO_MODE_SECAM;
  645. }
  646. if (tun2.capability & V4L2_TUNER_CAP_LOW)
  647. tun->flags |= VIDEO_TUNER_LOW;
  648. if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
  649. tun->flags |= VIDEO_TUNER_STEREO_ON;
  650. tun->signal = tun2.signal;
  651. break;
  652. }
  653. case VIDIOCSTUNER: /* select a tuner input */
  654. {
  655. #if 0 /* FIXME */
  656. err = drv(inode, file, VIDIOC_S_INPUT, &i);
  657. if (err < 0)
  658. dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err);
  659. #else
  660. err = 0;
  661. #endif
  662. break;
  663. }
  664. case VIDIOCGFREQ: /* get frequency */
  665. {
  666. int *freq = arg;
  667. freq2.tuner = 0;
  668. err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
  669. if (err < 0)
  670. dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n",err);
  671. if (0 == err)
  672. *freq = freq2.frequency;
  673. break;
  674. }
  675. case VIDIOCSFREQ: /* set frequency */
  676. {
  677. int *freq = arg;
  678. freq2.tuner = 0;
  679. drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
  680. freq2.frequency = *freq;
  681. err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2);
  682. if (err < 0)
  683. dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n",err);
  684. break;
  685. }
  686. case VIDIOCGAUDIO: /* get audio properties/controls */
  687. {
  688. struct video_audio *aud = arg;
  689. err = drv(inode, file, VIDIOC_G_AUDIO, &aud2);
  690. if (err < 0) {
  691. dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n",err);
  692. break;
  693. }
  694. memcpy(aud->name, aud2.name,
  695. min(sizeof(aud->name), sizeof(aud2.name)));
  696. aud->name[sizeof(aud->name) - 1] = 0;
  697. aud->audio = aud2.index;
  698. aud->flags = 0;
  699. i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv);
  700. if (i >= 0) {
  701. aud->volume = i;
  702. aud->flags |= VIDEO_AUDIO_VOLUME;
  703. }
  704. i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv);
  705. if (i >= 0) {
  706. aud->bass = i;
  707. aud->flags |= VIDEO_AUDIO_BASS;
  708. }
  709. i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv);
  710. if (i >= 0) {
  711. aud->treble = i;
  712. aud->flags |= VIDEO_AUDIO_TREBLE;
  713. }
  714. i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv);
  715. if (i >= 0) {
  716. aud->balance = i;
  717. aud->flags |= VIDEO_AUDIO_BALANCE;
  718. }
  719. i = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv);
  720. if (i >= 0) {
  721. if (i)
  722. aud->flags |= VIDEO_AUDIO_MUTE;
  723. aud->flags |= VIDEO_AUDIO_MUTABLE;
  724. }
  725. aud->step = 1;
  726. qctrl2.id = V4L2_CID_AUDIO_VOLUME;
  727. if (drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2) == 0 &&
  728. !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
  729. aud->step = qctrl2.step;
  730. aud->mode = 0;
  731. memset(&tun2,0,sizeof(tun2));
  732. err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
  733. if (err < 0) {
  734. dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n",err);
  735. err = 0;
  736. break;
  737. }
  738. if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2)
  739. aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
  740. else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
  741. aud->mode = VIDEO_SOUND_STEREO;
  742. else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO)
  743. aud->mode = VIDEO_SOUND_MONO;
  744. break;
  745. }
  746. case VIDIOCSAUDIO: /* set audio controls */
  747. {
  748. struct video_audio *aud = arg;
  749. memset(&aud2,0,sizeof(aud2));
  750. memset(&tun2,0,sizeof(tun2));
  751. aud2.index = aud->audio;
  752. err = drv(inode, file, VIDIOC_S_AUDIO, &aud2);
  753. if (err < 0) {
  754. dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n",err);
  755. break;
  756. }
  757. set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME,
  758. aud->volume, drv);
  759. set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS,
  760. aud->bass, drv);
  761. set_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE,
  762. aud->treble, drv);
  763. set_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE,
  764. aud->balance, drv);
  765. set_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE,
  766. !!(aud->flags & VIDEO_AUDIO_MUTE), drv);
  767. err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
  768. if (err < 0)
  769. dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n",err);
  770. if (err == 0) {
  771. switch (aud->mode) {
  772. default:
  773. case VIDEO_SOUND_MONO:
  774. case VIDEO_SOUND_LANG1:
  775. tun2.audmode = V4L2_TUNER_MODE_MONO;
  776. break;
  777. case VIDEO_SOUND_STEREO:
  778. tun2.audmode = V4L2_TUNER_MODE_STEREO;
  779. break;
  780. case VIDEO_SOUND_LANG2:
  781. tun2.audmode = V4L2_TUNER_MODE_LANG2;
  782. break;
  783. }
  784. err = drv(inode, file, VIDIOC_S_TUNER, &tun2);
  785. if (err < 0)
  786. dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n",err);
  787. }
  788. err = 0;
  789. break;
  790. }
  791. #if 0
  792. case VIDIOCGMBUF:
  793. /* v4l2 drivers must implement that themself. The
  794. mmap() differences can't be translated fully
  795. transparent, thus there is no point to try that */
  796. #endif
  797. case VIDIOCMCAPTURE: /* capture a frame */
  798. {
  799. struct video_mmap *mm = arg;
  800. fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
  801. memset(&buf2,0,sizeof(buf2));
  802. memset(fmt2,0,sizeof(*fmt2));
  803. fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  804. err = drv(inode, file, VIDIOC_G_FMT, fmt2);
  805. if (err < 0) {
  806. dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n",err);
  807. break;
  808. }
  809. if (mm->width != fmt2->fmt.pix.width ||
  810. mm->height != fmt2->fmt.pix.height ||
  811. palette_to_pixelformat(mm->format) !=
  812. fmt2->fmt.pix.pixelformat)
  813. {/* New capture format... */
  814. fmt2->fmt.pix.width = mm->width;
  815. fmt2->fmt.pix.height = mm->height;
  816. fmt2->fmt.pix.pixelformat =
  817. palette_to_pixelformat(mm->format);
  818. fmt2->fmt.pix.field = V4L2_FIELD_ANY;
  819. fmt2->fmt.pix.bytesperline = 0;
  820. err = drv(inode, file, VIDIOC_S_FMT, fmt2);
  821. if (err < 0) {
  822. dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n",err);
  823. break;
  824. }
  825. }
  826. buf2.index = mm->frame;
  827. buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  828. err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
  829. if (err < 0) {
  830. dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n",err);
  831. break;
  832. }
  833. err = drv(inode, file, VIDIOC_QBUF, &buf2);
  834. if (err < 0) {
  835. dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n",err);
  836. break;
  837. }
  838. err = drv(inode, file, VIDIOC_STREAMON, &captype);
  839. if (err < 0)
  840. dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n",err);
  841. break;
  842. }
  843. case VIDIOCSYNC: /* wait for a frame */
  844. {
  845. int *i = arg;
  846. buf2.index = *i;
  847. buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  848. err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
  849. if (err < 0) {
  850. /* No such buffer */
  851. dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err);
  852. break;
  853. }
  854. if (!(buf2.flags & V4L2_BUF_FLAG_MAPPED)) {
  855. /* Buffer is not mapped */
  856. err = -EINVAL;
  857. break;
  858. }
  859. /* make sure capture actually runs so we don't block forever */
  860. err = drv(inode, file, VIDIOC_STREAMON, &captype);
  861. if (err < 0) {
  862. dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n",err);
  863. break;
  864. }
  865. /* Loop as long as the buffer is queued, but not done */
  866. while ((buf2.flags &
  867. (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))
  868. == V4L2_BUF_FLAG_QUEUED)
  869. {
  870. err = poll_one(file);
  871. if (err < 0 || /* error or sleep was interrupted */
  872. err == 0) /* timeout? Shouldn't occur. */
  873. break;
  874. err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
  875. if (err < 0)
  876. dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err);
  877. }
  878. if (!(buf2.flags & V4L2_BUF_FLAG_DONE)) /* not done */
  879. break;
  880. do {
  881. err = drv(inode, file, VIDIOC_DQBUF, &buf2);
  882. if (err < 0)
  883. dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n",err);
  884. } while (err == 0 && buf2.index != *i);
  885. break;
  886. }
  887. case VIDIOCGVBIFMT: /* query VBI data capture format */
  888. {
  889. struct vbi_format *fmt = arg;
  890. fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
  891. memset(fmt2, 0, sizeof(*fmt2));
  892. fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
  893. err = drv(inode, file, VIDIOC_G_FMT, fmt2);
  894. if (err < 0) {
  895. dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
  896. break;
  897. }
  898. memset(fmt, 0, sizeof(*fmt));
  899. fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line;
  900. fmt->sampling_rate = fmt2->fmt.vbi.sampling_rate;
  901. fmt->sample_format = VIDEO_PALETTE_RAW;
  902. fmt->start[0] = fmt2->fmt.vbi.start[0];
  903. fmt->count[0] = fmt2->fmt.vbi.count[0];
  904. fmt->start[1] = fmt2->fmt.vbi.start[1];
  905. fmt->count[1] = fmt2->fmt.vbi.count[1];
  906. fmt->flags = fmt2->fmt.vbi.flags & 0x03;
  907. break;
  908. }
  909. case VIDIOCSVBIFMT:
  910. {
  911. struct vbi_format *fmt = arg;
  912. fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
  913. memset(fmt2, 0, sizeof(*fmt2));
  914. fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
  915. fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line;
  916. fmt2->fmt.vbi.sampling_rate = fmt->sampling_rate;
  917. fmt2->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
  918. fmt2->fmt.vbi.start[0] = fmt->start[0];
  919. fmt2->fmt.vbi.count[0] = fmt->count[0];
  920. fmt2->fmt.vbi.start[1] = fmt->start[1];
  921. fmt2->fmt.vbi.count[1] = fmt->count[1];
  922. fmt2->fmt.vbi.flags = fmt->flags;
  923. err = drv(inode, file, VIDIOC_TRY_FMT, fmt2);
  924. if (err < 0) {
  925. dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err);
  926. break;
  927. }
  928. if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line ||
  929. fmt2->fmt.vbi.sampling_rate != fmt->sampling_rate ||
  930. VIDEO_PALETTE_RAW != fmt->sample_format ||
  931. fmt2->fmt.vbi.start[0] != fmt->start[0] ||
  932. fmt2->fmt.vbi.count[0] != fmt->count[0] ||
  933. fmt2->fmt.vbi.start[1] != fmt->start[1] ||
  934. fmt2->fmt.vbi.count[1] != fmt->count[1] ||
  935. fmt2->fmt.vbi.flags != fmt->flags) {
  936. err = -EINVAL;
  937. break;
  938. }
  939. err = drv(inode, file, VIDIOC_S_FMT, fmt2);
  940. if (err < 0)
  941. dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err);
  942. break;
  943. }
  944. default:
  945. err = -ENOIOCTLCMD;
  946. break;
  947. }
  948. if (cap2)
  949. kfree(cap2);
  950. if (fmt2)
  951. kfree(fmt2);
  952. return err;
  953. }
  954. EXPORT_SYMBOL(v4l_compat_translate_ioctl);
  955. /*
  956. * Local variables:
  957. * c-basic-offset: 8
  958. * End:
  959. */