pvrusb2-v4l2.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242
  1. /*
  2. *
  3. * $Id$
  4. *
  5. * Copyright (C) 2005 Mike Isely <isely@pobox.com>
  6. * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. *
  21. */
  22. #include <linux/kernel.h>
  23. #include <linux/version.h>
  24. #include "pvrusb2-context.h"
  25. #include "pvrusb2-hdw.h"
  26. #include "pvrusb2.h"
  27. #include "pvrusb2-debug.h"
  28. #include "pvrusb2-v4l2.h"
  29. #include "pvrusb2-ioread.h"
  30. #include <linux/videodev2.h>
  31. #include <media/v4l2-dev.h>
  32. #include <media/v4l2-common.h>
  33. struct pvr2_v4l2_dev;
  34. struct pvr2_v4l2_fh;
  35. struct pvr2_v4l2;
  36. struct pvr2_v4l2_dev {
  37. struct video_device devbase; /* MUST be first! */
  38. struct pvr2_v4l2 *v4lp;
  39. struct pvr2_context_stream *stream;
  40. enum pvr2_config config;
  41. };
  42. struct pvr2_v4l2_fh {
  43. struct pvr2_channel channel;
  44. struct pvr2_v4l2_dev *dev_info;
  45. enum v4l2_priority prio;
  46. struct pvr2_ioread *rhp;
  47. struct file *file;
  48. struct pvr2_v4l2 *vhead;
  49. struct pvr2_v4l2_fh *vnext;
  50. struct pvr2_v4l2_fh *vprev;
  51. wait_queue_head_t wait_data;
  52. int fw_mode_flag;
  53. };
  54. struct pvr2_v4l2 {
  55. struct pvr2_channel channel;
  56. struct pvr2_v4l2_fh *vfirst;
  57. struct pvr2_v4l2_fh *vlast;
  58. struct v4l2_prio_state prio;
  59. /* streams - Note that these must be separately, individually,
  60. * allocated pointers. This is because the v4l core is going to
  61. * manage their deletion - separately, individually... */
  62. struct pvr2_v4l2_dev *dev_video;
  63. struct pvr2_v4l2_dev *dev_radio;
  64. };
  65. static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
  66. module_param_array(video_nr, int, NULL, 0444);
  67. MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor");
  68. static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
  69. module_param_array(radio_nr, int, NULL, 0444);
  70. MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor");
  71. static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
  72. module_param_array(vbi_nr, int, NULL, 0444);
  73. MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor");
  74. static struct v4l2_capability pvr_capability ={
  75. .driver = "pvrusb2",
  76. .card = "Hauppauge WinTV pvr-usb2",
  77. .bus_info = "usb",
  78. .version = KERNEL_VERSION(0,8,0),
  79. .capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
  80. V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
  81. V4L2_CAP_READWRITE),
  82. .reserved = {0,0,0,0}
  83. };
  84. static struct v4l2_tuner pvr_v4l2_tuners[]= {
  85. {
  86. .index = 0,
  87. .name = "TV Tuner",
  88. .type = V4L2_TUNER_ANALOG_TV,
  89. .capability = (V4L2_TUNER_CAP_NORM |
  90. V4L2_TUNER_CAP_STEREO |
  91. V4L2_TUNER_CAP_LANG1 |
  92. V4L2_TUNER_CAP_LANG2),
  93. .rangelow = 0,
  94. .rangehigh = 0,
  95. .rxsubchans = V4L2_TUNER_SUB_STEREO,
  96. .audmode = V4L2_TUNER_MODE_STEREO,
  97. .signal = 0,
  98. .afc = 0,
  99. .reserved = {0,0,0,0}
  100. }
  101. };
  102. static struct v4l2_fmtdesc pvr_fmtdesc [] = {
  103. {
  104. .index = 0,
  105. .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
  106. .flags = V4L2_FMT_FLAG_COMPRESSED,
  107. .description = "MPEG1/2",
  108. // This should really be V4L2_PIX_FMT_MPEG, but xawtv
  109. // breaks when I do that.
  110. .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
  111. .reserved = { 0, 0, 0, 0 }
  112. }
  113. };
  114. #define PVR_FORMAT_PIX 0
  115. #define PVR_FORMAT_VBI 1
  116. static struct v4l2_format pvr_format [] = {
  117. [PVR_FORMAT_PIX] = {
  118. .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
  119. .fmt = {
  120. .pix = {
  121. .width = 720,
  122. .height = 576,
  123. // This should really be V4L2_PIX_FMT_MPEG,
  124. // but xawtv breaks when I do that.
  125. .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
  126. .field = V4L2_FIELD_INTERLACED,
  127. .bytesperline = 0, // doesn't make sense
  128. // here
  129. //FIXME : Don't know what to put here...
  130. .sizeimage = (32*1024),
  131. .colorspace = 0, // doesn't make sense here
  132. .priv = 0
  133. }
  134. }
  135. },
  136. [PVR_FORMAT_VBI] = {
  137. .type = V4L2_BUF_TYPE_VBI_CAPTURE,
  138. .fmt = {
  139. .vbi = {
  140. .sampling_rate = 27000000,
  141. .offset = 248,
  142. .samples_per_line = 1443,
  143. .sample_format = V4L2_PIX_FMT_GREY,
  144. .start = { 0, 0 },
  145. .count = { 0, 0 },
  146. .flags = 0,
  147. .reserved = { 0, 0 }
  148. }
  149. }
  150. }
  151. };
  152. /*
  153. * pvr_ioctl()
  154. *
  155. * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
  156. *
  157. */
  158. static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
  159. unsigned int cmd, void *arg)
  160. {
  161. struct pvr2_v4l2_fh *fh = file->private_data;
  162. struct pvr2_v4l2 *vp = fh->vhead;
  163. struct pvr2_v4l2_dev *dev_info = fh->dev_info;
  164. struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
  165. int ret = -EINVAL;
  166. if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
  167. v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),cmd);
  168. }
  169. if (!pvr2_hdw_dev_ok(hdw)) {
  170. pvr2_trace(PVR2_TRACE_ERROR_LEGS,
  171. "ioctl failed - bad or no context");
  172. return -EFAULT;
  173. }
  174. /* check priority */
  175. switch (cmd) {
  176. case VIDIOC_S_CTRL:
  177. case VIDIOC_S_STD:
  178. case VIDIOC_S_INPUT:
  179. case VIDIOC_S_TUNER:
  180. case VIDIOC_S_FREQUENCY:
  181. ret = v4l2_prio_check(&vp->prio, &fh->prio);
  182. if (ret)
  183. return ret;
  184. }
  185. switch (cmd) {
  186. case VIDIOC_QUERYCAP:
  187. {
  188. struct v4l2_capability *cap = arg;
  189. memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
  190. ret = 0;
  191. break;
  192. }
  193. case VIDIOC_G_PRIORITY:
  194. {
  195. enum v4l2_priority *p = arg;
  196. *p = v4l2_prio_max(&vp->prio);
  197. ret = 0;
  198. break;
  199. }
  200. case VIDIOC_S_PRIORITY:
  201. {
  202. enum v4l2_priority *prio = arg;
  203. ret = v4l2_prio_change(&vp->prio, &fh->prio, *prio);
  204. break;
  205. }
  206. case VIDIOC_ENUMSTD:
  207. {
  208. struct v4l2_standard *vs = (struct v4l2_standard *)arg;
  209. int idx = vs->index;
  210. ret = pvr2_hdw_get_stdenum_value(hdw,vs,idx+1);
  211. break;
  212. }
  213. case VIDIOC_G_STD:
  214. {
  215. int val = 0;
  216. ret = pvr2_ctrl_get_value(
  217. pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val);
  218. *(v4l2_std_id *)arg = val;
  219. break;
  220. }
  221. case VIDIOC_S_STD:
  222. {
  223. ret = pvr2_ctrl_set_value(
  224. pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),
  225. *(v4l2_std_id *)arg);
  226. break;
  227. }
  228. case VIDIOC_ENUMINPUT:
  229. {
  230. struct pvr2_ctrl *cptr;
  231. struct v4l2_input *vi = (struct v4l2_input *)arg;
  232. struct v4l2_input tmp;
  233. unsigned int cnt;
  234. cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
  235. memset(&tmp,0,sizeof(tmp));
  236. tmp.index = vi->index;
  237. ret = 0;
  238. switch (vi->index) {
  239. case PVR2_CVAL_INPUT_TV:
  240. case PVR2_CVAL_INPUT_RADIO:
  241. tmp.type = V4L2_INPUT_TYPE_TUNER;
  242. break;
  243. case PVR2_CVAL_INPUT_SVIDEO:
  244. case PVR2_CVAL_INPUT_COMPOSITE:
  245. tmp.type = V4L2_INPUT_TYPE_CAMERA;
  246. break;
  247. default:
  248. ret = -EINVAL;
  249. break;
  250. }
  251. if (ret < 0) break;
  252. cnt = 0;
  253. pvr2_ctrl_get_valname(cptr,vi->index,
  254. tmp.name,sizeof(tmp.name)-1,&cnt);
  255. tmp.name[cnt] = 0;
  256. /* Don't bother with audioset, since this driver currently
  257. always switches the audio whenever the video is
  258. switched. */
  259. /* Handling std is a tougher problem. It doesn't make
  260. sense in cases where a device might be multi-standard.
  261. We could just copy out the current value for the
  262. standard, but it can change over time. For now just
  263. leave it zero. */
  264. memcpy(vi, &tmp, sizeof(tmp));
  265. ret = 0;
  266. break;
  267. }
  268. case VIDIOC_G_INPUT:
  269. {
  270. struct pvr2_ctrl *cptr;
  271. struct v4l2_input *vi = (struct v4l2_input *)arg;
  272. int val;
  273. cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
  274. val = 0;
  275. ret = pvr2_ctrl_get_value(cptr,&val);
  276. vi->index = val;
  277. break;
  278. }
  279. case VIDIOC_S_INPUT:
  280. {
  281. struct v4l2_input *vi = (struct v4l2_input *)arg;
  282. ret = pvr2_ctrl_set_value(
  283. pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
  284. vi->index);
  285. break;
  286. }
  287. case VIDIOC_ENUMAUDIO:
  288. {
  289. ret = -EINVAL;
  290. break;
  291. }
  292. case VIDIOC_G_AUDIO:
  293. {
  294. ret = -EINVAL;
  295. break;
  296. }
  297. case VIDIOC_S_AUDIO:
  298. {
  299. ret = -EINVAL;
  300. break;
  301. }
  302. case VIDIOC_G_TUNER:
  303. {
  304. struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
  305. unsigned int status_mask;
  306. int val;
  307. if (vt->index !=0) break;
  308. status_mask = pvr2_hdw_get_signal_status(hdw);
  309. memcpy(vt, &pvr_v4l2_tuners[vt->index],
  310. sizeof(struct v4l2_tuner));
  311. vt->signal = 0;
  312. if (status_mask & PVR2_SIGNAL_OK) {
  313. if (status_mask & PVR2_SIGNAL_STEREO) {
  314. vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
  315. } else {
  316. vt->rxsubchans = V4L2_TUNER_SUB_MONO;
  317. }
  318. if (status_mask & PVR2_SIGNAL_SAP) {
  319. vt->rxsubchans |= (V4L2_TUNER_SUB_LANG1 |
  320. V4L2_TUNER_SUB_LANG2);
  321. }
  322. vt->signal = 65535;
  323. }
  324. val = 0;
  325. ret = pvr2_ctrl_get_value(
  326. pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
  327. &val);
  328. vt->audmode = val;
  329. break;
  330. }
  331. case VIDIOC_S_TUNER:
  332. {
  333. struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
  334. if (vt->index != 0)
  335. break;
  336. ret = pvr2_ctrl_set_value(
  337. pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
  338. vt->audmode);
  339. }
  340. case VIDIOC_S_FREQUENCY:
  341. {
  342. const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
  343. ret = pvr2_ctrl_set_value(
  344. pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
  345. vf->frequency * 62500);
  346. break;
  347. }
  348. case VIDIOC_G_FREQUENCY:
  349. {
  350. struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
  351. int val = 0;
  352. ret = pvr2_ctrl_get_value(
  353. pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
  354. &val);
  355. val /= 62500;
  356. vf->frequency = val;
  357. break;
  358. }
  359. case VIDIOC_ENUM_FMT:
  360. {
  361. struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg;
  362. /* Only one format is supported : mpeg.*/
  363. if (fd->index != 0)
  364. break;
  365. memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
  366. ret = 0;
  367. break;
  368. }
  369. case VIDIOC_G_FMT:
  370. {
  371. struct v4l2_format *vf = (struct v4l2_format *)arg;
  372. int val;
  373. switch(vf->type) {
  374. case V4L2_BUF_TYPE_VIDEO_CAPTURE:
  375. memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
  376. sizeof(struct v4l2_format));
  377. val = 0;
  378. pvr2_ctrl_get_value(
  379. pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES),
  380. &val);
  381. vf->fmt.pix.width = val;
  382. val = 0;
  383. pvr2_ctrl_get_value(
  384. pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
  385. &val);
  386. vf->fmt.pix.height = val;
  387. ret = 0;
  388. break;
  389. case V4L2_BUF_TYPE_VBI_CAPTURE:
  390. // ????? Still need to figure out to do VBI correctly
  391. ret = -EINVAL;
  392. break;
  393. default:
  394. ret = -EINVAL;
  395. break;
  396. }
  397. break;
  398. }
  399. case VIDIOC_TRY_FMT:
  400. case VIDIOC_S_FMT:
  401. {
  402. struct v4l2_format *vf = (struct v4l2_format *)arg;
  403. ret = 0;
  404. switch(vf->type) {
  405. case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
  406. int lmin,lmax;
  407. struct pvr2_ctrl *hcp,*vcp;
  408. int h = vf->fmt.pix.height;
  409. int w = vf->fmt.pix.width;
  410. hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES);
  411. vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES);
  412. lmin = pvr2_ctrl_get_min(hcp);
  413. lmax = pvr2_ctrl_get_max(hcp);
  414. if (w < lmin) {
  415. w = lmin;
  416. } else if (w > lmax) {
  417. w = lmax;
  418. }
  419. lmin = pvr2_ctrl_get_min(vcp);
  420. lmax = pvr2_ctrl_get_max(vcp);
  421. if (h < lmin) {
  422. h = lmin;
  423. } else if (h > lmax) {
  424. h = lmax;
  425. }
  426. memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
  427. sizeof(struct v4l2_format));
  428. vf->fmt.pix.width = w;
  429. vf->fmt.pix.height = h;
  430. if (cmd == VIDIOC_S_FMT) {
  431. pvr2_ctrl_set_value(hcp,vf->fmt.pix.width);
  432. pvr2_ctrl_set_value(vcp,vf->fmt.pix.height);
  433. }
  434. } break;
  435. case V4L2_BUF_TYPE_VBI_CAPTURE:
  436. // ????? Still need to figure out to do VBI correctly
  437. ret = -EINVAL;
  438. break;
  439. default:
  440. ret = -EINVAL;
  441. break;
  442. }
  443. break;
  444. }
  445. case VIDIOC_STREAMON:
  446. {
  447. ret = pvr2_hdw_set_stream_type(hdw,dev_info->config);
  448. if (ret < 0) return ret;
  449. ret = pvr2_hdw_set_streaming(hdw,!0);
  450. break;
  451. }
  452. case VIDIOC_STREAMOFF:
  453. {
  454. ret = pvr2_hdw_set_streaming(hdw,0);
  455. break;
  456. }
  457. case VIDIOC_QUERYCTRL:
  458. {
  459. struct pvr2_ctrl *cptr;
  460. struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
  461. ret = 0;
  462. if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
  463. cptr = pvr2_hdw_get_ctrl_nextv4l(
  464. hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
  465. if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
  466. } else {
  467. cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
  468. }
  469. if (!cptr) {
  470. pvr2_trace(PVR2_TRACE_V4LIOCTL,
  471. "QUERYCTRL id=0x%x not implemented here",
  472. vc->id);
  473. ret = -EINVAL;
  474. break;
  475. }
  476. pvr2_trace(PVR2_TRACE_V4LIOCTL,
  477. "QUERYCTRL id=0x%x mapping name=%s (%s)",
  478. vc->id,pvr2_ctrl_get_name(cptr),
  479. pvr2_ctrl_get_desc(cptr));
  480. strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
  481. vc->flags = pvr2_ctrl_get_v4lflags(cptr);
  482. vc->default_value = pvr2_ctrl_get_def(cptr);
  483. switch (pvr2_ctrl_get_type(cptr)) {
  484. case pvr2_ctl_enum:
  485. vc->type = V4L2_CTRL_TYPE_MENU;
  486. vc->minimum = 0;
  487. vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
  488. vc->step = 1;
  489. break;
  490. case pvr2_ctl_bool:
  491. vc->type = V4L2_CTRL_TYPE_BOOLEAN;
  492. vc->minimum = 0;
  493. vc->maximum = 1;
  494. vc->step = 1;
  495. break;
  496. case pvr2_ctl_int:
  497. vc->type = V4L2_CTRL_TYPE_INTEGER;
  498. vc->minimum = pvr2_ctrl_get_min(cptr);
  499. vc->maximum = pvr2_ctrl_get_max(cptr);
  500. vc->step = 1;
  501. break;
  502. default:
  503. pvr2_trace(PVR2_TRACE_V4LIOCTL,
  504. "QUERYCTRL id=0x%x name=%s not mappable",
  505. vc->id,pvr2_ctrl_get_name(cptr));
  506. ret = -EINVAL;
  507. break;
  508. }
  509. break;
  510. }
  511. case VIDIOC_QUERYMENU:
  512. {
  513. struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg;
  514. unsigned int cnt = 0;
  515. ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
  516. vm->index,
  517. vm->name,sizeof(vm->name)-1,
  518. &cnt);
  519. vm->name[cnt] = 0;
  520. break;
  521. }
  522. case VIDIOC_G_CTRL:
  523. {
  524. struct v4l2_control *vc = (struct v4l2_control *)arg;
  525. int val = 0;
  526. ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
  527. &val);
  528. vc->value = val;
  529. break;
  530. }
  531. case VIDIOC_S_CTRL:
  532. {
  533. struct v4l2_control *vc = (struct v4l2_control *)arg;
  534. ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
  535. vc->value);
  536. break;
  537. }
  538. case VIDIOC_G_EXT_CTRLS:
  539. {
  540. struct v4l2_ext_controls *ctls =
  541. (struct v4l2_ext_controls *)arg;
  542. struct v4l2_ext_control *ctrl;
  543. unsigned int idx;
  544. int val;
  545. for (idx = 0; idx < ctls->count; idx++) {
  546. ctrl = ctls->controls + idx;
  547. ret = pvr2_ctrl_get_value(
  548. pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val);
  549. if (ret) {
  550. ctls->error_idx = idx;
  551. break;
  552. }
  553. /* Ensure that if read as a 64 bit value, the user
  554. will still get a hopefully sane value */
  555. ctrl->value64 = 0;
  556. ctrl->value = val;
  557. }
  558. break;
  559. }
  560. case VIDIOC_S_EXT_CTRLS:
  561. {
  562. struct v4l2_ext_controls *ctls =
  563. (struct v4l2_ext_controls *)arg;
  564. struct v4l2_ext_control *ctrl;
  565. unsigned int idx;
  566. for (idx = 0; idx < ctls->count; idx++) {
  567. ctrl = ctls->controls + idx;
  568. ret = pvr2_ctrl_set_value(
  569. pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
  570. ctrl->value);
  571. if (ret) {
  572. ctls->error_idx = idx;
  573. break;
  574. }
  575. }
  576. break;
  577. }
  578. case VIDIOC_TRY_EXT_CTRLS:
  579. {
  580. struct v4l2_ext_controls *ctls =
  581. (struct v4l2_ext_controls *)arg;
  582. struct v4l2_ext_control *ctrl;
  583. struct pvr2_ctrl *pctl;
  584. unsigned int idx;
  585. /* For the moment just validate that the requested control
  586. actually exists. */
  587. for (idx = 0; idx < ctls->count; idx++) {
  588. ctrl = ctls->controls + idx;
  589. pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
  590. if (!pctl) {
  591. ret = -EINVAL;
  592. ctls->error_idx = idx;
  593. break;
  594. }
  595. }
  596. break;
  597. }
  598. case VIDIOC_LOG_STATUS:
  599. {
  600. pvr2_hdw_trigger_module_log(hdw);
  601. ret = 0;
  602. break;
  603. }
  604. #ifdef CONFIG_VIDEO_ADV_DEBUG
  605. case VIDIOC_INT_G_REGISTER:
  606. case VIDIOC_INT_S_REGISTER:
  607. {
  608. u32 val;
  609. struct v4l2_register *req = (struct v4l2_register *)arg;
  610. if (cmd == VIDIOC_INT_S_REGISTER) val = req->val;
  611. ret = pvr2_hdw_register_access(
  612. hdw,req->i2c_id,req->reg,
  613. cmd == VIDIOC_INT_S_REGISTER,&val);
  614. if (cmd == VIDIOC_INT_G_REGISTER) req->val = val;
  615. break;
  616. }
  617. #endif
  618. default :
  619. ret = v4l_compat_translate_ioctl(inode,file,cmd,
  620. arg,pvr2_v4l2_do_ioctl);
  621. }
  622. pvr2_hdw_commit_ctl(hdw);
  623. if (ret < 0) {
  624. if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
  625. pvr2_trace(PVR2_TRACE_V4LIOCTL,
  626. "pvr2_v4l2_do_ioctl failure, ret=%d",ret);
  627. } else {
  628. if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
  629. pvr2_trace(PVR2_TRACE_V4LIOCTL,
  630. "pvr2_v4l2_do_ioctl failure, ret=%d"
  631. " command was:",ret);
  632. v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
  633. cmd);
  634. }
  635. }
  636. } else {
  637. pvr2_trace(PVR2_TRACE_V4LIOCTL,
  638. "pvr2_v4l2_do_ioctl complete, ret=%d (0x%x)",
  639. ret,ret);
  640. }
  641. return ret;
  642. }
  643. static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
  644. {
  645. enum pvr2_config cfg = dip->config;
  646. int minor_id = dip->devbase.minor;
  647. enum pvr2_v4l_type pvt;
  648. struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
  649. switch (cfg) {
  650. case pvr2_config_mpeg:
  651. pvt = pvr2_v4l_type_video;
  652. break;
  653. case pvr2_config_vbi:
  654. pvt = pvr2_v4l_type_vbi;
  655. break;
  656. case pvr2_config_radio:
  657. pvt = pvr2_v4l_type_radio;
  658. break;
  659. default: /* paranoia */
  660. pvt = pvr2_v4l_type_video;
  661. break;
  662. }
  663. pvr2_hdw_v4l_store_minor_number(hdw,pvt,-1);
  664. /* Paranoia */
  665. dip->v4lp = NULL;
  666. dip->stream = NULL;
  667. /* Actual deallocation happens later when all internal references
  668. are gone. */
  669. video_unregister_device(&dip->devbase);
  670. switch (cfg) {
  671. case pvr2_config_mpeg:
  672. printk(KERN_INFO "pvrusb2: unregistered device video%d [%s]\n",
  673. minor_id & 0x1f,
  674. pvr2_config_get_name(cfg));
  675. break;
  676. case pvr2_config_radio:
  677. printk(KERN_INFO "pvrusb2: unregistered device radio%d [%s]\n",
  678. minor_id & 0x1f,
  679. pvr2_config_get_name(cfg));
  680. break;
  681. case pvr2_config_vbi:
  682. printk(KERN_INFO "pvrusb2: unregistered device vbi%d [%s]\n",
  683. minor_id & 0x1f,
  684. pvr2_config_get_name(cfg));
  685. break;
  686. default:
  687. break;
  688. }
  689. }
  690. static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
  691. {
  692. if (vp->dev_video) {
  693. pvr2_v4l2_dev_destroy(vp->dev_video);
  694. vp->dev_video = 0;
  695. }
  696. if (vp->dev_radio) {
  697. pvr2_v4l2_dev_destroy(vp->dev_radio);
  698. vp->dev_radio = 0;
  699. }
  700. pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
  701. pvr2_channel_done(&vp->channel);
  702. kfree(vp);
  703. }
  704. static void pvr2_video_device_release(struct video_device *vdev)
  705. {
  706. struct pvr2_v4l2_dev *dev;
  707. dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
  708. kfree(dev);
  709. }
  710. static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
  711. {
  712. struct pvr2_v4l2 *vp;
  713. vp = container_of(chp,struct pvr2_v4l2,channel);
  714. if (!vp->channel.mc_head->disconnect_flag) return;
  715. if (vp->vfirst) return;
  716. pvr2_v4l2_destroy_no_lock(vp);
  717. }
  718. static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
  719. unsigned int cmd, unsigned long arg)
  720. {
  721. /* Temporary hack : use ivtv api until a v4l2 one is available. */
  722. #define IVTV_IOC_G_CODEC 0xFFEE7703
  723. #define IVTV_IOC_S_CODEC 0xFFEE7704
  724. if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0;
  725. return video_usercopy(inode, file, cmd, arg, pvr2_v4l2_do_ioctl);
  726. }
  727. static int pvr2_v4l2_release(struct inode *inode, struct file *file)
  728. {
  729. struct pvr2_v4l2_fh *fhp = file->private_data;
  730. struct pvr2_v4l2 *vp = fhp->vhead;
  731. struct pvr2_context *mp = fhp->vhead->channel.mc_head;
  732. pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
  733. if (fhp->rhp) {
  734. struct pvr2_stream *sp;
  735. struct pvr2_hdw *hdw;
  736. hdw = fhp->channel.mc_head->hdw;
  737. pvr2_hdw_set_streaming(hdw,0);
  738. sp = pvr2_ioread_get_stream(fhp->rhp);
  739. if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
  740. pvr2_ioread_destroy(fhp->rhp);
  741. fhp->rhp = NULL;
  742. }
  743. if (fhp->dev_info->config == pvr2_config_radio) {
  744. int ret;
  745. struct pvr2_hdw *hdw;
  746. hdw = fhp->channel.mc_head->hdw;
  747. if ((ret = pvr2_ctrl_set_value(
  748. pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
  749. PVR2_CVAL_INPUT_TV))) {
  750. return ret;
  751. }
  752. }
  753. v4l2_prio_close(&vp->prio, &fhp->prio);
  754. file->private_data = NULL;
  755. pvr2_context_enter(mp); do {
  756. if (fhp->vnext) {
  757. fhp->vnext->vprev = fhp->vprev;
  758. } else {
  759. vp->vlast = fhp->vprev;
  760. }
  761. if (fhp->vprev) {
  762. fhp->vprev->vnext = fhp->vnext;
  763. } else {
  764. vp->vfirst = fhp->vnext;
  765. }
  766. fhp->vnext = NULL;
  767. fhp->vprev = NULL;
  768. fhp->vhead = NULL;
  769. pvr2_channel_done(&fhp->channel);
  770. pvr2_trace(PVR2_TRACE_STRUCT,
  771. "Destroying pvr_v4l2_fh id=%p",fhp);
  772. kfree(fhp);
  773. if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
  774. pvr2_v4l2_destroy_no_lock(vp);
  775. }
  776. } while (0); pvr2_context_exit(mp);
  777. return 0;
  778. }
  779. static int pvr2_v4l2_open(struct inode *inode, struct file *file)
  780. {
  781. struct pvr2_v4l2_dev *dip; /* Our own context pointer */
  782. struct pvr2_v4l2_fh *fhp;
  783. struct pvr2_v4l2 *vp;
  784. struct pvr2_hdw *hdw;
  785. dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
  786. vp = dip->v4lp;
  787. hdw = vp->channel.hdw;
  788. pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
  789. if (!pvr2_hdw_dev_ok(hdw)) {
  790. pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
  791. "pvr2_v4l2_open: hardware not ready");
  792. return -EIO;
  793. }
  794. fhp = kmalloc(sizeof(*fhp),GFP_KERNEL);
  795. if (!fhp) {
  796. return -ENOMEM;
  797. }
  798. memset(fhp,0,sizeof(*fhp));
  799. init_waitqueue_head(&fhp->wait_data);
  800. fhp->dev_info = dip;
  801. pvr2_context_enter(vp->channel.mc_head); do {
  802. pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
  803. pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
  804. /* pk: warning, severe ugliness follows. 18+ only.
  805. please blaim V4L(ivtv) for braindamaged interfaces,
  806. not the implementor. This is probably flawed, but
  807. suggestions on how to do this "right" are welcome! */
  808. if (dip->config == pvr2_config_radio) {
  809. int ret;
  810. if ((pvr2_channel_check_stream_no_lock(&fhp->channel,
  811. fhp->dev_info->stream)) != 0) {
  812. /* We can 't switch modes while streaming */
  813. pvr2_channel_done(&fhp->channel);
  814. kfree(fhp);
  815. pvr2_context_exit(vp->channel.mc_head);
  816. return -EBUSY;
  817. }
  818. if ((ret = pvr2_ctrl_set_value(
  819. pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
  820. PVR2_CVAL_INPUT_RADIO))) {
  821. pvr2_channel_done(&fhp->channel);
  822. kfree(fhp);
  823. pvr2_context_exit(vp->channel.mc_head);
  824. return ret;
  825. }
  826. }
  827. fhp->vnext = NULL;
  828. fhp->vprev = vp->vlast;
  829. if (vp->vlast) {
  830. vp->vlast->vnext = fhp;
  831. } else {
  832. vp->vfirst = fhp;
  833. }
  834. vp->vlast = fhp;
  835. fhp->vhead = vp;
  836. } while (0); pvr2_context_exit(vp->channel.mc_head);
  837. fhp->file = file;
  838. file->private_data = fhp;
  839. v4l2_prio_open(&vp->prio,&fhp->prio);
  840. fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
  841. return 0;
  842. }
  843. static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
  844. {
  845. wake_up(&fhp->wait_data);
  846. }
  847. static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
  848. {
  849. int ret;
  850. struct pvr2_stream *sp;
  851. struct pvr2_hdw *hdw;
  852. if (fh->rhp) return 0;
  853. /* First read() attempt. Try to claim the stream and start
  854. it... */
  855. if ((ret = pvr2_channel_claim_stream(&fh->channel,
  856. fh->dev_info->stream)) != 0) {
  857. /* Someone else must already have it */
  858. return ret;
  859. }
  860. fh->rhp = pvr2_channel_create_mpeg_stream(fh->dev_info->stream);
  861. if (!fh->rhp) {
  862. pvr2_channel_claim_stream(&fh->channel,NULL);
  863. return -ENOMEM;
  864. }
  865. hdw = fh->channel.mc_head->hdw;
  866. sp = fh->dev_info->stream->stream;
  867. pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
  868. pvr2_hdw_set_stream_type(hdw,fh->dev_info->config);
  869. pvr2_hdw_set_streaming(hdw,!0);
  870. ret = pvr2_ioread_set_enabled(fh->rhp,!0);
  871. return ret;
  872. }
  873. static ssize_t pvr2_v4l2_read(struct file *file,
  874. char __user *buff, size_t count, loff_t *ppos)
  875. {
  876. struct pvr2_v4l2_fh *fh = file->private_data;
  877. int ret;
  878. if (fh->fw_mode_flag) {
  879. struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
  880. char *tbuf;
  881. int c1,c2;
  882. int tcnt = 0;
  883. unsigned int offs = *ppos;
  884. tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
  885. if (!tbuf) return -ENOMEM;
  886. while (count) {
  887. c1 = count;
  888. if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
  889. c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
  890. if (c2 < 0) {
  891. tcnt = c2;
  892. break;
  893. }
  894. if (!c2) break;
  895. if (copy_to_user(buff,tbuf,c2)) {
  896. tcnt = -EFAULT;
  897. break;
  898. }
  899. offs += c2;
  900. tcnt += c2;
  901. buff += c2;
  902. count -= c2;
  903. *ppos += c2;
  904. }
  905. kfree(tbuf);
  906. return tcnt;
  907. }
  908. if (fh->dev_info->config == pvr2_config_radio) {
  909. /* Radio device nodes on this device
  910. cannot be read or written. */
  911. return -EPERM;
  912. }
  913. if (!fh->rhp) {
  914. ret = pvr2_v4l2_iosetup(fh);
  915. if (ret) {
  916. return ret;
  917. }
  918. }
  919. for (;;) {
  920. ret = pvr2_ioread_read(fh->rhp,buff,count);
  921. if (ret >= 0) break;
  922. if (ret != -EAGAIN) break;
  923. if (file->f_flags & O_NONBLOCK) break;
  924. /* Doing blocking I/O. Wait here. */
  925. ret = wait_event_interruptible(
  926. fh->wait_data,
  927. pvr2_ioread_avail(fh->rhp) >= 0);
  928. if (ret < 0) break;
  929. }
  930. return ret;
  931. }
  932. static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
  933. {
  934. unsigned int mask = 0;
  935. struct pvr2_v4l2_fh *fh = file->private_data;
  936. int ret;
  937. if (fh->fw_mode_flag) {
  938. mask |= POLLIN | POLLRDNORM;
  939. return mask;
  940. }
  941. if (fh->dev_info->config == pvr2_config_radio) {
  942. /* Radio device nodes on this device
  943. cannot be read or written. */
  944. return -EPERM;
  945. }
  946. if (!fh->rhp) {
  947. ret = pvr2_v4l2_iosetup(fh);
  948. if (ret) return POLLERR;
  949. }
  950. poll_wait(file,&fh->wait_data,wait);
  951. if (pvr2_ioread_avail(fh->rhp) >= 0) {
  952. mask |= POLLIN | POLLRDNORM;
  953. }
  954. return mask;
  955. }
  956. static const struct file_operations vdev_fops = {
  957. .owner = THIS_MODULE,
  958. .open = pvr2_v4l2_open,
  959. .release = pvr2_v4l2_release,
  960. .read = pvr2_v4l2_read,
  961. .ioctl = pvr2_v4l2_ioctl,
  962. .llseek = no_llseek,
  963. .poll = pvr2_v4l2_poll,
  964. };
  965. #define VID_HARDWARE_PVRUSB2 38 /* FIXME : need a good value */
  966. static struct video_device vdev_template = {
  967. .owner = THIS_MODULE,
  968. .type = VID_TYPE_CAPTURE | VID_TYPE_TUNER,
  969. .type2 = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE
  970. | V4L2_CAP_TUNER | V4L2_CAP_AUDIO
  971. | V4L2_CAP_READWRITE),
  972. .hardware = VID_HARDWARE_PVRUSB2,
  973. .fops = &vdev_fops,
  974. };
  975. static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
  976. struct pvr2_v4l2 *vp,
  977. enum pvr2_config cfg)
  978. {
  979. int mindevnum;
  980. int unit_number;
  981. int v4l_type;
  982. enum pvr2_v4l_type pvt;
  983. dip->v4lp = vp;
  984. dip->config = cfg;
  985. switch (dip->config) {
  986. case pvr2_config_mpeg:
  987. v4l_type = VFL_TYPE_GRABBER;
  988. pvt = pvr2_v4l_type_video;
  989. dip->stream = &vp->channel.mc_head->video_stream;
  990. break;
  991. case pvr2_config_vbi:
  992. v4l_type = VFL_TYPE_VBI;
  993. pvt = pvr2_v4l_type_vbi;
  994. break;
  995. case pvr2_config_radio:
  996. v4l_type = VFL_TYPE_RADIO;
  997. pvt = pvr2_v4l_type_radio;
  998. break;
  999. default:
  1000. /* Bail out (this should be impossible) */
  1001. err("Failed to set up pvrusb2 v4l dev"
  1002. " due to unrecognized config");
  1003. return;
  1004. }
  1005. /* radio device doesn 't need its own stream */
  1006. if (!dip->stream && dip->config != pvr2_config_radio) {
  1007. err("Failed to set up pvrusb2 v4l dev"
  1008. " due to missing stream instance");
  1009. return;
  1010. }
  1011. memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
  1012. dip->devbase.release = pvr2_video_device_release;
  1013. mindevnum = -1;
  1014. unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
  1015. if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
  1016. switch (v4l_type) {
  1017. case VFL_TYPE_VBI:
  1018. mindevnum = vbi_nr[unit_number];
  1019. break;
  1020. case VFL_TYPE_RADIO:
  1021. mindevnum = radio_nr[unit_number];
  1022. break;
  1023. case VFL_TYPE_GRABBER:
  1024. default:
  1025. mindevnum = video_nr[unit_number];
  1026. break;
  1027. }
  1028. }
  1029. if ((video_register_device(&dip->devbase, v4l_type, mindevnum) < 0) &&
  1030. (video_register_device(&dip->devbase, v4l_type, -1) < 0)) {
  1031. err("Failed to register pvrusb2 v4l device");
  1032. }
  1033. switch (dip->config) {
  1034. case pvr2_config_mpeg:
  1035. printk(KERN_INFO "pvrusb2: registered device video%d [%s]\n",
  1036. dip->devbase.minor & 0x1f,
  1037. pvr2_config_get_name(dip->config));
  1038. break;
  1039. case pvr2_config_radio:
  1040. printk(KERN_INFO "pvrusb2: registered device radio%d [%s]\n",
  1041. dip->devbase.minor & 0x1f,
  1042. pvr2_config_get_name(dip->config));
  1043. break;
  1044. case pvr2_config_vbi:
  1045. printk(KERN_INFO "pvrusb2: registered device vbi%d [%s]\n",
  1046. dip->devbase.minor & 0x1f,
  1047. pvr2_config_get_name(dip->config));
  1048. break;
  1049. default:
  1050. break;
  1051. }
  1052. pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
  1053. pvt,dip->devbase.minor);
  1054. }
  1055. struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
  1056. {
  1057. struct pvr2_v4l2 *vp;
  1058. vp = kmalloc(sizeof(*vp),GFP_KERNEL);
  1059. if (!vp) return vp;
  1060. memset(vp,0,sizeof(*vp));
  1061. vp->dev_video = kmalloc(sizeof(*vp->dev_video),GFP_KERNEL);
  1062. vp->dev_radio = kmalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
  1063. if (!(vp->dev_video && vp->dev_radio)) {
  1064. if (vp->dev_video) kfree(vp->dev_video);
  1065. if (vp->dev_radio) kfree(vp->dev_radio);
  1066. kfree(vp);
  1067. return NULL;
  1068. }
  1069. memset(vp->dev_video,0,sizeof(*vp->dev_video));
  1070. memset(vp->dev_radio,0,sizeof(*vp->dev_radio));
  1071. pvr2_channel_init(&vp->channel,mnp);
  1072. pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
  1073. vp->channel.check_func = pvr2_v4l2_internal_check;
  1074. /* register streams */
  1075. pvr2_v4l2_dev_init(vp->dev_video,vp,pvr2_config_mpeg);
  1076. pvr2_v4l2_dev_init(vp->dev_radio,vp,pvr2_config_radio);
  1077. return vp;
  1078. }
  1079. /*
  1080. Stuff for Emacs to see, in order to encourage consistent editing style:
  1081. *** Local Variables: ***
  1082. *** mode: c ***
  1083. *** fill-column: 75 ***
  1084. *** tab-width: 8 ***
  1085. *** c-basic-offset: 8 ***
  1086. *** End: ***
  1087. */