All of lore.kernel.org
 help / color / mirror / Atom feed
* Smart card reader support for Anysee DVB devices
@ 2011-07-17 14:18 István Váradi
  2011-08-14 23:51 ` Antti Palosaari
  0 siblings, 1 reply; 16+ messages in thread
From: István Váradi @ 2011-07-17 14:18 UTC (permalink / raw)
  To: linux-media

[-- Attachment #1: Type: text/plain, Size: 1727 bytes --]

Hi,

I have developed smart card reader support for the Anysee devices by
extending Antti Palosaari's driver. I attached the patches for it. It
registers a character device named /dev/anysee_scN for each Anysee
device.

The character device supports two ioctl's (see anysee_sc), one for
detecting the presence of a card, the other one for resetting the card
and querying the ATR. The write() operation writes to the card by
packaging the bytes into USB commands. The read() operation issues an
appropriate command over USB and returns the reply. I have also
written a simple OpenCT driver (attached) which shows the usage.

I would like to have the kernel driver included in the official
sources. For this reason I corresponded with Antti, and he suggested
the perhaps the kernel driver should have a lower-level interface. I
had the following proposal:

We would continue having the two ioctls, ANYSEE_SC_ACTIVATE and
ANYSEE_SC_PRESENT, however, ANYSEE_SC_ACTIVATE would do only the
register reading and writing.

Besides these two we need access to the anysee_ctrl_msg() function
somehow. I think the cleanest way would be via another ioctl() call in
which we would pass the return buffer as well, with the length so that
we know how many bytes to copy. Another possibility would be that a
call to write() calls anysee_ctrl_msg() and stores the return data in
a 64 byte buffer that we allocate for each device. The read()
following a write() would read this buffer, then discard it. Further
read() attempts would fail with EAGAIN, or we could maintain an offset
into the 64 byte buffer, and read as long as there is data, and fail
only then. A write() would cause losing any unread data.

What do you think?

Thanks,

Istvan

[-- Attachment #2: patch --]
[-- Type: application/octet-stream, Size: 11432 bytes --]

--- anysee.c.orig	2010-08-02 00:11:14.000000000 +0200
+++ anysee.c	2010-12-28 09:04:45.000000000 +0100
@@ -32,11 +32,14 @@
  */
 
 #include "anysee.h"
+#include "anysee_sc.h"
 #include "tda1002x.h"
 #include "mt352.h"
 #include "mt352_priv.h"
 #include "zl10353.h"
 
+#include <linux/device.h>
+
 /* debug */
 static int dvb_usb_anysee_debug;
 module_param_named(debug, dvb_usb_anysee_debug, int, 0644);
@@ -132,6 +135,273 @@
 	return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
 }
 
+static dev_t sc_dev;
+static const unsigned sc_count = 16;
+static struct class* sc_class = 0;
+
+static int anysee_sc_open(struct inode *inode, struct file *filp)
+{
+        struct anysee_sc_state* sc_state = container_of(inode->i_cdev, struct anysee_sc_state, cdev);
+        filp->private_data = sc_state;
+        return 0;
+}
+
+static int anysee_sc_check_presence(struct dvb_usb_device* d)
+{
+    int ret = 0;
+    u8 x;
+
+    ret = anysee_read_reg(d, 0x0080, &x);
+    if (ret!=0) return ret;
+
+    if ((x&0x02)!=0) return 0;
+
+    ret = anysee_write_reg(d, 0xb1, 0xa7);
+    if (ret!=0) return ret;
+
+    ret = anysee_read_reg(d, 0x0080, &x);
+    
+    if (ret!=0) return ret;
+    else return ((x&0x02)==0) ? -EPIPE : 0;
+}
+
+static int anysee_sc_read_byte(struct dvb_usb_device* d, u8* dest, unsigned int timeout,
+                               u8 last)
+{
+    static const unsigned read_interval = 20;
+    
+    u8 cmd[] = { 0x34, 0x06, 0x01, 0x00 };
+    
+    u8 buf[4];
+    unsigned num_cycles = timeout / read_interval, i;
+
+    int ret = 0;
+    cmd[3] = last;
+    for(i = 0; i<num_cycles && ret==0; ++i) {
+        ret = anysee_ctrl_msg(d, cmd, sizeof(cmd), buf, sizeof(buf));
+        if (ret==0) {
+            if (buf[0]==0x01) {
+                *dest = buf[2];
+                return 0;
+            }
+            if (msleep_interruptible(read_interval)>0) {
+                return -EAGAIN;
+            }
+        }
+    }
+    
+    return -ETIMEDOUT;
+}
+
+static ssize_t anysee_sc_read(struct file *filp, char __user *buf, size_t count, loff_t *offp)
+{
+        struct anysee_sc_state* sc_state = (struct anysee_sc_state*)filp->private_data;
+        struct dvb_usb_device* d = sc_state->dvb_usb_device;
+        
+        int ret = 0;
+        unsigned index = 0;
+        u8 read_buf[count];
+
+
+	if (mutex_lock_interruptible(&sc_state->mutex) < 0)
+		return -EAGAIN;
+        
+        if (ret==0) {
+            ret = anysee_sc_check_presence(d);
+        }
+
+        while(ret==0 && index<count) {
+            ret = anysee_sc_read_byte(d, read_buf+index, (index==0) ? 1000 : 100, 0x01);
+            if (ret==0) ++index;
+        }
+
+        if (ret==0) {
+            if (copy_to_user(buf, read_buf, index)) {
+                ret = -EFAULT;
+            }
+        }
+
+        mutex_unlock(&sc_state->mutex);
+    
+        return (ret==0) ? index : ret;
+}
+
+static ssize_t anysee_sc_write(struct file *filp, const char __user *buf, size_t count, loff_t *offp)
+{
+        struct anysee_sc_state* sc_state = (struct anysee_sc_state*)filp->private_data;
+        struct dvb_usb_device* d = sc_state->dvb_usb_device;
+
+        u8 cmd[] = { 0x34, 0x08, 0x01, 0x01, 0x00, 0x05 };
+        ssize_t ret = 0;
+        unsigned written = 0;
+
+        if (count>256) {
+                return -EINVAL;
+        }
+        
+	if (mutex_lock_interruptible(&sc_state->mutex) < 0)
+		return -EAGAIN;
+
+        if (ret==0) {
+            ret = anysee_sc_check_presence(d);
+        }
+
+        if (ret==0) {
+                cmd[5] = count&0xff;
+                ret =  anysee_ctrl_msg(d, cmd, sizeof(cmd), 0, 0);
+        }
+        
+        while (ret==0 && written<count) {
+                u8 write_buf[52];
+
+                unsigned to_write = count - written;
+                if (to_write>48) to_write = 48;
+
+                write_buf[0] = 0x34;
+                write_buf[1] = 0x07;
+                write_buf[2] = to_write;
+                if (copy_from_user(write_buf+3, buf + written, to_write)) {
+                    ret = -EFAULT;
+                }
+
+                if (ret==0) {
+                    write_buf[to_write+3] = 0x01;
+                    
+                    ret = anysee_ctrl_msg(d, write_buf, to_write + 4,
+                                          write_buf, 1);
+                    if (ret==0) {
+                        if (write_buf[0]==to_write) {
+                            written += to_write;
+                        } else {
+                            ret = -EIO;
+                        }
+                    }
+                }
+        }
+        
+        mutex_unlock(&sc_state->mutex);
+
+        return (ret==0) ? count : ret;
+}
+
+static int anysee_sc_activate(struct anysee_sc_state* sc_state, unsigned long arg)
+{    
+        struct dvb_usb_device* d = sc_state->dvb_usb_device;
+        struct anysee_sc_activate __user* params = (struct anysee_sc_activate __user*)arg;
+        int ret = 0;
+        u8 x;
+
+        if (!access_ok(VERIFY_WRITE, params, sizeof(anysee_sc_activate))) {
+            ret = -EFAULT;
+        }
+
+        if (ret==0) {
+            ret = anysee_sc_check_presence(d);
+        }
+        
+        if (ret==0) {
+            ret = anysee_read_reg(d, 0x00a0, &x);
+        }
+
+        if (ret==0) {
+            ret = anysee_write_reg(d, 0x00a0, x|0x01);
+        }
+
+        if (ret==0) {
+            static u8 cmd[] = { 0x34, 0x09, 0x01 };
+            ret = anysee_ctrl_msg(d, cmd, sizeof(cmd), 0, 0);
+        }
+
+        if (ret==0) {
+            static u8 cmd[] = { 0x34, 0x08, 0x01, 0x02 };
+            ret = anysee_ctrl_msg(d, cmd, sizeof(cmd), 0, 0);
+        }
+
+        if (ret==0) {
+            unsigned index = 0;
+            unsigned atr_length = 2;
+            unsigned fmt_index = 1;
+            unsigned k = 0;
+            
+            while(index<sizeof(params->atr) && index<atr_length && ret==0) {
+                ret = anysee_sc_read_byte(d, &x, (index==0) ? 1000 : 100, 0x00);
+                if (ret==0) {
+                    if (index==fmt_index) {
+                        if (index==1) k = x&0x0f;
+                        if (x&0x10) ++atr_length;
+                        if (x&0x20) ++atr_length;
+                        if (x&0x40) ++atr_length;
+                        if (x&0x80) {
+                            fmt_index = atr_length;
+                            ++atr_length;
+                        } else {
+                            atr_length += k;
+                        }
+                    }
+                    params->atr[index++] = x;
+                }
+            }
+            params->atr_length = index;
+        }
+
+        return ret;
+}
+
+static int anysee_sc_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+{
+        struct anysee_sc_state* sc_state = (struct anysee_sc_state*)filp->private_data;
+        int ret = -ENODEV;
+
+	if (mutex_lock_interruptible(&sc_state->mutex) < 0)
+		return -EAGAIN;
+
+        switch(cmd) {
+            case ANYSEE_SC_ACTIVATE:
+              ret = anysee_sc_activate(sc_state, arg);
+              break;
+            case ANYSEE_SC_PRESENT:
+              ret = anysee_sc_check_presence(sc_state->dvb_usb_device);
+              if (ret==-EPIPE) ret = 0;
+              else if (ret==0) ret = 1;
+        }
+
+        mutex_unlock(&sc_state->mutex);
+
+        return ret;
+}
+
+static struct file_operations anysee_sc_fops = {
+        .owner = THIS_MODULE,
+        .open = anysee_sc_open,
+        .read = anysee_sc_read,
+        .write = anysee_sc_write,
+        .ioctl = anysee_sc_ioctl,
+};
+
+static int anysee_sc_init(struct dvb_usb_adapter* adap)
+{
+        struct dvb_usb_device* d = adap->dev;
+        int ret = 0;
+        struct anysee_state *state = d->priv;
+        state->sc_state.dvb_usb_device = d;
+        
+        state->sc_state.devnum = MKDEV(MAJOR(sc_dev), d->adapter[0].id);
+        
+        cdev_init(&state->sc_state.cdev, &anysee_sc_fops);
+        state->sc_state.cdev.owner = THIS_MODULE;
+
+        mutex_init(&state->sc_state.mutex);
+        
+        ret = cdev_add(&state->sc_state.cdev, state->sc_state.devnum, 1);
+        if (ret) {
+		err("%s: cdev_add failed. Error number %d", __func__, ret);
+        } else {
+                device_create(sc_class, adap->dvb_adap.device, state->sc_state.devnum, 
+                              0, "anysee_sc%u", d->adapter[0].id);
+        }
+        return ret;
+}
+
 static int anysee_init(struct dvb_usb_device *d)
 {
 	int ret;
@@ -148,6 +418,17 @@
 	return 0;
 }
 
+static void anysee_exit(struct usb_interface *intf)
+{
+	struct dvb_usb_device *d = usb_get_intfdata(intf);
+        struct anysee_state *state = d->priv;
+
+        device_destroy(sc_class, state->sc_state.devnum);
+        cdev_del(&state->sc_state.cdev);
+
+        dvb_usb_device_exit(intf);
+}
+
 /* I2C */
 static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
 	int num)
@@ -269,6 +550,10 @@
 		return ret;
 	deb_info("%s: IO port D:%02x\n", __func__, io_d);
 
+        ret = anysee_sc_init(adap);
+	if (ret)
+		return ret;
+
 	/* Select demod using trial and error method. */
 
 	/* Try to attach demodulator in following order:
@@ -541,7 +826,7 @@
 static struct usb_driver anysee_driver = {
 	.name       = "dvb_usb_anysee",
 	.probe      = anysee_probe,
-	.disconnect = dvb_usb_device_exit,
+	.disconnect = anysee_exit,
 	.id_table   = anysee_table,
 };
 
@@ -550,10 +835,28 @@
 {
 	int ret;
 
-	ret = usb_register(&anysee_driver);
-	if (ret)
-		err("%s: usb_register failed. Error number %d", __func__, ret);
-
+        ret = alloc_chrdev_region(&sc_dev, 0, sc_count, "anysee_sc");
+        if (ret) 
+		err("%s: alloc_chrdev_region failed. Error number %d", __func__, ret);
+        
+        if (!ret) {
+                sc_class = class_create(THIS_MODULE, "anysee_sc");
+                if (IS_ERR(sc_class)) {
+                        err("%s: class_simple_create failed.", __func__);
+                        unregister_chrdev_region(sc_dev, sc_count);
+                        ret = -ENODEV;
+                }
+        }
+
+        if (!ret) {
+                ret = usb_register(&anysee_driver);
+                if (ret) {
+                        err("%s: usb_register failed. Error number %d", __func__, ret);
+                        class_destroy(sc_class);
+                        unregister_chrdev_region(sc_dev, sc_count);
+                }
+        }
+                
 	return ret;
 }
 
@@ -561,6 +864,11 @@
 {
 	/* deregister this driver from the USB subsystem */
 	usb_deregister(&anysee_driver);
+
+        class_destroy(sc_class);
+        
+        unregister_chrdev_region(sc_dev, sc_count);
+
 }
 
 module_init(anysee_module_init);
--- anysee.h.orig	2010-08-02 00:11:14.000000000 +0200
+++ anysee.h	2010-12-05 19:07:55.000000000 +0100
@@ -34,6 +34,8 @@
 #ifndef _DVB_USB_ANYSEE_H_
 #define _DVB_USB_ANYSEE_H_
 
+#include <linux/cdev.h>
+
 #define DVB_USB_LOG_PREFIX "anysee"
 #include "dvb-usb.h"
 
@@ -56,9 +58,17 @@
 	CMD_SMARTCARD           = 0x34,
 };
 
+struct anysee_sc_state {
+        struct dvb_usb_device* dvb_usb_device;
+        dev_t devnum;
+        struct cdev cdev;
+        struct mutex mutex;
+};
+
 struct anysee_state {
 	u8 tuner;
 	u8 seq;
+        struct anysee_sc_state sc_state;
 };
 
 #endif

[-- Attachment #3: anysee_sc.h --]
[-- Type: text/x-chdr, Size: 338 bytes --]

#ifndef ANYSEE_SC_H
#define ANYSEE_SC_H

#include <linux/ioctl.h>

#define ANYSEE_SC_IOC_MAGIC 's'

struct anysee_sc_activate {
        unsigned atr_length;
        unsigned char atr[33];
};

#define ANYSEE_SC_ACTIVATE _IOR(ANYSEE_SC_IOC_MAGIC, 1, struct anysee_sc_activate)

#define ANYSEE_SC_PRESENT _IO(ANYSEE_SC_IOC_MAGIC, 2)

#endif

[-- Attachment #4: ifd-anysee.c --]
[-- Type: text/x-csrc, Size: 2581 bytes --]

#include "internal.h"

#include "anysee_sc.h"

#include <string.h>
#include <fcntl.h>

static int anysee_open(ifd_reader_t* reader, const char* name)
{
    ifd_device_t* dev = 0;
    int fd = -1;
    const char* device_name = 0;

    ifd_debug(1, "anysee_open: name='%s'\n", name);

    device_name = strchr(name, ':');
    if (device_name==0) return -1;
    ++device_name;

    fd = open(device_name, O_RDWR);
    ifd_debug(2, "anysee_open: fd=%d\n", fd);
    if (fd<0) return -1;
    
    reader->name = "Anysee DVB USB card reader";
    reader->nslots = 1;

    dev = ifd_device_new(name, 0, sizeof(*dev));
    reader->device = dev;
    dev->timeout = 1000;
    dev->fd = fd;
    dev->type = IFD_DEVICE_TYPE_OTHER;

    return 0;
}

static int anysee_close(ifd_reader_t * reader)
{
    return close(reader->device->fd);
}

static int anysee_activate(ifd_reader_t *reader)
{
    return 0;
}

static int anysee_deactivate(ifd_reader_t *reader)
{
    return 0;
}

static int anysee_card_status(ifd_reader_t *reader, int slot, int *status)
{
    int rv = ioctl(reader->device->fd, ANYSEE_SC_PRESENT);
    ifd_debug(2, "anysee_card_status: rv=%d\n", rv);
    if (rv<0) {
        return -1;
    } else {
        *status = (rv==0) ? 0 : IFD_CARD_PRESENT;
        return 0;
    }
}

static int anysee_card_reset(ifd_reader_t *reader, int slot, void *atr, size_t atr_len)
{
    struct anysee_sc_activate activate;

    if (ioctl(reader->device->fd, ANYSEE_SC_ACTIVATE, &activate)<0) {
        ifd_debug(2, "anysee_card_reset: failed\n");
        return -1;
    } else {
        size_t length = (atr_len<activate.atr_length) ? atr_len : activate.atr_length;
        memcpy(atr, activate.atr, length);
        return length;
    }
}


static int anysee_send(ifd_reader_t *reader, unsigned int dad,
                       const unsigned char *buffer, size_t len)
{
    return write(reader->device->fd, buffer, len);
}

static int anysee_recv(ifd_reader_t *reader, unsigned int dad,
                       unsigned char *buffer, size_t len,
                       long timeout)
{
    return read(reader->device->fd, buffer, len);
}

static struct ifd_driver_ops anysee_ops;

void ifd_anysee_register()
{
    anysee_ops.open = &anysee_open;
    anysee_ops.close = &anysee_close;
    anysee_ops.activate = &anysee_activate;
    anysee_ops.deactivate = &anysee_deactivate;
    anysee_ops.card_status = &anysee_card_status;
    anysee_ops.card_reset = &anysee_card_reset;
    anysee_ops.send = &anysee_send;
    anysee_ops.recv = &anysee_recv;

    ifd_driver_register("anysee", &anysee_ops);
}

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Smart card reader support for Anysee DVB devices
  2011-07-17 14:18 Smart card reader support for Anysee DVB devices István Váradi
@ 2011-08-14 23:51 ` Antti Palosaari
  2011-08-15 11:14   ` Antti Palosaari
  0 siblings, 1 reply; 16+ messages in thread
From: Antti Palosaari @ 2011-08-14 23:51 UTC (permalink / raw)
  To: István Váradi; +Cc: linux-media

Hello,
I looked your codes and examined also some more. About your driver, I
don't like you put so much functionality to the Kernel driver. Just put
this functionality to the userspace driver all and offer only lowest
possible interface (read + write) from Kernel. If you look other IFDs it
is like that.
On the other hand I see it could be possible to add some glue and
functionality to the Kernel driver if you find already existing
userspace protocol (IFD driver) which can be used. Add some emulation to
Kernel and use existing user space. Select some well supported serial
smartcard reader and make Anysee driver speak like that.

Biggest problem I see whole thing is poor application support. OpenCT is
rather legacy but there is no good alternative. All this kind of serial
drivers seems to be OpenCT currently.

regards
Antti

On 07/17/2011 05:18 PM, István Váradi wrote:
> Hi,
> 
> I have developed smart card reader support for the Anysee devices by
> extending Antti Palosaari's driver. I attached the patches for it. It
> registers a character device named /dev/anysee_scN for each Anysee
> device.
> 
> The character device supports two ioctl's (see anysee_sc), one for
> detecting the presence of a card, the other one for resetting the card
> and querying the ATR. The write() operation writes to the card by
> packaging the bytes into USB commands. The read() operation issues an
> appropriate command over USB and returns the reply. I have also
> written a simple OpenCT driver (attached) which shows the usage.
> 
> I would like to have the kernel driver included in the official
> sources. For this reason I corresponded with Antti, and he suggested
> the perhaps the kernel driver should have a lower-level interface. I
> had the following proposal:
> 
> We would continue having the two ioctls, ANYSEE_SC_ACTIVATE and
> ANYSEE_SC_PRESENT, however, ANYSEE_SC_ACTIVATE would do only the
> register reading and writing.
> 
> Besides these two we need access to the anysee_ctrl_msg() function
> somehow. I think the cleanest way would be via another ioctl() call in
> which we would pass the return buffer as well, with the length so that
> we know how many bytes to copy. Another possibility would be that a
> call to write() calls anysee_ctrl_msg() and stores the return data in
> a 64 byte buffer that we allocate for each device. The read()
> following a write() would read this buffer, then discard it. Further
> read() attempts would fail with EAGAIN, or we could maintain an offset
> into the 64 byte buffer, and read as long as there is data, and fail
> only then. A write() would cause losing any unread data.
> 
> What do you think?
> 
> Thanks,
> 
> Istvan


-- 
http://palosaari.fi/

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Smart card reader support for Anysee DVB devices
  2011-08-14 23:51 ` Antti Palosaari
