2 * Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz>
3 * Copyright (c) 2001, 2007 Johann Deneux <johann.deneux@gmail.com>
5 * USB/RS232 I-Force joysticks and wheels.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 void iforce_serial_xmit(struct iforce
*iforce
)
32 if (test_and_set_bit(IFORCE_XMIT_RUNNING
, iforce
->xmit_flags
)) {
33 set_bit(IFORCE_XMIT_AGAIN
, iforce
->xmit_flags
);
37 spin_lock_irqsave(&iforce
->xmit_lock
, flags
);
40 if (iforce
->xmit
.head
== iforce
->xmit
.tail
) {
41 clear_bit(IFORCE_XMIT_RUNNING
, iforce
->xmit_flags
);
42 spin_unlock_irqrestore(&iforce
->xmit_lock
, flags
);
48 serio_write(iforce
->serio
, 0x2b);
50 serio_write(iforce
->serio
, iforce
->xmit
.buf
[iforce
->xmit
.tail
]);
51 cs
^= iforce
->xmit
.buf
[iforce
->xmit
.tail
];
52 XMIT_INC(iforce
->xmit
.tail
, 1);
54 for (i
=iforce
->xmit
.buf
[iforce
->xmit
.tail
]; i
>= 0; --i
) {
55 serio_write(iforce
->serio
, iforce
->xmit
.buf
[iforce
->xmit
.tail
]);
56 cs
^= iforce
->xmit
.buf
[iforce
->xmit
.tail
];
57 XMIT_INC(iforce
->xmit
.tail
, 1);
60 serio_write(iforce
->serio
, cs
);
62 if (test_and_clear_bit(IFORCE_XMIT_AGAIN
, iforce
->xmit_flags
))
65 clear_bit(IFORCE_XMIT_RUNNING
, iforce
->xmit_flags
);
67 spin_unlock_irqrestore(&iforce
->xmit_lock
, flags
);
70 static void iforce_serio_write_wakeup(struct serio
*serio
)
72 struct iforce
*iforce
= serio_get_drvdata(serio
);
74 iforce_serial_xmit(iforce
);
77 static irqreturn_t
iforce_serio_irq(struct serio
*serio
,
78 unsigned char data
, unsigned int flags
)
80 struct iforce
*iforce
= serio_get_drvdata(serio
);
89 if (data
> 3 && data
!= 0xff)
97 if (data
> IFORCE_MAX_LENGTH
) {
106 if (iforce
->idx
< iforce
->len
) {
107 iforce
->csum
+= iforce
->data
[iforce
->idx
++] = data
;
111 if (iforce
->idx
== iforce
->len
) {
112 iforce_process_packet(iforce
, (iforce
->id
<< 8) | iforce
->idx
, iforce
->data
);
123 static int iforce_serio_connect(struct serio
*serio
, struct serio_driver
*drv
)
125 struct iforce
*iforce
;
128 iforce
= kzalloc(sizeof(struct iforce
), GFP_KERNEL
);
132 iforce
->bus
= IFORCE_232
;
133 iforce
->serio
= serio
;
135 serio_set_drvdata(serio
, iforce
);
137 err
= serio_open(serio
, drv
);
141 err
= iforce_init_device(iforce
);
147 fail2
: serio_close(serio
);
148 fail1
: serio_set_drvdata(serio
, NULL
);
153 static void iforce_serio_disconnect(struct serio
*serio
)
155 struct iforce
*iforce
= serio_get_drvdata(serio
);
157 input_unregister_device(iforce
->dev
);
159 serio_set_drvdata(serio
, NULL
);
163 static const struct serio_device_id iforce_serio_ids
[] = {
166 .proto
= SERIO_IFORCE
,
173 MODULE_DEVICE_TABLE(serio
, iforce_serio_ids
);
175 struct serio_driver iforce_serio_drv
= {
179 .description
= "RS232 I-Force joysticks and wheels driver",
180 .id_table
= iforce_serio_ids
,
181 .write_wakeup
= iforce_serio_write_wakeup
,
182 .interrupt
= iforce_serio_irq
,
183 .connect
= iforce_serio_connect
,
184 .disconnect
= iforce_serio_disconnect
,