Blame contrib/Kobil_mIDentity_switch/Kobil_mIDentity_switch.c

Packit 9f0df5
/*
Packit 9f0df5
    Activate the smartcard interface on the kobil midentity usb device
Packit 9f0df5
    Copyright (C) 2006  Norbert Federa <norbert.federa@neoware.com>
Packit 9f0df5
Packit 9f0df5
    This program is free software; you can redistribute it and/or
Packit 9f0df5
    modify it under the terms of the GNU Lesser General Public
Packit 9f0df5
    License as published by the Free Software Foundation; either
Packit 9f0df5
    version 2.1 of the License, or (at your option) any later version.
Packit 9f0df5
Packit 9f0df5
    This library is distributed in the hope that it will be useful,
Packit 9f0df5
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 9f0df5
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 9f0df5
    Lesser General Public License for more details.
Packit 9f0df5
Packit 9f0df5
	You should have received a copy of the GNU Lesser General Public License
Packit 9f0df5
	along with this library; if not, write to the Free Software Foundation,
Packit 9f0df5
	Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
Packit 9f0df5
Packit 9f0df5
Author:	Norbert Federa <norbert.federa@neoware.com>
Packit 9f0df5
Date:   2006-04-06
Packit 9f0df5
Packit 9f0df5
Packit 9f0df5
Description:
Packit 9f0df5
Packit 9f0df5
This tool is needed to activate the smartcard interface on the kobil midentity
Packit 9f0df5
usb device (vendor 0x04D6 id 0x4081)
Packit 9f0df5
Packit 9f0df5
Kobil's own implementation was a kernel usb driver which did just send a
Packit 9f0df5
libusb_control_transfer in the probe routine.
Packit 9f0df5
Packit 9f0df5
We do the same via libusb and call this program from our /sbin/hotblug script
Packit 9f0df5
if the mIDentity gets added.
Packit 9f0df5
Packit 9f0df5
The kobil switcher driver was found inside this zip ...
Packit 9f0df5
http://www.kobil.com/download/partner/KOBIL_mIDentity_SDK_Build_20060320_RELEASE.zip
Packit 9f0df5
... under Interfaces/Linux/module_with_binary_final.tar.gz.
Packit 9f0df5
Packit 9f0df5
Here the interesting part of the kernel driver inside the probe function:
Packit 9f0df5
Packit 9f0df5
        if (dev->descriptor.idVendor == KOBIL_VENDOR_ID){
Packit 9f0df5
                printk("!!!!! DEVICE FOUND !!! !\n");
Packit 9f0df5
		ret = libusb_control_transfer(dev,
Packit 9f0df5
		send_pipe,
Packit 9f0df5
		0x09,
Packit 9f0df5
		0x22,
Packit 9f0df5
		0x0200,
Packit 9f0df5
		0x0001,
Packit 9f0df5
		switchCmd,
Packit 9f0df5
		sizeof(switchCmd),
Packit 9f0df5
		5000);
Packit 9f0df5
	}
Packit 9f0df5
Packit 9f0df5
Initally the it did not work with libusb because the ioctl gets ignored with
Packit 9f0df5
the used RequestType of 0x22 in combination with index 0x0001, but index 0x0002
Packit 9f0df5
worked.  See usb/devio.c functions  proc_control() ->  check_ctrlrecip() ->
Packit 9f0df5
findintfep() in order to understand why.
Packit 9f0df5
*/
Packit 9f0df5
Packit 9f0df5
#include <stdio.h>
Packit 9f0df5
#include <string.h>
Packit 9f0df5
#include <unistd.h>
Packit 9f0df5
#include <stdlib.h>
Packit 9f0df5
#include <libusb.h>
Packit 9f0df5
#include <errno.h>
Packit 9f0df5
Packit 9f0df5
#include "config.h"
Packit 9f0df5
Packit 9f0df5
#define KOBIL_VENDOR_ID		0x0D46
Packit 9f0df5
#define MID_DEVICE_ID		0x4081
Packit 9f0df5
#define KOBIL_TIMEOUT		5000
Packit 9f0df5
#define VAL_STARTUP_4080        1
Packit 9f0df5
#define VAL_STARTUP_4000        2
Packit 9f0df5
#define VAL_STARTUP_4020        3
Packit 9f0df5
#define VAL_STARTUP_40A0        4
Packit 9f0df5
#define HIDCMD_SWITCH_DEVICE    0x0004
Packit 9f0df5
Packit 9f0df5
#define bmRequestType           0x22
Packit 9f0df5
#define bRequest                0x09
Packit 9f0df5
#define wValue                  0x0200
Packit 9f0df5
#define wIndex                  0x0002  /* this was originally 0x0001 */
Packit 9f0df5
Packit 9f0df5
Packit 9f0df5
static int kobil_midentity_control_msg(libusb_device_handle *usb)
Packit 9f0df5
{
Packit 9f0df5
	int ret;
Packit 9f0df5
Packit 9f0df5
	unsigned char switchCmd[10];
Packit 9f0df5
Packit 9f0df5
	unsigned char Sleep = 1;
Packit 9f0df5
	unsigned char hardDisk = 1;
Packit 9f0df5
Packit 9f0df5
	unsigned char param = ((hardDisk) << 4) | (Sleep);
Packit 9f0df5
Packit 9f0df5
	memset(switchCmd, 0x0, sizeof(switchCmd));
Packit 9f0df5
	switchCmd[0] = HIDCMD_SWITCH_DEVICE >> 8;
Packit 9f0df5
	switchCmd[1] = HIDCMD_SWITCH_DEVICE;
Packit 9f0df5
	switchCmd[5] = VAL_STARTUP_4000;
Packit 9f0df5
	switchCmd[9] = param;
Packit 9f0df5
Packit 9f0df5
	ret = libusb_control_transfer(usb, bmRequestType, bRequest, wValue, wIndex,
Packit 9f0df5
			switchCmd, sizeof(switchCmd), KOBIL_TIMEOUT);
Packit 9f0df5
Packit 9f0df5
	return(!(ret==sizeof(switchCmd)));
Packit 9f0df5
}
Packit 9f0df5
Packit 9f0df5
Packit 9f0df5
static int kobil_midentity_claim_interface(libusb_device_handle *usb, int ifnum)
Packit 9f0df5
{
Packit 9f0df5
	int rv;
Packit 9f0df5
Packit 9f0df5
	printf("claiming interface #%d ... ", ifnum);
Packit 9f0df5
	rv = libusb_claim_interface(usb, ifnum);
Packit 9f0df5
	if (rv == 0)
Packit 9f0df5
	{
Packit 9f0df5
		printf("success\n");
Packit 9f0df5
		return rv;
Packit 9f0df5
	}
Packit 9f0df5
	else
Packit 9f0df5
		printf("failed\n");
Packit 9f0df5
Packit 9f0df5
	printf("failed with error %d, trying to detach kernel driver ....\n", rv);
Packit 9f0df5
	rv = libusb_detach_kernel_driver(usb, ifnum);
Packit 9f0df5
	if (rv == 0)
Packit 9f0df5
	{
Packit 9f0df5
		printf("success, claiming interface again ...");
Packit 9f0df5
		rv = libusb_claim_interface(usb, ifnum);
Packit 9f0df5
		if (rv == 0)
Packit 9f0df5
		{
Packit 9f0df5
			printf("success\n");
Packit 9f0df5
			return rv;
Packit 9f0df5
		}
Packit 9f0df5
		else
Packit 9f0df5
			printf("failed\n");
Packit 9f0df5
	}
Packit 9f0df5
Packit 9f0df5
	printf("failed with error %d, giving up.\n", rv);
Packit 9f0df5
	return rv;
Packit 9f0df5
}
Packit 9f0df5
Packit 9f0df5
Packit 9f0df5
int main(int argc, char *argv[])
Packit 9f0df5
{
Packit 9f0df5
	libusb_device **devs, *dev;
Packit 9f0df5
	libusb_device *found_dev = NULL;
Packit 9f0df5
	struct libusb_device_handle *usb = NULL;
Packit 9f0df5
	int rv, i;
Packit 9f0df5
	ssize_t cnt;
Packit 9f0df5
Packit 9f0df5
	(void)argc;
Packit 9f0df5
	(void)argv;
Packit 9f0df5
Packit 9f0df5
	rv = libusb_init(NULL);
Packit 9f0df5
	if (rv < 0)
Packit 9f0df5
	{
Packit 9f0df5
		(void)printf("libusb_init() failed\n");
Packit 9f0df5
		return rv;
Packit 9f0df5
	}
Packit 9f0df5
Packit 9f0df5
	cnt = libusb_get_device_list(NULL, &devs);
Packit 9f0df5
	if (cnt < 0)
Packit 9f0df5
	{
Packit 9f0df5
		(void)printf("libusb_get_device_list() failed\n");
Packit 9f0df5
		return (int)cnt;
Packit 9f0df5
	}
Packit 9f0df5
Packit 9f0df5
	/* for every device */
Packit 9f0df5
	i = 0;
Packit 9f0df5
	while ((dev = devs[i++]) != NULL)
Packit 9f0df5
	{
Packit 9f0df5
		struct libusb_device_descriptor desc;
Packit 9f0df5
Packit 9f0df5
		rv = libusb_get_device_descriptor(dev, &desc);
Packit 9f0df5
		if (rv < 0) {
Packit 9f0df5
			(void)printf("failed to get device descriptor\n");
Packit 9f0df5
			continue;
Packit 9f0df5
		}
Packit 9f0df5
Packit 9f0df5
		printf("vendor/product: %04X %04X\n", desc.idVendor, desc.idProduct);
Packit 9f0df5
		if (desc.idVendor == KOBIL_VENDOR_ID && desc.idProduct == MID_DEVICE_ID)
Packit 9f0df5
			found_dev = dev;
Packit 9f0df5
	}
Packit 9f0df5
Packit 9f0df5
	if (found_dev == NULL)
Packit 9f0df5
	{
Packit 9f0df5
		printf("device not found. aborting.\n");
Packit 9f0df5
		if (0 != geteuid())
Packit 9f0df5
			printf("Try to rerun this program as root.\n");
Packit 9f0df5
		exit(1);
Packit 9f0df5
	}
Packit 9f0df5
Packit 9f0df5
	printf("Device found, opening ... ");
Packit 9f0df5
	rv = libusb_open(found_dev, &usb;;
Packit 9f0df5
	if (rv < 0)
Packit 9f0df5
	{
Packit 9f0df5
		printf("failed, aborting.\n");
Packit 9f0df5
		exit(2);
Packit 9f0df5
	}
Packit 9f0df5
	printf("success\n");
Packit 9f0df5
Packit 9f0df5
	rv = kobil_midentity_claim_interface(usb, 0);
Packit 9f0df5
	if (rv < 0)
Packit 9f0df5
	{
Packit 9f0df5
		libusb_close(usb);
Packit 9f0df5
		exit(3);
Packit 9f0df5
	}
Packit 9f0df5
Packit 9f0df5
	rv = kobil_midentity_claim_interface(usb, 1);
Packit 9f0df5
	if (rv < 0)
Packit 9f0df5
	{
Packit 9f0df5
		libusb_close(usb);
Packit 9f0df5
		exit(3);
Packit 9f0df5
	}
Packit 9f0df5
Packit 9f0df5
	printf("Activating the CCID configuration .... ");
Packit 9f0df5
	rv = kobil_midentity_control_msg(usb);
Packit 9f0df5
	if (rv == 0)
Packit 9f0df5
		printf("success\n");
Packit 9f0df5
	else
Packit 9f0df5
		printf("failed with error %d, giving up.\n", rv);
Packit 9f0df5
Packit 9f0df5
	libusb_close(usb);
Packit 9f0df5
Packit 9f0df5
	return 0;
Packit 9f0df5
}
Packit 9f0df5