1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
2 | /* |
3 | * Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz> |
4 | * Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com> |
5 | * |
6 | * USB/RS232 I-Force joysticks and wheels. |
7 | */ |
8 | |
9 | #include <linux/kernel.h> |
10 | #include <linux/slab.h> |
11 | #include <linux/input.h> |
12 | #include <linux/module.h> |
13 | #include <linux/spinlock.h> |
14 | #include <linux/circ_buf.h> |
15 | #include <linux/mutex.h> |
16 | |
17 | /* This module provides arbitrary resource management routines. |
18 | * I use it to manage the device's memory. |
19 | * Despite the name of this module, I am *not* going to access the ioports. |
20 | */ |
21 | #include <linux/ioport.h> |
22 | |
23 | |
24 | #define IFORCE_MAX_LENGTH 16 |
25 | |
26 | #define IFORCE_EFFECTS_MAX 32 |
27 | |
28 | /* Each force feedback effect is made of one core effect, which can be |
29 | * associated to at most to effect modifiers |
30 | */ |
31 | #define FF_MOD1_IS_USED 0 |
32 | #define FF_MOD2_IS_USED 1 |
33 | #define FF_CORE_IS_USED 2 |
34 | #define FF_CORE_IS_PLAYED 3 /* Effect is currently being played */ |
35 | #define FF_CORE_SHOULD_PLAY 4 /* User wants the effect to be played */ |
36 | #define FF_CORE_UPDATE 5 /* Effect is being updated */ |
37 | #define FF_MODCORE_CNT 6 |
38 | |
39 | struct iforce_core_effect { |
40 | /* Information about where modifiers are stored in the device's memory */ |
41 | struct resource mod1_chunk; |
42 | struct resource mod2_chunk; |
43 | unsigned long flags[BITS_TO_LONGS(FF_MODCORE_CNT)]; |
44 | }; |
45 | |
46 | #define FF_CMD_EFFECT 0x010e |
47 | #define FF_CMD_ENVELOPE 0x0208 |
48 | #define FF_CMD_MAGNITUDE 0x0303 |
49 | #define FF_CMD_PERIOD 0x0407 |
50 | #define FF_CMD_CONDITION 0x050a |
51 | |
52 | #define FF_CMD_AUTOCENTER 0x4002 |
53 | #define FF_CMD_PLAY 0x4103 |
54 | #define FF_CMD_ENABLE 0x4201 |
55 | #define FF_CMD_GAIN 0x4301 |
56 | |
57 | #define FF_CMD_QUERY 0xff01 |
58 | |
59 | /* Buffer for async write */ |
60 | #define XMIT_SIZE 256 |
61 | #define XMIT_INC(var, n) (var)+=n; (var)&= XMIT_SIZE -1 |
62 | /* iforce::xmit_flags */ |
63 | #define IFORCE_XMIT_RUNNING 0 |
64 | #define IFORCE_XMIT_AGAIN 1 |
65 | |
66 | struct iforce_device { |
67 | u16 idvendor; |
68 | u16 idproduct; |
69 | char *name; |
70 | signed short *btn; |
71 | signed short *abs; |
72 | signed short *ff; |
73 | }; |
74 | |
75 | struct iforce; |
76 | |
77 | struct iforce_xport_ops { |
78 | void (*xmit)(struct iforce *iforce); |
79 | int (*get_id)(struct iforce *iforce, u8 id, |
80 | u8 *response_data, size_t *response_len); |
81 | int (*start_io)(struct iforce *iforce); |
82 | void (*stop_io)(struct iforce *iforce); |
83 | }; |
84 | |
85 | struct iforce { |
86 | struct input_dev *dev; /* Input device interface */ |
87 | struct iforce_device *type; |
88 | const struct iforce_xport_ops *xport_ops; |
89 | |
90 | spinlock_t xmit_lock; |
91 | /* Buffer used for asynchronous sending of bytes to the device */ |
92 | struct circ_buf xmit; |
93 | unsigned char xmit_data[XMIT_SIZE]; |
94 | unsigned long xmit_flags[1]; |
95 | |
96 | /* Force Feedback */ |
97 | wait_queue_head_t wait; |
98 | struct resource device_memory; |
99 | struct iforce_core_effect core_effects[IFORCE_EFFECTS_MAX]; |
100 | struct mutex mem_mutex; |
101 | }; |
102 | |
103 | /* Get hi and low bytes of a 16-bits int */ |
104 | #define HI(a) ((unsigned char)((a) >> 8)) |
105 | #define LO(a) ((unsigned char)((a) & 0xff)) |
106 | |
107 | /* For many parameters, it seems that 0x80 is a special value that should |
108 | * be avoided. Instead, we replace this value by 0x7f |
109 | */ |
110 | #define HIFIX80(a) ((unsigned char)(((a)<0? (a)+255 : (a))>>8)) |
111 | |
112 | /* Encode a time value */ |
113 | #define TIME_SCALE(a) (a) |
114 | |
115 | static inline int iforce_get_id_packet(struct iforce *iforce, u8 id, |
116 | u8 *response_data, size_t *response_len) |
117 | { |
118 | return iforce->xport_ops->get_id(iforce, id, |
119 | response_data, response_len); |
120 | } |
121 | |
122 | static inline void iforce_clear_xmit_and_wake(struct iforce *iforce) |
123 | { |
124 | clear_bit(IFORCE_XMIT_RUNNING, addr: iforce->xmit_flags); |
125 | wake_up_all(&iforce->wait); |
126 | } |
127 | |
128 | /* Public functions */ |
129 | /* iforce-main.c */ |
130 | int iforce_init_device(struct device *parent, u16 bustype, |
131 | struct iforce *iforce); |
132 | |
133 | /* iforce-packets.c */ |
134 | int iforce_control_playback(struct iforce*, u16 id, unsigned int); |
135 | void iforce_process_packet(struct iforce *iforce, |
136 | u8 packet_id, u8 *data, size_t len); |
137 | int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data); |
138 | void iforce_dump_packet(struct iforce *iforce, char *msg, u16 cmd, unsigned char *data); |
139 | |
140 | /* iforce-ff.c */ |
141 | int iforce_upload_periodic(struct iforce *, struct ff_effect *, struct ff_effect *); |
142 | int iforce_upload_constant(struct iforce *, struct ff_effect *, struct ff_effect *); |
143 | int iforce_upload_condition(struct iforce *, struct ff_effect *, struct ff_effect *); |
144 | |
145 | /* Public variables */ |
146 | extern struct serio_driver iforce_serio_drv; |
147 | extern struct usb_driver iforce_usb_driver; |
148 | |