Revision: 84 http://svn.sourceforge.net/mactel-linux/?rev=84&view=rev Author: nboichat Date: 2007-03-13 22:07:48 -0700 (Tue, 13 Mar 2007)
Log Message: ----------- Add appleir.patch. Added Paths: ----------- trunk/kernel/mactel-patches-2.6.21/appleir.patch Added: trunk/kernel/mactel-patches-2.6.21/appleir.patch =================================================================== --- trunk/kernel/mactel-patches-2.6.21/appleir.patch (rev 0) +++ trunk/kernel/mactel-patches-2.6.21/appleir.patch 2007-03-14 05:07:48 UTC (rev 84) @@ -0,0 +1,435 @@ +Apple IR patch. + +From: ? <?> + + +--- + + drivers/usb/input/Kconfig | 4 + drivers/usb/input/Makefile | 1 + drivers/usb/input/appleir.c | 390 +++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 395 insertions(+), 0 deletions(-) + +diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig +index 69a9f3b..f88c132 100644 +--- a/drivers/usb/input/Kconfig ++++ b/drivers/usb/input/Kconfig +@@ -185,6 +185,10 @@ config USB_ACECAD + To compile this driver as a module, choose M here: the + module will be called acecad. + ++config USB_APPLEIR ++ tristate "Apple Mac Mini USB IR receiver (built in)" ++ depends on USB && INPUT ++ + config USB_KBTAB + tristate "KB Gear JamStudio tablet support" + depends on USB && INPUT +diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile +index a9d206c..31c2509 100644 +--- a/drivers/usb/input/Makefile ++++ b/drivers/usb/input/Makefile +@@ -36,6 +36,7 @@ obj-$(CONFIG_USB_ATI_REMOTE2) += ati_remote2.o + obj-$(CONFIG_USB_HID) += usbhid.o + obj-$(CONFIG_USB_KBD) += usbkbd.o + obj-$(CONFIG_USB_KBTAB) += kbtab.o ++obj-$(CONFIG_USB_APPLEIR) += appleir.o + obj-$(CONFIG_USB_KEYSPAN_REMOTE) += keyspan_remote.o + obj-$(CONFIG_USB_MOUSE) += usbmouse.o + obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o +diff --git a/drivers/usb/input/appleir.c b/drivers/usb/input/appleir.c +new file mode 100644 +index 0000000..dc5f604 +--- /dev/null ++++ b/drivers/usb/input/appleir.c +@@ -0,0 +1,390 @@ ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/input.h> ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/usb.h> ++#include <linux/usb/input.h> ++#include <asm/unaligned.h> ++#include <asm/byteorder.h> ++ ++/* ++ * Version Information ++ * ++ */ ++ ++#if 0 ++#define DUMP_PACKETS ++#else ++#undef DUMP_PACKETS ++#endif ++ ++#define DRIVER_VERSION "v1.1" ++#define DRIVER_AUTHOR "James McKenzie" ++#define DRIVER_DESC "USB Apple MacMini IR Receiver driver" ++#define DRIVER_LICENSE "GPL" ++ ++MODULE_AUTHOR (DRIVER_AUTHOR); ++MODULE_DESCRIPTION (DRIVER_DESC); ++MODULE_LICENSE (DRIVER_LICENSE); ++ ++#ifndef USB_VENDOR_ID_APPLE ++#define USB_VENDOR_ID_APPLE 0x05ac ++#endif ++#ifndef USB_DEVICE_ID_APPLE_IR ++#define USB_DEVICE_ID_APPLE_IR 0x8240 ++#endif ++ ++#define URB_SIZE 32 ++ ++#define MAX_KEYS 8 ++#define MAX_KEYS_MASK (MAX_KEYS - 1 ) ++ ++struct appleir ++{ ++ struct input_dev *dev; ++ uint8_t *data; ++ dma_addr_t dma_buf; ++ struct usb_device *usbdev; ++ struct urb *urb; ++ int timer_initted; ++ struct timer_list key_up_timer; ++ int current_key; ++ char phys[32]; ++}; ++ ++ ++static struct usb_device_id appleir_ids[] = { ++ {USB_DEVICE (USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IR),.driver_info = 0}, ++ {} ++}; ++ ++MODULE_DEVICE_TABLE (usb, appleir_ids); ++ ++ ++/* I have two devices both of which report the following */ ++/* 25 87 ee 83 0a + */ ++/* 25 87 ee 83 0c - */ ++/* 25 87 ee 83 09 << */ ++/* 25 87 ee 83 06 >> */ ++/* 25 87 ee 83 05 >" */ ++/* 25 87 ee 83 03 menu */ ++/* 26 00 00 00 00 for key repeat*/ ++ ++/* Thomas Glanzmann reports the following responses */ ++/* 25 87 ee ca 0b + */ ++/* 25 87 ee ca 0d - */ ++/* 25 87 ee ca 08 << */ ++/* 25 87 ee ca 07 >> */ ++/* 25 87 ee ca 04 >" */ ++/* 25 87 ee ca 02 menu */ ++/* 26 00 00 00 00 for key repeat*/ ++/* He also observes the following event sometimes */ ++/* sent after a key is release, which I interpret */ ++/* as a flat battery message */ ++/* 25 87 e0 ca 06 flat battery */ ++ ++ ++static int keymap[MAX_KEYS] = { ++ KEY_RESERVED, KEY_MENU, ++ KEY_PLAYPAUSE, KEY_NEXTSONG, ++ KEY_PREVIOUSSONG, KEY_VOLUMEUP, ++ KEY_VOLUMEDOWN, KEY_RESERVED ++}; ++ ++static void ++dump_packet (struct appleir *appleir, char *msg, uint8_t * data, int len) ++{ ++ int i; ++ ++ printk (KERN_ERR "appleir: %s (%d bytes)", msg, len); ++ ++ for (i = 0; i < len; ++i) ++ { ++ printk (" %02x", data[i]); ++ } ++ ++ printk ("\n"); ++} ++ ++ ++static void ++key_up (struct appleir *appleir, int key) ++{ ++ //printk (KERN_ERR "key %d up\n", key); ++ input_report_key (appleir->dev, key, 0); ++ input_sync (appleir->dev); ++} ++ ++static void ++key_down (struct appleir *appleir, int key) ++{ ++ //printk (KERN_ERR "key %d down\n", key); ++ input_report_key (appleir->dev, key, 1); ++ input_sync (appleir->dev); ++} ++ ++static void ++battery_flat (struct appleir *appleir) ++{ ++ printk (KERN_ERR "appleir: possible flat battery?\n"); ++} ++ ++static void ++key_up_tick (unsigned long data) ++{ ++ struct appleir *appleir = (struct appleir *) data; ++ ++ if (appleir->current_key) ++ { ++ key_up (appleir, appleir->current_key); ++ appleir->current_key = 0; ++ } ++} ++ ++static void ++new_data (struct appleir *appleir, uint8_t * data, int len) ++{ ++ static const uint8_t keydown[] = { 0x25, 0x87, 0xee }; ++ static const uint8_t keyrepeat[] = { 0x26, 0x00, 0x00, 0x00, 0x00 }; ++ static const uint8_t flatbattery[] = { 0x25, 0x87, 0xe0 }; ++ ++#ifdef DUMP_PACKETS ++ dump_packet (appleir, "received", data, len); ++#endif ++ ++ if (len != 5) ++ return; ++ ++ if (!memcmp (data, keydown, sizeof (keydown))) ++ { ++ /*If we already have a key down, take it up before marking */ ++ /*this one down */ ++ if (appleir->current_key) ++ key_up (appleir, appleir->current_key); ++ appleir->current_key = keymap[(data[4] >> 1) & MAX_KEYS_MASK]; ++ ++ key_down (appleir, appleir->current_key); ++ /*remote doesn't do key up, either pull them up, in the test */ ++ /*above, or here set a timer which pulls them up after 1/8 s */ ++ mod_timer (&appleir->key_up_timer, jiffies + HZ / 8); ++ ++ return; ++ } ++ ++ if (!memcmp (data, keyrepeat, sizeof (keyrepeat))) ++ { ++ key_down (appleir, appleir->current_key); ++ /*remote doesn't do key up, either pull them up, in the test */ ++ /*above, or here set a timer which pulls them up after 1/8 s */ ++ mod_timer (&appleir->key_up_timer, jiffies + HZ / 8); ++ return; ++ } ++ ++ if (!memcmp (data, flatbattery, sizeof (flatbattery))) ++ { ++ battery_flat (appleir); ++ /*Fall through */ ++ } ++ ++ dump_packet (appleir, "unknown packet", data, len); ++} ++ ++static void ++appleir_urb (struct urb *urb, struct pt_regs *regs) ++{ ++ struct appleir *appleir = urb->context; ++ int retval; ++ ++ switch (urb->status) ++ { ++ case 0: ++ new_data (appleir, urb->transfer_buffer, urb->actual_length); ++ break; ++ case -ECONNRESET: ++ case -ENOENT: ++ case -ESHUTDOWN: ++ /* this urb is terminated, clean up */ ++ dbg ("%s - urb shutting down with status: %d", __FUNCTION__, ++ urb->status); ++ return; ++ default: ++ dbg ("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); ++ } ++ ++ retval = usb_submit_urb (urb, GFP_ATOMIC); ++ if (retval) ++ err ("%s - usb_submit_urb failed with result %d", __FUNCTION__, retval); ++} ++ ++ ++static int ++appleir_open (struct input_dev *dev) ++{ ++ struct appleir *appleir = dev->private; ++ ++ //appleir->urb->dev = appleir->usbdev; ++ ++ if (usb_submit_urb (appleir->urb, GFP_KERNEL)) ++ return -EIO; ++ ++ return 0; ++} ++ ++static void ++appleir_close (struct input_dev *dev) ++{ ++ struct appleir *appleir = dev->private; ++ usb_kill_urb (appleir->urb); ++ del_timer_sync (&appleir->key_up_timer); ++} ++ ++ ++ ++ ++static int ++appleir_probe (struct usb_interface *intf, const struct usb_device_id *id) ++{ ++ struct usb_device *dev = interface_to_usbdev (intf); ++ struct usb_endpoint_descriptor *endpoint; ++ struct appleir *appleir = NULL; ++ struct input_dev *input_dev; ++ int i; ++ ++ appleir = kzalloc (sizeof (struct appleir), GFP_KERNEL); ++ if (!appleir) ++ goto fail; ++ ++ memset (appleir, 0, sizeof (struct appleir)); ++ ++ ++ appleir->data = ++ usb_buffer_alloc (dev, URB_SIZE, GFP_KERNEL, &appleir->dma_buf); ++ if (!appleir->data) ++ goto fail; ++ ++ appleir->urb = usb_alloc_urb (0, GFP_KERNEL); ++ if (!appleir->urb) ++ goto fail; ++ ++ appleir->usbdev = dev; ++ ++ input_dev = input_allocate_device (); ++ if (!input_dev) ++ goto fail; ++ ++ appleir->dev = input_dev; ++ ++ ++ usb_make_path (dev, appleir->phys, sizeof (appleir->phys)); ++ strlcpy (appleir->phys, "/input0", sizeof (appleir->phys)); ++ ++ input_dev->name = "Apple Mac mini infrared remote control driver"; ++ input_dev->phys = appleir->phys; ++ usb_to_input_id (dev, &input_dev->id); ++ input_dev->cdev.dev = &intf->dev; ++ input_dev->private = appleir; ++ ++ input_dev->evbit[0] = BIT (EV_KEY) | BIT (EV_REP); ++ input_dev->ledbit[0] = 0; ++ ++ for (i = 0; i < MAX_KEYS; i++) ++ { ++ set_bit (keymap[i], input_dev->keybit); ++ } ++ ++ clear_bit (0, input_dev->keybit); ++ ++ input_dev->open = appleir_open; ++ input_dev->close = appleir_close; ++ ++ endpoint = &intf->cur_altsetting->endpoint[0].desc; ++ ++ usb_fill_int_urb (appleir->urb, dev, ++ usb_rcvintpipe (dev, endpoint->bEndpointAddress), ++ appleir->data, 8, ++ appleir_urb, appleir, endpoint->bInterval); ++ ++ appleir->urb->transfer_dma = appleir->dma_buf; ++ appleir->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; ++ ++ usb_set_intfdata (intf, appleir); ++ ++ init_timer (&appleir->key_up_timer); ++ ++ appleir->key_up_timer.function = key_up_tick; ++ appleir->key_up_timer.data = (unsigned long) appleir; ++ ++ appleir->timer_initted++; ++ ++ input_register_device (appleir->dev); ++ ++ return 0; ++ ++fail: ++ ++ if (appleir) ++ { ++ ++ ++ if (appleir->data) ++ usb_buffer_free (dev, URB_SIZE, appleir->data, appleir->dma_buf); ++ ++ if (appleir->timer_initted) ++ del_timer_sync (&appleir->key_up_timer); ++ ++ if (appleir->dev) ++ input_free_device (appleir->dev); ++ ++ kfree (appleir); ++ } ++ ++ return -ENOMEM; ++} ++ ++static void ++appleir_disconnect (struct usb_interface *intf) ++{ ++ struct appleir *appleir = usb_get_intfdata (intf); ++ ++ usb_set_intfdata (intf, NULL); ++ if (appleir) ++ { ++ input_unregister_device (appleir->dev); ++ if (appleir->timer_initted) ++ del_timer_sync (&appleir->key_up_timer); ++ usb_kill_urb (appleir->urb); ++ usb_free_urb (appleir->urb); ++ usb_buffer_free (interface_to_usbdev (intf), URB_SIZE, appleir->data, ++ appleir->dma_buf); ++ kfree (appleir); ++ } ++} ++ ++static struct usb_driver appleir_driver = { ++ .name = "appleir", ++ .probe = appleir_probe, ++ .disconnect = appleir_disconnect, ++ .id_table = appleir_ids, ++}; ++ ++static int __init ++appleir_init (void) ++{ ++ int retval; ++ retval = usb_register (&appleir_driver); ++ if (retval) ++ goto out; ++ info (DRIVER_VERSION ":" DRIVER_DESC); ++out: ++ return retval; ++} ++ ++static void __exit ++appleir_exit (void) ++{ ++ usb_deregister (&appleir_driver); ++} ++ ++module_init (appleir_init); ++module_exit (appleir_exit); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ Mactel-linux-devel mailing list Mactel-linux-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mactel-linux-devel