blob: c551c0c88d8eacae3048ed9a539365017eaff065 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/drivers/char/ppdev.c
3 *
4 * This is the code behind /dev/parport* -- it allows a user-space
5 * application to use the parport subsystem.
6 *
7 * Copyright (C) 1998-2000, 2002 Tim Waugh <tim@cyberelk.net>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 *
14 * A /dev/parportx device node represents an arbitrary device
15 * on port 'x'. The following operations are possible:
16 *
17 * open do nothing, set up default IEEE 1284 protocol to be COMPAT
18 * close release port and unregister device (if necessary)
19 * ioctl
20 * EXCL register device exclusively (may fail)
21 * CLAIM (register device first time) parport_claim_or_block
22 * RELEASE parport_release
23 * SETMODE set the IEEE 1284 protocol to use for read/write
24 * SETPHASE set the IEEE 1284 phase of a particular mode. Not to be
25 * confused with ioctl(fd, SETPHASER, &stun). ;-)
26 * DATADIR data_forward / data_reverse
27 * WDATA write_data
28 * RDATA read_data
29 * WCONTROL write_control
30 * RCONTROL read_control
31 * FCONTROL frob_control
32 * RSTATUS read_status
33 * NEGOT parport_negotiate
34 * YIELD parport_yield_blocking
35 * WCTLONIRQ on interrupt, set control lines
36 * CLRIRQ clear (and return) interrupt count
37 * SETTIME sets device timeout (struct timeval)
38 * GETTIME gets device timeout (struct timeval)
39 * GETMODES gets hardware supported modes (unsigned int)
40 * GETMODE gets the current IEEE1284 mode
41 * GETPHASE gets the current IEEE1284 phase
42 * GETFLAGS gets current (user-visible) flags
43 * SETFLAGS sets current (user-visible) flags
44 * read/write read or write in current IEEE 1284 protocol
45 * select wait for interrupt (in readfds)
46 *
47 * Changes:
48 * Added SETTIME/GETTIME ioctl, Fred Barnes, 1999.
49 *
50 * Arnaldo Carvalho de Melo <acme@conectiva.com.br> 2000/08/25
51 * - On error, copy_from_user and copy_to_user do not return -EFAULT,
52 * They return the positive number of bytes *not* copied due to address
53 * space errors.
54 *
55 * Added GETMODES/GETMODE/GETPHASE ioctls, Fred Barnes <frmb2@ukc.ac.uk>, 03/01/2001.
56 * Added GETFLAGS/SETFLAGS ioctls, Fred Barnes, 04/2001
57 */
58
59#include <linux/module.h>
60#include <linux/init.h>
61#include <linux/sched.h>
62#include <linux/device.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070063#include <linux/ioctl.h>
64#include <linux/parport.h>
65#include <linux/ctype.h>
66#include <linux/poll.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090067#include <linux/slab.h>
Rene Hermane6a67842006-03-25 03:07:13 -080068#include <linux/major.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070069#include <linux/ppdev.h>
Arnd Bergmann613655f2010-06-02 14:28:52 +020070#include <linux/mutex.h>
Alan Cox6d535d32008-07-25 01:48:16 -070071#include <linux/uaccess.h>
Bamvor Jian Zhang17a35962016-01-08 15:50:49 +080072#include <linux/compat.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070073
74#define PP_VERSION "ppdev: user-space parallel port driver"
75#define CHRDEV "ppdev"
76
77struct pp_struct {
Sudip Mukherjeed85c1a22016-02-12 18:33:40 +053078 struct pardevice *pdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -070079 wait_queue_head_t irq_wait;
80 atomic_t irqc;
81 unsigned int flags;
82 int irqresponse;
83 unsigned char irqctl;
84 struct ieee1284_info state;
85 struct ieee1284_info saved_state;
86 long default_inactivity;
87};
88
89/* pp_struct.flags bitfields */
90#define PP_CLAIMED (1<<0)
91#define PP_EXCL (1<<1)
92
93/* Other constants */
94#define PP_INTERRUPT_TIMEOUT (10 * HZ) /* 10s */
95#define PP_BUFFER_SIZE 1024
96#define PARDEVICE_MAX 8
97
98/* ROUND_UP macro from fs/select.c */
99#define ROUND_UP(x,y) (((x)+(y)-1)/(y))
100
Arnd Bergmann613655f2010-06-02 14:28:52 +0200101static DEFINE_MUTEX(pp_do_mutex);
Bamvor Jian Zhang3b9ab372016-01-08 15:50:48 +0800102
103/* define fixed sized ioctl cmd for y2038 migration */
104#define PPGETTIME32 _IOR(PP_IOCTL, 0x95, s32[2])
105#define PPSETTIME32 _IOW(PP_IOCTL, 0x96, s32[2])
106#define PPGETTIME64 _IOR(PP_IOCTL, 0x95, s64[2])
107#define PPSETTIME64 _IOW(PP_IOCTL, 0x96, s64[2])
108
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530109static inline void pp_enable_irq(struct pp_struct *pp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110{
111 struct parport *port = pp->pdev->port;
Sudip Mukherjee27f3b8a2016-02-12 18:33:41 +0530112
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530113 port->ops->enable_irq(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114}
115
Sudip Mukherjeed85c1a22016-02-12 18:33:40 +0530116static ssize_t pp_read(struct file *file, char __user *buf, size_t count,
117 loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118{
Al Viro496ad9a2013-01-23 17:07:38 -0500119 unsigned int minor = iminor(file_inode(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 struct pp_struct *pp = file->private_data;
Sudip Mukherjeed85c1a22016-02-12 18:33:40 +0530121 char *kbuffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 ssize_t bytes_read = 0;
123 struct parport *pport;
124 int mode;
125
126 if (!(pp->flags & PP_CLAIMED)) {
127 /* Don't have the port claimed */
Michael Buesch81fc4012009-06-17 16:27:49 -0700128 pr_debug(CHRDEV "%x: claim the port first\n", minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129 return -EINVAL;
130 }
131
132 /* Trivial case. */
133 if (count == 0)
134 return 0;
135
136 kbuffer = kmalloc(min_t(size_t, count, PP_BUFFER_SIZE), GFP_KERNEL);
137 if (!kbuffer) {
138 return -ENOMEM;
139 }
140 pport = pp->pdev->port;
141 mode = pport->ieee1284.mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR);
142
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530143 parport_set_timeout(pp->pdev,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 (file->f_flags & O_NONBLOCK) ?
145 PARPORT_INACTIVITY_O_NONBLOCK :
146 pp->default_inactivity);
147
148 while (bytes_read == 0) {
149 ssize_t need = min_t(unsigned long, count, PP_BUFFER_SIZE);
150
151 if (mode == IEEE1284_MODE_EPP) {
152 /* various specials for EPP mode */
153 int flags = 0;
154 size_t (*fn)(struct parport *, void *, size_t, int);
155
156 if (pp->flags & PP_W91284PIC) {
157 flags |= PARPORT_W91284PIC;
158 }
159 if (pp->flags & PP_FASTREAD) {
160 flags |= PARPORT_EPP_FAST;
161 }
162 if (pport->ieee1284.mode & IEEE1284_ADDR) {
163 fn = pport->ops->epp_read_addr;
164 } else {
165 fn = pport->ops->epp_read_data;
166 }
167 bytes_read = (*fn)(pport, kbuffer, need, flags);
168 } else {
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530169 bytes_read = parport_read(pport, kbuffer, need);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 }
171
172 if (bytes_read != 0)
173 break;
174
175 if (file->f_flags & O_NONBLOCK) {
176 bytes_read = -EAGAIN;
177 break;
178 }
179
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530180 if (signal_pending(current)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 bytes_read = -ERESTARTSYS;
182 break;
183 }
184
185 cond_resched();
186 }
187
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530188 parport_set_timeout(pp->pdev, pp->default_inactivity);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530190 if (bytes_read > 0 && copy_to_user(buf, kbuffer, bytes_read))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 bytes_read = -EFAULT;
192
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530193 kfree(kbuffer);
194 pp_enable_irq(pp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 return bytes_read;
196}
197
Sudip Mukherjeed85c1a22016-02-12 18:33:40 +0530198static ssize_t pp_write(struct file *file, const char __user *buf,
199 size_t count, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200{
Al Viro496ad9a2013-01-23 17:07:38 -0500201 unsigned int minor = iminor(file_inode(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 struct pp_struct *pp = file->private_data;
Sudip Mukherjeed85c1a22016-02-12 18:33:40 +0530203 char *kbuffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 ssize_t bytes_written = 0;
205 ssize_t wrote;
206 int mode;
207 struct parport *pport;
208
209 if (!(pp->flags & PP_CLAIMED)) {
210 /* Don't have the port claimed */
Michael Buesch81fc4012009-06-17 16:27:49 -0700211 pr_debug(CHRDEV "%x: claim the port first\n", minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 return -EINVAL;
213 }
214
215 kbuffer = kmalloc(min_t(size_t, count, PP_BUFFER_SIZE), GFP_KERNEL);
216 if (!kbuffer) {
217 return -ENOMEM;
218 }
219 pport = pp->pdev->port;
220 mode = pport->ieee1284.mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR);
221
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530222 parport_set_timeout(pp->pdev,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 (file->f_flags & O_NONBLOCK) ?
224 PARPORT_INACTIVITY_O_NONBLOCK :
225 pp->default_inactivity);
226
227 while (bytes_written < count) {
228 ssize_t n = min_t(unsigned long, count - bytes_written, PP_BUFFER_SIZE);
229
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530230 if (copy_from_user(kbuffer, buf + bytes_written, n)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 bytes_written = -EFAULT;
232 break;
233 }
234
235 if ((pp->flags & PP_FASTWRITE) && (mode == IEEE1284_MODE_EPP)) {
236 /* do a fast EPP write */
237 if (pport->ieee1284.mode & IEEE1284_ADDR) {
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530238 wrote = pport->ops->epp_write_addr(pport,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 kbuffer, n, PARPORT_EPP_FAST);
240 } else {
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530241 wrote = pport->ops->epp_write_data(pport,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 kbuffer, n, PARPORT_EPP_FAST);
243 }
244 } else {
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530245 wrote = parport_write(pp->pdev->port, kbuffer, n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 }
247
248 if (wrote <= 0) {
249 if (!bytes_written) {
250 bytes_written = wrote;
251 }
252 break;
253 }
254
255 bytes_written += wrote;
256
257 if (file->f_flags & O_NONBLOCK) {
258 if (!bytes_written)
259 bytes_written = -EAGAIN;
260 break;
261 }
262
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530263 if (signal_pending(current))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265
266 cond_resched();
267 }
268
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530269 parport_set_timeout(pp->pdev, pp->default_inactivity);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530271 kfree(kbuffer);
272 pp_enable_irq(pp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 return bytes_written;
274}
275
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530276static void pp_irq(void *private)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277{
Jeff Garzik5712cb32007-10-19 02:54:26 -0400278 struct pp_struct *pp = private;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
280 if (pp->irqresponse) {
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530281 parport_write_control(pp->pdev->port, pp->irqctl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 pp->irqresponse = 0;
283 }
284
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530285 atomic_inc(&pp->irqc);
286 wake_up_interruptible(&pp->irq_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287}
288
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530289static int register_device(int minor, struct pp_struct *pp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290{
291 struct parport *port;
Sudip Mukherjeed85c1a22016-02-12 18:33:40 +0530292 struct pardevice *pdev = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 char *name;
294 int fl;
295
Julia Lawall87575432010-05-26 14:43:55 -0700296 name = kasprintf(GFP_KERNEL, CHRDEV "%x", minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 if (name == NULL)
298 return -ENOMEM;
299
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530300 port = parport_find_number(minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 if (!port) {
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530302 printk(KERN_WARNING "%s: no associated port!\n", name);
303 kfree(name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 return -ENXIO;
305 }
306
307 fl = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0;
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530308 pdev = parport_register_device(port, name, NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 NULL, pp_irq, fl, pp);
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530310 parport_put_port(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311
312 if (!pdev) {
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530313 printk(KERN_WARNING "%s: failed to register device!\n", name);
314 kfree(name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 return -ENXIO;
316 }
317
318 pp->pdev = pdev;
Michael Buesch81fc4012009-06-17 16:27:49 -0700319 pr_debug("%s: registered pardevice\n", name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 return 0;
321}
322
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530323static enum ieee1284_phase init_phase(int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324{
325 switch (mode & ~(IEEE1284_DEVICEID
326 | IEEE1284_ADDR)) {
327 case IEEE1284_MODE_NIBBLE:
328 case IEEE1284_MODE_BYTE:
329 return IEEE1284_PH_REV_IDLE;
330 }
331 return IEEE1284_PH_FWD_IDLE;
332}
333
Bamvor Jian Zhang3b9ab372016-01-08 15:50:48 +0800334static int pp_set_timeout(struct pardevice *pdev, long tv_sec, int tv_usec)
335{
336 long to_jiffies;
337
338 if ((tv_sec < 0) || (tv_usec < 0))
339 return -EINVAL;
340
341 to_jiffies = usecs_to_jiffies(tv_usec);
342 to_jiffies += tv_sec * HZ;
343 if (to_jiffies <= 0)
344 return -EINVAL;
345
346 pdev->timeout = to_jiffies;
347 return 0;
348}
349
Alan Cox6d535d32008-07-25 01:48:16 -0700350static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351{
Al Viro496ad9a2013-01-23 17:07:38 -0500352 unsigned int minor = iminor(file_inode(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 struct pp_struct *pp = file->private_data;
Sudip Mukherjeed85c1a22016-02-12 18:33:40 +0530354 struct parport *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 void __user *argp = (void __user *)arg;
356
357 /* First handle the cases that don't take arguments. */
358 switch (cmd) {
359 case PPCLAIM:
360 {
361 struct ieee1284_info *info;
362 int ret;
363
364 if (pp->flags & PP_CLAIMED) {
Michael Buesch81fc4012009-06-17 16:27:49 -0700365 pr_debug(CHRDEV "%x: you've already got it!\n", minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 return -EINVAL;
367 }
368
369 /* Deferred device registration. */
370 if (!pp->pdev) {
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530371 int err = register_device(minor, pp);
Sudip Mukherjee27f3b8a2016-02-12 18:33:41 +0530372
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 if (err) {
374 return err;
375 }
376 }
377
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530378 ret = parport_claim_or_block(pp->pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 if (ret < 0)
380 return ret;
381
382 pp->flags |= PP_CLAIMED;
383
384 /* For interrupt-reporting to work, we need to be
385 * informed of each interrupt. */
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530386 pp_enable_irq(pp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387
388 /* We may need to fix up the state machine. */
389 info = &pp->pdev->port->ieee1284;
390 pp->saved_state.mode = info->mode;
391 pp->saved_state.phase = info->phase;
392 info->mode = pp->state.mode;
393 info->phase = pp->state.phase;
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530394 pp->default_inactivity = parport_set_timeout(pp->pdev, 0);
395 parport_set_timeout(pp->pdev, pp->default_inactivity);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396
397 return 0;
398 }
399 case PPEXCL:
400 if (pp->pdev) {
Michael Buesch81fc4012009-06-17 16:27:49 -0700401 pr_debug(CHRDEV "%x: too late for PPEXCL; "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 "already registered\n", minor);
403 if (pp->flags & PP_EXCL)
404 /* But it's not really an error. */
405 return 0;
406 /* There's no chance of making the driver happy. */
407 return -EINVAL;
408 }
409
410 /* Just remember to register the device exclusively
411 * when we finally do the registration. */
412 pp->flags |= PP_EXCL;
413 return 0;
414 case PPSETMODE:
415 {
416 int mode;
Sudip Mukherjee27f3b8a2016-02-12 18:33:41 +0530417
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530418 if (copy_from_user(&mode, argp, sizeof(mode)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 return -EFAULT;
420 /* FIXME: validate mode */
421 pp->state.mode = mode;
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530422 pp->state.phase = init_phase(mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423
424 if (pp->flags & PP_CLAIMED) {
425 pp->pdev->port->ieee1284.mode = mode;
426 pp->pdev->port->ieee1284.phase = pp->state.phase;
427 }
428
429 return 0;
430 }
431 case PPGETMODE:
432 {
433 int mode;
434
435 if (pp->flags & PP_CLAIMED) {
436 mode = pp->pdev->port->ieee1284.mode;
437 } else {
438 mode = pp->state.mode;
439 }
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530440 if (copy_to_user(argp, &mode, sizeof(mode))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 return -EFAULT;
442 }
443 return 0;
444 }
445 case PPSETPHASE:
446 {
447 int phase;
Sudip Mukherjee27f3b8a2016-02-12 18:33:41 +0530448
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530449 if (copy_from_user(&phase, argp, sizeof(phase))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 return -EFAULT;
451 }
452 /* FIXME: validate phase */
453 pp->state.phase = phase;
454
455 if (pp->flags & PP_CLAIMED) {
456 pp->pdev->port->ieee1284.phase = phase;
457 }
458
459 return 0;
460 }
461 case PPGETPHASE:
462 {
463 int phase;
464
465 if (pp->flags & PP_CLAIMED) {
466 phase = pp->pdev->port->ieee1284.phase;
467 } else {
468 phase = pp->state.phase;
469 }
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530470 if (copy_to_user(argp, &phase, sizeof(phase))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 return -EFAULT;
472 }
473 return 0;
474 }
475 case PPGETMODES:
476 {
477 unsigned int modes;
478
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530479 port = parport_find_number(minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 if (!port)
481 return -ENODEV;
482
483 modes = port->modes;
Julia Lawalld98808a2011-05-26 16:25:59 -0700484 parport_put_port(port);
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530485 if (copy_to_user(argp, &modes, sizeof(modes))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 return -EFAULT;
487 }
488 return 0;
489 }
490 case PPSETFLAGS:
491 {
492 int uflags;
493
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530494 if (copy_from_user(&uflags, argp, sizeof(uflags))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 return -EFAULT;
496 }
497 pp->flags &= ~PP_FLAGMASK;
498 pp->flags |= (uflags & PP_FLAGMASK);
499 return 0;
500 }
501 case PPGETFLAGS:
502 {
503 int uflags;
504
505 uflags = pp->flags & PP_FLAGMASK;
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530506 if (copy_to_user(argp, &uflags, sizeof(uflags))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 return -EFAULT;
508 }
509 return 0;
510 }
511 } /* end switch() */
512
513 /* Everything else requires the port to be claimed, so check
514 * that now. */
515 if ((pp->flags & PP_CLAIMED) == 0) {
Michael Buesch81fc4012009-06-17 16:27:49 -0700516 pr_debug(CHRDEV "%x: claim the port first\n", minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 return -EINVAL;
518 }
519
520 port = pp->pdev->port;
521 switch (cmd) {
522 struct ieee1284_info *info;
523 unsigned char reg;
524 unsigned char mask;
525 int mode;
Bamvor Jian Zhang3b9ab372016-01-08 15:50:48 +0800526 s32 time32[2];
527 s64 time64[2];
528 struct timespec64 ts;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530
531 case PPRSTATUS:
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530532 reg = parport_read_status(port);
533 if (copy_to_user(argp, &reg, sizeof(reg)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 return -EFAULT;
535 return 0;
536 case PPRDATA:
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530537 reg = parport_read_data(port);
538 if (copy_to_user(argp, &reg, sizeof(reg)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 return -EFAULT;
540 return 0;
541 case PPRCONTROL:
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530542 reg = parport_read_control(port);
543 if (copy_to_user(argp, &reg, sizeof(reg)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 return -EFAULT;
545 return 0;
546 case PPYIELD:
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530547 parport_yield_blocking(pp->pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 return 0;
549
550 case PPRELEASE:
551 /* Save the state machine's state. */
552 info = &pp->pdev->port->ieee1284;
553 pp->state.mode = info->mode;
554 pp->state.phase = info->phase;
555 info->mode = pp->saved_state.mode;
556 info->phase = pp->saved_state.phase;
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530557 parport_release(pp->pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 pp->flags &= ~PP_CLAIMED;
559 return 0;
560
561 case PPWCONTROL:
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530562 if (copy_from_user(&reg, argp, sizeof(reg)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 return -EFAULT;
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530564 parport_write_control(port, reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 return 0;
566
567 case PPWDATA:
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530568 if (copy_from_user(&reg, argp, sizeof(reg)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 return -EFAULT;
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530570 parport_write_data(port, reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 return 0;
572
573 case PPFCONTROL:
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530574 if (copy_from_user(&mask, argp,
575 sizeof(mask)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 return -EFAULT;
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530577 if (copy_from_user(&reg, 1 + (unsigned char __user *) arg,
578 sizeof(reg)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 return -EFAULT;
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530580 parport_frob_control(port, mask, reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 return 0;
582
583 case PPDATADIR:
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530584 if (copy_from_user(&mode, argp, sizeof(mode)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 return -EFAULT;
586 if (mode)
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530587 port->ops->data_reverse(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 else
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530589 port->ops->data_forward(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 return 0;
591
592 case PPNEGOT:
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530593 if (copy_from_user(&mode, argp, sizeof(mode)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 return -EFAULT;
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530595 switch ((ret = parport_negotiate(port, mode))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 case 0: break;
597 case -1: /* handshake failed, peripheral not IEEE 1284 */
598 ret = -EIO;
599 break;
600 case 1: /* handshake succeeded, peripheral rejected mode */
601 ret = -ENXIO;
602 break;
603 }
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530604 pp_enable_irq(pp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 return ret;
606
607 case PPWCTLONIRQ:
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530608 if (copy_from_user(&reg, argp, sizeof(reg)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 return -EFAULT;
610
611 /* Remember what to set the control lines to, for next
612 * time we get an interrupt. */
613 pp->irqctl = reg;
614 pp->irqresponse = 1;
615 return 0;
616
617 case PPCLRIRQ:
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530618 ret = atomic_read(&pp->irqc);
619 if (copy_to_user(argp, &ret, sizeof(ret)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 return -EFAULT;
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530621 atomic_sub(ret, &pp->irqc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 return 0;
623
Bamvor Jian Zhang3b9ab372016-01-08 15:50:48 +0800624 case PPSETTIME32:
625 if (copy_from_user(time32, argp, sizeof(time32)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 return -EFAULT;
Bamvor Jian Zhang3b9ab372016-01-08 15:50:48 +0800627
628 return pp_set_timeout(pp->pdev, time32[0], time32[1]);
629
630 case PPSETTIME64:
631 if (copy_from_user(time64, argp, sizeof(time64)))
632 return -EFAULT;
633
634 return pp_set_timeout(pp->pdev, time64[0], time64[1]);
635
636 case PPGETTIME32:
637 jiffies_to_timespec64(pp->pdev->timeout, &ts);
638 time32[0] = ts.tv_sec;
639 time32[1] = ts.tv_nsec / NSEC_PER_USEC;
640 if ((time32[0] < 0) || (time32[1] < 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 return -EINVAL;
Bamvor Jian Zhang3b9ab372016-01-08 15:50:48 +0800642
643 if (copy_to_user(argp, time32, sizeof(time32)))
644 return -EFAULT;
645
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 return 0;
647
Bamvor Jian Zhang3b9ab372016-01-08 15:50:48 +0800648 case PPGETTIME64:
649 jiffies_to_timespec64(pp->pdev->timeout, &ts);
650 time64[0] = ts.tv_sec;
651 time64[1] = ts.tv_nsec / NSEC_PER_USEC;
652 if ((time64[0] < 0) || (time64[1] < 0))
653 return -EINVAL;
654
655 if (copy_to_user(argp, time64, sizeof(time64)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 return -EFAULT;
Bamvor Jian Zhang3b9ab372016-01-08 15:50:48 +0800657
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 return 0;
659
660 default:
Michael Buesch81fc4012009-06-17 16:27:49 -0700661 pr_debug(CHRDEV "%x: What? (cmd=0x%x)\n", minor, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 return -EINVAL;
663 }
664
665 /* Keep the compiler happy */
666 return 0;
667}
668
Alan Cox6d535d32008-07-25 01:48:16 -0700669static long pp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
670{
671 long ret;
Sudip Mukherjee27f3b8a2016-02-12 18:33:41 +0530672
Arnd Bergmann613655f2010-06-02 14:28:52 +0200673 mutex_lock(&pp_do_mutex);
Alan Cox6d535d32008-07-25 01:48:16 -0700674 ret = pp_do_ioctl(file, cmd, arg);
Arnd Bergmann613655f2010-06-02 14:28:52 +0200675 mutex_unlock(&pp_do_mutex);
Alan Cox6d535d32008-07-25 01:48:16 -0700676 return ret;
677}
678
Bamvor Jian Zhang17a35962016-01-08 15:50:49 +0800679#ifdef CONFIG_COMPAT
680static long pp_compat_ioctl(struct file *file, unsigned int cmd,
681 unsigned long arg)
682{
683 return pp_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
684}
685#endif
686
Sudip Mukherjeed85c1a22016-02-12 18:33:40 +0530687static int pp_open(struct inode *inode, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688{
689 unsigned int minor = iminor(inode);
690 struct pp_struct *pp;
691
692 if (minor >= PARPORT_MAX)
693 return -ENXIO;
694
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530695 pp = kmalloc(sizeof(struct pp_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 if (!pp)
697 return -ENOMEM;
698
699 pp->state.mode = IEEE1284_MODE_COMPAT;
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530700 pp->state.phase = init_phase(pp->state.mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 pp->flags = 0;
702 pp->irqresponse = 0;
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530703 atomic_set(&pp->irqc, 0);
704 init_waitqueue_head(&pp->irq_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705
706 /* Defer the actual device registration until the first claim.
707 * That way, we know whether or not the driver wants to have
708 * exclusive access to the port (PPEXCL).
709 */
710 pp->pdev = NULL;
711 file->private_data = pp;
712
713 return 0;
714}
715
Sudip Mukherjeed85c1a22016-02-12 18:33:40 +0530716static int pp_release(struct inode *inode, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717{
718 unsigned int minor = iminor(inode);
719 struct pp_struct *pp = file->private_data;
720 int compat_negot;
721
722 compat_negot = 0;
723 if (!(pp->flags & PP_CLAIMED) && pp->pdev &&
724 (pp->state.mode != IEEE1284_MODE_COMPAT)) {
725 struct ieee1284_info *info;
726
727 /* parport released, but not in compatibility mode */
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530728 parport_claim_or_block(pp->pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 pp->flags |= PP_CLAIMED;
730 info = &pp->pdev->port->ieee1284;
731 pp->saved_state.mode = info->mode;
732 pp->saved_state.phase = info->phase;
733 info->mode = pp->state.mode;
734 info->phase = pp->state.phase;
735 compat_negot = 1;
736 } else if ((pp->flags & PP_CLAIMED) && pp->pdev &&
737 (pp->pdev->port->ieee1284.mode != IEEE1284_MODE_COMPAT)) {
738 compat_negot = 2;
739 }
740 if (compat_negot) {
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530741 parport_negotiate(pp->pdev->port, IEEE1284_MODE_COMPAT);
Michael Buesch81fc4012009-06-17 16:27:49 -0700742 pr_debug(CHRDEV "%x: negotiated back to compatibility "
743 "mode because user-space forgot\n", minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 }
745
746 if (pp->flags & PP_CLAIMED) {
747 struct ieee1284_info *info;
748
749 info = &pp->pdev->port->ieee1284;
750 pp->state.mode = info->mode;
751 pp->state.phase = info->phase;
752 info->mode = pp->saved_state.mode;
753 info->phase = pp->saved_state.phase;
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530754 parport_release(pp->pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 if (compat_negot != 1) {
Michael Buesch81fc4012009-06-17 16:27:49 -0700756 pr_debug(CHRDEV "%x: released pardevice "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 "because user-space forgot\n", minor);
758 }
759 }
760
761 if (pp->pdev) {
762 const char *name = pp->pdev->name;
Sudip Mukherjee27f3b8a2016-02-12 18:33:41 +0530763
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530764 parport_unregister_device(pp->pdev);
765 kfree(name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 pp->pdev = NULL;
Michael Buesch81fc4012009-06-17 16:27:49 -0700767 pr_debug(CHRDEV "%x: unregistered pardevice\n", minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 }
769
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530770 kfree(pp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771
772 return 0;
773}
774
775/* No kernel lock held - fine */
Sudip Mukherjeed85c1a22016-02-12 18:33:40 +0530776static unsigned int pp_poll(struct file *file, poll_table *wait)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777{
778 struct pp_struct *pp = file->private_data;
779 unsigned int mask = 0;
780
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530781 poll_wait(file, &pp->irq_wait, wait);
782 if (atomic_read(&pp->irqc))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 mask |= POLLIN | POLLRDNORM;
784
785 return mask;
786}
787
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800788static struct class *ppdev_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789
Arjan van de Ven62322d22006-07-03 00:24:21 -0700790static const struct file_operations pp_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 .owner = THIS_MODULE,
792 .llseek = no_llseek,
793 .read = pp_read,
794 .write = pp_write,
795 .poll = pp_poll,
Alan Cox6d535d32008-07-25 01:48:16 -0700796 .unlocked_ioctl = pp_ioctl,
Bamvor Jian Zhang17a35962016-01-08 15:50:49 +0800797#ifdef CONFIG_COMPAT
798 .compat_ioctl = pp_compat_ioctl,
799#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 .open = pp_open,
801 .release = pp_release,
802};
803
804static void pp_attach(struct parport *port)
805{
Greg Kroah-Hartman03457cd2008-07-21 20:03:34 -0700806 device_create(ppdev_class, port->dev, MKDEV(PP_MAJOR, port->number),
807 NULL, "parport%d", port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808}
809
810static void pp_detach(struct parport *port)
811{
Greg Kroah-Hartman04880ed2006-09-12 17:00:10 +0200812 device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813}
814
815static struct parport_driver pp_driver = {
816 .name = CHRDEV,
817 .attach = pp_attach,
818 .detach = pp_detach,
819};
820
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530821static int __init ppdev_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822{
Greg Kroah-Hartman8ab5e4c2005-06-20 21:15:16 -0700823 int err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530825 if (register_chrdev(PP_MAJOR, CHRDEV, &pp_fops)) {
826 printk(KERN_WARNING CHRDEV ": unable to get major %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 PP_MAJOR);
828 return -EIO;
829 }
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800830 ppdev_class = class_create(THIS_MODULE, CHRDEV);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 if (IS_ERR(ppdev_class)) {
832 err = PTR_ERR(ppdev_class);
833 goto out_chrdev;
834 }
Alexey Khoroshilov9a32bb32012-09-02 00:31:58 +0400835 err = parport_register_driver(&pp_driver);
836 if (err < 0) {
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530837 printk(KERN_WARNING CHRDEV ": unable to register with parport\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 goto out_class;
839 }
840
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530841 printk(KERN_INFO PP_VERSION "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 goto out;
843
844out_class:
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800845 class_destroy(ppdev_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846out_chrdev:
847 unregister_chrdev(PP_MAJOR, CHRDEV);
848out:
849 return err;
850}
851
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530852static void __exit ppdev_cleanup(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 /* Clean up all parport stuff */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 parport_unregister_driver(&pp_driver);
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800856 class_destroy(ppdev_class);
Sudip Mukherjee783ea442016-02-12 18:33:39 +0530857 unregister_chrdev(PP_MAJOR, CHRDEV);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858}
859
860module_init(ppdev_init);
861module_exit(ppdev_cleanup);
862
863MODULE_LICENSE("GPL");
864MODULE_ALIAS_CHARDEV_MAJOR(PP_MAJOR);