@ 2011-08-15 11:14   ` Antti Palosaari
  2011-08-17 20:41     ` Antti Palosaari
  0 siblings, 1 reply; 16+ messages in thread
From: Antti Palosaari @ 2011-08-15 11:14 UTC (permalink / raw)
  To: István Váradi; +Cc: linux-media

On 08/15/2011 02:51 AM, Antti Palosaari wrote:
> Biggest problem I see whole thing is poor application support. OpenCT is
> rather legacy but there is no good alternative. All this kind of serial
> drivers seems to be OpenCT currently.

I wonder if it is possible to make virtual CCID device since CCID seems
to be unfortunately the only interface SmartCard guys currently care.


Antti

-- 
http://palosaari.fi/

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Smart card reader support for Anysee DVB devices
  2011-08-15 11:14   ` Antti Palosaari
@ 2011-08-17 20:41     ` Antti Palosaari
  2011-08-29 14:44       ` István Váradi
  0 siblings, 1 reply; 16+ messages in thread
From: Antti Palosaari @ 2011-08-17 20:41 UTC (permalink / raw)
  To: István Váradi; +Cc: linux-media

On 08/15/2011 02:14 PM, Antti Palosaari wrote:
> On 08/15/2011 02:51 AM, Antti Palosaari wrote:
>> Biggest problem I see whole thing is poor application support. OpenCT is
>> rather legacy but there is no good alternative. All this kind of serial
>> drivers seems to be OpenCT currently.
> 
> I wonder if it is possible to make virtual CCID device since CCID seems
> to be unfortunately the only interface SmartCard guys currently care.

I studied scenario and looks like it is possible to implement way like,
register virtual USB HCI (virtual motherboard USB controller) then
register virtual PC/SC device to that which hooks all calls to HW via
Anysee driver. Some glue surely needed for emulate PC/SC. I think there
is not any such driver yet. Anyhow, there is virtual USB HCI driver
currently in staging which can be used as example, or even use it to
register virtual device. That kind of functionality surely needs more
talking...


regards,
Antti
-- 
http://palosaari.fi/

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Smart card reader support for Anysee DVB devices
  2011-08-17 20:41     ` Antti Palosaari
