Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hid-picolcd_cir.c
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2010-2012 by Bruno PrĂ©mont <[email protected]> *
3  * *
4  * Based on Logitech G13 driver (v0.4) *
5  * Copyright (C) 2009 by Rick L. Vinyard, Jr. <[email protected]> *
6  * *
7  * This program is free software: you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation, version 2 of the License. *
10  * *
11  * This driver is distributed in the hope that it will be useful, but *
12  * WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14  * General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU General Public License *
17  * along with this software. If not see <http://www.gnu.org/licenses/>. *
18  ***************************************************************************/
19 
20 #include <linux/hid.h>
21 #include <linux/hid-debug.h>
22 #include <linux/input.h>
23 #include "hid-ids.h"
24 #include "usbhid/usbhid.h"
25 #include <linux/usb.h>
26 
27 #include <linux/fb.h>
28 #include <linux/vmalloc.h>
29 #include <linux/backlight.h>
30 #include <linux/lcd.h>
31 
32 #include <linux/leds.h>
33 
34 #include <linux/seq_file.h>
35 #include <linux/debugfs.h>
36 
37 #include <linux/completion.h>
38 #include <linux/uaccess.h>
39 #include <linux/module.h>
40 #include <media/rc-core.h>
41 
42 #include "hid-picolcd.h"
43 
44 
46  struct hid_report *report, u8 *raw_data, int size)
47 {
48  unsigned long flags;
49  int i, w, sz;
50  DEFINE_IR_RAW_EVENT(rawir);
51 
52  /* ignore if rc_dev is NULL or status is shunned */
53  spin_lock_irqsave(&data->lock, flags);
54  if (!data->rc_dev || (data->status & PICOLCD_CIR_SHUN)) {
55  spin_unlock_irqrestore(&data->lock, flags);
56  return 1;
57  }
58  spin_unlock_irqrestore(&data->lock, flags);
59 
60  /* PicoLCD USB packets contain 16-bit intervals in network order,
61  * with value negated for pulse. Intervals are in microseconds.
62  *
63  * Note: some userspace LIRC code for PicoLCD says negated values
64  * for space - is it a matter of IR chip? (pulse for my TSOP2236)
65  *
66  * In addition, the first interval seems to be around 15000 + base
67  * interval for non-first report of IR data - thus the quirk below
68  * to get RC_CODE to understand Sony and JVC remotes I have at hand
69  */
70  sz = size > 0 ? min((int)raw_data[0], size-1) : 0;
71  for (i = 0; i+1 < sz; i += 2) {
72  init_ir_raw_event(&rawir);
73  w = (raw_data[i] << 8) | (raw_data[i+1]);
74  rawir.pulse = !!(w & 0x8000);
75  rawir.duration = US_TO_NS(rawir.pulse ? (65536 - w) : w);
76  /* Quirk!! - see above */
77  if (i == 0 && rawir.duration > 15000000)
78  rawir.duration -= 15000000;
79  ir_raw_event_store(data->rc_dev, &rawir);
80  }
81  ir_raw_event_handle(data->rc_dev);
82 
83  return 1;
84 }
85 
86 static int picolcd_cir_open(struct rc_dev *dev)
87 {
88  struct picolcd_data *data = dev->priv;
89  unsigned long flags;
90 
91  spin_lock_irqsave(&data->lock, flags);
92  data->status &= ~PICOLCD_CIR_SHUN;
93  spin_unlock_irqrestore(&data->lock, flags);
94  return 0;
95 }
96 
97 static void picolcd_cir_close(struct rc_dev *dev)
98 {
99  struct picolcd_data *data = dev->priv;
100  unsigned long flags;
101 
102  spin_lock_irqsave(&data->lock, flags);
103  data->status |= PICOLCD_CIR_SHUN;
104  spin_unlock_irqrestore(&data->lock, flags);
105 }
106 
107 /* initialize CIR input device */
109 {
110  struct rc_dev *rdev;
111  int ret = 0;
112 
113  rdev = rc_allocate_device();
114  if (!rdev)
115  return -ENOMEM;
116 
117  rdev->priv = data;
119  rdev->allowed_protos = RC_TYPE_ALL;
120  rdev->open = picolcd_cir_open;
121  rdev->close = picolcd_cir_close;
122  rdev->input_name = data->hdev->name;
123  rdev->input_phys = data->hdev->phys;
124  rdev->input_id.bustype = data->hdev->bus;
125  rdev->input_id.vendor = data->hdev->vendor;
126  rdev->input_id.product = data->hdev->product;
127  rdev->input_id.version = data->hdev->version;
128  rdev->dev.parent = &data->hdev->dev;
129  rdev->driver_name = PICOLCD_NAME;
130  rdev->map_name = RC_MAP_RC6_MCE;
131  rdev->timeout = MS_TO_NS(100);
132  rdev->rx_resolution = US_TO_NS(1);
133 
134  ret = rc_register_device(rdev);
135  if (ret)
136  goto err;
137  data->rc_dev = rdev;
138  return 0;
139 
140 err:
141  rc_free_device(rdev);
142  return ret;
143 }
144 
146 {
147  struct rc_dev *rdev = data->rc_dev;
148 
149  data->rc_dev = NULL;
150  rc_unregister_device(rdev);
151 }
152