webcam.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  1. #include "shared.h"
  2. #include "webcam.h"
  3. #include "wdm.h"
  4. #include "urb.h"
  5. /****************************
  6. * *
  7. ****************************/
  8. /****************************
  9. * UTILS *
  10. ****************************/
  11. int r5u870_control_msg( struct driverInstance* this, int write, int class, u8 request, u16 value, u16 index, void* data, u16 size ){
  12. char* dbuf = NULL;
  13. int res;
  14. if( size ){
  15. dbuf = kmalloc( size, GFP_KERNEL );
  16. if ( !dbuf )return -ENOMEM;
  17. if ( write ) memcpy( dbuf, data, size );
  18. }
  19. //int usb_control_msg(struct usb_device * dev, unsigned int pipe, __u8 request,__u8 requesttype, __u16 value, __u16 index, void * data, __u16 size, int timeout );
  20. res = usb_control_msg(
  21. this->usbDevice,
  22. write ? usb_sndctrlpipe( this->usbDevice, 0 ) : usb_rcvctrlpipe( this->usbDevice, 0 ),
  23. request,
  24. ( write ? USB_DIR_OUT : USB_DIR_IN ) | ( class ? (USB_TYPE_CLASS | USB_RECIP_INTERFACE) : (USB_TYPE_VENDOR | USB_RECIP_DEVICE) ),
  25. value,
  26. index,
  27. dbuf,
  28. size,
  29. 1000
  30. );
  31. if( dbuf ) {
  32. if( !write ) memcpy( data, dbuf, size );
  33. kfree( dbuf );
  34. }
  35. return res;
  36. }
  37. static int r5u870_set_gen_reg( struct driverInstance* this, int cmd, int reg, int val ){
  38. int res = r5u870_control_msg( this, 1, 0, cmd, val, reg, NULL, 0 );
  39. if( res < 0 ){
  40. printk( KERN_ERR "[%s] %s %04x/%04x/%04x failed: %d\n", KBUILD_MODNAME, __FUNCTION__, cmd, reg, val, res);
  41. return res;
  42. }
  43. return 0;
  44. }
  45. static int r5u870_set_reg_wdm( struct driverInstance* this, int reg, int val ){
  46. return r5u870_set_gen_reg( this, 0xc2, reg, val);
  47. }
  48. /****************************
  49. * MICROCODE *
  50. ****************************/
  51. static int r5u870_microcode_get_state( struct driverInstance* this ){
  52. char buf[1];
  53. int res;
  54. res = r5u870_control_msg( this, 0, 0, 0xa4, 0, 0, buf, 1 );
  55. if ((res != 1) || ((buf[0] != 0) && (buf[0] != 1))) {
  56. printk( KERN_ERR "[%s] command 0xa4 failed: %d", KBUILD_MODNAME, res);
  57. return res < 0 ? res : -EIO;
  58. }
  59. printk( KERN_NOTICE "[%s] camera reports %s microcode state\n", KBUILD_MODNAME, buf[0] ? "positive" : "negative" );
  60. return (buf[0] == 0) ? -ENOENT : 0;
  61. }
  62. static int r5u870_microcode_get_ver( struct driverInstance* this, int *verp ){
  63. char buf[2];
  64. int res;
  65. res = r5u870_control_msg( this, 0, 0, 0xc3, 0, 0x0e, buf, 2 );
  66. if (res != 2) {
  67. printk( KERN_ERR "[%s] command 0xa3 failed: %d\n", KBUILD_MODNAME, res );
  68. return res < 0 ? res : -EIO;
  69. }
  70. res = le16_to_cpup((__le16 *) buf);
  71. printk( KERN_NOTICE "[%s] camera reports version %04x\n", KBUILD_MODNAME, res );
  72. *verp = res;
  73. return 0;
  74. }
  75. static int r5u870_microcode_reset( struct driverInstance* this ){
  76. int res;
  77. printk( KERN_NOTICE "[%s] sending microcode reset command\n", KBUILD_MODNAME );
  78. msleep( 100 );// The Windows driver waits 1sec
  79. res = r5u870_set_gen_reg( this, 0xa6, 0, 0 );
  80. if ( !res ) msleep(200);
  81. return res;
  82. }
  83. static int r5u870_microcode_upload( struct driverInstance* this ){
  84. const struct firmware *fws;
  85. char *pgbuf;
  86. const u8 *dptr;
  87. int tolerance = 3;
  88. int i, rem, addr, len, res = 0;
  89. pgbuf = (char *) kmalloc(64, GFP_KERNEL);
  90. if( !pgbuf ) return -ENOMEM;
  91. printk( KERN_NOTICE "[%s] loading microcode file \"%s\"\n", KBUILD_MODNAME, this->webcamModel->ucodeFile );
  92. res = request_firmware( &fws, this->webcamModel->ucodeFile, &this->usbDevice->dev );
  93. if( res ) {
  94. printk( KERN_ERR "[%s] Microcode file \"%s\" is missing\n", KBUILD_MODNAME, this->webcamModel->ucodeFile );
  95. kfree( pgbuf );
  96. return res;
  97. }
  98. i = 0;
  99. dptr = fws->data;
  100. rem = fws->size;
  101. while( rem ){
  102. if( rem < 3 ){
  103. printk( KERN_ERR "[%s] Microcode file msg %d is incomplete", KBUILD_MODNAME, i );
  104. res = -EINVAL;
  105. break;
  106. }
  107. len = dptr[0];
  108. addr = dptr[1] | (dptr[2] << 8);
  109. dptr += 3;
  110. rem -= 3;
  111. if ((rem < len) || (len > 64)) {
  112. printk( KERN_ERR "[%s] Microcode file msg %d has bad length %d\n", KBUILD_MODNAME, i, len );
  113. res = -EINVAL;
  114. break;
  115. }
  116. /*
  117. * The USB stack has issues with the initseq data if
  118. * initseq points into the vmalloc arena. This is
  119. * the case for microcode embedded in a module, or
  120. * data loaded by request_firmware().
  121. *
  122. * As a workaround, we memcpy() into a kmalloc page.
  123. */
  124. memcpy(pgbuf, dptr, len);
  125. dptr += len;
  126. rem -= len;
  127. retry:
  128. // TODO: Maybe make this use r5u870_control_msg or similar?
  129. res = usb_control_msg(
  130. this->usbDevice,
  131. usb_sndctrlpipe( this->usbDevice, 0 ),
  132. 0xa0,
  133. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  134. addr,
  135. 0,
  136. pgbuf,
  137. len,
  138. 1000
  139. );
  140. if (res < 0) {
  141. if (tolerance--) goto retry;
  142. printk( KERN_ERR "[%s] command a0[%d] failed: %d\n", KBUILD_MODNAME, i, res);
  143. break;
  144. }
  145. if (res != len) {
  146. printk( KERN_ERR "[%s] command a0[%d] failed: %d (exp %d)\n", KBUILD_MODNAME, i, res, len);
  147. res = -EIO;
  148. break;
  149. }
  150. i++;
  151. }
  152. release_firmware( fws );
  153. kfree( pgbuf );
  154. return res;
  155. }
  156. static int r5u870_microcode_enable( struct driverInstance* this ){
  157. char buf[1];
  158. int res;
  159. buf[0] = 1;
  160. res = r5u870_control_msg( this, 1, 0, 0xa1, 0, 0, buf, 1 );
  161. if( res != 1 ) {
  162. printk( KERN_ERR "[%s] command 0xa1 failed: %d\n", KBUILD_MODNAME, res );
  163. return res < 0 ? res : -EIO;
  164. }
  165. return 0;
  166. }
  167. static int webcamMicrocode( struct driverInstance* this ){//r5u870_dev_init
  168. int mcver;
  169. int res;
  170. if ( !this->webcamModel->ucodeFile ) return 0;
  171. res = r5u870_microcode_get_state( this );
  172. if ( res && (res != -ENOENT) ) return res;
  173. if( !res ){
  174. res = r5u870_microcode_get_ver( this, &mcver );
  175. if ( res ) return res;
  176. if ( mcver != this->webcamModel->ucodeVersion ){
  177. res = r5u870_microcode_reset( this );
  178. if( res ) return res;
  179. res = -ENOENT;
  180. }
  181. }
  182. if( res == -ENOENT ){
  183. res = r5u870_microcode_upload( this );
  184. if( res < 0 ) return res;
  185. res = r5u870_microcode_enable( this );
  186. if( res ) return res;
  187. res = r5u870_microcode_get_ver( this, &mcver );
  188. if( res ) return res;
  189. }
  190. if( mcver != this->webcamModel->ucodeVersion ){
  191. printk( KERN_ERR "[%s] Unexpected microcode version (exp:%04x got:%04x)\n", KBUILD_MODNAME, this->webcamModel->ucodeVersion, mcver);
  192. }
  193. //Halt capture in case it's running (broken driver?)
  194. res = this->vh_cap_stop( this );
  195. if (res < 0) return res;
  196. return 0;
  197. }
  198. /****************************
  199. * FORMAT *
  200. ****************************/
  201. int webcamTryFormat( struct driverInstance* this, struct v4l2_pix_format* requestedFormat, char setFlag ){
  202. const struct r5u870_pixelformat* format;
  203. const struct r5u870_resolution* resolutionTable;
  204. const struct r5u870_resolution* resolution;
  205. int i;
  206. format = NULL;
  207. for ( i = 0; i < this->webcamFormatsCount; i++ ) {
  208. if ( this->webcamFormats[i].pixelformat == requestedFormat->pixelformat ) {
  209. format = &this->webcamFormats[i];
  210. break;
  211. }
  212. }
  213. if ( format == NULL ) return -EINVAL;
  214. resolutionTable = format->resolutionTable;
  215. if ( !resolutionTable || !resolutionTable[0].width ){
  216. printk( KERN_ERR "[%s] invalid resolution table\n", KBUILD_MODNAME );
  217. return -EINVAL;
  218. }
  219. //Find the most acceptable resolution
  220. resolution = NULL;
  221. for( i = 0; resolutionTable[i].width > 0; i++ ){
  222. if ( !resolution ){
  223. resolution = &resolutionTable[i];
  224. }else if( resolution->width > requestedFormat->width ){
  225. if( resolutionTable[i].width < resolution->width ) resolution = &resolutionTable[i];
  226. }else if( resolution->height > requestedFormat->height ){
  227. if( resolutionTable[i].width <= requestedFormat->width && resolutionTable[i].height < resolution->height ) resolution = &resolutionTable[i];
  228. }else if( resolutionTable[i].width <= requestedFormat->width && resolutionTable[i].height <= requestedFormat->height &&
  229. ( resolutionTable[i].width > resolution->width || ( resolutionTable[i].width == resolution->width && resolutionTable[i].height > resolution->height ) ) ){
  230. resolution = &resolutionTable[i];
  231. }
  232. }
  233. if( (requestedFormat->width > 1) && (requestedFormat->height > 1) ){
  234. if ( (resolution->width > requestedFormat->width) || (resolution->height > requestedFormat->height) ) {
  235. printk( KERN_WARNING "[%s] Bad size request. Returning -EINVAL.\n", KBUILD_MODNAME );
  236. return -EINVAL;
  237. }
  238. }
  239. printk( KERN_NOTICE "[%s] Requested %s %dx%d. Using %dx%d.\n",
  240. KBUILD_MODNAME,
  241. format->description,
  242. requestedFormat->width,
  243. requestedFormat->height,
  244. resolution->width,
  245. resolution->height
  246. );
  247. memset( requestedFormat, 0, sizeof(*requestedFormat) );
  248. requestedFormat->width = resolution->width;
  249. requestedFormat->height = resolution->height;
  250. requestedFormat->pixelformat = format->pixelformat;
  251. requestedFormat->bytesperline = requestedFormat->width * 2;
  252. requestedFormat->sizeimage = requestedFormat->width * requestedFormat->height * 2;
  253. requestedFormat->field = V4L2_FIELD_INTERLACED;
  254. requestedFormat->colorspace = V4L2_COLORSPACE_SMPTE170M;
  255. if( !setFlag ) return 0;
  256. if( (this->webcamCurrentPixelformat.width != requestedFormat->width) ||
  257. (this->webcamCurrentPixelformat.height != requestedFormat->height) ||
  258. (this->webcamCurrentPixelformat.pixelformat != requestedFormat->pixelformat) ||
  259. (this->webcamCurrentPixelformat.sizeimage != requestedFormat->sizeimage) ){
  260. this->vh_configured = 0;
  261. }
  262. this->webcamCurrentPixelformat = *requestedFormat;
  263. this->webcamCurrentFormat = format;
  264. this->webcamCurrentResolution = resolution;
  265. return 0;
  266. }
  267. /****************************
  268. * WDM *
  269. ****************************/
  270. //Set the frame size and data format.
  271. //Do not call this function with the isochronous stream active.
  272. //r5u870_set_fmt_wdm
  273. static int webcamApplyFormat_wdm( struct driverInstance* this ){
  274. int res;
  275. msleep(1);
  276. res = r5u870_set_gen_reg( this, 0xc5, 2, this->webcamCurrentFormat->formatId );
  277. if( res ) return res;
  278. msleep(1);
  279. res = r5u870_set_gen_reg( this, 0xc5, 0, this->webcamCurrentResolution->width );
  280. if( res ) return res;
  281. msleep(1);
  282. res = r5u870_set_gen_reg( this, 0xc5, 1, this->webcamCurrentResolution->height );
  283. if( res ) return res;
  284. msleep(5);
  285. return 0;
  286. }
  287. //Turn frame grabbing on or off (WDM).
  288. //This will also turn on or off the LED.
  289. static inline int webcamSetCaptureState_wdm( struct driverInstance* this, int val ){
  290. return r5u870_set_gen_reg( this, 0xc4, val, 0 );
  291. }
  292. static int r5u870_cap_stop_wdm( struct driverInstance* this ){
  293. return webcamSetCaptureState_wdm( this, 0 );
  294. }
  295. static int webcamSetControlCallback_wdm( struct v4l2_ctrl* control ){
  296. struct driverInstance* this = container_of( control->handler, struct driverInstance, webcamControlHandler );
  297. struct webcam_control* webcamControl;
  298. int err = 0;
  299. if( atomic_read( &this->webcamControlRegisterIsEnabled ) ){
  300. if( !control->priv ){
  301. printk( KERN_ERR "[%s] %s err: control->priv == NULL\n", KBUILD_MODNAME, __FUNCTION__ );
  302. return -EINVAL;
  303. }
  304. webcamControl = control->priv;
  305. err = r5u870_set_reg_wdm( this, webcamControl->reg, control->val );
  306. if( err )printk( KERN_ERR "[%s](%s) id: %u, val: %i, err: %i\n", KBUILD_MODNAME, __FUNCTION__, control->id, control->val, err );
  307. }else err = -EBUSY;
  308. return err;
  309. }
  310. static int webcamAddControls_wdm( struct driverInstance* this ){
  311. int err = 0;
  312. int i;
  313. //TODO: Find a beautiful way to calculate the number of controls
  314. v4l2_ctrl_handler_init( &this->webcamControlHandler, 19 );
  315. for( i = 0; this->webcamModel->controls_wdm[i] != R5U870_WDM_CTRL_LAST; i++ ){
  316. v4l2_ctrl_new_custom(
  317. &this->webcamControlHandler,
  318. &r5u870_wdm_ctrls[ this->webcamModel->controls_wdm[i] ].control,
  319. &r5u870_wdm_ctrls[ this->webcamModel->controls_wdm[i] ]
  320. );
  321. if( this->webcamControlHandler.error )break;
  322. }
  323. if( this->webcamControlHandler.error ){
  324. err = this->webcamControlHandler.error;
  325. v4l2_ctrl_handler_free( &this->webcamControlHandler );
  326. }else this->v4l2Device.ctrl_handler = &this->webcamControlHandler;
  327. return err;
  328. }
  329. /*
  330. * r5u870_decide_pkt_wdm
  331. *
  332. * Based on the size of an isochronous data packet, this function
  333. * decides whether to copy the packet into the frame buffer and possibly
  334. * complete the frame, or to discard both the packet and the frame.
  335. *
  336. * Returns:
  337. * 0 Frame is done
  338. * -EAGAIN Append packet to frame, frame is not done
  339. * -EPIPE Discard frame and packet
  340. * -EIO The device is nonresponsive, abort
  341. */
  342. static int r5u870_decide_pkt_wdm( struct driverInstance* this, int pktstatus, int pktlen, const u8* pktdata, int* start ){
  343. int ret = -EAGAIN;
  344. *start = 0;
  345. if( pktstatus ){//Abort current frame
  346. if( printk_ratelimit() )printk( KERN_NOTICE "[%s] frame abort: packet status %d\n", KBUILD_MODNAME, pktstatus );
  347. this->vh_frame_accum = -1;
  348. this->vh_emptypkts = 0;
  349. ret = -EPIPE;
  350. }else if( !pktlen ){
  351. if( ++this->vh_emptypkts == R5U870_EMPTYPKT_FRAME_DELIM ){
  352. if(this->vh_frame_accum == -1) ret = -EPIPE;//Frame was previously aborted
  353. else if( this->vh_frame_accum == this->webcamCurrentPixelformat.sizeimage ) ret = 0;//Complete frame
  354. else{//Not enough data in frame sequence
  355. if( printk_ratelimit() ) printk( KERN_NOTICE "[%s] frame abort: Frame seq too short (exp:%d got:%d)\n", KBUILD_MODNAME, this->webcamCurrentPixelformat.sizeimage, this->vh_frame_accum );
  356. ret = -EPIPE;
  357. }
  358. if( !this->vh_firstframe ){//Always reject the first frame
  359. this->vh_firstframe = 1;
  360. this->vh_frame_accum = -1;
  361. ret = -EPIPE;
  362. }else this->vh_frame_accum = 0;
  363. }else if( this->vh_emptypkts >= R5U870_EMPTYPKT_GIVE_UP ){
  364. if( printk_ratelimit() ) printk( KERN_NOTICE "[%s] %d empty packets, giving up\n", KBUILD_MODNAME, this->vh_emptypkts );
  365. ret = -EIO;
  366. }
  367. }else{
  368. this->vh_emptypkts = 0;
  369. if( this->vh_frame_accum == -1 ) ret = -EPIPE;//Frame was previously aborted
  370. else if( (this->vh_frame_accum + pktlen) <= this->webcamCurrentPixelformat.sizeimage ) this->vh_frame_accum += pktlen;//Append this data
  371. else{//Oversized frame, abort
  372. if( printk_ratelimit() ) printk( KERN_NOTICE "[%s] frame abort: Frame seq too long\n", KBUILD_MODNAME );
  373. this->vh_frame_accum = -1;
  374. ret = -EPIPE;
  375. }
  376. }
  377. return ret;
  378. }
  379. /****************************
  380. * CAPTURE *
  381. ****************************/
  382. //r5u870_config_iso_ep
  383. static int webcamConfigInterface( struct driverInstance* this ){
  384. int res;
  385. if( !this->vh_configured ){
  386. this->vh_ctrl_sync = 0;
  387. res = usbcam_choose_altsetting( this );
  388. if( res ){
  389. printk( KERN_ERR "[%s] need %d B/s, no altsetting provides\n", KBUILD_MODNAME, this->webcamCurrentResolution->requiredBandwidth );
  390. return res;
  391. }
  392. printk( KERN_NOTICE "[%s] using altsetting %d\n", KBUILD_MODNAME, this->usbCurrentAltsetting );
  393. }
  394. res = usb_set_interface( this->usbDevice, this->urbstreamInterfaceNumber, this->usbCurrentAltsetting );
  395. if( res ){
  396. printk( KERN_ERR "[%s] could not set altsetting: %d\n", KBUILD_MODNAME, res );
  397. return res;
  398. }
  399. return 0;
  400. }
  401. int webcamCaptureStart( struct driverInstance* this ){
  402. int res;
  403. if( atomic_read( &this->webcamIsCaptuing ) )return 0;
  404. if( !this->webcamModel->isUvc ){
  405. res = webcamConfigInterface( this );
  406. if( res )return res;
  407. }
  408. atomic_set( &this->webcamControlRegisterIsEnabled, 1 );
  409. if( !this->vh_configured ){
  410. v4l2_ctrl_handler_setup( &this->webcamControlHandler );
  411. res = this->webcamApplyFormat( this );
  412. if( res ){
  413. printk( KERN_ERR "[%s] could not configure capture: %d\n", KBUILD_MODNAME, res );
  414. goto out_set_idle;
  415. }
  416. if( this->webcamModel->rm_no_ctrl_reload ) this->vh_ctrl_sync = 1;
  417. }
  418. if( this->webcamModel->isUvc ){
  419. res = webcamConfigInterface( this );
  420. if( res ) goto out_set_idle;
  421. }
  422. this->vh_configured = 1;
  423. res = usbcam_urbstream_config_iso( this );
  424. if( res < 0 ) {
  425. printk( KERN_ERR "[%s] urbstream init failed: %d\n", KBUILD_MODNAME, res );
  426. goto out_set_idle;
  427. }
  428. atomic_set( &this->webcamIsCaptuing, 1 );
  429. if( !this->webcamModel->isUvc ){
  430. res = webcamSetCaptureState_wdm( this, 1 );
  431. if( res )goto out_cleanup_urbstream;
  432. }
  433. if( !this->vh_ctrl_sync ){
  434. //Reload the control values after changing res/format
  435. v4l2_ctrl_handler_setup( &this->webcamControlHandler );
  436. this->vh_ctrl_sync = 1;
  437. }
  438. printk( KERN_NOTICE "[%s] starting capture\n", KBUILD_MODNAME );
  439. this->vh_firstframe = 0;
  440. this->vh_frame_accum = -1;
  441. this->vh_framebuf_offset = 0;
  442. this->vh_emptypkts = R5U870_EMPTYPKT_FRAME_DELIM - 1;
  443. res = usbcam_urbstream_start( this );
  444. if(res) goto out_stop_capture;
  445. return 0;
  446. out_stop_capture:
  447. (void) this->vh_cap_stop( this );
  448. out_cleanup_urbstream:
  449. usbcam_urbstream_cleanup( this );
  450. out_set_idle:
  451. usb_set_interface( this->usbDevice, this->urbstreamInterfaceNumber, 0 );
  452. atomic_set( &this->webcamControlRegisterIsEnabled, 0 );
  453. atomic_set( &this->webcamIsCaptuing, 0 );
  454. return res;
  455. }
  456. void webcamCaptureStop( struct driverInstance* this ){//r5u870_do_stop
  457. struct videobuffer_capsule* cursor;
  458. struct videobuffer_capsule* tmp;
  459. unsigned long flags = 0;
  460. if( atomic_read( &this->webcamIsCaptuing ) ){
  461. atomic_set( &this->webcamIsCaptuing, 0 );
  462. atomic_set( &this->webcamControlRegisterIsEnabled, 0 );
  463. usbcam_urbstream_stop( this );
  464. spin_lock_irqsave( &this->buflistSpinlock, flags );
  465. atomic_set( &this->buflistIsDisabled, 1 );
  466. list_for_each_entry_safe( cursor, tmp, &this->buflist, listItem ){
  467. list_del( &cursor->listItem );
  468. vb2_buffer_done( &cursor->videobuffer, VB2_BUF_STATE_ERROR );
  469. }
  470. spin_unlock_irqrestore( &this->buflistSpinlock, flags );
  471. if( !atomic_read( &this->usbDeviceIsDisconnected ) ){
  472. usb_set_interface( this->usbDevice, this->urbstreamInterfaceNumber, 0);
  473. this->vh_cap_stop( this );
  474. }
  475. usbcam_urbstream_cleanup( this );
  476. printk( KERN_NOTICE "[%s] Webcam capture stopped\n", KBUILD_MODNAME );
  477. }
  478. }
  479. /****************************
  480. * PACKET PROCESSING *
  481. ****************************/
  482. static inline struct videobuffer_capsule* usbcam_capture_curframe( struct driverInstance* this ){
  483. return list_empty( &this->buflist ) ? NULL : list_entry( this->buflist.next, struct videobuffer_capsule, listItem );
  484. }
  485. static void usbcam_curframe_complete( struct driverInstance* this, enum vb2_buffer_state bufstate ){
  486. struct videobuffer_capsule* curframe;
  487. unsigned long flags = 0;
  488. spin_lock_irqsave( &this->buflistSpinlock, flags );
  489. curframe = usbcam_capture_curframe( this );
  490. if( !curframe ){
  491. spin_unlock_irqrestore( &this->buflistSpinlock, flags );
  492. if( printk_ratelimit() ) printk( KERN_WARNING "[%s] No videobuffers in queue.\n", KBUILD_MODNAME );
  493. return;
  494. }
  495. list_del( &curframe->listItem );
  496. spin_unlock_irqrestore( &this->buflistSpinlock, flags );
  497. curframe->videobuffer.timestamp = ktime_get_ns();
  498. vb2_buffer_done( &curframe->videobuffer, bufstate );
  499. }
  500. //#define EAGAIN 11
  501. //#define EPIPE 32
  502. //#define EPROTO 71
  503. //#define EOVERFLOW 75
  504. //static void r5u870_iso_packet_done(struct usbcam_dev *udp, struct usbcam_urbstream *usp, const uint8_t *pktdata, int pktlen, int pktstatus)
  505. void r5u870_iso_packet_done( struct driverInstance* this, const uint8_t *pktdata, int pktlen, int pktstatus ) {
  506. struct videobuffer_capsule* currentVideobuffer;
  507. int res, start = 0;
  508. unsigned long flags = 0;
  509. res = this->vh_decide_pkt( this, pktstatus, pktlen, (u8 *) pktdata, &start );
  510. switch( res ) {
  511. case -EPIPE:
  512. if( this->vh_framebuf_offset ){
  513. this->vh_framebuf_offset = 0;
  514. usbcam_curframe_complete( this, VB2_BUF_STATE_ERROR );
  515. }
  516. break;
  517. case 0:
  518. case -EAGAIN:
  519. if( pktlen ) {
  520. spin_lock_irqsave( &this->buflistSpinlock, flags );
  521. currentVideobuffer = usbcam_capture_curframe( this );
  522. if( !currentVideobuffer ){
  523. spin_unlock_irqrestore( &this->buflistSpinlock, flags );
  524. //Some programs get stupid when starting the capture and do not have time
  525. //to queue videobuffers, so we just display a warning and continue working.
  526. if( printk_ratelimit() ) printk( KERN_WARNING "[%s] Running out of videobuffers.\n", KBUILD_MODNAME );
  527. //webcamCaptureStop( this );
  528. break;
  529. }
  530. BUG_ON( pktlen - start + this->vh_framebuf_offset > vb2_plane_size( &currentVideobuffer->videobuffer, 0 ) );
  531. //This is our one and only memcpy. It's kind of hard to get around doing this, as we
  532. //cannot predict into which isochronous packets the camera will choose to return data.
  533. memcpy( vb2_plane_vaddr( &currentVideobuffer->videobuffer, 0 ) + this->vh_framebuf_offset, pktdata + start, pktlen - start );
  534. this->vh_framebuf_offset += (pktlen - start);
  535. //printk( KERN_NOTICE "(%s) offset now: %d\n", __FUNCTION__, this->vh_framebuf_offset );
  536. spin_unlock_irqrestore( &this->buflistSpinlock, flags );
  537. }
  538. if( !res ) {
  539. this->vh_framebuf_offset = 0;
  540. usbcam_curframe_complete( this, VB2_BUF_STATE_DONE );
  541. }
  542. break;
  543. case -EIO:
  544. webcamCaptureStop( this );
  545. break;
  546. default:
  547. BUG();
  548. }
  549. }
  550. /****************************
  551. * INIT *
  552. ****************************/
  553. void webcamRelease( struct driverInstance* this ){//r5u870_usbcam_release
  554. struct claimed_interface* interfaceTemp;
  555. struct claimed_interface* interfaceCursor;
  556. webcamCaptureStop( this );
  557. v4l2_ctrl_handler_free( &this->webcamControlHandler );
  558. list_for_each_entry_safe( interfaceCursor, interfaceTemp, &this->claimedInterfacesList, listItem ){
  559. usb_set_intfdata( interfaceCursor->interface, NULL );
  560. usb_put_intf( interfaceCursor->interface );
  561. usb_driver_release_interface( this->usbDeviceDriver, interfaceCursor->interface );
  562. list_del( &interfaceCursor->listItem );
  563. }
  564. }
  565. /*
  566. * Someone clever at HP decided to use 05ca:1870 for two distinct devices.
  567. * The Pavilion dv1xxx machines all seem to have the less common of the
  568. * two. There is no known, working method to distinguish the devices
  569. * using USB commands only. We resort to reading the model number out
  570. * of DMI.
  571. */
  572. static int dv1000 = 2;
  573. module_param( dv1000, int, S_IRUGO | S_IWUSR );
  574. MODULE_PARM_DESC( dv1000, "HP dv1000 detect mode (0=no,1=yes,2=DMI)" );
  575. static int r5u870_check_hp_dv1000( void ){
  576. const char *prod_name;
  577. if ( !dv1000 ) return 0;
  578. if ( dv1000 == 1 ) return 1;
  579. prod_name = dmi_get_system_info( DMI_PRODUCT_NAME );
  580. if ( !prod_name ) printk( KERN_INFO "r5u870: No DMI model found\n" );
  581. else {
  582. printk( KERN_INFO "r5u870: Found DMI model: \"%s\"\n", prod_name );
  583. if ( !strncmp( prod_name, "HP Pavilion dv1000", 18 ) && !isdigit( prod_name[18] ) ) return 1;
  584. }
  585. return 0;
  586. }
  587. static const struct r5u870_model* r5u870_find_model( int driver_info ){
  588. if ( driver_info == R5U870_DI_HP_PAVWC_WDM ) {
  589. if ( r5u870_check_hp_dv1000() ) driver_info = R5U870_DI_HP_WEBCAM1K;
  590. }
  591. if ( ( driver_info <= R5U870_DI_INVALID ) || ( driver_info >= ARRAY_SIZE(r5u870_models) ) ) return NULL;
  592. if ( !r5u870_models[driver_info].modelName ) return NULL;
  593. return &r5u870_models[driver_info];
  594. }
  595. int webcamInit( struct driverInstance* this, const struct usb_device_id* devid ){
  596. int res = 0;
  597. this->vh_ctrl_ifnum = -1;
  598. this->urbstreamInterfaceNumber = -1;
  599. this->urbstreamMinPacketSize = -1;
  600. this->webcamModel = r5u870_find_model( devid->driver_info );
  601. if( !this->webcamModel ){
  602. printk( KERN_ERR "[%s] no suitable model descriptor for %04x:%04x\n",
  603. KBUILD_MODNAME, le16_to_cpu( this->usbDevice->descriptor.idVendor ), le16_to_cpu( this->usbDevice->descriptor.idProduct ) );
  604. return -ENODEV;
  605. }
  606. this->webcamFormats = this->webcamModel->pixelformats;
  607. this->webcamFormatsCount = this->webcamModel->pixelformatsCount;
  608. if( this->webcamModel->isUvc ) {
  609. this->webcamApplyFormat = webcamApplyFormat_uvc;
  610. this->vh_cap_stop = r5u870_cap_stop_uvc;
  611. this->vh_decide_pkt = r5u870_decide_pkt_uvc;
  612. }else{
  613. this->webcamApplyFormat = webcamApplyFormat_wdm;
  614. this->vh_cap_stop = r5u870_cap_stop_wdm;
  615. this->vh_decide_pkt = r5u870_decide_pkt_wdm;
  616. }
  617. printk( KERN_INFO "[%s] Detected %s\n", KBUILD_MODNAME, this->webcamModel->modelName );
  618. snprintf( this->videoDevice.name, sizeof( this->videoDevice.name ), "%s", this->webcamModel->modelName );
  619. res = webcamMicrocode( this );
  620. if(res < 0){
  621. printk( KERN_ERR "[%s] webcamMicrocode failed: %d\n", KBUILD_MODNAME, res );
  622. goto out_failed;
  623. }
  624. if ( this->webcamModel->isUvc ) {//This appears to be a UVC VideoControl interface.
  625. res = r5u870_uvc_parse_vc( this );
  626. if (res < 0) {
  627. printk( KERN_ERR "[%s] UVC setup failed: %d \n", KBUILD_MODNAME, res );
  628. goto out_failed;
  629. }
  630. } else {//We are looking at a proprietary Ricoh interface
  631. this->urbstreamInterfaceNumber = this->usbInterface->altsetting->desc.bInterfaceNumber;
  632. this->urbstreamEndpoint = 6;
  633. }
  634. if( this->webcamModel->controls_wdm ){
  635. res = webcamAddControls_wdm( this );
  636. if ( res ) {
  637. printk( KERN_ERR "[%s] Vendor control setup failed: %d\n", KBUILD_MODNAME, res );
  638. goto out_failed;
  639. }
  640. }
  641. //Configure the usbcam pixel format and control arrays
  642. if( !this->webcamFormatsCount ){
  643. printk( KERN_ERR "[%s] No pixel formats detected\n", KBUILD_MODNAME );
  644. res = -ENODEV;
  645. goto out_failed;
  646. }
  647. /* Set the default format */
  648. this->webcamCurrentFormat = &this->webcamFormats[0];
  649. this->webcamCurrentResolution = &this->webcamCurrentFormat->resolutionTable[0];
  650. this->webcamCurrentPixelformat.width = this->webcamCurrentResolution->width;
  651. this->webcamCurrentPixelformat.height = this->webcamCurrentResolution->height;
  652. this->webcamCurrentPixelformat.pixelformat = this->webcamCurrentFormat->pixelformat;
  653. this->webcamCurrentPixelformat.bytesperline = this->webcamCurrentPixelformat.width * 2;
  654. this->webcamCurrentPixelformat.sizeimage = this->webcamCurrentPixelformat.width * this->webcamCurrentPixelformat.height * 2;
  655. this->webcamCurrentPixelformat.colorspace = V4L2_COLORSPACE_SMPTE170M;
  656. this->webcamCurrentPixelformat.field = V4L2_FIELD_INTERLACED;
  657. return 0;
  658. out_failed:
  659. webcamRelease( this );
  660. return res;
  661. }