@ 2011-08-29 14:44       ` István Váradi
  2011-08-29 14:50         ` Antti Palosaari
  0 siblings, 1 reply; 16+ messages in thread
From: István Váradi @ 2011-08-29 14:44 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: linux-media

Hi,

2011/8/17 Antti Palosaari <crope@iki.fi>:
> On 08/15/2011 02:14 PM, Antti Palosaari wrote:
>> On 08/15/2011 02:51 AM, Antti Palosaari wrote:
>>> Biggest problem I see whole thing is poor application support. OpenCT is
>>> rather legacy but there is no good alternative. All this kind of serial
>>> drivers seems to be OpenCT currently.
>>
>> I wonder if it is possible to make virtual CCID device since CCID seems
>> to be unfortunately the only interface SmartCard guys currently care.
>
> I studied scenario and looks like it is possible to implement way like,
> register virtual USB HCI (virtual motherboard USB controller) then
> register virtual PC/SC device to that which hooks all calls to HW via
> Anysee driver. Some glue surely needed for emulate PC/SC. I think there
> is not any such driver yet. Anyhow, there is virtual USB HCI driver
> currently in staging which can be used as example, or even use it to
> register virtual device. That kind of functionality surely needs more
> talking...

It maybe that smartcard guys care only for CCID, but wouldn't it be an
overkill to implement an emulation of that for the driver? It can be
done, of course, but I think it would be much more complicated than
the current one. Is it really necessary to put such complexity into
the kernel? In my opinion, this should be handled in user-space.

