yoloserv/modules/atlantean/src/fjveincam.c
2023-05-26 07:24:58 -03:00

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");