Version:  2.0.40 2.2.26 2.4.37 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16

Linux/drivers/input/misc/yealink.c

  1 /*
  2  * drivers/usb/input/yealink.c
  3  *
  4  * Copyright (c) 2005 Henk Vergonet <Henk.Vergonet@gmail.com>
  5  *
  6  * This program is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU General Public License as
  8  * published by the Free Software Foundation; either version 2 of
  9  * the License, or (at your option) any later version.
 10  *
 11  * This program is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14  * GNU General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU General Public License
 17  * along with this program; if not, write to the Free Software
 18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 19  */
 20 /*
 21  * Description:
 22  *   Driver for the USB-P1K voip usb phone.
 23  *   This device is produced by Yealink Network Technology Co Ltd
 24  *   but may be branded under several names:
 25  *      - Yealink usb-p1k
 26  *      - Tiptel 115
 27  *      - ...
 28  *
 29  * This driver is based on:
 30  *   - the usbb2k-api   http://savannah.nongnu.org/projects/usbb2k-api/
 31  *   - information from http://memeteau.free.fr/usbb2k
 32  *   - the xpad-driver  drivers/input/joystick/xpad.c
 33  *
 34  * Thanks to:
 35  *   - Olivier Vandorpe, for providing the usbb2k-api.
 36  *   - Martin Diehl, for spotting my memory allocation bug.
 37  *
 38  * History:
 39  *   20050527 henk      First version, functional keyboard. Keyboard events
 40  *                      will pop-up on the ../input/eventX bus.
 41  *   20050531 henk      Added led, LCD, dialtone and sysfs interface.
 42  *   20050610 henk      Cleanups, make it ready for public consumption.
 43  *   20050630 henk      Cleanups, fixes in response to comments.
 44  *   20050701 henk      sysfs write serialisation, fix potential unload races
 45  *   20050801 henk      Added ringtone, restructure USB
 46  *   20050816 henk      Merge 2.6.13-rc6
 47  */
 48 
 49 #include <linux/kernel.h>
 50 #include <linux/slab.h>
 51 #include <linux/module.h>
 52 #include <linux/rwsem.h>
 53 #include <linux/usb/input.h>
 54 #include <linux/map_to_7segment.h>
 55 
 56 #include "yealink.h"
 57 
 58 #define DRIVER_VERSION "yld-20051230"
 59 #define DRIVER_AUTHOR "Henk Vergonet"
 60 #define DRIVER_DESC "Yealink phone driver"
 61 
 62 #define YEALINK_POLLING_FREQUENCY       10      /* in [Hz] */
 63 
 64 struct yld_status {
 65         u8      lcd[24];
 66         u8      led;
 67         u8      dialtone;
 68         u8      ringtone;
 69         u8      keynum;
 70 } __attribute__ ((packed));
 71 
 72 /*
 73  * Register the LCD segment and icon map
 74  */
 75 #define _LOC(k,l)       { .a = (k), .m = (l) }
 76 #define _SEG(t, a, am, b, bm, c, cm, d, dm, e, em, f, fm, g, gm)        \
 77         { .type = (t),                                                  \
 78           .u = { .s = { _LOC(a, am), _LOC(b, bm), _LOC(c, cm),          \
 79                         _LOC(d, dm), _LOC(e, em), _LOC(g, gm),          \
 80                         _LOC(f, fm) } } }
 81 #define _PIC(t, h, hm, n)                                               \
 82         { .type = (t),                                                  \
 83           .u = { .p = { .name = (n), .a = (h), .m = (hm) } } }
 84 
 85 static const struct lcd_segment_map {
 86         char    type;
 87         union {
 88                 struct pictogram_map {
 89                         u8      a,m;
 90                         char    name[10];
 91                 }       p;
 92                 struct segment_map {
 93                         u8      a,m;
 94                 } s[7];
 95         } u;
 96 } lcdMap[] = {
 97 #include "yealink.h"
 98 };
 99 
100 struct yealink_dev {
101         struct input_dev *idev;         /* input device */
102         struct usb_device *udev;        /* usb device */
103         struct usb_interface *intf;     /* usb interface */
104 
105         /* irq input channel */
106         struct yld_ctl_packet   *irq_data;
107         dma_addr_t              irq_dma;
108         struct urb              *urb_irq;
109 
110         /* control output channel */
111         struct yld_ctl_packet   *ctl_data;
112         dma_addr_t              ctl_dma;
113         struct usb_ctrlrequest  *ctl_req;
114         struct urb              *urb_ctl;
115 
116         char phys[64];                  /* physical device path */
117 
118         u8 lcdMap[ARRAY_SIZE(lcdMap)];  /* state of LCD, LED ... */
119         int key_code;                   /* last reported key     */
120 
121         unsigned int shutdown:1;
122 
123         int     stat_ix;
124         union {
125                 struct yld_status s;
126                 u8                b[sizeof(struct yld_status)];
127         } master, copy;
128 };
129 
130 
131 /*******************************************************************************
132  * Yealink lcd interface
133  ******************************************************************************/
134 
135 /*
136  * Register a default 7 segment character set
137  */
138 static SEG7_DEFAULT_MAP(map_seg7);
139 
140  /* Display a char,
141   * char '\9' and '\n' are placeholders and do not overwrite the original text.
142   * A space will always hide an icon.
143   */
144 static int setChar(struct yealink_dev *yld, int el, int chr)
145 {
146         int i, a, m, val;
147 
148         if (el >= ARRAY_SIZE(lcdMap))
149                 return -EINVAL;
150 
151         if (chr == '\t' || chr == '\n')
152             return 0;
153 
154         yld->lcdMap[el] = chr;
155 
156         if (lcdMap[el].type == '.') {
157                 a = lcdMap[el].u.p.a;
158                 m = lcdMap[el].u.p.m;
159                 if (chr != ' ')
160                         yld->master.b[a] |= m;
161                 else
162                         yld->master.b[a] &= ~m;
163                 return 0;
164         }
165 
166         val = map_to_seg7(&map_seg7, chr);
167         for (i = 0; i < ARRAY_SIZE(lcdMap[0].u.s); i++) {
168                 m = lcdMap[el].u.s[i].m;
169 
170                 if (m == 0)
171                         continue;
172 
173                 a = lcdMap[el].u.s[i].a;
174                 if (val & 1)
175                         yld->master.b[a] |= m;
176                 else
177                         yld->master.b[a] &= ~m;
178                 val = val >> 1;
179         }
180         return 0;
181 };
182 
183 /*******************************************************************************
184  * Yealink key interface
185  ******************************************************************************/
186 
187 /* Map device buttons to internal key events.
188  *
189  * USB-P1K button layout:
190  *
191  *             up
192  *       IN           OUT
193  *            down
194  *
195  *     pickup   C    hangup
196  *       1      2      3
197  *       4      5      6
198  *       7      8      9
199  *       *      0      #
200  *
201  * The "up" and "down" keys, are symbolised by arrows on the button.
202  * The "pickup" and "hangup" keys are symbolised by a green and red phone
203  * on the button.
204  */
205 static int map_p1k_to_key(int scancode)
206 {
207         switch(scancode) {              /* phone key:   */
208         case 0x23: return KEY_LEFT;     /*   IN         */
209         case 0x33: return KEY_UP;       /*   up         */
210         case 0x04: return KEY_RIGHT;    /*   OUT        */
211         case 0x24: return KEY_DOWN;     /*   down       */
212         case 0x03: return KEY_ENTER;    /*   pickup     */
213         case 0x14: return KEY_BACKSPACE; /*  C          */
214         case 0x13: return KEY_ESC;      /*   hangup     */
215         case 0x00: return KEY_1;        /*   1          */
216         case 0x01: return KEY_2;        /*   2          */
217         case 0x02: return KEY_3;        /*   3          */
218         case 0x10: return KEY_4;        /*   4          */
219         case 0x11: return KEY_5;        /*   5          */
220         case 0x12: return KEY_6;        /*   6          */
221         case 0x20: return KEY_7;        /*   7          */
222         case 0x21: return KEY_8;        /*   8          */
223         case 0x22: return KEY_9;        /*   9          */
224         case 0x30: return KEY_KPASTERISK; /* *          */
225         case 0x31: return KEY_0;        /*   0          */
226         case 0x32: return KEY_LEFTSHIFT |
227                           KEY_3 << 8;   /*   #          */
228         }
229         return -EINVAL;
230 }
231 
232 /* Completes a request by converting the data into events for the
233  * input subsystem.
234  *
235  * The key parameter can be cascaded: key2 << 8 | key1
236  */
237 static void report_key(struct yealink_dev *yld, int key)
238 {
239         struct input_dev *idev = yld->idev;
240 
241         if (yld->key_code >= 0) {
242                 /* old key up */
243                 input_report_key(idev, yld->key_code & 0xff, 0);
244                 if (yld->key_code >> 8)
245                         input_report_key(idev, yld->key_code >> 8, 0);
246         }
247 
248         yld->key_code = key;
249         if (key >= 0) {
250                 /* new valid key */
251                 input_report_key(idev, key & 0xff, 1);
252                 if (key >> 8)
253                         input_report_key(idev, key >> 8, 1);
254         }
255         input_sync(idev);
256 }
257 
258 /*******************************************************************************
259  * Yealink usb communication interface
260  ******************************************************************************/
261 
262 static int yealink_cmd(struct yealink_dev *yld, struct yld_ctl_packet *p)
263 {
264         u8      *buf = (u8 *)p;
265         int     i;
266         u8      sum = 0;
267 
268         for(i=0; i<USB_PKT_LEN-1; i++)
269                 sum -= buf[i];
270         p->sum = sum;
271         return usb_control_msg(yld->udev,
272                         usb_sndctrlpipe(yld->udev, 0),
273                         USB_REQ_SET_CONFIGURATION,
274                         USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
275                         0x200, 3,
276                         p, sizeof(*p),
277                         USB_CTRL_SET_TIMEOUT);
278 }
279 
280 static u8 default_ringtone[] = {
281         0xEF,                   /* volume [0-255] */
282         0xFB, 0x1E, 0x00, 0x0C, /* 1250 [hz], 12/100 [s] */
283         0xFC, 0x18, 0x00, 0x0C, /* 1000 [hz], 12/100 [s] */
284         0xFB, 0x1E, 0x00, 0x0C,
285         0xFC, 0x18, 0x00, 0x0C,
286         0xFB, 0x1E, 0x00, 0x0C,
287         0xFC, 0x18, 0x00, 0x0C,
288         0xFB, 0x1E, 0x00, 0x0C,
289         0xFC, 0x18, 0x00, 0x0C,
290         0xFF, 0xFF, 0x01, 0x90, /* silent, 400/100 [s] */
291         0x00, 0x00              /* end of sequence */
292 };
293 
294 static int yealink_set_ringtone(struct yealink_dev *yld, u8 *buf, size_t size)
295 {
296         struct yld_ctl_packet *p = yld->ctl_data;
297         int     ix, len;
298 
299         if (size <= 0)
300                 return -EINVAL;
301 
302         /* Set the ringtone volume */
303         memset(yld->ctl_data, 0, sizeof(*(yld->ctl_data)));
304         yld->ctl_data->cmd      = CMD_RING_VOLUME;
305         yld->ctl_data->size     = 1;
306         yld->ctl_data->data[0]  = buf[0];
307         yealink_cmd(yld, p);
308 
309         buf++;
310         size--;
311 
312         p->cmd = CMD_RING_NOTE;
313         ix = 0;
314         while (size != ix) {
315                 len = size - ix;
316                 if (len > sizeof(p->data))
317                         len = sizeof(p->data);
318                 p->size   = len;
319                 p->offset = cpu_to_be16(ix);
320                 memcpy(p->data, &buf[ix], len);
321                 yealink_cmd(yld, p);
322                 ix += len;
323         }
324         return 0;
325 }
326 
327 /* keep stat_master & stat_copy in sync.
328  */
329 static int yealink_do_idle_tasks(struct yealink_dev *yld)
330 {
331         u8 val;
332         int i, ix, len;
333 
334         ix = yld->stat_ix;
335 
336         memset(yld->ctl_data, 0, sizeof(*(yld->ctl_data)));
337         yld->ctl_data->cmd  = CMD_KEYPRESS;
338         yld->ctl_data->size = 1;
339         yld->ctl_data->sum  = 0xff - CMD_KEYPRESS;
340 
341         /* If state update pointer wraps do a KEYPRESS first. */
342         if (ix >= sizeof(yld->master)) {
343                 yld->stat_ix = 0;
344                 return 0;
345         }
346 
347         /* find update candidates: copy != master */
348         do {
349                 val = yld->master.b[ix];
350                 if (val != yld->copy.b[ix])
351                         goto send_update;
352         } while (++ix < sizeof(yld->master));
353 
354         /* nothing todo, wait a bit and poll for a KEYPRESS */
355         yld->stat_ix = 0;
356         /* TODO how can we wait abit. ??
357          * msleep_interruptible(1000 / YEALINK_POLLING_FREQUENCY);
358          */
359         return 0;
360 
361 send_update:
362 
363         /* Setup an appropriate update request */
364         yld->copy.b[ix] = val;
365         yld->ctl_data->data[0] = val;
366 
367         switch(ix) {
368         case offsetof(struct yld_status, led):
369                 yld->ctl_data->cmd      = CMD_LED;
370                 yld->ctl_data->sum      = -1 - CMD_LED - val;
371                 break;
372         case offsetof(struct yld_status, dialtone):
373                 yld->ctl_data->cmd      = CMD_DIALTONE;
374                 yld->ctl_data->sum      = -1 - CMD_DIALTONE - val;
375                 break;
376         case offsetof(struct yld_status, ringtone):
377                 yld->ctl_data->cmd      = CMD_RINGTONE;
378                 yld->ctl_data->sum      = -1 - CMD_RINGTONE - val;
379                 break;
380         case offsetof(struct yld_status, keynum):
381                 val--;
382                 val &= 0x1f;
383                 yld->ctl_data->cmd      = CMD_SCANCODE;
384                 yld->ctl_data->offset   = cpu_to_be16(val);
385                 yld->ctl_data->data[0]  = 0;
386                 yld->ctl_data->sum      = -1 - CMD_SCANCODE - val;
387                 break;
388         default:
389                 len = sizeof(yld->master.s.lcd) - ix;
390                 if (len > sizeof(yld->ctl_data->data))
391                         len = sizeof(yld->ctl_data->data);
392 
393                 /* Combine up to <len> consecutive LCD bytes in a singe request
394                  */
395                 yld->ctl_data->cmd      = CMD_LCD;
396                 yld->ctl_data->offset   = cpu_to_be16(ix);
397                 yld->ctl_data->size     = len;
398                 yld->ctl_data->sum      = -CMD_LCD - ix - val - len;
399                 for(i=1; i<len; i++) {
400                         ix++;
401                         val = yld->master.b[ix];
402                         yld->copy.b[ix]         = val;
403                         yld->ctl_data->data[i]  = val;
404                         yld->ctl_data->sum     -= val;
405                 }
406         }
407         yld->stat_ix = ix + 1;
408         return 1;
409 }
410 
411 /* Decide on how to handle responses
412  *
413  * The state transition diagram is somethhing like:
414  *
415  *          syncState<--+
416  *               |      |
417  *               |    idle
418  *              \|/     |
419  * init --ok--> waitForKey --ok--> getKey
420  *  ^               ^                |
421  *  |               +-------ok-------+
422  * error,start
423  *
424  */
425 static void urb_irq_callback(struct urb *urb)
426 {
427         struct yealink_dev *yld = urb->context;
428         int ret, status = urb->status;
429 
430         if (status)
431                 dev_err(&yld->intf->dev, "%s - urb status %d\n",
432                         __func__, status);
433 
434         switch (yld->irq_data->cmd) {
435         case CMD_KEYPRESS:
436 
437                 yld->master.s.keynum = yld->irq_data->data[0];
438                 break;
439 
440         case CMD_SCANCODE:
441                 dev_dbg(&yld->intf->dev, "get scancode %x\n",
442                         yld->irq_data->data[0]);
443 
444                 report_key(yld, map_p1k_to_key(yld->irq_data->data[0]));
445                 break;
446 
447         default:
448                 dev_err(&yld->intf->dev, "unexpected response %x\n",
449                         yld->irq_data->cmd);
450         }
451 
452         yealink_do_idle_tasks(yld);
453 
454         if (!yld->shutdown) {
455                 ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
456                 if (ret && ret != -EPERM)
457                         dev_err(&yld->intf->dev,
458                                 "%s - usb_submit_urb failed %d\n",
459                                 __func__, ret);
460         }
461 }
462 
463 static void urb_ctl_callback(struct urb *urb)
464 {
465         struct yealink_dev *yld = urb->context;
466         int ret = 0, status = urb->status;
467 
468         if (status)
469                 dev_err(&yld->intf->dev, "%s - urb status %d\n",
470                         __func__, status);
471 
472         switch (yld->ctl_data->cmd) {
473         case CMD_KEYPRESS:
474         case CMD_SCANCODE:
475                 /* ask for a response */
476                 if (!yld->shutdown)
477                         ret = usb_submit_urb(yld->urb_irq, GFP_ATOMIC);
478                 break;
479         default:
480                 /* send new command */
481                 yealink_do_idle_tasks(yld);
482                 if (!yld->shutdown)
483                         ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
484                 break;
485         }
486 
487         if (ret && ret != -EPERM)
488                 dev_err(&yld->intf->dev, "%s - usb_submit_urb failed %d\n",
489                         __func__, ret);
490 }
491 
492 /*******************************************************************************
493  * input event interface
494  ******************************************************************************/
495 
496 /* TODO should we issue a ringtone on a SND_BELL event?
497 static int input_ev(struct input_dev *dev, unsigned int type,
498                 unsigned int code, int value)
499 {
500 
501         if (type != EV_SND)
502                 return -EINVAL;
503 
504         switch (code) {
505         case SND_BELL:
506         case SND_TONE:
507                 break;
508         default:
509                 return -EINVAL;
510         }
511 
512         return 0;
513 }
514 */
515 
516 static int input_open(struct input_dev *dev)
517 {
518         struct yealink_dev *yld = input_get_drvdata(dev);
519         int i, ret;
520 
521         dev_dbg(&yld->intf->dev, "%s\n", __func__);
522 
523         /* force updates to device */
524         for (i = 0; i<sizeof(yld->master); i++)
525                 yld->copy.b[i] = ~yld->master.b[i];
526         yld->key_code = -1;     /* no keys pressed */
527 
528         yealink_set_ringtone(yld, default_ringtone, sizeof(default_ringtone));
529 
530         /* issue INIT */
531         memset(yld->ctl_data, 0, sizeof(*(yld->ctl_data)));
532         yld->ctl_data->cmd      = CMD_INIT;
533         yld->ctl_data->size     = 10;
534         yld->ctl_data->sum      = 0x100-CMD_INIT-10;
535         if ((ret = usb_submit_urb(yld->urb_ctl, GFP_KERNEL)) != 0) {
536                 dev_dbg(&yld->intf->dev,
537                         "%s - usb_submit_urb failed with result %d\n",
538                         __func__, ret);
539                 return ret;
540         }
541         return 0;
542 }
543 
544 static void input_close(struct input_dev *dev)
545 {
546         struct yealink_dev *yld = input_get_drvdata(dev);
547 
548         yld->shutdown = 1;
549         /*
550          * Make sure the flag is seen by other CPUs before we start
551          * killing URBs so new URBs won't be submitted
552          */
553         smp_wmb();
554 
555         usb_kill_urb(yld->urb_ctl);
556         usb_kill_urb(yld->urb_irq);
557 
558         yld->shutdown = 0;
559         smp_wmb();
560 }
561 
562 /*******************************************************************************
563  * sysfs interface
564  ******************************************************************************/
565 
566 static DECLARE_RWSEM(sysfs_rwsema);
567 
568 /* Interface to the 7-segments translation table aka. char set.
569  */
570 static ssize_t show_map(struct device *dev, struct device_attribute *attr,
571                                 char *buf)
572 {
573         memcpy(buf, &map_seg7, sizeof(map_seg7));
574         return sizeof(map_seg7);
575 }
576 
577 static ssize_t store_map(struct device *dev, struct device_attribute *attr,
578                                 const char *buf, size_t cnt)
579 {
580         if (cnt != sizeof(map_seg7))
581                 return -EINVAL;
582         memcpy(&map_seg7, buf, sizeof(map_seg7));
583         return sizeof(map_seg7);
584 }
585 
586 /* Interface to the LCD.
587  */
588 
589 /* Reading /sys/../lineX will return the format string with its settings:
590  *
591  * Example:
592  * cat ./line3
593  * 888888888888
594  * Linux Rocks!
595  */
596 static ssize_t show_line(struct device *dev, char *buf, int a, int b)
597 {
598         struct yealink_dev *yld;
599         int i;
600 
601         down_read(&sysfs_rwsema);
602         yld = dev_get_drvdata(dev);
603         if (yld == NULL) {
604                 up_read(&sysfs_rwsema);
605                 return -ENODEV;
606         }
607 
608         for (i = a; i < b; i++)
609                 *buf++ = lcdMap[i].type;
610         *buf++ = '\n';
611         for (i = a; i < b; i++)
612                 *buf++ = yld->lcdMap[i];
613         *buf++ = '\n';
614         *buf = 0;
615 
616         up_read(&sysfs_rwsema);
617         return 3 + ((b - a) << 1);
618 }
619 
620 static ssize_t show_line1(struct device *dev, struct device_attribute *attr,
621                         char *buf)
622 {
623         return show_line(dev, buf, LCD_LINE1_OFFSET, LCD_LINE2_OFFSET);
624 }
625 
626 static ssize_t show_line2(struct device *dev, struct device_attribute *attr,
627                         char *buf)
628 {
629         return show_line(dev, buf, LCD_LINE2_OFFSET, LCD_LINE3_OFFSET);
630 }
631 
632 static ssize_t show_line3(struct device *dev, struct device_attribute *attr,
633                         char *buf)
634 {
635         return show_line(dev, buf, LCD_LINE3_OFFSET, LCD_LINE4_OFFSET);
636 }
637 
638 /* Writing to /sys/../lineX will set the coresponding LCD line.
639  * - Excess characters are ignored.
640  * - If less characters are written than allowed, the remaining digits are
641  *   unchanged.
642  * - The '\n' or '\t' char is a placeholder, it does not overwrite the
643  *   original content.
644  */
645 static ssize_t store_line(struct device *dev, const char *buf, size_t count,
646                 int el, size_t len)
647 {
648         struct yealink_dev *yld;
649         int i;
650 
651         down_write(&sysfs_rwsema);
652         yld = dev_get_drvdata(dev);
653         if (yld == NULL) {
654                 up_write(&sysfs_rwsema);
655                 return -ENODEV;
656         }
657 
658         if (len > count)
659                 len = count;
660         for (i = 0; i < len; i++)
661                 setChar(yld, el++, buf[i]);
662 
663         up_write(&sysfs_rwsema);
664         return count;
665 }
666 
667 static ssize_t store_line1(struct device *dev, struct device_attribute *attr,
668                                 const char *buf, size_t count)
669 {
670         return store_line(dev, buf, count, LCD_LINE1_OFFSET, LCD_LINE1_SIZE);
671 }
672 
673 static ssize_t store_line2(struct device *dev, struct device_attribute *attr,
674                                 const char *buf, size_t count)
675 {
676         return store_line(dev, buf, count, LCD_LINE2_OFFSET, LCD_LINE2_SIZE);
677 }
678 
679 static ssize_t store_line3(struct device *dev, struct device_attribute *attr,
680                                 const char *buf, size_t count)
681 {
682         return store_line(dev, buf, count, LCD_LINE3_OFFSET, LCD_LINE3_SIZE);
683 }
684 
685 /* Interface to visible and audible "icons", these include:
686  * pictures on the LCD, the LED, and the dialtone signal.
687  */
688 
689 /* Get a list of "switchable elements" with their current state. */
690 static ssize_t get_icons(struct device *dev, struct device_attribute *attr,
691                         char *buf)
692 {
693         struct yealink_dev *yld;
694         int i, ret = 1;
695 
696         down_read(&sysfs_rwsema);
697         yld = dev_get_drvdata(dev);
698         if (yld == NULL) {
699                 up_read(&sysfs_rwsema);
700                 return -ENODEV;
701         }
702 
703         for (i = 0; i < ARRAY_SIZE(lcdMap); i++) {
704                 if (lcdMap[i].type != '.')
705                         continue;
706                 ret += sprintf(&buf[ret], "%s %s\n",
707                                 yld->lcdMap[i] == ' ' ? "  " : "on",
708                                 lcdMap[i].u.p.name);
709         }
710         up_read(&sysfs_rwsema);
711         return ret;
712 }
713 
714 /* Change the visibility of a particular element. */
715 static ssize_t set_icon(struct device *dev, const char *buf, size_t count,
716                         int chr)
717 {
718         struct yealink_dev *yld;
719         int i;
720 
721         down_write(&sysfs_rwsema);
722         yld = dev_get_drvdata(dev);
723         if (yld == NULL) {
724                 up_write(&sysfs_rwsema);
725                 return -ENODEV;
726         }
727 
728         for (i = 0; i < ARRAY_SIZE(lcdMap); i++) {
729                 if (lcdMap[i].type != '.')
730                         continue;
731                 if (strncmp(buf, lcdMap[i].u.p.name, count) == 0) {
732                         setChar(yld, i, chr);
733                         break;
734                 }
735         }
736 
737         up_write(&sysfs_rwsema);
738         return count;
739 }
740 
741 static ssize_t show_icon(struct device *dev, struct device_attribute *attr,
742                 const char *buf, size_t count)
743 {
744         return set_icon(dev, buf, count, buf[0]);
745 }
746 
747 static ssize_t hide_icon(struct device *dev, struct device_attribute *attr,
748                 const char *buf, size_t count)
749 {
750         return set_icon(dev, buf, count, ' ');
751 }
752 
753 /* Upload a ringtone to the device.
754  */
755 
756 /* Stores raw ringtone data in the phone */
757 static ssize_t store_ringtone(struct device *dev,
758                 struct device_attribute *attr,
759                 const char *buf, size_t count)
760 {
761         struct yealink_dev *yld;
762 
763         down_write(&sysfs_rwsema);
764         yld = dev_get_drvdata(dev);
765         if (yld == NULL) {
766                 up_write(&sysfs_rwsema);
767                 return -ENODEV;
768         }
769 
770         /* TODO locking with async usb control interface??? */
771         yealink_set_ringtone(yld, (char *)buf, count);
772         up_write(&sysfs_rwsema);
773         return count;
774 }
775 
776 #define _M444   S_IRUGO
777 #define _M664   S_IRUGO|S_IWUSR|S_IWGRP
778 #define _M220   S_IWUSR|S_IWGRP
779 
780 static DEVICE_ATTR(map_seg7     , _M664, show_map       , store_map     );
781 static DEVICE_ATTR(line1        , _M664, show_line1     , store_line1   );
782 static DEVICE_ATTR(line2        , _M664, show_line2     , store_line2   );
783 static DEVICE_ATTR(line3        , _M664, show_line3     , store_line3   );
784 static DEVICE_ATTR(get_icons    , _M444, get_icons      , NULL          );
785 static DEVICE_ATTR(show_icon    , _M220, NULL           , show_icon     );
786 static DEVICE_ATTR(hide_icon    , _M220, NULL           , hide_icon     );
787 static DEVICE_ATTR(ringtone     , _M220, NULL           , store_ringtone);
788 
789 static struct attribute *yld_attributes[] = {
790         &dev_attr_line1.attr,
791         &dev_attr_line2.attr,
792         &dev_attr_line3.attr,
793         &dev_attr_get_icons.attr,
794         &dev_attr_show_icon.attr,
795         &dev_attr_hide_icon.attr,
796         &dev_attr_map_seg7.attr,
797         &dev_attr_ringtone.attr,
798         NULL
799 };
800 
801 static struct attribute_group yld_attr_group = {
802         .attrs = yld_attributes
803 };
804 
805 /*******************************************************************************
806  * Linux interface and usb initialisation
807  ******************************************************************************/
808 
809 struct driver_info {
810         char *name;
811 };
812 
813 static const struct driver_info info_P1K = {
814         .name   = "Yealink usb-p1k",
815 };
816 
817 static const struct usb_device_id usb_table [] = {
818         {
819                 .match_flags            = USB_DEVICE_ID_MATCH_DEVICE |
820                                                 USB_DEVICE_ID_MATCH_INT_INFO,
821                 .idVendor               = 0x6993,
822                 .idProduct              = 0xb001,
823                 .bInterfaceClass        = USB_CLASS_HID,
824                 .bInterfaceSubClass     = 0,
825                 .bInterfaceProtocol     = 0,
826                 .driver_info            = (kernel_ulong_t)&info_P1K
827         },
828         { }
829 };
830 
831 static int usb_cleanup(struct yealink_dev *yld, int err)
832 {
833         if (yld == NULL)
834                 return err;
835 
836         if (yld->idev) {
837                 if (err)
838                         input_free_device(yld->idev);
839                 else
840                         input_unregister_device(yld->idev);
841         }
842 
843         usb_free_urb(yld->urb_irq);
844         usb_free_urb(yld->urb_ctl);
845 
846         kfree(yld->ctl_req);
847         usb_free_coherent(yld->udev, USB_PKT_LEN, yld->ctl_data, yld->ctl_dma);
848         usb_free_coherent(yld->udev, USB_PKT_LEN, yld->irq_data, yld->irq_dma);
849 
850         kfree(yld);
851         return err;
852 }
853 
854 static void usb_disconnect(struct usb_interface *intf)
855 {
856         struct yealink_dev *yld;
857 
858         down_write(&sysfs_rwsema);
859         yld = usb_get_intfdata(intf);
860         sysfs_remove_group(&intf->dev.kobj, &yld_attr_group);
861         usb_set_intfdata(intf, NULL);
862         up_write(&sysfs_rwsema);
863 
864         usb_cleanup(yld, 0);
865 }
866 
867 static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
868 {
869         struct usb_device *udev = interface_to_usbdev (intf);
870         struct driver_info *nfo = (struct driver_info *)id->driver_info;
871         struct usb_host_interface *interface;
872         struct usb_endpoint_descriptor *endpoint;
873         struct yealink_dev *yld;
874         struct input_dev *input_dev;
875         int ret, pipe, i;
876 
877         interface = intf->cur_altsetting;
878         endpoint = &interface->endpoint[0].desc;
879         if (!usb_endpoint_is_int_in(endpoint))
880                 return -ENODEV;
881 
882         yld = kzalloc(sizeof(struct yealink_dev), GFP_KERNEL);
883         if (!yld)
884                 return -ENOMEM;
885 
886         yld->udev = udev;
887         yld->intf = intf;
888 
889         yld->idev = input_dev = input_allocate_device();
890         if (!input_dev)
891                 return usb_cleanup(yld, -ENOMEM);
892 
893         /* allocate usb buffers */
894         yld->irq_data = usb_alloc_coherent(udev, USB_PKT_LEN,
895                                            GFP_ATOMIC, &yld->irq_dma);
896         if (yld->irq_data == NULL)
897                 return usb_cleanup(yld, -ENOMEM);
898 
899         yld->ctl_data = usb_alloc_coherent(udev, USB_PKT_LEN,
900                                            GFP_ATOMIC, &yld->ctl_dma);
901         if (!yld->ctl_data)
902                 return usb_cleanup(yld, -ENOMEM);
903 
904         yld->ctl_req = kmalloc(sizeof(*(yld->ctl_req)), GFP_KERNEL);
905         if (yld->ctl_req == NULL)
906                 return usb_cleanup(yld, -ENOMEM);
907 
908         /* allocate urb structures */
909         yld->urb_irq = usb_alloc_urb(0, GFP_KERNEL);
910         if (yld->urb_irq == NULL)
911                 return usb_cleanup(yld, -ENOMEM);
912 
913         yld->urb_ctl = usb_alloc_urb(0, GFP_KERNEL);
914         if (yld->urb_ctl == NULL)
915                 return usb_cleanup(yld, -ENOMEM);
916 
917         /* get a handle to the interrupt data pipe */
918         pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
919         ret = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
920         if (ret != USB_PKT_LEN)
921                 dev_err(&intf->dev, "invalid payload size %d, expected %zd\n",
922                         ret, USB_PKT_LEN);
923 
924         /* initialise irq urb */
925         usb_fill_int_urb(yld->urb_irq, udev, pipe, yld->irq_data,
926                         USB_PKT_LEN,
927                         urb_irq_callback,
928                         yld, endpoint->bInterval);
929         yld->urb_irq->transfer_dma = yld->irq_dma;
930         yld->urb_irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
931         yld->urb_irq->dev = udev;
932 
933         /* initialise ctl urb */
934         yld->ctl_req->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE |
935                                       USB_DIR_OUT;
936         yld->ctl_req->bRequest  = USB_REQ_SET_CONFIGURATION;
937         yld->ctl_req->wValue    = cpu_to_le16(0x200);
938         yld->ctl_req->wIndex    = cpu_to_le16(interface->desc.bInterfaceNumber);
939         yld->ctl_req->wLength   = cpu_to_le16(USB_PKT_LEN);
940 
941         usb_fill_control_urb(yld->urb_ctl, udev, usb_sndctrlpipe(udev, 0),
942                         (void *)yld->ctl_req, yld->ctl_data, USB_PKT_LEN,
943                         urb_ctl_callback, yld);
944         yld->urb_ctl->transfer_dma      = yld->ctl_dma;
945         yld->urb_ctl->transfer_flags    |= URB_NO_TRANSFER_DMA_MAP;
946         yld->urb_ctl->dev = udev;
947 
948         /* find out the physical bus location */
949         usb_make_path(udev, yld->phys, sizeof(yld->phys));
950         strlcat(yld->phys,  "/input0", sizeof(yld->phys));
951 
952         /* register settings for the input device */
953         input_dev->name = nfo->name;
954         input_dev->phys = yld->phys;
955         usb_to_input_id(udev, &input_dev->id);
956         input_dev->dev.parent = &intf->dev;
957 
958         input_set_drvdata(input_dev, yld);
959 
960         input_dev->open = input_open;
961         input_dev->close = input_close;
962         /* input_dev->event = input_ev; TODO */
963 
964         /* register available key events */
965         input_dev->evbit[0] = BIT_MASK(EV_KEY);
966         for (i = 0; i < 256; i++) {
967                 int k = map_p1k_to_key(i);
968                 if (k >= 0) {
969                         set_bit(k & 0xff, input_dev->keybit);
970                         if (k >> 8)
971                                 set_bit(k >> 8, input_dev->keybit);
972                 }
973         }
974 
975         ret = input_register_device(yld->idev);
976         if (ret)
977                 return usb_cleanup(yld, ret);
978 
979         usb_set_intfdata(intf, yld);
980 
981         /* clear visible elements */
982         for (i = 0; i < ARRAY_SIZE(lcdMap); i++)
983                 setChar(yld, i, ' ');
984 
985         /* display driver version on LCD line 3 */
986         store_line3(&intf->dev, NULL,
987                         DRIVER_VERSION, sizeof(DRIVER_VERSION));
988 
989         /* Register sysfs hooks (don't care about failure) */
990         ret = sysfs_create_group(&intf->dev.kobj, &yld_attr_group);
991         return 0;
992 }
993 
994 static struct usb_driver yealink_driver = {
995         .name           = "yealink",
996         .probe          = usb_probe,
997         .disconnect     = usb_disconnect,
998         .id_table       = usb_table,
999 };
1000 
1001 module_usb_driver(yealink_driver);
1002 
1003 MODULE_DEVICE_TABLE (usb, usb_table);
1004 
1005 MODULE_AUTHOR(DRIVER_AUTHOR);
1006 MODULE_DESCRIPTION(DRIVER_DESC);
1007 MODULE_LICENSE("GPL");
1008 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us