Regards,

Istvan

>
>
> regards,
> Antti
> --
> http://palosaari.fi/
>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Smart card reader support for Anysee DVB devices
  2011-08-29 14:44       ` István Váradi
@ 2011-08-29 14:50         ` Antti Palosaari
  2011-08-29 15:13           ` István Váradi
  2011-10-03 12:36           ` James Courtier-Dutton
  0 siblings, 2 replies; 16+ messages in thread
From: Antti Palosaari @ 2011-08-29 14:50 UTC (permalink / raw)
  To: István Váradi; +Cc: linux-media

On 08/29/2011 05:44 PM, István Váradi wrote:
> Hi,
>
> 2011/8/17 Antti Palosaari<crope@iki.fi>:
>> On 08/15/2011 02:14 PM, Antti Palosaari wrote:
>>> On 08/15/2011 02:51 AM, Antti Palosaari wrote:
>>>> Biggest problem I see whole thing is poor application support. OpenCT is
>>>> rather legacy but there is no good alternative. All this kind of serial
>>>> drivers seems to be OpenCT currently.
>>>
>>> I wonder if it is possible to make virtual CCID device since CCID seems
>>> to be unfortunately the only interface SmartCard guys currently care.
>>
>> I studied scenario and looks like it is possible to implement way like,
>> register virtual USB HCI (virtual motherboard USB controller) then
>> register virtual PC/SC device to that which hooks all calls to HW via
>> Anysee driver. Some glue surely needed for emulate PC/SC. I think there
>> is not any such driver yet. Anyhow, there is virtual USB HCI driver
>> currently in staging which can be used as example, or even use it to
>> register virtual device. That kind of functionality surely needs more
>> talking...
>
> It maybe that smartcard guys care only for CCID, but wouldn't it be an
> overkill to implement an emulation of that for the driver? It can be
> done, of course, but I think it would be much more complicated than
> the current one. Is it really necessary to put such complexity into
> the kernel? In my opinion, this should be handled in user-space.

Only De facto serial smartcard protocol is so called Phoenix/Smartmouse, 
implementing new protocol is totally dead idea. It will never got any 
support.

There is already such drivers, at least Infinity Unlimited USB Phoenix 
driver (iuu_phoenix.c). It uses USB-serial driver framework and some 
small emulation for Phoenix protocol. Look that driver to see which kind 
of complexity it adds. Anysee have *just* same situation.

regards
Antti


-- 
http://palosaari.fi/

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Smart card reader support for Anysee DVB devices
  2011-08-29 14:50         ` Antti Palosaari
@ 2011-08-29 15:13           ` István Váradi
  2011-08-29 15:23             ` Antti Palosaari
  2011-10-03 12:36           ` James Courtier-Dutton
  1 sibling, 1 reply; 16+ messages in thread
From: István Váradi @ 2011-08-29 15:13 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: linux-media

2011/8/29 Antti Palosaari <crope@iki.fi>:
> On 08/29/2011 05:44 PM, István Váradi wrote:
>>
>> Hi,
>>
>> 2011/8/17 Antti Palosaari<crope@iki.fi>:
>>>
>>> On 08/15/2011 02:14 PM, Antti Palosaari wrote:
>>>>
>>>> On 08/15/2011 02:51 AM, Antti Palosaari wrote:
>>>>>
>>>>> Biggest problem I see whole thing is poor application support. OpenCT
>>>>> is
>>>>> rather legacy but there is no good alternative. All this kind of serial
>>>>> drivers seems to be OpenCT currently.
>>>>
>>>> I wonder if it is possible to make virtual CCID device since CCID seems
>>>> to be unfortunately the only interface SmartCard guys currently care.
>>>
>>> I studied scenario and looks like it is possible to implement way like,
>>> register virtual USB HCI (virtual motherboard USB controller) then
>>> register virtual PC/SC device to that which hooks all calls to HW via
>>> Anysee driver. Some glue surely needed for emulate PC/SC. I think there
>>> is not any such driver yet. Anyhow, there is virtual USB HCI driver
>>> currently in staging which can be used as example, or even use it to
>>> register virtual device. That kind of functionality surely needs more
>>> talking...
>>
>> It maybe that smartcard guys care only for CCID, but wouldn't it be an
>> overkill to implement an emulation of that for the driver? It can be
>> done, of course, but I think it would be much more complicated than
>> the current one. Is it really necessary to put such complexity into
>> the kernel? In my opinion, this should be handled in user-space.
>
> Only De facto serial smartcard protocol is so called Phoenix/Smartmouse,
> implementing new protocol is totally dead idea. It will never got any
> support.
>
> There is already such drivers, at least Infinity Unlimited USB Phoenix
> driver (iuu_phoenix.c). It uses USB-serial driver framework and some small
> emulation for Phoenix protocol. Look that driver to see which kind of
> complexity it adds. Anysee have *just* same situation.

Phoenix/Smartmouse and CCID are quite different aren't they? So to
support Phoenix I would need provide a USB serial device which talks
the protocol, but there would be no need for a virtual USB HCI. Is
that correct?

Regards,

Istvan

