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