]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/linux/opensimpad-2.4.27-vrs1-pxa1-jpm1/2.4.27-mh1.patch
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / linux / opensimpad-2.4.27-vrs1-pxa1-jpm1 / 2.4.27-mh1.patch
1
2 #
3 # Patch managed by http://www.holgerschurig.de/patcher.html
4 #
5
6 --- linux-2.4.27/arch/sparc64/kernel/ioctl32.c~patch-2.4.27-mh1
7 +++ linux-2.4.27/arch/sparc64/kernel/ioctl32.c
8 @@ -4322,6 +4322,11 @@
9  #define CMTPGETCONNLIST        _IOR('C', 210, int)
10  #define CMTPGETCONNINFO        _IOR('C', 211, int)
11  
12 +#define HIDPCONNADD    _IOW('H', 200, int)
13 +#define HIDPCONNDEL    _IOW('H', 201, int)
14 +#define HIDPGETCONNLIST        _IOR('H', 210, int)
15 +#define HIDPGETCONNINFO        _IOR('H', 211, int)
16 +
17  struct ioctl_trans {
18         unsigned int cmd;
19         unsigned int handler;
20 @@ -5050,6 +5055,10 @@
21  COMPATIBLE_IOCTL(CMTPCONNDEL)
22  COMPATIBLE_IOCTL(CMTPGETCONNLIST)
23  COMPATIBLE_IOCTL(CMTPGETCONNINFO)
24 +COMPATIBLE_IOCTL(HIDPCONNADD)
25 +COMPATIBLE_IOCTL(HIDPCONNDEL)
26 +COMPATIBLE_IOCTL(HIDPGETCONNLIST)
27 +COMPATIBLE_IOCTL(HIDPGETCONNINFO)
28  /* Scanner */
29  COMPATIBLE_IOCTL(SCANNER_IOCTL_VENDOR)
30  COMPATIBLE_IOCTL(SCANNER_IOCTL_PRODUCT)
31 --- linux-2.4.27/CREDITS~patch-2.4.27-mh1
32 +++ linux-2.4.27/CREDITS
33 @@ -1348,6 +1348,7 @@
34  D: Maintainer of the Linux Bluetooth Subsystem
35  D: Author and maintainer of the various Bluetooth HCI drivers
36  D: Author and maintainer of the CAPI message transport protocol driver
37 +D: Author and maintainer of the Bluetooth HID protocol driver
38  D: Various other Bluetooth related patches, cleanups and fixes
39  S: Germany
40  
41 --- linux-2.4.27/Documentation/Configure.help~patch-2.4.27-mh1
42 +++ linux-2.4.27/Documentation/Configure.help
43 @@ -23313,6 +23313,7 @@
44                 RFCOMM Module (RFCOMM Protocol)
45                 BNEP Module (Bluetooth Network Encapsulation Protocol)
46                 CMTP Module (CAPI Message Transport Protocol)
47 +               HIDP Module (Human Interface Device Protocol)
48  
49    Say Y here to compile Bluetooth support into the kernel or say M to
50    compile it as module (bluez.o).
51 @@ -23378,6 +23379,15 @@
52    Say Y here to compile CMTP support into the kernel or say M to
53    compile it as module (cmtp.o).
54  
55 +HIDP protocol support
56 +CONFIG_BLUEZ_HIDP
57 +  HIDP (Human Interface Device Protocol) is a transport layer
58 +  for HID reports.  HIDP is required for the Bluetooth Human
59 +  Interface Device Profile.
60 +
61 +  Say Y here to compile HIDP support into the kernel or say M to
62 +  compile it as module (hidp.o).
63 +
64  HCI UART driver
65  CONFIG_BLUEZ_HCIUART
66    Bluetooth HCI UART driver.
67 --- linux-2.4.27/MAINTAINERS~patch-2.4.27-mh1
68 +++ linux-2.4.27/MAINTAINERS
69 @@ -359,6 +359,11 @@
70  M:     marcel@holtmann.org
71  S:     Maintained
72  
73 +BLUETOOTH HIDP LAYER
74 +P:     Marcel Holtmann
75 +M:     marcel@holtmann.org
76 +S:     Maintained
77 +
78  BLUETOOTH HCI UART DRIVER
79  P:     Marcel Holtmann
80  M:     marcel@holtmann.org
81 --- linux-2.4.27/net/bluetooth/Config.in~patch-2.4.27-mh1
82 +++ linux-2.4.27/net/bluetooth/Config.in
83 @@ -14,6 +14,7 @@
84        source net/bluetooth/rfcomm/Config.in
85        source net/bluetooth/bnep/Config.in
86        source net/bluetooth/cmtp/Config.in
87 +      source net/bluetooth/hidp/Config.in
88        source drivers/bluetooth/Config.in
89     fi
90  
91 --- /dev/null
92 +++ linux-2.4.27/net/bluetooth/hidp/Config.in
93 @@ -0,0 +1,5 @@
94 +#
95 +# Bluetooth HIDP layer configuration
96 +#
97 +
98 +dep_tristate 'HIDP protocol support' CONFIG_BLUEZ_HIDP $CONFIG_INPUT $CONFIG_BLUEZ_L2CAP
99 --- /dev/null
100 +++ linux-2.4.27/net/bluetooth/hidp/core.c
101 @@ -0,0 +1,655 @@
102 +/* 
103 +   HIDP implementation for Linux Bluetooth stack (BlueZ).
104 +   Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
105 +
106 +   This program is free software; you can redistribute it and/or modify
107 +   it under the terms of the GNU General Public License version 2 as
108 +   published by the Free Software Foundation;
109 +
110 +   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
111 +   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
112 +   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
113 +   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
114 +   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
115 +   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
116 +   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
117 +   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
118 +
119 +   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
120 +   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
121 +   SOFTWARE IS DISCLAIMED.
122 +*/
123 +
124 +#include <linux/config.h>
125 +#include <linux/module.h>
126 +
127 +#include <linux/types.h>
128 +#include <linux/errno.h>
129 +#include <linux/kernel.h>
130 +#include <linux/major.h>
131 +#include <linux/sched.h>
132 +#include <linux/slab.h>
133 +#include <linux/poll.h>
134 +#include <linux/fcntl.h>
135 +#include <linux/skbuff.h>
136 +#include <linux/socket.h>
137 +#include <linux/ioctl.h>
138 +#include <linux/file.h>
139 +#include <linux/init.h>
140 +#include <net/sock.h>
141 +
142 +#include <linux/input.h>
143 +
144 +#include <net/bluetooth/bluetooth.h>
145 +#include <net/bluetooth/l2cap.h>
146 +
147 +#include "hidp.h"
148 +
149 +#ifndef CONFIG_BT_HIDP_DEBUG
150 +#undef  BT_DBG
151 +#define BT_DBG(D...)
152 +#endif
153 +
154 +#define VERSION "1.0"
155 +
156 +static DECLARE_RWSEM(hidp_session_sem);
157 +static LIST_HEAD(hidp_session_list);
158 +
159 +static unsigned char hidp_keycode[256] = {
160 +         0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
161 +        50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
162 +         4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
163 +        27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
164 +        65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
165 +       105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
166 +        72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
167 +       191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
168 +       115,114,  0,  0,  0,121,  0, 89, 93,124, 92, 94, 95,  0,  0,  0,
169 +       122,123, 90, 91, 85,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
170 +         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
171 +         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
172 +         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
173 +         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
174 +        29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
175 +       150,158,159,128,136,177,178,176,142,152,173,140
176 +};
177 +
178 +static struct hidp_session *__hidp_get_session(bdaddr_t *bdaddr)
179 +{
180 +       struct hidp_session *session;
181 +       struct list_head *p;
182 +
183 +       BT_DBG("");
184 +
185 +       list_for_each(p, &hidp_session_list) {
186 +               session = list_entry(p, struct hidp_session, list);
187 +               if (!bacmp(bdaddr, &session->bdaddr))
188 +                       return session;
189 +       }
190 +       return NULL;
191 +}
192 +
193 +static void __hidp_link_session(struct hidp_session *session)
194 +{
195 +       MOD_INC_USE_COUNT;
196 +       list_add(&session->list, &hidp_session_list);
197 +}
198 +
199 +static void __hidp_unlink_session(struct hidp_session *session)
200 +{
201 +       list_del(&session->list);
202 +       MOD_DEC_USE_COUNT;
203 +}
204 +
205 +static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
206 +{
207 +       bacpy(&ci->bdaddr, &session->bdaddr);
208 +
209 +       ci->flags = session->flags;
210 +       ci->state = session->state;
211 +
212 +       ci->vendor  = 0x0000;
213 +       ci->product = 0x0000;
214 +       ci->version = 0x0000;
215 +       memset(ci->name, 0, 128);
216 +
217 +       if (session->input) {
218 +               ci->vendor  = session->input->idvendor;
219 +               ci->product = session->input->idproduct;
220 +               ci->version = session->input->idversion;
221 +               if (session->input->name)
222 +                       strncpy(ci->name, session->input->name, 128);
223 +               else
224 +                       strncpy(ci->name, "HID Boot Device", 128);
225 +       }
226 +}
227 +
228 +static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
229 +{
230 +       struct hidp_session *session = dev->private;
231 +       struct sk_buff *skb;
232 +       unsigned char newleds;
233 +
234 +       BT_DBG("session %p hid %p data %p size %d", session, device, data, size);
235 +
236 +       if (type != EV_LED)
237 +               return -1;
238 +
239 +       newleds = (!!test_bit(LED_KANA,    dev->led) << 3) |
240 +                 (!!test_bit(LED_COMPOSE, dev->led) << 3) |
241 +                 (!!test_bit(LED_SCROLLL, dev->led) << 2) |
242 +                 (!!test_bit(LED_CAPSL,   dev->led) << 1) |
243 +                 (!!test_bit(LED_NUML,    dev->led));
244 +
245 +       if (session->leds == newleds)
246 +               return 0;
247 +
248 +       session->leds = newleds;
249 +
250 +       if (!(skb = alloc_skb(3, GFP_ATOMIC))) {
251 +               BT_ERR("Can't allocate memory for new frame");
252 +               return -ENOMEM;
253 +       }
254 +
255 +       *skb_put(skb, 1) = 0xa2;
256 +       *skb_put(skb, 1) = 0x01;
257 +       *skb_put(skb, 1) = newleds;
258 +
259 +       skb_queue_tail(&session->intr_transmit, skb);
260 +
261 +       hidp_schedule(session);
262 +
263 +       return 0;
264 +}
265 +
266 +static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
267 +{
268 +       struct input_dev *dev = session->input;
269 +       unsigned char *keys = session->keys;
270 +       unsigned char *udata = skb->data + 1;
271 +       signed char *sdata = skb->data + 1;
272 +       int i, size = skb->len - 1;
273 +
274 +       switch (skb->data[0]) {
275 +       case 0x01:      /* Keyboard report */
276 +               for (i = 0; i < 8; i++)
277 +                       input_report_key(dev, hidp_keycode[i + 224], (udata[0] >> i) & 1);
278 +
279 +               for (i = 2; i < 8; i++) {
280 +                       if (keys[i] > 3 && memscan(udata + 2, keys[i], 6) == udata + 8) {
281 +                               if (hidp_keycode[keys[i]])
282 +                                       input_report_key(dev, hidp_keycode[keys[i]], 0);
283 +                               else
284 +                                       BT_ERR("Unknown key (scancode %#x) released.", keys[i]);
285 +                       }
286 +
287 +                       if (udata[i] > 3 && memscan(keys + 2, udata[i], 6) == keys + 8) {
288 +                               if (hidp_keycode[udata[i]])
289 +                                       input_report_key(dev, hidp_keycode[udata[i]], 1);
290 +                               else
291 +                                       BT_ERR("Unknown key (scancode %#x) pressed.", udata[i]);
292 +                       }
293 +               }
294 +
295 +               memcpy(keys, udata, 8);
296 +               break;
297 +
298 +       case 0x02:      /* Mouse report */
299 +               input_report_key(dev, BTN_LEFT,   sdata[0] & 0x01);
300 +               input_report_key(dev, BTN_RIGHT,  sdata[0] & 0x02);
301 +               input_report_key(dev, BTN_MIDDLE, sdata[0] & 0x04);
302 +               input_report_key(dev, BTN_SIDE,   sdata[0] & 0x08);
303 +               input_report_key(dev, BTN_EXTRA,  sdata[0] & 0x10);
304 +
305 +               input_report_rel(dev, REL_X, sdata[1]);
306 +               input_report_rel(dev, REL_Y, sdata[2]);
307 +
308 +               if (size > 3)
309 +                       input_report_rel(dev, REL_WHEEL, sdata[3]);
310 +               break;
311 +       }
312 +
313 +       input_event(dev, EV_RST, 0, 0);
314 +}
315 +
316 +static void hidp_idle_timeout(unsigned long arg)
317 +{
318 +       struct hidp_session *session = (struct hidp_session *) arg;
319 +
320 +       atomic_inc(&session->terminate);
321 +       hidp_schedule(session);
322 +}
323 +
324 +static inline void hidp_set_timer(struct hidp_session *session)
325 +{
326 +       if (session->idle_to > 0)
327 +               mod_timer(&session->timer, jiffies + HZ * session->idle_to);
328 +}
329 +
330 +static inline void hidp_del_timer(struct hidp_session *session)
331 +{
332 +       if (session->idle_to > 0)
333 +               del_timer(&session->timer);
334 +}
335 +
336 +static inline void hidp_send_message(struct hidp_session *session, unsigned char hdr)
337 +{
338 +       struct sk_buff *skb;
339 +
340 +       BT_DBG("session %p", session);
341 +
342 +       if (!(skb = alloc_skb(1, GFP_ATOMIC))) {
343 +               BT_ERR("Can't allocate memory for message");
344 +               return;
345 +       }
346 +
347 +       *skb_put(skb, 1) = hdr;
348 +
349 +       skb_queue_tail(&session->ctrl_transmit, skb);
350 +
351 +       hidp_schedule(session);
352 +}
353 +
354 +static inline int hidp_recv_frame(struct hidp_session *session, struct sk_buff *skb)
355 +{
356 +       __u8 hdr;
357 +
358 +       BT_DBG("session %p skb %p len %d", session, skb, skb->len);
359 +
360 +       hdr = skb->data[0];
361 +       skb_pull(skb, 1);
362 +
363 +       if (hdr == 0xa1) {
364 +               hidp_set_timer(session);
365 +
366 +               if (session->input)
367 +                       hidp_input_report(session, skb);
368 +       } else {
369 +               BT_DBG("Unsupported protocol header 0x%02x", hdr);
370 +       }
371 +
372 +       kfree_skb(skb);
373 +       return 0;
374 +}
375 +
376 +static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
377 +{
378 +       struct iovec iv = { data, len };
379 +       struct msghdr msg;
380 +
381 +       BT_DBG("sock %p data %p len %d", sock, data, len);
382 +
383 +       if (!len)
384 +               return 0;
385 +
386 +       memset(&msg, 0, sizeof(msg));
387 +       msg.msg_iovlen = 1;
388 +       msg.msg_iov = &iv;
389 +
390 +       return sock_sendmsg(sock, &msg, len);
391 +}
392 +
393 +static int hidp_process_transmit(struct hidp_session *session)
394 +{
395 +       struct sk_buff *skb;
396 +
397 +       BT_DBG("session %p", session);
398 +
399 +       while ((skb = skb_dequeue(&session->ctrl_transmit))) {
400 +               if (hidp_send_frame(session->ctrl_sock, skb->data, skb->len) < 0) {
401 +                       skb_queue_head(&session->ctrl_transmit, skb);
402 +                       break;
403 +               }
404 +
405 +               hidp_set_timer(session);
406 +               kfree_skb(skb);
407 +       }
408 +
409 +       while ((skb = skb_dequeue(&session->intr_transmit))) {
410 +               if (hidp_send_frame(session->intr_sock, skb->data, skb->len) < 0) {
411 +                       skb_queue_head(&session->intr_transmit, skb);
412 +                       break;
413 +               }
414 +
415 +               hidp_set_timer(session);
416 +               kfree_skb(skb);
417 +       }
418 +
419 +       return skb_queue_len(&session->ctrl_transmit) +
420 +                               skb_queue_len(&session->intr_transmit);
421 +}
422 +
423 +static int hidp_session(void *arg)
424 +{
425 +       struct hidp_session *session = arg;
426 +       struct sock *ctrl_sk = session->ctrl_sock->sk;
427 +       struct sock *intr_sk = session->intr_sock->sk;
428 +       struct sk_buff *skb;
429 +       int vendor = 0x0000, product = 0x0000;
430 +       wait_queue_t ctrl_wait, intr_wait;
431 +       unsigned long timeo = HZ;
432 +
433 +       BT_DBG("session %p", session);
434 +
435 +       if (session->input) {
436 +               vendor  = session->input->idvendor;
437 +               product = session->input->idproduct;
438 +       }
439 +
440 +       daemonize(); reparent_to_init();
441 +
442 +       sprintf(current->comm, "khidpd_%04x%04x", vendor, product);
443 +
444 +       sigfillset(&current->blocked);
445 +       flush_signals(current);
446 +
447 +       current->nice = -15;
448 +
449 +       set_fs(KERNEL_DS);
450 +
451 +       init_waitqueue_entry(&ctrl_wait, current);
452 +       init_waitqueue_entry(&intr_wait, current);
453 +       add_wait_queue(ctrl_sk->sleep, &ctrl_wait);
454 +       add_wait_queue(intr_sk->sleep, &intr_wait);
455 +       while (!atomic_read(&session->terminate)) {
456 +               set_current_state(TASK_INTERRUPTIBLE);
457 +
458 +               if (ctrl_sk->state != BT_CONNECTED || intr_sk->state != BT_CONNECTED)
459 +                       break;
460 +
461 +               while ((skb = skb_dequeue(&ctrl_sk->receive_queue))) {
462 +                       skb_orphan(skb);
463 +                       hidp_recv_frame(session, skb);
464 +               }
465 +
466 +               while ((skb = skb_dequeue(&intr_sk->receive_queue))) {
467 +                       skb_orphan(skb);
468 +                       hidp_recv_frame(session, skb);
469 +               }
470 +
471 +               hidp_process_transmit(session);
472 +
473 +               schedule();
474 +       }
475 +       set_current_state(TASK_RUNNING);
476 +       remove_wait_queue(intr_sk->sleep, &intr_wait);
477 +       remove_wait_queue(ctrl_sk->sleep, &ctrl_wait);
478 +
479 +       down_write(&hidp_session_sem);
480 +
481 +       hidp_del_timer(session);
482 +
483 +       if (intr_sk->state != BT_CONNECTED) {
484 +               init_waitqueue_entry(&ctrl_wait, current);
485 +               add_wait_queue(ctrl_sk->sleep, &ctrl_wait);
486 +               while (timeo && ctrl_sk->state != BT_CLOSED) {
487 +                       set_current_state(TASK_INTERRUPTIBLE);
488 +                       timeo = schedule_timeout(timeo);
489 +               }
490 +               set_current_state(TASK_RUNNING);
491 +               remove_wait_queue(ctrl_sk->sleep, &ctrl_wait);
492 +               timeo = HZ;
493 +       }
494 +
495 +       fput(session->ctrl_sock->file);
496 +
497 +       init_waitqueue_entry(&intr_wait, current);
498 +       add_wait_queue(intr_sk->sleep, &intr_wait);
499 +       while (timeo && intr_sk->state != BT_CLOSED) {
500 +               set_current_state(TASK_INTERRUPTIBLE);
501 +               timeo = schedule_timeout(timeo);
502 +       }
503 +       set_current_state(TASK_RUNNING);
504 +       remove_wait_queue(intr_sk->sleep, &intr_wait);
505 +
506 +       fput(session->intr_sock->file);
507 +
508 +       __hidp_unlink_session(session);
509 +
510 +       if (session->input) {
511 +               input_unregister_device(session->input);
512 +               kfree(session->input);
513 +       }
514 +
515 +       up_write(&hidp_session_sem);
516 +
517 +       kfree(session);
518 +       return 0;
519 +}
520 +
521 +static inline void hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req)
522 +{
523 +       struct input_dev *input = session->input;
524 +       int i;
525 +
526 +       input->private = session;
527 +
528 +       input->idbus     = BUS_BLUETOOTH;
529 +       input->idvendor  = req->vendor;
530 +       input->idproduct = req->product;
531 +       input->idversion = req->version;
532 +
533 +       if (req->subclass & 0x40) {
534 +               set_bit(EV_KEY, input->evbit);
535 +               set_bit(EV_LED, input->evbit);
536 +               set_bit(EV_REP, input->evbit);
537 +
538 +               set_bit(LED_NUML,    input->ledbit);
539 +               set_bit(LED_CAPSL,   input->ledbit);
540 +               set_bit(LED_SCROLLL, input->ledbit);
541 +               set_bit(LED_COMPOSE, input->ledbit);
542 +               set_bit(LED_KANA,    input->ledbit);
543 +
544 +               for (i = 0; i < sizeof(hidp_keycode); i++)
545 +                       set_bit(hidp_keycode[i], input->keybit);
546 +               clear_bit(0, input->keybit);
547 +       }
548 +
549 +       if (req->subclass & 0x80) {
550 +               input->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
551 +               input->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
552 +               input->relbit[0] = BIT(REL_X) | BIT(REL_Y);
553 +               input->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
554 +               input->relbit[0] |= BIT(REL_WHEEL);
555 +       }
556 +
557 +       input->event = hidp_input_event;
558 +
559 +       input_register_device(input);
560 +}
561 +
562 +int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
563 +{
564 +       struct hidp_session *session, *s;
565 +       int err;
566 +
567 +       BT_DBG("");
568 +
569 +       if (bacmp(&bluez_pi(ctrl_sock->sk)->src, &bluez_pi(intr_sock->sk)->src) ||
570 +                       bacmp(&bluez_pi(ctrl_sock->sk)->dst, &bluez_pi(intr_sock->sk)->dst))
571 +               return -ENOTUNIQ;
572 +
573 +       session = kmalloc(sizeof(struct hidp_session), GFP_KERNEL);
574 +       if (!session) 
575 +               return -ENOMEM;
576 +       memset(session, 0, sizeof(struct hidp_session));
577 +
578 +       session->input = kmalloc(sizeof(struct input_dev), GFP_KERNEL);
579 +       if (!session->input) {
580 +               kfree(session);
581 +               return -ENOMEM;
582 +       }
583 +       memset(session->input, 0, sizeof(struct input_dev));
584 +
585 +       down_write(&hidp_session_sem);
586 +
587 +       s = __hidp_get_session(&bluez_pi(ctrl_sock->sk)->dst);
588 +       if (s && s->state == BT_CONNECTED) {
589 +               err = -EEXIST;
590 +               goto failed;
591 +       }
592 +
593 +       bacpy(&session->bdaddr, &bluez_pi(ctrl_sock->sk)->dst);
594 +
595 +       session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->omtu, l2cap_pi(ctrl_sock->sk)->imtu);
596 +       session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->omtu, l2cap_pi(intr_sock->sk)->imtu);
597 +
598 +       BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu);
599 +
600 +       session->ctrl_sock = ctrl_sock;
601 +       session->intr_sock = intr_sock;
602 +       session->state     = BT_CONNECTED;
603 +
604 +       init_timer(&session->timer);
605 +
606 +       session->timer.function = hidp_idle_timeout;
607 +       session->timer.data     = (unsigned long) session;
608 +
609 +       skb_queue_head_init(&session->ctrl_transmit);
610 +       skb_queue_head_init(&session->intr_transmit);
611 +
612 +       session->flags   = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
613 +       session->idle_to = req->idle_to;
614 +
615 +       if (session->input)
616 +               hidp_setup_input(session, req);
617 +
618 +       __hidp_link_session(session);
619 +
620 +       hidp_set_timer(session);
621 +
622 +       err = kernel_thread(hidp_session, session, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
623 +       if (err < 0)
624 +               goto unlink;
625 +
626 +       if (session->input) {
627 +               hidp_send_message(session, 0x70);
628 +               session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
629 +
630 +               session->leds = 0xff;
631 +               hidp_input_event(session->input, EV_LED, 0, 0);
632 +       }
633 +
634 +       up_write(&hidp_session_sem);
635 +       return 0;
636 +
637 +unlink:
638 +       hidp_del_timer(session);
639 +
640 +       __hidp_unlink_session(session);
641 +
642 +       if (session->input)
643 +               input_unregister_device(session->input);
644 +
645 +failed:
646 +       up_write(&hidp_session_sem);
647 +
648 +       if (session->input)
649 +               kfree(session->input);
650 +
651 +       kfree(session);
652 +       return err;
653 +}
654 +
655 +int hidp_del_connection(struct hidp_conndel_req *req)
656 +{
657 +       struct hidp_session *session;
658 +       int err = 0;
659 +
660 +       BT_DBG("");
661 +
662 +       down_read(&hidp_session_sem);
663 +
664 +       session = __hidp_get_session(&req->bdaddr);
665 +       if (session) {
666 +               if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {
667 +                       hidp_send_message(session, 0x15);
668 +               } else {
669 +                       /* Flush the transmit queues */
670 +                       skb_queue_purge(&session->ctrl_transmit);
671 +                       skb_queue_purge(&session->intr_transmit);
672 +
673 +                       /* Kill session thread */
674 +                       atomic_inc(&session->terminate);
675 +                       hidp_schedule(session);
676 +               }
677 +       } else
678 +               err = -ENOENT;
679 +
680 +       up_read(&hidp_session_sem);
681 +       return err;
682 +}
683 +
684 +int hidp_get_connlist(struct hidp_connlist_req *req)
685 +{
686 +       struct list_head *p;
687 +       int err = 0, n = 0;
688 +
689 +       BT_DBG("");
690 +
691 +       down_read(&hidp_session_sem);
692 +
693 +       list_for_each(p, &hidp_session_list) {
694 +               struct hidp_session *session;
695 +               struct hidp_conninfo ci;
696 +
697 +               session = list_entry(p, struct hidp_session, list);
698 +
699 +               __hidp_copy_session(session, &ci);
700 +
701 +               if (copy_to_user(req->ci, &ci, sizeof(ci))) {
702 +                       err = -EFAULT;
703 +                       break;
704 +               }
705 +
706 +               if (++n >= req->cnum)
707 +                       break;
708 +
709 +               req->ci++;
710 +       }
711 +       req->cnum = n;
712 +
713 +       up_read(&hidp_session_sem);
714 +       return err;
715 +}
716 +
717 +int hidp_get_conninfo(struct hidp_conninfo *ci)
718 +{
719 +       struct hidp_session *session;
720 +       int err = 0;
721 +
722 +       down_read(&hidp_session_sem);
723 +
724 +       session = __hidp_get_session(&ci->bdaddr);
725 +       if (session)
726 +               __hidp_copy_session(session, ci);
727 +       else
728 +               err = -ENOENT;
729 +
730 +       up_read(&hidp_session_sem);
731 +       return err;
732 +}
733 +
734 +static int __init hidp_init(void)
735 +{
736 +       l2cap_load();
737 +
738 +       hidp_init_sockets();
739 +
740 +       BT_INFO("BlueZ HIDP ver %s", VERSION);
741 +       BT_INFO("Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>");
742 +
743 +       return 0;
744 +}
745 +
746 +static void __exit hidp_exit(void)
747 +{
748 +       hidp_cleanup_sockets();
749 +}
750 +
751 +module_init(hidp_init);
752 +module_exit(hidp_exit);
753 +
754 +MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
755 +MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);
756 +MODULE_LICENSE("GPL");
757 --- /dev/null
758 +++ linux-2.4.27/net/bluetooth/hidp/hidp.h
759 @@ -0,0 +1,122 @@
760 +/* 
761 +   HIDP implementation for Linux Bluetooth stack (BlueZ).
762 +   Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
763 +
764 +   This program is free software; you can redistribute it and/or modify
765 +   it under the terms of the GNU General Public License version 2 as
766 +   published by the Free Software Foundation;
767 +
768 +   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
769 +   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
770 +   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
771 +   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
772 +   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
773 +   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
774 +   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
775 +   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
776 +
777 +   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
778 +   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
779 +   SOFTWARE IS DISCLAIMED.
780 +*/
781 +
782 +#ifndef __HIDP_H
783 +#define __HIDP_H
784 +
785 +#include <linux/types.h>
786 +#include <net/bluetooth/bluetooth.h>
787 +
788 +/* HIDP ioctl defines */
789 +#define HIDPCONNADD    _IOW('H', 200, int)
790 +#define HIDPCONNDEL    _IOW('H', 201, int)
791 +#define HIDPGETCONNLIST        _IOR('H', 210, int)
792 +#define HIDPGETCONNINFO        _IOR('H', 211, int)
793 +
794 +#define HIDP_VIRTUAL_CABLE_UNPLUG      0
795 +#define HIDP_BOOT_PROTOCOL_MODE                1
796 +#define HIDP_BLUETOOTH_VENDOR_ID       9
797 +
798 +struct hidp_connadd_req {
799 +       int   ctrl_sock;        // Connected control socket
800 +       int   intr_sock;        // Connteted interrupt socket
801 +       __u16 parser;
802 +       __u16 rd_size;
803 +       __u8 *rd_data;
804 +       __u8  country;
805 +       __u8  subclass;
806 +       __u16 vendor;
807 +       __u16 product;
808 +       __u16 version;
809 +       __u32 flags;
810 +       __u32 idle_to;
811 +       char  name[128];
812 +};
813 +
814 +struct hidp_conndel_req {
815 +       bdaddr_t bdaddr;
816 +       __u32    flags;
817 +};
818 +
819 +struct hidp_conninfo {
820 +       bdaddr_t bdaddr;
821 +       __u32    flags;
822 +       __u16    state;
823 +       __u16    vendor;
824 +       __u16    product;
825 +       __u16    version;
826 +       char     name[128];
827 +};
828 +
829 +struct hidp_connlist_req {
830 +       __u32  cnum;
831 +       struct hidp_conninfo *ci;
832 +};
833 +
834 +int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock);
835 +int hidp_del_connection(struct hidp_conndel_req *req);
836 +int hidp_get_connlist(struct hidp_connlist_req *req);
837 +int hidp_get_conninfo(struct hidp_conninfo *ci);
838 +
839 +/* HIDP session defines */
840 +struct hidp_session {
841 +       struct list_head list;
842 +
843 +       struct socket *ctrl_sock;
844 +       struct socket *intr_sock;
845 +
846 +       bdaddr_t bdaddr;
847 +
848 +       unsigned long state;
849 +       unsigned long flags;
850 +       unsigned long idle_to;
851 +
852 +       uint ctrl_mtu;
853 +       uint intr_mtu;
854 +
855 +       atomic_t terminate;
856 +
857 +       unsigned char keys[8];
858 +       unsigned char leds;
859 +
860 +       struct input_dev *input;
861 +
862 +       struct timer_list timer;
863 +
864 +       struct sk_buff_head ctrl_transmit;
865 +       struct sk_buff_head intr_transmit;
866 +};
867 +
868 +static inline void hidp_schedule(struct hidp_session *session)
869 +{
870 +       struct sock *ctrl_sk = session->ctrl_sock->sk;
871 +       struct sock *intr_sk = session->intr_sock->sk;
872 +
873 +       wake_up_interruptible(ctrl_sk->sleep);
874 +       wake_up_interruptible(intr_sk->sleep);
875 +}
876 +
877 +/* HIDP init defines */
878 +extern int __init hidp_init_sockets(void);
879 +extern void __exit hidp_cleanup_sockets(void);
880 +
881 +#endif /* __HIDP_H */
882 --- /dev/null
883 +++ linux-2.4.27/net/bluetooth/hidp/Makefile
884 @@ -0,0 +1,10 @@
885 +#
886 +# Makefile for the Linux Bluetooth HIDP layer
887 +#
888 +
889 +O_TARGET := hidp.o
890 +
891 +obj-y  := core.o sock.o
892 +obj-m  += $(O_TARGET)
893 +
894 +include $(TOPDIR)/Rules.make
895 --- /dev/null
896 +++ linux-2.4.27/net/bluetooth/hidp/sock.c
897 @@ -0,0 +1,212 @@
898 +/* 
899 +   HIDP implementation for Linux Bluetooth stack (BlueZ).
900 +   Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
901 +
902 +   This program is free software; you can redistribute it and/or modify
903 +   it under the terms of the GNU General Public License version 2 as
904 +   published by the Free Software Foundation;
905 +
906 +   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
907 +   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
908 +   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
909 +   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
910 +   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
911 +   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
912 +   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
913 +   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
914 +
915 +   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
916 +   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
917 +   SOFTWARE IS DISCLAIMED.
918 +*/
919 +
920 +#include <linux/config.h>
921 +#include <linux/module.h>
922 +
923 +#include <linux/types.h>
924 +#include <linux/errno.h>
925 +#include <linux/kernel.h>
926 +#include <linux/major.h>
927 +#include <linux/sched.h>
928 +#include <linux/slab.h>
929 +#include <linux/poll.h>
930 +#include <linux/fcntl.h>
931 +#include <linux/skbuff.h>
932 +#include <linux/socket.h>
933 +#include <linux/ioctl.h>
934 +#include <linux/file.h>
935 +#include <linux/init.h>
936 +#include <net/sock.h>
937 +
938 +#include "hidp.h"
939 +
940 +#ifndef CONFIG_BT_HIDP_DEBUG
941 +#undef  BT_DBG
942 +#define BT_DBG(D...)
943 +#endif
944 +
945 +static int hidp_sock_release(struct socket *sock)
946 +{
947 +       struct sock *sk = sock->sk;
948 +
949 +       BT_DBG("sock %p sk %p", sock, sk);
950 +
951 +       if (!sk)
952 +               return 0;
953 +
954 +       sock_orphan(sk);
955 +       sock_put(sk);
956 +
957 +       MOD_DEC_USE_COUNT;
958 +       return 0;
959 +}
960 +
961 +static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
962 +{
963 +       struct hidp_connadd_req ca;
964 +       struct hidp_conndel_req cd;
965 +       struct hidp_connlist_req cl;
966 +       struct hidp_conninfo ci;
967 +       struct socket *csock;
968 +       struct socket *isock;
969 +       int err;
970 +
971 +       BT_DBG("cmd %x arg %lx", cmd, arg);
972 +
973 +       switch (cmd) {
974 +       case HIDPCONNADD:
975 +               if (!capable(CAP_NET_ADMIN))
976 +                       return -EACCES;
977 +
978 +               if (copy_from_user(&ca, (void *) arg, sizeof(ca)))
979 +                       return -EFAULT;
980 +
981 +               csock = sockfd_lookup(ca.ctrl_sock, &err);
982 +               if (!csock)
983 +                       return err;
984 +
985 +               isock = sockfd_lookup(ca.intr_sock, &err);
986 +               if (!isock) {
987 +                       fput(csock->file);
988 +                       return err;
989 +               }
990 +
991 +               if (csock->sk->state != BT_CONNECTED || isock->sk->state != BT_CONNECTED) {
992 +                       fput(csock->file);
993 +                       fput(isock->file);
994 +                       return -EBADFD;
995 +               }
996 +
997 +               err = hidp_add_connection(&ca, csock, isock);
998 +               if (!err) {
999 +                       if (copy_to_user((void *) arg, &ca, sizeof(ca)))
1000 +                               err = -EFAULT;
1001 +               } else {
1002 +                       fput(csock->file);
1003 +                       fput(isock->file);
1004 +               }
1005 +
1006 +               return err;
1007 +
1008 +       case HIDPCONNDEL:
1009 +               if (!capable(CAP_NET_ADMIN))
1010 +                       return -EACCES;
1011 +
1012 +               if (copy_from_user(&cd, (void *) arg, sizeof(cd)))
1013 +                       return -EFAULT;
1014 +
1015 +               return hidp_del_connection(&cd);
1016 +
1017 +       case HIDPGETCONNLIST:
1018 +               if (copy_from_user(&cl, (void *) arg, sizeof(cl)))
1019 +                       return -EFAULT;
1020 +
1021 +               if (cl.cnum <= 0)
1022 +                       return -EINVAL;
1023 +
1024 +               err = hidp_get_connlist(&cl);
1025 +               if (!err && copy_to_user((void *) arg, &cl, sizeof(cl)))
1026 +                       return -EFAULT;
1027 +
1028 +               return err;
1029 +
1030 +       case HIDPGETCONNINFO:
1031 +               if (copy_from_user(&ci, (void *) arg, sizeof(ci)))
1032 +                       return -EFAULT;
1033 +
1034 +               err = hidp_get_conninfo(&ci);
1035 +               if (!err && copy_to_user((void *) arg, &ci, sizeof(ci)))
1036 +                       return -EFAULT;
1037 +
1038 +               return err;
1039 +       }
1040 +
1041 +       return -EINVAL;
1042 +}
1043 +
1044 +static struct proto_ops hidp_sock_ops = {
1045 +       family:         PF_BLUETOOTH,
1046 +       release:        hidp_sock_release,
1047 +       ioctl:          hidp_sock_ioctl,
1048 +       bind:           sock_no_bind,
1049 +       getname:        sock_no_getname,
1050 +       sendmsg:        sock_no_sendmsg,
1051 +       recvmsg:        sock_no_recvmsg,
1052 +       poll:           sock_no_poll,
1053 +       listen:         sock_no_listen,
1054 +       shutdown:       sock_no_shutdown,
1055 +       setsockopt:     sock_no_setsockopt,
1056 +       getsockopt:     sock_no_getsockopt,
1057 +       connect:        sock_no_connect,
1058 +       socketpair:     sock_no_socketpair,
1059 +       accept:         sock_no_accept,
1060 +       mmap:           sock_no_mmap
1061 +};
1062 +
1063 +static int hidp_sock_create(struct socket *sock, int protocol)
1064 +{
1065 +       struct sock *sk;
1066 +
1067 +       BT_DBG("sock %p", sock);
1068 +
1069 +       if (sock->type != SOCK_RAW)
1070 +               return -ESOCKTNOSUPPORT;
1071 +
1072 +       sock->ops = &hidp_sock_ops;
1073 +
1074 +       if (!(sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, 1)))
1075 +               return -ENOMEM;
1076 +
1077 +       MOD_INC_USE_COUNT;
1078 +
1079 +       sock->state = SS_UNCONNECTED;
1080 +       sock_init_data(sock, sk);
1081 +
1082 +       sk->destruct = NULL;
1083 +       sk->protocol = protocol;
1084 +
1085 +       return 0;
1086 +}
1087 +
1088 +static struct net_proto_family hidp_sock_family_ops = {
1089 +       family:         PF_BLUETOOTH,
1090 +       create:         hidp_sock_create
1091 +};
1092 +
1093 +int __init hidp_init_sockets(void)
1094 +{
1095 +       int err;
1096 +
1097 +       if ((err = bluez_sock_register(BTPROTO_HIDP, &hidp_sock_family_ops)))
1098 +               BT_ERR("Can't register HIDP socket layer (%d)", err);
1099 +
1100 +       return err;
1101 +}
1102 +
1103 +void __exit hidp_cleanup_sockets(void)
1104 +{
1105 +       int err;
1106 +
1107 +       if ((err = bluez_sock_unregister(BTPROTO_HIDP)))
1108 +               BT_ERR("Can't unregister HIDP socket layer (%d)", err);
1109 +}
1110 --- linux-2.4.27/net/bluetooth/Makefile~patch-2.4.27-mh1
1111 +++ linux-2.4.27/net/bluetooth/Makefile
1112 @@ -16,6 +16,7 @@
1113  subdir-$(CONFIG_BLUEZ_RFCOMM) += rfcomm
1114  subdir-$(CONFIG_BLUEZ_BNEP) += bnep
1115  subdir-$(CONFIG_BLUEZ_CMTP) += cmtp
1116 +subdir-$(CONFIG_BLUEZ_HIDP) += hidp
1117  
1118  ifeq ($(CONFIG_BLUEZ_RFCOMM),y)
1119  obj-y += rfcomm/rfcomm.o
1120 @@ -25,6 +26,14 @@
1121  obj-y += bnep/bnep.o
1122  endif
1123  
1124 +ifeq ($(CONFIG_BLUEZ_CMTP),y)
1125 +obj-y += cmtp/cmtp.o
1126 +endif
1127 +
1128 +ifeq ($(CONFIG_BLUEZ_HIDP),y)
1129 +obj-y += hidp/hidp.o
1130 +endif
1131 +
1132  include $(TOPDIR)/Rules.make
1133  
1134  bluez.o: $(bluez-objs)