>
> regards
> Antti
>
>
> --
> http://palosaari.fi/
>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Smart card reader support for Anysee DVB devices
  2011-08-29 15:13           ` István Váradi
@ 2011-08-29 15:23             ` Antti Palosaari
  2011-09-02 11:04               ` Bjørn Mork
  0 siblings, 1 reply; 16+ messages in thread
From: Antti Palosaari @ 2011-08-29 15:23 UTC (permalink / raw)
  To: István Váradi; +Cc: linux-media

On 08/29/2011 06:13 PM, István Váradi wrote:
> 2011/8/29 Antti Palosaari<crope@iki.fi>:
>> On 08/29/2011 05:44 PM, István Váradi wrote:
>>> 2011/8/17 Antti Palosaari<crope@iki.fi>:
>>>> On 08/15/2011 02:14 PM, Antti Palosaari wrote:
>>>>> On 08/15/2011 02:51 AM, Antti Palosaari wrote:
>>>>>> Biggest problem I see whole thing is poor application support. OpenCT
>>>>>> is
>>>>>> rather legacy but there is no good alternative. All this kind of serial
>>>>>> drivers seems to be OpenCT currently.
>>>>>
>>>>> I wonder if it is possible to make virtual CCID device since CCID seems
>>>>> to be unfortunately the only interface SmartCard guys currently care.
>>>>
>>>> I studied scenario and looks like it is possible to implement way like,
>>>> register virtual USB HCI (virtual motherboard USB controller) then
>>>> register virtual PC/SC device to that which hooks all calls to HW via
>>>> Anysee driver. Some glue surely needed for emulate PC/SC. I think there
>>>> is not any such driver yet. Anyhow, there is virtual USB HCI driver
>>>> currently in staging which can be used as example, or even use it to
>>>> register virtual device. That kind of functionality surely needs more
>>>> talking...
>>>
>>> It maybe that smartcard guys care only for CCID, but wouldn't it be an
>>> overkill to implement an emulation of that for the driver? It can be
>>> done, of course, but I think it would be much more complicated than
>>> the current one. Is it really necessary to put such complexity into
>>> the kernel? In my opinion, this should be handled in user-space.
>>
>> Only De facto serial smartcard protocol is so called Phoenix/Smartmouse,
>> implementing new protocol is totally dead idea. It will never got any
>> support.
>>
>> There is already such drivers, at least Infinity Unlimited USB Phoenix
>> driver (iuu_phoenix.c). It uses USB-serial driver framework and some small
>> emulation for Phoenix protocol. Look that driver to see which kind of
>> complexity it adds. Anysee have *just* same situation.
>
> Phoenix/Smartmouse and CCID are quite different aren't they? So to
> support Phoenix I would need provide a USB serial device which talks
> the protocol, but there would be no need for a virtual USB HCI. Is
> that correct?

Yes, CCID and serial are different interfaces. CCID is new interface 
specified by USB organization that needs "hardware" level interface 
profile like mass storage profile. Serial is block device interface 
(/dev/tty).

Since Anysee device itself does not have CCID interface it is needed to 
make virtual USB device in order to get CCID support. I have never seen 
virtual USB devices like that, but there is VHCI in current kernel 
staging that actually does something like that over IP.


regards
Antti
-- 
http://palosaari.fi/

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Smart card reader support for Anysee DVB devices
  2011-08-29 15:23             ` Antti Palosaari
@ 2011-09-02 11:04               ` Bjørn Mork
  2011-09-02 13:32                 ` Antti Palosaari
  0 siblings, 1 reply; 16+ messages in thread
From: Bjørn Mork @ 2011-09-02 11:04 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: István Váradi, linux-media

Antti Palosaari <crope@iki.fi> writes:

> Since Anysee device itself does not have CCID interface it is needed
> to make virtual USB device in order to get CCID support. I have never
> seen virtual USB devices like that, but there is VHCI in current
> kernel staging that actually does something like that over IP.

Don't know if you have seen this already, but there's a virtual CCID
device implementation in QEMU.  See http://wiki.qemu.org/Features/Smartcard
Should be a good starting point.  Combine it withe the VHCI driver from
USBIP and you have your CCID device.


Bjørn

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Smart card reader support for Anysee DVB devices
  2011-09-02 11:04               ` Bjørn Mork
@ 2011-09-02 13:32                 ` Antti Palosaari
  2011-09-28 14:32                   ` Antti Palosaari
  0 siblings, 1 reply; 16+ messages in thread
From: Antti Palosaari @ 2011-09-02 13:32 UTC (permalink / raw)
  To: Bjørn Mork; +Cc: István Váradi, linux-media

On 09/02/2011 02:04 PM, Bjørn Mork wrote:
> Antti Palosaari<crope@iki.fi>  writes:
>
>> Since Anysee device itself does not have CCID interface it is needed
>> to make virtual USB device in order to get CCID support. I have never
>> seen virtual USB devices like that, but there is VHCI in current
>> kernel staging that actually does something like that over IP.
>
> Don't know if you have seen this already, but there's a virtual CCID
> device implementation in QEMU.  See http://wiki.qemu.org/Features/Smartcard
> Should be a good starting point.  Combine it withe the VHCI driver from
> USBIP and you have your CCID device.

It is first time I hear about QEMU virtual CCID. Now we have all parts 
needed for USBIP VHCI and QEMU virtual CCID, just glue those together.

I wonder if it is wise to even create virtual CCID "core" to Kernel. 
There is few other readers that can use that too, actually I think all 
USB readers that have unique USB ID (blocking out those which uses 
USB-serial converters with common IDs).

As I see that CCID still more complex as serial device I will still look 
implementing it as serial as now.

regards
Antti


-- 
http://palosaari.fi/

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Smart card reader support for Anysee DVB devices
  2011-09-02 13:32                 ` Antti Palosaari
@ 2011-09-28 14:32                   ` Antti Palosaari
  2011-09-30 15:36                     ` Antti Palosaari
  0 siblings, 1 reply; 16+ messages in thread
From: Antti Palosaari @ 2011-09-28 14:32 UTC (permalink / raw)
  To: Bjørn Mork, István Váradi; +Cc: linux-media

[-- Attachment #1: Type: text/plain, Size: 1677 bytes --]

On 09/02/2011 04:32 PM, Antti Palosaari wrote:
> On 09/02/2011 02:04 PM, Bjørn Mork wrote:
>> Antti Palosaari<crope@iki.fi> writes:
>>
>>> Since Anysee device itself does not have CCID interface it is needed
>>> to make virtual USB device in order to get CCID support. I have never
>>> seen virtual USB devices like that, but there is VHCI in current
>>> kernel staging that actually does something like that over IP.
>>
>> Don't know if you have seen this already, but there's a virtual CCID
>> device implementation in QEMU. See
>> http://wiki.qemu.org/Features/Smartcard
>> Should be a good starting point. Combine it withe the VHCI driver from
>> USBIP and you have your CCID device.
>
> It is first time I hear about QEMU virtual CCID. Now we have all parts
> needed for USBIP VHCI and QEMU virtual CCID, just glue those together.
>
> I wonder if it is wise to even create virtual CCID "core" to Kernel.
> There is few other readers that can use that too, actually I think all
> USB readers that have unique USB ID (blocking out those which uses
> USB-serial converters with common IDs).
>
> As I see that CCID still more complex as serial device I will still look
> implementing it as serial as now.

Here it is, patch attached. Implemented as serial device. Anysee uses 
two different smart card interfaces, CST56I01 and TDA8024. That one is 
old CST56I01, I will try to add TDA8024 later, maybe even tonight.

Anyhow, it is something like proof-of-concept currently, missing locks 
and abusing ttyUSB. Have you any idea if I should reserve own major 
device numbers for Anysee or should I reserve one like DVB common?

Any other ideas?

Antti
-- 
http://palosaari.fi/

[-- Attachment #2: anysee_smartcard_sniper2.patch --]
[-- Type: text/plain, Size: 10932 bytes --]

diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c
index 0bc1372..79497f3 100644
--- a/drivers/media/dvb/dvb-usb/anysee.c
+++ b/drivers/media/dvb/dvb-usb/anysee.c
@@ -44,7 +44,7 @@
 #include "cxd2820r.h"
 
 /* debug */
-static int dvb_usb_anysee_debug;
+static int dvb_usb_anysee_debug = -1;
 module_param_named(debug, dvb_usb_anysee_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
 static int dvb_usb_anysee_delsys;
@@ -67,6 +67,11 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
 	if (mutex_lock_interruptible(&anysee_usb_mutex) < 0)
 		return -EAGAIN;
 
+	if (sbuf[0] == CMD_SMARTCARD) {
+		deb_xfer(">>> ");
+		debug_dump(buf, slen, deb_xfer);
+	}
+
 	/* We need receive one message more after dvb_usb_generic_rw due
 	   to weird transaction flow, which is 1 x send + 2 x receive. */
 	ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0);
@@ -79,8 +84,15 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
 		if (ret)
 			err("%s: recv bulk message failed: %d", __func__, ret);
 		else {
-			deb_xfer("<<< ");
-			debug_dump(buf, act_len, deb_xfer);
+//			deb_xfer("<<< ");
+//			debug_dump(buf, act_len, deb_xfer);
+			if (sbuf[0] == CMD_SMARTCARD) {
+				if (buf[63] != 0x4f)
+					deb_info("%s: packet NOK: %02x\n", __func__, buf[63]);
+
+				deb_xfer("<<< ");
+				debug_dump(buf, 40, deb_xfer);
+			}
 		}
 	}
 
@@ -701,6 +713,8 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
 		adap->fe_adap[0].fe = dvb_attach(tda10023_attach,
 			&anysee_tda10023_config, &adap->dev->i2c_adap, 0x48);
 
+		state->has_sc = true;
+
 		break;
 	case ANYSEE_HW_507SI: /* 11 */
 		/* E30 S2 Plus */
@@ -1014,6 +1028,7 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
 	return ret;
 }
 
