1/* 2 Activate the smartcard interface on the kobil midentity usb device 3 Copyright (C) 2006 Norbert Federa <norbert.federa@neoware.com> 4 5 This program is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public License 16 along with this library; if not, write to the Free Software Foundation, 17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 19Author: Norbert Federa <norbert.federa@neoware.com> 20Date: 2006-04-06 21 22 23Description: 24 25This tool is needed to activate the smartcard interface on the kobil midentity 26usb device (vendor 0x04D6 id 0x4081) 27 28Kobil's own implementation was a kernel usb driver which did just send a 29usb_control_msg in the probe routine. 30 31We do the same via libusb and call this program from our /sbin/hotblug script 32if the mIDentity gets added. 33 34The kobil switcher driver was found inside this zip ... 35http://www.kobil.com/download/partner/KOBIL_mIDentity_SDK_Build_20060320_RELEASE.zip 36... under Interfaces/Linux/module_with_binary_final.tar.gz. 37 38Here the interesting part of the kernel driver inside the probe function: 39 40 if (dev->descriptor.idVendor == KOBIL_VENDOR_ID){ 41 printk("!!!!! DEVICE FOUND !!! !\n"); 42 ret = usb_control_msg(dev, 43 send_pipe, 44 0x09, 45 0x22, 46 0x0200, 47 0x0001, 48 switchCmd, 49 sizeof(switchCmd), 50 5000); 51 } 52 53Initally the it did not work with libusb because the ioctl gets ignored with 54the used RequestType of 0x22 in combination with index 0x0001, but index 0x0002 55worked. See usb/devio.c functions proc_control() -> check_ctrlrecip() -> 56findintfep() in order to understand why. 57*/ 58 59#include <stdio.h> 60#include <string.h> 61#include <usb.h> 62#include <errno.h> 63 64#include "config.h" 65 66#define KOBIL_VENDOR_ID 0x0D46 67#define MID_DEVICE_ID 0x4081 68#define KOBIL_TIMEOUT 5000 69#define VAL_STARTUP_4080 1 70#define VAL_STARTUP_4000 2 71#define VAL_STARTUP_4020 3 72#define VAL_STARTUP_40A0 4 73#define HIDCMD_SWITCH_DEVICE 0x0004 74 75#define bmRequestType 0x22 76#define bRequest 0x09 77#define wValue 0x0200 78#define wIndex 0x0002 /* this was originally 0x0001 */ 79 80 81static int kobil_midentity_control_msg(usb_dev_handle *usb) 82{ 83 int ret; 84 85 char switchCmd[10]; 86 87 unsigned char Sleep = 1; 88 unsigned char hardDisk = 1; 89 90 unsigned char param = ((hardDisk)<<4) | (Sleep); 91 92 memset(switchCmd, 0x0, sizeof(switchCmd)); 93 switchCmd[0] = HIDCMD_SWITCH_DEVICE>>8; 94 switchCmd[1] = HIDCMD_SWITCH_DEVICE; 95 switchCmd[5] = VAL_STARTUP_4000; 96 switchCmd[9] = param; 97 98 ret = usb_control_msg(usb, bmRequestType, bRequest, wValue, wIndex, 99 switchCmd, sizeof(switchCmd), KOBIL_TIMEOUT); 100 101 return(!(ret==sizeof(switchCmd))); 102} 103 104 105static int kobil_midentity_claim_interface(usb_dev_handle *usb, int ifnum) 106{ 107 int rv; 108 109 printf("claiming interface #%d ...\n", ifnum); 110 rv = usb_claim_interface(usb, ifnum); 111 if (rv == 0) 112 { 113 printf("success\n"); 114 return(rv); 115 } 116 117#ifdef HAVE_USB_DETACH_KERNEL_DRIVER_NP 118 printf("failed with error %d, trying to detach kernel driver ....\n", rv); 119 rv = usb_detach_kernel_driver_np(usb, ifnum); 120 if (rv == 0) 121 { 122 printf("success, claiming interface again ..."); 123 rv = usb_claim_interface(usb, ifnum); 124 if (rv == 0) 125 { 126 printf("success\n"); 127 return(rv); 128 } 129 } 130#endif 131 printf("failed with error %d, giving up.\n", rv); 132 return(rv); 133} 134 135 136int main(int argc, char *argv[]) 137{ 138 struct usb_bus *bus; 139 struct usb_device *dev = NULL; 140 struct usb_device *found_dev = NULL; 141 usb_dev_handle *usb = NULL; 142 int rv; 143 144 usb_init(); 145 146 usb_find_busses(); 147 usb_find_devices(); 148 149 for (bus = usb_busses; bus; bus = bus->next) 150 { 151 for (dev = bus->devices; dev; dev = dev->next) 152 { 153 printf("vendor/product: %04X %04X\n", 154 dev->descriptor.idVendor, dev->descriptor.idProduct); 155 if (dev->descriptor.idVendor == KOBIL_VENDOR_ID 156 && dev->descriptor.idProduct ==MID_DEVICE_ID) 157 { 158 found_dev = dev; 159 } 160 } 161 } 162 163 if (found_dev == NULL) 164 { 165 printf("device not found. aborting.\n"); 166 if (0 != geteuid()) 167 printf("Try to rerun this program as root.\n"); 168 exit(1); 169 } 170 171 printf("Device found, opening ... "); 172 usb = usb_open(found_dev); 173 if (!usb) 174 { 175 printf("failed, aborting.\n"); 176 exit(2); 177 } 178 printf("success\n"); 179 180 rv = kobil_midentity_claim_interface(usb, 0); 181 if (rv < 0) 182 { 183 usb_close(usb); 184 exit(3); 185 } 186 rv = kobil_midentity_claim_interface(usb, 1); 187 if (rv < 0) 188 { 189 usb_close(usb); 190 exit(3); 191 } 192 193 printf("Activating the CCID configuration .... "); 194 rv = kobil_midentity_control_msg(usb); 195 if (rv == 0) 196 printf("success\n"); 197 else 198 printf("failed with error %d, giving up.\n", rv); 199 200 usb_close(usb); 201 202 return 0; 203} 204 205