Smart card reader support for Anysee DVB devices

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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: patch
Description: Binary data

#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
#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);
}

[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux