urb.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. #include "shared.h"
  2. #include "urb.h"
  3. /****************************
  4. * ALTSETTING *
  5. ****************************/
  6. //Traverse the alternate setting list and find one that provides
  7. //the least bandwidth that satisfies the minimum requirement.
  8. int usbcam_choose_altsetting( struct driverInstance* this ){
  9. struct usb_interface *intf;
  10. const struct usb_host_interface *aintf;
  11. const struct usb_endpoint_descriptor* endpointDescriptor = NULL;
  12. int i, j;
  13. int endpointMaxPacketSize;
  14. int bandwidth;
  15. int best_alt = -1, best_alt_bw = 0;
  16. int interfaceNumber = this->urbstreamInterfaceNumber;
  17. int pipe = usb_rcvisocpipe( this->usbDevice, this->urbstreamEndpoint );
  18. if( atomic_read(&this->usbDeviceIsDisconnected) ){
  19. printk( KERN_WARNING "[%s] %s: device is disconnected\n", KBUILD_MODNAME, __FUNCTION__ );
  20. return -ENODEV;
  21. }
  22. if( interfaceNumber < 0 ) interfaceNumber = this->usbInterface->cur_altsetting->desc.bInterfaceNumber;
  23. intf = usb_ifnum_to_if( this->usbDevice, interfaceNumber );
  24. if( !intf ) {
  25. printk( KERN_WARNING "[%s] %s: interface %d does not exist\n", KBUILD_MODNAME, __FUNCTION__, interfaceNumber );
  26. return -ENODEV;
  27. }
  28. for (i = 0; i < intf->num_altsetting; i++) {
  29. aintf = &intf->altsetting[i];
  30. for (j = 0; j < aintf->desc.bNumEndpoints; j++) {
  31. endpointDescriptor = &aintf->endpoint[j].desc;
  32. if( (endpointDescriptor->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) == usb_pipeendpoint(pipe) )break;
  33. }
  34. if ( j == aintf->desc.bNumEndpoints ) {
  35. //Desired endpoint not present in this descriptor
  36. printk( KERN_NOTICE "[%s] altsetting %d has no EP%d\n", KBUILD_MODNAME, i, usb_pipeendpoint(pipe) );
  37. continue;
  38. }
  39. if ( !usb_endpoint_xfer_isoc(endpointDescriptor) || !usb_endpoint_dir_in(endpointDescriptor) ){
  40. //Something is horribly wrong
  41. printk( KERN_NOTICE "[%s] altsetting %d has unexpected EP%d\n", KBUILD_MODNAME, i, usb_pipeendpoint(pipe) );
  42. continue;
  43. }
  44. bandwidth = 0;
  45. endpointMaxPacketSize = le16_to_cpu( endpointDescriptor->wMaxPacketSize );
  46. if( this->usbDevice->speed == USB_SPEED_HIGH ){
  47. //8 uframes per regular frame
  48. bandwidth = 8000;
  49. //high bandwidth endpoint?
  50. endpointMaxPacketSize = (endpointMaxPacketSize & 0x7ff) * (((endpointMaxPacketSize >> 11) & 0x3) + 1);
  51. }else{
  52. bandwidth = 1000;
  53. endpointMaxPacketSize &= 0x7ff;
  54. }
  55. bandwidth *= endpointMaxPacketSize;
  56. //Divide by interval / frame skippage
  57. bandwidth = bandwidth / (1 << (endpointDescriptor->bInterval - 1));
  58. printk( KERN_NOTICE "[%s] altsetting %d provides %d B/s bandwidth\n", KBUILD_MODNAME, i, bandwidth );
  59. //Check the bandwidth
  60. if( bandwidth < this->webcamCurrentResolution->requiredBandwidth ) continue;
  61. //Check the packet size
  62. if( (this->urbstreamMinPacketSize >= 0) && (endpointMaxPacketSize < this->urbstreamMinPacketSize) ) continue;
  63. if( (best_alt < 0) || (bandwidth < best_alt_bw) ){
  64. best_alt = i;
  65. best_alt_bw = bandwidth;
  66. }
  67. }
  68. if (best_alt == -1) return -ENODEV;
  69. this->usbCurrentAltsetting = best_alt;
  70. return 0;
  71. }
  72. /****************************
  73. * CLEANUP *
  74. ****************************/
  75. static void usbcam_urb_free( struct urb* urbp ){
  76. usb_free_coherent( urbp->dev, urbp->transfer_buffer_length, urbp->transfer_buffer, urbp->transfer_dma );
  77. //usb_buffer_free( urbp->dev, urbp->transfer_buffer_length, urbp->transfer_buffer, urbp->transfer_dma );
  78. usb_free_urb( urbp );
  79. }
  80. void usbcam_urbstream_cleanup( struct driverInstance* this ){
  81. int i;
  82. for( i = 0; i < URBSTREAM_URB_COUNT; i++ ) if( this->urbstreamUrbs[i].urbp ){
  83. usbcam_urb_free( this->urbstreamUrbs[i].urbp );
  84. this->urbstreamUrbs[i].urbp = NULL;
  85. }
  86. }
  87. /****************************
  88. * WORK PROCESS *
  89. ****************************/
  90. //NEVER SLEEP IN A COMPLETION HANDLER.
  91. //These are often called in atomic context.
  92. static void urbCompleteHandler( struct urb* urb ){
  93. struct urb_capsule* urbCapsule = urb->context;
  94. struct driverInstance* this = urbCapsule->driverInstanceThis;
  95. if( urb->status == -ECONNRESET || urb->status == -ENOENT ) return;//usb_kill_urb() or usb_unlink_urb()
  96. if( !queue_work( this->urbstreamWorkqueue, &urbCapsule->workitem ) ) printk( KERN_ERR "[%s] %s: queue_work err\n", KBUILD_MODNAME, __FUNCTION__ );
  97. }
  98. static void usbcam_urbstream_iso_process( struct work_struct* work ){
  99. struct urb_capsule* urbCapsule = container_of( work, struct urb_capsule, workitem );
  100. struct driverInstance* this = urbCapsule->driverInstanceThis;
  101. struct urb* urbp = urbCapsule->urbp;
  102. int i = 0;
  103. int res = 0;
  104. char* buf;
  105. int len;
  106. int status;
  107. if( !atomic_read( &this->urbstreamIsStreaming ) ) return;
  108. //printk( KERN_NOTICE "[%s] urbstream[%d] processing %p\n", KBUILD_MODNAME, this->us_endpoint, ibp );
  109. for( i = 0; i < urbp->number_of_packets; i++ ){
  110. buf = (((char *) urbp->transfer_buffer) + urbp->iso_frame_desc[i].offset);
  111. len = urbp->iso_frame_desc[i].actual_length;
  112. status = urbp->iso_frame_desc[i].status;
  113. urbp->iso_frame_desc[i].actual_length = 0;
  114. urbp->iso_frame_desc[i].status = 0;
  115. //void r5u870_iso_packet_done( struct driverInstance* this, const uint8_t *pktdata, int pktlen, int pktstatus )
  116. r5u870_iso_packet_done( this, buf, len, status );
  117. }
  118. if( atomic_read( &this->urbstreamIsStreaming ) ){
  119. res = usb_submit_urb( urbp, GFP_ATOMIC );
  120. if( res == -EL2NSYNC ) res = usb_submit_urb( urbp, GFP_ATOMIC );
  121. if( res ){
  122. printk( KERN_NOTICE "[%s] urbstream[%d] resubmit %p failed: %d\n", KBUILD_MODNAME, this->urbstreamEndpoint, urbCapsule, res );
  123. webcamCaptureStop( this );
  124. }
  125. }
  126. }
  127. /****************************
  128. * STOP START *
  129. ****************************/
  130. void usbcam_urbstream_stop( struct driverInstance* this ){
  131. int i = 0;
  132. atomic_set( &this->urbstreamIsStreaming, 0 );
  133. for( i = 0; i < URBSTREAM_URB_COUNT; i++ ) usb_kill_urb( this->urbstreamUrbs[i].urbp );
  134. }
  135. int usbcam_urbstream_start( struct driverInstance* this ){
  136. int res = 0;
  137. int i = 0;
  138. if( atomic_read( &this->urbstreamIsStreaming ) ){
  139. printk( KERN_WARNING "[%s] %s: urbstream[%d] already streaming\n", KBUILD_MODNAME, __FUNCTION__, this->urbstreamEndpoint );
  140. return -EEXIST;
  141. }
  142. atomic_set( &this->urbstreamIsStreaming, 1 );
  143. for( i = 0; i < URBSTREAM_URB_COUNT; i++ ){
  144. res = usb_submit_urb( this->urbstreamUrbs[i].urbp, GFP_KERNEL );
  145. if( res == -EL2NSYNC ) res = usb_submit_urb( this->urbstreamUrbs[i].urbp, GFP_KERNEL );
  146. if( res ){
  147. printk( KERN_ERR "[%s] %s: URB submit failed: %d\n", KBUILD_MODNAME, __FUNCTION__, res );
  148. printk( KERN_ERR "[%s] urbstream[%d] start failed: %i\n", KBUILD_MODNAME, this->urbstreamEndpoint, res );
  149. usbcam_urbstream_stop( this );
  150. break;
  151. }
  152. }
  153. return res;
  154. }
  155. /****************************
  156. * PREPARE *
  157. ****************************/
  158. struct urb* usbcam_urb_alloc( struct driverInstance* this, int packetSize ){
  159. struct urb* urbp;
  160. int totalBytesCount;
  161. int i;
  162. urbp = usb_alloc_urb( URBSTREAM_URB_PACKETS_COUNT, GFP_KERNEL );
  163. if( !urbp ) return NULL;
  164. urbp->dev = this->usbDevice;
  165. urbp->pipe = usb_rcvisocpipe( this->usbDevice, this->urbstreamEndpoint );
  166. urbp->number_of_packets = URBSTREAM_URB_PACKETS_COUNT;
  167. urbp->transfer_buffer = NULL;
  168. urbp->transfer_buffer_length = 0;
  169. totalBytesCount = packetSize * URBSTREAM_URB_PACKETS_COUNT;
  170. urbp->transfer_buffer = usb_alloc_coherent( urbp->dev, totalBytesCount, GFP_KERNEL, &urbp->transfer_dma );
  171. //urbp->transfer_buffer = usb_buffer_alloc( urbp->dev, totalBytesCount, GFP_KERNEL, &urbp->transfer_dma );
  172. if( !urbp->transfer_buffer ){
  173. usb_free_urb( urbp );
  174. return NULL;
  175. }
  176. urbp->transfer_buffer_length = totalBytesCount;
  177. urbp->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
  178. urbp->transfer_flags |= URB_ISO_ASAP;
  179. for(i = 0; i < URBSTREAM_URB_PACKETS_COUNT; i++){
  180. urbp->iso_frame_desc[i].offset = (i * packetSize);
  181. urbp->iso_frame_desc[i].length = packetSize;
  182. urbp->iso_frame_desc[i].actual_length = 0;
  183. urbp->iso_frame_desc[i].status = 0;
  184. }
  185. urbp->complete = urbCompleteHandler;
  186. urbp->interval = 1;//FIXME: find the appropriate interval for the endpoint
  187. return urbp;
  188. }
  189. int usbcam_urbstream_config_iso( struct driverInstance* this ){
  190. struct usb_host_endpoint* endpoint;
  191. int err = 0;
  192. int packetSize = 0;
  193. int i;
  194. endpoint = this->usbDevice->ep_in[this->urbstreamEndpoint];
  195. if( !endpoint ){
  196. printk( KERN_ERR "[%s] Endpoint %d is not exist\n", KBUILD_MODNAME, this->urbstreamEndpoint );
  197. return -EINVAL;
  198. }
  199. packetSize = __le16_to_cpu( endpoint->desc.wMaxPacketSize );
  200. if ( !packetSize ) {
  201. printk( KERN_ERR "[%s] urbstream[%d]: current endpoint has maxpacket=0\n", KBUILD_MODNAME, this->urbstreamEndpoint );
  202. return -EINVAL;
  203. }
  204. if ( this->usbDevice->speed == USB_SPEED_HIGH ) packetSize = (packetSize & 0x7ff) * (((packetSize >> 11) & 0x3) + 1);
  205. else packetSize &= 0x7ff;
  206. printk( KERN_NOTICE "[%s] urbstream[%d] using packetSize %d\n", KBUILD_MODNAME, this->urbstreamEndpoint, packetSize );
  207. for( i = 0; i < URBSTREAM_URB_COUNT; i++ ){
  208. this->urbstreamUrbs[i].urbp = usbcam_urb_alloc( this, packetSize );
  209. if( !this->urbstreamUrbs[i].urbp ){
  210. usbcam_urbstream_cleanup( this );
  211. err = -ENOMEM;
  212. break;
  213. }
  214. this->urbstreamUrbs[i].urbp->context = &this->urbstreamUrbs[i];
  215. this->urbstreamUrbs[i].driverInstanceThis = this;
  216. INIT_WORK( &this->urbstreamUrbs[i].workitem, usbcam_urbstream_iso_process );
  217. }
  218. return err;
  219. }