main.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. #include "shared.h"
  2. #include "main.h"
  3. /****************************
  4. * UTILS *
  5. ****************************/
  6. static inline const struct r5u870_resolution* webcamGetFormatResolutionTable( struct driverInstance* this, __u32 format ){
  7. int i;
  8. for( i = 0; i < this->webcamFormatsCount; i++ ){
  9. if( this->webcamFormats[i].pixelformat == format ){
  10. return this->webcamFormats[i].resolutionTable;
  11. }
  12. }
  13. return NULL;
  14. }
  15. /****************************
  16. * videoDevice ioctl ops *
  17. ****************************/
  18. //These callbacks are protected by this->videoDevice.lock. Don't worry!
  19. static int vidioc_querycap_callback( struct file* file, void* fh, struct v4l2_capability* cap ){
  20. struct driverInstance* this = video_drvdata( file );
  21. const char busName[] = "USB";
  22. strlcpy( cap->driver, KBUILD_MODNAME, sizeof(cap->driver) );
  23. strlcpy( cap->card , this->webcamModel->modelName, sizeof(cap->card) );
  24. strlcpy( cap->bus_info, busName, sizeof(cap->bus_info) );
  25. cap->version = KERNEL_VERSION( 2, 0, 0 );
  26. cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS;
  27. cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
  28. return 0;
  29. }
  30. static int vidioc_enum_fmt_vid_cap_callback( struct file* file, void* fh, struct v4l2_fmtdesc* f ){
  31. struct driverInstance* this = video_drvdata( file );
  32. const struct r5u870_pixelformat* pixelformat;
  33. if( f->index >= this->webcamFormatsCount ) return -EINVAL;
  34. pixelformat = &this->webcamFormats[ f->index ];
  35. f->flags = pixelformat->flags;
  36. f->pixelformat = pixelformat->pixelformat;
  37. strlcpy( f->description, pixelformat->description, sizeof(f->description) );
  38. return 0;
  39. }
  40. static int vidioc_g_fmt_vid_cap_callback( struct file* file, void* fh, struct v4l2_format* f ){
  41. struct driverInstance* this = video_drvdata( file );
  42. f->fmt.pix = this->webcamCurrentPixelformat;
  43. return 0;
  44. }
  45. static int vidioc_s_fmt_vid_cap_callback( struct file* file, void* fh, struct v4l2_format* f ){
  46. struct driverInstance* this = video_drvdata( file );
  47. int res;
  48. if( atomic_read( &this->usbDeviceIsDisconnected ) ){
  49. printk( KERN_WARNING "[%s] VIDIOC_S_FMT: device disconnected\n", KBUILD_MODNAME );
  50. return -EIO;
  51. }
  52. if( !memcmp(&f->fmt.pix, &this->webcamCurrentPixelformat, sizeof(f->fmt.pix)) ){
  53. printk( KERN_NOTICE "[%s] VIDIOC_S_FMT: nothing to do\n", KBUILD_MODNAME );
  54. return 0;
  55. }
  56. if( atomic_read(&this->webcamIsCaptuing) ){
  57. printk( KERN_WARNING "[%s] VIDIOC_S_FMT: capture in progress\n", KBUILD_MODNAME );
  58. return -EBUSY;
  59. }
  60. res = webcamTryFormat( this, &f->fmt.pix, 1 );
  61. if( res )printk( KERN_ERR "[%s] VIDIOC_S_FMT: err: %i\n", KBUILD_MODNAME, res );
  62. return res;
  63. }
  64. static int vidioc_try_fmt_vid_cap_callback( struct file* file, void* fh, struct v4l2_format* f ){
  65. struct driverInstance* this = video_drvdata( file );
  66. if ( atomic_read( &this->usbDeviceIsDisconnected ) ) return -EIO;
  67. return webcamTryFormat( this, &f->fmt.pix, 0 );
  68. }
  69. static int vidioc_enum_input_callback( struct file* file, void* fh, struct v4l2_input* input ){
  70. const char camName[] = "Camera";
  71. if( input->index ) return -EINVAL;
  72. strlcpy( input->name, camName, sizeof(input->name) );
  73. input->type = V4L2_INPUT_TYPE_CAMERA;
  74. return 0;
  75. }
  76. static int vidioc_g_input_callback( struct file* file, void* fh, unsigned int* i ){
  77. *i = 0;
  78. return 0;
  79. }
  80. static int vidioc_s_input_callback( struct file* file, void* fh, unsigned int i ){
  81. return ( i ? -EINVAL : 0 );
  82. }
  83. /*
  84. TODO: Come up with something with standards.
  85. I don’t know what to specify as the standard, so I just write 0.
  86. Some programs, for example skype, do not work if these functions are not implemented.
  87. */
  88. static int vidioc_querystd_callback( struct file* file, void* fh, v4l2_std_id* argp ){
  89. printk( KERN_NOTICE "[%s] FIXME: %s is not implemented!\n", KBUILD_MODNAME, __FUNCTION__ );
  90. *argp = 0;
  91. return 0;
  92. }
  93. static int vidioc_g_std_callback( struct file* file, void* fh, v4l2_std_id* argp ){
  94. printk( KERN_NOTICE "[%s] FIXME: %s is not implemented!\n", KBUILD_MODNAME, __FUNCTION__ );
  95. *argp = 0;
  96. return 0;
  97. }
  98. static int vidioc_s_std_callback( struct file* file, void* fh, v4l2_std_id argp ){
  99. printk( KERN_NOTICE "[%s] FIXME: %s is not implemented!\n", KBUILD_MODNAME, __FUNCTION__ );
  100. return 0;
  101. }
  102. static int vidioc_enum_framesizes_callback( struct file* file, void* fh, struct v4l2_frmsizeenum* fsize ){
  103. struct driverInstance* this = video_drvdata( file );
  104. const struct r5u870_resolution* resolutionTable;
  105. int i;
  106. resolutionTable = webcamGetFormatResolutionTable( this, fsize->pixel_format );
  107. if( !resolutionTable ) return -EINVAL;
  108. for( i = 0; resolutionTable[i].width; i++ ){
  109. if( i == fsize->index ){
  110. fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
  111. fsize->discrete.width = resolutionTable[i].width;
  112. fsize->discrete.height = resolutionTable[i].height;
  113. return 0;
  114. }
  115. }
  116. return -EINVAL;
  117. }
  118. static int vidioc_enum_frameintervals_callback( struct file* file, void* fh, struct v4l2_frmivalenum* fival ){
  119. struct driverInstance* this = video_drvdata( file );
  120. const struct r5u870_resolution* resolutionTable;
  121. int i;
  122. if( fival->index ) return -EINVAL;
  123. resolutionTable = webcamGetFormatResolutionTable( this, fival->pixel_format );
  124. if( !resolutionTable ) return -EINVAL;
  125. for( i = 0; resolutionTable[i].width; i++ ){
  126. if( fival->width == resolutionTable[i].width && fival->height == resolutionTable[i].height ){
  127. fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
  128. fival->discrete.numerator = resolutionTable[i].width * resolutionTable[i].height * 2;
  129. fival->discrete.denominator = resolutionTable[i].requiredBandwidth;
  130. return 0;
  131. }
  132. }
  133. return -EINVAL;
  134. }
  135. /****************************
  136. * videobuf2 ops *
  137. ****************************/
  138. //These callbacks are protected by this->videobuf2Queue.lock.
  139. static int queue_setup_callback( struct vb2_queue* videobufQueue, unsigned int* numBuffers, unsigned int* numPlanes, unsigned int sizes[], struct device* alloc_devs[] ){
  140. struct driverInstance* this = videobufQueue->drv_priv;
  141. if( *numBuffers < VIDEOBUF_QUEUE_MIN_BUF_NEED ) *numBuffers = VIDEOBUF_QUEUE_MIN_BUF_NEED;
  142. *numPlanes = 1;
  143. sizes[0] = this->webcamCurrentPixelformat.sizeimage;
  144. return 0;
  145. }
  146. //called every time the buffer is queued from userspace and from the VIDIOC_PREPARE_BUF ioctl
  147. static int buf_prepare_callback( struct vb2_buffer* videoBuffer ){
  148. struct driverInstance* this = vb2_get_drv_priv( videoBuffer->vb2_queue );
  149. if ( vb2_plane_size( videoBuffer, 0 ) < this->webcamCurrentPixelformat.sizeimage ) {
  150. printk( KERN_ERR "[%s] buffer too small (%lu < %u)\n", KBUILD_MODNAME, vb2_plane_size( videoBuffer, 0 ), this->webcamCurrentPixelformat.sizeimage );
  151. return -EINVAL;
  152. }
  153. vb2_set_plane_payload( videoBuffer, 0, this->webcamCurrentPixelformat.sizeimage );
  154. return 0;
  155. }
  156. //passes buffer to the driver; driver should give the buffer back by calling vb2_buffer_done() function
  157. static void buf_queue_callback( struct vb2_buffer* videoBuffer ){
  158. struct driverInstance* this = vb2_get_drv_priv( videoBuffer->vb2_queue );
  159. struct videobuffer_capsule* videobufCapsule = container_of( videoBuffer, struct videobuffer_capsule, videobuffer );
  160. unsigned long flags = 0;
  161. if( atomic_read( &this->buflistIsDisabled ) ){
  162. videoBuffer->timestamp = ktime_get_ns();
  163. vb2_buffer_done( videoBuffer, VB2_BUF_STATE_ERROR );
  164. }else{
  165. spin_lock_irqsave( &this->buflistSpinlock, flags );
  166. list_add_tail( &videobufCapsule->listItem, &this->buflist );
  167. spin_unlock_irqrestore( &this->buflistSpinlock, flags );
  168. }
  169. }
  170. static int start_streaming_callback( struct vb2_queue* videobufQueue, unsigned int count ){
  171. struct driverInstance* this = vb2_get_drv_priv( videobufQueue );
  172. return webcamCaptureStart( this );
  173. }
  174. static void stop_streaming_callback( struct vb2_queue* videobufQueue ){
  175. struct driverInstance* this = videobufQueue->drv_priv;
  176. webcamCaptureStop( this );
  177. atomic_set( &this->buflistIsDisabled, 0 );
  178. }
  179. /****************************
  180. * USB *
  181. ****************************/
  182. static int usbDeviceProbe_callback( struct usb_interface* usbInterface, const struct usb_device_id* usbDeviceId ){
  183. int err = 0;
  184. //void * devm_kzalloc(struct device * dev, size_t size, gfp_t gfp);
  185. struct driverInstance* this = devm_kzalloc( &usbInterface->dev, sizeof(struct driverInstance), GFP_KERNEL );
  186. if( !this ){
  187. printk( KERN_ERR "[%s] devm_kzalloc err\n", KBUILD_MODNAME );
  188. return -ENOMEM;
  189. }
  190. this->usbInterface = usb_get_intf( usbInterface );//NEED CLEAN
  191. this->usbDevice = usb_get_dev( interface_to_usbdev(usbInterface) );//NEED CLEAN
  192. this->usbDeviceDriver = to_usb_driver( usbInterface->dev.driver );
  193. this->dev = &usbInterface->dev;
  194. INIT_LIST_HEAD( &this->buflist );
  195. mutex_init( &this->lock );//Initialize the mutex to unlocked state.
  196. spin_lock_init( &this->buflistSpinlock );
  197. INIT_LIST_HEAD( &this->claimedInterfacesList );
  198. err = webcamInit( this, usbDeviceId );//NEED CLEAN
  199. if( err ){
  200. printk( KERN_ERR "[%s] WebcamInit failed: %i\n", KBUILD_MODNAME, err );
  201. goto l_put_interface_and_usb_device;
  202. }
  203. err = v4l2_device_register( this->dev, &this->v4l2Device );//NEED CLEAN
  204. if( err ){
  205. printk( KERN_ERR "[%s] v4l2_device_register result: %i\n", KBUILD_MODNAME, err );
  206. goto l_webcamRelease;
  207. }
  208. //videobuf2 queue init
  209. this->videobuf2Queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  210. this->videobuf2Queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
  211. this->videobuf2Queue.drv_priv = this;
  212. this->videobuf2Queue.buf_struct_size = sizeof( struct videobuffer_capsule );
  213. this->videobuf2Queue.ops = &videobuf2QueueOps;
  214. this->videobuf2Queue.mem_ops = &vb2_vmalloc_memops;//videobuf2MemOps
  215. this->videobuf2Queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
  216. this->videobuf2Queue.min_buffers_needed = VIDEOBUF_QUEUE_MIN_BUF_NEED;
  217. this->videobuf2Queue.lock = &this->lock;
  218. this->videobuf2Queue.gfp_flags = GFP_KERNEL;//GFP_DMA32
  219. err = vb2_queue_init( &this->videobuf2Queue );
  220. if( err ){
  221. printk( KERN_ERR "[%s] vb2_queue_init err: %i\n", KBUILD_MODNAME, err );
  222. goto l_v4l2_device_unregister;
  223. }
  224. //videoDevice init
  225. strlcpy( this->videoDevice.name, KBUILD_MODNAME, sizeof(this->videoDevice.name) );
  226. this->videoDevice.release = video_device_release_empty;
  227. this->videoDevice.fops = &v4l2FileOperations;
  228. this->videoDevice.ioctl_ops = &videoDeviceIoctlOps;
  229. this->videoDevice.lock = &this->lock;//This lock will be automatically applied in ioctl_ops.
  230. this->videoDevice.queue = &this->videobuf2Queue;
  231. this->videoDevice.v4l2_dev = &this->v4l2Device;
  232. this->videoDevice.tvnorms = V4L2_STD_ALL;
  233. this->videoDevice.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
  234. video_set_drvdata( &this->videoDevice, this );
  235. err = video_register_device( &this->videoDevice, VFL_TYPE_VIDEO, -1 );//NEED CLEAN
  236. if( err ){
  237. printk( KERN_ERR "[%s] video_register_device err: %i\n", KBUILD_MODNAME, err );
  238. goto l_v4l2_device_unregister;
  239. }
  240. this->urbstreamWorkqueue = create_singlethread_workqueue( KBUILD_MODNAME );//NEED CLEAN
  241. //static inline void usb_set_intfdata(struct usb_interface *intf, void *data);
  242. usb_set_intfdata( usbInterface, this );
  243. return err;
  244. l_v4l2_device_unregister:
  245. v4l2_device_unregister( &this->v4l2Device );
  246. l_webcamRelease:
  247. webcamRelease( this );
  248. l_put_interface_and_usb_device:
  249. usb_put_dev( this->usbDevice );
  250. usb_put_intf( this->usbInterface );
  251. return err;
  252. }
  253. //also called befoure module unloading
  254. static void usbDeviceDisconnect_callback( struct usb_interface* usbInterface ){
  255. //static inline void *usb_get_intfdata(struct usb_interface *intf);
  256. struct driverInstance* this = usb_get_intfdata( usbInterface );
  257. atomic_set( &this->usbDeviceIsDisconnected, 1 );
  258. webcamRelease( this );
  259. flush_workqueue( this->urbstreamWorkqueue );
  260. destroy_workqueue( this->urbstreamWorkqueue );
  261. video_unregister_device( &this->videoDevice );
  262. v4l2_device_unregister( &this->v4l2Device );
  263. usb_set_intfdata( usbInterface, NULL );
  264. usb_put_dev( this->usbDevice );
  265. usb_put_intf( this->usbInterface );
  266. }
  267. /****************************
  268. * module entry point *
  269. ****************************/
  270. static int onLoad( void ){
  271. printk( KERN_NOTICE "%s is here.\n", KBUILD_MODNAME );
  272. return usb_register( &usbDriver_s );
  273. }
  274. static void onUnload( void ){
  275. usb_deregister( &usbDriver_s );
  276. printk( KERN_NOTICE "%s has been unloaded.\n", KBUILD_MODNAME );
  277. }
  278. module_init( onLoad );
  279. module_exit( onUnload );
  280. MODULE_LICENSE( "GPL" );