/* Read entry point */
static ssize_t
tele_read(struct file *file, char *buffer,
size_t count, loff_t *ppos)
{
int retval, bytes_read;
tele_device_t *tele_device;
/* Get the address of tele_device */
tele_device = (tele_device_t *)file->private_data;
/* ... */
/* Synchronous read */
retval = usb_bulk_msg(tele_device->usbdev, /* usb_device */
usb_rcvbulkpipe(tele_device->usbdev,
tele_device->bulk_in_addr),
/* Pipe */
tele_device->bulk_in_buf,
/* Read buffer */
min(tele_device->bulk_in_len,count),
/* Bytes to read */
&bytes_read, /* Bytes read */
5000); /* Timeout in 5 sec */
/* Copy telemetry data to user space */
if (!retval) {
if (copy_to_user(buffer, tele_device->bulk_in_buf,
bytes_read)) {
return -EFAULT;
} else {
return bytes_read;
}
}
return retval;
}
/* Write entry point */
static ssize_t
tele_write(struct file *file, const char *buffer,
size_t write_count, loff_t *ppos)
{
char *tele_buf = NULL;
struct urb *urb = NULL;
tele_device_t *tele_device;
/* Get the address of tele_device */
tele_device = (tele_device_t *)file->private_data;
/* ... */
/* Allocate a bulk URB */
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
return -ENOMEM;
}
/* Allocate a DMA-consistent transfer buffer and copy in
data from user space. On return, tele_buf contains
the buffer’s CPU address, while urb->transfer_dma
contains the DMA address */
tele_buf = usb_buffer_alloc(tele_dev->usbdev, write_count,
GFP_KERNEL, &urb->transfer_dma);
if (copy_from_user(tele_buf, buffer, write_count)) {
usb_buffer_free(tele_device->usbdev, write_count,
tele_buf, urb->transfer_dma);
usb_free_urb(urb);
return -EFAULT
}
/* Populate bulk URB fields */
usb_fill_bulk_urb(urb, tele_device->usbdev,
usb_sndbulkpipe(tele_device->usbdev,
tele_device->bulk_out_addr),
tele_buf, write_count, tele_write_callback,
tele_device);
/* urb->transfer_dma is valid, so preferably utilize
that for data transfer */
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
/* Submit URB asynchronously */
usb_submit_urb(urb, GFP_KERNEL);
/* Release URB reference */
usb_free_urb(urb);
return(write_count);
}
/* Write callback */
static void
tele_write_callback(struct urb *urb)
{
tele_device_t *tele_device;
/* Get the address of tele_device */
tele_device = (tele_device_t *)urb->context;
/* urb->status contains the submission status. It’s 0 if
successful. Resubmit the URB in case of errors other than
-ENOENT, -ECONNRESET, and -ESHUTDOWN */
/* ... */
/* Free the transfer buffer. usb_buffer_free() is the
release-counterpart of usb_buffer_alloc() called
from tele_write() */
usb_buffer_free(urb->dev, urb->transfer_buffer_length,
urb->transfer_buffer, urb->transfer_dma);
}
syntax highlighted by Code2HTML, v. 0.9.1