This source file includes following definitions.
- parkbd_readlines
- parkbd_writelines
- parkbd_write
- parkbd_interrupt
- parkbd_getport
- parkbd_allocate_serio
- parkbd_attach
- parkbd_detach
- parkbd_init
- parkbd_exit
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 
  33 
  34 
  35 
  36 
  37 
  38 
  39 
  40 
  41 
  42 
  43 #include <linux/module.h>
  44 #include <linux/parport.h>
  45 #include <linux/slab.h>
  46 #include <linux/init.h>
  47 #include <linux/serio.h>
  48 
  49 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
  50 MODULE_DESCRIPTION("Parallel port to Keyboard port adapter driver");
  51 MODULE_LICENSE("GPL");
  52 
  53 static unsigned int parkbd_pp_no;
  54 module_param_named(port, parkbd_pp_no, int, 0);
  55 MODULE_PARM_DESC(port, "Parallel port the adapter is connected to (default is 0)");
  56 
  57 static unsigned int parkbd_mode = SERIO_8042;
  58 module_param_named(mode, parkbd_mode, uint, 0);
  59 MODULE_PARM_DESC(mode, "Mode of operation: XT = 0/AT = 1 (default)");
  60 
  61 #define PARKBD_CLOCK    0x01    
  62 #define PARKBD_DATA     0x02    
  63 
  64 static int parkbd_buffer;
  65 static int parkbd_counter;
  66 static unsigned long parkbd_last;
  67 static int parkbd_writing;
  68 static unsigned long parkbd_start;
  69 
  70 static struct pardevice *parkbd_dev;
  71 static struct serio *parkbd_port;
  72 
  73 static int parkbd_readlines(void)
  74 {
  75         return (parport_read_status(parkbd_dev->port) >> 6) ^ 2;
  76 }
  77 
  78 static void parkbd_writelines(int data)
  79 {
  80         parport_write_control(parkbd_dev->port, (~data & 3) | 0x10);
  81 }
  82 
  83 static int parkbd_write(struct serio *port, unsigned char c)
  84 {
  85         unsigned char p;
  86 
  87         if (!parkbd_mode) return -1;
  88 
  89         p = c ^ (c >> 4);
  90         p = p ^ (p >> 2);
  91         p = p ^ (p >> 1);
  92 
  93         parkbd_counter = 0;
  94         parkbd_writing = 1;
  95         parkbd_buffer = c | (((int) (~p & 1)) << 8) | 0x600;
  96 
  97         parkbd_writelines(2);
  98 
  99         return 0;
 100 }
 101 
 102 static void parkbd_interrupt(void *dev_id)
 103 {
 104 
 105         if (parkbd_writing) {
 106 
 107                 if (parkbd_counter && ((parkbd_counter == 11) || time_after(jiffies, parkbd_last + HZ/100))) {
 108                         parkbd_counter = 0;
 109                         parkbd_buffer = 0;
 110                         parkbd_writing = 0;
 111                         parkbd_writelines(3);
 112                         return;
 113                 }
 114 
 115                 parkbd_writelines(((parkbd_buffer >> parkbd_counter++) & 1) | 2);
 116 
 117                 if (parkbd_counter == 11) {
 118                         parkbd_counter = 0;
 119                         parkbd_buffer = 0;
 120                         parkbd_writing = 0;
 121                         parkbd_writelines(3);
 122                 }
 123 
 124         } else {
 125 
 126                 if ((parkbd_counter == parkbd_mode + 10) || time_after(jiffies, parkbd_last + HZ/100)) {
 127                         parkbd_counter = 0;
 128                         parkbd_buffer = 0;
 129                 }
 130 
 131                 parkbd_buffer |= (parkbd_readlines() >> 1) << parkbd_counter++;
 132 
 133                 if (parkbd_counter == parkbd_mode + 10)
 134                         serio_interrupt(parkbd_port, (parkbd_buffer >> (2 - parkbd_mode)) & 0xff, 0);
 135         }
 136 
 137         parkbd_last = jiffies;
 138 }
 139 
 140 static int parkbd_getport(struct parport *pp)
 141 {
 142         struct pardev_cb parkbd_parport_cb;
 143 
 144         memset(&parkbd_parport_cb, 0, sizeof(parkbd_parport_cb));
 145         parkbd_parport_cb.irq_func = parkbd_interrupt;
 146         parkbd_parport_cb.flags = PARPORT_FLAG_EXCL;
 147 
 148         parkbd_dev = parport_register_dev_model(pp, "parkbd",
 149                                                 &parkbd_parport_cb, 0);
 150 
 151         if (!parkbd_dev)
 152                 return -ENODEV;
 153 
 154         if (parport_claim(parkbd_dev)) {
 155                 parport_unregister_device(parkbd_dev);
 156                 return -EBUSY;
 157         }
 158 
 159         parkbd_start = jiffies;
 160 
 161         return 0;
 162 }
 163 
 164 static struct serio *parkbd_allocate_serio(void)
 165 {
 166         struct serio *serio;
 167 
 168         serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
 169         if (serio) {
 170                 serio->id.type = parkbd_mode;
 171                 serio->write = parkbd_write,
 172                 strlcpy(serio->name, "PARKBD AT/XT keyboard adapter", sizeof(serio->name));
 173                 snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", parkbd_dev->port->name);
 174         }
 175 
 176         return serio;
 177 }
 178 
 179 static void parkbd_attach(struct parport *pp)
 180 {
 181         if (pp->number != parkbd_pp_no) {
 182                 pr_debug("Not using parport%d.\n", pp->number);
 183                 return;
 184         }
 185 
 186         if (parkbd_getport(pp))
 187                 return;
 188 
 189         parkbd_port = parkbd_allocate_serio();
 190         if (!parkbd_port) {
 191                 parport_release(parkbd_dev);
 192                 parport_unregister_device(parkbd_dev);
 193                 return;
 194         }
 195 
 196         parkbd_writelines(3);
 197 
 198         serio_register_port(parkbd_port);
 199 
 200         printk(KERN_INFO "serio: PARKBD %s adapter on %s\n",
 201                         parkbd_mode ? "AT" : "XT", parkbd_dev->port->name);
 202 
 203         return;
 204 }
 205 
 206 static void parkbd_detach(struct parport *port)
 207 {
 208         if (!parkbd_port || port->number != parkbd_pp_no)
 209                 return;
 210 
 211         parport_release(parkbd_dev);
 212         serio_unregister_port(parkbd_port);
 213         parport_unregister_device(parkbd_dev);
 214         parkbd_port = NULL;
 215 }
 216 
 217 static struct parport_driver parkbd_parport_driver = {
 218         .name = "parkbd",
 219         .match_port = parkbd_attach,
 220         .detach = parkbd_detach,
 221         .devmodel = true,
 222 };
 223 
 224 static int __init parkbd_init(void)
 225 {
 226         return parport_register_driver(&parkbd_parport_driver);
 227 }
 228 
 229 static void __exit parkbd_exit(void)
 230 {
 231         parport_unregister_driver(&parkbd_parport_driver);
 232 }
 233 
 234 module_init(parkbd_init);
 235 module_exit(parkbd_exit);