Am Dienstag, 24. April 2007 13:19 schrieb Wael Adel: > so these are the required modifications required to wait until the urb > is finished then i can transfer the read data to the user-space > > *********************************************************************************************************************** > static void skel_read_bulk_callback(struct urb *urb, struct pt_regs *regs) > { > struct usb_skel *dev; > complete((struct completion *)urb->context); > dev = (struct usb_skel *)urb->context; > > > /* sync/async unlink faults aren't errors */ > if (urb->status && > !(urb->status == -ENOENT || > urb->status == -ECONNRESET || > urb->status == -ESHUTDOWN)) { > dbg("%s - nonzero write bulk status received: %d", > __FUNCTION__, urb->status); > } > > /* free up our allocated buffer */ > usb_buffer_free(urb->dev, urb->transfer_buffer_length, > urb->transfer_buffer, urb->transfer_dma);
Don't free the buffer here. You want to read from it. > up(&dev->limit_sem); > } > > static ssize_t skel_read(struct file *file, const char *user_buffer, > size_t count, loff_t *ppos) > { > struct completion done; You need to call init_completion() on that before you use it. > struct usb_skel *dev; > int retval = 0,readbytes; > struct urb *urb = NULL; > char *buf = NULL; > size_t readsize = min(count, (size_t)MAX_TRANSFER); > > dev = (struct usb_skel *)file->private_data; > > /* verify that we actually have some data to write */ read that would be > if (count == 0) > goto exit; > > /* limit the number of URBs in flight to stop a user from using up all > RAM */ > if (down_interruptible(&dev->limit_sem)) { > retval = -ERESTARTSYS; > goto exit; > } > > /* create a urb, and a buffer for it, and copy the data to the urb */ > urb = usb_alloc_urb(0, GFP_KERNEL); > if (!urb) { > retval = -ENOMEM; > goto error; > } > > buf = usb_buffer_alloc(dev->udev, readsize, GFP_KERNEL, > &urb->transfer_dma); > if (!buf) { > retval = -ENOMEM; > goto error; > } > > /* initialize the urb properly */ > usb_fill_bulk_urb(urb, dev->udev, > usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr), > buf, readsize, skel_read_bulk_callback, dev); You must pass a pointer to done, not dev. > urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; > > /* send the data out the bulk port */ > retval = usb_submit_urb(urb, GFP_KERNEL); > if (retval) { > err("%s - failed submitting write urb, error %d", __FUNCTION__, > retval); write? > goto error; > } > > wait_for_completion(&done); > > if ( copy_to_user(user_buffer, dev->bulk_in_buffer, readbytes) ) > retval = -EFAULT; > else > retval = readbytes; 1. Here you need to free the URB and the buffer 2. You must deal with your device delivering less bytes than you asked for You can use urb->actual_length > return retval; > > /* release our reference to this urb, the USB core will eventually > free it entirely */ > usb_free_urb(urb); > > exit: > return readsize; > > error: > usb_buffer_free(dev->udev, readsize, buf, urb->transfer_dma); > usb_free_urb(urb); > up(&dev->limit_sem); > return retval; > } > ********************************************************************************************************************* > is it right? or there is something else i should adjust. > thanks in advance. > > > > > HTH > > Oliver > > -- > > SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg) > > This signature is a legal requirement > > > -- SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg) This signature is a legal requirement ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/ _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel