📄 ir_inf_combo.c
字号:
//pallas/drv/ircombo/inf_ircombo.c/*----------------------------------------------------------------------------+|| This source code has been made available to you by IBM on an AS-IS| basis. Anyone receiving this source is licensed under IBM| copyrights to use it in any way he or she deems fit, including| copying it, modifying it, compiling it, and redistributing it either| with or without modifications. No license under IBM patents or| patent applications is to be implied by the copyright license.|| Any user of this software should understand that IBM cannot provide| technical support for this software and will not be responsible for| any consequences resulting from the use of this software.|| Any person who transfers this source code or any derivative work| must include the IBM copyright notice, this paragraph, and the| preceding two paragraphs in the transferred software.|| COPYRIGHT I B M CORPORATION 1998| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M+----------------------------------------------------------------------------*///Comment: // Linux redwood IR driver// IR Keyboard and Remove Controller is supported by default// #define _IR_MOUSE_SUPPORT to enable IR mouse support//Revision Log: // Sept/12/2001 Created by YYD// Nov/22/2001 Removed the wrongly used old mouse movement code by YYD//FixMe: Logically the queue used in rawir will not cause races// I'm not using any locks when dequeue and enqueue now.// Because the most dangerous is not be able to dequeue// when there are data or not be able to enqueue when there// are spaces. The first is more possible.// The necessary header files#include <linux/config.h>#include <linux/version.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/stddef.h>#include <asm/system.h>#include <linux/string.h>#include <linux/threads.h>#include <linux/interrupt.h>#include <linux/devfs_fs_kernel.h>#include <asm/hardirq.h>#include <asm/softirq.h>#include <asm/io.h>// for irkey#include <linux/kbd_ll.h>// for rawir#include <linux/fs.h>#include <linux/sched.h>#include <linux/fcntl.h>#include <linux/poll.h>#include <asm/uaccess.h>#include <linux/errno.h>#include <linux/spinlock.h>// local includes#include "os/os-generic.h"#include "os/os-sync.h"#include "os/helper-queue.h"#include "gpt/gpt_atom.h"#include "gpt/gpt_ports.h"#include "ir/ir_osi_device.h"#include "ir/ir_osi_acer_kbms.h"#include "ir/ir_osi_hitachi.h"#ifdef __IRCOMBO_DEBUG#define __DRV_DEBUG#endif#include "os/drv_debug.h"#include "os/pversion.h"#ifdef _IR_MOUSE_SUPPORT#include <busmouse.h> // linux/drivers/char/busmouse.h#define ACER_MOUSE_MINOR 11 // do you have a better minor code ? :-)//To prepare the device// cd /dev// mknod irmouse c 10 11// ln -f irmouse mousestatic int acer_mouse_init(void);static void acer_mouse_cleanup(void);#endif // _IR_MOUSE_SUPPORT#define RAWIR_MAJOR 100 // the major device number of rawir#define RAWIR_DRIVER_NAME "rawir" // the module name#define RAWIR_MAX_OPENS 5 // we enable rawir device to be opened by 5 times simutaniously#define RAWIR_QUEUE_SIZE 32 // the max number of events awaiting readingstatic int acer_kbms_init(void);static void acer_kbms_cleanup(void);static int raw_ir_init(void);static void raw_ir_cleanup(void);static void acer_kbms_event(UINT32 timediff);static void raw_ir_event(UINT32 timediff);#ifdef MODULEMODULE_AUTHOR("Yudong Yang / IBM CRL");MODULE_DESCRIPTION("Input driver for IBM Redwood onboard IR receiver port");#endif///////////////////////////////////////////////////////////////////////////////// Generic driver section///////////////////////////////////////////////////////////////////////////////static void *pMouseHandle=NULL;static void *_gpGPTPort=NULL;static __IR_DEVICE _gDevKBMS ={ init: NULL, deinit: NULL, event: acer_kbms_event};static __IR_DEVICE _gDevRawIR = { init: NULL, deinit: NULL, event: raw_ir_event};static int ir_inf_init(void){ if(_gpGPTPort) return 0; // already initialized#ifdef CONFIG_LAMAR PVERSION("IR-Combo for IBM Lamar");#else PVERSION("IR-Combo for IBM Redwood5");#endif if(acer_kbms_init() < 0) { PFATAL("AcerKBMS init failed!\n"); return -1; } if(raw_ir_init() < 0) { PFATAL("RawIR init failed!\n"); acer_kbms_cleanup(); return -1; }#if 0 _gpGPTPort = ioremap(__GPT_PORT_BASE, __GPT_PORT_RANGE); if(!_gpGPTPort) { PFATAL("GPT port IO Remap failed!\n"); raw_ir_cleanup(); acer_kbms_cleanup(); return -1; } gpt_atom_init_port(_gpGPTPort);#endif ir_osi_register_device(&_gDevKBMS); ir_osi_register_device(&_gDevRawIR); if(0 > ir_osi_init()) { PFATAL("IR OSI init failed!\n"); ir_osi_unregister_device(&_gDevKBMS); ir_osi_unregister_device(&_gDevRawIR);// gpt_atom_init_port(NULL);// iounmap(_gpGPTPort);// _gpGPTPort = NULL; raw_ir_cleanup(); acer_kbms_cleanup(); return -1; } if(ir_osi_start() == 0) return 0; PFATAL("start IR failed!\n"); // clean up now ir_osi_unregister_device(&_gDevKBMS); ir_osi_unregister_device(&_gDevRawIR);// gpt_atom_init_port(NULL);// iounmap(_gpGPTPort);// _gpGPTPort = NULL; raw_ir_cleanup(); acer_kbms_cleanup(); return -1;}static void ir_inf_deinit(void){ raw_ir_cleanup(); acer_kbms_cleanup(); ir_osi_unregister_device(&_gDevKBMS); ir_osi_unregister_device(&_gDevRawIR); ir_osi_stop(); ir_osi_deinit();// gpt_atom_init_port(NULL);// iounmap(_gpGPTPort);// _gpGPTPort = NULL;}module_init(ir_inf_init);module_exit(ir_inf_deinit);///////////////////////////////////////////////////////////////////////////////// RawIR driver section///////////////////////////////////////////////////////////////////////////////static ssize_t rawir_read(struct file *file, char *buffer, size_t length, loff_t * offset);static int rawir_open(struct inode *inode, struct file *file);static int rawir_release(struct inode *inode, struct file *file);static unsigned int rawir_poll(struct file *, struct poll_table_struct *);static int rawir_fasync(int fd, struct file *filp, int mode);static int rawir_open_count = 0;static struct file_operations RawIRFops = { read: rawir_read, poll: rawir_poll, /* poll */ open: rawir_open, release: rawir_release, /* a.k.a. close */ fasync: rawir_fasync, /* fasync */};typedef struct __RAWIR_DEVICE_SLOTS_STRUCT{ UINT32 queuebuf[RAWIR_QUEUE_SIZE]; // the buffer for queue QUEUE_T dataq; // queue where data is saved struct fasync_struct *async_queue; // for asyncronized access wait_queue_head_t wait; // my wait queue spinlock_t lock; // a lock for the queue when needed, hope will not struct __RAWIR_DEVICE_SLOTS_STRUCT *pNext; // my list of opened devices} RAWIR_DEVICE_SLOTS;static RAWIR_DEVICE_SLOTS *_gpRawIRSlots=NULL;static spinlock_t _g_irlock;static devfs_handle_t devfs_handle;static int raw_ir_init(void){ spin_lock_init(_g_irlock); _gpRawIRSlots=NULL; rawir_open_count = 0; if (devfs_register_chrdev(RAWIR_MAJOR, RAWIR_DRIVER_NAME, &RawIRFops) < 0) return -1; devfs_handle = devfs_find_handle(NULL, RAWIR_DRIVER_NAME, 0, 0, DEVFS_SPECIAL_CHR,0); if(devfs_handle == NULL) { devfs_handle = devfs_register(NULL, RAWIR_DRIVER_NAME, DEVFS_FL_DEFAULT, RAWIR_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR, &RawIRFops, NULL); } else devfs_handle = NULL; return 0;}static void raw_ir_cleanup(){ devfs_unregister_chrdev(RAWIR_MAJOR, RAWIR_DRIVER_NAME); if(devfs_handle != NULL) devfs_unregister(devfs_handle);}static void handle_raw_ir_code(USHORT uCode){ // I'm using spin_lock_bh, so no problem RAWIR_DEVICE_SLOTS *pSlot = _gpRawIRSlots; while(pSlot) { os_enqueue(&pSlot->dataq, &uCode); // FixMe: if this will race ? if(pSlot->async_queue) kill_fasync(&pSlot->async_queue, SIGIO, POLL_IN); wake_up_interruptible(&pSlot->wait); pSlot = pSlot->pNext; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -