Version:  2.0.40 2.2.26 2.4.37 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10

Linux/drivers/staging/media/lirc/lirc_imon.c

  1 /*
  2  *   lirc_imon.c:  LIRC/VFD/LCD driver for SoundGraph iMON IR/VFD/LCD
  3  *                 including the iMON PAD model
  4  *
  5  *   Copyright(C) 2004  Venky Raju(dev@venky.ws)
  6  *   Copyright(C) 2009  Jarod Wilson <jarod@wilsonet.com>
  7  *
  8  *   lirc_imon is free software; you can redistribute it and/or modify
  9  *   it under the terms of the GNU General Public License as published by
 10  *   the Free Software Foundation; either version 2 of the License, or
 11  *   (at your option) any later version.
 12  *
 13  *   This program is distributed in the hope that it will be useful,
 14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16  *   GNU General Public License for more details.
 17  *
 18  *   You should have received a copy of the GNU General Public License
 19  *   along with this program; if not, write to the Free Software
 20  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 21  */
 22 
 23 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 24 
 25 #include <linux/errno.h>
 26 #include <linux/kernel.h>
 27 #include <linux/module.h>
 28 #include <linux/slab.h>
 29 #include <linux/uaccess.h>
 30 #include <linux/usb.h>
 31 
 32 #include <media/lirc.h>
 33 #include <media/lirc_dev.h>
 34 
 35 #define MOD_AUTHOR      "Venky Raju <dev@venky.ws>"
 36 #define MOD_DESC        "Driver for SoundGraph iMON MultiMedia IR/Display"
 37 #define MOD_NAME        "lirc_imon"
 38 #define MOD_VERSION     "0.8"
 39 
 40 #define DISPLAY_MINOR_BASE      144
 41 #define DEVICE_NAME     "lcd%d"
 42 
 43 #define BUF_CHUNK_SIZE  4
 44 #define BUF_SIZE        128
 45 
 46 #define BIT_DURATION    250     /* each bit received is 250us */
 47 
 48 /*** P R O T O T Y P E S ***/
 49 
 50 /* USB Callback prototypes */
 51 static int imon_probe(struct usb_interface *interface,
 52                       const struct usb_device_id *id);
 53 static void imon_disconnect(struct usb_interface *interface);
 54 static void usb_rx_callback(struct urb *urb);
 55 static void usb_tx_callback(struct urb *urb);
 56 
 57 /* suspend/resume support */
 58 static int imon_resume(struct usb_interface *intf);
 59 static int imon_suspend(struct usb_interface *intf, pm_message_t message);
 60 
 61 /* Display file_operations function prototypes */
 62 static int display_open(struct inode *inode, struct file *file);
 63 static int display_close(struct inode *inode, struct file *file);
 64 
 65 /* VFD write operation */
 66 static ssize_t vfd_write(struct file *file, const char __user *buf,
 67                          size_t n_bytes, loff_t *pos);
 68 
 69 /* LIRC driver function prototypes */
 70 static int ir_open(void *data);
 71 static void ir_close(void *data);
 72 
 73 /*** G L O B A L S ***/
 74 #define IMON_DATA_BUF_SZ        35
 75 
 76 struct imon_context {
 77         struct usb_device *usbdev;
 78         /* Newer devices have two interfaces */
 79         int display;                    /* not all controllers do */
 80         int display_isopen;             /* display port has been opened */
 81         int ir_isopen;                  /* IR port open */
 82         int dev_present;                /* USB device presence */
 83         struct mutex ctx_lock;          /* to lock this object */
 84         wait_queue_head_t remove_ok;    /* For unexpected USB disconnects */
 85 
 86         int vfd_proto_6p;               /* some VFD require a 6th packet */
 87 
 88         struct lirc_driver *driver;
 89         struct usb_endpoint_descriptor *rx_endpoint;
 90         struct usb_endpoint_descriptor *tx_endpoint;
 91         struct urb *rx_urb;
 92         struct urb *tx_urb;
 93         unsigned char usb_rx_buf[8];
 94         unsigned char usb_tx_buf[8];
 95 
 96         struct rx_data {
 97                 int count;              /* length of 0 or 1 sequence */
 98                 int prev_bit;           /* logic level of sequence */
 99                 int initial_space;      /* initial space flag */
100         } rx;
101 
102         struct tx_t {
103                 unsigned char data_buf[IMON_DATA_BUF_SZ]; /* user data buffer */
104                 struct completion finished;     /* wait for write to finish */
105                 atomic_t busy;                  /* write in progress */
106                 int status;                     /* status of tx completion */
107         } tx;
108 };
109 
110 static const struct file_operations display_fops = {
111         .owner          = THIS_MODULE,
112         .open           = &display_open,
113         .write          = &vfd_write,
114         .release        = &display_close,
115         .llseek         = noop_llseek,
116 };
117 
118 /*
119  * USB Device ID for iMON USB Control Boards
120  *
121  * The Windows drivers contain 6 different inf files, more or less one for
122  * each new device until the 0x0034-0x0046 devices, which all use the same
123  * driver. Some of the devices in the 34-46 range haven't been definitively
124  * identified yet. Early devices have either a TriGem Computer, Inc. or a
125  * Samsung vendor ID (0x0aa8 and 0x04e8 respectively), while all later
126  * devices use the SoundGraph vendor ID (0x15c2).
127  */
128 static struct usb_device_id imon_usb_id_table[] = {
129         /* TriGem iMON (IR only) -- TG_iMON.inf */
130         { USB_DEVICE(0x0aa8, 0x8001) },
131 
132         /* SoundGraph iMON (IR only) -- sg_imon.inf */
133         { USB_DEVICE(0x04e8, 0xff30) },
134 
135         /* SoundGraph iMON VFD (IR & VFD) -- iMON_VFD.inf */
136         { USB_DEVICE(0x0aa8, 0xffda) },
137 
138         /* SoundGraph iMON SS (IR & VFD) -- iMON_SS.inf */
139         { USB_DEVICE(0x15c2, 0xffda) },
140 
141         {}
142 };
143 
144 /* Some iMON VFD models requires a 6th packet for VFD writes */
145 static struct usb_device_id vfd_proto_6p_list[] = {
146         { USB_DEVICE(0x15c2, 0xffda) },
147         {}
148 };
149 
150 /* Some iMON devices have no lcd/vfd, don't set one up */
151 static struct usb_device_id ir_only_list[] = {
152         { USB_DEVICE(0x0aa8, 0x8001) },
153         { USB_DEVICE(0x04e8, 0xff30) },
154         {}
155 };
156 
157 /* USB Device data */
158 static struct usb_driver imon_driver = {
159         .name           = MOD_NAME,
160         .probe          = imon_probe,
161         .disconnect     = imon_disconnect,
162         .suspend        = imon_suspend,
163         .resume         = imon_resume,
164         .id_table       = imon_usb_id_table,
165 };
166 
167 static struct usb_class_driver imon_class = {
168         .name           = DEVICE_NAME,
169         .fops           = &display_fops,
170         .minor_base     = DISPLAY_MINOR_BASE,
171 };
172 
173 /* to prevent races between open() and disconnect(), probing, etc */
174 static DEFINE_MUTEX(driver_lock);
175 
176 static int debug;
177 
178 /***  M O D U L E   C O D E ***/
179 
180 MODULE_AUTHOR(MOD_AUTHOR);
181 MODULE_DESCRIPTION(MOD_DESC);
182 MODULE_VERSION(MOD_VERSION);
183 MODULE_LICENSE("GPL");
184 MODULE_DEVICE_TABLE(usb, imon_usb_id_table);
185 module_param(debug, int, S_IRUGO | S_IWUSR);
186 MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes(default: no)");
187 
188 static void free_imon_context(struct imon_context *context)
189 {
190         struct device *dev = context->driver->dev;
191 
192         usb_free_urb(context->tx_urb);
193         usb_free_urb(context->rx_urb);
194         lirc_buffer_free(context->driver->rbuf);
195         kfree(context->driver->rbuf);
196         kfree(context->driver);
197         kfree(context);
198 
199         dev_dbg(dev, "%s: iMON context freed\n", __func__);
200 }
201 
202 static void deregister_from_lirc(struct imon_context *context)
203 {
204         int retval;
205         int minor = context->driver->minor;
206 
207         retval = lirc_unregister_driver(minor);
208         if (retval)
209                 dev_err(&context->usbdev->dev,
210                         "unable to deregister from lirc(%d)", retval);
211         else
212                 dev_info(&context->usbdev->dev,
213                          "Deregistered iMON driver (minor:%d)\n", minor);
214 }
215 
216 /**
217  * Called when the Display device (e.g. /dev/lcd0)
218  * is opened by the application.
219  */
220 static int display_open(struct inode *inode, struct file *file)
221 {
222         struct usb_interface *interface;
223         struct imon_context *context = NULL;
224         int subminor;
225         int retval = 0;
226 
227         /* prevent races with disconnect */
228         mutex_lock(&driver_lock);
229 
230         subminor = iminor(inode);
231         interface = usb_find_interface(&imon_driver, subminor);
232         if (!interface) {
233                 pr_err("%s: could not find interface for minor %d\n",
234                        __func__, subminor);
235                 retval = -ENODEV;
236                 goto exit;
237         }
238         context = usb_get_intfdata(interface);
239 
240         if (!context) {
241                 dev_err(&interface->dev, "no context found for minor %d\n",
242                         subminor);
243                 retval = -ENODEV;
244                 goto exit;
245         }
246 
247         mutex_lock(&context->ctx_lock);
248 
249         if (!context->display) {
250                 dev_err(&interface->dev,
251                         "%s: display not supported by device\n", __func__);
252                 retval = -ENODEV;
253         } else if (context->display_isopen) {
254                 dev_err(&interface->dev,
255                         "%s: display port is already open\n", __func__);
256                 retval = -EBUSY;
257         } else {
258                 context->display_isopen = 1;
259                 file->private_data = context;
260                 dev_info(context->driver->dev, "display port opened\n");
261         }
262 
263         mutex_unlock(&context->ctx_lock);
264 
265 exit:
266         mutex_unlock(&driver_lock);
267         return retval;
268 }
269 
270 /**
271  * Called when the display device (e.g. /dev/lcd0)
272  * is closed by the application.
273  */
274 static int display_close(struct inode *inode, struct file *file)
275 {
276         struct imon_context *context = NULL;
277         int retval = 0;
278 
279         context = file->private_data;
280 
281         if (!context) {
282                 pr_err("%s: no context for device\n", __func__);
283                 return -ENODEV;
284         }
285 
286         mutex_lock(&context->ctx_lock);
287 
288         if (!context->display) {
289                 dev_err(&context->usbdev->dev,
290                         "%s: display not supported by device\n", __func__);
291                 retval = -ENODEV;
292         } else if (!context->display_isopen) {
293                 dev_err(&context->usbdev->dev,
294                         "%s: display is not open\n", __func__);
295                 retval = -EIO;
296         } else {
297                 context->display_isopen = 0;
298                 dev_info(context->driver->dev, "display port closed\n");
299                 if (!context->dev_present && !context->ir_isopen) {
300                         /*
301                          * Device disconnected before close and IR port is not
302                          * open. If IR port is open, context will be deleted by
303                          * ir_close.
304                          */
305                         mutex_unlock(&context->ctx_lock);
306                         free_imon_context(context);
307                         return retval;
308                 }
309         }
310 
311         mutex_unlock(&context->ctx_lock);
312         return retval;
313 }
314 
315 /**
316  * Sends a packet to the device -- this function must be called
317  * with context->ctx_lock held.
318  */
319 static int send_packet(struct imon_context *context)
320 {
321         unsigned int pipe;
322         int interval = 0;
323         int retval = 0;
324 
325         /* Check if we need to use control or interrupt urb */
326         pipe = usb_sndintpipe(context->usbdev,
327                               context->tx_endpoint->bEndpointAddress);
328         interval = context->tx_endpoint->bInterval;
329 
330         usb_fill_int_urb(context->tx_urb, context->usbdev, pipe,
331                          context->usb_tx_buf,
332                          sizeof(context->usb_tx_buf),
333                          usb_tx_callback, context, interval);
334 
335         context->tx_urb->actual_length = 0;
336 
337         reinit_completion(&context->tx.finished);
338         atomic_set(&context->tx.busy, 1);
339 
340         retval = usb_submit_urb(context->tx_urb, GFP_KERNEL);
341         if (retval) {
342                 atomic_set(&context->tx.busy, 0);
343                 dev_err(&context->usbdev->dev, "error submitting urb(%d)\n",
344                         retval);
345         } else {
346                 /* Wait for transmission to complete (or abort) */
347                 mutex_unlock(&context->ctx_lock);
348                 retval = wait_for_completion_interruptible(
349                                 &context->tx.finished);
350                 if (retval)
351                         dev_err(&context->usbdev->dev,
352                                 "%s: task interrupted\n", __func__);
353                 mutex_lock(&context->ctx_lock);
354 
355                 retval = context->tx.status;
356                 if (retval)
357                         dev_err(&context->usbdev->dev,
358                                 "packet tx failed (%d)\n", retval);
359         }
360 
361         return retval;
362 }
363 
364 /**
365  * Writes data to the VFD.  The iMON VFD is 2x16 characters
366  * and requires data in 5 consecutive USB interrupt packets,
367  * each packet but the last carrying 7 bytes.
368  *
369  * I don't know if the VFD board supports features such as
370  * scrolling, clearing rows, blanking, etc. so at
371  * the caller must provide a full screen of data.  If fewer
372  * than 32 bytes are provided spaces will be appended to
373  * generate a full screen.
374  */
375 static ssize_t vfd_write(struct file *file, const char __user *buf,
376                          size_t n_bytes, loff_t *pos)
377 {
378         int i;
379         int offset;
380         int seq;
381         int retval = 0;
382         struct imon_context *context;
383         const unsigned char vfd_packet6[] = {
384                 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF };
385         int *data_buf = NULL;
386 
387         context = file->private_data;
388         if (!context) {
389                 pr_err("%s: no context for device\n", __func__);
390                 return -ENODEV;
391         }
392 
393         mutex_lock(&context->ctx_lock);
394 
395         if (!context->dev_present) {
396                 dev_err(&context->usbdev->dev,
397                         "%s: no iMON device present\n", __func__);
398                 retval = -ENODEV;
399                 goto exit;
400         }
401 
402         if (n_bytes <= 0 || n_bytes > IMON_DATA_BUF_SZ - 3) {
403                 dev_err(&context->usbdev->dev,
404                         "%s: invalid payload size\n", __func__);
405                 retval = -EINVAL;
406                 goto exit;
407         }
408 
409         data_buf = memdup_user(buf, n_bytes);
410         if (IS_ERR(data_buf)) {
411                 mutex_unlock(&context->ctx_lock);
412                 return PTR_ERR(data_buf);
413         }
414 
415         memcpy(context->tx.data_buf, data_buf, n_bytes);
416 
417         /* Pad with spaces */
418         for (i = n_bytes; i < IMON_DATA_BUF_SZ - 3; ++i)
419                 context->tx.data_buf[i] = ' ';
420 
421         for (i = IMON_DATA_BUF_SZ - 3; i < IMON_DATA_BUF_SZ; ++i)
422                 context->tx.data_buf[i] = 0xFF;
423 
424         offset = 0;
425         seq = 0;
426 
427         do {
428                 memcpy(context->usb_tx_buf, context->tx.data_buf + offset, 7);
429                 context->usb_tx_buf[7] = (unsigned char)seq;
430 
431                 retval = send_packet(context);
432                 if (retval) {
433                         dev_err(&context->usbdev->dev,
434                                 "send packet failed for packet #%d\n",
435                                 seq / 2);
436                         goto exit;
437                 } else {
438                         seq += 2;
439                         offset += 7;
440                 }
441 
442         } while (offset < IMON_DATA_BUF_SZ);
443 
444         if (context->vfd_proto_6p) {
445                 /* Send packet #6 */
446                 memcpy(context->usb_tx_buf, &vfd_packet6, sizeof(vfd_packet6));
447                 context->usb_tx_buf[7] = (unsigned char)seq;
448                 retval = send_packet(context);
449                 if (retval)
450                         dev_err(&context->usbdev->dev,
451                                 "send packet failed for packet #%d\n",
452                                 seq / 2);
453         }
454 
455 exit:
456         mutex_unlock(&context->ctx_lock);
457         kfree(data_buf);
458 
459         return (!retval) ? n_bytes : retval;
460 }
461 
462 /**
463  * Callback function for USB core API: transmit data
464  */
465 static void usb_tx_callback(struct urb *urb)
466 {
467         struct imon_context *context;
468 
469         if (!urb)
470                 return;
471         context = (struct imon_context *)urb->context;
472         if (!context)
473                 return;
474 
475         context->tx.status = urb->status;
476 
477         /* notify waiters that write has finished */
478         atomic_set(&context->tx.busy, 0);
479         complete(&context->tx.finished);
480 }
481 
482 /**
483  * Called by lirc_dev when the application opens /dev/lirc
484  */
485 static int ir_open(void *data)
486 {
487         struct imon_context *context;
488 
489         /* prevent races with disconnect */
490         mutex_lock(&driver_lock);
491 
492         context = data;
493 
494         /* initial IR protocol decode variables */
495         context->rx.count = 0;
496         context->rx.initial_space = 1;
497         context->rx.prev_bit = 0;
498 
499         init_completion(&context->tx.finished);
500 
501         context->ir_isopen = 1;
502         dev_info(context->driver->dev, "IR port opened\n");
503 
504         mutex_unlock(&driver_lock);
505         return 0;
506 }
507 
508 /**
509  * Called by lirc_dev when the application closes /dev/lirc
510  */
511 static void ir_close(void *data)
512 {
513         struct imon_context *context;
514 
515         context = data;
516         if (!context) {
517                 pr_err("%s: no context for device\n", __func__);
518                 return;
519         }
520 
521         mutex_lock(&context->ctx_lock);
522 
523         context->ir_isopen = 0;
524         dev_info(context->driver->dev, "IR port closed\n");
525 
526         if (!context->dev_present) {
527                 /*
528                  * Device disconnected while IR port was still open. Driver
529                  * was not deregistered at disconnect time, so do it now.
530                  */
531                 deregister_from_lirc(context);
532 
533                 if (!context->display_isopen) {
534                         mutex_unlock(&context->ctx_lock);
535                         free_imon_context(context);
536                         return;
537                 }
538                 /*
539                  * If display port is open, context will be deleted by
540                  * display_close
541                  */
542         }
543 
544         mutex_unlock(&context->ctx_lock);
545 }
546 
547 /**
548  * Convert bit count to time duration (in us) and submit
549  * the value to lirc_dev.
550  */
551 static void submit_data(struct imon_context *context)
552 {
553         unsigned char buf[4];
554         int value = context->rx.count;
555         int i;
556 
557         dev_dbg(context->driver->dev, "submitting data to LIRC\n");
558 
559         value *= BIT_DURATION;
560         value &= PULSE_MASK;
561         if (context->rx.prev_bit)
562                 value |= PULSE_BIT;
563 
564         for (i = 0; i < 4; ++i)
565                 buf[i] = value >> (i * 8);
566 
567         lirc_buffer_write(context->driver->rbuf, buf);
568         wake_up(&context->driver->rbuf->wait_poll);
569 }
570 
571 /**
572  * Process the incoming packet
573  */
574 static void imon_incoming_packet(struct imon_context *context,
575                                  struct urb *urb, int intf)
576 {
577         int len = urb->actual_length;
578         unsigned char *buf = urb->transfer_buffer;
579         struct device *dev = context->driver->dev;
580         int octet, bit;
581         unsigned char mask;
582 
583         /*
584          * just bail out if no listening IR client
585          */
586         if (!context->ir_isopen)
587                 return;
588 
589         if (len != 8) {
590                 dev_warn(dev, "imon %s: invalid incoming packet size (len = %d, intf%d)\n",
591                          __func__, len, intf);
592                 return;
593         }
594 
595         if (debug)
596                 dev_info(dev, "raw packet: %*ph\n", len, buf);
597         /*
598          * Translate received data to pulse and space lengths.
599          * Received data is active low, i.e. pulses are 0 and
600          * spaces are 1.
601          *
602          * My original algorithm was essentially similar to
603          * Changwoo Ryu's with the exception that he switched
604          * the incoming bits to active high and also fed an
605          * initial space to LIRC at the start of a new sequence
606          * if the previous bit was a pulse.
607          *
608          * I've decided to adopt his algorithm.
609          */
610 
611         if (buf[7] == 1 && context->rx.initial_space) {
612                 /* LIRC requires a leading space */
613                 context->rx.prev_bit = 0;
614                 context->rx.count = 4;
615                 submit_data(context);
616                 context->rx.count = 0;
617         }
618 
619         for (octet = 0; octet < 5; ++octet) {
620                 mask = 0x80;
621                 for (bit = 0; bit < 8; ++bit) {
622                         int curr_bit = !(buf[octet] & mask);
623 
624                         if (curr_bit != context->rx.prev_bit) {
625                                 if (context->rx.count) {
626                                         submit_data(context);
627                                         context->rx.count = 0;
628                                 }
629                                 context->rx.prev_bit = curr_bit;
630                         }
631                         ++context->rx.count;
632                         mask >>= 1;
633                 }
634         }
635 
636         if (buf[7] == 10) {
637                 if (context->rx.count) {
638                         submit_data(context);
639                         context->rx.count = 0;
640                 }
641                 context->rx.initial_space = context->rx.prev_bit;
642         }
643 }
644 
645 /**
646  * Callback function for USB core API: receive data
647  */
648 static void usb_rx_callback(struct urb *urb)
649 {
650         struct imon_context *context;
651         int intfnum = 0;
652 
653         if (!urb)
654                 return;
655 
656         context = (struct imon_context *)urb->context;
657         if (!context)
658                 return;
659 
660         switch (urb->status) {
661         case -ENOENT:           /* usbcore unlink successful! */
662                 return;
663 
664         case 0:
665                 imon_incoming_packet(context, urb, intfnum);
666                 break;
667 
668         default:
669                 dev_warn(context->driver->dev, "imon %s: status(%d): ignored\n",
670                          __func__, urb->status);
671                 break;
672         }
673 
674         usb_submit_urb(context->rx_urb, GFP_ATOMIC);
675 }
676 
677 /**
678  * Callback function for USB core API: Probe
679  */
680 static int imon_probe(struct usb_interface *interface,
681                       const struct usb_device_id *id)
682 {
683         struct usb_device *usbdev = NULL;
684         struct usb_host_interface *iface_desc = NULL;
685         struct usb_endpoint_descriptor *rx_endpoint = NULL;
686         struct usb_endpoint_descriptor *tx_endpoint = NULL;
687         struct urb *rx_urb = NULL;
688         struct urb *tx_urb = NULL;
689         struct lirc_driver *driver = NULL;
690         struct lirc_buffer *rbuf = NULL;
691         struct device *dev = &interface->dev;
692         int ifnum;
693         int lirc_minor = 0;
694         int num_endpts;
695         int retval = -ENOMEM;
696         int display_ep_found = 0;
697         int ir_ep_found = 0;
698         int vfd_proto_6p = 0;
699         struct imon_context *context = NULL;
700         int i;
701         u16 vendor, product;
702 
703         /* prevent races probing devices w/multiple interfaces */
704         mutex_lock(&driver_lock);
705 
706         context = kzalloc(sizeof(*context), GFP_KERNEL);
707         if (!context)
708                 goto driver_unlock;
709 
710         /*
711          * Try to auto-detect the type of display if the user hasn't set
712          * it by hand via the display_type modparam. Default is VFD.
713          */
714         if (usb_match_id(interface, ir_only_list))
715                 context->display = 0;
716         else
717                 context->display = 1;
718 
719         usbdev     = usb_get_dev(interface_to_usbdev(interface));
720         iface_desc = interface->cur_altsetting;
721         num_endpts = iface_desc->desc.bNumEndpoints;
722         ifnum      = iface_desc->desc.bInterfaceNumber;
723         vendor     = le16_to_cpu(usbdev->descriptor.idVendor);
724         product    = le16_to_cpu(usbdev->descriptor.idProduct);
725 
726         dev_dbg(dev, "%s: found iMON device (%04x:%04x, intf%d)\n",
727                 __func__, vendor, product, ifnum);
728 
729         /*
730          * Scan the endpoint list and set:
731          *      first input endpoint = IR endpoint
732          *      first output endpoint = display endpoint
733          */
734         for (i = 0; i < num_endpts && !(ir_ep_found && display_ep_found); ++i) {
735                 struct usb_endpoint_descriptor *ep;
736                 int ep_dir;
737                 int ep_type;
738 
739                 ep = &iface_desc->endpoint[i].desc;
740                 ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK;
741                 ep_type = usb_endpoint_type(ep);
742 
743                 if (!ir_ep_found &&
744                         ep_dir == USB_DIR_IN &&
745                         ep_type == USB_ENDPOINT_XFER_INT) {
746 
747                         rx_endpoint = ep;
748                         ir_ep_found = 1;
749                         dev_dbg(dev, "%s: found IR endpoint\n", __func__);
750 
751                 } else if (!display_ep_found && ep_dir == USB_DIR_OUT &&
752                            ep_type == USB_ENDPOINT_XFER_INT) {
753                         tx_endpoint = ep;
754                         display_ep_found = 1;
755                         dev_dbg(dev, "%s: found display endpoint\n", __func__);
756                 }
757         }
758 
759         /*
760          * Some iMON receivers have no display. Unfortunately, it seems
761          * that SoundGraph recycles device IDs between devices both with
762          * and without... :\
763          */
764         if (context->display == 0) {
765                 display_ep_found = 0;
766                 dev_dbg(dev, "%s: device has no display\n", __func__);
767         }
768 
769         /* Input endpoint is mandatory */
770         if (!ir_ep_found) {
771                 dev_err(dev, "%s: no valid input (IR) endpoint found.\n",
772                         __func__);
773                 retval = -ENODEV;
774                 goto free_context;
775         }
776 
777         /* Determine if display requires 6 packets */
778         if (display_ep_found) {
779                 if (usb_match_id(interface, vfd_proto_6p_list))
780                         vfd_proto_6p = 1;
781 
782                 dev_dbg(dev, "%s: vfd_proto_6p: %d\n",
783                         __func__, vfd_proto_6p);
784         }
785 
786         driver = kzalloc(sizeof(*driver), GFP_KERNEL);
787         if (!driver)
788                 goto free_context;
789 
790         rbuf = kmalloc(sizeof(*rbuf), GFP_KERNEL);
791         if (!rbuf)
792                 goto free_driver;
793 
794         if (lirc_buffer_init(rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) {
795                 dev_err(dev, "%s: lirc_buffer_init failed\n", __func__);
796                 goto free_rbuf;
797         }
798         rx_urb = usb_alloc_urb(0, GFP_KERNEL);
799         if (!rx_urb)
800                 goto free_lirc_buf;
801         tx_urb = usb_alloc_urb(0, GFP_KERNEL);
802         if (!tx_urb)
803                 goto free_rx_urb;
804 
805         mutex_init(&context->ctx_lock);
806         context->vfd_proto_6p = vfd_proto_6p;
807 
808         strcpy(driver->name, MOD_NAME);
809         driver->minor = -1;
810         driver->code_length = BUF_CHUNK_SIZE * 8;
811         driver->sample_rate = 0;
812         driver->features = LIRC_CAN_REC_MODE2;
813         driver->data = context;
814         driver->rbuf = rbuf;
815         driver->set_use_inc = ir_open;
816         driver->set_use_dec = ir_close;
817         driver->dev = &interface->dev;
818         driver->owner = THIS_MODULE;
819 
820         mutex_lock(&context->ctx_lock);
821 
822         context->driver = driver;
823         /* start out in keyboard mode */
824 
825         lirc_minor = lirc_register_driver(driver);
826         if (lirc_minor < 0) {
827                 dev_err(dev, "%s: lirc_register_driver failed\n", __func__);
828                 goto free_tx_urb;
829         }
830 
831         dev_info(dev, "Registered iMON driver (lirc minor: %d)\n",
832                  lirc_minor);
833 
834         /* Needed while unregistering! */
835         driver->minor = lirc_minor;
836 
837         context->usbdev = usbdev;
838         context->dev_present = 1;
839         context->rx_endpoint = rx_endpoint;
840         context->rx_urb = rx_urb;
841 
842         /*
843          * tx is used to send characters to lcd/vfd, associate RF
844          * remotes, set IR protocol, and maybe more...
845          */
846         context->tx_endpoint = tx_endpoint;
847         context->tx_urb = tx_urb;
848 
849         if (display_ep_found)
850                 context->display = 1;
851 
852         usb_fill_int_urb(context->rx_urb, context->usbdev,
853                          usb_rcvintpipe(context->usbdev,
854                          context->rx_endpoint->bEndpointAddress),
855                 context->usb_rx_buf, sizeof(context->usb_rx_buf),
856                 usb_rx_callback, context,
857                 context->rx_endpoint->bInterval);
858 
859         retval = usb_submit_urb(context->rx_urb, GFP_KERNEL);
860         if (retval) {
861                 dev_err(dev, "usb_submit_urb failed for intf0 (%d)\n", retval);
862                 goto unregister_lirc;
863         }
864 
865         usb_set_intfdata(interface, context);
866 
867         if (context->display && ifnum == 0) {
868                 dev_dbg(dev, "%s: Registering iMON display with sysfs\n",
869                         __func__);
870 
871                 if (usb_register_dev(interface, &imon_class)) {
872                         /* Not a fatal error, so ignore */
873                         dev_info(dev, "%s: could not get a minor number for display\n",
874                                  __func__);
875                 }
876         }
877 
878         dev_info(dev, "iMON device (%04x:%04x, intf%d) on usb<%d:%d> initialized\n",
879                  vendor, product, ifnum, usbdev->bus->busnum, usbdev->devnum);
880 
881         /* Everything went fine. Just unlock and return retval (with is 0) */
882         mutex_unlock(&context->ctx_lock);
883         goto driver_unlock;
884 
885 unregister_lirc:
886         lirc_unregister_driver(driver->minor);
887 
888 free_tx_urb:
889         mutex_unlock(&context->ctx_lock);
890         usb_free_urb(tx_urb);
891 
892 free_rx_urb:
893         usb_free_urb(rx_urb);
894 
895 free_lirc_buf:
896         lirc_buffer_free(rbuf);
897 
898 free_rbuf:
899         kfree(rbuf);
900 
901 free_driver:
902         kfree(driver);
903 free_context:
904         kfree(context);
905         context = NULL;
906 
907 driver_unlock:
908         mutex_unlock(&driver_lock);
909 
910         return retval;
911 }
912 
913 /**
914  * Callback function for USB core API: disconnect
915  */
916 static void imon_disconnect(struct usb_interface *interface)
917 {
918         struct imon_context *context;
919         int ifnum;
920 
921         /* prevent races with ir_open()/display_open() */
922         mutex_lock(&driver_lock);
923 
924         context = usb_get_intfdata(interface);
925         ifnum = interface->cur_altsetting->desc.bInterfaceNumber;
926 
927         mutex_lock(&context->ctx_lock);
928 
929         usb_set_intfdata(interface, NULL);
930 
931         /* Abort ongoing write */
932         if (atomic_read(&context->tx.busy)) {
933                 usb_kill_urb(context->tx_urb);
934                 complete(&context->tx.finished);
935         }
936 
937         context->dev_present = 0;
938         usb_kill_urb(context->rx_urb);
939         if (context->display)
940                 usb_deregister_dev(interface, &imon_class);
941 
942         if (!context->ir_isopen && !context->dev_present) {
943                 deregister_from_lirc(context);
944                 mutex_unlock(&context->ctx_lock);
945                 if (!context->display_isopen)
946                         free_imon_context(context);
947         } else
948                 mutex_unlock(&context->ctx_lock);
949 
950         mutex_unlock(&driver_lock);
951 
952         dev_info(&interface->dev, "%s: iMON device (intf%d) disconnected\n",
953                  __func__, ifnum);
954 }
955 
956 static int imon_suspend(struct usb_interface *intf, pm_message_t message)
957 {
958         struct imon_context *context = usb_get_intfdata(intf);
959 
960         usb_kill_urb(context->rx_urb);
961 
962         return 0;
963 }
964 
965 static int imon_resume(struct usb_interface *intf)
966 {
967         struct imon_context *context = usb_get_intfdata(intf);
968 
969         usb_fill_int_urb(context->rx_urb, context->usbdev,
970                          usb_rcvintpipe(context->usbdev,
971                          context->rx_endpoint->bEndpointAddress),
972                 context->usb_rx_buf, sizeof(context->usb_rx_buf),
973                 usb_rx_callback, context,
974                 context->rx_endpoint->bInterval);
975 
976         return usb_submit_urb(context->rx_urb, GFP_ATOMIC);
977 }
978 
979 module_usb_driver(imon_driver);
980 

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