1*c04148f9SAlfred E. Heggestad /* 2*c04148f9SAlfred E. Heggestad * Driver for the VoIP USB phones with CM109 chipsets. 3*c04148f9SAlfred E. Heggestad * 4*c04148f9SAlfred E. Heggestad * Copyright (C) 2007 - 2008 Alfred E. Heggestad <aeh@db.org> 5*c04148f9SAlfred E. Heggestad * 6*c04148f9SAlfred E. Heggestad * This program is free software; you can redistribute it and/or 7*c04148f9SAlfred E. Heggestad * modify it under the terms of the GNU General Public License as 8*c04148f9SAlfred E. Heggestad * published by the Free Software Foundation, version 2. 9*c04148f9SAlfred E. Heggestad */ 10*c04148f9SAlfred E. Heggestad 11*c04148f9SAlfred E. Heggestad /* 12*c04148f9SAlfred E. Heggestad * Tested devices: 13*c04148f9SAlfred E. Heggestad * - Komunikate KIP1000 14*c04148f9SAlfred E. Heggestad * - Genius G-talk 15*c04148f9SAlfred E. Heggestad * - Allied-Telesis Corega USBPH01 16*c04148f9SAlfred E. Heggestad * - ... 17*c04148f9SAlfred E. Heggestad * 18*c04148f9SAlfred E. Heggestad * This driver is based on the yealink.c driver 19*c04148f9SAlfred E. Heggestad * 20*c04148f9SAlfred E. Heggestad * Thanks to: 21*c04148f9SAlfred E. Heggestad * - Authors of yealink.c 22*c04148f9SAlfred E. Heggestad * - Thomas Reitmayr 23*c04148f9SAlfred E. Heggestad * - Oliver Neukum for good review comments and code 24*c04148f9SAlfred E. Heggestad * - Shaun Jackman <sjackman@gmail.com> for Genius G-talk keymap 25*c04148f9SAlfred E. Heggestad * - Dmitry Torokhov for valuable input and review 26*c04148f9SAlfred E. Heggestad * 27*c04148f9SAlfred E. Heggestad * Todo: 28*c04148f9SAlfred E. Heggestad * - Read/write EEPROM 29*c04148f9SAlfred E. Heggestad */ 30*c04148f9SAlfred E. Heggestad 31*c04148f9SAlfred E. Heggestad #include <linux/kernel.h> 32*c04148f9SAlfred E. Heggestad #include <linux/init.h> 33*c04148f9SAlfred E. Heggestad #include <linux/slab.h> 34*c04148f9SAlfred E. Heggestad #include <linux/module.h> 35*c04148f9SAlfred E. Heggestad #include <linux/moduleparam.h> 36*c04148f9SAlfred E. Heggestad #include <linux/rwsem.h> 37*c04148f9SAlfred E. Heggestad #include <linux/usb/input.h> 38*c04148f9SAlfred E. Heggestad 39*c04148f9SAlfred E. Heggestad #define CM109_DEBUG 0 40*c04148f9SAlfred E. Heggestad 41*c04148f9SAlfred E. Heggestad #define DRIVER_VERSION "20080805" 42*c04148f9SAlfred E. Heggestad #define DRIVER_AUTHOR "Alfred E. Heggestad" 43*c04148f9SAlfred E. Heggestad #define DRIVER_DESC "CM109 phone driver" 44*c04148f9SAlfred E. Heggestad 45*c04148f9SAlfred E. Heggestad static char *phone = "kip1000"; 46*c04148f9SAlfred E. Heggestad module_param(phone, charp, S_IRUSR); 47*c04148f9SAlfred E. Heggestad MODULE_PARM_DESC(phone, "Phone name {kip1000, gtalk, usbph01}"); 48*c04148f9SAlfred E. Heggestad 49*c04148f9SAlfred E. Heggestad enum { 50*c04148f9SAlfred E. Heggestad /* HID Registers */ 51*c04148f9SAlfred E. Heggestad HID_IR0 = 0x00, /* Record/Playback-mute button, Volume up/down */ 52*c04148f9SAlfred E. Heggestad HID_IR1 = 0x01, /* GPI, generic registers or EEPROM_DATA0 */ 53*c04148f9SAlfred E. Heggestad HID_IR2 = 0x02, /* Generic registers or EEPROM_DATA1 */ 54*c04148f9SAlfred E. Heggestad HID_IR3 = 0x03, /* Generic registers or EEPROM_CTRL */ 55*c04148f9SAlfred E. Heggestad HID_OR0 = 0x00, /* Mapping control, buzzer, SPDIF (offset 0x04) */ 56*c04148f9SAlfred E. Heggestad HID_OR1 = 0x01, /* GPO - General Purpose Output */ 57*c04148f9SAlfred E. Heggestad HID_OR2 = 0x02, /* Set GPIO to input/output mode */ 58*c04148f9SAlfred E. Heggestad HID_OR3 = 0x03, /* SPDIF status channel or EEPROM_CTRL */ 59*c04148f9SAlfred E. Heggestad 60*c04148f9SAlfred E. Heggestad /* HID_IR0 */ 61*c04148f9SAlfred E. Heggestad RECORD_MUTE = 1 << 3, 62*c04148f9SAlfred E. Heggestad PLAYBACK_MUTE = 1 << 2, 63*c04148f9SAlfred E. Heggestad VOLUME_DOWN = 1 << 1, 64*c04148f9SAlfred E. Heggestad VOLUME_UP = 1 << 0, 65*c04148f9SAlfred E. Heggestad 66*c04148f9SAlfred E. Heggestad /* HID_OR0 */ 67*c04148f9SAlfred E. Heggestad /* bits 7-6 68*c04148f9SAlfred E. Heggestad 0: HID_OR1-2 are used for GPO; HID_OR0, 3 are used for buzzer 69*c04148f9SAlfred E. Heggestad and SPDIF 70*c04148f9SAlfred E. Heggestad 1: HID_OR0-3 are used as generic HID registers 71*c04148f9SAlfred E. Heggestad 2: Values written to HID_OR0-3 are also mapped to MCU_CTRL, 72*c04148f9SAlfred E. Heggestad EEPROM_DATA0-1, EEPROM_CTRL (see Note) 73*c04148f9SAlfred E. Heggestad 3: Reserved 74*c04148f9SAlfred E. Heggestad */ 75*c04148f9SAlfred E. Heggestad HID_OR_GPO_BUZ_SPDIF = 0 << 6, 76*c04148f9SAlfred E. Heggestad HID_OR_GENERIC_HID_REG = 1 << 6, 77*c04148f9SAlfred E. Heggestad HID_OR_MAP_MCU_EEPROM = 2 << 6, 78*c04148f9SAlfred E. Heggestad 79*c04148f9SAlfred E. Heggestad BUZZER_ON = 1 << 5, 80*c04148f9SAlfred E. Heggestad 81*c04148f9SAlfred E. Heggestad /* up to 256 normal keys, up to 16 special keys */ 82*c04148f9SAlfred E. Heggestad KEYMAP_SIZE = 256 + 16, 83*c04148f9SAlfred E. Heggestad }; 84*c04148f9SAlfred E. Heggestad 85*c04148f9SAlfred E. Heggestad /* CM109 protocol packet */ 86*c04148f9SAlfred E. Heggestad struct cm109_ctl_packet { 87*c04148f9SAlfred E. Heggestad u8 byte[4]; 88*c04148f9SAlfred E. Heggestad } __attribute__ ((packed)); 89*c04148f9SAlfred E. Heggestad 90*c04148f9SAlfred E. Heggestad enum { USB_PKT_LEN = sizeof(struct cm109_ctl_packet) }; 91*c04148f9SAlfred E. Heggestad 92*c04148f9SAlfred E. Heggestad /* CM109 device structure */ 93*c04148f9SAlfred E. Heggestad struct cm109_dev { 94*c04148f9SAlfred E. Heggestad struct input_dev *idev; /* input device */ 95*c04148f9SAlfred E. Heggestad struct usb_device *udev; /* usb device */ 96*c04148f9SAlfred E. Heggestad struct usb_interface *intf; 97*c04148f9SAlfred E. Heggestad 98*c04148f9SAlfred E. Heggestad /* irq input channel */ 99*c04148f9SAlfred E. Heggestad struct cm109_ctl_packet *irq_data; 100*c04148f9SAlfred E. Heggestad dma_addr_t irq_dma; 101*c04148f9SAlfred E. Heggestad struct urb *urb_irq; 102*c04148f9SAlfred E. Heggestad 103*c04148f9SAlfred E. Heggestad /* control output channel */ 104*c04148f9SAlfred E. Heggestad struct cm109_ctl_packet *ctl_data; 105*c04148f9SAlfred E. Heggestad dma_addr_t ctl_dma; 106*c04148f9SAlfred E. Heggestad struct usb_ctrlrequest *ctl_req; 107*c04148f9SAlfred E. Heggestad dma_addr_t ctl_req_dma; 108*c04148f9SAlfred E. Heggestad struct urb *urb_ctl; 109*c04148f9SAlfred E. Heggestad /* 110*c04148f9SAlfred E. Heggestad * The 3 bitfields below are protected by ctl_submit_lock. 111*c04148f9SAlfred E. Heggestad * They have to be separate since they are accessed from IRQ 112*c04148f9SAlfred E. Heggestad * context. 113*c04148f9SAlfred E. Heggestad */ 114*c04148f9SAlfred E. Heggestad unsigned irq_urb_pending:1; /* irq_urb is in flight */ 115*c04148f9SAlfred E. Heggestad unsigned ctl_urb_pending:1; /* ctl_urb is in flight */ 116*c04148f9SAlfred E. Heggestad unsigned buzzer_pending:1; /* need to issue buzz command */ 117*c04148f9SAlfred E. Heggestad spinlock_t ctl_submit_lock; 118*c04148f9SAlfred E. Heggestad 119*c04148f9SAlfred E. Heggestad unsigned char buzzer_state; /* on/off */ 120*c04148f9SAlfred E. Heggestad 121*c04148f9SAlfred E. Heggestad /* flags */ 122*c04148f9SAlfred E. Heggestad unsigned open:1; 123*c04148f9SAlfred E. Heggestad unsigned resetting:1; 124*c04148f9SAlfred E. Heggestad unsigned shutdown:1; 125*c04148f9SAlfred E. Heggestad 126*c04148f9SAlfred E. Heggestad /* This mutex protects writes to the above flags */ 127*c04148f9SAlfred E. Heggestad struct mutex pm_mutex; 128*c04148f9SAlfred E. Heggestad 129*c04148f9SAlfred E. Heggestad unsigned short keymap[KEYMAP_SIZE]; 130*c04148f9SAlfred E. Heggestad 131*c04148f9SAlfred E. Heggestad char phys[64]; /* physical device path */ 132*c04148f9SAlfred E. Heggestad int key_code; /* last reported key */ 133*c04148f9SAlfred E. Heggestad int keybit; /* 0=new scan 1,2,4,8=scan columns */ 134*c04148f9SAlfred E. Heggestad u8 gpi; /* Cached value of GPI (high nibble) */ 135*c04148f9SAlfred E. Heggestad }; 136*c04148f9SAlfred E. Heggestad 137*c04148f9SAlfred E. Heggestad /****************************************************************************** 138*c04148f9SAlfred E. Heggestad * CM109 key interface 139*c04148f9SAlfred E. Heggestad *****************************************************************************/ 140*c04148f9SAlfred E. Heggestad 141*c04148f9SAlfred E. Heggestad static unsigned short special_keymap(int code) 142*c04148f9SAlfred E. Heggestad { 143*c04148f9SAlfred E. Heggestad if (code > 0xff) { 144*c04148f9SAlfred E. Heggestad switch (code - 0xff) { 145*c04148f9SAlfred E. Heggestad case RECORD_MUTE: return KEY_MUTE; 146*c04148f9SAlfred E. Heggestad case PLAYBACK_MUTE: return KEY_MUTE; 147*c04148f9SAlfred E. Heggestad case VOLUME_DOWN: return KEY_VOLUMEDOWN; 148*c04148f9SAlfred E. Heggestad case VOLUME_UP: return KEY_VOLUMEUP; 149*c04148f9SAlfred E. Heggestad } 150*c04148f9SAlfred E. Heggestad } 151*c04148f9SAlfred E. Heggestad return KEY_RESERVED; 152*c04148f9SAlfred E. Heggestad } 153*c04148f9SAlfred E. Heggestad 154*c04148f9SAlfred E. Heggestad /* Map device buttons to internal key events. 155*c04148f9SAlfred E. Heggestad * 156*c04148f9SAlfred E. Heggestad * The "up" and "down" keys, are symbolised by arrows on the button. 157*c04148f9SAlfred E. Heggestad * The "pickup" and "hangup" keys are symbolised by a green and red phone 158*c04148f9SAlfred E. Heggestad * on the button. 159*c04148f9SAlfred E. Heggestad 160*c04148f9SAlfred E. Heggestad Komunikate KIP1000 Keyboard Matrix 161*c04148f9SAlfred E. Heggestad 162*c04148f9SAlfred E. Heggestad -> -- 1 -- 2 -- 3 --> GPI pin 4 (0x10) 163*c04148f9SAlfred E. Heggestad | | | | 164*c04148f9SAlfred E. Heggestad <- -- 4 -- 5 -- 6 --> GPI pin 5 (0x20) 165*c04148f9SAlfred E. Heggestad | | | | 166*c04148f9SAlfred E. Heggestad END - 7 -- 8 -- 9 --> GPI pin 6 (0x40) 167*c04148f9SAlfred E. Heggestad | | | | 168*c04148f9SAlfred E. Heggestad OK -- * -- 0 -- # --> GPI pin 7 (0x80) 169*c04148f9SAlfred E. Heggestad | | | | 170*c04148f9SAlfred E. Heggestad 171*c04148f9SAlfred E. Heggestad /|\ /|\ /|\ /|\ 172*c04148f9SAlfred E. Heggestad | | | | 173*c04148f9SAlfred E. Heggestad GPO 174*c04148f9SAlfred E. Heggestad pin: 3 2 1 0 175*c04148f9SAlfred E. Heggestad 0x8 0x4 0x2 0x1 176*c04148f9SAlfred E. Heggestad 177*c04148f9SAlfred E. Heggestad */ 178*c04148f9SAlfred E. Heggestad static unsigned short keymap_kip1000(int scancode) 179*c04148f9SAlfred E. Heggestad { 180*c04148f9SAlfred E. Heggestad switch (scancode) { /* phone key: */ 181*c04148f9SAlfred E. Heggestad case 0x82: return KEY_NUMERIC_0; /* 0 */ 182*c04148f9SAlfred E. Heggestad case 0x14: return KEY_NUMERIC_1; /* 1 */ 183*c04148f9SAlfred E. Heggestad case 0x12: return KEY_NUMERIC_2; /* 2 */ 184*c04148f9SAlfred E. Heggestad case 0x11: return KEY_NUMERIC_3; /* 3 */ 185*c04148f9SAlfred E. Heggestad case 0x24: return KEY_NUMERIC_4; /* 4 */ 186*c04148f9SAlfred E. Heggestad case 0x22: return KEY_NUMERIC_5; /* 5 */ 187*c04148f9SAlfred E. Heggestad case 0x21: return KEY_NUMERIC_6; /* 6 */ 188*c04148f9SAlfred E. Heggestad case 0x44: return KEY_NUMERIC_7; /* 7 */ 189*c04148f9SAlfred E. Heggestad case 0x42: return KEY_NUMERIC_8; /* 8 */ 190*c04148f9SAlfred E. Heggestad case 0x41: return KEY_NUMERIC_9; /* 9 */ 191*c04148f9SAlfred E. Heggestad case 0x81: return KEY_NUMERIC_POUND; /* # */ 192*c04148f9SAlfred E. Heggestad case 0x84: return KEY_NUMERIC_STAR; /* * */ 193*c04148f9SAlfred E. Heggestad case 0x88: return KEY_ENTER; /* pickup */ 194*c04148f9SAlfred E. Heggestad case 0x48: return KEY_ESC; /* hangup */ 195*c04148f9SAlfred E. Heggestad case 0x28: return KEY_LEFT; /* IN */ 196*c04148f9SAlfred E. Heggestad case 0x18: return KEY_RIGHT; /* OUT */ 197*c04148f9SAlfred E. Heggestad default: return special_keymap(scancode); 198*c04148f9SAlfred E. Heggestad } 199*c04148f9SAlfred E. Heggestad } 200*c04148f9SAlfred E. Heggestad 201*c04148f9SAlfred E. Heggestad /* 202*c04148f9SAlfred E. Heggestad Contributed by Shaun Jackman <sjackman@gmail.com> 203*c04148f9SAlfred E. Heggestad 204*c04148f9SAlfred E. Heggestad Genius G-Talk keyboard matrix 205*c04148f9SAlfred E. Heggestad 0 1 2 3 206*c04148f9SAlfred E. Heggestad 4: 0 4 8 Talk 207*c04148f9SAlfred E. Heggestad 5: 1 5 9 End 208*c04148f9SAlfred E. Heggestad 6: 2 6 # Up 209*c04148f9SAlfred E. Heggestad 7: 3 7 * Down 210*c04148f9SAlfred E. Heggestad */ 211*c04148f9SAlfred E. Heggestad static unsigned short keymap_gtalk(int scancode) 212*c04148f9SAlfred E. Heggestad { 213*c04148f9SAlfred E. Heggestad switch (scancode) { 214*c04148f9SAlfred E. Heggestad case 0x11: return KEY_NUMERIC_0; 215*c04148f9SAlfred E. Heggestad case 0x21: return KEY_NUMERIC_1; 216*c04148f9SAlfred E. Heggestad case 0x41: return KEY_NUMERIC_2; 217*c04148f9SAlfred E. Heggestad case 0x81: return KEY_NUMERIC_3; 218*c04148f9SAlfred E. Heggestad case 0x12: return KEY_NUMERIC_4; 219*c04148f9SAlfred E. Heggestad case 0x22: return KEY_NUMERIC_5; 220*c04148f9SAlfred E. Heggestad case 0x42: return KEY_NUMERIC_6; 221*c04148f9SAlfred E. Heggestad case 0x82: return KEY_NUMERIC_7; 222*c04148f9SAlfred E. Heggestad case 0x14: return KEY_NUMERIC_8; 223*c04148f9SAlfred E. Heggestad case 0x24: return KEY_NUMERIC_9; 224*c04148f9SAlfred E. Heggestad case 0x44: return KEY_NUMERIC_POUND; /* # */ 225*c04148f9SAlfred E. Heggestad case 0x84: return KEY_NUMERIC_STAR; /* * */ 226*c04148f9SAlfred E. Heggestad case 0x18: return KEY_ENTER; /* Talk (green handset) */ 227*c04148f9SAlfred E. Heggestad case 0x28: return KEY_ESC; /* End (red handset) */ 228*c04148f9SAlfred E. Heggestad case 0x48: return KEY_UP; /* Menu up (rocker switch) */ 229*c04148f9SAlfred E. Heggestad case 0x88: return KEY_DOWN; /* Menu down (rocker switch) */ 230*c04148f9SAlfred E. Heggestad default: return special_keymap(scancode); 231*c04148f9SAlfred E. Heggestad } 232*c04148f9SAlfred E. Heggestad } 233*c04148f9SAlfred E. Heggestad 234*c04148f9SAlfred E. Heggestad /* 235*c04148f9SAlfred E. Heggestad * Keymap for Allied-Telesis Corega USBPH01 236*c04148f9SAlfred E. Heggestad * http://www.alliedtelesis-corega.com/2/1344/1437/1360/chprd.html 237*c04148f9SAlfred E. Heggestad * 238*c04148f9SAlfred E. Heggestad * Contributed by july@nat.bg 239*c04148f9SAlfred E. Heggestad */ 240*c04148f9SAlfred E. Heggestad static unsigned short keymap_usbph01(int scancode) 241*c04148f9SAlfred E. Heggestad { 242*c04148f9SAlfred E. Heggestad switch (scancode) { 243*c04148f9SAlfred E. Heggestad case 0x11: return KEY_NUMERIC_0; /* 0 */ 244*c04148f9SAlfred E. Heggestad case 0x21: return KEY_NUMERIC_1; /* 1 */ 245*c04148f9SAlfred E. Heggestad case 0x41: return KEY_NUMERIC_2; /* 2 */ 246*c04148f9SAlfred E. Heggestad case 0x81: return KEY_NUMERIC_3; /* 3 */ 247*c04148f9SAlfred E. Heggestad case 0x12: return KEY_NUMERIC_4; /* 4 */ 248*c04148f9SAlfred E. Heggestad case 0x22: return KEY_NUMERIC_5; /* 5 */ 249*c04148f9SAlfred E. Heggestad case 0x42: return KEY_NUMERIC_6; /* 6 */ 250*c04148f9SAlfred E. Heggestad case 0x82: return KEY_NUMERIC_7; /* 7 */ 251*c04148f9SAlfred E. Heggestad case 0x14: return KEY_NUMERIC_8; /* 8 */ 252*c04148f9SAlfred E. Heggestad case 0x24: return KEY_NUMERIC_9; /* 9 */ 253*c04148f9SAlfred E. Heggestad case 0x44: return KEY_NUMERIC_POUND; /* # */ 254*c04148f9SAlfred E. Heggestad case 0x84: return KEY_NUMERIC_STAR; /* * */ 255*c04148f9SAlfred E. Heggestad case 0x18: return KEY_ENTER; /* pickup */ 256*c04148f9SAlfred E. Heggestad case 0x28: return KEY_ESC; /* hangup */ 257*c04148f9SAlfred E. Heggestad case 0x48: return KEY_LEFT; /* IN */ 258*c04148f9SAlfred E. Heggestad case 0x88: return KEY_RIGHT; /* OUT */ 259*c04148f9SAlfred E. Heggestad default: return special_keymap(scancode); 260*c04148f9SAlfred E. Heggestad } 261*c04148f9SAlfred E. Heggestad } 262*c04148f9SAlfred E. Heggestad 263*c04148f9SAlfred E. Heggestad static unsigned short (*keymap)(int) = keymap_kip1000; 264*c04148f9SAlfred E. Heggestad 265*c04148f9SAlfred E. Heggestad /* 266*c04148f9SAlfred E. Heggestad * Completes a request by converting the data into events for the 267*c04148f9SAlfred E. Heggestad * input subsystem. 268*c04148f9SAlfred E. Heggestad */ 269*c04148f9SAlfred E. Heggestad static void report_key(struct cm109_dev *dev, int key) 270*c04148f9SAlfred E. Heggestad { 271*c04148f9SAlfred E. Heggestad struct input_dev *idev = dev->idev; 272*c04148f9SAlfred E. Heggestad 273*c04148f9SAlfred E. Heggestad if (dev->key_code >= 0) { 274*c04148f9SAlfred E. Heggestad /* old key up */ 275*c04148f9SAlfred E. Heggestad input_report_key(idev, dev->key_code, 0); 276*c04148f9SAlfred E. Heggestad } 277*c04148f9SAlfred E. Heggestad 278*c04148f9SAlfred E. Heggestad dev->key_code = key; 279*c04148f9SAlfred E. Heggestad if (key >= 0) { 280*c04148f9SAlfred E. Heggestad /* new valid key */ 281*c04148f9SAlfred E. Heggestad input_report_key(idev, key, 1); 282*c04148f9SAlfred E. Heggestad } 283*c04148f9SAlfred E. Heggestad 284*c04148f9SAlfred E. Heggestad input_sync(idev); 285*c04148f9SAlfred E. Heggestad } 286*c04148f9SAlfred E. Heggestad 287*c04148f9SAlfred E. Heggestad /****************************************************************************** 288*c04148f9SAlfred E. Heggestad * CM109 usb communication interface 289*c04148f9SAlfred E. Heggestad *****************************************************************************/ 290*c04148f9SAlfred E. Heggestad 291*c04148f9SAlfred E. Heggestad static void cm109_submit_buzz_toggle(struct cm109_dev *dev) 292*c04148f9SAlfred E. Heggestad { 293*c04148f9SAlfred E. Heggestad int error; 294*c04148f9SAlfred E. Heggestad 295*c04148f9SAlfred E. Heggestad if (dev->buzzer_state) 296*c04148f9SAlfred E. Heggestad dev->ctl_data->byte[HID_OR0] |= BUZZER_ON; 297*c04148f9SAlfred E. Heggestad else 298*c04148f9SAlfred E. Heggestad dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON; 299*c04148f9SAlfred E. Heggestad 300*c04148f9SAlfred E. Heggestad error = usb_submit_urb(dev->urb_ctl, GFP_ATOMIC); 301*c04148f9SAlfred E. Heggestad if (error) 302*c04148f9SAlfred E. Heggestad err("%s: usb_submit_urb (urb_ctl) failed %d", __func__, error); 303*c04148f9SAlfred E. Heggestad } 304*c04148f9SAlfred E. Heggestad 305*c04148f9SAlfred E. Heggestad /* 306*c04148f9SAlfred E. Heggestad * IRQ handler 307*c04148f9SAlfred E. Heggestad */ 308*c04148f9SAlfred E. Heggestad static void cm109_urb_irq_callback(struct urb *urb) 309*c04148f9SAlfred E. Heggestad { 310*c04148f9SAlfred E. Heggestad struct cm109_dev *dev = urb->context; 311*c04148f9SAlfred E. Heggestad const int status = urb->status; 312*c04148f9SAlfred E. Heggestad int error; 313*c04148f9SAlfred E. Heggestad 314*c04148f9SAlfred E. Heggestad #if CM109_DEBUG 315*c04148f9SAlfred E. Heggestad info("### URB IRQ: [0x%02x 0x%02x 0x%02x 0x%02x] keybit=0x%02x", 316*c04148f9SAlfred E. Heggestad dev->irq_data->byte[0], 317*c04148f9SAlfred E. Heggestad dev->irq_data->byte[1], 318*c04148f9SAlfred E. Heggestad dev->irq_data->byte[2], 319*c04148f9SAlfred E. Heggestad dev->irq_data->byte[3], 320*c04148f9SAlfred E. Heggestad dev->keybit); 321*c04148f9SAlfred E. Heggestad #endif 322*c04148f9SAlfred E. Heggestad 323*c04148f9SAlfred E. Heggestad if (status) { 324*c04148f9SAlfred E. Heggestad if (status == -ESHUTDOWN) 325*c04148f9SAlfred E. Heggestad return; 326*c04148f9SAlfred E. Heggestad err("%s: urb status %d", __func__, status); 327*c04148f9SAlfred E. Heggestad } 328*c04148f9SAlfred E. Heggestad 329*c04148f9SAlfred E. Heggestad /* Special keys */ 330*c04148f9SAlfred E. Heggestad if (dev->irq_data->byte[HID_IR0] & 0x0f) { 331*c04148f9SAlfred E. Heggestad const int code = (dev->irq_data->byte[HID_IR0] & 0x0f); 332*c04148f9SAlfred E. Heggestad report_key(dev, dev->keymap[0xff + code]); 333*c04148f9SAlfred E. Heggestad } 334*c04148f9SAlfred E. Heggestad 335*c04148f9SAlfred E. Heggestad /* Scan key column */ 336*c04148f9SAlfred E. Heggestad if (dev->keybit == 0xf) { 337*c04148f9SAlfred E. Heggestad 338*c04148f9SAlfred E. Heggestad /* Any changes ? */ 339*c04148f9SAlfred E. Heggestad if ((dev->gpi & 0xf0) == (dev->irq_data->byte[HID_IR1] & 0xf0)) 340*c04148f9SAlfred E. Heggestad goto out; 341*c04148f9SAlfred E. Heggestad 342*c04148f9SAlfred E. Heggestad dev->gpi = dev->irq_data->byte[HID_IR1] & 0xf0; 343*c04148f9SAlfred E. Heggestad dev->keybit = 0x1; 344*c04148f9SAlfred E. Heggestad } else { 345*c04148f9SAlfred E. Heggestad report_key(dev, dev->keymap[dev->irq_data->byte[HID_IR1]]); 346*c04148f9SAlfred E. Heggestad 347*c04148f9SAlfred E. Heggestad dev->keybit <<= 1; 348*c04148f9SAlfred E. Heggestad if (dev->keybit > 0x8) 349*c04148f9SAlfred E. Heggestad dev->keybit = 0xf; 350*c04148f9SAlfred E. Heggestad } 351*c04148f9SAlfred E. Heggestad 352*c04148f9SAlfred E. Heggestad out: 353*c04148f9SAlfred E. Heggestad 354*c04148f9SAlfred E. Heggestad spin_lock(&dev->ctl_submit_lock); 355*c04148f9SAlfred E. Heggestad 356*c04148f9SAlfred E. Heggestad dev->irq_urb_pending = 0; 357*c04148f9SAlfred E. Heggestad 358*c04148f9SAlfred E. Heggestad if (likely(!dev->shutdown)) { 359*c04148f9SAlfred E. Heggestad 360*c04148f9SAlfred E. Heggestad if (dev->buzzer_state) 361*c04148f9SAlfred E. Heggestad dev->ctl_data->byte[HID_OR0] |= BUZZER_ON; 362*c04148f9SAlfred E. Heggestad else 363*c04148f9SAlfred E. Heggestad dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON; 364*c04148f9SAlfred E. Heggestad 365*c04148f9SAlfred E. Heggestad dev->ctl_data->byte[HID_OR1] = dev->keybit; 366*c04148f9SAlfred E. Heggestad dev->ctl_data->byte[HID_OR2] = dev->keybit; 367*c04148f9SAlfred E. Heggestad 368*c04148f9SAlfred E. Heggestad dev->buzzer_pending = 0; 369*c04148f9SAlfred E. Heggestad dev->ctl_urb_pending = 1; 370*c04148f9SAlfred E. Heggestad 371*c04148f9SAlfred E. Heggestad error = usb_submit_urb(dev->urb_ctl, GFP_ATOMIC); 372*c04148f9SAlfred E. Heggestad if (error) 373*c04148f9SAlfred E. Heggestad err("%s: usb_submit_urb (urb_ctl) failed %d", 374*c04148f9SAlfred E. Heggestad __func__, error); 375*c04148f9SAlfred E. Heggestad } 376*c04148f9SAlfred E. Heggestad 377*c04148f9SAlfred E. Heggestad spin_unlock(&dev->ctl_submit_lock); 378*c04148f9SAlfred E. Heggestad } 379*c04148f9SAlfred E. Heggestad 380*c04148f9SAlfred E. Heggestad static void cm109_urb_ctl_callback(struct urb *urb) 381*c04148f9SAlfred E. Heggestad { 382*c04148f9SAlfred E. Heggestad struct cm109_dev *dev = urb->context; 383*c04148f9SAlfred E. Heggestad const int status = urb->status; 384*c04148f9SAlfred E. Heggestad int error; 385*c04148f9SAlfred E. Heggestad 386*c04148f9SAlfred E. Heggestad #if CM109_DEBUG 387*c04148f9SAlfred E. Heggestad info("### URB CTL: [0x%02x 0x%02x 0x%02x 0x%02x]", 388*c04148f9SAlfred E. Heggestad dev->ctl_data->byte[0], 389*c04148f9SAlfred E. Heggestad dev->ctl_data->byte[1], 390*c04148f9SAlfred E. Heggestad dev->ctl_data->byte[2], 391*c04148f9SAlfred E. Heggestad dev->ctl_data->byte[3]); 392*c04148f9SAlfred E. Heggestad #endif 393*c04148f9SAlfred E. Heggestad 394*c04148f9SAlfred E. Heggestad if (status) 395*c04148f9SAlfred E. Heggestad err("%s: urb status %d", __func__, status); 396*c04148f9SAlfred E. Heggestad 397*c04148f9SAlfred E. Heggestad spin_lock(&dev->ctl_submit_lock); 398*c04148f9SAlfred E. Heggestad 399*c04148f9SAlfred E. Heggestad dev->ctl_urb_pending = 0; 400*c04148f9SAlfred E. Heggestad 401*c04148f9SAlfred E. Heggestad if (likely(!dev->shutdown)) { 402*c04148f9SAlfred E. Heggestad 403*c04148f9SAlfred E. Heggestad if (dev->buzzer_pending) { 404*c04148f9SAlfred E. Heggestad dev->buzzer_pending = 0; 405*c04148f9SAlfred E. Heggestad dev->ctl_urb_pending = 1; 406*c04148f9SAlfred E. Heggestad cm109_submit_buzz_toggle(dev); 407*c04148f9SAlfred E. Heggestad } else if (likely(!dev->irq_urb_pending)) { 408*c04148f9SAlfred E. Heggestad /* ask for key data */ 409*c04148f9SAlfred E. Heggestad dev->irq_urb_pending = 1; 410*c04148f9SAlfred E. Heggestad error = usb_submit_urb(dev->urb_irq, GFP_ATOMIC); 411*c04148f9SAlfred E. Heggestad if (error) 412*c04148f9SAlfred E. Heggestad err("%s: usb_submit_urb (urb_irq) failed %d", 413*c04148f9SAlfred E. Heggestad __func__, error); 414*c04148f9SAlfred E. Heggestad } 415*c04148f9SAlfred E. Heggestad } 416*c04148f9SAlfred E. Heggestad 417*c04148f9SAlfred E. Heggestad spin_unlock(&dev->ctl_submit_lock); 418*c04148f9SAlfred E. Heggestad } 419*c04148f9SAlfred E. Heggestad 420*c04148f9SAlfred E. Heggestad static void cm109_toggle_buzzer_async(struct cm109_dev *dev) 421*c04148f9SAlfred E. Heggestad { 422*c04148f9SAlfred E. Heggestad unsigned long flags; 423*c04148f9SAlfred E. Heggestad 424*c04148f9SAlfred E. Heggestad spin_lock_irqsave(&dev->ctl_submit_lock, flags); 425*c04148f9SAlfred E. Heggestad 426*c04148f9SAlfred E. Heggestad if (dev->ctl_urb_pending) { 427*c04148f9SAlfred E. Heggestad /* URB completion will resubmit */ 428*c04148f9SAlfred E. Heggestad dev->buzzer_pending = 1; 429*c04148f9SAlfred E. Heggestad } else { 430*c04148f9SAlfred E. Heggestad dev->ctl_urb_pending = 1; 431*c04148f9SAlfred E. Heggestad cm109_submit_buzz_toggle(dev); 432*c04148f9SAlfred E. Heggestad } 433*c04148f9SAlfred E. Heggestad 434*c04148f9SAlfred E. Heggestad spin_unlock_irqrestore(&dev->ctl_submit_lock, flags); 435*c04148f9SAlfred E. Heggestad } 436*c04148f9SAlfred E. Heggestad 437*c04148f9SAlfred E. Heggestad static void cm109_toggle_buzzer_sync(struct cm109_dev *dev, int on) 438*c04148f9SAlfred E. Heggestad { 439*c04148f9SAlfred E. Heggestad int error; 440*c04148f9SAlfred E. Heggestad 441*c04148f9SAlfred E. Heggestad if (on) 442*c04148f9SAlfred E. Heggestad dev->ctl_data->byte[HID_OR0] |= BUZZER_ON; 443*c04148f9SAlfred E. Heggestad else 444*c04148f9SAlfred E. Heggestad dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON; 445*c04148f9SAlfred E. Heggestad 446*c04148f9SAlfred E. Heggestad error = usb_control_msg(dev->udev, 447*c04148f9SAlfred E. Heggestad usb_sndctrlpipe(dev->udev, 0), 448*c04148f9SAlfred E. Heggestad dev->ctl_req->bRequest, 449*c04148f9SAlfred E. Heggestad dev->ctl_req->bRequestType, 450*c04148f9SAlfred E. Heggestad le16_to_cpu(dev->ctl_req->wValue), 451*c04148f9SAlfred E. Heggestad le16_to_cpu(dev->ctl_req->wIndex), 452*c04148f9SAlfred E. Heggestad dev->ctl_data, 453*c04148f9SAlfred E. Heggestad USB_PKT_LEN, USB_CTRL_SET_TIMEOUT); 454*c04148f9SAlfred E. Heggestad if (error && error != EINTR) 455*c04148f9SAlfred E. Heggestad err("%s: usb_control_msg() failed %d", __func__, error); 456*c04148f9SAlfred E. Heggestad } 457*c04148f9SAlfred E. Heggestad 458*c04148f9SAlfred E. Heggestad static void cm109_stop_traffic(struct cm109_dev *dev) 459*c04148f9SAlfred E. Heggestad { 460*c04148f9SAlfred E. Heggestad dev->shutdown = 1; 461*c04148f9SAlfred E. Heggestad /* 462*c04148f9SAlfred E. Heggestad * Make sure other CPUs see this 463*c04148f9SAlfred E. Heggestad */ 464*c04148f9SAlfred E. Heggestad smp_wmb(); 465*c04148f9SAlfred E. Heggestad 466*c04148f9SAlfred E. Heggestad usb_kill_urb(dev->urb_ctl); 467*c04148f9SAlfred E. Heggestad usb_kill_urb(dev->urb_irq); 468*c04148f9SAlfred E. Heggestad 469*c04148f9SAlfred E. Heggestad cm109_toggle_buzzer_sync(dev, 0); 470*c04148f9SAlfred E. Heggestad 471*c04148f9SAlfred E. Heggestad dev->shutdown = 0; 472*c04148f9SAlfred E. Heggestad smp_wmb(); 473*c04148f9SAlfred E. Heggestad } 474*c04148f9SAlfred E. Heggestad 475*c04148f9SAlfred E. Heggestad static void cm109_restore_state(struct cm109_dev *dev) 476*c04148f9SAlfred E. Heggestad { 477*c04148f9SAlfred E. Heggestad if (dev->open) { 478*c04148f9SAlfred E. Heggestad /* 479*c04148f9SAlfred E. Heggestad * Restore buzzer state. 480*c04148f9SAlfred E. Heggestad * This will also kick regular URB submission 481*c04148f9SAlfred E. Heggestad */ 482*c04148f9SAlfred E. Heggestad cm109_toggle_buzzer_async(dev); 483*c04148f9SAlfred E. Heggestad } 484*c04148f9SAlfred E. Heggestad } 485*c04148f9SAlfred E. Heggestad 486*c04148f9SAlfred E. Heggestad /****************************************************************************** 487*c04148f9SAlfred E. Heggestad * input event interface 488*c04148f9SAlfred E. Heggestad *****************************************************************************/ 489*c04148f9SAlfred E. Heggestad 490*c04148f9SAlfred E. Heggestad static int cm109_input_open(struct input_dev *idev) 491*c04148f9SAlfred E. Heggestad { 492*c04148f9SAlfred E. Heggestad struct cm109_dev *dev = input_get_drvdata(idev); 493*c04148f9SAlfred E. Heggestad int error; 494*c04148f9SAlfred E. Heggestad 495*c04148f9SAlfred E. Heggestad error = usb_autopm_get_interface(dev->intf); 496*c04148f9SAlfred E. Heggestad if (error < 0) { 497*c04148f9SAlfred E. Heggestad err("%s - cannot autoresume, result %d", 498*c04148f9SAlfred E. Heggestad __func__, error); 499*c04148f9SAlfred E. Heggestad return error; 500*c04148f9SAlfred E. Heggestad } 501*c04148f9SAlfred E. Heggestad 502*c04148f9SAlfred E. Heggestad mutex_lock(&dev->pm_mutex); 503*c04148f9SAlfred E. Heggestad 504*c04148f9SAlfred E. Heggestad dev->buzzer_state = 0; 505*c04148f9SAlfred E. Heggestad dev->key_code = -1; /* no keys pressed */ 506*c04148f9SAlfred E. Heggestad dev->keybit = 0xf; 507*c04148f9SAlfred E. Heggestad 508*c04148f9SAlfred E. Heggestad /* issue INIT */ 509*c04148f9SAlfred E. Heggestad dev->ctl_data->byte[HID_OR0] = HID_OR_GPO_BUZ_SPDIF; 510*c04148f9SAlfred E. Heggestad dev->ctl_data->byte[HID_OR1] = dev->keybit; 511*c04148f9SAlfred E. Heggestad dev->ctl_data->byte[HID_OR2] = dev->keybit; 512*c04148f9SAlfred E. Heggestad dev->ctl_data->byte[HID_OR3] = 0x00; 513*c04148f9SAlfred E. Heggestad 514*c04148f9SAlfred E. Heggestad error = usb_submit_urb(dev->urb_ctl, GFP_KERNEL); 515*c04148f9SAlfred E. Heggestad if (error) 516*c04148f9SAlfred E. Heggestad err("%s: usb_submit_urb (urb_ctl) failed %d", __func__, error); 517*c04148f9SAlfred E. Heggestad else 518*c04148f9SAlfred E. Heggestad dev->open = 1; 519*c04148f9SAlfred E. Heggestad 520*c04148f9SAlfred E. Heggestad mutex_unlock(&dev->pm_mutex); 521*c04148f9SAlfred E. Heggestad 522*c04148f9SAlfred E. Heggestad if (error) 523*c04148f9SAlfred E. Heggestad usb_autopm_put_interface(dev->intf); 524*c04148f9SAlfred E. Heggestad 525*c04148f9SAlfred E. Heggestad return error; 526*c04148f9SAlfred E. Heggestad } 527*c04148f9SAlfred E. Heggestad 528*c04148f9SAlfred E. Heggestad static void cm109_input_close(struct input_dev *idev) 529*c04148f9SAlfred E. Heggestad { 530*c04148f9SAlfred E. Heggestad struct cm109_dev *dev = input_get_drvdata(idev); 531*c04148f9SAlfred E. Heggestad 532*c04148f9SAlfred E. Heggestad mutex_lock(&dev->pm_mutex); 533*c04148f9SAlfred E. Heggestad 534*c04148f9SAlfred E. Heggestad /* 535*c04148f9SAlfred E. Heggestad * Once we are here event delivery is stopped so we 536*c04148f9SAlfred E. Heggestad * don't need to worry about someone starting buzzer 537*c04148f9SAlfred E. Heggestad * again 538*c04148f9SAlfred E. Heggestad */ 539*c04148f9SAlfred E. Heggestad cm109_stop_traffic(dev); 540*c04148f9SAlfred E. Heggestad dev->open = 0; 541*c04148f9SAlfred E. Heggestad 542*c04148f9SAlfred E. Heggestad mutex_unlock(&dev->pm_mutex); 543*c04148f9SAlfred E. Heggestad 544*c04148f9SAlfred E. Heggestad usb_autopm_put_interface(dev->intf); 545*c04148f9SAlfred E. Heggestad } 546*c04148f9SAlfred E. Heggestad 547*c04148f9SAlfred E. Heggestad static int cm109_input_ev(struct input_dev *idev, unsigned int type, 548*c04148f9SAlfred E. Heggestad unsigned int code, int value) 549*c04148f9SAlfred E. Heggestad { 550*c04148f9SAlfred E. Heggestad struct cm109_dev *dev = input_get_drvdata(idev); 551*c04148f9SAlfred E. Heggestad 552*c04148f9SAlfred E. Heggestad #if CM109_DEBUG 553*c04148f9SAlfred E. Heggestad info("input_ev: type=%u code=%u value=%d", type, code, value); 554*c04148f9SAlfred E. Heggestad #endif 555*c04148f9SAlfred E. Heggestad 556*c04148f9SAlfred E. Heggestad if (type != EV_SND) 557*c04148f9SAlfred E. Heggestad return -EINVAL; 558*c04148f9SAlfred E. Heggestad 559*c04148f9SAlfred E. Heggestad switch (code) { 560*c04148f9SAlfred E. Heggestad case SND_TONE: 561*c04148f9SAlfred E. Heggestad case SND_BELL: 562*c04148f9SAlfred E. Heggestad dev->buzzer_state = !!value; 563*c04148f9SAlfred E. Heggestad if (!dev->resetting) 564*c04148f9SAlfred E. Heggestad cm109_toggle_buzzer_async(dev); 565*c04148f9SAlfred E. Heggestad return 0; 566*c04148f9SAlfred E. Heggestad 567*c04148f9SAlfred E. Heggestad default: 568*c04148f9SAlfred E. Heggestad return -EINVAL; 569*c04148f9SAlfred E. Heggestad } 570*c04148f9SAlfred E. Heggestad } 571*c04148f9SAlfred E. Heggestad 572*c04148f9SAlfred E. Heggestad 573*c04148f9SAlfred E. Heggestad /****************************************************************************** 574*c04148f9SAlfred E. Heggestad * Linux interface and usb initialisation 575*c04148f9SAlfred E. Heggestad *****************************************************************************/ 576*c04148f9SAlfred E. Heggestad 577*c04148f9SAlfred E. Heggestad struct driver_info { 578*c04148f9SAlfred E. Heggestad char *name; 579*c04148f9SAlfred E. Heggestad }; 580*c04148f9SAlfred E. Heggestad 581*c04148f9SAlfred E. Heggestad static const struct driver_info info_cm109 = { 582*c04148f9SAlfred E. Heggestad .name = "CM109 USB driver", 583*c04148f9SAlfred E. Heggestad }; 584*c04148f9SAlfred E. Heggestad 585*c04148f9SAlfred E. Heggestad enum { 586*c04148f9SAlfred E. Heggestad VENDOR_ID = 0x0d8c, /* C-Media Electronics */ 587*c04148f9SAlfred E. Heggestad PRODUCT_ID_CM109 = 0x000e, /* CM109 defines range 0x0008 - 0x000f */ 588*c04148f9SAlfred E. Heggestad }; 589*c04148f9SAlfred E. Heggestad 590*c04148f9SAlfred E. Heggestad /* table of devices that work with this driver */ 591*c04148f9SAlfred E. Heggestad static const struct usb_device_id cm109_usb_table[] = { 592*c04148f9SAlfred E. Heggestad { 593*c04148f9SAlfred E. Heggestad .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 594*c04148f9SAlfred E. Heggestad USB_DEVICE_ID_MATCH_INT_INFO, 595*c04148f9SAlfred E. Heggestad .idVendor = VENDOR_ID, 596*c04148f9SAlfred E. Heggestad .idProduct = PRODUCT_ID_CM109, 597*c04148f9SAlfred E. Heggestad .bInterfaceClass = USB_CLASS_HID, 598*c04148f9SAlfred E. Heggestad .bInterfaceSubClass = 0, 599*c04148f9SAlfred E. Heggestad .bInterfaceProtocol = 0, 600*c04148f9SAlfred E. Heggestad .driver_info = (kernel_ulong_t) &info_cm109 601*c04148f9SAlfred E. Heggestad }, 602*c04148f9SAlfred E. Heggestad /* you can add more devices here with product ID 0x0008 - 0x000f */ 603*c04148f9SAlfred E. Heggestad { } 604*c04148f9SAlfred E. Heggestad }; 605*c04148f9SAlfred E. Heggestad 606*c04148f9SAlfred E. Heggestad static void cm109_usb_cleanup(struct cm109_dev *dev) 607*c04148f9SAlfred E. Heggestad { 608*c04148f9SAlfred E. Heggestad if (dev->ctl_req) 609*c04148f9SAlfred E. Heggestad usb_buffer_free(dev->udev, sizeof(*(dev->ctl_req)), 610*c04148f9SAlfred E. Heggestad dev->ctl_req, dev->ctl_req_dma); 611*c04148f9SAlfred E. Heggestad if (dev->ctl_data) 612*c04148f9SAlfred E. Heggestad usb_buffer_free(dev->udev, USB_PKT_LEN, 613*c04148f9SAlfred E. Heggestad dev->ctl_data, dev->ctl_dma); 614*c04148f9SAlfred E. Heggestad if (dev->irq_data) 615*c04148f9SAlfred E. Heggestad usb_buffer_free(dev->udev, USB_PKT_LEN, 616*c04148f9SAlfred E. Heggestad dev->irq_data, dev->irq_dma); 617*c04148f9SAlfred E. Heggestad 618*c04148f9SAlfred E. Heggestad usb_free_urb(dev->urb_irq); /* parameter validation in core/urb */ 619*c04148f9SAlfred E. Heggestad usb_free_urb(dev->urb_ctl); /* parameter validation in core/urb */ 620*c04148f9SAlfred E. Heggestad kfree(dev); 621*c04148f9SAlfred E. Heggestad } 622*c04148f9SAlfred E. Heggestad 623*c04148f9SAlfred E. Heggestad static void cm109_usb_disconnect(struct usb_interface *interface) 624*c04148f9SAlfred E. Heggestad { 625*c04148f9SAlfred E. Heggestad struct cm109_dev *dev = usb_get_intfdata(interface); 626*c04148f9SAlfred E. Heggestad 627*c04148f9SAlfred E. Heggestad usb_set_intfdata(interface, NULL); 628*c04148f9SAlfred E. Heggestad input_unregister_device(dev->idev); 629*c04148f9SAlfred E. Heggestad cm109_usb_cleanup(dev); 630*c04148f9SAlfred E. Heggestad } 631*c04148f9SAlfred E. Heggestad 632*c04148f9SAlfred E. Heggestad static int cm109_usb_probe(struct usb_interface *intf, 633*c04148f9SAlfred E. Heggestad const struct usb_device_id *id) 634*c04148f9SAlfred E. Heggestad { 635*c04148f9SAlfred E. Heggestad struct usb_device *udev = interface_to_usbdev(intf); 636*c04148f9SAlfred E. Heggestad struct driver_info *nfo = (struct driver_info *)id->driver_info; 637*c04148f9SAlfred E. Heggestad struct usb_host_interface *interface; 638*c04148f9SAlfred E. Heggestad struct usb_endpoint_descriptor *endpoint; 639*c04148f9SAlfred E. Heggestad struct cm109_dev *dev; 640*c04148f9SAlfred E. Heggestad struct input_dev *input_dev = NULL; 641*c04148f9SAlfred E. Heggestad int ret, pipe, i; 642*c04148f9SAlfred E. Heggestad int error = -ENOMEM; 643*c04148f9SAlfred E. Heggestad 644*c04148f9SAlfred E. Heggestad interface = intf->cur_altsetting; 645*c04148f9SAlfred E. Heggestad endpoint = &interface->endpoint[0].desc; 646*c04148f9SAlfred E. Heggestad 647*c04148f9SAlfred E. Heggestad if (!usb_endpoint_is_int_in(endpoint)) 648*c04148f9SAlfred E. Heggestad return -ENODEV; 649*c04148f9SAlfred E. Heggestad 650*c04148f9SAlfred E. Heggestad dev = kzalloc(sizeof(*dev), GFP_KERNEL); 651*c04148f9SAlfred E. Heggestad if (!dev) 652*c04148f9SAlfred E. Heggestad return -ENOMEM; 653*c04148f9SAlfred E. Heggestad 654*c04148f9SAlfred E. Heggestad spin_lock_init(&dev->ctl_submit_lock); 655*c04148f9SAlfred E. Heggestad mutex_init(&dev->pm_mutex); 656*c04148f9SAlfred E. Heggestad 657*c04148f9SAlfred E. Heggestad dev->udev = udev; 658*c04148f9SAlfred E. Heggestad dev->intf = intf; 659*c04148f9SAlfred E. Heggestad 660*c04148f9SAlfred E. Heggestad dev->idev = input_dev = input_allocate_device(); 661*c04148f9SAlfred E. Heggestad if (!input_dev) 662*c04148f9SAlfred E. Heggestad goto err_out; 663*c04148f9SAlfred E. Heggestad 664*c04148f9SAlfred E. Heggestad /* allocate usb buffers */ 665*c04148f9SAlfred E. Heggestad dev->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN, 666*c04148f9SAlfred E. Heggestad GFP_KERNEL, &dev->irq_dma); 667*c04148f9SAlfred E. Heggestad if (!dev->irq_data) 668*c04148f9SAlfred E. Heggestad goto err_out; 669*c04148f9SAlfred E. Heggestad 670*c04148f9SAlfred E. Heggestad dev->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN, 671*c04148f9SAlfred E. Heggestad GFP_KERNEL, &dev->ctl_dma); 672*c04148f9SAlfred E. Heggestad if (!dev->ctl_data) 673*c04148f9SAlfred E. Heggestad goto err_out; 674*c04148f9SAlfred E. Heggestad 675*c04148f9SAlfred E. Heggestad dev->ctl_req = usb_buffer_alloc(udev, sizeof(*(dev->ctl_req)), 676*c04148f9SAlfred E. Heggestad GFP_KERNEL, &dev->ctl_req_dma); 677*c04148f9SAlfred E. Heggestad if (!dev->ctl_req) 678*c04148f9SAlfred E. Heggestad goto err_out; 679*c04148f9SAlfred E. Heggestad 680*c04148f9SAlfred E. Heggestad /* allocate urb structures */ 681*c04148f9SAlfred E. Heggestad dev->urb_irq = usb_alloc_urb(0, GFP_KERNEL); 682*c04148f9SAlfred E. Heggestad if (!dev->urb_irq) 683*c04148f9SAlfred E. Heggestad goto err_out; 684*c04148f9SAlfred E. Heggestad 685*c04148f9SAlfred E. Heggestad dev->urb_ctl = usb_alloc_urb(0, GFP_KERNEL); 686*c04148f9SAlfred E. Heggestad if (!dev->urb_ctl) 687*c04148f9SAlfred E. Heggestad goto err_out; 688*c04148f9SAlfred E. Heggestad 689*c04148f9SAlfred E. Heggestad /* get a handle to the interrupt data pipe */ 690*c04148f9SAlfred E. Heggestad pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); 691*c04148f9SAlfred E. Heggestad ret = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); 692*c04148f9SAlfred E. Heggestad if (ret != USB_PKT_LEN) 693*c04148f9SAlfred E. Heggestad err("invalid payload size %d, expected %d", ret, USB_PKT_LEN); 694*c04148f9SAlfred E. Heggestad 695*c04148f9SAlfred E. Heggestad /* initialise irq urb */ 696*c04148f9SAlfred E. Heggestad usb_fill_int_urb(dev->urb_irq, udev, pipe, dev->irq_data, 697*c04148f9SAlfred E. Heggestad USB_PKT_LEN, 698*c04148f9SAlfred E. Heggestad cm109_urb_irq_callback, dev, endpoint->bInterval); 699*c04148f9SAlfred E. Heggestad dev->urb_irq->transfer_dma = dev->irq_dma; 700*c04148f9SAlfred E. Heggestad dev->urb_irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 701*c04148f9SAlfred E. Heggestad dev->urb_irq->dev = udev; 702*c04148f9SAlfred E. Heggestad 703*c04148f9SAlfred E. Heggestad /* initialise ctl urb */ 704*c04148f9SAlfred E. Heggestad dev->ctl_req->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | 705*c04148f9SAlfred E. Heggestad USB_DIR_OUT; 706*c04148f9SAlfred E. Heggestad dev->ctl_req->bRequest = USB_REQ_SET_CONFIGURATION; 707*c04148f9SAlfred E. Heggestad dev->ctl_req->wValue = cpu_to_le16(0x200); 708*c04148f9SAlfred E. Heggestad dev->ctl_req->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber); 709*c04148f9SAlfred E. Heggestad dev->ctl_req->wLength = cpu_to_le16(USB_PKT_LEN); 710*c04148f9SAlfred E. Heggestad 711*c04148f9SAlfred E. Heggestad usb_fill_control_urb(dev->urb_ctl, udev, usb_sndctrlpipe(udev, 0), 712*c04148f9SAlfred E. Heggestad (void *)dev->ctl_req, dev->ctl_data, USB_PKT_LEN, 713*c04148f9SAlfred E. Heggestad cm109_urb_ctl_callback, dev); 714*c04148f9SAlfred E. Heggestad dev->urb_ctl->setup_dma = dev->ctl_req_dma; 715*c04148f9SAlfred E. Heggestad dev->urb_ctl->transfer_dma = dev->ctl_dma; 716*c04148f9SAlfred E. Heggestad dev->urb_ctl->transfer_flags |= URB_NO_SETUP_DMA_MAP | 717*c04148f9SAlfred E. Heggestad URB_NO_TRANSFER_DMA_MAP; 718*c04148f9SAlfred E. Heggestad dev->urb_ctl->dev = udev; 719*c04148f9SAlfred E. Heggestad 720*c04148f9SAlfred E. Heggestad /* find out the physical bus location */ 721*c04148f9SAlfred E. Heggestad usb_make_path(udev, dev->phys, sizeof(dev->phys)); 722*c04148f9SAlfred E. Heggestad strlcat(dev->phys, "/input0", sizeof(dev->phys)); 723*c04148f9SAlfred E. Heggestad 724*c04148f9SAlfred E. Heggestad /* register settings for the input device */ 725*c04148f9SAlfred E. Heggestad input_dev->name = nfo->name; 726*c04148f9SAlfred E. Heggestad input_dev->phys = dev->phys; 727*c04148f9SAlfred E. Heggestad usb_to_input_id(udev, &input_dev->id); 728*c04148f9SAlfred E. Heggestad input_dev->dev.parent = &intf->dev; 729*c04148f9SAlfred E. Heggestad 730*c04148f9SAlfred E. Heggestad input_set_drvdata(input_dev, dev); 731*c04148f9SAlfred E. Heggestad input_dev->open = cm109_input_open; 732*c04148f9SAlfred E. Heggestad input_dev->close = cm109_input_close; 733*c04148f9SAlfred E. Heggestad input_dev->event = cm109_input_ev; 734*c04148f9SAlfred E. Heggestad 735*c04148f9SAlfred E. Heggestad input_dev->keycode = dev->keymap; 736*c04148f9SAlfred E. Heggestad input_dev->keycodesize = sizeof(unsigned char); 737*c04148f9SAlfred E. Heggestad input_dev->keycodemax = ARRAY_SIZE(dev->keymap); 738*c04148f9SAlfred E. Heggestad 739*c04148f9SAlfred E. Heggestad input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_SND); 740*c04148f9SAlfred E. Heggestad input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); 741*c04148f9SAlfred E. Heggestad 742*c04148f9SAlfred E. Heggestad /* register available key events */ 743*c04148f9SAlfred E. Heggestad for (i = 0; i < KEYMAP_SIZE; i++) { 744*c04148f9SAlfred E. Heggestad unsigned short k = keymap(i); 745*c04148f9SAlfred E. Heggestad dev->keymap[i] = k; 746*c04148f9SAlfred E. Heggestad __set_bit(k, input_dev->keybit); 747*c04148f9SAlfred E. Heggestad } 748*c04148f9SAlfred E. Heggestad __clear_bit(KEY_RESERVED, input_dev->keybit); 749*c04148f9SAlfred E. Heggestad 750*c04148f9SAlfred E. Heggestad error = input_register_device(dev->idev); 751*c04148f9SAlfred E. Heggestad if (error) 752*c04148f9SAlfred E. Heggestad goto err_out; 753*c04148f9SAlfred E. Heggestad 754*c04148f9SAlfred E. Heggestad usb_set_intfdata(intf, dev); 755*c04148f9SAlfred E. Heggestad 756*c04148f9SAlfred E. Heggestad return 0; 757*c04148f9SAlfred E. Heggestad 758*c04148f9SAlfred E. Heggestad err_out: 759*c04148f9SAlfred E. Heggestad input_free_device(input_dev); 760*c04148f9SAlfred E. Heggestad cm109_usb_cleanup(dev); 761*c04148f9SAlfred E. Heggestad return error; 762*c04148f9SAlfred E. Heggestad } 763*c04148f9SAlfred E. Heggestad 764*c04148f9SAlfred E. Heggestad static int cm109_usb_suspend(struct usb_interface *intf, pm_message_t message) 765*c04148f9SAlfred E. Heggestad { 766*c04148f9SAlfred E. Heggestad struct cm109_dev *dev = usb_get_intfdata(intf); 767*c04148f9SAlfred E. Heggestad 768*c04148f9SAlfred E. Heggestad info("cm109: usb_suspend (event=%d)", message.event); 769*c04148f9SAlfred E. Heggestad 770*c04148f9SAlfred E. Heggestad mutex_lock(&dev->pm_mutex); 771*c04148f9SAlfred E. Heggestad cm109_stop_traffic(dev); 772*c04148f9SAlfred E. Heggestad mutex_unlock(&dev->pm_mutex); 773*c04148f9SAlfred E. Heggestad 774*c04148f9SAlfred E. Heggestad return 0; 775*c04148f9SAlfred E. Heggestad } 776*c04148f9SAlfred E. Heggestad 777*c04148f9SAlfred E. Heggestad static int cm109_usb_resume(struct usb_interface *intf) 778*c04148f9SAlfred E. Heggestad { 779*c04148f9SAlfred E. Heggestad struct cm109_dev *dev = usb_get_intfdata(intf); 780*c04148f9SAlfred E. Heggestad 781*c04148f9SAlfred E. Heggestad info("cm109: usb_resume"); 782*c04148f9SAlfred E. Heggestad 783*c04148f9SAlfred E. Heggestad mutex_lock(&dev->pm_mutex); 784*c04148f9SAlfred E. Heggestad cm109_restore_state(dev); 785*c04148f9SAlfred E. Heggestad mutex_unlock(&dev->pm_mutex); 786*c04148f9SAlfred E. Heggestad 787*c04148f9SAlfred E. Heggestad return 0; 788*c04148f9SAlfred E. Heggestad } 789*c04148f9SAlfred E. Heggestad 790*c04148f9SAlfred E. Heggestad static int cm109_usb_pre_reset(struct usb_interface *intf) 791*c04148f9SAlfred E. Heggestad { 792*c04148f9SAlfred E. Heggestad struct cm109_dev *dev = usb_get_intfdata(intf); 793*c04148f9SAlfred E. Heggestad 794*c04148f9SAlfred E. Heggestad mutex_lock(&dev->pm_mutex); 795*c04148f9SAlfred E. Heggestad 796*c04148f9SAlfred E. Heggestad /* 797*c04148f9SAlfred E. Heggestad * Make sure input events don't try to toggle buzzer 798*c04148f9SAlfred E. Heggestad * while we are resetting 799*c04148f9SAlfred E. Heggestad */ 800*c04148f9SAlfred E. Heggestad dev->resetting = 1; 801*c04148f9SAlfred E. Heggestad smp_wmb(); 802*c04148f9SAlfred E. Heggestad 803*c04148f9SAlfred E. Heggestad cm109_stop_traffic(dev); 804*c04148f9SAlfred E. Heggestad 805*c04148f9SAlfred E. Heggestad return 0; 806*c04148f9SAlfred E. Heggestad } 807*c04148f9SAlfred E. Heggestad 808*c04148f9SAlfred E. Heggestad static int cm109_usb_post_reset(struct usb_interface *intf) 809*c04148f9SAlfred E. Heggestad { 810*c04148f9SAlfred E. Heggestad struct cm109_dev *dev = usb_get_intfdata(intf); 811*c04148f9SAlfred E. Heggestad 812*c04148f9SAlfred E. Heggestad dev->resetting = 0; 813*c04148f9SAlfred E. Heggestad smp_wmb(); 814*c04148f9SAlfred E. Heggestad 815*c04148f9SAlfred E. Heggestad cm109_restore_state(dev); 816*c04148f9SAlfred E. Heggestad 817*c04148f9SAlfred E. Heggestad mutex_unlock(&dev->pm_mutex); 818*c04148f9SAlfred E. Heggestad 819*c04148f9SAlfred E. Heggestad return 0; 820*c04148f9SAlfred E. Heggestad } 821*c04148f9SAlfred E. Heggestad 822*c04148f9SAlfred E. Heggestad static struct usb_driver cm109_driver = { 823*c04148f9SAlfred E. Heggestad .name = "cm109", 824*c04148f9SAlfred E. Heggestad .probe = cm109_usb_probe, 825*c04148f9SAlfred E. Heggestad .disconnect = cm109_usb_disconnect, 826*c04148f9SAlfred E. Heggestad .suspend = cm109_usb_suspend, 827*c04148f9SAlfred E. Heggestad .resume = cm109_usb_resume, 828*c04148f9SAlfred E. Heggestad .reset_resume = cm109_usb_resume, 829*c04148f9SAlfred E. Heggestad .pre_reset = cm109_usb_pre_reset, 830*c04148f9SAlfred E. Heggestad .post_reset = cm109_usb_post_reset, 831*c04148f9SAlfred E. Heggestad .id_table = cm109_usb_table, 832*c04148f9SAlfred E. Heggestad .supports_autosuspend = 1, 833*c04148f9SAlfred E. Heggestad }; 834*c04148f9SAlfred E. Heggestad 835*c04148f9SAlfred E. Heggestad static int __init cm109_select_keymap(void) 836*c04148f9SAlfred E. Heggestad { 837*c04148f9SAlfred E. Heggestad /* Load the phone keymap */ 838*c04148f9SAlfred E. Heggestad if (!strcasecmp(phone, "kip1000")) { 839*c04148f9SAlfred E. Heggestad keymap = keymap_kip1000; 840*c04148f9SAlfred E. Heggestad info("Keymap for Komunikate KIP1000 phone loaded"); 841*c04148f9SAlfred E. Heggestad } else if (!strcasecmp(phone, "gtalk")) { 842*c04148f9SAlfred E. Heggestad keymap = keymap_gtalk; 843*c04148f9SAlfred E. Heggestad info("Keymap for Genius G-talk phone loaded"); 844*c04148f9SAlfred E. Heggestad } else if (!strcasecmp(phone, "usbph01")) { 845*c04148f9SAlfred E. Heggestad keymap = keymap_usbph01; 846*c04148f9SAlfred E. Heggestad info("Keymap for Allied-Telesis Corega USBPH01 phone loaded"); 847*c04148f9SAlfred E. Heggestad } else { 848*c04148f9SAlfred E. Heggestad err("Unsupported phone: %s", phone); 849*c04148f9SAlfred E. Heggestad return -EINVAL; 850*c04148f9SAlfred E. Heggestad } 851*c04148f9SAlfred E. Heggestad 852*c04148f9SAlfred E. Heggestad return 0; 853*c04148f9SAlfred E. Heggestad } 854*c04148f9SAlfred E. Heggestad 855*c04148f9SAlfred E. Heggestad static int __init cm109_init(void) 856*c04148f9SAlfred E. Heggestad { 857*c04148f9SAlfred E. Heggestad int err; 858*c04148f9SAlfred E. Heggestad 859*c04148f9SAlfred E. Heggestad err = cm109_select_keymap(); 860*c04148f9SAlfred E. Heggestad if (err) 861*c04148f9SAlfred E. Heggestad return err; 862*c04148f9SAlfred E. Heggestad 863*c04148f9SAlfred E. Heggestad err = usb_register(&cm109_driver); 864*c04148f9SAlfred E. Heggestad if (err) 865*c04148f9SAlfred E. Heggestad return err; 866*c04148f9SAlfred E. Heggestad 867*c04148f9SAlfred E. Heggestad info(DRIVER_DESC ": " DRIVER_VERSION " (C) " DRIVER_AUTHOR); 868*c04148f9SAlfred E. Heggestad 869*c04148f9SAlfred E. Heggestad return 0; 870*c04148f9SAlfred E. Heggestad } 871*c04148f9SAlfred E. Heggestad 872*c04148f9SAlfred E. Heggestad static void __exit cm109_exit(void) 873*c04148f9SAlfred E. Heggestad { 874*c04148f9SAlfred E. Heggestad usb_deregister(&cm109_driver); 875*c04148f9SAlfred E. Heggestad } 876*c04148f9SAlfred E. Heggestad 877*c04148f9SAlfred E. Heggestad module_init(cm109_init); 878*c04148f9SAlfred E. Heggestad module_exit(cm109_exit); 879*c04148f9SAlfred E. Heggestad 880*c04148f9SAlfred E. Heggestad MODULE_DEVICE_TABLE(usb, cm109_usb_table); 881*c04148f9SAlfred E. Heggestad 882*c04148f9SAlfred E. Heggestad MODULE_AUTHOR(DRIVER_AUTHOR); 883*c04148f9SAlfred E. Heggestad MODULE_DESCRIPTION(DRIVER_DESC); 884*c04148f9SAlfred E. Heggestad MODULE_LICENSE("GPL"); 885