3 # Patch managed by http://www.holgerschurig.de/patcher.html
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
9 #define CMTPGETCONNLIST _IOR('C', 210, int)
10 #define CMTPGETCONNINFO _IOR('C', 211, int)
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)
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)
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
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
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)
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).
55 +HIDP protocol support
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.
61 + Say Y here to compile HIDP support into the kernel or say M to
62 + compile it as module (hidp.o).
66 Bluetooth HCI UART driver.
67 --- linux-2.4.27/MAINTAINERS~patch-2.4.27-mh1
68 +++ linux-2.4.27/MAINTAINERS
70 M: marcel@holtmann.org
75 +M: marcel@holtmann.org
78 BLUETOOTH HCI UART DRIVER
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
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
92 +++ linux-2.4.27/net/bluetooth/hidp/Config.in
95 +# Bluetooth HIDP layer configuration
98 +dep_tristate 'HIDP protocol support' CONFIG_BLUEZ_HIDP $CONFIG_INPUT $CONFIG_BLUEZ_L2CAP
100 +++ linux-2.4.27/net/bluetooth/hidp/core.c
103 + HIDP implementation for Linux Bluetooth stack (BlueZ).
104 + Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
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;
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.
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.
124 +#include <linux/config.h>
125 +#include <linux/module.h>
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>
142 +#include <linux/input.h>
144 +#include <net/bluetooth/bluetooth.h>
145 +#include <net/bluetooth/l2cap.h>
149 +#ifndef CONFIG_BT_HIDP_DEBUG
151 +#define BT_DBG(D...)
154 +#define VERSION "1.0"
156 +static DECLARE_RWSEM(hidp_session_sem);
157 +static LIST_HEAD(hidp_session_list);
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
178 +static struct hidp_session *__hidp_get_session(bdaddr_t *bdaddr)
180 + struct hidp_session *session;
181 + struct list_head *p;
185 + list_for_each(p, &hidp_session_list) {
186 + session = list_entry(p, struct hidp_session, list);
187 + if (!bacmp(bdaddr, &session->bdaddr))
193 +static void __hidp_link_session(struct hidp_session *session)
196 + list_add(&session->list, &hidp_session_list);
199 +static void __hidp_unlink_session(struct hidp_session *session)
201 + list_del(&session->list);
205 +static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
207 + bacpy(&ci->bdaddr, &session->bdaddr);
209 + ci->flags = session->flags;
210 + ci->state = session->state;
212 + ci->vendor = 0x0000;
213 + ci->product = 0x0000;
214 + ci->version = 0x0000;
215 + memset(ci->name, 0, 128);
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);
224 + strncpy(ci->name, "HID Boot Device", 128);
228 +static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
230 + struct hidp_session *session = dev->private;
231 + struct sk_buff *skb;
232 + unsigned char newleds;
234 + BT_DBG("session %p hid %p data %p size %d", session, device, data, size);
236 + if (type != EV_LED)
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));
245 + if (session->leds == newleds)
248 + session->leds = newleds;
250 + if (!(skb = alloc_skb(3, GFP_ATOMIC))) {
251 + BT_ERR("Can't allocate memory for new frame");
255 + *skb_put(skb, 1) = 0xa2;
256 + *skb_put(skb, 1) = 0x01;
257 + *skb_put(skb, 1) = newleds;
259 + skb_queue_tail(&session->intr_transmit, skb);
261 + hidp_schedule(session);
266 +static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
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;
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);
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);
284 + BT_ERR("Unknown key (scancode %#x) released.", keys[i]);
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);
291 + BT_ERR("Unknown key (scancode %#x) pressed.", udata[i]);
295 + memcpy(keys, udata, 8);
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);
305 + input_report_rel(dev, REL_X, sdata[1]);
306 + input_report_rel(dev, REL_Y, sdata[2]);
309 + input_report_rel(dev, REL_WHEEL, sdata[3]);
313 + input_event(dev, EV_RST, 0, 0);
316 +static void hidp_idle_timeout(unsigned long arg)
318 + struct hidp_session *session = (struct hidp_session *) arg;
320 + atomic_inc(&session->terminate);
321 + hidp_schedule(session);
324 +static inline void hidp_set_timer(struct hidp_session *session)
326 + if (session->idle_to > 0)
327 + mod_timer(&session->timer, jiffies + HZ * session->idle_to);
330 +static inline void hidp_del_timer(struct hidp_session *session)
332 + if (session->idle_to > 0)
333 + del_timer(&session->timer);
336 +static inline void hidp_send_message(struct hidp_session *session, unsigned char hdr)
338 + struct sk_buff *skb;
340 + BT_DBG("session %p", session);
342 + if (!(skb = alloc_skb(1, GFP_ATOMIC))) {
343 + BT_ERR("Can't allocate memory for message");
347 + *skb_put(skb, 1) = hdr;
349 + skb_queue_tail(&session->ctrl_transmit, skb);
351 + hidp_schedule(session);
354 +static inline int hidp_recv_frame(struct hidp_session *session, struct sk_buff *skb)
358 + BT_DBG("session %p skb %p len %d", session, skb, skb->len);
360 + hdr = skb->data[0];
364 + hidp_set_timer(session);
366 + if (session->input)
367 + hidp_input_report(session, skb);
369 + BT_DBG("Unsupported protocol header 0x%02x", hdr);
376 +static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
378 + struct iovec iv = { data, len };
381 + BT_DBG("sock %p data %p len %d", sock, data, len);
386 + memset(&msg, 0, sizeof(msg));
387 + msg.msg_iovlen = 1;
390 + return sock_sendmsg(sock, &msg, len);
393 +static int hidp_process_transmit(struct hidp_session *session)
395 + struct sk_buff *skb;
397 + BT_DBG("session %p", session);
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);
405 + hidp_set_timer(session);
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);
415 + hidp_set_timer(session);
419 + return skb_queue_len(&session->ctrl_transmit) +
420 + skb_queue_len(&session->intr_transmit);
423 +static int hidp_session(void *arg)
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;
433 + BT_DBG("session %p", session);
435 + if (session->input) {
436 + vendor = session->input->idvendor;
437 + product = session->input->idproduct;
440 + daemonize(); reparent_to_init();
442 + sprintf(current->comm, "khidpd_%04x%04x", vendor, product);
444 + sigfillset(¤t->blocked);
445 + flush_signals(current);
447 + current->nice = -15;
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);
458 + if (ctrl_sk->state != BT_CONNECTED || intr_sk->state != BT_CONNECTED)
461 + while ((skb = skb_dequeue(&ctrl_sk->receive_queue))) {
463 + hidp_recv_frame(session, skb);
466 + while ((skb = skb_dequeue(&intr_sk->receive_queue))) {
468 + hidp_recv_frame(session, skb);
471 + hidp_process_transmit(session);
475 + set_current_state(TASK_RUNNING);
476 + remove_wait_queue(intr_sk->sleep, &intr_wait);
477 + remove_wait_queue(ctrl_sk->sleep, &ctrl_wait);
479 + down_write(&hidp_session_sem);
481 + hidp_del_timer(session);
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);
490 + set_current_state(TASK_RUNNING);
491 + remove_wait_queue(ctrl_sk->sleep, &ctrl_wait);
495 + fput(session->ctrl_sock->file);
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);
503 + set_current_state(TASK_RUNNING);
504 + remove_wait_queue(intr_sk->sleep, &intr_wait);
506 + fput(session->intr_sock->file);
508 + __hidp_unlink_session(session);
510 + if (session->input) {
511 + input_unregister_device(session->input);
512 + kfree(session->input);
515 + up_write(&hidp_session_sem);
521 +static inline void hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req)
523 + struct input_dev *input = session->input;
526 + input->private = session;
528 + input->idbus = BUS_BLUETOOTH;
529 + input->idvendor = req->vendor;
530 + input->idproduct = req->product;
531 + input->idversion = req->version;
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);
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);
544 + for (i = 0; i < sizeof(hidp_keycode); i++)
545 + set_bit(hidp_keycode[i], input->keybit);
546 + clear_bit(0, input->keybit);
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);
557 + input->event = hidp_input_event;
559 + input_register_device(input);
562 +int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
564 + struct hidp_session *session, *s;
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))
573 + session = kmalloc(sizeof(struct hidp_session), GFP_KERNEL);
576 + memset(session, 0, sizeof(struct hidp_session));
578 + session->input = kmalloc(sizeof(struct input_dev), GFP_KERNEL);
579 + if (!session->input) {
583 + memset(session->input, 0, sizeof(struct input_dev));
585 + down_write(&hidp_session_sem);
587 + s = __hidp_get_session(&bluez_pi(ctrl_sock->sk)->dst);
588 + if (s && s->state == BT_CONNECTED) {
593 + bacpy(&session->bdaddr, &bluez_pi(ctrl_sock->sk)->dst);
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);
598 + BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu);
600 + session->ctrl_sock = ctrl_sock;
601 + session->intr_sock = intr_sock;
602 + session->state = BT_CONNECTED;
604 + init_timer(&session->timer);
606 + session->timer.function = hidp_idle_timeout;
607 + session->timer.data = (unsigned long) session;
609 + skb_queue_head_init(&session->ctrl_transmit);
610 + skb_queue_head_init(&session->intr_transmit);
612 + session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
613 + session->idle_to = req->idle_to;
615 + if (session->input)
616 + hidp_setup_input(session, req);
618 + __hidp_link_session(session);
620 + hidp_set_timer(session);
622 + err = kernel_thread(hidp_session, session, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
626 + if (session->input) {
627 + hidp_send_message(session, 0x70);
628 + session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
630 + session->leds = 0xff;
631 + hidp_input_event(session->input, EV_LED, 0, 0);
634 + up_write(&hidp_session_sem);
638 + hidp_del_timer(session);
640 + __hidp_unlink_session(session);
642 + if (session->input)
643 + input_unregister_device(session->input);
646 + up_write(&hidp_session_sem);
648 + if (session->input)
649 + kfree(session->input);
655 +int hidp_del_connection(struct hidp_conndel_req *req)
657 + struct hidp_session *session;
662 + down_read(&hidp_session_sem);
664 + session = __hidp_get_session(&req->bdaddr);
666 + if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {
667 + hidp_send_message(session, 0x15);
669 + /* Flush the transmit queues */
670 + skb_queue_purge(&session->ctrl_transmit);
671 + skb_queue_purge(&session->intr_transmit);
673 + /* Kill session thread */
674 + atomic_inc(&session->terminate);
675 + hidp_schedule(session);
680 + up_read(&hidp_session_sem);
684 +int hidp_get_connlist(struct hidp_connlist_req *req)
686 + struct list_head *p;
687 + int err = 0, n = 0;
691 + down_read(&hidp_session_sem);
693 + list_for_each(p, &hidp_session_list) {
694 + struct hidp_session *session;
695 + struct hidp_conninfo ci;
697 + session = list_entry(p, struct hidp_session, list);
699 + __hidp_copy_session(session, &ci);
701 + if (copy_to_user(req->ci, &ci, sizeof(ci))) {
706 + if (++n >= req->cnum)
713 + up_read(&hidp_session_sem);
717 +int hidp_get_conninfo(struct hidp_conninfo *ci)
719 + struct hidp_session *session;
722 + down_read(&hidp_session_sem);
724 + session = __hidp_get_session(&ci->bdaddr);
726 + __hidp_copy_session(session, ci);
730 + up_read(&hidp_session_sem);
734 +static int __init hidp_init(void)
738 + hidp_init_sockets();
740 + BT_INFO("BlueZ HIDP ver %s", VERSION);
741 + BT_INFO("Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>");
746 +static void __exit hidp_exit(void)
748 + hidp_cleanup_sockets();
751 +module_init(hidp_init);
752 +module_exit(hidp_exit);
754 +MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
755 +MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);
756 +MODULE_LICENSE("GPL");
758 +++ linux-2.4.27/net/bluetooth/hidp/hidp.h
761 + HIDP implementation for Linux Bluetooth stack (BlueZ).
762 + Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
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;
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.
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.
785 +#include <linux/types.h>
786 +#include <net/bluetooth/bluetooth.h>
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)
794 +#define HIDP_VIRTUAL_CABLE_UNPLUG 0
795 +#define HIDP_BOOT_PROTOCOL_MODE 1
796 +#define HIDP_BLUETOOTH_VENDOR_ID 9
798 +struct hidp_connadd_req {
799 + int ctrl_sock; // Connected control socket
800 + int intr_sock; // Connteted interrupt socket
814 +struct hidp_conndel_req {
819 +struct hidp_conninfo {
829 +struct hidp_connlist_req {
831 + struct hidp_conninfo *ci;
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);
839 +/* HIDP session defines */
840 +struct hidp_session {
841 + struct list_head list;
843 + struct socket *ctrl_sock;
844 + struct socket *intr_sock;
848 + unsigned long state;
849 + unsigned long flags;
850 + unsigned long idle_to;
855 + atomic_t terminate;
857 + unsigned char keys[8];
858 + unsigned char leds;
860 + struct input_dev *input;
862 + struct timer_list timer;
864 + struct sk_buff_head ctrl_transmit;
865 + struct sk_buff_head intr_transmit;
868 +static inline void hidp_schedule(struct hidp_session *session)
870 + struct sock *ctrl_sk = session->ctrl_sock->sk;
871 + struct sock *intr_sk = session->intr_sock->sk;
873 + wake_up_interruptible(ctrl_sk->sleep);
874 + wake_up_interruptible(intr_sk->sleep);
877 +/* HIDP init defines */
878 +extern int __init hidp_init_sockets(void);
879 +extern void __exit hidp_cleanup_sockets(void);
881 +#endif /* __HIDP_H */
883 +++ linux-2.4.27/net/bluetooth/hidp/Makefile
886 +# Makefile for the Linux Bluetooth HIDP layer
891 +obj-y := core.o sock.o
892 +obj-m += $(O_TARGET)
894 +include $(TOPDIR)/Rules.make
896 +++ linux-2.4.27/net/bluetooth/hidp/sock.c
899 + HIDP implementation for Linux Bluetooth stack (BlueZ).
900 + Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
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;
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.
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.
920 +#include <linux/config.h>
921 +#include <linux/module.h>
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>
940 +#ifndef CONFIG_BT_HIDP_DEBUG
942 +#define BT_DBG(D...)
945 +static int hidp_sock_release(struct socket *sock)
947 + struct sock *sk = sock->sk;
949 + BT_DBG("sock %p sk %p", sock, sk);
961 +static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
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;
971 + BT_DBG("cmd %x arg %lx", cmd, arg);
975 + if (!capable(CAP_NET_ADMIN))
978 + if (copy_from_user(&ca, (void *) arg, sizeof(ca)))
981 + csock = sockfd_lookup(ca.ctrl_sock, &err);
985 + isock = sockfd_lookup(ca.intr_sock, &err);
991 + if (csock->sk->state != BT_CONNECTED || isock->sk->state != BT_CONNECTED) {
997 + err = hidp_add_connection(&ca, csock, isock);
999 + if (copy_to_user((void *) arg, &ca, sizeof(ca)))
1002 + fput(csock->file);
1003 + fput(isock->file);
1009 + if (!capable(CAP_NET_ADMIN))
1012 + if (copy_from_user(&cd, (void *) arg, sizeof(cd)))
1015 + return hidp_del_connection(&cd);
1017 + case HIDPGETCONNLIST:
1018 + if (copy_from_user(&cl, (void *) arg, sizeof(cl)))
1024 + err = hidp_get_connlist(&cl);
1025 + if (!err && copy_to_user((void *) arg, &cl, sizeof(cl)))
1030 + case HIDPGETCONNINFO:
1031 + if (copy_from_user(&ci, (void *) arg, sizeof(ci)))
1034 + err = hidp_get_conninfo(&ci);
1035 + if (!err && copy_to_user((void *) arg, &ci, sizeof(ci)))
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
1063 +static int hidp_sock_create(struct socket *sock, int protocol)
1067 + BT_DBG("sock %p", sock);
1069 + if (sock->type != SOCK_RAW)
1070 + return -ESOCKTNOSUPPORT;
1072 + sock->ops = &hidp_sock_ops;
1074 + if (!(sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, 1)))
1077 + MOD_INC_USE_COUNT;
1079 + sock->state = SS_UNCONNECTED;
1080 + sock_init_data(sock, sk);
1082 + sk->destruct = NULL;
1083 + sk->protocol = protocol;
1088 +static struct net_proto_family hidp_sock_family_ops = {
1089 + family: PF_BLUETOOTH,
1090 + create: hidp_sock_create
1093 +int __init hidp_init_sockets(void)
1097 + if ((err = bluez_sock_register(BTPROTO_HIDP, &hidp_sock_family_ops)))
1098 + BT_ERR("Can't register HIDP socket layer (%d)", err);
1103 +void __exit hidp_cleanup_sockets(void)
1107 + if ((err = bluez_sock_unregister(BTPROTO_HIDP)))
1108 + BT_ERR("Can't unregister HIDP socket layer (%d)", err);
1110 --- linux-2.4.27/net/bluetooth/Makefile~patch-2.4.27-mh1
1111 +++ linux-2.4.27/net/bluetooth/Makefile
1113 subdir-$(CONFIG_BLUEZ_RFCOMM) += rfcomm
1114 subdir-$(CONFIG_BLUEZ_BNEP) += bnep
1115 subdir-$(CONFIG_BLUEZ_CMTP) += cmtp
1116 +subdir-$(CONFIG_BLUEZ_HIDP) += hidp
1118 ifeq ($(CONFIG_BLUEZ_RFCOMM),y)
1119 obj-y += rfcomm/rfcomm.o
1121 obj-y += bnep/bnep.o
1124 +ifeq ($(CONFIG_BLUEZ_CMTP),y)
1125 +obj-y += cmtp/cmtp.o
1128 +ifeq ($(CONFIG_BLUEZ_HIDP),y)
1129 +obj-y += hidp/hidp.o
1132 include $(TOPDIR)/Rules.make
1134 bluez.o: $(bluez-objs)