+#if 0
 static int anysee_rc_query(struct dvb_usb_device *d)
 {
 	u8 buf[] = {CMD_GET_IR_CODE};
@@ -1039,6 +1054,7 @@ static int anysee_rc_query(struct dvb_usb_device *d)
 
 	return 0;
 }
+#endif
 
 static int anysee_ci_read_attribute_mem(struct dvb_ca_en50221 *ci, int slot,
 	int addr)
@@ -1208,6 +1224,292 @@ static void anysee_ci_release(struct dvb_usb_device *d)
 	return;
 }
 
+// stty -aF /dev/ttyUSB0
+// setserial /dev/ttyUSB0
+// statserial /dev/ttyUSB0
+// more /proc/tty/drivers
+// watch head /proc/tty/driver/serial
+// http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html_single/Serial-HOWTO.html
+
+
+static int anysee_rc_query(struct dvb_usb_device *d)
+{
+	u8 sbuf[] = {CMD_SMARTCARD, 0x06, 0x20};
+	u8 rbuf[60];
+	int ret;
+	u8 *ptr;
+	struct anysee_state *state = d->priv;
+	struct tty_struct *tty = state->sc_tty_driver->ttys[0];
+
+	if (state->sc_poll_count-- <= 0)
+		return 0;
+
+	deb_info("%s:\n", __func__);
+
+	ret = anysee_ctrl_msg(d, sbuf, sizeof(sbuf), rbuf, sizeof(rbuf));
+	if (ret)
+		return -EIO;
+
+	if (rbuf[0] != 0) {
+		ptr = &rbuf[2];
+		deb_info("rece data: ");
+		debug_dump(ptr, rbuf[0], deb_info);
+
+		tty_insert_flip_string(tty, &rbuf[2], rbuf[0]);
+		tty_flip_buffer_push(tty);
+	}
+
+	return 0;
+}
+
+static int anysee_sc_open(struct tty_struct *tty, struct file *filp)
+{
+	struct dvb_usb_device *d = tty->driver_data;
+	struct anysee_state *state = d->priv;
+	int ret, i;
+	u8 sbuf[5] = {CMD_SMARTCARD, 0x03, 1};
+	u8 tab[][2] = {
+		{0x00, 0xaf},
+		{0x10, 0x08},
+		{0x11, 0x4c},
+	};
+
+	deb_info("%s:\n", __func__);
+
+	for (i = 0; i < ARRAY_SIZE(tab); i++) {
+		sbuf[3] = tab[i][0];
+		sbuf[4] = tab[i][1];
+		ret = anysee_ctrl_msg(d, sbuf, sizeof(sbuf), NULL, 0);
+		if (ret)
+			goto err;
+	}
+
+	state->sc_poll_count = 0;
+
+	return 0;
+err:
+	return ret;
+}
+
+static void anysee_sc_close(struct tty_struct *tty, struct file *filp)
+{
+	struct dvb_usb_device *d = tty->driver_data;
+	struct anysee_state *state = d->priv;
+
+	deb_info("%s:\n", __func__);
+
+	state->sc_poll_count = 0;
+
+	msleep(1000);
+
+	return;
+}
+
+static int anysee_sc_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
+{
+	int ret;
+	struct dvb_usb_device *d = tty->driver_data;
+	struct anysee_state *state = d->priv;
+	u8 sbuf[] = {CMD_SMARTCARD, 0x08, 0x01, 0x02};
+
+	deb_info("%s: set=%x clear=%x set_RTS=%d clear_RTS=%d sc_card_present=%d\n", __func__, set, clear, (set & TIOCM_RTS), (clear & TIOCM_RTS),  state->sc_card_present);
+
+	if ((set & TIOCM_RTS) && state->sc_card_present) {
+		deb_info("%s: RESET CARD\n", __func__);
+		ret = anysee_ctrl_msg(d, sbuf, sizeof(sbuf), NULL, 0);
+		if (ret)
+			goto err;
+
+		state->sc_poll_count = 50;
+	}
+
+	return 0;
+err:
+	return ret;
+}
+
+static int anysee_sc_tiocmget(struct tty_struct *tty)
+{
+	struct dvb_usb_device *d = tty->driver_data;
+	struct anysee_state *state = d->priv;
+	int ret;
+	u8 sbuf[] = {CMD_SMARTCARD, 0x02, 0x01, 0x10};
+	u8 rbuf[1];
+	int tio = 0;
+
+	deb_info("%s:\n", __func__);
+	ret = anysee_ctrl_msg(d, sbuf, sizeof(sbuf), rbuf, sizeof(rbuf));
+	if (ret)
+		goto err;
+
+	if (rbuf[0] & (1 << 7)) {
+		tio |= TIOCM_CD;
+		state->sc_card_present = false;
+	} else {
+		tio &= ~TIOCM_CD;
+		state->sc_card_present = true;
+	}
+
+	deb_info("%s: TIO=%x rd:", __func__, tio);
+	debug_dump(rbuf, 1, deb_info);
+
+	return tio;
+err:
+	return ret;
+}
+
+static int anysee_sc_write(struct tty_struct *tty, const u8 *buf, int count)
+{
+	struct dvb_usb_device *d = tty->driver_data;
+	struct anysee_state *state = d->priv;
+	int ret;
+	u8 rbuf[60];
+	u8 sbuf[60] = {CMD_SMARTCARD, 0x08, 0x01, 0x01, 0x00, count};
+
+	deb_info("send data: ");
+	debug_dump(buf, count, deb_info);
+
+	ret = anysee_ctrl_msg(d, sbuf, 7, NULL, 0);
+	if (ret)
+		goto err;
+
+	sbuf[1] = 0x07;
+	sbuf[2] = count;
+	memcpy(&sbuf[3], buf, count);
+
+	ret = anysee_ctrl_msg(d, sbuf, count+3, rbuf, sizeof(rbuf));
+	if (ret)
+		goto err;
+
+	if (rbuf[0]) {
+		/* TODO: can that echo removed ? */
+		tty_insert_flip_string(tty, &sbuf[3], rbuf[0]);
+		tty_flip_buffer_push(tty);
+	}
+
+	state->sc_poll_count = 50;
+
+	return count;
+
+err:
+	return ret;
+}
+
+static int anysee_sc_write_room(struct tty_struct *tty)
+{
+	deb_info("%s:\n", __func__);
+	return 32;
+}
+
+static void anysee_sc_set_termios(struct tty_struct *tty, struct ktermios *old)
+{
+	tty_termios_copy_hw(tty->termios, old);
+	deb_info("%s:\n", __func__);
+	return;
+}
+
+static int anysee_sc_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+	int idx = tty->index;
+
+	deb_info("%s:\n", __func__);
+
+	if (tty_init_termios(tty) == 0) {
+		tty_driver_kref_get(driver);
+		tty->count++;
+		driver->ttys[idx] = tty;
+		tty->driver_data = driver->driver_state;
+		return 0;
+	}
+	return -ENOMEM;
+}
+
+static const struct tty_operations serial_ops = {
+	.open =			anysee_sc_open,
+	.close =		anysee_sc_close,
+	.write =		anysee_sc_write,
+//	.hangup = 		anysee_sc_hangup,
+	.write_room =		anysee_sc_write_room,
+//	.ioctl =		anysee_sc_ioctl,
+	.set_termios =		anysee_sc_set_termios,
+//	.throttle =		anysee_sc_throttle,
+//	.unthrottle =		anysee_sc_unthrottle,
+//	.break_ctl =		anysee_sc_break,
+//	.chars_in_buffer =	anysee_sc_chars_in_buffer,
+	.tiocmget =		anysee_sc_tiocmget,
+	.tiocmset =		anysee_sc_tiocmset,
+//	.get_icount = 		anysee_sc_get_icount,
+//	.cleanup = 		anysee_sc_cleanup,
+	.install = 		anysee_sc_install,
+//	.proc_fops =		&anysee_sc_proc_fops,
+};
+
+#define SERIAL_TTY_MAJOR 188  /* abuse usb-serial... */
+static int anysee_sc_init(struct dvb_usb_device *d)
+{
+	struct anysee_state *state = d->priv;
+	int ret;
+
+	deb_info("%s:\n", __func__);
+
+	state->sc_tty_driver = alloc_tty_driver(1);
+	if (!state->sc_tty_driver) {
+		ret = -ENOMEM;
+		goto err_alloc_tty_driver;
+	}
+
+	state->sc_tty_driver->owner = THIS_MODULE;
+	state->sc_tty_driver->driver_name = "anysee";
+	state->sc_tty_driver->name = "ttyUSB";
+	state->sc_tty_driver->major = SERIAL_TTY_MAJOR;
+	state->sc_tty_driver->minor_start = 0;
+	state->sc_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	state->sc_tty_driver->subtype = SERIAL_TYPE_NORMAL;
+	state->sc_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	state->sc_tty_driver->init_termios = tty_std_termios;
+	state->sc_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	state->sc_tty_driver->init_termios.c_ispeed = 9600;
+	state->sc_tty_driver->init_termios.c_ospeed = 9600;
+	state->sc_tty_driver->driver_state = d;
+	tty_set_operations(state->sc_tty_driver, &serial_ops);
+	ret = tty_register_driver(state->sc_tty_driver);
+	if (ret)
+		goto err_tty_register_driver;
+
+	if (!tty_register_device(state->sc_tty_driver, 0, NULL))
+		goto err_tty_register_device;
+
+	info("serial device registered");
+
+	return 0;
+
+err_tty_register_device:
+	tty_unregister_driver(state->sc_tty_driver);
+
+err_tty_register_driver:
+	put_tty_driver(state->sc_tty_driver);
+
+err_alloc_tty_driver:
+	state->has_sc = false;
+	err("%s: failed=%d", __func__, ret);
+
+	return ret;
+}
+
+
+static void anysee_sc_release(struct dvb_usb_device *d)
+{
+	struct anysee_state *state = d->priv;
+
+	/* detach SmartCard */
+	if (state->has_sc) {
+		tty_unregister_device(state->sc_tty_driver, 0);
+		tty_unregister_driver(state->sc_tty_driver);
+	}
+
+	return;
+}
+
 static int anysee_init(struct dvb_usb_device *d)
 {
 	struct anysee_state *state = d->priv;
@@ -1232,6 +1534,15 @@ static int anysee_init(struct dvb_usb_device *d)
 		}
 	}
 
