64 |
64 |
65 static struct tty_driver *tty_driver = NULL; |
65 static struct tty_driver *tty_driver = NULL; |
66 ec_tty_t *ttys[EC_TTY_MAX_DEVICES]; |
66 ec_tty_t *ttys[EC_TTY_MAX_DEVICES]; |
67 struct semaphore tty_sem; |
67 struct semaphore tty_sem; |
68 |
68 |
|
69 void ec_tty_wakeup(unsigned long); |
|
70 |
69 /*****************************************************************************/ |
71 /*****************************************************************************/ |
70 |
72 |
71 /** \cond */ |
73 /** \cond */ |
72 |
74 |
73 MODULE_AUTHOR("Florian Pose <fp@igh-essen.com>"); |
75 MODULE_AUTHOR("Florian Pose <fp@igh-essen.com>"); |
175 tty_unregister_driver(tty_driver); |
177 tty_unregister_driver(tty_driver); |
176 put_tty_driver(tty_driver); |
178 put_tty_driver(tty_driver); |
177 printk(KERN_INFO PFX "Module unloading.\n"); |
179 printk(KERN_INFO PFX "Module unloading.\n"); |
178 } |
180 } |
179 |
181 |
180 /*****************************************************************************/ |
182 /****************************************************************************** |
181 |
183 * ec_tty_t methods. |
182 unsigned int ec_tty_tx_size(ec_tty_t *tty) |
184 *****************************************************************************/ |
183 { |
|
184 unsigned int ret; |
|
185 |
|
186 if (tty->tx_write_idx >= tty->tx_read_idx) { |
|
187 ret = tty->tx_write_idx - tty->tx_read_idx; |
|
188 } else { |
|
189 ret = EC_TTY_TX_BUFFER_SIZE + tty->tx_write_idx - tty->tx_read_idx; |
|
190 } |
|
191 |
|
192 return ret; |
|
193 } |
|
194 |
|
195 /*****************************************************************************/ |
|
196 |
|
197 unsigned int ec_tty_tx_space(ec_tty_t *tty) |
|
198 { |
|
199 return EC_TTY_TX_BUFFER_SIZE - 1 - ec_tty_tx_size(tty); |
|
200 } |
|
201 |
|
202 /*****************************************************************************/ |
|
203 |
|
204 unsigned int ec_tty_rx_size(ec_tty_t *tty) |
|
205 { |
|
206 unsigned int ret; |
|
207 |
|
208 if (tty->rx_write_idx >= tty->rx_read_idx) { |
|
209 ret = tty->rx_write_idx - tty->rx_read_idx; |
|
210 } else { |
|
211 ret = EC_TTY_RX_BUFFER_SIZE + tty->rx_write_idx - tty->rx_read_idx; |
|
212 } |
|
213 |
|
214 return ret; |
|
215 } |
|
216 |
|
217 /*****************************************************************************/ |
|
218 |
|
219 unsigned int ec_tty_rx_space(ec_tty_t *tty) |
|
220 { |
|
221 return EC_TTY_RX_BUFFER_SIZE - 1 - ec_tty_rx_size(tty); |
|
222 } |
|
223 |
|
224 /*****************************************************************************/ |
|
225 |
|
226 void ec_tty_wakeup(unsigned long data) |
|
227 { |
|
228 ec_tty_t *tty = (ec_tty_t *) data; |
|
229 size_t to_recv; |
|
230 |
|
231 /* Wake up any process waiting to send data */ |
|
232 if (tty->wakeup) { |
|
233 if (tty->tty) { |
|
234 #if EC_TTY_DEBUG >= 1 |
|
235 printk(KERN_INFO PFX "Waking up.\n"); |
|
236 #endif |
|
237 tty_wakeup(tty->tty); |
|
238 } |
|
239 tty->wakeup = 0; |
|
240 } |
|
241 |
|
242 /* Push received data into TTY core. */ |
|
243 to_recv = ec_tty_rx_size(tty); |
|
244 if (to_recv && tty->tty) { |
|
245 unsigned char *cbuf; |
|
246 int space = tty_prepare_flip_string(tty->tty, &cbuf, to_recv); |
|
247 |
|
248 if (space < to_recv) { |
|
249 printk(KERN_WARNING PFX "Insufficient space to_recv=%d space=%d\n", |
|
250 to_recv, space); |
|
251 } |
|
252 |
|
253 if (space < 0) { |
|
254 to_recv = 0; |
|
255 } else { |
|
256 to_recv = space; |
|
257 } |
|
258 |
|
259 if (to_recv) { |
|
260 unsigned int i; |
|
261 |
|
262 #if EC_TTY_DEBUG >= 1 |
|
263 printk(KERN_INFO PFX "Pushing %u bytes to TTY core.\n", to_recv); |
|
264 #endif |
|
265 |
|
266 for (i = 0; i < to_recv; i++) { |
|
267 cbuf[i] = tty->rx_buffer[tty->rx_read_idx]; |
|
268 tty->rx_read_idx = (tty->rx_read_idx + 1) % EC_TTY_RX_BUFFER_SIZE; |
|
269 } |
|
270 tty_flip_buffer_push(tty->tty); |
|
271 } |
|
272 } |
|
273 |
|
274 tty->timer.expires += 1; |
|
275 add_timer(&tty->timer); |
|
276 } |
|
277 |
|
278 /*****************************************************************************/ |
|
279 |
185 |
280 int ec_tty_init(ec_tty_t *tty, int minor, |
186 int ec_tty_init(ec_tty_t *tty, int minor, |
281 int (*cflag_cb)(void *, tcflag_t), void *cb_data) |
187 int (*cflag_cb)(void *, tcflag_t), void *cb_data) |
282 { |
188 { |
283 tty->minor = minor; |
189 tty->minor = minor; |
312 tty_unregister_device(tty_driver, tty->minor); |
218 tty_unregister_device(tty_driver, tty->minor); |
313 } |
219 } |
314 |
220 |
315 /*****************************************************************************/ |
221 /*****************************************************************************/ |
316 |
222 |
|
223 unsigned int ec_tty_tx_size(ec_tty_t *tty) |
|
224 { |
|
225 unsigned int ret; |
|
226 |
|
227 if (tty->tx_write_idx >= tty->tx_read_idx) { |
|
228 ret = tty->tx_write_idx - tty->tx_read_idx; |
|
229 } else { |
|
230 ret = EC_TTY_TX_BUFFER_SIZE + tty->tx_write_idx - tty->tx_read_idx; |
|
231 } |
|
232 |
|
233 return ret; |
|
234 } |
|
235 |
|
236 /*****************************************************************************/ |
|
237 |
|
238 unsigned int ec_tty_tx_space(ec_tty_t *tty) |
|
239 { |
|
240 return EC_TTY_TX_BUFFER_SIZE - 1 - ec_tty_tx_size(tty); |
|
241 } |
|
242 |
|
243 /*****************************************************************************/ |
|
244 |
|
245 unsigned int ec_tty_rx_size(ec_tty_t *tty) |
|
246 { |
|
247 unsigned int ret; |
|
248 |
|
249 if (tty->rx_write_idx >= tty->rx_read_idx) { |
|
250 ret = tty->rx_write_idx - tty->rx_read_idx; |
|
251 } else { |
|
252 ret = EC_TTY_RX_BUFFER_SIZE + tty->rx_write_idx - tty->rx_read_idx; |
|
253 } |
|
254 |
|
255 return ret; |
|
256 } |
|
257 |
|
258 /*****************************************************************************/ |
|
259 |
|
260 unsigned int ec_tty_rx_space(ec_tty_t *tty) |
|
261 { |
|
262 return EC_TTY_RX_BUFFER_SIZE - 1 - ec_tty_rx_size(tty); |
|
263 } |
|
264 |
|
265 /*****************************************************************************/ |
|
266 |
317 int ec_tty_get_serial_info(ec_tty_t *tty, struct serial_struct *data) |
267 int ec_tty_get_serial_info(ec_tty_t *tty, struct serial_struct *data) |
318 { |
268 { |
319 struct serial_struct tmp; |
269 struct serial_struct tmp; |
320 |
270 |
321 if (!data) |
271 if (!data) |
325 |
275 |
326 if (copy_to_user(data, &tmp, sizeof(*data))) { |
276 if (copy_to_user(data, &tmp, sizeof(*data))) { |
327 return -EFAULT; |
277 return -EFAULT; |
328 } |
278 } |
329 return 0; |
279 return 0; |
|
280 } |
|
281 |
|
282 /*****************************************************************************/ |
|
283 |
|
284 /** Timer function. |
|
285 */ |
|
286 void ec_tty_wakeup(unsigned long data) |
|
287 { |
|
288 ec_tty_t *tty = (ec_tty_t *) data; |
|
289 size_t to_recv; |
|
290 |
|
291 /* Wake up any process waiting to send data */ |
|
292 if (tty->wakeup) { |
|
293 if (tty->tty) { |
|
294 #if EC_TTY_DEBUG >= 1 |
|
295 printk(KERN_INFO PFX "Waking up.\n"); |
|
296 #endif |
|
297 tty_wakeup(tty->tty); |
|
298 } |
|
299 tty->wakeup = 0; |
|
300 } |
|
301 |
|
302 /* Push received data into TTY core. */ |
|
303 to_recv = ec_tty_rx_size(tty); |
|
304 if (to_recv && tty->tty) { |
|
305 unsigned char *cbuf; |
|
306 int space = tty_prepare_flip_string(tty->tty, &cbuf, to_recv); |
|
307 |
|
308 if (space < to_recv) { |
|
309 printk(KERN_WARNING PFX "Insufficient space to_recv=%d space=%d\n", |
|
310 to_recv, space); |
|
311 } |
|
312 |
|
313 if (space < 0) { |
|
314 to_recv = 0; |
|
315 } else { |
|
316 to_recv = space; |
|
317 } |
|
318 |
|
319 if (to_recv) { |
|
320 unsigned int i; |
|
321 |
|
322 #if EC_TTY_DEBUG >= 1 |
|
323 printk(KERN_INFO PFX "Pushing %u bytes to TTY core.\n", to_recv); |
|
324 #endif |
|
325 |
|
326 for (i = 0; i < to_recv; i++) { |
|
327 cbuf[i] = tty->rx_buffer[tty->rx_read_idx]; |
|
328 tty->rx_read_idx = |
|
329 (tty->rx_read_idx + 1) % EC_TTY_RX_BUFFER_SIZE; |
|
330 } |
|
331 tty_flip_buffer_push(tty->tty); |
|
332 } |
|
333 } |
|
334 |
|
335 tty->timer.expires += 1; |
|
336 add_timer(&tty->timer); |
330 } |
337 } |
331 |
338 |
332 /****************************************************************************** |
339 /****************************************************************************** |
333 * Device callbacks |
340 * Device callbacks |
334 *****************************************************************************/ |
341 *****************************************************************************/ |
731 printk(KERN_WARNING PFX "Dropping %u bytes.\n", size - to_recv); |
738 printk(KERN_WARNING PFX "Dropping %u bytes.\n", size - to_recv); |
732 } |
739 } |
733 |
740 |
734 for (i = 0; i < size; i++) { |
741 for (i = 0; i < size; i++) { |
735 tty->rx_buffer[tty->rx_write_idx] = buffer[i]; |
742 tty->rx_buffer[tty->rx_write_idx] = buffer[i]; |
736 tty->rx_write_idx = (tty->rx_write_idx + 1) % EC_TTY_RX_BUFFER_SIZE; |
743 tty->rx_write_idx = |
|
744 (tty->rx_write_idx + 1) % EC_TTY_RX_BUFFER_SIZE; |
737 } |
745 } |
738 } |
746 } |
739 } |
747 } |
740 |
748 |
741 /*****************************************************************************/ |
749 /*****************************************************************************/ |