trying to get the driver test
This commit is contained in:
parent
46710ce8c9
commit
a7b664e397
@ -1,6 +1,9 @@
|
|||||||
ACTION!="add",\
|
ACTION!="add",\
|
||||||
|
DRIVERS=="fjveincam",\
|
||||||
|
MODE="0666",
|
||||||
SUBSYSTEM=="usb",\
|
SUBSYSTEM=="usb",\
|
||||||
ATTRS{idVendor}=="04c5",\
|
ATTRS{idVendor}=="04c5",\
|
||||||
ATTRS{idProduct}=="1526",\
|
ATTRS{idProduct}=="1526",\
|
||||||
SYMLINK+="usb/fjveincam0",\
|
SYMLINK+="usb/fjveincam%n",\
|
||||||
RUN+="/bin/bash -c 'date >> /tmp/fjpv'"
|
RUN+="/bin/bash -c 'date >> /tmp/fjpv'",\
|
||||||
|
RUN+="/bin/bash -c 'echo $kernel _ $devpath _ $number id=$id MM=$major:$minor $name $sys >> /tmp/fjpv'"
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
VERSION := $(shell uname -r)
|
VERSION := $(shell uname -r)
|
||||||
#KERNDIR = /usr/src/linux-headers-5.15.0-58
|
#KERNDIR = /usr/src/linux-headers-5.15.0-58
|
||||||
KERNDIR = /usr/src/linux-headers-$(VERSION)
|
KERNDIR = /usr/src/linux-headers-$(VERSION)
|
||||||
INSTALLDIR = /lib/modules/$(VERSION)/drivers/usb/misc
|
INSTALLDIR = /lib/modules/$(VERSION)/kernel/drivers/usb/misc
|
||||||
BUILD_DIR := $(shell pwd)
|
BUILD_DIR := $(shell pwd)
|
||||||
VERBOSE = 0
|
VERBOSE = 0
|
||||||
TARGET = fjveincam
|
TARGET = fjveincam
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
sudo rmmod fjveincam.ko
|
rmmod fjveincam.ko
|
||||||
make clean
|
make clean
|
||||||
make
|
make
|
||||||
sudo cp fjveincam.ko /usr/lib/modules/5.15.0-72-generic/kernel/drivers/usb/misc/
|
make install
|
||||||
sudo insmod fjveincam.ko
|
cp fjveincam.ko /usr/lib/modules/`uname -r`/kernel/drivers/usb/misc/
|
||||||
|
cp 93-unicon-palmvene.rules /usr/lib/udev/rules.d/
|
||||||
|
insmod fjveincam.ko
|
||||||
|
depmod
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
/*
|
/**
|
||||||
* USB PalmSecure Sensor driver (kernel-2.6)
|
* USB PalmSecure Sensor driver (kernel-2.6)
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012 FUJITSU FRONTECH LIMITED
|
* Copyright (C) 2012 FUJITSU FRONTECH LIMITED
|
||||||
@ -8,36 +8,90 @@
|
|||||||
* 2 as published by the Free Software Foundation.
|
* 2 as published by the Free Software Foundation.
|
||||||
*
|
*
|
||||||
* Notes:
|
* Notes:
|
||||||
|
* Heavily based on usb_skeleton.c
|
||||||
|
* Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
|
||||||
*
|
*
|
||||||
* History:
|
* History:
|
||||||
*
|
*
|
||||||
* 2012-07-06 - V31L01
|
* 2012-07-06 - V31L01
|
||||||
* - first version
|
* - first version
|
||||||
*
|
*
|
||||||
|
* Problems? Try...
|
||||||
|
* lsusb or lsusb -vd MANU:PROD // swap in the device values << FUJITSU PalmSecure-F Pro
|
||||||
|
* sudo udevadm info -a -n /dev/usb/fjveincam0 // get infor about the device << major=180 minor=0
|
||||||
|
* cat /sys/class/usbmisc/fjveincam0/ * //
|
||||||
|
* ls -al /sys/class/usbmisc/fjveincam0/device/driver/module - coresize,
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h> //+
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
// kref.h-
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h> //+
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h> //+
|
||||||
#include <linux/usb.h>
|
#include <linux/usb.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* Define these values to match your devices */
|
||||||
|
#define VENDOR_ID 0x04C5
|
||||||
|
#define PRODUCT_ID 0x1526
|
||||||
|
|
||||||
|
/* table of devices that work with this driver */
|
||||||
|
static struct usb_device_id fjveincam_table [] = {
|
||||||
|
{ USB_DEVICE(VENDOR_ID, PRODUCT_ID) },
|
||||||
|
{ } /* Terminating entry */
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(usb, fjveincam_table);
|
||||||
|
|
||||||
|
|
||||||
|
/* Get a minor range for your devices from the usb maintainer */
|
||||||
|
#define USB_subminor_BASE 160
|
||||||
|
|
||||||
|
|
||||||
|
/* Structure to hold all of our device specific stuff */
|
||||||
|
struct fjveincam {
|
||||||
|
struct usb_device *udev;
|
||||||
|
unsigned char subminor; /* minor number - used in disconnect() */
|
||||||
|
char confirmed; /* Not zero if the device is used (Not in phase of confirming) */
|
||||||
|
int open_count; /* count the number of openers */
|
||||||
|
char *obuf, *ibuf; /* transfer buffers */
|
||||||
|
char bulk_in_ep; /* Endpoint assignments */
|
||||||
|
char bulk_out_ep; /* Endpoint assignments */
|
||||||
|
wait_queue_head_t wait_q; /* wait-queue for checking sensors */
|
||||||
|
struct mutex io_mutex; /* lock to prevent concurrent reads or writes */
|
||||||
|
int o_timeout; /* counter of open time out */
|
||||||
|
int r_error; /* counter of read error */
|
||||||
|
int r_lasterr; /* read last error */
|
||||||
|
int w_error; /* counter of write error */
|
||||||
|
int w_lasterr; /* write last error */
|
||||||
|
};
|
||||||
|
#define to_skel_dev(d) container_of(d, struct fjveincam, kref)
|
||||||
|
|
||||||
|
static struct usb_driver usb_fjveincam_driver;
|
||||||
|
//skel static void fjveincam_draw_down(struct usb_fjveincam *dev);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* our private defines. if this grows any larger, use your own .h file */
|
||||||
#include "fjveincam.h"
|
#include "fjveincam.h"
|
||||||
|
|
||||||
#define CONFIG_FJVEINCAM_DEBUG
|
|
||||||
|
|
||||||
/*
|
#define CONFIG_FJVEINCAM_DEBUGXXX
|
||||||
#undef dbg
|
|
||||||
#ifdef CONFIG_FJVEINCAM_DEBUG
|
|
||||||
#define dbg(format, arg...) printk(KERN_DEBUG __FILE__":%d : " format "\n" , __LINE__, ## arg);
|
//
|
||||||
#else
|
// # # ##### ###### ##### ## # ####
|
||||||
#define dbg(format, arg...)
|
// # # # # # # # # # #
|
||||||
#endif
|
// # # # ##### # # # # # ####
|
||||||
*/
|
// # # # # ##### ###### # #
|
||||||
|
// # # # # # # # # # # #
|
||||||
|
// ###### # # ###### # # # # ###### ####
|
||||||
|
//
|
||||||
|
|
||||||
/* Endpoint direction check macros */
|
/* Endpoint direction check macros */
|
||||||
#define IS_EP_BULK(ep) ((ep)->bmAttributes == USB_ENDPOINT_XFER_BULK ? 1 : 0)
|
#define IS_EP_BULK(ep) ((ep)->bmAttributes == USB_ENDPOINT_XFER_BULK ? 1 : 0)
|
||||||
@ -52,22 +106,20 @@
|
|||||||
|
|
||||||
/* minor number defines */
|
/* minor number defines */
|
||||||
|
|
||||||
#define USB_FJVEINCAM_MINOR_BASE 160 /* minor base number */
|
|
||||||
|
|
||||||
|
|
||||||
/* Waiting time for sensor confirming. */
|
/* Waiting time for sensor confirming. */
|
||||||
/* Change this value when the time-out happens before the sensor confirming ends. */
|
/* Change this value when the time-out happens before the sensor confirming ends. */
|
||||||
#define SENSOR_CONFIRMED_WAIT_TIME 100
|
#define SENSOR_CONFIRMED_WAIT_TIME 1
|
||||||
|
|
||||||
/* Read timeouts -- R_NAK_TIMEOUT * R_EXPIRE = Number of seconds */
|
/* Read timeouts -- R_NAK_TIMEOUT * R_EXPIRE = Number of seconds */
|
||||||
#define R_NAK_TIMEOUT (5000) /* Default number of X seconds to wait */
|
#define R_NAK_TIMEOUT (50) /* Default number of X seconds to wait */
|
||||||
#define R_EXPIRE 1 /* Number of attempts to wait X seconds */
|
#define R_EXPIRE 1 /* Number of attempts to wait X seconds */
|
||||||
|
|
||||||
/* Write timeouts */
|
/* Write timeouts */
|
||||||
#define W_NAK_TIMEOUT (5000) /* Default number of X seconds to wait */
|
#define W_NAK_TIMEOUT (50) /* Default number of X seconds to wait */
|
||||||
|
|
||||||
/* Ioctl timeouts */
|
/* Ioctl timeouts */
|
||||||
#define C_NAK_TIMEOUT (10000) /* Default number of X seconds to wait */
|
#define C_NAK_TIMEOUT (100) /* Default number of X seconds to wait */
|
||||||
|
|
||||||
/* Allocate buffer byte size */
|
/* Allocate buffer byte size */
|
||||||
#define IBUF_SIZE 32768
|
#define IBUF_SIZE 32768
|
||||||
@ -78,177 +130,174 @@
|
|||||||
#define SENSOR_CONFIRMED 1 /* Sensor is now used */
|
#define SENSOR_CONFIRMED 1 /* Sensor is now used */
|
||||||
|
|
||||||
|
|
||||||
/* table of devices that work with this driver
|
|
||||||
- Carl add 1526
|
|
||||||
*/
|
|
||||||
static struct usb_device_id fjveincam_device_ids [] = {
|
|
||||||
{ USB_DEVICE(0x04C5, 0x1084) },
|
|
||||||
{ USB_DEVICE(0x04C5, 0x125a) },
|
|
||||||
{ USB_DEVICE(0x04C5, 0x1526) },
|
|
||||||
{ } /* Terminating entry */
|
|
||||||
};
|
|
||||||
MODULE_DEVICE_TABLE(usb, fjveincam_device_ids);
|
|
||||||
|
|
||||||
|
|
||||||
static DEFINE_MUTEX(fjveincam_mutex); /* Initializes to unlocked */
|
static DEFINE_MUTEX(fjveincam_mutex); /* Initializes to unlocked */
|
||||||
|
|
||||||
struct fjveincam_usb_data {
|
|
||||||
struct usb_device *udev;
|
|
||||||
unsigned char fjveincam_minor; /* minor number - used in disconnect() */
|
|
||||||
char confirmed; /* Not zero if the device is used (Not in phase of confirming) */
|
|
||||||
int open_count; /* count the number of openers */
|
|
||||||
char *obuf, *ibuf; /* transfer buffers */
|
|
||||||
char bulk_in_ep; /* Endpoint assignments */
|
|
||||||
char bulk_out_ep; /* Endpoint assignments */
|
|
||||||
wait_queue_head_t wait_q; /* wait-queue for checking sensors */
|
|
||||||
struct mutex io_mutex; /* lock to prevent concurrent reads or writes */
|
|
||||||
int o_timeout; /* counter of open time out */
|
|
||||||
int r_error; /* counter of read error */
|
|
||||||
int r_lasterr; /* read last error */
|
|
||||||
int w_error; /* counter of write error */
|
|
||||||
int w_lasterr; /* write last error */
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct usb_driver usb_fjveincam_driver;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
static void dbg(int line, char * func, char * remark, unsigned long num){
|
static void dbg(int line, char * func, char * remark, unsigned long num){
|
||||||
printk(">>>>>>>>>>>>>>.. USB Driver: %s @ %d (%s): %s = %lu", __FILE__, line, remark, func, num);
|
pr_notice(">>>>>>>>>>>>>>.. USB Driver: %s @ %d (%s): %s = %lu", __FILE__, line, remark, func, num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ####### ### # #######
|
||||||
|
// # # # #
|
||||||
|
// # # # #
|
||||||
|
// ##### # # #####
|
||||||
|
// # # # #
|
||||||
|
// # # # #
|
||||||
|
// # ### ####### #######
|
||||||
|
//
|
||||||
|
// @func
|
||||||
static int usb_fjveincam_open(struct inode *inode, struct file *file)
|
static int usb_fjveincam_open(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
|
|
||||||
struct fjveincam_usb_data *fjveincam;
|
struct fjveincam *dev;
|
||||||
struct usb_interface *intf;
|
struct usb_interface *interface;
|
||||||
|
int subminor;
|
||||||
int fjveincam_minor;
|
int retval = 0;
|
||||||
|
|
||||||
int errx = 0;
|
|
||||||
long wait;
|
long wait;
|
||||||
|
|
||||||
dbg(__LINE__, "usb_fjveincam_open", "init open", 0L);
|
// does this even run?
|
||||||
|
dbg(__LINE__, "usb_fjveincam_open", "********* fjveincam open", ENODEV);
|
||||||
|
pr_notice("**************81 FFFFFFFFFUCK");
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
|
||||||
mutex_lock(&fjveincam_mutex);
|
mutex_lock(&fjveincam_mutex);
|
||||||
|
|
||||||
fjveincam_minor = iminor(inode);
|
subminor = iminor(inode);
|
||||||
|
|
||||||
dbg(__LINE__, "usb_fjveincam_open", "open", fjveincam_minor);
|
dbg(__LINE__, "usb_fjveincam_open", "open", subminor);
|
||||||
|
|
||||||
intf = usb_find_interface(&usb_fjveincam_driver, fjveincam_minor);
|
interface = usb_find_interface(&usb_fjveincam_driver, subminor);
|
||||||
if (!intf) {
|
if (!interface) {
|
||||||
dbg(__LINE__, "usb_fjveincam_open", "unable to access minor", fjveincam_minor);
|
pr_err("%s - error, can't find device for minor %d\n",
|
||||||
mutex_unlock(&fjveincam_mutex);
|
__func__, subminor);
|
||||||
return -ENODEV;
|
retval = -ENODEV;
|
||||||
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
fjveincam = usb_get_intfdata(intf);
|
dev = usb_get_intfdata(interface);
|
||||||
if ((!fjveincam) || (!fjveincam->udev)) {
|
if ((!dev) || (!dev->udev)) {
|
||||||
dbg(__LINE__, "usb_fjveincam_open", "device not present", 0L);
|
dbg(__LINE__, "usb_fjveincam_open", "device not present", 0L);
|
||||||
mutex_unlock(&fjveincam_mutex);
|
retval = -ENODEV;
|
||||||
return -ENODEV;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&(fjveincam->io_mutex));
|
mutex_lock(&(dev->io_mutex));
|
||||||
|
|
||||||
if (fjveincam->open_count) {
|
if (dev->open_count) {
|
||||||
/* Another process has opened. */
|
/* Another process has opened. */
|
||||||
if (fjveincam->confirmed == SENSOR_CONFIRMED) {
|
if (dev->confirmed == SENSOR_CONFIRMED) {
|
||||||
/* The sensor was confirmed. */
|
/* The sensor was confirmed. */
|
||||||
dbg(__LINE__, "usb_fjveincam_open", "device already open", 0L);
|
dbg(__LINE__, "usb_fjveincam_open", "device already open", 0L);
|
||||||
errx = -EBUSY;
|
retval = -EBUSY;
|
||||||
goto out_error;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&(fjveincam->io_mutex));
|
mutex_unlock(&(dev->io_mutex));
|
||||||
|
|
||||||
/* Wait until the sensor is confirmed or closed, because another process is open. */
|
/* Wait until the sensor is confirmed or closed, because another process is open. */
|
||||||
/* Change SENSOR_CONFIRMED_WAIT_TIME value when the time-out happens before the sensor is confirmed. */
|
/* Change SENSOR_CONFIRMED_WAIT_TIME value when the time-out happens before the sensor is confirmed. */
|
||||||
wait = wait_event_interruptible_timeout(fjveincam->wait_q,
|
wait = wait_event_interruptible_timeout(dev->wait_q,
|
||||||
(!fjveincam->open_count)||(fjveincam->confirmed==SENSOR_CONFIRMED),
|
(!dev->open_count)||(dev->confirmed==SENSOR_CONFIRMED),
|
||||||
SENSOR_CONFIRMED_WAIT_TIME);
|
SENSOR_CONFIRMED_WAIT_TIME);
|
||||||
|
|
||||||
mutex_lock(&(fjveincam->io_mutex));
|
mutex_lock(&(dev->io_mutex));
|
||||||
if (wait == 0) {
|
if (wait == 0) {
|
||||||
/* Time-out happens before the sensor is confirmed. */
|
/* Time-out happens before the sensor is confirmed. */
|
||||||
dbg(__LINE__, "usb_fjveincam_open", "preconfirmation timeout", 0L);
|
dbg(__LINE__, "usb_fjveincam_open", "preconfirmation timeout", 0L);
|
||||||
fjveincam->o_timeout++;
|
dev->o_timeout++;
|
||||||
fjveincam->confirmed=SENSOR_CONFIRMED;
|
dev->confirmed=SENSOR_CONFIRMED;
|
||||||
errx = -EBUSY;
|
retval = -EBUSY;
|
||||||
goto out_error;
|
goto exit;
|
||||||
}
|
}
|
||||||
else if (fjveincam->confirmed==SENSOR_CONFIRMED) {
|
else if (dev->confirmed==SENSOR_CONFIRMED) {
|
||||||
/* Another process completed the sensor confirming, and started the use of the sensor. */
|
/* Another process completed the sensor confirming, and started the use of the sensor. */
|
||||||
dbg(__LINE__, "usb_fjveincam_open", "device already open", 0L);
|
dbg(__LINE__, "usb_fjveincam_open", "device already open", 0L);
|
||||||
errx = -EBUSY;
|
retval = -EBUSY;
|
||||||
goto out_error;
|
goto exit;
|
||||||
}
|
}
|
||||||
else if(wait == -ERESTARTSYS) {
|
else if(wait == -ERESTARTSYS) {
|
||||||
errx = -ERESTARTSYS;
|
retval = -ERESTARTSYS;
|
||||||
goto out_error;
|
goto exit;
|
||||||
}
|
}
|
||||||
/* else {
|
/* else {
|
||||||
// Another process closed the sensor.
|
// Another process closed the sensor.
|
||||||
} */
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
init_waitqueue_head(&fjveincam->wait_q);
|
init_waitqueue_head(&dev->wait_q);
|
||||||
fjveincam->open_count = 1;
|
dev->open_count = 1;
|
||||||
file->private_data = fjveincam; /* Used by the read and write methods */
|
file->private_data = dev; /* Used by the read and write methods */
|
||||||
|
|
||||||
out_error:
|
|
||||||
mutex_unlock(&(fjveincam->io_mutex));
|
|
||||||
|
|
||||||
|
exit:
|
||||||
|
mutex_unlock(&(dev->io_mutex));
|
||||||
mutex_unlock(&fjveincam_mutex);
|
mutex_unlock(&fjveincam_mutex);
|
||||||
|
|
||||||
return errx;
|
return retval;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usb_fjveincam_close(struct inode *inode, struct file *file)
|
// @func
|
||||||
|
static int usb_fjveincam_release(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
struct fjveincam_usb_data *fjveincam = file->private_data;
|
struct fjveincam *dev = file->private_data;
|
||||||
|
mutex_lock(&(dev->io_mutex));
|
||||||
mutex_lock(&(fjveincam->io_mutex));
|
|
||||||
|
|
||||||
fjveincam->confirmed = SENSOR_NOT_CONFIRMED;
|
|
||||||
|
|
||||||
fjveincam->open_count = 0;
|
|
||||||
|
|
||||||
|
dev->confirmed = SENSOR_NOT_CONFIRMED;
|
||||||
|
dev->open_count = 0;
|
||||||
file->private_data = NULL;
|
file->private_data = NULL;
|
||||||
|
|
||||||
if (!fjveincam->udev) {
|
if (!dev->udev) {
|
||||||
/* The device was unplugged while open - need to clean up */
|
/* The device was unplugged while open - need to clean up */
|
||||||
dbg(__LINE__, "funczz", "device was unplugged while open .. tidying up", 0L);
|
dbg(__LINE__, "funczz", "device was unplugged while open .. tidying up", 0L);
|
||||||
|
|
||||||
mutex_unlock(&(fjveincam->io_mutex));
|
mutex_unlock(&(dev->io_mutex));
|
||||||
|
kfree(dev->ibuf);
|
||||||
kfree(fjveincam->ibuf);
|
kfree(dev->obuf);
|
||||||
kfree(fjveincam->obuf);
|
kfree(dev);
|
||||||
kfree(fjveincam);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
wake_up_interruptible(&fjveincam->wait_q); /* Wake_up the process waiting in open() function. */
|
wake_up_interruptible(&dev->wait_q); /* Wake_up the process waiting in open() function. */
|
||||||
|
dbg(__LINE__, "usb_fjveincam_close", "closing...", 0L);
|
||||||
dbg(__LINE__, "usb_fjveincam_close", "closing...", 0L);
|
mutex_unlock(&(dev->io_mutex));
|
||||||
|
|
||||||
mutex_unlock(&(fjveincam->io_mutex));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ### # #######
|
||||||
|
// # # # #
|
||||||
|
// # # # #
|
||||||
|
// # # # #
|
||||||
|
// # # # #
|
||||||
|
// # # # #
|
||||||
|
// ### # #######
|
||||||
|
//
|
||||||
|
// @func
|
||||||
static ssize_t usb_fjveincam_read(struct file *file, char *buffer,
|
static ssize_t usb_fjveincam_read(struct file *file, char *buffer,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct fjveincam_usb_data *fjveincam = file->private_data;
|
struct fjveincam *dev = file->private_data;
|
||||||
struct usb_device *dev;
|
struct usb_device *udev;
|
||||||
|
|
||||||
ssize_t bytes_read = 0; /* Overall count of bytes_read */
|
ssize_t bytes_read = 0; /* Overall count of bytes_read */
|
||||||
ssize_t ret = 0;
|
ssize_t ret = 0;
|
||||||
|
|
||||||
int fjveincam_minor;
|
int subminor;
|
||||||
int partial; /* Number of bytes successfully read */
|
int partial; /* Number of bytes successfully read */
|
||||||
int this_read; /* Max number of bytes to read */
|
int this_read; /* Max number of bytes to read */
|
||||||
int result;
|
int result;
|
||||||
@ -259,19 +308,19 @@ static ssize_t usb_fjveincam_read(struct file *file, char *buffer,
|
|||||||
|
|
||||||
ktime_get_ts64(&CURRENT_TIME);
|
ktime_get_ts64(&CURRENT_TIME);
|
||||||
|
|
||||||
mutex_lock(&(fjveincam->io_mutex));
|
mutex_lock(&(dev->io_mutex));
|
||||||
|
|
||||||
fjveincam_minor = fjveincam->fjveincam_minor;
|
subminor = dev->subminor;
|
||||||
|
|
||||||
dev = fjveincam->udev;
|
udev = dev->udev;
|
||||||
if (!dev) {
|
if (!udev) {
|
||||||
/* The device was unplugged before the file was released */
|
/* The device was unplugged before the file was released */
|
||||||
dbg(__LINE__, "usb_fjveincam_read", "device was unplugged", 0L);
|
dbg(__LINE__, "usb_fjveincam_read", "device was unplugged", 0L);
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto out_error;
|
goto out_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ibuf = fjveincam->ibuf;
|
ibuf = dev->ibuf;
|
||||||
|
|
||||||
file->f_path.dentry->d_inode->i_atime = CURRENT_TIME;
|
file->f_path.dentry->d_inode->i_atime = CURRENT_TIME;
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
@ -283,13 +332,13 @@ static ssize_t usb_fjveincam_read(struct file *file, char *buffer,
|
|||||||
|
|
||||||
this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
|
this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
|
||||||
|
|
||||||
result = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, fjveincam->bulk_in_ep), ibuf, this_read, &partial, R_NAK_TIMEOUT);
|
result = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, dev->bulk_in_ep), ibuf, this_read, &partial, R_NAK_TIMEOUT);
|
||||||
//dbg("%s: minor:%d result:%d this_read:%d partial:%d count:%d", "funczz", fjveincam_minor, result, this_read, partial, count);
|
//dbg("%s: minor:%d result:%d this_read:%d partial:%d count:%d", "funczz", subminor, result, this_read, partial, count);
|
||||||
dbg(__LINE__, "usb_fjveincam_read", "partial read", 0L);
|
dbg(__LINE__, "usb_fjveincam_read", "partial read", 0L);
|
||||||
|
|
||||||
fjveincam->r_lasterr = result;
|
dev->r_lasterr = result;
|
||||||
if (result == -ETIMEDOUT) { /* NAK */
|
if (result == -ETIMEDOUT) { /* NAK */
|
||||||
fjveincam->r_error++;
|
dev->r_error++;
|
||||||
if (!partial) { /* No data */
|
if (!partial) { /* No data */
|
||||||
if (--r_expire <= 0) { /* Give it up */
|
if (--r_expire <= 0) { /* Give it up */
|
||||||
dbg(__LINE__, "usb_fjveincam_read", "excessive NAKs", 0L);
|
dbg(__LINE__, "usb_fjveincam_read", "excessive NAKs", 0L);
|
||||||
@ -305,14 +354,14 @@ static ssize_t usb_fjveincam_read(struct file *file, char *buffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (result == -EPIPE) { /* No hope */
|
if (result == -EPIPE) { /* No hope */
|
||||||
fjveincam->r_error++;
|
dev->r_error++;
|
||||||
if(usb_clear_halt(dev, fjveincam->bulk_in_ep)) {
|
if(usb_clear_halt(udev, dev->bulk_in_ep)) {
|
||||||
dbg(__LINE__, "usb_fjveincam_read", "failed to clear endpoint halt condition", 0L);
|
dbg(__LINE__, "usb_fjveincam_read", "failed to clear endpoint halt condition", 0L);
|
||||||
}
|
}
|
||||||
ret = result;
|
ret = result;
|
||||||
break;
|
break;
|
||||||
} else if ((result < 0) && (result != EREMOTEIO)) {
|
} else if ((result < 0) && (result != EREMOTEIO)) {
|
||||||
fjveincam->r_error++;
|
dev->r_error++;
|
||||||
dbg(__LINE__, "usb_fjveincam_read", "an error occurred", 0L);
|
dbg(__LINE__, "usb_fjveincam_read", "an error occurred", 0L);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
break;
|
break;
|
||||||
@ -339,21 +388,23 @@ out_error:
|
|||||||
|
|
||||||
dbg(__LINE__, "usb_fjveincam_read", "bytes were read", 0L);
|
dbg(__LINE__, "usb_fjveincam_read", "bytes were read", 0L);
|
||||||
|
|
||||||
mutex_unlock(&(fjveincam->io_mutex));
|
mutex_unlock(&(dev->io_mutex));
|
||||||
|
|
||||||
return ret ? ret : bytes_read;
|
return ret ? ret : bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @func
|
||||||
static ssize_t usb_fjveincam_write(struct file *file, const char *buffer,
|
static ssize_t usb_fjveincam_write(struct file *file, const char *buffer,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct fjveincam_usb_data *fjveincam = file->private_data;
|
struct fjveincam *dev = file->private_data;
|
||||||
struct usb_device *dev;
|
struct usb_device *udev;
|
||||||
|
|
||||||
ssize_t bytes_written = 0; /* Overall count of bytes written */
|
ssize_t bytes_written = 0; /* Overall count of bytes written */
|
||||||
ssize_t ret = 0;
|
ssize_t ret = 0;
|
||||||
|
|
||||||
int fjveincam_minor;
|
int subminor;
|
||||||
int this_write; /* Number of bytes to write */
|
int this_write; /* Number of bytes to write */
|
||||||
int partial; /* Number of bytes successfully written */
|
int partial; /* Number of bytes successfully written */
|
||||||
int result = 0;
|
int result = 0;
|
||||||
@ -362,18 +413,18 @@ static ssize_t usb_fjveincam_write(struct file *file, const char *buffer,
|
|||||||
struct timespec64 CURRENT_TIME;
|
struct timespec64 CURRENT_TIME;
|
||||||
|
|
||||||
ktime_get_ts64(&CURRENT_TIME);
|
ktime_get_ts64(&CURRENT_TIME);
|
||||||
mutex_lock(&(fjveincam->io_mutex));
|
mutex_lock(&(dev->io_mutex));
|
||||||
|
|
||||||
fjveincam_minor = fjveincam->fjveincam_minor;
|
subminor = dev->subminor;
|
||||||
|
|
||||||
dev = fjveincam->udev;
|
udev = dev->udev;
|
||||||
if (!dev) {
|
if (!udev) {
|
||||||
dbg(__LINE__, "usb_fjveincam_write", "device was unplugged", 0L);
|
dbg(__LINE__, "usb_fjveincam_write", "device was unplugged", 0L);
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto out_error;
|
goto out_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
obuf = fjveincam->obuf;
|
obuf = dev->obuf;
|
||||||
file->f_path.dentry->d_inode->i_atime = CURRENT_TIME;
|
file->f_path.dentry->d_inode->i_atime = CURRENT_TIME;
|
||||||
|
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
@ -384,29 +435,29 @@ static ssize_t usb_fjveincam_write(struct file *file, const char *buffer,
|
|||||||
|
|
||||||
this_write = (count >= OBUF_SIZE) ? OBUF_SIZE : count;
|
this_write = (count >= OBUF_SIZE) ? OBUF_SIZE : count;
|
||||||
|
|
||||||
if (copy_from_user(fjveincam->obuf, buffer, this_write)) {
|
if (copy_from_user(dev->obuf, buffer, this_write)) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = usb_bulk_msg(dev,usb_sndbulkpipe(dev, fjveincam->bulk_out_ep), obuf, this_write, &partial, W_NAK_TIMEOUT);
|
result = usb_bulk_msg(udev,usb_sndbulkpipe(udev, dev->bulk_out_ep), obuf, this_write, &partial, W_NAK_TIMEOUT);
|
||||||
dbg(__LINE__, "usb_fjveincam_write", "bulk data sent", 0L);
|
dbg(__LINE__, "usb_fjveincam_write", "bulk data sent", 0L);
|
||||||
|
|
||||||
fjveincam->w_lasterr = result;
|
dev->w_lasterr = result;
|
||||||
if (result == -ETIMEDOUT) { /* NAK */
|
if (result == -ETIMEDOUT) { /* NAK */
|
||||||
dbg(__LINE__, "usb_fjveincam_write", "excess NAKs", 0L);
|
dbg(__LINE__, "usb_fjveincam_write", "excess NAKs", 0L);
|
||||||
fjveincam->w_error++;
|
dev->w_error++;
|
||||||
ret = result;
|
ret = result;
|
||||||
break;
|
break;
|
||||||
} else if (result < 0) { /* We should not get any I/O errors */
|
} else if (result < 0) { /* We should not get any I/O errors */
|
||||||
dbg(__LINE__, "usb_fjveincam_write", "error detected", 0L);
|
dbg(__LINE__, "usb_fjveincam_write", "error detected", 0L);
|
||||||
fjveincam->w_error++;
|
dev->w_error++;
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (partial != this_write) { /* Unable to write all contents of obuf */
|
if (partial != this_write) { /* Unable to write all contents of obuf */
|
||||||
fjveincam->w_error++;
|
dev->w_error++;
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -423,27 +474,42 @@ static ssize_t usb_fjveincam_write(struct file *file, const char *buffer,
|
|||||||
|
|
||||||
out_error:
|
out_error:
|
||||||
|
|
||||||
mutex_unlock(&(fjveincam->io_mutex));
|
mutex_unlock(&(dev->io_mutex));
|
||||||
|
|
||||||
return ret ? ret : bytes_written;
|
return ret ? ret : bytes_written;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ### ####### ##### ####### #
|
||||||
|
// # # # # # # #
|
||||||
|
// # # # # # #
|
||||||
|
// # # # # # #
|
||||||
|
// # # # # # #
|
||||||
|
// # # # # # # #
|
||||||
|
// ### ####### ##### # #######
|
||||||
|
//
|
||||||
|
// @func
|
||||||
static long usb_fjveincam_unlocked_ioctl(struct file *file, uint cmd, ulong arg)
|
static long usb_fjveincam_unlocked_ioctl(struct file *file, uint cmd, ulong arg)
|
||||||
{
|
{
|
||||||
struct fjveincam_usb_data *fjveincam = file->private_data;
|
struct fjveincam *dev = file->private_data;
|
||||||
struct usb_device *dev;
|
struct usb_device *udev;
|
||||||
|
char obuf[256];
|
||||||
int fjveincam_minor;
|
int subminor;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
return -99;
|
||||||
|
|
||||||
|
memset(&obuf,0,sizeof(obuf));
|
||||||
printk(">>>>>>>>> IOCTL %d\n", cmd);
|
printk(">>>>>>>>> IOCTL %d\n", cmd);
|
||||||
mutex_lock(&(fjveincam->io_mutex));
|
mutex_lock(&(dev->io_mutex));
|
||||||
|
|
||||||
fjveincam_minor = fjveincam->fjveincam_minor;
|
subminor = dev->subminor;
|
||||||
|
|
||||||
dbg(__LINE__, "usb_fjveincam_ioctl", "ioctl", 0L);
|
dbg(__LINE__, "usb_fjveincam_ioctl", "ioctl", 0L);
|
||||||
|
|
||||||
if (!fjveincam->udev) {
|
if (!dev->udev) {
|
||||||
dbg(__LINE__, "usb_fjveincam_ioctl", "device was unplugged", 0L);
|
dbg(__LINE__, "usb_fjveincam_ioctl", "device was unplugged", 0L);
|
||||||
retval = -ENODEV;
|
retval = -ENODEV;
|
||||||
goto out_error;
|
goto out_error;
|
||||||
@ -462,8 +528,8 @@ static long usb_fjveincam_unlocked_ioctl(struct file *file, uint cmd, ulong arg)
|
|||||||
} cmsg;
|
} cmsg;
|
||||||
int pipe, nb, ret;
|
int pipe, nb, ret;
|
||||||
unsigned char buf[974];
|
unsigned char buf[974];
|
||||||
|
dbg(__LINE__, "usb_fjveincam_ioctl", "USB_FJVEINCAM_IOCTL_CTRLMSG", 0L);
|
||||||
dev = fjveincam->udev;
|
udev = dev->udev;
|
||||||
|
|
||||||
dbg(__LINE__, "usb_fjveincam_ioctl", "dealing with an ioctl", 0L);
|
dbg(__LINE__, "usb_fjveincam_ioctl", "dealing with an ioctl", 0L);
|
||||||
|
|
||||||
@ -486,16 +552,16 @@ static long usb_fjveincam_unlocked_ioctl(struct file *file, uint cmd, ulong arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((cmsg.req.bRequestType & 0x80) == 0) {
|
if ((cmsg.req.bRequestType & 0x80) == 0) {
|
||||||
pipe = usb_sndctrlpipe(dev, 0);
|
pipe = usb_sndctrlpipe(udev, 0);
|
||||||
if (nb > 0 && copy_from_user(buf, cmsg.data, nb)) {
|
if (nb > 0 && copy_from_user(buf, cmsg.data, nb)) {
|
||||||
retval = -EFAULT;
|
retval = -EFAULT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pipe = usb_rcvctrlpipe(dev, 0);
|
pipe = usb_rcvctrlpipe(udev, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = usb_control_msg(dev, pipe,
|
ret = usb_control_msg(udev, pipe,
|
||||||
cmsg.req.bRequest,
|
cmsg.req.bRequest,
|
||||||
cmsg.req.bRequestType,
|
cmsg.req.bRequestType,
|
||||||
cmsg.req.wValue,
|
cmsg.req.wValue,
|
||||||
@ -504,10 +570,12 @@ static long usb_fjveincam_unlocked_ioctl(struct file *file, uint cmd, ulong arg)
|
|||||||
|
|
||||||
dbg(__LINE__, "usb_fjveincam_ioctl", "request", 0L);
|
dbg(__LINE__, "usb_fjveincam_ioctl", "request", 0L);
|
||||||
|
|
||||||
//dbg("%s: minor:%d request result:%d cmd[%02X:%04X:%04X:%04X] rsp[%02X:%02X:%02X:%02X]",
|
sprintf(obuf,"%s: minor:%d request result:%d cmd[%02X:%04X:%04X:%04X] rsp[%02X:%02X:%02X:%02X]",
|
||||||
// "funczz", fjveincam_minor, ret,
|
"funczz", subminor, ret,
|
||||||
// cmsg.req.bRequest, cmsg.req.wValue, cmsg.req.wIndex, cmsg.req.wLength,
|
cmsg.req.bRequest, cmsg.req.wValue, cmsg.req.wIndex, cmsg.req.wLength,
|
||||||
// buf[0], buf[1], buf[2], buf[3]);
|
buf[0], buf[1], buf[2], buf[3]);
|
||||||
|
dbg(__LINE__, "usb_fjveincam_ioctl", obuf, 0L);
|
||||||
|
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dbg(__LINE__, "usb_fjveincam_ioctl", "error detected", 0L);
|
dbg(__LINE__, "usb_fjveincam_ioctl", "error detected", 0L);
|
||||||
@ -527,15 +595,16 @@ static long usb_fjveincam_unlocked_ioctl(struct file *file, uint cmd, ulong arg)
|
|||||||
|
|
||||||
case USB_FJVEINCAMV30_IOCTL_CHECK:
|
case USB_FJVEINCAMV30_IOCTL_CHECK:
|
||||||
case USB_FJVEINCAM_IOCTL_CHECK:
|
case USB_FJVEINCAM_IOCTL_CHECK:
|
||||||
/* nop */
|
dbg(__LINE__, "usb_fjveincam_ioctl", "USB_FJVEINCAM_IOCTL_CHECK", 0L);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Notification of the end of sensor confirming. */
|
/* Notification of the end of sensor confirming. */
|
||||||
case USB_FJVEINCAMV30_IOCTL_CONFIRM:
|
case USB_FJVEINCAMV30_IOCTL_CONFIRM:
|
||||||
case USB_FJVEINCAM_IOCTL_CONFIRM:
|
case USB_FJVEINCAM_IOCTL_CONFIRM:
|
||||||
{
|
{
|
||||||
fjveincam->confirmed = SENSOR_CONFIRMED; /* Sensor confirming was completed, and started the use of the sensor. */
|
dbg(__LINE__, "usb_fjveincam_ioctl", "USB_FJVEINCAM_IOCTL_CONFIRM", 0L);
|
||||||
wake_up_interruptible(&fjveincam->wait_q); /* Wake_up the process waiting in open() function. */
|
dev->confirmed = SENSOR_CONFIRMED; /* Sensor confirming was completed, and started the use of the sensor. */
|
||||||
|
wake_up_interruptible(&dev->wait_q); /* Wake_up the process waiting in open() function. */
|
||||||
dbg(__LINE__, "usb_fjveincam_ioctl", "sensor was checked", 0L);
|
dbg(__LINE__, "usb_fjveincam_ioctl", "sensor was checked", 0L);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -544,14 +613,15 @@ static long usb_fjveincam_unlocked_ioctl(struct file *file, uint cmd, ulong arg)
|
|||||||
case USB_FJVEINCAM_IOCTL_INFO:
|
case USB_FJVEINCAM_IOCTL_INFO:
|
||||||
{
|
{
|
||||||
struct fjveincam_info info;
|
struct fjveincam_info info;
|
||||||
|
dbg(__LINE__, "usb_fjveincam_ioctl", "USB_FJVEINCAM_IOCTL_INFO", 0L);
|
||||||
|
|
||||||
info.magic = FJPV_MAGIC; /* Magic number for indicating Fujitsu Palmsecure sensor driver. */
|
info.magic = FJPV_MAGIC; /* Magic number for indicating Fujitsu Palmsecure sensor driver. */
|
||||||
info.minor = fjveincam_minor;
|
info.minor = subminor;
|
||||||
info.o_timeout = fjveincam->o_timeout;
|
info.o_timeout = dev->o_timeout;
|
||||||
info.r_error = fjveincam->r_error;
|
info.r_error = dev->r_error;
|
||||||
info.r_lasterr = fjveincam->r_lasterr;
|
info.r_lasterr = dev->r_lasterr;
|
||||||
info.w_error = fjveincam->w_error;
|
info.w_error = dev->w_error;
|
||||||
info.w_lasterr = fjveincam->w_lasterr;
|
info.w_lasterr = dev->w_lasterr;
|
||||||
strncpy((char*)info.version, DRIVER_VERSION, sizeof(info.version));
|
strncpy((char*)info.version, DRIVER_VERSION, sizeof(info.version));
|
||||||
if (copy_to_user((void *)arg, &info, sizeof(info)))
|
if (copy_to_user((void *)arg, &info, sizeof(info)))
|
||||||
retval = -EFAULT;
|
retval = -EFAULT;
|
||||||
@ -567,37 +637,51 @@ static long usb_fjveincam_unlocked_ioctl(struct file *file, uint cmd, ulong arg)
|
|||||||
|
|
||||||
out_error:
|
out_error:
|
||||||
|
|
||||||
mutex_unlock(&(fjveincam->io_mutex));
|
mutex_unlock(&(dev->io_mutex));
|
||||||
|
|
||||||
dbg(__LINE__, "usb_fjveincam_ioctl", "OK...", 0L);
|
dbg(__LINE__, "usb_fjveincam_ioctl", "OK...", 0L);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Kernel VFS uses this to lookup actual driver functions to call on
|
|
||||||
open(fd, O_RD) -> open
|
|
||||||
close(fd) -> close
|
// @config
|
||||||
*/
|
|
||||||
static struct file_operations usb_fjveincam_fops = {
|
static struct file_operations usb_fjveincam_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
|
.open = usb_fjveincam_open,
|
||||||
|
.release = usb_fjveincam_release,
|
||||||
.read = usb_fjveincam_read,
|
.read = usb_fjveincam_read,
|
||||||
.write = usb_fjveincam_write,
|
.write = usb_fjveincam_write,
|
||||||
.unlocked_ioctl = usb_fjveincam_unlocked_ioctl,
|
.unlocked_ioctl = usb_fjveincam_unlocked_ioctl,
|
||||||
.open = usb_fjveincam_open,
|
|
||||||
.release = usb_fjveincam_close,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// @config
|
||||||
static struct usb_class_driver fjveincam_class = {
|
static struct usb_class_driver fjveincam_class = {
|
||||||
.name = "usb/fjveincam%d",
|
.name = "usb/fjveincam%d",
|
||||||
.fops = &usb_fjveincam_fops,
|
.fops = &usb_fjveincam_fops,
|
||||||
.minor_base = USB_FJVEINCAM_MINOR_BASE,
|
.minor_base = USB_subminor_BASE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// ##### ##### #### ##### ######
|
||||||
|
// # # # # # # # # #
|
||||||
|
// # # # # # # ##### #####
|
||||||
|
// ##### ##### # # # # #
|
||||||
|
// # # # # # # # #
|
||||||
|
// # # # #### ##### ######
|
||||||
|
//
|
||||||
|
// Runs when the *device* is plugged in
|
||||||
|
// @func
|
||||||
static int usb_fjveincam_probe(struct usb_interface *intf,
|
static int usb_fjveincam_probe(struct usb_interface *intf,
|
||||||
const struct usb_device_id *id)
|
const struct usb_device_id *id)
|
||||||
{
|
{
|
||||||
struct usb_device *dev = interface_to_usbdev(intf);
|
struct usb_device *udev = interface_to_usbdev(intf);
|
||||||
struct fjveincam_usb_data *fjveincam;
|
struct fjveincam *dev;
|
||||||
struct usb_host_interface *interface;
|
struct usb_host_interface *interface;
|
||||||
struct usb_endpoint_descriptor *endpoint;
|
struct usb_endpoint_descriptor *endpoint;
|
||||||
|
|
||||||
@ -607,22 +691,38 @@ static int usb_fjveincam_probe(struct usb_interface *intf,
|
|||||||
char have_bulk_in, have_bulk_out;
|
char have_bulk_in, have_bulk_out;
|
||||||
char name[20];
|
char name[20];
|
||||||
char buf[128];
|
char buf[128];
|
||||||
|
struct usb_class_driver *class_driver = intf->dev.driver_data;
|
||||||
|
|
||||||
|
pr_info("Associated file name: %s\n", class_driver->name);
|
||||||
|
|
||||||
|
// Dump usb_interface structure
|
||||||
|
pr_info("Dumping usb_interface structure:\n");
|
||||||
|
pr_info(" Interface number: %d\n", intf->cur_altsetting->desc.bInterfaceNumber);
|
||||||
|
pr_info(" Interface class: 0x%02x\n", intf->cur_altsetting->desc.bInterfaceClass);
|
||||||
|
// Add more fields as needed
|
||||||
|
|
||||||
|
// Dump usb_device_id structure
|
||||||
|
pr_info("Dumping usb_device_id structure:\n");
|
||||||
|
pr_info(" Matched vendor ID: 0x%04x\n", id->idVendor);
|
||||||
|
pr_info(" Matched product ID: 0x%04x\n", id->idProduct);
|
||||||
|
// Add more fields as needed
|
||||||
|
|
||||||
memset(&buf,0,sizeof(buf));
|
memset(&buf,0,sizeof(buf));
|
||||||
|
|
||||||
dbg(__LINE__, "usb_fjveincam_probe", "probed; [device id]", 0L);
|
dbg(__LINE__, "usb_fjveincam_probe", "probed; [device id]", 0L);
|
||||||
|
|
||||||
sprintf(buf, "vendor id 0x%x, device id 0x%x, portnum:%d",
|
sprintf(buf, "vendor id 0x%x, device id 0x%x, portnum:%d minor_base:%d",
|
||||||
dev->descriptor.idVendor, dev->descriptor.idProduct,
|
udev->descriptor.idVendor, udev->descriptor.idProduct,
|
||||||
dev->portnum);
|
udev->portnum, USB_subminor_BASE);
|
||||||
dbg(__LINE__, "usb_fjveincam_probe", buf, 0L);
|
dbg(__LINE__, "usb_fjveincam_probe", buf, 0L);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* After this point we can be a little noisy about what we are trying to
|
* After this point we can be a little noisy about what we are trying to
|
||||||
* configure.
|
* configure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (dev->descriptor.bNumConfigurations != 1) {
|
if (udev->descriptor.bNumConfigurations != 1) {
|
||||||
dbg(__LINE__, "funczz", "only one device configuration is supported", 0L);
|
dbg(__LINE__, "funczz", "only one device configuration is supported", 0L);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
@ -633,7 +733,7 @@ static int usb_fjveincam_probe(struct usb_interface *intf,
|
|||||||
|
|
||||||
interface = &intf->altsetting[0];
|
interface = &intf->altsetting[0];
|
||||||
|
|
||||||
dbg(__LINE__, "usb_fjveincam_probe", "endpoints", 0L);
|
dbg(__LINE__, "usb_fjveincam_probe", "endpoints", 0L);
|
||||||
|
|
||||||
if (interface->desc.bNumEndpoints != 2) {
|
if (interface->desc.bNumEndpoints != 2) {
|
||||||
dbg(__LINE__, "usb_fjveincam_probe", "**ERROR** endpoint count", 0L);
|
dbg(__LINE__, "usb_fjveincam_probe", "**ERROR** endpoint count", 0L);
|
||||||
@ -677,47 +777,47 @@ static int usb_fjveincam_probe(struct usb_interface *intf,
|
|||||||
* Determine a minor number and initialize the structure associated
|
* Determine a minor number and initialize the structure associated
|
||||||
* with it.
|
* with it.
|
||||||
*/
|
*/
|
||||||
if (!(fjveincam = kzalloc (sizeof (struct fjveincam_usb_data), GFP_KERNEL))) {
|
if (!(dev = kzalloc (sizeof (struct fjveincam), GFP_KERNEL))) {
|
||||||
dbg(__LINE__, "usb_fjveincam_probe", "**ERROR** insufficient memory", 0L);
|
dbg(__LINE__, "usb_fjveincam_probe", "**ERROR** insufficient memory", 0L);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
mutex_init(&(fjveincam->io_mutex)); /* Initializes to unlocked */
|
mutex_init(&(dev->io_mutex)); /* Initializes to unlocked */
|
||||||
|
|
||||||
/* Ok, now initialize all the relevant values */
|
/* Ok, now initialize all the relevant values */
|
||||||
if (!(fjveincam->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) {
|
if (!(dev->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) {
|
||||||
dbg(__LINE__, "usb_fjveincam_probe", "**ERROR** insufficient output memory", 0L);
|
dbg(__LINE__, "usb_fjveincam_probe", "**ERROR** insufficient output memory", 0L);
|
||||||
kfree(fjveincam);
|
kfree(dev);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(fjveincam->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) {
|
if (!(dev->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) {
|
||||||
dbg(__LINE__, "usb_fjveincam_probe", "**ERROR** insufficient input memory", 0L);
|
dbg(__LINE__, "usb_fjveincam_probe", "**ERROR** insufficient input memory", 0L);
|
||||||
kfree(fjveincam->obuf);
|
kfree(dev->obuf);
|
||||||
kfree(fjveincam);
|
kfree(dev);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_get_dev(dev);
|
usb_get_dev(udev);
|
||||||
fjveincam->bulk_in_ep = have_bulk_in;
|
dev->bulk_in_ep = have_bulk_in;
|
||||||
fjveincam->bulk_out_ep = have_bulk_out;
|
dev->bulk_out_ep = have_bulk_out;
|
||||||
fjveincam->udev = dev;
|
dev->udev = udev;
|
||||||
fjveincam->open_count = 0;
|
dev->open_count = 0;
|
||||||
fjveincam->confirmed = SENSOR_NOT_CONFIRMED;
|
dev->confirmed = SENSOR_NOT_CONFIRMED;
|
||||||
|
|
||||||
usb_set_intfdata(intf, fjveincam);
|
usb_set_intfdata(intf, dev);
|
||||||
|
|
||||||
retval = usb_register_dev(intf, &fjveincam_class);
|
retval = usb_register_dev(intf, &fjveincam_class);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
dbg(__LINE__, "usb_fjveincam_probe", "**ERROR** unable to get a minor number", 0L);
|
dbg(__LINE__, "usb_fjveincam_probe", "**ERROR** unable to get a minor number", 0L);
|
||||||
usb_set_intfdata(intf, NULL);
|
usb_set_intfdata(intf, NULL);
|
||||||
kfree(fjveincam->ibuf);
|
kfree(dev->ibuf);
|
||||||
kfree(fjveincam->obuf);
|
kfree(dev->obuf);
|
||||||
kfree(fjveincam);
|
kfree(dev);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg(__LINE__, "usb_fjveincam_probe", "have a minor", intf->minor);
|
dbg(__LINE__, "usb_fjveincam_probe", "have a minor", intf->minor);
|
||||||
fjveincam->fjveincam_minor = intf->minor;
|
dev->subminor = intf->minor;
|
||||||
|
|
||||||
snprintf(name, sizeof(name), fjveincam_class.name,
|
snprintf(name, sizeof(name), fjveincam_class.name,
|
||||||
intf->minor - fjveincam_class.minor_base);
|
intf->minor - fjveincam_class.minor_base);
|
||||||
@ -728,10 +828,24 @@ static int usb_fjveincam_probe(struct usb_interface *intf,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ##### ####### # # # #
|
||||||
|
// # # # # ## # ## #
|
||||||
|
// # # # # # # # # #
|
||||||
|
// # # # # # # # # #
|
||||||
|
// # # # # # # # # #
|
||||||
|
// # # # # # ## # ##
|
||||||
|
// ##### ####### # # # #
|
||||||
|
//
|
||||||
|
// Runs when the *device* is disconnected, or the module is unloaded
|
||||||
|
// @func
|
||||||
static void usb_fjveincam_disconnect(struct usb_interface *interface)
|
static void usb_fjveincam_disconnect(struct usb_interface *interface)
|
||||||
{
|
{
|
||||||
struct fjveincam_usb_data *fjveincam = usb_get_intfdata(interface);
|
struct fjveincam *dev = usb_get_intfdata(interface);
|
||||||
int fjveincam_minor = interface->minor;
|
int subminor = interface->minor;
|
||||||
|
|
||||||
usb_set_intfdata(interface, NULL);
|
usb_set_intfdata(interface, NULL);
|
||||||
|
|
||||||
@ -739,44 +853,50 @@ static void usb_fjveincam_disconnect(struct usb_interface *interface)
|
|||||||
usb_deregister_dev (interface, &fjveincam_class);
|
usb_deregister_dev (interface, &fjveincam_class);
|
||||||
|
|
||||||
mutex_lock(&fjveincam_mutex); /* If there is a process in open(), wait for return. */
|
mutex_lock(&fjveincam_mutex); /* If there is a process in open(), wait for return. */
|
||||||
mutex_lock(&(fjveincam->io_mutex));
|
mutex_lock(&(dev->io_mutex));
|
||||||
|
|
||||||
dev_info(&interface->dev, "USB PalmVeinCam #%d now disconnected\n", (fjveincam_minor - fjveincam_class.minor_base));
|
dev_info(&interface->dev, "USB PalmVeinCam #%d now disconnected\n", (subminor - fjveincam_class.minor_base));
|
||||||
|
|
||||||
usb_driver_release_interface(&usb_fjveincam_driver,
|
usb_driver_release_interface(&usb_fjveincam_driver,
|
||||||
fjveincam->udev->actconfig->interface[0]);
|
dev->udev->actconfig->interface[0]);
|
||||||
|
|
||||||
if (fjveincam->open_count) {
|
if (dev->open_count) {
|
||||||
/* The device is still open - cleanup must be delayed */
|
/* The device is still open - cleanup must be delayed */
|
||||||
dbg(__LINE__, "usb_fjveincam_disconnect", "device was unplugged while open", 0L);
|
dbg(__LINE__, "usb_fjveincam_disconnect", "device was unplugged while open", 0L);
|
||||||
fjveincam->udev = 0;
|
dev->udev = 0;
|
||||||
mutex_unlock(&(fjveincam->io_mutex));
|
mutex_unlock(&(dev->io_mutex));
|
||||||
mutex_unlock(&fjveincam_mutex);
|
mutex_unlock(&fjveincam_mutex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg(__LINE__, "usb_fjveincam_disconnect", "deallocating...", 0L);
|
dbg(__LINE__, "usb_fjveincam_disconnect", "deallocating...", 0L);
|
||||||
|
|
||||||
mutex_unlock(&(fjveincam->io_mutex));
|
mutex_unlock(&(dev->io_mutex));
|
||||||
mutex_unlock(&fjveincam_mutex);
|
mutex_unlock(&fjveincam_mutex);
|
||||||
|
|
||||||
kfree(fjveincam->ibuf);
|
kfree(dev->ibuf);
|
||||||
kfree(fjveincam->obuf);
|
kfree(dev->obuf);
|
||||||
kfree(fjveincam);
|
kfree(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct usb_driver usb_fjveincam_driver = {
|
|
||||||
.name = "fjveincam",
|
|
||||||
.probe = usb_fjveincam_probe,
|
|
||||||
.disconnect = usb_fjveincam_disconnect,
|
|
||||||
.id_table = fjveincam_device_ids,
|
|
||||||
.no_dynamic_id = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ###### ####### ##### ### ##### ####### ### ###### # #
|
||||||
|
// # # # # # # # # # ### # # ## #
|
||||||
|
// # # # # # # # # # # # # #
|
||||||
|
// ###### ##### # #### # ##### # # ###### # # #
|
||||||
|
// # # # # # # # # # # # # #
|
||||||
|
// # # # # # # # # # # # # ##
|
||||||
|
// # # ####### ##### ### ##### # # # # #
|
||||||
|
//
|
||||||
|
// Runs when the *module* is loaded
|
||||||
|
// @func
|
||||||
static int __init usb_fjveincam_init(void){
|
static int __init usb_fjveincam_init(void){
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
/* register this driver with the USB subsystem - fires on driver module insmod */
|
// register this driver with the USB subsystem - fires on driver module insmod
|
||||||
dbg(__LINE__, "usb_fjveincam_init", "USB registration with ioctl %lu", USB_FJVEINCAM_IOCTL_INFO);
|
dbg(__LINE__, "usb_fjveincam_init", "USB registration with ioctl %lu", USB_FJVEINCAM_IOCTL_INFO);
|
||||||
result = usb_register(&usb_fjveincam_driver);
|
result = usb_register(&usb_fjveincam_driver);
|
||||||
if (result){
|
if (result){
|
||||||
@ -785,18 +905,34 @@ static int __init usb_fjveincam_init(void){
|
|||||||
dbg(__LINE__, "usb_fjveincam_init", "registration complete", result);
|
dbg(__LINE__, "usb_fjveincam_init", "registration complete", result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
// This runs when the *module* is unloaded
|
||||||
|
// @func
|
||||||
static void __exit usb_fjveincam_exit(void)
|
static void __exit usb_fjveincam_exit(void)
|
||||||
{
|
{
|
||||||
/* deregister this driver with the USB subsystem - fires on driver module rmmod */
|
// deregister this driver with the USB subsystem - fires on driver module rmmod
|
||||||
dbg(__LINE__, "usb_fjveincam_init", "USB de-registration with ioctl %lu", USB_FJVEINCAM_IOCTL_INFO);
|
dbg(__LINE__, "usb_fjveincam_exit", "USB de-registration with ioctl %lu", USB_FJVEINCAM_IOCTL_INFO);
|
||||||
usb_deregister(&usb_fjveincam_driver);
|
usb_deregister(&usb_fjveincam_driver);
|
||||||
dbg(__LINE__, "usb_fjveincam_exit", "removing the driver", 0L);
|
dbg(__LINE__, "usb_fjveincam_exit", "removing the driver", 0L);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(usb_fjveincam_init);
|
module_init(usb_fjveincam_init);
|
||||||
module_exit(usb_fjveincam_exit);
|
module_exit(usb_fjveincam_exit);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// @config
|
||||||
|
static struct usb_driver usb_fjveincam_driver = {
|
||||||
|
.name = "fjveincam",
|
||||||
|
.probe = usb_fjveincam_probe,
|
||||||
|
.disconnect = usb_fjveincam_disconnect,
|
||||||
|
.id_table = fjveincam_table,
|
||||||
|
.no_dynamic_id = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
|||||||
@ -18,6 +18,8 @@
|
|||||||
#ifndef _FJVEINCAM_
|
#ifndef _FJVEINCAM_
|
||||||
#define _FJVEINCAM_
|
#define _FJVEINCAM_
|
||||||
|
|
||||||
|
//#define CONFIG_FJVEINCAM_DEBUG
|
||||||
|
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
/* ioctl */
|
/* ioctl */
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
@ -65,4 +67,6 @@ struct fjveincam_info {
|
|||||||
unsigned char version[8]; /* device driver version string */
|
unsigned char version[8]; /* device driver version string */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _FJVEINCAM_ */
|
#endif /* _FJVEINCAM_ */
|
||||||
|
|||||||
@ -44,6 +44,23 @@ make
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Jun 01 11:27:08 virgil kernel: >>>>>>>>>>>>>>.. USB Driver: /t200/yoloserv/modules/fjpalmvein/C/fjpalmvein-main/fjveincam.c @ 750 (deallocating...): usb_fjveincam_disconnect = 0
|
||||||
|
Jun 01 11:27:09 virgil kernel: usb 4-6.1: new high-speed USB device number 38 using xhci_hcd
|
||||||
|
Jun 01 11:27:10 virgil kernel: usb 4-6.1: New USB device found, idVendor=04c5, idProduct=1526, bcdDevice= 2.00
|
||||||
|
Jun 01 11:27:10 virgil kernel: usb 4-6.1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
|
||||||
|
Jun 01 11:27:10 virgil kernel: usb 4-6.1: Product: FUJITSU PalmSecure-F Pro
|
||||||
|
Jun 01 11:27:10 virgil kernel: usb 4-6.1: Manufacturer: FUJITSU
|
||||||
|
Jun 01 11:27:10 virgil kernel: >>>>>>>>>>>>>>.. USB Driver: /t200/yoloserv/modules/fjpalmvein/C/fjpalmvein-main/fjveincam.c @ 606 (probed; [device id]): usb_fjveincam_probe = 0
|
||||||
|
Jun 01 11:27:10 virgil kernel: >>>>>>>>>>>>>>.. USB Driver: /t200/yoloserv/modules/fjpalmvein/C/fjpalmvein-main/fjveincam.c @ 611 (vendor id 0x4c5, device id 0x1526, portnum:1): usb_fjveincam_probe = 0
|
||||||
|
Jun 01 11:27:10 virgil kernel: >>>>>>>>>>>>>>.. USB Driver: /t200/yoloserv/modules/fjpalmvein/C/fjpalmvein-main/fjveincam.c @ 630 (endpoints): usb_fjveincam_probe = 0
|
||||||
|
Jun 01 11:27:10 virgil kernel: >>>>>>>>>>>>>>.. USB Driver: /t200/yoloserv/modules/fjpalmvein/C/fjpalmvein-main/fjveincam.c @ 645 (bulk in): usb_fjveincam_probe = 0
|
||||||
|
Jun 01 11:27:10 virgil kernel: >>>>>>>>>>>>>>.. USB Driver: /t200/yoloserv/modules/fjpalmvein/C/fjpalmvein-main/fjveincam.c @ 652 (bulk out): usb_fjveincam_probe = 0
|
||||||
|
Jun 01 11:27:10 virgil kernel: >>>>>>>>>>>>>>.. USB Driver: /t200/yoloserv/modules/fjpalmvein/C/fjpalmvein-main/fjveincam.c @ 713 (have a minor): usb_fjveincam_probe = 0
|
||||||
|
Jun 01 11:27:10 virgil kernel: fjveincam 4-6.1:1.0: USB PalmVeinCam device now attached to usb/fjveincam-160
|
||||||
|
Jun 01 11:27:10 virgil mtp-probe[306997]: checking bus 4, device 38: "/sys/devices/pci0000:00/0000:00:02.4/0000:05:00.0/usb4/4-6/4-6.1"
|
||||||
|
Jun 01 11:27:10 virgil mtp-probe[306997]: bus: 4, device: 38 was not an MTP device
|
||||||
|
Jun 01 11:27:10 virgil systemd-udevd[306996]: 4-6.1:1.0: Process '/usr/lib/snapd/snap-device-helper bind snap_arduino_arduino /devices/pci0000:00/0000:00:02.4/0000:05:00.0/usb4/4-6/4-6.1/4-6.1:1.0 0:0' failed with exit code 1.
|
||||||
|
Jun 01 11:27:10 virgil systemd-udevd[306996]: 4-6.1:1.0: Process '/usr/lib/snapd/snap-device-helper bind snap_cups_cupsd /devices/pci0000:00/0000:00:02.4/0000:05:00.0/usb4/4-6/4-6.1/4-6.1:1.0 0:0' failed with exit code 1.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user