+	/* attach SmartCard */
+	if (state->has_sc) {
+		ret = anysee_sc_init(d);
+		if (ret) {
+			state->has_sc = false;
+			return ret;
+		}
+	}
+
 	return 0;
 }
 
@@ -1280,6 +1591,7 @@ static void anysee_disconnect(struct usb_interface *intf)
 {
 	struct dvb_usb_device *d = usb_get_intfdata(intf);
 
+	anysee_sc_release(d);
 	anysee_ci_release(d);
 	dvb_usb_device_exit(intf);
 
@@ -1342,7 +1654,7 @@ static struct dvb_usb_device_properties anysee_properties = {
 		.protocol         = RC_TYPE_OTHER,
 		.module_name      = "anysee",
 		.rc_query         = anysee_rc_query,
-		.rc_interval      = 250,  /* windows driver uses 500ms */
+		.rc_interval      = 150,  /* windows driver uses 500ms */
 	},
 
 	.i2c_algo         = &anysee_i2c_algo,
diff --git a/drivers/media/dvb/dvb-usb/anysee.h b/drivers/media/dvb/dvb-usb/anysee.h
index 8ac8794..1026717 100644
--- a/drivers/media/dvb/dvb-usb/anysee.h
+++ b/drivers/media/dvb/dvb-usb/anysee.h
@@ -38,6 +38,9 @@
 #include "dvb-usb.h"
 #include "dvb_ca_en50221.h"
 
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+
 #define deb_info(args...) dprintk(dvb_usb_anysee_debug, 0x01, args)
 #define deb_xfer(args...) dprintk(dvb_usb_anysee_debug, 0x02, args)
 #define deb_rc(args...)   dprintk(dvb_usb_anysee_debug, 0x04, args)
@@ -63,8 +66,14 @@ struct anysee_state {
 	u8 seq;
 	u8 fe_id:1; /* frondend ID */
 	u8 has_ci:1;
+	u8 has_sc:1;
+
 	struct dvb_ca_en50221 ci;
 	unsigned long ci_cam_ready; /* jiffies */
+
+	struct tty_driver *sc_tty_driver;
+	u8 sc_card_present:1;
+	int sc_poll_count;
 };
 
 #define ANYSEE_HW_507T    2 /* E30 */

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: Smart card reader support for Anysee DVB devices
  2011-09-28 14:32                   ` Antti Palosaari
@ 2011-09-30 15:36                     ` Antti Palosaari
  2011-10-02 21:06                       ` HoP
  2011-10-03 17:56                       ` Bjørn Mork
  0 siblings, 2 replies; 16+ messages in thread
From: Antti Palosaari @ 2011-09-30 15:36 UTC (permalink / raw)
  To: Bjørn Mork, István Váradi; +Cc: linux-media

On 09/28/2011 05:32 PM, Antti Palosaari wrote:
> On 09/02/2011 04:32 PM, Antti Palosaari wrote:

>> As I see that CCID still more complex as serial device I will still look
>> implementing it as serial as now.
>
> Here it is, patch attached. Implemented as serial device. Anysee uses
> two different smart card interfaces, CST56I01 and TDA8024. That one is
> old CST56I01, I will try to add TDA8024 later, maybe even tonight.
>
> Anyhow, it is something like proof-of-concept currently, missing locks
> and abusing ttyUSB. Have you any idea if I should reserve own major
> device numbers for Anysee or should I reserve one like DVB common?
>
> Any other ideas?

http://git.linuxtv.org/anttip/media_tree.git/shortlog/refs/heads/anysee

Now it works for TDA8024 based readers too (addition to CST56I01). Main 
difference was that TDA8024 designs reads card presence from GPIO whilst 
for CST56I01 it was got from anysee firmware (I think CST56I01 outputs 
that using I2C whilst TDA8024 have external IO line).

I tested it;
* E30 Combo Plus (TDA8024)
* E7 T2C (TDA8024)
* E30 C (CST56I01)

If you would like to help me then you can find out correct device name 
and whats needed for that. I mainly see following possibilities;
* /dev/ttyAnyseeN
* /dev/ttyDVBN
* /dev/adapterN/serial

regards
Antti
-- 
http://palosaari.fi/

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Smart card reader support for Anysee DVB devices
  2011-09-30 15:36                     ` Antti Palosaari
@ 2011-10-02 21:06                       ` HoP
  2011-10-03 17:56                       ` Bjørn Mork
  1 sibling, 0 replies; 16+ messages in thread
From: HoP @ 2011-10-02 21:06 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: Bjørn Mork, István Váradi, linux-media

> If you would like to help me then you can find out correct device name and
> whats needed for that. I mainly see following possibilities;
> * /dev/ttyAnyseeN
> * /dev/ttyDVBN
> * /dev/adapterN/serial
>

/dev/ttyscXN

or

/dev/dvb/adapterX/scN

where X = ordered adapter number
and N = ordered smartcard number in one device

/Honza

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Smart card reader support for Anysee DVB devices
  2011-08-29 14:50         ` Antti Palosaari
  2011-08-29 15:13           ` István Váradi
@ 2011-10-03 12:36           ` James Courtier-Dutton
  2011-10-03 12:50             ` Antti Palosaari
  1 sibling, 1 reply; 16+ messages in thread
From: James Courtier-Dutton @ 2011-10-03 12:36 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: István Váradi, linux-media

2011/8/29 Antti Palosaari <crope@iki.fi>:
> On 08/29/2011 05:44 PM, István Váradi wrote:
>>
>> Hi,
>>
>> 2011/8/17 Antti Palosaari<crope@iki.fi>:
>>>
>>> On 08/15/2011 02:14 PM, Antti Palosaari wrote:
>>>>
>>>> On 08/15/2011 02:51 AM, Antti Palosaari wrote:
>>>>>
>>>>> Biggest problem I see whole thing is poor application support. OpenCT
>>>>> is
>>>>> rather legacy but there is no good alternative. All this kind of serial
>>>>> drivers seems to be OpenCT currently.
>>>>
>>>> I wonder if it is possible to make virtual CCID device since CCID seems
>>>> to be unfortunately the only interface SmartCard guys currently care.
>>>
>>> I studied scenario and looks like it is possible to implement way like,
>>> register virtual USB HCI (virtual motherboard USB controller) then
>>> register virtual PC/SC device to that which hooks all calls to HW via
>>> Anysee driver. Some glue surely needed for emulate PC/SC. I think there
>>> is not any such driver yet. Anyhow, there is virtual USB HCI driver
>>> currently in staging which can be used as example, or even use it to
>>> register virtual device. That kind of functionality surely needs more
>>> talking...
>>
>> It maybe that smartcard guys care only for CCID, but wouldn't it be an
>> overkill to implement an emulation of that for the driver? It can be
>> done, of course, but I think it would be much more complicated than
>> the current one. Is it really necessary to put such complexity into
>> the kernel? In my opinion, this should be handled in user-space.
>
> Only De facto serial smartcard protocol is so called Phoenix/Smartmouse,
> implementing new protocol is totally dead idea. It will never got any
> support.
>
> There is already such drivers, at least Infinity Unlimited USB Phoenix
> driver (iuu_phoenix.c). It uses USB-serial driver framework and some small
> emulation for Phoenix protocol. Look that driver to see which kind of
> complexity it adds. Anysee have *just* same situation.
>
I helped write the iuu_phoenix.c driver.
With regards to "The character device supports two ioctl's (see
anysee_sc), one for
detecting the presence of a card, the other one for resetting the card
and querying the ATR."
The iuu_phoenix.c driver uses standard phoenix/smartmouse reset and
atr controls. (i.e. with DCD, DTR, RTS, CTS lines etc)
As the result the iuu_phoenix.c driver works out of the box with oscam.
It might be a good idea to use a similar interface for your driver.
The result would be that your driver would work out of the box with
oscam as well as other user space programs that read smart cards.
The problem would be if you wished to support smart card program
capabilities, the Phoenix/Smartmouse interface does not support that.
If I add programmer functionallity to the iuu_phoenix driver, I would
probably add an IOCTL for it.

Kind Regards

James

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Smart card reader support for Anysee DVB devices
  2011-10-03 12:36           ` James Courtier-Dutton
@ 2011-10-03 12:50             ` Antti Palosaari
  0 siblings, 0 replies; 16+ messages in thread
From: Antti Palosaari @ 2011-10-03 12:50 UTC (permalink / raw)
  To: James Courtier-Dutton; +Cc: István Váradi, linux-media

On 10/03/2011 03:36 PM, James Courtier-Dutton wrote:
> 2011/8/29 Antti Palosaari<crope@iki.fi>:
>> Only De facto serial smartcard protocol is so called Phoenix/Smartmouse,
>> implementing new protocol is totally dead idea. It will never got any
>> support.
>>
>> There is already such drivers, at least Infinity Unlimited USB Phoenix
>> driver (iuu_phoenix.c). It uses USB-serial driver framework and some small
>> emulation for Phoenix protocol. Look that driver to see which kind of
>> complexity it adds. Anysee have *just* same situation.
>>
> I helped write the iuu_phoenix.c driver.
> With regards to "The character device supports two ioctl's (see
> anysee_sc), one for
> detecting the presence of a card, the other one for resetting the card
> and querying the ATR."
> The iuu_phoenix.c driver uses standard phoenix/smartmouse reset and
> atr controls. (i.e. with DCD, DTR, RTS, CTS lines etc)
> As the result the iuu_phoenix.c driver works out of the box with oscam.
> It might be a good idea to use a similar interface for your driver.
> The result would be that your driver would work out of the box with
> oscam as well as other user space programs that read smart cards.
> The problem would be if you wished to support smart card program
> capabilities, the Phoenix/Smartmouse interface does not support that.
> If I add programmer functionallity to the iuu_phoenix driver, I would
> probably add an IOCTL for it.

Thank you for the feedback. I already did that. See latest tree:
http://git.linuxtv.org/anttip/media_tree.git/shortlog/refs/heads/anysee

Adding IOCTLs and making new userspace IFD was István idea / propose.

Interface is now de facto standard Phoenix. Unfortunately it is not very 
compatible yet. I used oscam as client during development mainly since 
as a open source it was easy to look and add debugs to see what kind of 
protocol is. Unfortunately I did mistake and removed accidentally my 
original tree and was forced to rewrite it. At that point oscam stopped 
working, but it is surely small bug. I suspect .set_termios() or 
.tiocmget() or .tiocmset().

Currently device name and location are under the discussion. Mainly, 
should that device be under /dev/tty* as other character devices or 
under /dev/dvb/adapterN/ as a property of DVB card.

regards
Antti
-- 
http://palosaari.fi/

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Smart card reader support for Anysee DVB devices
  2011-09-30 15:36                     ` Antti Palosaari
  2011-10-02 21:06                       ` HoP
@ 2011-10-03 17:56                       ` Bjørn Mork
  1 sibling, 0 replies; 16+ messages in thread
From: Bjørn Mork @ 2011-10-03 17:56 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: István Váradi, linux-media

Antti Palosaari <crope@iki.fi> writes:

> If you would like to help me then you can find out correct device name
> and whats needed for that. I mainly see following possibilities;
> * /dev/ttyAnyseeN
> * /dev/ttyDVBN
> * /dev/adapterN/serial

You should probably include the TTY maintainer in that discussion.  I
assume this device won't really be a TTY device?  Then it probably
shouldn't be named like one.


Bjørn

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2011-10-03 17:56 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-17 14:18 Smart card reader support for Anysee DVB devices István Váradi
2011-08-14 23:51 ` Antti Palosaari
2011-08-15 11:14   ` Antti Palosaari
2011-08-17 20:41     ` Antti Palosaari
2011-08-29 14:44       ` István Váradi
2011-08-29 14:50         ` Antti Palosaari
2011-08-29 15:13           ` István Váradi
2011-08-29 15:23             ` Antti Palosaari
2011-09-02 11:04               ` Bjørn Mork
2011-09-02 13:32                 ` Antti Palosaari
2011-09-28 14:32                   ` Antti Palosaari
2011-09-30 15:36                     ` Antti Palosaari
2011-10-02 21:06                       ` HoP
2011-10-03 17:56                       ` Bjørn Mork
2011-10-03 12:36           ` James Courtier-Dutton
2011-10-03 12:50             ` Antti Palosaari

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.