160 lines
3.8 KiB
C
160 lines
3.8 KiB
C
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/usb.h>
|
|
|
|
#define CGU18
|
|
#ifdef CGU18
|
|
#include <linux/uaccess.h>
|
|
#endif
|
|
|
|
//https://sysplay.in/blog/linux-device-drivers/2014/02/usb-drivers-in-linux-data-transfer-to-from-usb-devices/
|
|
|
|
#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
|
|
#define BULK_EP_OUT 0x01
|
|
#define BULK_EP_IN 0x82
|
|
#define MAX_PKT_SIZE 512
|
|
|
|
static struct usb_device *device;
|
|
static struct usb_class_driver class;
|
|
static unsigned char bulk_buf[MAX_PKT_SIZE];
|
|
|
|
static int usb_fjveincam_open(struct inode *i, struct file *f)
|
|
{
|
|
printk(KERN_NOTICE "fjveincam open");
|
|
return 0;
|
|
}
|
|
static int usb_fjveincam_close(struct inode *i, struct file *f)
|
|
{
|
|
printk(KERN_NOTICE "fjveincam close");
|
|
return 0;
|
|
}
|
|
static ssize_t usb_fjveincam_read(struct file *f, char __user *buf, size_t cnt, loff_t *off)
|
|
{
|
|
int retval;
|
|
int read_cnt;
|
|
printk(KERN_NOTICE "fjveincam read");
|
|
|
|
/* Read the data from the bulk endpoint */
|
|
retval = usb_bulk_msg(device, usb_rcvbulkpipe(device, BULK_EP_IN),
|
|
bulk_buf, MAX_PKT_SIZE, &read_cnt, 5000);
|
|
if (retval)
|
|
{
|
|
printk(KERN_ERR "Bulk message returned %d\n", retval);
|
|
return retval;
|
|
}
|
|
if (copy_to_user(buf, bulk_buf, MIN(cnt, read_cnt)))
|
|
{
|
|
return -EFAULT;
|
|
}
|
|
|
|
return MIN(cnt, read_cnt);
|
|
}
|
|
static ssize_t usb_fjveincam_write(struct file *f, const char __user *buf, size_t cnt,
|
|
loff_t *off)
|
|
{
|
|
int retval;
|
|
int wrote_cnt = MIN(cnt, MAX_PKT_SIZE);
|
|
printk(KERN_NOTICE "fjveincam write");
|
|
|
|
#ifdef CGU18
|
|
if (copy_from_user(bulk_buf, buf, MIN(cnt, MAX_PKT_SIZE)))
|
|
#else
|
|
if (copy_from_user(bulk_buf, buf, MIN(cnt, MAX_PKT_SIZE)))
|
|
#endif
|
|
{
|
|
return -EFAULT;
|
|
}
|
|
|
|
/* Write the data into the bulk endpoint */
|
|
retval = usb_bulk_msg(device, usb_sndbulkpipe(device, BULK_EP_OUT),
|
|
bulk_buf, MIN(cnt, MAX_PKT_SIZE), &wrote_cnt, 5000);
|
|
if (retval)
|
|
{
|
|
printk(KERN_ERR "Bulk message returned %d\n", retval);
|
|
return retval;
|
|
}
|
|
|
|
return wrote_cnt;
|
|
}
|
|
|
|
static struct file_operations fops =
|
|
{
|
|
.owner = THIS_MODULE,
|
|
.open = usb_fjveincam_open,
|
|
.release = usb_fjveincam_close,
|
|
.read = usb_fjveincam_read,
|
|
.write = usb_fjveincam_write,
|
|
};
|
|
|
|
static int usb_fjveincam_probe(struct usb_interface *interface, const struct usb_device_id *id)
|
|
{
|
|
int retval;
|
|
|
|
device = interface_to_usbdev(interface);
|
|
printk(KERN_NOTICE "fjveincam probe");
|
|
|
|
class.name = "usb/pen%d";
|
|
class.fops = &fops;
|
|
if ((retval = usb_register_dev(interface, &class)) < 0)
|
|
{
|
|
/* Something prevented us from registering this driver */
|
|
printk(KERN_ERR "Not able to get a minor for this device.");
|
|
}
|
|
else
|
|
{
|
|
printk(KERN_INFO "Minor obtained: %d\n", interface->minor);
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
static void usb_fjveincam_disconnect(struct usb_interface *interface)
|
|
{
|
|
printk(KERN_NOTICE "fjveincam disconnect");
|
|
|
|
usb_deregister_dev(interface, &class);
|
|
}
|
|
|
|
/* Table of devices that work with this driver */
|
|
static struct usb_device_id usb_fjveincam_table[] =
|
|
{
|
|
{ USB_DEVICE(0x058F, 0x6387) },
|
|
{} /* Terminating entry */
|
|
};
|
|
MODULE_DEVICE_TABLE (usb, usb_fjveincam_table);
|
|
|
|
static struct usb_driver usb_fjveincam_driver =
|
|
{
|
|
.name = "usb_fjveincam_driver",
|
|
.probe = usb_fjveincam_probe,
|
|
.disconnect = usb_fjveincam_disconnect,
|
|
.id_table = usb_fjveincam_table,
|
|
};
|
|
|
|
static int __init usb_fjveincam_init(void)
|
|
{
|
|
int result;
|
|
printk(KERN_NOTICE "fjveincam init");
|
|
|
|
/* Register this driver with the USB subsystem */
|
|
if ((result = usb_register(&usb_fjveincam_driver)))
|
|
{
|
|
printk(KERN_ERR "usb_register failed. Error number %d", result);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static void __exit usb_fjveincam_exit(void)
|
|
{
|
|
printk(KERN_NOTICE "fjveincam exit");
|
|
|
|
/* Deregister this driver with the USB subsystem */
|
|
usb_deregister(&usb_fjveincam_driver);
|
|
}
|
|
|
|
module_init(usb_fjveincam_init);
|
|
module_exit(usb_fjveincam_exit);
|
|
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_AUTHOR("Carl Goodwin <cg@dispension.com>");
|
|
MODULE_DESCRIPTION("USB Pen Device Driver"); |