Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * drivers/usb/input/yealink.c
0004  *
0005  * Copyright (c) 2005 Henk Vergonet <Henk.Vergonet@gmail.com>
0006  */
0007 /*
0008  * Description:
0009  *   Driver for the USB-P1K voip usb phone.
0010  *   This device is produced by Yealink Network Technology Co Ltd
0011  *   but may be branded under several names:
0012  *  - Yealink usb-p1k
0013  *  - Tiptel 115
0014  *  - ...
0015  *
0016  * This driver is based on:
0017  *   - the usbb2k-api   http://savannah.nongnu.org/projects/usbb2k-api/
0018  *   - information from http://memeteau.free.fr/usbb2k
0019  *   - the xpad-driver  drivers/input/joystick/xpad.c
0020  *
0021  * Thanks to:
0022  *   - Olivier Vandorpe, for providing the usbb2k-api.
0023  *   - Martin Diehl, for spotting my memory allocation bug.
0024  *
0025  * History:
0026  *   20050527 henk  First version, functional keyboard. Keyboard events
0027  *          will pop-up on the ../input/eventX bus.
0028  *   20050531 henk  Added led, LCD, dialtone and sysfs interface.
0029  *   20050610 henk  Cleanups, make it ready for public consumption.
0030  *   20050630 henk  Cleanups, fixes in response to comments.
0031  *   20050701 henk  sysfs write serialisation, fix potential unload races
0032  *   20050801 henk  Added ringtone, restructure USB
0033  *   20050816 henk  Merge 2.6.13-rc6
0034  */
0035 
0036 #include <linux/kernel.h>
0037 #include <linux/slab.h>
0038 #include <linux/module.h>
0039 #include <linux/rwsem.h>
0040 #include <linux/usb/input.h>
0041 #include <linux/map_to_7segment.h>
0042 
0043 #include "yealink.h"
0044 
0045 #define DRIVER_VERSION "yld-20051230"
0046 
0047 #define YEALINK_POLLING_FREQUENCY   10  /* in [Hz] */
0048 
0049 struct yld_status {
0050     u8  lcd[24];
0051     u8  led;
0052     u8  dialtone;
0053     u8  ringtone;
0054     u8  keynum;
0055 } __attribute__ ((packed));
0056 
0057 /*
0058  * Register the LCD segment and icon map
0059  */
0060 #define _LOC(k,l)   { .a = (k), .m = (l) }
0061 #define _SEG(t, a, am, b, bm, c, cm, d, dm, e, em, f, fm, g, gm)    \
0062     { .type = (t),                          \
0063       .u = { .s = { _LOC(a, am), _LOC(b, bm), _LOC(c, cm),      \
0064                 _LOC(d, dm), _LOC(e, em), _LOC(g, gm),      \
0065             _LOC(f, fm) } } }
0066 #define _PIC(t, h, hm, n)                       \
0067     { .type = (t),                          \
0068       .u = { .p = { .name = (n), .a = (h), .m = (hm) } } }
0069 
0070 static const struct lcd_segment_map {
0071     char    type;
0072     union {
0073         struct pictogram_map {
0074             u8  a,m;
0075             char    name[10];
0076         }   p;
0077         struct segment_map {
0078             u8  a,m;
0079         } s[7];
0080     } u;
0081 } lcdMap[] = {
0082 #include "yealink.h"
0083 };
0084 
0085 struct yealink_dev {
0086     struct input_dev *idev;     /* input device */
0087     struct usb_device *udev;    /* usb device */
0088     struct usb_interface *intf; /* usb interface */
0089 
0090     /* irq input channel */
0091     struct yld_ctl_packet   *irq_data;
0092     dma_addr_t      irq_dma;
0093     struct urb      *urb_irq;
0094 
0095     /* control output channel */
0096     struct yld_ctl_packet   *ctl_data;
0097     dma_addr_t      ctl_dma;
0098     struct usb_ctrlrequest  *ctl_req;
0099     struct urb      *urb_ctl;
0100 
0101     char phys[64];          /* physical device path */
0102 
0103     u8 lcdMap[ARRAY_SIZE(lcdMap)];  /* state of LCD, LED ... */
0104     int key_code;           /* last reported key     */
0105 
0106     unsigned int shutdown:1;
0107 
0108     int stat_ix;
0109     union {
0110         struct yld_status s;
0111         u8        b[sizeof(struct yld_status)];
0112     } master, copy;
0113 };
0114 
0115 
0116 /*******************************************************************************
0117  * Yealink lcd interface
0118  ******************************************************************************/
0119 
0120 /*
0121  * Register a default 7 segment character set
0122  */
0123 static SEG7_DEFAULT_MAP(map_seg7);
0124 
0125  /* Display a char,
0126   * char '\9' and '\n' are placeholders and do not overwrite the original text.
0127   * A space will always hide an icon.
0128   */
0129 static int setChar(struct yealink_dev *yld, int el, int chr)
0130 {
0131     int i, a, m, val;
0132 
0133     if (el >= ARRAY_SIZE(lcdMap))
0134         return -EINVAL;
0135 
0136     if (chr == '\t' || chr == '\n')
0137         return 0;
0138 
0139     yld->lcdMap[el] = chr;
0140 
0141     if (lcdMap[el].type == '.') {
0142         a = lcdMap[el].u.p.a;
0143         m = lcdMap[el].u.p.m;
0144         if (chr != ' ')
0145             yld->master.b[a] |= m;
0146         else
0147             yld->master.b[a] &= ~m;
0148         return 0;
0149     }
0150 
0151     val = map_to_seg7(&map_seg7, chr);
0152     for (i = 0; i < ARRAY_SIZE(lcdMap[0].u.s); i++) {
0153         m = lcdMap[el].u.s[i].m;
0154 
0155         if (m == 0)
0156             continue;
0157 
0158         a = lcdMap[el].u.s[i].a;
0159         if (val & 1)
0160             yld->master.b[a] |= m;
0161         else
0162             yld->master.b[a] &= ~m;
0163         val = val >> 1;
0164     }
0165     return 0;
0166 };
0167 
0168 /*******************************************************************************
0169  * Yealink key interface
0170  ******************************************************************************/
0171 
0172 /* Map device buttons to internal key events.
0173  *
0174  * USB-P1K button layout:
0175  *
0176  *             up
0177  *       IN           OUT
0178  *            down
0179  *
0180  *     pickup   C    hangup
0181  *       1      2      3
0182  *       4      5      6
0183  *       7      8      9
0184  *       *      0      #
0185  *
0186  * The "up" and "down" keys, are symbolised by arrows on the button.
0187  * The "pickup" and "hangup" keys are symbolised by a green and red phone
0188  * on the button.
0189  */
0190 static int map_p1k_to_key(int scancode)
0191 {
0192     switch(scancode) {      /* phone key:   */
0193     case 0x23: return KEY_LEFT; /*   IN     */
0194     case 0x33: return KEY_UP;   /*   up     */
0195     case 0x04: return KEY_RIGHT;    /*   OUT    */
0196     case 0x24: return KEY_DOWN; /*   down   */
0197     case 0x03: return KEY_ENTER;    /*   pickup */
0198     case 0x14: return KEY_BACKSPACE; /*  C      */
0199     case 0x13: return KEY_ESC;  /*   hangup */
0200     case 0x00: return KEY_1;    /*   1      */
0201     case 0x01: return KEY_2;    /*   2      */
0202     case 0x02: return KEY_3;    /*   3      */
0203     case 0x10: return KEY_4;    /*   4      */
0204     case 0x11: return KEY_5;    /*   5      */
0205     case 0x12: return KEY_6;    /*   6      */
0206     case 0x20: return KEY_7;    /*   7      */
0207     case 0x21: return KEY_8;    /*   8      */
0208     case 0x22: return KEY_9;    /*   9      */
0209     case 0x30: return KEY_KPASTERISK; /* *      */
0210     case 0x31: return KEY_0;    /*   0      */
0211     case 0x32: return KEY_LEFTSHIFT |
0212               KEY_3 << 8;   /*   #      */
0213     }
0214     return -EINVAL;
0215 }
0216 
0217 /* Completes a request by converting the data into events for the
0218  * input subsystem.
0219  *
0220  * The key parameter can be cascaded: key2 << 8 | key1
0221  */
0222 static void report_key(struct yealink_dev *yld, int key)
0223 {
0224     struct input_dev *idev = yld->idev;
0225 
0226     if (yld->key_code >= 0) {
0227         /* old key up */
0228         input_report_key(idev, yld->key_code & 0xff, 0);
0229         if (yld->key_code >> 8)
0230             input_report_key(idev, yld->key_code >> 8, 0);
0231     }
0232 
0233     yld->key_code = key;
0234     if (key >= 0) {
0235         /* new valid key */
0236         input_report_key(idev, key & 0xff, 1);
0237         if (key >> 8)
0238             input_report_key(idev, key >> 8, 1);
0239     }
0240     input_sync(idev);
0241 }
0242 
0243 /*******************************************************************************
0244  * Yealink usb communication interface
0245  ******************************************************************************/
0246 
0247 static int yealink_cmd(struct yealink_dev *yld, struct yld_ctl_packet *p)
0248 {
0249     u8  *buf = (u8 *)p;
0250     int i;
0251     u8  sum = 0;
0252 
0253     for(i=0; i<USB_PKT_LEN-1; i++)
0254         sum -= buf[i];
0255     p->sum = sum;
0256     return usb_control_msg(yld->udev,
0257             usb_sndctrlpipe(yld->udev, 0),
0258             USB_REQ_SET_CONFIGURATION,
0259             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
0260             0x200, 3,
0261             p, sizeof(*p),
0262             USB_CTRL_SET_TIMEOUT);
0263 }
0264 
0265 static u8 default_ringtone[] = {
0266     0xEF,           /* volume [0-255] */
0267     0xFB, 0x1E, 0x00, 0x0C, /* 1250 [hz], 12/100 [s] */
0268     0xFC, 0x18, 0x00, 0x0C, /* 1000 [hz], 12/100 [s] */
0269     0xFB, 0x1E, 0x00, 0x0C,
0270     0xFC, 0x18, 0x00, 0x0C,
0271     0xFB, 0x1E, 0x00, 0x0C,
0272     0xFC, 0x18, 0x00, 0x0C,
0273     0xFB, 0x1E, 0x00, 0x0C,
0274     0xFC, 0x18, 0x00, 0x0C,
0275     0xFF, 0xFF, 0x01, 0x90, /* silent, 400/100 [s] */
0276     0x00, 0x00      /* end of sequence */
0277 };
0278 
0279 static int yealink_set_ringtone(struct yealink_dev *yld, u8 *buf, size_t size)
0280 {
0281     struct yld_ctl_packet *p = yld->ctl_data;
0282     int ix, len;
0283 
0284     if (size <= 0)
0285         return -EINVAL;
0286 
0287     /* Set the ringtone volume */
0288     memset(yld->ctl_data, 0, sizeof(*(yld->ctl_data)));
0289     yld->ctl_data->cmd  = CMD_RING_VOLUME;
0290     yld->ctl_data->size = 1;
0291     yld->ctl_data->data[0]  = buf[0];
0292     yealink_cmd(yld, p);
0293 
0294     buf++;
0295     size--;
0296 
0297     p->cmd = CMD_RING_NOTE;
0298     ix = 0;
0299     while (size != ix) {
0300         len = size - ix;
0301         if (len > sizeof(p->data))
0302             len = sizeof(p->data);
0303         p->size   = len;
0304         p->offset = cpu_to_be16(ix);
0305         memcpy(p->data, &buf[ix], len);
0306         yealink_cmd(yld, p);
0307         ix += len;
0308     }
0309     return 0;
0310 }
0311 
0312 /* keep stat_master & stat_copy in sync.
0313  */
0314 static int yealink_do_idle_tasks(struct yealink_dev *yld)
0315 {
0316     u8 val;
0317     int i, ix, len;
0318 
0319     ix = yld->stat_ix;
0320 
0321     memset(yld->ctl_data, 0, sizeof(*(yld->ctl_data)));
0322     yld->ctl_data->cmd  = CMD_KEYPRESS;
0323     yld->ctl_data->size = 1;
0324     yld->ctl_data->sum  = 0xff - CMD_KEYPRESS;
0325 
0326     /* If state update pointer wraps do a KEYPRESS first. */
0327     if (ix >= sizeof(yld->master)) {
0328         yld->stat_ix = 0;
0329         return 0;
0330     }
0331 
0332     /* find update candidates: copy != master */
0333     do {
0334         val = yld->master.b[ix];
0335         if (val != yld->copy.b[ix])
0336             goto send_update;
0337     } while (++ix < sizeof(yld->master));
0338 
0339     /* nothing todo, wait a bit and poll for a KEYPRESS */
0340     yld->stat_ix = 0;
0341     /* TODO how can we wait abit. ??
0342      * msleep_interruptible(1000 / YEALINK_POLLING_FREQUENCY);
0343      */
0344     return 0;
0345 
0346 send_update:
0347 
0348     /* Setup an appropriate update request */
0349     yld->copy.b[ix] = val;
0350     yld->ctl_data->data[0] = val;
0351 
0352     switch(ix) {
0353     case offsetof(struct yld_status, led):
0354         yld->ctl_data->cmd  = CMD_LED;
0355         yld->ctl_data->sum  = -1 - CMD_LED - val;
0356         break;
0357     case offsetof(struct yld_status, dialtone):
0358         yld->ctl_data->cmd  = CMD_DIALTONE;
0359         yld->ctl_data->sum  = -1 - CMD_DIALTONE - val;
0360         break;
0361     case offsetof(struct yld_status, ringtone):
0362         yld->ctl_data->cmd  = CMD_RINGTONE;
0363         yld->ctl_data->sum  = -1 - CMD_RINGTONE - val;
0364         break;
0365     case offsetof(struct yld_status, keynum):
0366         val--;
0367         val &= 0x1f;
0368         yld->ctl_data->cmd  = CMD_SCANCODE;
0369         yld->ctl_data->offset   = cpu_to_be16(val);
0370         yld->ctl_data->data[0]  = 0;
0371         yld->ctl_data->sum  = -1 - CMD_SCANCODE - val;
0372         break;
0373     default:
0374         len = sizeof(yld->master.s.lcd) - ix;
0375         if (len > sizeof(yld->ctl_data->data))
0376             len = sizeof(yld->ctl_data->data);
0377 
0378         /* Combine up to <len> consecutive LCD bytes in a singe request
0379          */
0380         yld->ctl_data->cmd  = CMD_LCD;
0381         yld->ctl_data->offset   = cpu_to_be16(ix);
0382         yld->ctl_data->size = len;
0383         yld->ctl_data->sum  = -CMD_LCD - ix - val - len;
0384         for(i=1; i<len; i++) {
0385             ix++;
0386             val = yld->master.b[ix];
0387             yld->copy.b[ix]     = val;
0388             yld->ctl_data->data[i]  = val;
0389             yld->ctl_data->sum     -= val;
0390         }
0391     }
0392     yld->stat_ix = ix + 1;
0393     return 1;
0394 }
0395 
0396 /* Decide on how to handle responses
0397  *
0398  * The state transition diagram is somethhing like:
0399  *
0400  *          syncState<--+
0401  *               |      |
0402  *               |    idle
0403  *              \|/     |
0404  * init --ok--> waitForKey --ok--> getKey
0405  *  ^               ^                |
0406  *  |               +-------ok-------+
0407  * error,start
0408  *
0409  */
0410 static void urb_irq_callback(struct urb *urb)
0411 {
0412     struct yealink_dev *yld = urb->context;
0413     int ret, status = urb->status;
0414 
0415     if (status)
0416         dev_err(&yld->intf->dev, "%s - urb status %d\n",
0417             __func__, status);
0418 
0419     switch (yld->irq_data->cmd) {
0420     case CMD_KEYPRESS:
0421 
0422         yld->master.s.keynum = yld->irq_data->data[0];
0423         break;
0424 
0425     case CMD_SCANCODE:
0426         dev_dbg(&yld->intf->dev, "get scancode %x\n",
0427             yld->irq_data->data[0]);
0428 
0429         report_key(yld, map_p1k_to_key(yld->irq_data->data[0]));
0430         break;
0431 
0432     default:
0433         dev_err(&yld->intf->dev, "unexpected response %x\n",
0434             yld->irq_data->cmd);
0435     }
0436 
0437     yealink_do_idle_tasks(yld);
0438 
0439     if (!yld->shutdown) {
0440         ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
0441         if (ret && ret != -EPERM)
0442             dev_err(&yld->intf->dev,
0443                 "%s - usb_submit_urb failed %d\n",
0444                 __func__, ret);
0445     }
0446 }
0447 
0448 static void urb_ctl_callback(struct urb *urb)
0449 {
0450     struct yealink_dev *yld = urb->context;
0451     int ret = 0, status = urb->status;
0452 
0453     if (status)
0454         dev_err(&yld->intf->dev, "%s - urb status %d\n",
0455             __func__, status);
0456 
0457     switch (yld->ctl_data->cmd) {
0458     case CMD_KEYPRESS:
0459     case CMD_SCANCODE:
0460         /* ask for a response */
0461         if (!yld->shutdown)
0462             ret = usb_submit_urb(yld->urb_irq, GFP_ATOMIC);
0463         break;
0464     default:
0465         /* send new command */
0466         yealink_do_idle_tasks(yld);
0467         if (!yld->shutdown)
0468             ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
0469         break;
0470     }
0471 
0472     if (ret && ret != -EPERM)
0473         dev_err(&yld->intf->dev, "%s - usb_submit_urb failed %d\n",
0474             __func__, ret);
0475 }
0476 
0477 /*******************************************************************************
0478  * input event interface
0479  ******************************************************************************/
0480 
0481 /* TODO should we issue a ringtone on a SND_BELL event?
0482 static int input_ev(struct input_dev *dev, unsigned int type,
0483         unsigned int code, int value)
0484 {
0485 
0486     if (type != EV_SND)
0487         return -EINVAL;
0488 
0489     switch (code) {
0490     case SND_BELL:
0491     case SND_TONE:
0492         break;
0493     default:
0494         return -EINVAL;
0495     }
0496 
0497     return 0;
0498 }
0499 */
0500 
0501 static int input_open(struct input_dev *dev)
0502 {
0503     struct yealink_dev *yld = input_get_drvdata(dev);
0504     int i, ret;
0505 
0506     dev_dbg(&yld->intf->dev, "%s\n", __func__);
0507 
0508     /* force updates to device */
0509     for (i = 0; i<sizeof(yld->master); i++)
0510         yld->copy.b[i] = ~yld->master.b[i];
0511     yld->key_code = -1; /* no keys pressed */
0512 
0513         yealink_set_ringtone(yld, default_ringtone, sizeof(default_ringtone));
0514 
0515     /* issue INIT */
0516     memset(yld->ctl_data, 0, sizeof(*(yld->ctl_data)));
0517     yld->ctl_data->cmd  = CMD_INIT;
0518     yld->ctl_data->size = 10;
0519     yld->ctl_data->sum  = 0x100-CMD_INIT-10;
0520     if ((ret = usb_submit_urb(yld->urb_ctl, GFP_KERNEL)) != 0) {
0521         dev_dbg(&yld->intf->dev,
0522             "%s - usb_submit_urb failed with result %d\n",
0523             __func__, ret);
0524         return ret;
0525     }
0526     return 0;
0527 }
0528 
0529 static void input_close(struct input_dev *dev)
0530 {
0531     struct yealink_dev *yld = input_get_drvdata(dev);
0532 
0533     yld->shutdown = 1;
0534     /*
0535      * Make sure the flag is seen by other CPUs before we start
0536      * killing URBs so new URBs won't be submitted
0537      */
0538     smp_wmb();
0539 
0540     usb_kill_urb(yld->urb_ctl);
0541     usb_kill_urb(yld->urb_irq);
0542 
0543     yld->shutdown = 0;
0544     smp_wmb();
0545 }
0546 
0547 /*******************************************************************************
0548  * sysfs interface
0549  ******************************************************************************/
0550 
0551 static DECLARE_RWSEM(sysfs_rwsema);
0552 
0553 /* Interface to the 7-segments translation table aka. char set.
0554  */
0555 static ssize_t show_map(struct device *dev, struct device_attribute *attr,
0556                 char *buf)
0557 {
0558     memcpy(buf, &map_seg7, sizeof(map_seg7));
0559     return sizeof(map_seg7);
0560 }
0561 
0562 static ssize_t store_map(struct device *dev, struct device_attribute *attr,
0563                 const char *buf, size_t cnt)
0564 {
0565     if (cnt != sizeof(map_seg7))
0566         return -EINVAL;
0567     memcpy(&map_seg7, buf, sizeof(map_seg7));
0568     return sizeof(map_seg7);
0569 }
0570 
0571 /* Interface to the LCD.
0572  */
0573 
0574 /* Reading /sys/../lineX will return the format string with its settings:
0575  *
0576  * Example:
0577  * cat ./line3
0578  * 888888888888
0579  * Linux Rocks!
0580  */
0581 static ssize_t show_line(struct device *dev, char *buf, int a, int b)
0582 {
0583     struct yealink_dev *yld;
0584     int i;
0585 
0586     down_read(&sysfs_rwsema);
0587     yld = dev_get_drvdata(dev);
0588     if (yld == NULL) {
0589         up_read(&sysfs_rwsema);
0590         return -ENODEV;
0591     }
0592 
0593     for (i = a; i < b; i++)
0594         *buf++ = lcdMap[i].type;
0595     *buf++ = '\n';
0596     for (i = a; i < b; i++)
0597         *buf++ = yld->lcdMap[i];
0598     *buf++ = '\n';
0599     *buf = 0;
0600 
0601     up_read(&sysfs_rwsema);
0602     return 3 + ((b - a) << 1);
0603 }
0604 
0605 static ssize_t show_line1(struct device *dev, struct device_attribute *attr,
0606             char *buf)
0607 {
0608     return show_line(dev, buf, LCD_LINE1_OFFSET, LCD_LINE2_OFFSET);
0609 }
0610 
0611 static ssize_t show_line2(struct device *dev, struct device_attribute *attr,
0612             char *buf)
0613 {
0614     return show_line(dev, buf, LCD_LINE2_OFFSET, LCD_LINE3_OFFSET);
0615 }
0616 
0617 static ssize_t show_line3(struct device *dev, struct device_attribute *attr,
0618             char *buf)
0619 {
0620     return show_line(dev, buf, LCD_LINE3_OFFSET, LCD_LINE4_OFFSET);
0621 }
0622 
0623 /* Writing to /sys/../lineX will set the coresponding LCD line.
0624  * - Excess characters are ignored.
0625  * - If less characters are written than allowed, the remaining digits are
0626  *   unchanged.
0627  * - The '\n' or '\t' char is a placeholder, it does not overwrite the
0628  *   original content.
0629  */
0630 static ssize_t store_line(struct device *dev, const char *buf, size_t count,
0631         int el, size_t len)
0632 {
0633     struct yealink_dev *yld;
0634     int i;
0635 
0636     down_write(&sysfs_rwsema);
0637     yld = dev_get_drvdata(dev);
0638     if (yld == NULL) {
0639         up_write(&sysfs_rwsema);
0640         return -ENODEV;
0641     }
0642 
0643     if (len > count)
0644         len = count;
0645     for (i = 0; i < len; i++)
0646         setChar(yld, el++, buf[i]);
0647 
0648     up_write(&sysfs_rwsema);
0649     return count;
0650 }
0651 
0652 static ssize_t store_line1(struct device *dev, struct device_attribute *attr,
0653                 const char *buf, size_t count)
0654 {
0655     return store_line(dev, buf, count, LCD_LINE1_OFFSET, LCD_LINE1_SIZE);
0656 }
0657 
0658 static ssize_t store_line2(struct device *dev, struct device_attribute *attr,
0659                 const char *buf, size_t count)
0660 {
0661     return store_line(dev, buf, count, LCD_LINE2_OFFSET, LCD_LINE2_SIZE);
0662 }
0663 
0664 static ssize_t store_line3(struct device *dev, struct device_attribute *attr,
0665                 const char *buf, size_t count)
0666 {
0667     return store_line(dev, buf, count, LCD_LINE3_OFFSET, LCD_LINE3_SIZE);
0668 }
0669 
0670 /* Interface to visible and audible "icons", these include:
0671  * pictures on the LCD, the LED, and the dialtone signal.
0672  */
0673 
0674 /* Get a list of "switchable elements" with their current state. */
0675 static ssize_t get_icons(struct device *dev, struct device_attribute *attr,
0676             char *buf)
0677 {
0678     struct yealink_dev *yld;
0679     int i, ret = 1;
0680 
0681     down_read(&sysfs_rwsema);
0682     yld = dev_get_drvdata(dev);
0683     if (yld == NULL) {
0684         up_read(&sysfs_rwsema);
0685         return -ENODEV;
0686     }
0687 
0688     for (i = 0; i < ARRAY_SIZE(lcdMap); i++) {
0689         if (lcdMap[i].type != '.')
0690             continue;
0691         ret += sprintf(&buf[ret], "%s %s\n",
0692                 yld->lcdMap[i] == ' ' ? "  " : "on",
0693                 lcdMap[i].u.p.name);
0694     }
0695     up_read(&sysfs_rwsema);
0696     return ret;
0697 }
0698 
0699 /* Change the visibility of a particular element. */
0700 static ssize_t set_icon(struct device *dev, const char *buf, size_t count,
0701             int chr)
0702 {
0703     struct yealink_dev *yld;
0704     int i;
0705 
0706     down_write(&sysfs_rwsema);
0707     yld = dev_get_drvdata(dev);
0708     if (yld == NULL) {
0709         up_write(&sysfs_rwsema);
0710         return -ENODEV;
0711     }
0712 
0713     for (i = 0; i < ARRAY_SIZE(lcdMap); i++) {
0714         if (lcdMap[i].type != '.')
0715             continue;
0716         if (strncmp(buf, lcdMap[i].u.p.name, count) == 0) {
0717             setChar(yld, i, chr);
0718             break;
0719         }
0720     }
0721 
0722     up_write(&sysfs_rwsema);
0723     return count;
0724 }
0725 
0726 static ssize_t show_icon(struct device *dev, struct device_attribute *attr,
0727         const char *buf, size_t count)
0728 {
0729     return set_icon(dev, buf, count, buf[0]);
0730 }
0731 
0732 static ssize_t hide_icon(struct device *dev, struct device_attribute *attr,
0733         const char *buf, size_t count)
0734 {
0735     return set_icon(dev, buf, count, ' ');
0736 }
0737 
0738 /* Upload a ringtone to the device.
0739  */
0740 
0741 /* Stores raw ringtone data in the phone */
0742 static ssize_t store_ringtone(struct device *dev,
0743         struct device_attribute *attr,
0744         const char *buf, size_t count)
0745 {
0746     struct yealink_dev *yld;
0747 
0748     down_write(&sysfs_rwsema);
0749     yld = dev_get_drvdata(dev);
0750     if (yld == NULL) {
0751         up_write(&sysfs_rwsema);
0752         return -ENODEV;
0753     }
0754 
0755     /* TODO locking with async usb control interface??? */
0756     yealink_set_ringtone(yld, (char *)buf, count);
0757     up_write(&sysfs_rwsema);
0758     return count;
0759 }
0760 
0761 #define _M444   S_IRUGO
0762 #define _M664   S_IRUGO|S_IWUSR|S_IWGRP
0763 #define _M220   S_IWUSR|S_IWGRP
0764 
0765 static DEVICE_ATTR(map_seg7 , _M664, show_map   , store_map );
0766 static DEVICE_ATTR(line1    , _M664, show_line1 , store_line1   );
0767 static DEVICE_ATTR(line2    , _M664, show_line2 , store_line2   );
0768 static DEVICE_ATTR(line3    , _M664, show_line3 , store_line3   );
0769 static DEVICE_ATTR(get_icons    , _M444, get_icons  , NULL      );
0770 static DEVICE_ATTR(show_icon    , _M220, NULL       , show_icon );
0771 static DEVICE_ATTR(hide_icon    , _M220, NULL       , hide_icon );
0772 static DEVICE_ATTR(ringtone , _M220, NULL       , store_ringtone);
0773 
0774 static struct attribute *yld_attributes[] = {
0775     &dev_attr_line1.attr,
0776     &dev_attr_line2.attr,
0777     &dev_attr_line3.attr,
0778     &dev_attr_get_icons.attr,
0779     &dev_attr_show_icon.attr,
0780     &dev_attr_hide_icon.attr,
0781     &dev_attr_map_seg7.attr,
0782     &dev_attr_ringtone.attr,
0783     NULL
0784 };
0785 
0786 static const struct attribute_group yld_attr_group = {
0787     .attrs = yld_attributes
0788 };
0789 
0790 /*******************************************************************************
0791  * Linux interface and usb initialisation
0792  ******************************************************************************/
0793 
0794 struct driver_info {
0795     char *name;
0796 };
0797 
0798 static const struct driver_info info_P1K = {
0799     .name   = "Yealink usb-p1k",
0800 };
0801 
0802 static const struct usb_device_id usb_table [] = {
0803     {
0804         .match_flags        = USB_DEVICE_ID_MATCH_DEVICE |
0805                         USB_DEVICE_ID_MATCH_INT_INFO,
0806         .idVendor       = 0x6993,
0807         .idProduct      = 0xb001,
0808         .bInterfaceClass    = USB_CLASS_HID,
0809         .bInterfaceSubClass = 0,
0810         .bInterfaceProtocol = 0,
0811         .driver_info        = (kernel_ulong_t)&info_P1K
0812     },
0813     { }
0814 };
0815 
0816 static int usb_cleanup(struct yealink_dev *yld, int err)
0817 {
0818     if (yld == NULL)
0819         return err;
0820 
0821         if (yld->idev) {
0822         if (err)
0823             input_free_device(yld->idev);
0824         else
0825             input_unregister_device(yld->idev);
0826     }
0827 
0828     usb_free_urb(yld->urb_irq);
0829     usb_free_urb(yld->urb_ctl);
0830 
0831     kfree(yld->ctl_req);
0832     usb_free_coherent(yld->udev, USB_PKT_LEN, yld->ctl_data, yld->ctl_dma);
0833     usb_free_coherent(yld->udev, USB_PKT_LEN, yld->irq_data, yld->irq_dma);
0834 
0835     kfree(yld);
0836     return err;
0837 }
0838 
0839 static void usb_disconnect(struct usb_interface *intf)
0840 {
0841     struct yealink_dev *yld;
0842 
0843     down_write(&sysfs_rwsema);
0844     yld = usb_get_intfdata(intf);
0845     sysfs_remove_group(&intf->dev.kobj, &yld_attr_group);
0846     usb_set_intfdata(intf, NULL);
0847     up_write(&sysfs_rwsema);
0848 
0849     usb_cleanup(yld, 0);
0850 }
0851 
0852 static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
0853 {
0854     struct usb_device *udev = interface_to_usbdev (intf);
0855     struct driver_info *nfo = (struct driver_info *)id->driver_info;
0856     struct usb_host_interface *interface;
0857     struct usb_endpoint_descriptor *endpoint;
0858     struct yealink_dev *yld;
0859     struct input_dev *input_dev;
0860     int ret, pipe, i;
0861 
0862     interface = intf->cur_altsetting;
0863 
0864     if (interface->desc.bNumEndpoints < 1)
0865         return -ENODEV;
0866 
0867     endpoint = &interface->endpoint[0].desc;
0868     if (!usb_endpoint_is_int_in(endpoint))
0869         return -ENODEV;
0870 
0871     yld = kzalloc(sizeof(struct yealink_dev), GFP_KERNEL);
0872     if (!yld)
0873         return -ENOMEM;
0874 
0875     yld->udev = udev;
0876     yld->intf = intf;
0877 
0878     yld->idev = input_dev = input_allocate_device();
0879     if (!input_dev)
0880         return usb_cleanup(yld, -ENOMEM);
0881 
0882     /* allocate usb buffers */
0883     yld->irq_data = usb_alloc_coherent(udev, USB_PKT_LEN,
0884                        GFP_KERNEL, &yld->irq_dma);
0885     if (yld->irq_data == NULL)
0886         return usb_cleanup(yld, -ENOMEM);
0887 
0888     yld->ctl_data = usb_alloc_coherent(udev, USB_PKT_LEN,
0889                        GFP_KERNEL, &yld->ctl_dma);
0890     if (!yld->ctl_data)
0891         return usb_cleanup(yld, -ENOMEM);
0892 
0893     yld->ctl_req = kmalloc(sizeof(*(yld->ctl_req)), GFP_KERNEL);
0894     if (yld->ctl_req == NULL)
0895         return usb_cleanup(yld, -ENOMEM);
0896 
0897     /* allocate urb structures */
0898     yld->urb_irq = usb_alloc_urb(0, GFP_KERNEL);
0899         if (yld->urb_irq == NULL)
0900         return usb_cleanup(yld, -ENOMEM);
0901 
0902     yld->urb_ctl = usb_alloc_urb(0, GFP_KERNEL);
0903         if (yld->urb_ctl == NULL)
0904         return usb_cleanup(yld, -ENOMEM);
0905 
0906     /* get a handle to the interrupt data pipe */
0907     pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
0908     ret = usb_maxpacket(udev, pipe);
0909     if (ret != USB_PKT_LEN)
0910         dev_err(&intf->dev, "invalid payload size %d, expected %zd\n",
0911             ret, USB_PKT_LEN);
0912 
0913     /* initialise irq urb */
0914     usb_fill_int_urb(yld->urb_irq, udev, pipe, yld->irq_data,
0915             USB_PKT_LEN,
0916             urb_irq_callback,
0917             yld, endpoint->bInterval);
0918     yld->urb_irq->transfer_dma = yld->irq_dma;
0919     yld->urb_irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
0920     yld->urb_irq->dev = udev;
0921 
0922     /* initialise ctl urb */
0923     yld->ctl_req->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE |
0924                       USB_DIR_OUT;
0925     yld->ctl_req->bRequest  = USB_REQ_SET_CONFIGURATION;
0926     yld->ctl_req->wValue    = cpu_to_le16(0x200);
0927     yld->ctl_req->wIndex    = cpu_to_le16(interface->desc.bInterfaceNumber);
0928     yld->ctl_req->wLength   = cpu_to_le16(USB_PKT_LEN);
0929 
0930     usb_fill_control_urb(yld->urb_ctl, udev, usb_sndctrlpipe(udev, 0),
0931             (void *)yld->ctl_req, yld->ctl_data, USB_PKT_LEN,
0932             urb_ctl_callback, yld);
0933     yld->urb_ctl->transfer_dma  = yld->ctl_dma;
0934     yld->urb_ctl->transfer_flags    |= URB_NO_TRANSFER_DMA_MAP;
0935     yld->urb_ctl->dev = udev;
0936 
0937     /* find out the physical bus location */
0938     usb_make_path(udev, yld->phys, sizeof(yld->phys));
0939     strlcat(yld->phys,  "/input0", sizeof(yld->phys));
0940 
0941     /* register settings for the input device */
0942     input_dev->name = nfo->name;
0943     input_dev->phys = yld->phys;
0944     usb_to_input_id(udev, &input_dev->id);
0945     input_dev->dev.parent = &intf->dev;
0946 
0947     input_set_drvdata(input_dev, yld);
0948 
0949     input_dev->open = input_open;
0950     input_dev->close = input_close;
0951     /* input_dev->event = input_ev; TODO */
0952 
0953     /* register available key events */
0954     input_dev->evbit[0] = BIT_MASK(EV_KEY);
0955     for (i = 0; i < 256; i++) {
0956         int k = map_p1k_to_key(i);
0957         if (k >= 0) {
0958             set_bit(k & 0xff, input_dev->keybit);
0959             if (k >> 8)
0960                 set_bit(k >> 8, input_dev->keybit);
0961         }
0962     }
0963 
0964     ret = input_register_device(yld->idev);
0965     if (ret)
0966         return usb_cleanup(yld, ret);
0967 
0968     usb_set_intfdata(intf, yld);
0969 
0970     /* clear visible elements */
0971     for (i = 0; i < ARRAY_SIZE(lcdMap); i++)
0972         setChar(yld, i, ' ');
0973 
0974     /* display driver version on LCD line 3 */
0975     store_line3(&intf->dev, NULL,
0976             DRIVER_VERSION, sizeof(DRIVER_VERSION));
0977 
0978     /* Register sysfs hooks (don't care about failure) */
0979     ret = sysfs_create_group(&intf->dev.kobj, &yld_attr_group);
0980     return 0;
0981 }
0982 
0983 static struct usb_driver yealink_driver = {
0984     .name       = "yealink",
0985     .probe      = usb_probe,
0986     .disconnect = usb_disconnect,
0987     .id_table   = usb_table,
0988 };
0989 
0990 module_usb_driver(yealink_driver);
0991 
0992 MODULE_DEVICE_TABLE (usb, usb_table);
0993 
0994 MODULE_AUTHOR("Henk Vergonet");
0995 MODULE_DESCRIPTION("Yealink phone driver");
0996 MODULE_LICENSE("GPL");